tensorflow2.x第六篇

本文介绍了一种使用RNN、LSTM和GRU等循环神经网络预测股票价格的方法。通过读取股票数据,将其归一化处理,然后使用循环神经网络进行训练和预测。最终,将预测结果与实际股票价格进行对比,并计算了预测的准确性。
  • rnn,LSTM,GRU股票预测
import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import Dropout, Dense, SimpleRNN
import matplotlib.pyplot as plt
import os
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error, mean_absolute_error
import math

maotai = pd.read_csv('./SH600519.csv')  # 读取股票文件

training_set = maotai.iloc[0:2426 - 300, 2:3].values  # 前(2426-300=2126)天的开盘价作为训练集,表格从0开始计数,2:3 是提取[2:3)列,前闭后开,故提取出C列开盘价
test_set = maotai.iloc[2426 - 300:, 2:3].values  # 后300天的开盘价作为测试集

# 归一化
sc = MinMaxScaler(feature_range=(0, 1))  # 定义归一化:归一化到(0,1)之间
training_set_scaled = sc.fit_transform(training_set)  # 求得训练集的最大值,最小值这些训练集固有的属性,并在训练集上进行归一化
test_set = sc.transform(test_set)  # 利用训练集的属性对测试集进行归一化

x_train = []
y_train = []

x_test = []
y_test = []

# 测试集:csv表格中前2426-300=2126天数据
# 利用for循环,遍历整个训练集,提取训练集中连续60天的开盘价作为输入特征x_train,第61天的数据作为标签,for循环共构建2426-300-60=2066组数据。
for i in range(60, len(training_set_scaled)):
    x_train.append(training_set_scaled[i - 60:i, 0])
    y_train.append(training_set_scaled[i, 0])
# 对训练集进行打乱
np.random.seed(7)
np.random.shuffle(x_train)
np.random.seed(7)
np.random.shuffle(y_train)
tf.random.set_seed(7)
# 将训练集由list格式变为array格式
x_train, y_train = np.array(x_train), np.array(y_train)

# 使x_train符合RNN输入要求:[送入样本数, 循环核时间展开步数, 每个时间步输入特征个数]。
# 此处整个数据集送入,送入样本数为x_train.shape[0]即2066组数据;输入60个开盘价,预测出第61天的开盘价,循环核时间展开步数为60; 每个时间步送入的特征是某一天的开盘价,只有1个数据,故每个时间步输入特征个数为1
x_train = np.reshape(x_train, (x_train.shape[0], 60, 1))
# 测试集:csv表格中后300天数据
# 利用for循环,遍历整个测试集,提取测试集中连续60天的开盘价作为输入特征x_train,第61天的数据作为标签,for循环共构建300-60=240组数据。
for i in range(60, len(test_set)):
    x_test.append(test_set[i - 60:i, 0])
    y_test.append(test_set[i, 0])
# 测试集变array并reshape为符合RNN输入要求:[送入样本数, 循环核时间展开步数, 每个时间步输入特征个数]
x_test, y_test = np.array(x_test), np.array(y_test)
x_test = np.reshape(x_test, (x_test.shape[0], 60, 1))
'''
    tf.keras.layers.SimpleRNN(
            神经元个数,
            activation=‘激活函数’,
            return_sequences=是否每个时刻输出ℎ𝑡𝑡到下一层) 
    (1)神经元个数:即循环核中记忆体的个数
    (2) return_sequences:在输出序列中,返回最后时间步的输出值ℎ𝑡𝑡还是返回全部时间步的输出。
                          当下一层依然是 RNN 层,通常为 True,反之如果后面是 Dense 层,
                          通常为 Fasle。
    (3)输入维度:三维张量(输入样本数, 循环核时间展开步数, 每个时间步输入特征个数)
    (4)输出维度:当 return_sequenc=True,三维张量(输入样本数, 循环核时间展开步数,本层的神经元个数);
                当 return_sequenc=False,二维张量(输入样本数,本层的神经元个数) 
    (5) activation:‘激活函数’(不写默认使用 tanh)
例:SimpleRNN(3, return_sequences=True),定义了一个具有三个记忆体的循环核,这个循环核会在每个时间步输出ℎ𝑡𝑡。
    '''
model = tf.keras.Sequential([
    
    SimpleRNN(80, return_sequences=True),
    Dropout(0.2),
    SimpleRNN(100),
    Dropout(0.2),
    Dense(1)
])
'''
model = tf.keras.Sequential([
    LSTM(80, return_sequences=True),
    Dropout(0.2),
    LSTM(100),
    Dropout(0.2),
    Dense(1)
])
'''
'''
model = tf.keras.Sequential([
    GRU(80, return_sequences=True),
    Dropout(0.2),
    GRU(100),
    Dropout(0.2),
    Dense(1)
])
'''
model.compile(optimizer=tf.keras.optimizers.Adam(0.001),
              loss='mean_squared_error')  # 损失函数用均方误差
# 该应用只观测loss数值,不观测准确率,所以删去metrics选项,一会在每个epoch迭代显示时只显示loss值

checkpoint_save_path = "./checkpoint/rnn_stock.ckpt"

if os.path.exists(checkpoint_save_path + '.index'):
    print('-------------load the model-----------------')
    model.load_weights(checkpoint_save_path)

cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_save_path,
                                                 save_weights_only=True,
                                                 save_best_only=True,
                                                 monitor='val_loss')

history = model.fit(x_train, y_train, batch_size=64, epochs=50, validation_data=(x_test, y_test), validation_freq=1,
                    callbacks=[cp_callback])

model.summary()

file = open('./weights.txt', 'w')  # 参数提取
for v in model.trainable_variables:
    file.write(str(v.name) + '\n')
    file.write(str(v.shape) + '\n')
    file.write(str(v.numpy()) + '\n')
file.close()

loss = history.history['loss']
val_loss = history.history['val_loss']

plt.plot(loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.title('Training and Validation Loss')
plt.legend()
plt.show()

################## predict ######################
# 测试集输入模型进行预测
predicted_stock_price = model.predict(x_test)
# 对预测数据还原---从(0,1)反归一化到原始范围
predicted_stock_price = sc.inverse_transform(predicted_stock_price)
# 对真实数据还原---从(0,1)反归一化到原始范围
real_stock_price = sc.inverse_transform(test_set[60:])
# 画出真实数据和预测数据的对比曲线
plt.plot(real_stock_price, color='red', label='MaoTai Stock Price')
plt.plot(predicted_stock_price, color='blue', label='Predicted MaoTai Stock Price')
plt.title('MaoTai Stock Price Prediction')
plt.xlabel('Time')
plt.ylabel('MaoTai Stock Price')
plt.legend()
plt.show()

##########evaluate##############
# calculate MSE 均方误差 ---> E[(预测值-真实值)^2] (预测值减真实值求平方后求均值)
mse = mean_squared_error(predicted_stock_price, real_stock_price)
# calculate RMSE 均方根误差--->sqrt[MSE]    (对均方误差开方)
rmse = math.sqrt(mean_squared_error(predicted_stock_price, real_stock_price))
# calculate MAE 平均绝对误差----->E[|预测值-真实值|](预测值减真实值求绝对值后求均值)
mae = mean_absolute_error(predicted_stock_price, real_stock_price)
print('均方误差: %.6f' % mse)
print('均方根误差: %.6f' % rmse)
print('平均绝对误差: %.6f' % mae)

------------------------------------------------------------------------------------------------
def lstm(inputs, state, params):
    W_xi, W_hi, b_i, W_xf, W_hf, b_f, W_xo, W_ho, b_o, W_xc, W_hc, b_c, W_hq, b_q = params
    (H, C) = state
    outputs = []
    for X in inputs:
        X=tf.reshape(X,[-1,W_xi.shape[0]])
        I = tf.sigmoid(tf.matmul(X, W_xi) + tf.matmul(H, W_hi) + b_i)
        F = tf.sigmoid(tf.matmul(X, W_xf) + tf.matmul(H, W_hf) + b_f)
        O = tf.sigmoid(tf.matmul(X, W_xo) + tf.matmul(H, W_ho) + b_o)
        C_tilda = tf.tanh(tf.matmul(X, W_xc) + tf.matmul(H, W_hc) + b_c)
        C = F * C + I * C_tilda
        H = O * tf.tanh(C)
        Y = tf.matmul(H, W_hq) + b_q
        outputs.append(Y)
    return outputs, (H, C)


<think>嗯,用户问的是如何逐行解析使用TensorFlow Keras API创建LSTM神经网络并进行编译和训练的代码。首先,我需要回忆一下用户提供的代码示例。看起来用户引用了两篇关于LSTM在时间序列预测中的应用,特别是股票价格预测。所以,用户的背景可能是想用LSTM处理时间序列数据,比如股市预测或者异常检测。 用户提供的代码包括模型构建的部分,使用了Sequential模型,添加了LSTM层、Dense层、Dropout层,然后编译和训练模型。我需要逐行解释这些代码的作用,确保每个参数的意义都讲清楚,比如units=64,return_sequences=True,input_shape这些参数。还要解释为什么使用LSTM而不是普通RNN,比如梯度消失的问题,以及LSTM的门控机制如何帮助解决这个问题。 然后,编译模型的时候,用户可能对损失函数和优化器的选择有疑问,比如为什么用均方误差(MSE)作为损失函数,Adam优化器的好处是什么。训练部分需要解释epochs和batch_size的作用,以及如何监控训练过程,比如validation_split的使用。 此外,用户可能还想知道每个层的作用,比如第一个LSTM层的return_sequences=True是为了将输出传递给下一个LSTM层,而第二个LSTM层不需要这个参数,因为它后面接的是全连接层。Dropout层的作用是防止过拟合,需要解释其比例参数0.5的意义。 可能还需要提到模型结构,比如输入形状input_shape=(X_train.shape[1], 1),这里的时间步长和特征数的设置。另外,模型摘要model.summary()的输出可以帮助用户理解各层的参数数量,这有助于调试和优化模型。 用户可能还关心如何评估模型性能,比如使用测试集进行预测,计算MSE或其他指标,以及如何可视化预测结果。不过根据问题,用户主要关注的是代码解析,所以需要集中在给出的代码部分,而暂时不涉及训练后的步骤。 需要确保解释清晰,用中文,避免专业术语过于晦涩,同时覆盖每一行代码的关键点。还要注意引用用户提供的参考文献,比如引用[^2]中的模型结构,说明LSTM单元如何解决梯度消失问题。同时,在回答最后生成相关问题,帮助用户深入理解,比如如何选择超参数、防止过拟合、评估模型等。</think>### 分步解析LSTM模型构建与训练代码 #### **1. 模型初始化** ```python model = keras.models.Sequential() ``` - **作用**: 创建一个顺序模型容器,用于按顺序堆叠神经网络层。顺序模型适用于简单的层堆叠结构[^2]。 - **注意**: 若需要更复杂的拓扑(如分支、共享层),需改用函数式API。 --- #### **2. 第一层LSTM单元** ```python model.add(keras.layers.LSTM(units=64, return_sequences=True, input_shape=(X_train.shape[1], 1))) ``` - **参数解析**: - `units=64`: 定义LSTM层有64个神经元,控制记忆单元容量 - `return_sequences=True`: 输出完整时间步序列(而非仅最后一步),用于堆叠多层LSTM - `input_shape=(时间步长, 特征数)`: 如`X_train.shape[1]`表示输入序列长度,`1`表示单特征(如股价) --- #### **3. 第二层LSTM单元** ```python model.add(keras.layers.LSTM(units=64)) ``` - **关键差异**: - 省略`return_sequences`,默认`False`,仅输出最后时间步结果 - 接收前一层的64维输出,进一步提取时序特征 --- #### **4. 全连接层与正则化** ```python model.add(keras.layers.Dense(128)) model.add(keras.layers.Dropout(0.5)) ``` - **Dense层**: 128个神经元的全连接层,将LSTM输出映射到高维空间 - **Dropout层**: 以0.5概率随机丢弃神经元,防止过拟合(正则化技术) --- #### **5. 输出层** ```python model.add(keras.layers.Dense(1)) ``` - **作用**: 输出最终预测值(如股价),`1`表示单目标回归任务 - **激活函数**: 默认线性激活,适合回归问题;分类任务需改用`sigmoid`等 --- #### **6. 模型编译** ```python model.compile(optimizer='adam', loss='mse') ``` - **优化器**: `adam`自适应学习率算法,平衡收敛速度与稳定性 - **损失函数**: `mse`(均方误差),衡量预测值与真实值的差异,常用于回归 --- #### **7. 模型训练** ```python model.fit(X_train, y_train, epochs=50, batch_size=32, validation_split=0.1) ``` - **参数说明**: - `epochs=50`: 全量数据迭代50次 - `batch_size=32`: 每次用32个样本更新权重 - `validation_split=0.1`: 取10%训练数据作为验证集,监控泛化能力 --- ### 关键概念补充 1. **LSTM结构优势** 通过遗忘门、输入门、输出门控制信息流,解决RNN长期依赖问题。数学表达式: $$f_t = \sigma(W_f \cdot [h_{t-1}, x_t] + b_f)$$ $$i_t = \sigma(W_i \cdot [h_{t-1}, x_t] + b_i)$$ $$C_t = f_t \cdot C_{t-1} + i_t \cdot \tanh(W_C \cdot [h_{t-1}, x_t] + b_C)$$ 2. **输入数据形状** 需为三维张量:`(样本数, 时间步长, 特征数)`。例如股价预测中,`时间步长=30`表示用30天数据预测下一天价格。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值