tensorflow实现简单的LSTM时序预测

数据集和代码:链接:https://pan.baidu.com/s/1hwk7rRJr_pZgKbUBWI6TNQ
提取码:jwpl

数据概览与任务描述:

在这里插入图片描述
数据集是精简排序过的,我们唯一需要用到的属性就是[‘Lane 1 Flow (Veh/5 Minutes)’]。
任务就是用前12个连续时刻的状态数据[St0,St1,…,St11]预测第13个时刻的状态pSt12。

数据集处理

我就min-max归一化了一下,没特别处理。其中lags=12就是时间步,也就是time_step,所有数据都被我做成了三维的矩阵,与LSTM的输入输出[batch_size,time_step,feature_num]对应:

#数据集处理:
trainData=np.array(list(pd.read_csv('train.csv', lineterminator='\n')['Lane 1 Flow (Veh/5 Minutes)']))
testData=np.array(list(pd.read_csv('test.csv',lineterminator='\n')['Lane 1 Flow (Veh/5 Minutes)']))
trainLen=len(trainData)
testLen=len(testData)
combineData=np.append(trainData,testData)

scl=MinMaxScaler()
combineData=scl.fit_transform(combineData.reshape(-1, 1))
min=scl.data_min_
max=scl.data_max_
trainData=combineData[:trainLen]
testData=combineData[trainLen:trainLen+testLen]

lags=12
train=[]
test=[]
#虽然特征只有一维,但我们还是做成[batch_size,time_step,feature_num]的形式
for i in range(lags,trainLen):
    train.append(trainData[i-lags:i+1])
for i in range(lags,testLen):
    test.append(testData[i-lags:i+1])
train=np.array(train)
test=np.array(test)

x_train=train[:,:-1]
y_train=train[:,-1,np.newaxis]
x_test=test[:,:-1]
y_test=test[:,-1,np.newaxis]

神经网络搭建

Tensorflow

tensorflow搭建神经网络的流程是建立计算图,编译计算图,然后传入数据,也就是静态图(2.0有动态图了,不过没用过)。计算图其实就是张量tensor和数据流向flow组成的,张量其实就是矩阵,也就是说tensorflow实现神经网络的本质实际上就是自定义了一个大的矩阵运算函数,LSTM、GRU都可以理解为一种封装好的复杂矩阵运算。

Tensorflow中的LSTM

Tensorflow中的LSTM接受一个形状为[batch_size,time_step,feature_num]的矩阵,输出一个形状为[batch_size,time_step,rnn_units]的矩阵,batch_size即batch的大小,time_step是时间步,也就是本题中的lags=12,feature_num是每项数据的属性列数量,本题中只有一个[‘Lane 1 Flow (Veh/5 Minutes)’],所以为1,rnn_units即RNN神经元的数量。

RNN的处理过程,可以理解为,对于接受的矩阵[batch_size,time_step,feature_num]进行batch_size次操作;在每个batch的操作中,又进行time_step次计算,每次计算的是t-1时刻的状态,输出的是模型预测的t时刻的状态。比如对于每个batch:
在这里插入图片描述
然后LSTM的输入输出就是batch_size个这样的矩阵的拼接。

即用t0-t11这样12个时刻的状态数据,预测t13的状态,不考虑batch_size,ti时刻状态用Sti表示,投入LSTM的输入是序列[St0,St1,…,St11],而LSTM的输出是序列[pSt1,pSt2,…,pSt12]。
其中pSti代表LSTM根据输入i-1时刻的输入状态,预测的i时刻的状态。

所以对于从LSTM输出的数据,就有两种处理方法;
1.把整个输出[pSt1,pSt2,…,pSt12]后面接一层全连接层,这样的理论依据是可以包含以往数据的信息。
2.只取出最后的输出pSt12作为结果,舍弃[pSt1,pSt2,…,pSt11]

同样的损失函数的计算也就分为对[pSt1,pSt2,…,pSt12]和[St1,St2,…,St11,St12(y)]算损失函数和只对pSt12和St12(y)算损失函数。

我的代码里是直接取了pSt12作为结果,只对pSt12和St12(y)算损失函数。

#定义神经网络:
feature_num=1
batch_size=128
epochs=4
time_step=12
pre_num=1

x_in=tf.placeholder(tf.float32, [None, time_step,feature_num])
y_in=tf.placeholder(tf.float32, [None, pre_num,feature_num])
batch=tf.shape(x_in)[0]
#定义常量
rnn_unit=32       #hidden layer units
output_size=1
lr=5e-4    #学习率

#输入层、输出层权重、偏置(relu)
weights={
         'out':tf.Variable(tf.random_normal([rnn_unit,1]))
        }
biases={
        'out':tf.Variable(tf.constant(0.1,shape=[1,]))
       }

cell=tf.nn.rnn_cell.BasicLSTMCell(rnn_unit)
init_state=cell.zero_state(batch,dtype=tf.float32)
output_rnn,final_states=tf.nn.dynamic_rnn(cell, x_in,initial_state=init_state, dtype=tf.float32)  #output_rnn是记录lstm每个输出节点的结果,final_states是最后一个cell的结果
output=output_rnn[:,time_step-pre_num:time_step,:]
output=tf.reshape(output,[-1,rnn_unit])
w_out = weights['out']
b_out = biases['out']
pred = tf.matmul(output, w_out) + b_out


loss = tf.losses.mean_squared_error(tf.reshape(pred, [-1]), tf.reshape(y_in, [-1]))
#tf.reduce_mean(tf.square(tf.reshape(pred, [-1]) - tf.reshape(y_in, [-1])))
train_op = tf.train.AdamOptimizer(lr).minimize(loss)

神经网络训练与预测:

这里主要说一下学习率的问题,学习率设高了无法通过递归下降到极值点,学习率设低了也可能会因为学习率太小而下降到局部极值点,从而成为局部最优,两种都不能产生比较好的模型:

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    print('模型训练:')
    for i in range(epochs):
        for j in range(len(x_train)//batch_size):
            _,pre_loss=sess.run([train_op,loss],feed_dict={x_in:x_train[j*batch_size:(j+1)*batch_size],y_in:y_train[j*batch_size:(j+1)*batch_size]})
        if (len(x_train) % batch_size != 0):
            _,pre_loss=sess.run([train_op,loss],feed_dict={x_in: x_train[(len(x_train) // batch_size) * batch_size:len(x_train)],y_in:y_train[(len(x_train) // batch_size) * batch_size:len(x_train)]})
        print(i,'th epaoch,last batch:',pre_loss)
    print('模型预测:')
    resPre=[]
    for i in range(len(x_test)//batch_size):
        predList=sess.run(pred,feed_dict={x_in:x_test[i*batch_size:(i+1)*batch_size]})
        for j in predList:
            resPre.append(j[0]);
    if (len(x_test)%batch_size!=0):
        predList=sess.run(pred,feed_dict={x_in:x_test[(len(x_test)//batch_size)*batch_size:len(x_test)]})
        for j in predList:
            resPre.append(j[0]);
    accRes=[]
    for i in y_test:accRes.append(i[0][0])
    resPre=np.array(resPre)
    accRes=np.array(accRes)
    print(sess.run(tf.losses.mean_squared_error(resPre, accRes)))
    plt.plot(list(range(len(accRes))), accRes, color='b')
    plt.plot(list(range(len(resPre))), resPre, color='r')
    plt.show()

结果:

没太多的调参,均方差0.0027658767:
在这里插入图片描述

  • 0
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值