基本预测类算法

本文介绍了灰色预测算法G(1,1)在小样本时间序列预测中的应用,包括数据预处理、GM(1,1)模型建立、白化方程求解,以及BP神经网络用于房价预测的过程。同时讨论了时间序列预测的基本原理和常见模型如AR、MA和ARMA。
摘要由CSDN通过智能技术生成

一:灰色预测算法G(1,1),可用于小样本时间序列预测。
首先,介绍相关基本概念。
白色系统:系统的相关信息全部已知。
黑色系统:系统全部信息未知。
灰色系统:处于黑色和白色系统的过渡阶段,只有部分信息已知。

算法流程:
  (1)对数据进行处理和检验:计算数列的级比:前一项和后一项的比值。如果所有的级比都落在区间(e-2/(n+1),e2/(n+1))。则满足数据满足要求。如果不满足的话,可以进行平移变换,使得原数列中每一个数据加上常数c,至于c的值,以实验为准。
  (2)当数据满足要求后,就可以建立GM(1,1)模型。
x0(k)+az1(k)=b。求解的话利用最小二乘法,直接进行求解。其中,
z1(k)=cx1(k)+(1-c)x1。在这里,要注意几个符号的含义和区别。x1(k)是累加生成数列中的一项。上标1。表示使用原始数列,经过一次累加得到。x1是表示通过原始数列,经过一次累加得到的数列。
(3)求解相应的白化方程:x1(t)’+ax1(t)=b。求解微分方程,得到解为:x1(t)=(x(0)(1)-b/a)e-a(t-1)+b/a。
(4)联立得到预测值:x(1)(k+1)=(x(0)(1)-b/a)e-ak+b/a。
x0(k+1)=x1(k+1)-x1(k)。
(5)估计误差,可以通过残差检验或者级比偏差值检验。
python代码如下:

def GM1_1(x0):
    #验证数据是否可以用
    if check_data(x0) ==0:
        pass
    else:
        x0 = offset(x0)
    #计算AOG
    x0 = np.array(x0)
    x1 = np.cumsum(x0)
    #计算x1的均值生成序列
    x1 = pd.DataFrame(x1)
    z1 = (x1+x1.shift())/2.0#该项与该项的前一项相加除以2,用shift比循环代码更简单
    z1 = z1[1:].values.reshape((len(z1)-1,1))#再将刚刚算出的数据转成ndarray,删去nan
    B = np.append(-z1,np.ones_like(z1),axis=1)#合并数据形成B矩阵
    Y = x0[1:].reshape((len(x0)-1,1))#建立Y矩阵
    #计算参数a,b np.dot为点乘,np.linalg.inv为矩阵求逆
    [[a],[b]] = np.dot(np.dot((np.linalg.inv(np.dot(B.T,B))),B.T),Y)
    #方程求解 f(k+1)表示x1(k+1)
    f = lambda k: (x0[0]-b/a)*np.exp(-a*(k-1))-(x0[0]-b/a)*np.exp(-a*(k-2))
    #求出估计的所有x1的预测值,大小和x0一样
    x1_pre = [f(k) for k in range(1,len(x0)+1)]
    #求x0的预测值
    #x1_pre = pd.DataFrame(x1_pre)
   
    delta = np.abs(x0 - np.array([f(i) for i in range(1,len(x0)+1)]))
    #检验预测值,利用残差检验
    residual_error = np.abs(x0-np.array(x1_pre))
    residual_error_max = residual_error.max
    #级比偏差值检验
    p = [1-((1-0.5*a)/(1+0.5*a))*l for l in lambda_k]


    return a,b,residual_error_max,p,f

二 BP神经网络预测
  我们将神经网络输出层映射到[0,1]之间,可以实现分类功能,映射方法可以通过选定合适的激活函数得到。同样地,通过改变激活函数,也可以实现预测功能。
一般流程如下:
(1)特征提取,特征提取的算法很多,选取合适的算法即可。当然,具体问题具体分析。
(2)数据标准化处理:主要为消除不同特征之间量纲的影响。
(3)接着是,神经网络结构的设计。BP神经网络,三级层级结构:input layyer,hidden layyer,output layyer。
  输入层神经元个数是输入特征的数目加上偏置节点数目。
  输出层经元个数是想要得到的结果的个数。
  对于隐藏层来说,神经元数目极大程度影响网络性能。一般是大规模调参得到最优值,当然,也有经验公式L=(n+m)1/2+a (1<a<10) 。
(4)模型训练,前向传播计算loss,反向传播更新权重。
接着,附上一道例题。
房价预测

import numpy as np  
import pandas as pd  
from matplotlib import pyplot as plt  
  
  
def sigmoid(x):  
    # 第一层到第二层的激活函数  
    return 1 / (1 + np.exp(-x))  
  
  
def deriv_sigmoid(x):  
    # 第一层到第二层的激活函数的求导函数  
    fx = sigmoid(x)  
    return fx * (1 - fx)  
  
  
def mse_loss(y_true, y_pred):  
    # 使用方差作为损失函数  
    return ((y_true - y_pred) ** 2).mean()  
  
  
class OurNeuralNetwork:  
  
    def __init__(self):  
        # 第一层到第二层的函数  
        self.w11 = np.random.normal()  
        self.w12 = np.random.normal()  
        self.w13 = np.random.normal()  
        self.w14 = np.random.normal()  
        self.w21 = np.random.normal()  
        self.w22 = np.random.normal()  
        self.w23 = np.random.normal()  
        self.w24 = np.random.normal()  
        # 第二层到第三层的函数  
        self.w1 = np.random.normal()  
        self.w2 = np.random.normal()  
        # 截距项,Biases  
        self.b1 = np.random.normal()  
        self.b2 = np.random.normal()  
        self.b3 = np.random.normal()  
  
    def feedforward(self, x):  
        # 前向传播学习  
        h1 = sigmoid(self.w11 * x[0] + self.w12 * x[1] + self.w13 * x[2] + self.w14 * x[3] + self.b1)  
        h2 = sigmoid(self.w21 * x[0] + self.w22 * x[1] + self.w23 * x[2] + self.w24 * x[3] + self.b1)  
        o1 = self.w1 * h1 + self.w2 * h2 + self.b3  
        return o1  
    #训练函数  
    def train(self, data, all_y_trues):  
        learn_rate = 0.01  # 学习率  
        epochs = 1000  # 训练的次数  
        # 画图数据  
        self.loss = np.zeros(100)  
        self.sum = 0;  
        # 开始训练  
        for epoch in range(epochs):  
            for x, y_true in zip(data, all_y_trues):  
                # 计算h1  
                h1 = sigmoid(self.w11 * x[0] + self.w12 * x[1] + self.w13 * x[2] + self.w14 * x[3] + self.b1)  
                # 计算h2  
                h2 = sigmoid(self.w21 * x[0] + self.w22 * x[1] + self.w23 * x[2] + self.w24 * x[3] + self.b2)  
                #计算输出节点  
                y_pred = self.w1 * h1 + self.w2 * h2 + self.b3  
                # 反向传播计算导数  
                d_L_d_ypred = -2 * (y_true - y_pred)  
                d_ypred_d_w1 = h1  
                d_ypred_d_w2 = h2  
                d_ypred_d_b3 = 0  
                d_ypred_d_h1 = self.w1  
                d_ypred_d_h2 = self.w2  
                sum_1=self.w11 * x[0] + self.w12 * x[1] + self.w13 * x[2] + self.w14 * x[3] + self.b1  
                d_h1_d_w11 = x[0] * deriv_sigmoid(sum_1)  
                d_h1_d_w12 = x[1] * deriv_sigmoid(sum_1)  
                d_h1_d_w13 = x[2] * deriv_sigmoid(sum_1)  
                d_h1_d_w14 = x[3] * deriv_sigmoid(sum_1)  
                d_h1_d_b1 = deriv_sigmoid(sum_1)  
                sum_2 = self.w21 * x[0] + self.w22 * x[1] + self.w23 * x[2] + self.w24 * x[3] + self.b2  
                d_h1_d_w21 = x[0] * deriv_sigmoid(sum_2)  
                d_h1_d_w22 = x[1] * deriv_sigmoid(sum_2)  
                d_h1_d_w23 = x[2] * deriv_sigmoid(sum_2)  
                d_h1_d_w24 = x[3] * deriv_sigmoid(sum_2)  
                d_h1_d_b2 = deriv_sigmoid(sum_2)  
  
                # 梯度下降法  
                self.w11 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w11  
                self.w12 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w12  
                self.w13 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w13  
                self.w14 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w14  
                self.b1 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_b1  
                self.w21 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h1_d_w21  
                self.w22 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h1_d_w22  
                self.w23 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h1_d_w23  
                self.w24 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h1_d_w24  
                self.b2 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h1_d_b2  
                self.w1 -= learn_rate * d_L_d_ypred * d_ypred_d_w1  
                self.w1 -= learn_rate * d_L_d_ypred * d_ypred_d_w2  
                self.b3 -= learn_rate * d_L_d_ypred * d_ypred_d_b3  
  
            if epoch % 10 == 0:  
                y_preds = np.apply_along_axis(self.feedforward, 1, data)  
                loss = mse_loss(all_y_trues, y_preds)  
                print("Epoch %d loss: %.3f" % (epoch, loss))  
                self.loss[self.sum] = loss  
                self.sum = self.sum + 1  
  
# 文件的名字  
FILENAME = "../data.xlsx"  
# 禁用科学计数法  
pd.set_option('float_format', lambda x: '%.3f' % x)  
np.set_printoptions(suppress=True, threshold=np.nan)  
# 得到的DataFrame分别为总价、面积、房间、客厅、年份  
data = pd.read_excel(FILENAME, header=0, usecols="A,D,H,I,J")  
# DataFrame转化为array  
DataArray = data.values  
Y = DataArray[:, 0]  
X = DataArray[:, 1:5]  
X = np.array(X)#转化为array,自变量  
Y = np.array(Y)#转化为array,因变量房价  
# 处理数据  
data = np.array(X)  
data_mean = np.sum(data, axis=0) / np.size(data, 0)  
data = (data - data_mean) / np.max(data)  
all_y_trues = np.array(Y)  
all_y_trues_mean = np.sum(all_y_trues) / np.size(all_y_trues)  
all_y_trues = (all_y_trues - all_y_trues_mean) / np.max(all_y_trues)  
# 训练数据  
network = OurNeuralNetwork()  
network.train(data, all_y_trues)  
# 输出神经网络参数  
print("w11-->%.3f" % network.w11)  
print("w12-->%.3f" % network.w12)  
print("w13-->%.3f" % network.w13)  
print("w14-->%.3f" % network.w14)  
print("w21-->%.3f" % network.w21)  
print("w22-->%.3f" % network.w22)  
print("w23-->%.3f" % network.w23)  
print("w24-->%.3f" % network.w24)  
print("w1-->%.3f" % network.w1)  
print("w2-->%.3f" % network.w2)  
print("b1-->%.3f" % network.b1)  
print("b2-->%.3f" % network.b2)  
print("b3-->%.3f" % network.b3)  
# 标题显示中文  
plt.rcParams['font.sans-serif']=['SimHei']  
plt.rcParams['axes.unicode_minus'] = False  
# 测试数据  
testData = np.array([99, 3, 2, 2014])  
testPrice = network.feedforward(testData)  
# 损失函数曲线图  
plt.plot(np.arange(100), network.loss)  
plt.show()  
# 真实值与预测值对比  
y_preds = np.apply_along_axis(network.feedforward, 1, data)  
plt.plot(np.arange(380), all_y_trues,"r^")  
plt.plot(np.arange(380),y_preds,"bs")  
plt.title("红色为真实值,蓝色为预测值")  
plt.show()  

时间序列预测
  主要用来,小样本预测。基本特点:假设事物的过去趋势会延伸到未来。常用的模型有:自回归AR,移动平均MA,ARMA模型等。注意:白噪声随机性过强,不能做时间序列预测。
  要求数据具有平稳性:即序列的均值和方差不发生明显的变化,一般要求均值和协方差不随时间变化。如果,序列不平稳,则无效。可以利用差分法转换,求原始数据的一阶差分,二阶差分等等。
  接着,介绍AR模型。利用变量自身历史数据对自身做预测。需要满足平稳性和自相关性。公式如下:
        Yt=a1Y(t-1)+a2Y(t-2)+……+anY(t-n)+Zt
也就是将t时刻前n个时刻,对应的值做线性组合。zt是白噪声。AR模型认为,t时刻的值,只和自身的值有关,而与系统在这些时刻中进来的噪声无关。
接着,是移动平均MA模型。和AR模型相反,系统认为自身的值只和噪声有关,而与自身的值无关。
       Yt=a1E(t-1)+a2E(t-2)+……+anE(t-n)+Zt
也就是将t时刻前n个时刻的白噪声,对应的值做线性组合。zt是白噪声
  将上述两个模型整合在一起,得到ARMA模型:
Yt=a1Y(t-1)+a2Y(t-2)+……+apY(t-p)+Zt+b1E(t-1)+b2E(t-2)+……+bqE(t-q)+Zt
得到时间序列Yt服从(p,q)阶自回归方程。
ARIMA模型是在ARMA模型的基础上加入差分。即之前的序列是不平稳的,在加入差分后,是平稳的。如果采用了d阶差分,结合上述ARMA模型,可得出ARIMA符合(p,d,q)阶模型。
流程如下

  • 3
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值