Python实现LSTM股票预测阶段心得笔记

前言

尝试阶段,本科课设,简易实现,应付期末,还在探索,欢迎交流

实现框架

  • TensorFlow

实验数据

来自老师给的CSV文件,共3000多行,每行包含字段如下:

avg_pricecloseamp_ratefactorhigh_limitlow_limitopenquote_rateturnoverturnover_ratevolume

本次预测是就是基于上述字段,预测之后某一天的股票平均价格。

前置知识

LSTM

https://zybuluo.com/hanbingtao/note/541458

TensorFlow

https://tf.wiki/
http://www.tensorfly.cn/

TensorFlow中的张量、变量、占位

神经网络训练过程中的一些术语

  • Epoch:当一个完整的数据集通过了神经网络一次并且返回了一次,这个过程称为一个 epoch,epoch的数量表示对训练集迭代执行了多少次。
  • Batch:在不能将数据一次性通过神经网络的时候,就需要将数据集分成几个 batch。BATCH SIZE表示一个 batch 中的样本总数。通常是在一个epoch中,有多个Batch通过神经网络模型,在一个Batch中,同时输入了多个样本进入神经网络模型。同时loss函数也是针对一批样本而言,也就是说神经网络通常是考虑令一批数据整体的误差最低。
  • Time Step:对于LSTM预测股票来说,时间步的大小决定了考虑多少天之前的数据进行训练和预测,例如Time Step设置为10,则表示用过去10天进行预测,此时每一批内的每一组样本应该包含10天的信息

关于tf.nn.dynamic_rnn与不同批的状态是否应该传递下去的问题

output_rnn,final_states=tf.nn.dynamic_rnn(cell, input_rnn,initial_state=init_state, dtype=tf.float32) 
#output_rnn是记录lstm每个输出节点的结果,final_states是最后一个cell的结果
#dynamic_rnn是一套循环操作,输入初始和值和状态,返回最终的值和状态
#输入初始的值的shape=(batch_size,time_step,rnn_unit),初始状态是h(batch_size,rnn_unit),c(batch_size,rnn_unit),每批的每组都有对应的状态
#输出值:shape=(batch_size,time_step,rnn_unit),因为每一组、每一个时间步、每一个细胞中都会有一个输出值
#输出状态:h(batch_size,rnn_unit),c(batch_size,rnn_unit) 每一组中的每一个细胞最后会得出一个状态值(h和c),
#output_rnn与final_states的关系:output_rnn是每个时间步的输出组成的矩阵,对于output_rnn中一个时间步内的数据h来说,经过一次y=wh+b变化得到这个时间步输出的结果y
#output_rnn中每个时间步的输出就是这个时间步的状态h,这个h还将用于下一个时间步的输出与状态的计算,也就是说每一个时间步的状态(c,h)都由上一个时间步的输出h和本次时间步的输入x计算得到
#output_rnn最后一个时间步的输出等于final_states中的h
#对于一批数据而言(一批有好多组),不同组数据的状态值是独立的,但是大家用的都是一套权重参数
#负向反馈的目标,是让loss尽可能低,这个loss是对一批数据(一批有很多组)的综合评价,修改后的权重参数并非让每一组的结果变的更好,而是让一批数据整体的结果变得更好
#如果不同批次内,同一组号的数据连接在一起结果是延时间的连续的,则final_states也应该feed进去,不考虑负向反馈的话,假如一共有n批数据,这样做等价于使用第一批数据并把时间步扩充了n倍的效果
#考虑负向反馈的话,这样做等价于,时间步扩充了n倍,但每次过固定数目的时间步就对之前一定数目的结果整体评估一下,然后更新权重参数
#相比于直接将时间步扩充了n倍,这样做准确度可能不如直接扩充,但是某一瞬间消耗的内存应该是小于直接扩充的,毕竟每次负向反馈的处理的权重参数少了很多

完整代码

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf

#训练和预测
only_prediction=0

#数据常量
colnums=21
output_size=10
rows=3000
#神经网络常量
rnn_unit=20      #hidden layer units
input_size=colnums-output_size
batch_size=5
time_step=10
epoch=2000
lr=0.0006  #学习率
#其他常数
# model_path='./model'
model_path='./model2'
data_path='./dataset.csv'


# 定义输入输出的w和b
wi = tf.Variable(tf.random_normal([input_size, rnn_unit]))
bi = tf.Variable(tf.random_normal(shape=[rnn_unit, ], mean=0.0, stddev=1.0))
wo = tf.Variable(tf.random_normal([rnn_unit, output_size]))
bo = tf.Variable(tf.random_normal(shape=[output_size, ], mean=0.0, stddev=1.0))

#导入数据
def import_data():
    f=open(data_path)
    df=pd.read_csv(f)     #读入股票数据
    data=df.iloc[:rows,:colnums].values
    return data


#获取训练集
def get_train_data(data,train_begin=0,train_end=500):
    batch_index=[]
    data_train=data[train_begin:train_end]
    train_x,train_y=[],[]   #训练集
    for i in range(int(len(data_train)/time_step)):
        if i % batch_size==0:
           batch_index.append(i)
        data = data_train[i*time_step:(i+1)*time_step,:]  # 对每批中每组数据进行标准化
        x=data[:,:colnums-output_size]
        mean_x=np.mean(x, axis=0)
        std_x=np.std(x, axis=0) + 0.1
        x = (x - mean_x) / std_x
        y=data[:,colnums-output_size:colnums]
        mean_y=np.mean(y, axis=0)
        std_y=np.std(y, axis=0) + 0.1
        y = (y - mean_y) / std_y
        train_x.append(x.tolist())
        train_y.append(y.tolist())
    return batch_index,train_x,train_y

#获取测试集
def get_test_data(data,test_begin=0,test_end=20):
    data_test=data[test_begin:test_end]

    test_x,test_y,mean,std=[],[],[],[]
    for i in range(int(len(data_test)/time_step)):
        x=data_test[i*time_step:(i+1)*time_step,:colnums-output_size]
        mean_x = np.mean(x, axis=0)
        std_x = np.std(x, axis=0) + 0.1
        x = (x - mean_x) / std_x
        mean_y, std_y = [], []
        for j in (range(output_size)):
            mean_y.append(mean_x[0])
            std_y.append(std_x[0])
        mean.append(mean_y)
        std.append(std_y)
        test_x.append(x.tolist())
    test_y=data_test[:,0]
    return test_x,test_y,mean,std

#定义模型
def RNN(cell,X,init_state):

    #定义隐藏层的运算
    input=tf.reshape(X,[-1,input_size])
    input_rnn=tf.matmul(input,wi)+bi

    input_rnn=tf.reshape(input_rnn,[-1,time_step,rnn_unit])
    output_rnn,final_states=tf.nn.dynamic_rnn(cell, input_rnn,initial_state=init_state, dtype=tf.float32)  #output_rnn是记录lstm每个输出节点的结果,final_states是最后一个cell的结果
    output=tf.reshape(output_rnn,[-1,rnn_unit]) #作为输出层的输入

    pred=tf.matmul(output,wo)+bo
    return pred,final_states

#开始训练
def train_data(train_begin=500,train_end=2500):
    #读数据集,设置神经网络模型,准备X和Y,初始状态
    batch_index, train_x, train_y = get_train_data(import_data(), train_begin, train_end)
    cell = tf.nn.rnn_cell.BasicLSTMCell(rnn_unit)
    X = tf.placeholder(tf.float32, shape=[None, time_step, input_size])
    Y = tf.placeholder(tf.float32, shape=[None, time_step, output_size])
    init_state = cell.zero_state(batch_size, dtype=tf.float32)

    #构建计算图结点
    pred, final_states=RNN(cell,X,init_state)
    loss = tf.reduce_mean(tf.square(tf.reshape(pred,[-1,]) - tf.reshape(Y,[-1,])))
    train_op = tf.train.AdamOptimizer(lr).minimize(loss)

    #声明保存模型需要用的对象
    saver = tf.train.Saver(tf.global_variables(), max_to_keep=15)

    #开始训练
    sess = tf.Session()
    sess.run(tf.global_variables_initializer())
    for i in range(epoch):
        for step in range(len(batch_index) - 1):

            feed_dict = {X: train_x[batch_index[step]:batch_index[step + 1]],
                         Y: train_y[batch_index[step]:batch_index[step + 1]]}

            _, loss_, states = sess.run([train_op, loss, final_states],
                                                feed_dict=feed_dict)
        print( i, loss_)
        if i % 20 == 0:
            print("保存模型:", saver.save(sess, model_path+'/stock.model', global_step=i))
    print("保存模型:", saver.save(sess, model_path, global_step=i))
    sess.close()


#预测
def prediction(test_begin=0,test_end=500):
    #读数据集,配置X和初始状态
    test_x, test_y,mean,std = get_test_data(import_data(), test_begin, test_end)
    X=tf.placeholder(tf.float32, shape=[None,time_step,input_size])
    cell = tf.nn.rnn_cell.BasicLSTMCell(rnn_unit)

    init_state = cell.zero_state(1, dtype=tf.float32)

    #构建计算图结点
    pred, final_states=RNN(cell,X,init_state)

    #配置读取模型需要用的对象
    saver=tf.train.Saver(tf.global_variables())

    #开始预测
    sess=tf.Session()
    module_file = tf.train.latest_checkpoint(model_path)
    saver.restore(sess, module_file)
    test_predict=[]

    for step in range(len(test_x)):
        prob=sess.run(pred,feed_dict={X:[test_x[step]]})
        test_predict.append(prob[len(prob)-1])
    sess.close
    # acc = np.average(np.abs(test_predict - test_y) / test_y)  # 偏差
    # print(acc)
    #以折线图表示结果
    real=[]
    pred=(np.array(test_predict)*std)+mean
    plt.figure()
    plt.plot(list(range(len(test_y))), test_y,  color='r')
    for step in range(0,len(test_predict)-1):
        real.append(test_y[(step+1) * time_step:(step+1) * time_step + output_size])
        plt.plot(list(range((step+1) * time_step, (step+1) * time_step + output_size)), pred[step], color='b', marker="v")
    acc = np.average(np.abs( pred[:len(real)]-np.array(real)) / np.array(real))  # 偏差
    print("acc", acc)
    plt.show()



if only_prediction==0:
    with tf.variable_scope('train'):
        train_data(500,2000)
    with tf.variable_scope('train', reuse=True):
        prediction(2500, 3000)
else:
    with tf.variable_scope('train'):
        prediction(2500, 3000)

经历与心得

起因

​ 大三下学期软件工程的课设就是要求尝试使用RNN进行股票预测,我之前从未接触过Python和神经网络的相关知识,这次课设算是给了我一个学习的动力。

经过

我的学习路线是bp神经网络,RNN神经网络,Python,TensorFlow。bp神经网络是开启我神经网络大门的钥匙,我学习的过程中,我曾对神经网络持有一种怀疑的态度,原因是,我对神经网络的认知是采用了一种特殊的数据结构,运用逐步接近最优的算法,通过大量输入与输出样本,模拟输入与输出中的某种规律,这种数据结构就是神经元,所采用的算法就是构造误差函数,使用梯度下降令误差函数达到最小。

梯度下降是其实并不难理解,假设y=f(x)是一元连续函数,梯度下降就是不断令x=x+ny’,假如y是某定义域内的凹函数,我们知道,y’=0的点是,该函数的极小值点,极小值点的左侧y’<0,而右侧y’>0,所以如果x梯度下降的起点在极小值点的左边,那么可见x在逐步增加的,如果起点在在极小值点右边,则x会逐步减少,且这种变化的幅度会随函数导数大小而改变,导数大变化幅度也大,导数小,变化幅度也小,可以想象,对于凹函数给定任意起点,不断使用梯度下降,最终x会收敛在极小值点。

我们可以求出误差函数对某一参数的偏导数,然后不断用梯度下降修正这个参数,当这个误差函数收敛到一个值时,则说明误差函数的极小值点(并非严谨定义上的极小值)时,参数应该接近的当前值,此时输出结果与预期结果相差的最小。神经网络用它独有的数据结构定义了大量参数,对这些参数求偏导并梯度下降,使误差函数收敛到一个值。

RNN和LSTM也是用的这个道理,只不过RNN和LSTM把一组运算的输出也作为输入的一部分进行运算,通常这两组数据具有时间先后关系,RNN是将之前的数据全部作为参考,而LSTM又引入了一组参数,可以令之前部分参数作为参考,即模型具备了遗忘能力。

学完Python后,我开始学习Python,Python我感觉从某个角度来说,和JavaScript很像,虽然是第一次接触Python,但是对于软件工程的学生来说,只做到能读懂代码还是很轻松的,我很快就完成了Python学习阶段,只学会了基础的语法和特性,Python的代码真的很简洁,写起来比Java得劲多了,但是Python还有很多进阶技巧我没来得及学,这个日后一定要补上。

TensorFlow框架把模型都封装好了,不改模型的话,只需要用它的api把运算图构建出来就好了,这个过程还好,理解神经网络后很快就上手了,但是一些机器学习领域的术语很让我困扰,不过还是在不断实践和查阅资料的过程中搞明白了。

结果

课设完成了,准确率还行,只预测后一天的价格情况还好,越往后越跑偏,但是考虑到本身股票一天之内就没多大变化,所以这个准确率虽然高,但多少给人一点自欺欺人的感觉,说实话我不认为股票有什么规律可以用神经网络来模拟,股票作为一个多人博弈的过程,它很多影响因素在于外界,我认为单从历史数据预测未来不是很把握,所以对于这个准确率我还是蛮惊讶的,期末又和老师以及其他同学交流过,我这套代码只能说是实现了,在数据预处理和超参数调整方面还有进步空间,马上要考研了,近期可能不会有很多时间来改进了,待以后慢慢摸索学习吧

相对误差的平均值 0.03125852369012719

在这里插入图片描述

  • 16
    点赞
  • 184
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
### 回答1: LSTM模型是一种循环神经网络,可以用于时间序列预测任务,包括多步预测。下面是一个使用Python实现LSTM多步预测的示例代码: 首先,导入必要的库: ``` import numpy as np import pandas as pd import matplotlib.pyplot as plt from keras.models import Sequential from keras.layers import Dense, LSTM ``` 接着,读取数据并进行预处理: ``` # 读取数据 data = pd.read_csv('data.csv') # 将数据归一化到0-1之间 max_value = np.max(data) min_value = np.min(data) data = (data - min_value) / (max_value - min_value) # 划分训练集和测试集 train_data = data[:-30] test_data = data[-30:] ``` 接着,定义函数来生成LSTM的输入和输出数据: ``` # 生成LSTM的输入和输出数据 def create_dataset(dataset, look_back=1, look_forward=1): X, Y = [], [] for i in range(len(dataset) - look_back - look_forward + 1): X.append(dataset[i:(i + look_back)]) Y.append(dataset[(i + look_back):(i + look_back + look_forward)]) return np.array(X), np.array(Y) ``` 然后,使用上述函数来生成训练集和测试集的输入和输出数据: ``` look_back = 10 look_forward = 5 x_train, y_train = create_dataset(train_data, look_back, look_forward) x_test, y_test = create_dataset(test_data, look_back, look_forward) ``` 接着,定义LSTM模型并进行训练: ``` # 定义LSTM模型 model = Sequential() model.add(LSTM(units=64, input_shape=(look_back, 1))) model.add(Dense(units=look_forward)) # 编译模型 model.compile(loss='mse', optimizer='adam') # 训练模型 model.fit(x_train, y_train, epochs=100, batch_size=32, verbose=2) ``` 最后,使用训练好的模型进行多步预测: ``` # 多步预测 predicts = [] for i in range(len(test_data) - look_back - look_forward + 1): X = test_data[i:(i + look_back)] X = np.array(X).reshape((1, look_back, 1)) Y = model.predict(X) predicts.append(Y.reshape(look_forward)) # 反归一化 predicts = np.array(predicts) predicts = predicts * (max_value - min_value) + min_value # 绘制结果 plt.plot(range(len(predicts)), predicts[:, 0], 'r', label='predict') plt.plot(range(len(test_data)), test_data, 'b', label='real') plt.legend(loc='best') plt.show() ``` 以上就是使用Python实现LSTM多步预测的示例代码,希望能对你有帮助。 ### 回答2: 实现LSTM(长短期记忆)模型进行多步预测,需要以下步骤: 1. 数据预处理:准备好输入数据,通常是一个时间序列的数据,如股票价格、气温等。将数据分为训练集和测试集,以便用训练集训练模型,并使用测试集评估模型的性能。 2. 构建LSTM模型:使用Python中的Keras或TensorFlow等深度学习框架构建LSTM模型。LSTM是一种循环神经网络,适合处理时间序列数据。模型的输入是过去的一段时间序列数据,而输出是未来的一段时间序列数据。 3. 定义模型结构:在构建LSTM模型时,需要定义模型的层数、每层的神经元数量等参数。可以选择相应的激活函数、优化器和损失函数以训练模型。 4. 训练模型:使用训练集训练LSTM模型。训练过程中,模型通过反向传播算法优化权重和偏差,减小预测值与真实值之间的误差。 5. 多步预测:在训练完成后,使用已经训练好的LSTM模型进行多步预测。首先,将一个时间窗口的历史数据输入模型,得到第一个时间步的预测结果。然后,将该预测结果作为下一个时间步的输入,继续进行预测,如此循环进行多次,直到获得所需的多步预测结果。 6. 评估模型性能:使用测试集评估模型的性能。比较模型的预测结果与真实值,计算评估指标如均方根误差(RMSE)等,以评估模型的准确性和稳定性。 总之,使用Python实现LSTM多步预测需要进行数据预处理、构建LSTM模型、训练模型、多步预测和评估模型性能的步骤。这些步骤可以借助深度学习框架如Keras或TensorFlow来实现,并根据具体情况进行调参和优化。 ### 回答3: LSTM(长短期记忆)是一种常用于时间序列预测的深度学习模型,通过在神经网络中引入门控机制来捕捉时间序列数据中的长期依赖关系。下面是使用Python实现LSTM多步预测的简要步骤: 1. 导入所需的库,如numpy和Keras。 2. 准备数据集,将时间序列数据组织成适当的输入-输出形式。通常,我们将样本数据划分为输入序列和对应的输出序列。可以使用滑动窗口技术将时间序列数据转化为适当的输入-输出对。 3. 标准化数据,以便将数据转化为可处理范围之内,在这里可以使用Scikit-learn的StandardScaler。 4. 创建LSTM模型,使用Keras库中的Sequential模型,并添加一个LSTM层和可能的其他Dense层。 5. 定义模型的超参数,如LSTM层的神经元数量、训练时的批次大小、迭代次数等。 6. 编译和训练模型。使用Keras的compile函数来配置模型的优化器、损失函数和评估指标,并使用fit函数来训练模型。 7. 多步预测。使用训练完成的模型对未来多个时间步长的输出进行预测。可以通过将前一时间步的预测输出作为下一时间步的输入来进行逐步预测。 8. 反标准化数据,将预测结果恢复到原始数据的尺度上。 9. 可选地,可以通过使用适当的评估指标来评估预测结果的准确性。 10. 输出预测结果,确定模型的性能和预测能力。 以上是使用Python实现LSTM多步预测的大致步骤。具体实现过程中需要根据具体数据集的特点进行适当的调整。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值