LSTM股票预测学习

有参考,有参考。自存学习 

#!/usr/bin/python3
# -*- encoding: utf-8 -*-
import os
os.environ['KMP_DUPLICATE_LIB_OK'] = 'TRUE'
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import torch
from torch import nn
import time

DAYS_FOR_TRAIN = 10


class LSTM_Regression(nn.Module):#调用nn.Module的初始化函数,初始化LSTMRegression类
    """
        使用LSTM进行回归

        参数:
        - input_size: feature size
        - hidden_size: number of hidden units
        - output_size: number of output
        - num_layers: layers of LSTM to stack
    """

    def __init__(self, input_size, hidden_size, output_size=1, num_layers=2):
        super().__init__()

        self.lstm = nn.LSTM(input_size, hidden_size, num_layers)#定义一个LSTM层
        # 其中输入的大小为inputsize,输出的大小为hiddensize,LSTM的层数为numlayers。
        self.fc = nn.Linear(hidden_size, output_size)
        #定义全连接层

    def forward(self, _x):
        x, _ = self.lstm(_x)  # _x is input, size (seq_len, batch, input_size)
        #这行代码是在LSTMRegression类的forward函数中,将输入_x送入LSTM层中进行计算,并将输出赋值给变量x
        s, b, h = x.shape  # x is output, size (seq_len, batch, hidden_size)
        x = x.view(s * b, h)
        x = self.fc(x)#把x送入全连接层
        x = x.view(s, b, -1)  # 把形状改回来
        return x


def create_dataset(data, days_for_train=5) -> (np.array, np.array):
    """
        根据给定的序列data,生成数据集

        数据集分为输入和输出,每一个输入的长度为days_for_train,每一个输出的长度为1。
        也就是说用days_for_train天的数据,对应下一天的数据。

        若给定序列的长度为d,将输出长度为(d-days_for_train+1)个输入/输出对
    """
    dataset_x, dataset_y = [], []
    for i in range(len(data) - days_for_train):
        _x = data[i:(i + days_for_train)]
        dataset_x.append(_x)
        dataset_y.append(data[i + days_for_train])
    return (np.array(dataset_x), np.array(dataset_y))
## 数据类型变换:dataset_x和data_set_y数据类型(type)由列表(list)->数组(numpy.nparray
#由序列变为数组

#模型训练
if __name__ == '__main__':
    t0 = time.time()
    #记录当前时间,将其赋值给变量t0。
    #通常情况下,可以通过将代码结束时的当前时间减去t0的值来测量代码的执行时间
    data_close = pd.read_csv('000001.csv')  # 读取文件

   #data_close = ts.get_k_data('000001', start='2019-01-01', index=True)['close']"""
   # 取上证指数的收盘价 ,'index=True'表示获取的是指数数据,而不是股票数据。['close']表示只获取收盘价数据。
   #data_close.to_csv('000001.csv', index=False)  # 将下载的数据转存为.csv格式保存
    #data_close = pd.read_csv('000001.csv')  # 读取.csv文件'''
    # df_sh = ts.get_k_data('sh', start='2019-01-01', end=datetime.datetime.now().strftime('%Y-%m-%d'))
    # print(df_sh.shape)'''


    '绘制原始数据折线图aa'
    data_close = data_close.astype('float32').values
    #转换数据type,数据类型转换为float32,values将其转换为numpy数组
    plt.plot(data_close)#将数据绘制折线图
    plt.savefig('data.png', format='png', dpi=200)#保存图像,名字,格式,分辨率
    plt.close()#关闭

    '数据预处理,将价格标准化到0~1'
    max_value = np.max(data_close)
    min_value = np.min(data_close)
    data_close = (data_close - min_value) / (max_value - min_value)
    '制作数据集'
    dataset_x, dataset_y = create_dataset(data_close, DAYS_FOR_TRAIN)

    '划分训练集和测试集,70%作为训练集'
    train_size = int(len(dataset_x) * 0.7)

    train_x = dataset_x[:train_size]
    train_y = dataset_y[:train_size]

    # 将数据改变形状,RNN 读入的数据维度是 (seq_size, batch_size, feature_size)
    train_x = train_x.reshape(-1, 1, DAYS_FOR_TRAIN)
    #-1表示该维度的大小由程序自动计算得出,1表示batchsize为1,
    # DAYSFORTRAIN表示featuresize为DAYSFORTRAIN。这是为了将数据转换为RNN读入的格式。
    train_y = train_y.reshape(-1, 1, 1)

    # 转为pytorch的tensor对象
    '将numpy数组trainx转换为PyTorch的tensor对象。'
    '这是因为在PyTorch中,神经网络的输入和输出必须是tensor对象。'
    '通过将trainx转换为tensor对象,可以将其作为神经网络的输入'
    train_x = torch.from_numpy(train_x)
    train_y = torch.from_numpy(train_y)

    model = LSTM_Regression(DAYS_FOR_TRAIN, 8, output_size=1, num_layers=2)
    # 导入模型并设置模型的参数输入输出层、隐藏层等

    model_total = sum([param.nelement() for param in model.parameters()])
    # 计算模型参数
    print("Number of model_total parameter: %.8fM" % (model_total / 1e6))
#这行代码的作用是打印模型的总参数数量。我们使用了Python的百分号格式化字符串,
# 其中%.8f表示将一个浮点数格式化为8位小数的字符串。我们将模型的总参数数量除以1e6,以将其从字节转换为兆字节。
# 最后,我们将结果插入到字符串中,使用%f占位符。
    train_loss = []
    loss_function = nn.MSELoss()
    optimizer = torch.optim.Adam(model.parameters(), lr=1e-2, betas=(0.9, 0.999), eps=1e-08, weight_decay=0)
    for i in range(200):#迭代200次
        out = model(train_x)
        loss = loss_function(out, train_y)
        loss.backward()
        optimizer.step()
        optimizer.zero_grad()
        train_loss.append(loss.item())
        '访问损失函数的值,您可以使用loss.item()方法。'
        '该方法将损失函数的标量值作为Python浮点数返回'
        '您可以使用loss.item()方法。该方法将损失函数的标量值作为Python浮点数返回'
        # 将训练过程的迭代次数和损失值写入文档保存,并在终端打印出来
        with open('log.txt', 'a+') as f:
            f.write('{} - {}\n'.format(i + 1, loss.item()))
        if (i + 1) % 1 == 0:
            print('Epoch: {}, Loss:{:.5f}'.format(i + 1, loss.item()))
    torch.save(model,"model.pt")
    # 画loss曲线 matplotlib
    plt.figure()#创建一个图形,空白画布
    plt.plot(train_loss, c='b', label='loss')#plt.plot(x可省略, y, format_string, 样式**kwargs)
    plt.title("Train_Loss_Curve")
    plt.ylabel('train_loss')
    plt.xlabel('epoch_num')
    plt.savefig('loss.png', format='png', dpi=200)
    plt.close()

    # torch.save(model.state_dict(), 'model_params.pkl')  # 可以保存模型的参数供未来使用
    t1 = time.time()
    T = t1 - t0
    print('The training time took %.2f' % (T / 60) + ' mins.')

    tt0 = time.asctime(time.localtime(t0))
    tt1 = time.asctime(time.localtime(t1))
    print('The starting time was ', tt0)
    print('The finishing time was ', tt1)

    # for test
    model = model.eval()  # 转换成测试模式
    # model.load_state_dict(torch.load('model_params.pkl'))  # 读取参数

    # 注意这里用的是全集 模型的输出长度会比原数据少DAYS_FOR_TRAIN 填充使长度相等再作图
    dataset_x = dataset_x.reshape(-1, 1, DAYS_FOR_TRAIN)  # (seq_size, batch_size, feature_size)
    dataset_x = torch.from_numpy(dataset_x)

    pred_test = model(dataset_x)  # 全量训练集
    # 的模型输出 (seq_size, batch_size, output_size)
    pred_test = pred_test.view(-1).data.numpy()
    pred_test = np.concatenate((np.zeros(DAYS_FOR_TRAIN), pred_test))  # 填充0 使长度相同
    assert len(pred_test) == len(data_close)

    plt.plot(pred_test, 'r', label='prediction')
    plt.plot(data_close, 'b', label='real')
    plt.plot((train_size, train_size), (0, 1), 'g--')#g-- 绿色虚线
# 分割线 左边是训练数据 右边是测试数据的输出
    plt.legend(loc='best')#添加图例 loc='best'位置默认,自动选择最佳位置
    plt.savefig('result.png', format='png', dpi=200)
    plt.close()

  • 13
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值