数学建模常用预测模型——灰色预测
在准备数学建模国赛期间复盘学习常用的预测模型——灰色预测,为个人学习时的笔记以及个人理解,如有错误,欢迎指正o( ̄▽ ̄)ブ
灰色预测的数学原理主要涉及灰色系统理论中的GM(1,1)模型。这个模型是最常用和基础的灰色预测模型。
假设有一个原始数据序列X(0),其中X(0) = [x(1), x(2), …, x(n)],表示一组时间序列数据。
- 累加生成序列:
首先,通过累加求得累加生成序列Z(0),其中Z(0) = [z(1), z(2), …, z(n)]。
z(k) = ∑x(i),i=1到k- 建立累加生成模型:
根据累加生成序列Z(0),可以得到一阶累加生成模型:
z ( k ) + a ∗ y ( k ) = b z(k) + a*y(k) = b z(k)+a∗y(k)=b
其中a和b是常数,y(k)表示灰色生成序列,而b表示初始条件。- 求解模型参数:
通过最小二乘法或其他参数估计方法,可以求解出累加生成模型中的参数a和b。- 还原数据:
使用累加生成模型,可以还原出白化数据序列X(1),其中X(1) = [x(1), x(2), …, > x(n)]。- 预测未来值:
根据还原后的白化数据序列,可以进行趋势预测,得到未来的预测结果。总的来说,GM(1,1)模型通过建立累加生成模型,将原始数据序列转换为灰色生成序列,然后再通过参数求解和还原操作得到白化数据序列,最后进行趋势预测。这个模型的基本思想是通过处理数据间的累加关系,降低随机干扰因素的影响,从而实现预测目的。
需要注意的是,虽然GM(1,1)是最常用的灰色预测模型,但在实际应用中,也有其他版本的模型,如GM(2,1)、GM(1,2)等,适用于不同类型的数据序列。灰色预测模型的准确性和可靠性也受到数据质量和特征的影响,在使用过程中需要综合考虑实际情况。
2.适用场景
灰色预测适用于以下场景:
- 数据量较少或者数据质量较差的情况
当原始数据缺乏足够的样本或者存在一定程度的噪音时,灰色预测模型能够通过建立累加生成模型,减少随机干扰因素对预测结果的影响,提供相对准确的预测。
- 系统变化规律不明显的情况
某些系统的变化规律可能比较模糊,不易被明确的数学模型表达,此时可以使用灰色预测模型进行趋势预测。
- 带有非线性特征的数据
灰色预测模型相对于传统的线性预测模型,更适用 于带有非线性特征的数据序列。
- 需要快速预测的场景
灰色预测模型具有简单、快速的特点,适用在时间紧迫的情况下进行预测。
3. 限制条件
需要注意的是,灰色预测也存在一定的限制条件:
- 数据的可靠性要求较高:灰色预测模型对数据的质量要求较高,尤其是对于噪音和异常值的处理。如果数据质量较差,模型的预测结果可能不准确。
- 数据应具备足够的变化趋势:灰色预测模型通过建立累加生成模型来捕捉数据的变化趋势,因此,数据序列应该具有一定变化规律和趋势,否则模型预测效果可能较差。
- 对未知因素的适应能力有限:灰色预测模型主要就与已有数据进行预测,对于未知因素的影响无法充分考虑。在面对复杂、多变的环境和系统时,模型的预测能力可能会受到限制。
综上所述,灰色预测模型适用于数据量较少、质量较差以及变化规律不明显的情况先进行预测。
关于灰色预测对数据的质量要求到底高不高👇
对于灰色预测模型,数据质量是影响预测结果准确的重要因素之一。
数据质量的要求主要包括以下几个方面:
- 数据的完整性:数据应该具有较高的完整性,即不缺失关键的数据点。确实的数据点会导致模型建立和预测的不准确性。
- 数据的精确性:数据应该准确无误的反映研究对象的真实情况。错误或是偏差过大的数据会导致模型建立和预测的失真。
- 数据的稳定性:数据序列应具有一定的稳定性,即不存在剧烈波动或异常值。过于不稳定的数据会影响模型对趋势的捕捉和预测准确性。
- 数据平稳性: 数据序列在时间上应该具有平稳性,即均值、方差等统计特征在时间上保持恒定。非平稳序列可能需要先进行平稳化处理,然后再应用灰色预测模型。‘
虽然灰色预测模型相对于传统的模型对数据质量要求低,但较好的数据质量仍然是提高预测准确性的重要保障。因此,在实际应用中,尽量确保数据的完整性、精确性、稳定性和平稳性,会有助于提高灰色预测的预测效果。
4. python代码实现
import numpy as np
import pandas as pd
from decimal import *
import matplotlib.pyplot as plt
'''Grade_ratio_test(X0)
用于进行级比检验,判断数据是否适合进行灰色预测。
首先计算序列中相邻两个元素的级比,然后根据级比的范围进行判断。
如果有任何一个级比不符合条件,则输出"该数据未经过级比查验",并返回 False 。
如果所有级比都符合条件,则输出"该数据经过级比查验",并返回 True 。
'''
def Grade_ratio_test(X0):
lambds = [X0[i - 1] / X0[i] for i in range(1, len(X0))]
X_min = np.e ** (-2 / (len(X0) + 1))
X_max = np.e ** (2 / (len(X0) + 1))
for lambd in lambds:
if lambd < X_min or lambd > X_max:
print('该数据未经过级比查验')
return False
print('该数据经过级比查验')
return True
'''
model_train(X0_train) 函数用于训练灰色预测模型。
首先根据原始数据 X0_train 计算生成序列 X1 ,然后根据 X1 计算数据矩阵 A 和 B 。
接着使用最小二乘法求解灰色模型的参数 a 和 u ,并将其转换为 Decimal 类型。最后输出灰色参数 a 和 u
'''
def model_train(X0_train):
# AGO生成序列X1
X1 = X0_train.cumsum()
Z= (np.array([-0.5 * (X1[k - 1] + X1[k]) for k in range(1, len(X1))])).reshape(len(X1) - 1, 1)
# 数据矩阵A、B
A = (X0_train[1:]).reshape(len(Z), 1)
B = np.hstack((Z, np.ones(len(Z)).reshape(len(Z), 1)))
# 求灰参数
a, u = np.linalg.inv(np.matmul(B.T, B)).dot(B.T).dot(A)
u = Decimal(u[0])
a = Decimal(a[0])
print("灰参数a:", a, ",灰参数u:", u)
return u,a
'''
model_predict(u, a, k, X0) 函数
用于进行灰色预测。根据给定的灰色参数 u 和 a ,通过灰色预测模型对序列 X0 进行预测。
预测结果是一个长度为 k 的数组 X0_hat ,表示对序列 X0 的预测结果
'''
def model_predict(u,a,k,X0):
predict_function =lambda k: (Decimal(X0[0]) - u / a) * np.exp(-a * k) + u / a
X1_hat = [float(predict_function(k)) for k in range(k)]
X0_hat = np.diff(X1_hat)
X0_hat = np.hstack((X1_hat[0], X0_hat))
return X0_hat
'''
依据后验差等到小差错概率判别猜测成果
:param X0_hat: 猜测成果
:return:
'''
def result_evaluate(X0_hat,X0):
S1 = np.std(X0, ddof=1) # 原始数据样本标准差
S2 = np.std(X0 - X0_hat, ddof=1) # 残差数据样本标准差
C = S2 / S1 # 后验差比
Pe = np.mean(X0 - X0_hat)
temp = np.abs((X0 - X0_hat - Pe)) < 0.6745 * S1
p = np.count_nonzero(temp) / len(X0) # 核算小差错概率
print("原数据样本标准差:", S1)
print("残差样本标准差:", S2)
print("后验差比:", C)
print("小差错概率p:", p)
if __name__ == '__main__':
plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体)
plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题)
# 原始数据X
data = pd.read_excel('./siwei_day_traffic.xlsx') #读取文件数据
X=data[data['week_day']=='周五'].jam_num[:5].astype(float).values #选择关键词为,,的前五个数据作为原始数据
print(X)
# 练习集
X_train = X[:int(len(X) * 0.7)]
# 测验集
X_test = X[int(len(X) * 0.7):]
Grade_ratio_test(X_train) # 对练习集进行级比检验,判断模型的可行性。
a,u=model_train(X_train) # 对练习集进行训练,得到灰色参数 a 和 u
Y_pred = model_predict(a,u,len(X),X) # 猜测# 对整个序列 X 进行预测,得到预测结果 Y_pred
Y_train_pred = Y_pred[:len(X_train)]
Y_test_pred = Y_pred[len(X_train):] # 将预测结果分别划分为训练集预测结果 Y_train_pred 和测验集预测结果 Y_test_pred
result_evaluate(Y_test_pred, X_test) # 对测验集预测结果进行评估
# 可视化
plt.grid()
plt.plot(np.arange(len(X_train)), X_train, '->')
plt.plot(np.arange(len(X_train)), Y_train_pred, '-o')
plt.legend(['负荷实践值', '灰色猜测模型猜测值'])
plt.title('练习集')
plt.show()
plt.grid()
plt.plot(np.arange(len(X_test)), X_test, '->')
plt.plot(np.arange(len(X_test)), Y_test_pred, '-o')
plt.legend(['负荷实践值', '灰色猜测模型猜测值'])
plt.title('测验集')
plt.show()
总结:
模型优点:数据少且无显着规则时可用,使用微分方程发掘数据实质规则。
模型缺点:灰色猜测只合适短期猜测、指数增加的猜测上面的案例是通过python实现的,但是matalab也同样很好实现,大家可以参考这篇博客数学建模:预测性模型学习——灰色预测模型