神经网络(LSTM)在股票预测中的具体实现:附keras和tensorflow核心源码讲解)

    最近不少网友一直在问我LSTM在股票预测中的实现为何直接copy网上的代码为何运行不了或者将和股票数据类似的数据运行在网上的一些模型上不能顺利运行?在这个我将一一解答上述问题,并给出相关代码在股票预测中的讲解(如还有问题可进群(225215316,进行讨论询问等)。

    首先,网上直接copy代码在自己的环境下运行,即使博主发出的代码是可行的,也可能由于环境配置问题带来报错问题,还有就是网上开源的模型我看了一部分,有些博主发出的代码也是复制黏贴左右拼凑的,代码的健壮行存在问题,多多少少存在一些小的问题,其次,有些人网上寻找股票预测代码是因为自己的数据和股票数据有些类似或者所需要的模型正是LSTM或者RNN,就开始了生硬的嵌套,其模型原理等了解的并不是很清楚,这将存在对神经网络所喂的数据格式存在问题等。即使有些模型跑的通,其参数还是存在或多或少的问题,因此本篇博客将从根本上解决上述问题;

 实现环境:

 本博客所以代码所用环境均为python3.0以上,tensorflow1.4.0,theano1.0.2 ,keras2.1.3,pandas0.21.0等主要环境版本;

 知识点概述:

原始的RNN神经网络在处理长序列时会出现RNN的梯度消失问题,简单讲就是后面的时间节点对于前面距离太长的时间节点感知能力有所下降,网络过深就没有办法在继续训练,所以LSTM神经网络模型得以出现。为了解决这个“容易忘”问题,便在神经网络层之间引入了核心元素CELL(细胞),LSTM的模型结构如下图2所示,CELL一共分为三种类型,其分别为:遗忘细胞,输入细胞,输出细胞。

图LSTM神经网络模型结构图

Lstm神经网络的整个过程分为四步:

第一步就是决定什么信息应该被神经元遗忘。这是一个被称为“遗忘门层”的Sigmod层组成的。如图所示,它输入ht−1和xt,然后在Ct−1 的每个神经元状态输出0到1之间的数字。“1”表示“完全保留这个”,“0”表示“完全遗忘这个”。

 

                                                                  

图:LSTM神经网络运算示意图(1)

第二步决定我们要在神经元细胞中保存什么信息,这包括两个部分。

如图2所示,首先,一个被称为“遗忘门层”的Sigmod层决定我们要更新的数值。然后,一个tanh层生成一个新的候选数值,Ct˜,它会被增加到神经元状态中。

 

                                                     

                                                          图:LSTM神经网络运算示意图(2)

第三步就是去更新我们这个候选者值。

如图所示,本文给旧的状态乘以一个,遗忘掉本文之前决定要遗忘的信息,然后我们增加新的候选值,该值是由更新每个状态的值来度量的。

                                                     

                     图:LSTM神经网络运算示意图(3)

第四步就是最终的决定要输出什么。

如图所示,输出是建立在我们的神经元状态的基础上的,但是有一个滤波器。首先,本文使用Sigmod层决定哪一部分的神经元状态需要被输出;然后让神经元状态经过tanh(让输出值变为-1~1之间)层并且乘上Sigmod门限的输出,只输出本文需要的输出。

                                                    

                       图:LSTM神经网络运算示意图(4)

LSTM凭借其对序列的记忆能力能在较长序列场景下完成出色的学习训练。就本博客实验而言,本文的股票数据其实就是基于时间序列的一组数据,而上述两个模型都可以完成基于序列的任务,但是我们的训练数据集序列较长,加之在大部分应用场景下,LSTM模型都是优于传统的 RNN模型。因此,在应对本实验数据集的情况下,我们选择RNN的变体LSTM神经网络模型。

 

数据的介绍与处理:

 

    本实验数据选用了SH000001股票从1990年12月到2015年12月6109个样本股票的数据信息作为输入。本数据信息的元素维度为10个,即为10个影响股票价格的信息数据,分别为:股票序号,股票号,时间,开盘价,闭盘价,最低价,最高价,volum,money ,change;样本的标签为股票的价格收益。标签是元素数据已经标注好的。数据来源于KAGGLE开源数据。

 

 数据的处理在本博客将不再累述,因为将原始数据进行输入也能得到不错的结果,该数据存入pandas数据库中,该模式下的存储易于pyyhon初学者对数据的读取,而且还显得高大上等等。

 

实验评价指标:

本实验的神经网络模型采用RMSE作为评价标准,其参数优化也是在RMSE的基础之上进行的。RMSE为均方跟误差,故股票预测的损失函数等也都是在RMSE的基础之上进行迭代优化的。本实验主要比较训练集误差损失train_loss和验证集误差损失val_loss和预测集误差损失pre_loss。很显然loss的值越低说明模型拟合的效果越好。

具体代码实现:

网上tensorflow版(调通后给出了详细代码注释,部分累赘代码省去,运行环境为上述所述):

 

# ——————————————————导入数据——————————————————————
f = open('data.csv')#重新写入数据位置和名称等
df = pd.read_csv(f)  # 读入股票数据
data = df.iloc[:, 2:10].values  # 取第3-10列
# 获取训练集,从0到5800个,即是前多少行数据
def get_train_data(batch_size=60, time_step=20, train_begin=0, train_end=5800):#函数传值,
    batch_index = []
    data_train = data[train_begin:train_end]#训练数据开始至结束
    normalized_train_data = (data_train - np.mean(data_train, axis=0)) / np.std(data_train, axis=0)  # 定义标准化语句
    train_x, train_y = [], []  # 训练集
    for i in range(len(normalized_train_data) - time_step):#以下即是获取训练集并进行标准化,并返回该函数的返回值
        if i % batch_size == 0:
            batch_index.append(i)
        x = normalized_train_data[i:i + time_step, :7]#即为前7列为输入维度数据
        y = normalized_train_data[i:i + time_step, 7, np.newaxis]#最后一列标签为Y,可以说出是要预测的,并与之比较,反向求参
        train_x.append(x.tolist())
        train_y.append(y.tolist())
    batch_index.append((len(normalized_train_data) - time_step))
    return batch_index, train_x, train_y
 
# 获取测试集,代码含义同上获取训练集,只不过该获取数据从5800个开始
def get_test_data(time_step=20, test_begin=5800):
    data_test = data[test_begin:]
    mean = np.mean(data_test, axis=0)
    std = np.std(data_test, axis=0)
    normalized_test_data = (data_test - mean) / std  # 标准化
    size = (len(normalized_test_data) + time_step) // time_step # 有size个sample
    test_x, test_y = [], []
    for i in range(size - 1):
        x = normalized_test_data[i * time_step:(i + 1) * time_step, :7]
        y = normalized_test_data[i * time_step:(i + 1) * time_step, 7]
        test_x.append(x.tolist())
        test_y.extend(y)
    test_x.append((normalized_test_data[(i + 1) * time_step:, :7]).tolist())
    test_y.extend((normalized_test_data[(i + 1) * time_step:, 7]).tolist())
    return mean, std, test_x, test_y
# ——————————————————定义神经网络变量——————————————————
# 输入层、输出层权重、偏置

weights = {
    'in': tf.Variable(tf.random_normal([input_size, rnn_unit])),
    'out': tf.Variable(tf.random_normal([rnn_unit, 1]))
}
biases = {
    'in': tf.Variable(tf.constant(0.1, shape=[rnn_unit, ])),
    'out': tf.Variable(tf.constant(0.1, shape=[1, ]))
}

# ——————————————————定义神经网络变量——————————————————
def lstm(X):
    batch_size = tf.shape(X)[0]
    time_step = tf.shape(X)[1]
    w_in = weights['in']
    b_in = biases['in']
    input = tf.reshape(X, [-1, input_size])  # 需要将tensor转成2维进行计算,计算后的结果作为隐藏层的输入
    input_rnn = tf.matmul(input, w_in) + b_in
    input_rnn = tf.reshape(input_rnn, [-1, time_step, rnn_unit])  # 将tensor转成3维,作为lstm cell的输入
    cell = tf.nn.rnn_cell.BasicLSTMCell(rnn_unit)
    init_state = cell.zero_state(batch_size, dtype=tf.float32)
    output_rnn, final_states = tf.nn.dynamic_rnn(cell, input_rnn, initial_state=init_state, dtype=tf.float32)
    output = tf.reshape(output_rnn, [-1, rnn_unit])
    w_out = weights['out']
    b_out = biases['out']
    pred = tf.matmul(output, w_out) + b_out
    return pred, final_states
# ————————————————训练模型————————————————————

def train_lstm(batch_size=60, time_step=20, train_begin=2000, train_end=5800):
    X = tf.placeholder(tf.float32, shape=[None, time_step, input_size])#预先定义X,Y占位符
    Y = tf.placeholder(tf.float32, shape=[None, time_step, output_size])
    batch_index, train_x, train_y = get_train_data(batch_size, time_step, train_begin, train_end)
    pred, _ = lstm(X)
    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)#保存模型

    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())#做一次全局sess
        for i in range(10):  # 这个迭代次数,可以更改,越大预测效果会更好,但需要更长时间
            for step in range(len(batch_index) - 1):#喂数据
                _, loss_ = sess.run([train_op, loss], feed_dict={X: train_x[batch_index[step]:batch_index[step + 1]],
                                                                 Y: train_y[batch_index[step]:batch_index[step + 1]]})
            print("Number of iterations:", i, " loss:", loss_)
        print("The train has finished")


train_lstm()

大家可以根据训练模型自行写出预测模型,应该不会很难了,以上均为正确代码段!

简单keras版:

   keras神经网络框架封装性好,虽然说大家经常诟病说keras不能很好的表示神经网络模型细节,但是通过调用K,还是可以很方便的进行修改自己的一些想要的东西的,作为python入门的初学者,还是建议大家熟悉一下该段核心代码,因为他很容易实现LSTM简单模型:

 

model = Sequential()#定义

model.add(LSTM(500,input_shape=(train_X.shape[1], train_X.shape[2])))#添加LSTM神经网络,即在头文件中已经导入了LSTM,输入神经网络数据形状为train_X.shape[1], train_X.shape[2]),其中500为神经元个数

# model.add(Dropout(0.5))#可根据自身情况添加dropout

 model.add(Dense(1))#定义输出层神经元个数为1个,即输出只有1维

# model.add(Activation('sigmoid'))#根据情况添加激活函数

model.compile(loss=rmse_koss, optimizer='adam')#模型优化,其中loss和optimzizer等式右边的损失函数和优化函数都可以根据自身需求进行调节和定义,当然你也可以用系统默认的损失函数和优化函数,本实现定义了RMSE为损失函数,所以你需要调用K文件库进行实现

history=model.fit(train_X, train_y, epochs=1,validation_split=0.1, batch_size=180, shuffle=True)#最后一句是对模型进行传值train_X, train_y,定义epochs迭代次数等;

 短短几行keras神经网络模型就将上述tersorflow代码所要实现的东西全部实现了,自行编写显示输出代码,即可得到如下所示的预测值与真实值的比较图,发现蓝色预测值能够很好的拟合绿色真实值,并能有效的预测出股票未来走势等;

 

最后如果大家还有什么疑问可以留言进行交流或者加入QQ群进行交流。

如果大家想做类似模型或者深度学习方面的项目或者需要学习资源可以加入QQ群:457756921,如果大家对上述模型较为感兴趣,可以开始行动了。

 

 

 

 

 

 

 

 

 

已标记关键词 清除标记
表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页