數學建模算法:灰色預測模型GM(1,1)及Python代碼


灰色預測模型GM(1,1)

灰色預測模型\(GM(1,1)\)是在數學建模比賽中常用的預測值方法,常用於中短期符合指數規律的預測。

其數學表達與原理分析參考文章尾部網頁與文獻資料。

  • 預處理

灰色模型要求數據前后級比落入范圍 \(\displaystyle \Theta\left(e^{-\frac{2}{n+1}},e^{\frac{2}{n+2}}\right)\) ,因此做線性平移預處理使得元數據滿足要求。

該預處理保證了數據一定落入級比范圍內。

線性平移:將數據平移至不小於1,檢查級比,若不滿足要求則將數據向上平移一個最小值直到滿足要求。

級比范圍

可以推斷出,級比的上下界在給定數據點數越多的情況下,越趨於1。

  • 代碼

經過整理,以下附上Python代碼:

import numpy as np
import matplotlib.pyplot as plt

# 線性平移預處理,確保數據級比在可容覆蓋范圍
def greyModelPreprocess(dataVec):
    "Set linear-bias c for dataVec"
    import numpy as np
    from scipy import io, integrate, linalg, signal
    from scipy.sparse.linalg import eigs
    from scipy.integrate import odeint

    c = 0
    x0 = np.array(dataVec, float)
    n = x0.shape[0]
    L = np.exp(-2/(n+1))
    R = np.exp(2/(n+2))
    xmax = x0.max()
    xmin = x0.min()
    if (xmin < 1):
        x0 += (1-xmin)
        c += (1-xmin)
    xmax = x0.max()
    xmin = x0.min()
    lambda_ = x0[0:-1] / x0[1:]  # 計算級比
    lambda_max = lambda_.max()
    lambda_min = lambda_.min()
    while (lambda_max > R or lambda_min < L):
        x0 += xmin
        c += xmin
        xmax = x0.max()
        xmin = x0.min()
        lambda_ = x0[0:-1] / x0[1:]
        lambda_max = lambda_.max()
        lambda_min = lambda_.min()
    return c

# 灰色預測模型
def greyModel(dataVec, predictLen):
    "Grey Model for exponential prediction"
    # dataVec = [1, 2, 3, 4, 5, 6]
    # predictLen = 5
    import numpy as np
    from scipy import io, integrate, linalg, signal
    from scipy.sparse.linalg import eigs
    from scipy.integrate import odeint

    x0 = np.array(dataVec, float)
    n = x0.shape[0]
    x1 = np.cumsum(x0)
    B = np.array([-0.5 * (x1[0:-1] + x1[1:]), np.ones(n-1)]).T
    Y = x0[1:]
    u = linalg.lstsq(B, Y)[0]

    def diffEqu(y, t, a, b):
        return np.array(-a * y + b)

    t = np.arange(n + predictLen)
    sol = odeint(diffEqu, x0[0], t, args=(u[0], u[1]))
    sol = sol.squeeze()
    res = np.hstack((x0[0], np.diff(sol)))
    return res

# 輸入數據
x = np.array([-18, 0.34, 4.68, 8.49, 29.84, 50.21, 77.65, 109.36])
c = greyModelPreprocess(x)
x_hat = greyModel(x+c, 5)-c

# 畫圖
t1 = range(x.size)
t2 = range(x_hat.size)
plt.plot(t1, x, color='r', linestyle="-", marker='*', label='True')
plt.plot(t2, x_hat, color='b', linestyle="--", marker='.', label="Predict")
plt.legend(loc='upper right')
plt.xlabel('xlabel')
plt.ylabel('ylabel')
plt.title('Prediction by Grey Model (GM(1,1))')
plt.show()

預測值與真實值圖像

灰色預測模型GM(2,1)

根據資料,\(GM(2,1)\)適用於非單調的擺動發展序列,或有飽和的S型序列。但是從圖像上觀察,數據預測由於為指數類型,變化過於誇張、預測趨勢也有偏離的狀況,可能實用性和普適性並不如\(GM(1,1)\)

# 灰色預測模型GM(2,1)
def greyModel2(dataVec, predictLen):
    "Grey Model for exponential prediction"
    # dataVec = [1, 2, 3, 4, 5, 6]
    # predictLen = 5
    import numpy as np
    import sympy as sy
    from scipy import io, integrate, linalg, signal

    x0 = np.array(dataVec, float)
    n = x0.shape[0]
    a_x0 = np.diff(x0) # 1次差分序列
    x1 = np.cumsum(x0) # 1次累加序列
    z = 0.5 * (x1[0:-1] + x1[1:]) # 均值生成序列
    B = np.array([-x0[1:], -z, np.ones(n-1)]).T
    u = linalg.lstsq(B, a_x0)[0]

    def diffEqu(x, f, a1, a2, b):
        return sy.diff(f(x), x, 2) + a1*sy.diff(f(x), x) + a2*f(x) - b # f''(x)+a1*f'(x)+a2*f(x)=b 二階常系數齊次微分方程

    t = np.arange(n + predictLen)
    x = sy.symbols('x')  # 約定變量
    f = sy.Function('f')  # 約定函數
    eq = sy.dsolve(diffEqu(x, f, u[0], u[1], u[2]), f(x), ics={f(t[0]): x1[0], f(t[n-1]): x1[-1]})
    f = sy.lambdify(x, eq.args[1], 'numpy')
    sol = f(t)
    res = np.hstack((x0[0], np.diff(sol)))
    return res

誤差分析部分:可就絕對誤差、相對誤差、級比、殘差做數據分析,以下示例為最小二乘法線性回歸分析。

def regressionAnalysis(xVec, yVec):
    import numpy as np
    from scipy import linalg

    x = np.array([xVec, np.ones(xVec.size)]).T
    u = linalg.lstsq(x, yVec)
    return u

res = regressionAnalysis(x_hat[0:x.size], x)
print(res[0]) # 回歸系數a, b
print(res[1]) # residuals 殘差平方和

參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM