基于pytorch LSTM 的股票预测

学习记录于《PyTorch深度学习项目实战100例》

https://weibaohang.blog.csdn.net/article/details/127365867?ydreferer=aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzQ3MjU2MTYyL2NhdGVnb3J5XzEyMDM2MTg5Lmh0bWw%2Fc3BtPTEwMDEuMjAxNC4zMDAxLjU0ODI%3D

1.tushare

Tushare是一个免费、开源的Python财经数据接口包。主要用于提供股票及金融市场相关的数据,是国内常用的金融数据分析工具之一。Tushare对于投资研究、教学、项目背景调研等多种需求提供了极大的方便。

Tushare的主要特点有:

数据丰富:Tushare提供了包括实时行情数据、历史行情数据、基本面数据、宏观经济数据、公司基本信息、大盘指数数据、行业数据、新闻和公告等多种数据。

接口简单:使用Python调用Tushare接口相当简单。即便是初学者,只需数行代码,就能获取所需的金融数据。

社区活跃:由于Tushare的免费和开源特性,其社区相当活跃,有大量的开发者和爱好者进行维护和更新。

扩展性强:除了官方提供的数据接口,Tushare也支持自定义数据扩展,可以通过插件方式实现数据的快速扩展。

要使用Tushare,用户通常需要先进行安装,可以通过pip轻松完成。之后,通过简单的API调用,就可以获取所需的数据。

python 复制代码
!pip install tushare

2.导入必要的依赖

python 复制代码
# 1.加载股票数据
pro = ts.pro_api('your-key')
df = pro.daily(ts_code='000001.SZ', start_date='20130711', end_date='20230711')

df.index = pd.to_datetime(df.trade_date)  # 索引转为日期
df = df.iloc[::-1]  # 由于获取的数据是倒序的,需要将其调整为正序

如何获取your-key

注册网站

https://tushare.pro/register
注册后进入个人主页


找到接口token

复制后粘贴 到your-key 里面

python 复制代码
# 创建一个 StandardScaler 实例
scaler = StandardScaler()
scaler_model = StandardScaler()

# 使用 scaler 对数据进行拟合和转换
data = scaler_model.fit_transform(np.array(df[['open', 'high', 'low', 'close']]).reshape(-1, 4))

# 使用 scaler 对 'close' 列进行拟合和转换
scaler.fit_transform(np.array(df['close']).reshape(-1, 1))

分开训练集和测试集

python 复制代码
def split_data(data,timestep):
  dataX= [] # 用于存储输入序列
  dataY= [] # 用于存储输出数据

  #将整个窗口的数据保存到X中,将未来的一天保存到Y中
  for index in range(len(data)-timestep):
    # 提取时间窗口内的数据作为输入序列
    dataX.append(data[index: index + timestep])
    # 下一个时间步的数据作为输出
    dataY.append(data[index + timestep][3]) #输出为第四列('close' 列)

  dataX = np.array(dataX)
  dataY = np.array(dataY)

  #获取训练集大小
  train_size = int(np.round(0.8 * dataX.shape[0]))

  # 划分训练集,测试集
  x_train = dataX[: train_size, :].reshape(-1, timestep, 4)
  y_train = dataY[: train_size]

  x_test = dataX[train_size:, :].reshape(-1, timestep, 4)
  y_test = dataY[train_size:]


  return[x_train,y_train,x_test,y_test]
python 复制代码
# 3.获取训练数据, x_train:1750,1,4
x_train,y_train,x_test,y_test = split_data(data,timestep=1)

探究数据集

python 复制代码
# 4.将数据转为tensor
x_train_tensor = torch.from_numpy(x_train).to(torch.float32)
y_train_tensor = torch.from_numpy(y_train).to(torch.float32)
x_test_tensor = torch.from_numpy(x_test).to(torch.float32)
y_test_tensor = torch.from_numpy(y_test).to(torch.float32)
python 复制代码
# 5.形成训练数据集
train_data = TensorDataset(x_train_tensor, y_train_tensor)
test_data = TensorDataset(x_test_tensor, y_test_tensor)

# 6.将数据加载成迭代器
batch_size =16
train_loader = torch.utils.data.DataLoader(train_data,
                                           batch_size,
                                           True)

test_loader = torch.utils.data.DataLoader(test_data,
                                          batch_size,
                                          False)

LSTM

LSTM,即长短时记忆(Long Short-Term Memory)网络,是一种特殊的循环神经网络(Recurrent Neural Network, RNN)结构。LSTM旨在解决传统RNN在处理长序列数据时容易出现的梯度消失或梯度爆炸问题。

以下是LSTM的主要组成部分和功能:

遗忘门 (Forget Gate): 决定从单元状态中删除什么信息。使用sigmoid函数,输出0表示"完全忘记",输出1表示"完全保留"。

输入门 (Input Gate): 有两部分组成。第一部分是sigmoid层,决定哪些值我们将更新。第二部分是tanh层,创建一个新的候选值向量,它可能被加到状态中。

单元状态 (Cell State): LSTM的核心部分,其在整个链上都有运行,只有一些少量的线性交互。单元状态类似于传送带,信息可以在其上自由流动,除非受到遗忘门或输入门的影响。

输出门 (Output Gate): 决定基于单元状态输出什么值。首先,sigmoid层决定我们将输出哪些部分。然后,将单元状态通过tanh(得到值在-1到1之间)并乘以sigmoid层的输出,这样只输出我们决定的部分。

LSTM的关键优势在于其能够记住长期的依赖关系。在许多序列任务中,当前的输出不仅仅依赖于前几个步骤,还可能依赖于很早之前的步骤。LSTM相比于普通的RNN更能够捕捉这些长期依赖关系。

实际上,LSTM的变种还有很多,例如GRU(Gated Recurrent Units)。不过,无论其结构如何调整,LSTM的核心思想是利用不同的门控结构来有选择地控制信息流,从而更好地学习和记住长期依赖关系

python 复制代码
class LSTM(nn.Module):
  def __init__(self,input_dim,hidden_dim,num_layers,output_dim):
    super(LSTM,self).__init__()
    self.hidden_dim = hidden_dim #隐藏层大小
    self.num_layers = num_layers #LSTM层数
    # input_dim 为特征维度,就是每个时间点对应的特征数量,这里为4
    self.lstm = nn.LSTM(input_dim,hidden_dim,num_layers,batch_first=True)
    self.fc = nn.Linear(hidden_dim,output_dim)

  def forward(self,x):
    # Initialize hidden state and cell state
    h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_dim)
    c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_dim)

    # Forward propagate through LSTM
    output, (h_n, c_n)= self.lstm(x, (h0, c0))
    batch_size, timestep, hidden_dim = output.shape

    # 将output变成 batch_size * timestep, hidden_dim
    output = output.reshape(-1, hidden_dim)
    output = self.fc(output)  # 形状为batch_size * timestep, 1
    output = output.reshape(timestep, batch_size, -1)
    return output[-1]  # 返回最后一个时间片的输出
python 复制代码
model = LSTM(input_dim, hidden_dim, num_layers, output_dim)  # 定义LSTM网络

打印模型

定义损失函数

python 复制代码
loss_function = nn.MSELoss()  # 定义损失函数
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)  # 定义优化器

配置信息

python 复制代码
timestep = 1  # 时间步长,就是利用多少时间窗口
batch_size = 16  # 批次大小
input_dim = 4  # 每个步长对应的特征数量,就是使用每天的4个特征,最高、最低、开盘、落盘
hidden_dim = 64  # 隐层大小
output_dim = 1  # 由于是回归任务,最终输出层大小为1
num_layers = 3  # LSTM的层数
epochs = 10
best_loss = 0
model_name = 'LSTM'
save_path = './{}.pth'.format(model_name)

train

python 复制代码
# 8. model 训练
save_path = '/content/sample_data/best.pth'
for epoch in range(epochs):
  model.train()
  running_loss= 0 #初始loss值
  train_bar = tqdm(train_loader) #通过使用tqdm来展示进度条
  for data in train_bar:
    x_train, y_train = data #
    # print(x_train.shape,y_train.shape) torch.Size([16, 1, 4]) torch.Size([16])
    optimizer.zero_grad()
    y_train_pred = model(x_train)
    loss = loss_function(y_train_pred,y_train.reshape(-1,1))
    loss.backward()
    optimizer.step()

    running_loss += loss.item()
    train_bar.desc = "train epoch[{}/{}] loss:{:.3f}".format(epoch + 1,epochs,loss) #每次你计算 loss 并更新 train_bar.desc,进度条的描述就会更新,从而实时显示你的训练 loss 和当前 epoch。
    torch.save(model.state_dict(),save_path)

加载模型

python 复制代码
# 加载权重和偏置
model.load_state_dict(torch.load(save_path))

模型验证

python 复制代码
# 模型验证
model.eval()
test_loss = 0
save_path_2="/content/sample_data/best_2.pth"
with torch.no_grad():
   test_bar = tqdm(test_loader)
   for data in test_bar:
      x_test, y_test = data
      y_test_pred = model(x_test)
      test_loss = loss_function(y_test_pred, y_test.reshape(-1, 1))

if test_loss < best_loss:
  best_loss = test_loss
  torch.save(model.state_dict(), save_path_2)

绘制模型

python 复制代码
# 9.绘制结果 train 的结果
pred_value =model(x_train_tensor).detach().numpy().reshape(-1, 1)
true_value =y_train_tensor.detach().numpy().reshape(-1, 1)
plt.figure(figsize=(12, 8))
plt.plot(scaler.inverse_transform(pred_value, "b"),label="Preds_value")
plt.plot(scaler.inverse_transform(true_value, "r"),label="Data_value")
plt.legend()
plt.show()

绘制test的结果

python 复制代码
y_test_pred = model(x_test_tensor)
plt.figure(figsize=(12, 8))
plt.plot(scaler.inverse_transform(y_test_pred.detach().numpy()), "b",label="pred_value")
plt.plot(scaler.inverse_transform(y_test_tensor.detach().numpy().reshape(-1, 1)), "r",label='true_value')
plt.legend()
plt.show()

代码ipynb

相关推荐
进击的六角龙29 分钟前
Python中处理Excel的基本概念(如工作簿、工作表等)
开发语言·python·excel
一只爱好编程的程序猿1 小时前
Java后台生成指定路径下创建指定名称的文件
java·python·数据下载
Aniay_ivy1 小时前
深入探索 Java 8 Stream 流:高效操作与应用场景
java·开发语言·python
gonghw4031 小时前
DearPyGui学习
python·gui
向阳12181 小时前
Bert快速入门
人工智能·python·自然语言处理·bert
engchina1 小时前
Neo4j 和 Python 初学者指南:如何使用可选关系匹配优化 Cypher 查询
数据库·python·neo4j
兆。1 小时前
掌握 PyQt5:从零开始的桌面应用开发
开发语言·爬虫·python·qt
南宫理的日知录2 小时前
99、Python并发编程:多线程的问题、临界资源以及同步机制
开发语言·python·学习·编程学习
coberup2 小时前
django Forbidden (403)错误解决方法
python·django·403错误
龙哥说跨境2 小时前
如何利用指纹浏览器爬虫绕过Cloudflare的防护?
服务器·网络·python·网络爬虫