用非线性最小二乘法对 Bass 模型做参数估计
时间: 2023-11-12 17:05:37 浏览: 133
Bass模型是一种经典的市场扩散模型,用于描述某种新产品在市场上的扩散过程。其数学形式为:
$$
y(t) = p \cdot F(t) + q \cdot G(t)
$$
其中,$y(t)$ 表示在时刻 $t$ 时产品的市场占有率,$p$ 是初始市场占有率,$q$ 是最终市场占有率,$F(t)$ 是创新效应,$G(t)$ 是模仿效应。$F(t)$ 和 $G(t)$ 的形式分别为:
$$
F(t) = \frac{m^2}{p+q} \cdot \frac{e^{-(p+q)m}}{(1+(q/p)e^{-qt})^2} \cdot (1-e^{-(p+q)t})
$$
$$
G(t) = \frac{m^2q}{p+q} \cdot \frac{e^{-(p+q)m}}{(1+(q/p)e^{-qt})^2} \cdot (e^{-(p+q)t}-1)
$$
其中,$m$ 是市场容量,$t$ 是时间。
现在我们想要用非线性最小二乘法对 Bass 模型中的参数 $p$、$q$ 和 $m$ 进行估计。具体步骤如下:
1. 导入必要的库和数据
```python
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
t = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
y = np.array([0.0001, 0.0002, 0.0004, 0.0008, 0.0016, 0.0032, 0.0064, 0.0128, 0.0256, 0.0512])
```
2. 定义 Bass 模型函数
```python
def bass_model(t, p, q, m):
f = (m**2 / (p + q)) * ((np.exp(-(p+q)*m)) / ((1 + (q/p)*np.exp(-q*t))**2)) * (1 - np.exp(-(p+q)*t))
g = (m**2 * q / (p + q)) * ((np.exp(-(p+q)*m)) / ((1 + (q/p)*np.exp(-q*t))**2)) * (np.exp(-(p+q)*t) - 1)
return p*f + q*g
```
3. 进行拟合
```python
popt, pcov = curve_fit(bass_model, t, y)
print('p:', popt[0])
print('q:', popt[1])
print('m:', popt[2])
```
其中,popt是最优拟合参数,pcov是协方差矩阵。
4. 绘制拟合曲线
```python
plt.plot(t, y, 'bo', label='data')
plt.plot(t, bass_model(t, *popt), 'r-', label='fit')
plt.legend()
plt.show()
```
完整代码如下:
```python
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
t = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
y = np.array([0.0001, 0.0002, 0.0004, 0.0008, 0.0016, 0.0032, 0.0064, 0.0128, 0.0256, 0.0512])
def bass_model(t, p, q, m):
f = (m**2 / (p + q)) * ((np.exp(-(p+q)*m)) / ((1 + (q/p)*np.exp(-q*t))**2)) * (1 - np.exp(-(p+q)*t))
g = (m**2 * q / (p + q)) * ((np.exp(-(p+q)*m)) / ((1 + (q/p)*np.exp(-q*t))**2)) * (np.exp(-(p+q)*t) - 1)
return p*f + q*g
popt, pcov = curve_fit(bass_model, t, y)
print('p:', popt[0])
print('q:', popt[1])
print('m:', popt[2])
plt.plot(t, y, 'bo', label='data')
plt.plot(t, bass_model(t, *popt), 'r-', label='fit')
plt.legend()
plt.show()
```
运行代码,即可得到拟合图和参数估计结果。