从零学习量化交易54LSTM神经网络股票趋势预测2

(1)打开Spyder软件,在目录D:\zwPython\zwrk\1_Quant_TensorFlow,新建文件

# -*- coding: utf-8 -*-
"""
Created on Tue Feb 18 16:21:25 2025

@author: Administrator
"""
import sys, os
sys.path.append("topqt/")

import numpy as np
import pandas as pd
import tushare as ts
import plotly as py
import plotly.figure_factory as pyff

import math
import arrow
import ffn
import pypinyin
import pandas_datareader as pdr
import matplotlib.pyplot as plt

import zsys2025  # 20250213
import ztools2025 as zt
import ztools_str as zstr
import ztools_data2025 as zdat
import ztools_draw2025 as zdr
import ztools_tq2025 as ztq  # 20250213
import zai_keras2025 as zks

import tensorflow as tf
from tensorflow.keras.models import Sequential, load_model
from tensorflow.keras.layers import Dense, Input, Dropout
from tensorflow.keras.optimizers import RMSprop
from tensorflow.keras.utils import plot_model
from tensorflow.keras.callbacks import TensorBoard

import tensorlayer as tl

# 1
print('\n#1,set.sys')
pd.set_option('display.width', 450)
pd.set_option('display.float_format', zt.xfloat3)
rlog = os.path.join('tmp', 'log_tmp')
# 注意:tf.gfile.DeleteRecursively 在 TensorFlow 2.x 中已被弃用,使用 tf.io.gfile.rmtree 替代
if os.path.exists(rlog):
    tf.io.gfile.rmtree(rlog)

#2.1 
print('\n#2.1,读取数据')
rss, fsgn, ksgn = 'tmp1/', 'TDS2_sz50', 'avg'
xlst = zsys2025.TDS_xlst9
zt.prx('xlst', xlst)

#
df_train, df_test, x_train, y_train, x_test, y_test = zdat.frd_TDS(rss, fsgn, ksgn, xlst)
#
df_train,df_test,y_train,y_test=zdat.df_xed_xtyp2x(df_train,df_test,'3',k0=99.5,k9=100.5)
y_train,y_test=pd.get_dummies(df_train['y']).values,pd.get_dummies(df_test['y']).values
#
typ_lst=y_train[0]
num_in,num_out=len(xlst),len(typ_lst)
print('\nnum_in,num_out:',num_in,num_out)
#
print('\ndf_test.tail()')
print(df_test.tail())
print('\nx_train.shape,', x_train.shape)
print('\ntype(x_train),', type(x_train))

#
#2.2
print('\n#2.2,转换数据格式shape')
rxn,txn=x_train.shape[0],x_test.shape[0]
x_train,x_test = x_train.reshape(rxn,num_in,-1),x_test.reshape(txn,num_in,-1)
print('\nx_train.shape,',x_train.shape)
print('\ntype(x_train),',type(x_train))


#
# 3
print('\n#3,model建立神经网络模型')
mx = zks.lstm020typ(num_in, num_out)
#
mx.summary()
plot_model(mx, to_file=os.path.join('tmp1', 'lstm0202_53.png'))


# 4 模型训练 
print('\n#4 模型训练 fit')  # 设置 profile_batch=0 禁用性能分析  verbose=0
tbCallBack = TensorBoard(log_dir=rlog, write_graph=True, write_images=True, profile_batch=0)
tn0 = arrow.now()
mx.fit(x_train, y_train, epochs=50,  batch_size=512, callbacks=[tbCallBack])
tn = zt.timNSec('', tn0, True)
# 确保保存模型的目录存在
model_save_dir = os.path.join('tmp1')
if not os.path.exists(model_save_dir):
    os.makedirs(model_save_dir)
model_save_path = os.path.join(model_save_dir, 'lstm0202_53.dat')
mx.save(model_save_path)


# 5 利用模型进行预测 predict
print('\n#5 模型预测 predict')
tn0 = arrow.now()
y_pred0 = mx.predict(x_test)
tn = zt.timNSec('', tn0, True)
y_pred=np.argmax(y_pred0, axis=1)+1
df_test['y_pred'] = zdat.ds4x(y_pred, df_test.index, True)
df_test.to_csv(os.path.join('tmp1', 'lstm0202_53.csv'), index=False)

#6
print('\n#6 acc准确度分析')
print('\nky0=10')
df=df_test
dacc,dfx,a10=ztq.ai_acc_xed2ext(df.y,df.y_pred,ky0=10,fgDebug=True)


#4
print('\n#4 acc准确度分类分析')
x1,x2=df['y'].value_counts(),df['y_pred'].value_counts()
zt.prx('x1',x1);zt.prx('x2',x2)

(2)程序输出结果

runfile('D:/zwPython/zwrk/1_Quant_TensorFlow/53-LSYMTrendsPrediction82-2.py.py', wdir='D:/zwPython/zwrk/1_Quant_TensorFlow')
Reloaded modules: zsys2025, ztools2025, zsys, ztools_str, ztools, ztools_web, ztools_data, ztools_tq, zpd_talib, ztools_data2025, zpd_talib2025, ztools_draw2025, ztools_tq2025, zai_keras2025, zai_tools2025

#1,set.sys

#2.1,读取数据

 xlst
['open', 'high', 'low', 'close', 'volume', 'avg', 'ma_2', 'ma_3', 'ma_5', 'ma_10', 'ma_15', 'ma_20', 'ma_25', 'ma_30', 'ma_50', 'ma_100', 'xyear', 'xmonth', 'xday', 'xday_week', 'xday_year', 'xweek_year']

num_in,num_out: 22 3

df_test.tail()
       open  high   low  close  ...  price  price_next  price_change  ktype
94939 4.390 4.510 4.380  4.510  ...  4.450       4.580       102.921      3
94940 4.490 4.490 4.420  4.430  ...  4.460       4.580       102.691      3
94941 4.440 4.530 4.420  4.500  ...  4.470       4.580       102.461      3
94942 4.490 4.510 4.460  4.480  ...  4.490       4.590       102.227      3
94943 4.490 4.530 4.490  4.520  ...  4.510       4.590       101.774      3

[5 rows x 27 columns]

x_train.shape, (116761, 22)

type(x_train), <class 'numpy.ndarray'>

#2.2,转换数据格式shape

x_train.shape, (116761, 22, 1)

type(x_train), <class 'numpy.ndarray'>

#3,model建立神经网络模型
Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
lstm_1 (LSTM)                (None, 22, 176)           125312    
_________________________________________________________________
dropout (Dropout)            (None, 22, 176)           0         
_________________________________________________________________
lstm_2 (LSTM)                (None, 88)                93280     
_________________________________________________________________
dropout_1 (Dropout)          (None, 88)                0         
_________________________________________________________________
dense_1 (Dense)              (None, 3)                 267       
=================================================================
Total params: 218,859
Trainable params: 218,859
Non-trainable params: 0
_________________________________________________________________

#4 模型训练 fit
Train on 116761 samples
Epoch 1/50
116761/116761 [==============================] - 69s 595us/sample - loss: 0.7941 - acc: 0.7172
Epoch 2/50
  4608/116761 [>.............................] - ETA: 1:04 - loss: 0.8010 - acc: 0.7125
Epoch 50/50
116761/116761 [==============================] - 75s 644us/sample - loss: 0.6824 - acc: 0.7320
3684.98 s, 17:36:02 ,t0, 16:34:37
WARNING:tensorflow:AutoGraph could not transform <function canonicalize_signatures.<locals>.signature_wrapper at 0x000002261DEAD438> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 3, expecting 4
WARNING: AutoGraph could not transform <function canonicalize_signatures.<locals>.signature_wrapper at 0x000002261DEAD438> and will run it as-is.
Please report this to the TensorFlow team. When filing the bug, set the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and attach the full output.
Cause: Bad argument number for Name: 3, expecting 4
INFO:tensorflow:Assets written to: tmp1\lstm0202_53.dat\assets

#5 模型预测 predict
30.37 s, 17:36:37 ,t0, 17:36:06

#6 acc准确度分析

ky0=10
ky0=10; n_df9,94944,n_dfk,63491
acc: 66.87%;  MSE:0.76, MAE:0.48,  RMSE:0.87, r2score:-0.46, @ky0:10.00

#4 acc准确度分类分析

 x1
3.000    64961
2.000    16967
1.000    13016
Name: y, dtype: int64

 x2
3    90375
1     2571
2     1998
Name: y_pred, dtype: int64

(3)程序代码注释

# -*- coding: utf-8 -*-
"""
Created on Tue Feb 18 16:21:25 2025

@author: Administrator
"""
# 导入sys和os模块,sys模块用于与Python解释器交互,os模块用于与操作系统交互
import sys, os
# 将"topqt/"目录添加到Python的模块搜索路径中,方便后续导入该目录下的自定义模块
sys.path.append("topqt/")

# 导入numpy库,用于高效的数值计算和数组操作
import numpy as np
# 导入pandas库,用于数据处理和分析,提供DataFrame等数据结构
import pandas as pd
# 导入tushare库,可用于获取财经数据,如股票数据
import tushare as ts
# 导入plotly库,用于创建交互式可视化图表
import plotly as py
# 导入plotly的figure_factory模块,提供创建特定类型图表的工具
import plotly.figure_factory as pyff

# 导入math模块,提供数学相关的函数
import math
# 导入arrow模块,用于处理日期和时间
import arrow
# 导入ffn库,用于金融数据分析
import ffn
# 导入pypinyin库,用于将汉字转换为拼音
import pypinyin
# 导入pandas_datareader库,用于从各种数据源读取金融数据
import pandas_datareader as pdr
# 导入matplotlib.pyplot库,用于绘制静态图表
import matplotlib.pyplot as plt

# 导入自定义模块zsys2025,可能包含系统配置和常量
import zsys2025  # 20250213
# 导入自定义模块ztools2025,可能包含通用工具函数
import ztools2025 as zt
# 导入自定义模块ztools_str,可能包含字符串处理工具函数
import ztools_str as zstr
# 导入自定义模块ztools_data2025,可能包含数据处理工具函数
import ztools_data2025 as zdat
# 导入自定义模块ztools_draw2025,可能包含绘图工具函数
import ztools_draw2025 as zdr
# 导入自定义模块ztools_tq2025,可能包含与tushare相关的工具函数
import ztools_tq2025 as ztq  # 20250213
# 导入自定义模块zai_keras2025,可能包含与Keras相关的自定义函数
import zai_keras2025 as zks

# 导入tensorflow库,用于构建和训练深度学习模型
import tensorflow as tf
# 从tensorflow.keras.models模块中导入Sequential和load_model函数
# Sequential用于创建顺序模型,load_model用于加载已保存的模型
from tensorflow.keras.models import Sequential, load_model
# 从tensorflow.keras.layers模块中导入Dense、Input和Dropout层
# Dense是全连接层,Input是输入层,Dropout用于防止过拟合
from tensorflow.keras.layers import Dense, Input, Dropout
# 从tensorflow.keras.optimizers模块中导入RMSprop优化器
from tensorflow.keras.optimizers import RMSprop
# 从tensorflow.keras.utils模块中导入plot_model函数,用于绘制模型的结构示意图
from tensorflow.keras.utils import plot_model
# 从tensorflow.keras.callbacks模块中导入TensorBoard回调函数,用于可视化训练过程
from tensorflow.keras.callbacks import TensorBoard

# 导入tensorlayer库,一个基于TensorFlow的深度学习库
import tensorlayer as tl

# 1
print('\n#1,set.sys')
# 设置pandas显示宽度为450个字符,方便查看数据
pd.set_option('display.width', 450)
# 设置pandas显示浮点数的格式,调用zt.xfloat3函数进行格式化
pd.set_option('display.float_format', zt.xfloat3)
# 定义日志文件的存储路径,将其存储在'tmp'目录下的'log_tmp'文件夹中
rlog = os.path.join('tmp', 'log_tmp')
# 检查日志文件路径是否存在,如果存在则删除该路径下的所有文件和文件夹
# 注意:tf.gfile.DeleteRecursively 在 TensorFlow 2.x 中已被弃用,使用 tf.io.gfile.rmtree 替代
if os.path.exists(rlog):
    tf.io.gfile.rmtree(rlog)

#2.1 
print('\n#2.1,读取数据')
# 定义数据存储的根路径
rss = 'tmp1/'
# 定义数据文件的标识
fsgn = 'TDS2_sz50'
# 定义数据的关键字
ksgn = 'avg'
# 从zsys2025模块中获取TDS_xlst9列表,该列表可能包含数据的特征列名
xlst = zsys2025.TDS_xlst9
# 调用zt.prx函数打印xlst列表的内容
zt.prx('xlst', xlst)

# 调用zdat.frd_TDS函数从指定路径读取数据,并将数据划分为训练集和测试集
# df_train是训练集的DataFrame,df_test是测试集的DataFrame
# x_train是训练集的特征数据,y_train是训练集的标签数据
# x_test是测试集的特征数据,y_test是测试集的标签数据
df_train, df_test, x_train, y_train, x_test, y_test = zdat.frd_TDS(rss, fsgn, ksgn, xlst)
# 对训练集和测试集的数据进行处理,可能是对数据进行标准化、归一化等操作
# '3'可能是处理的类型,k0和k9可能是处理的参数
df_train, df_test, y_train, y_test = zdat.df_xed_xtyp2x(df_train, df_test, '3', k0=99.5, k9=100.5)
# 将训练集和测试集的标签数据进行one-hot编码,将类别型数据转换为数值型数据
y_train, y_test = pd.get_dummies(df_train['y']).values, pd.get_dummies(df_test['y']).values
# 获取一个样本的one-hot编码结果,用于确定输出的类别数量
typ_lst = y_train[0]
# 计算输入特征的数量,即xlst列表的长度
num_in = len(xlst)
# 计算输出的类别数量
num_out = len(typ_lst)
# 打印输入和输出的数量
print('\nnum_in,num_out:', num_in, num_out)
# 打印测试集的最后几行数据
print('\ndf_test.tail()')
print(df_test.tail())
# 打印训练集特征数据的形状
print('\nx_train.shape,', x_train.shape)
# 打印训练集特征数据的类型
print('\ntype(x_train),', type(x_train))

#
#2.2
print('\n#2.2,转换数据格式shape')
# 获取训练集和测试集特征数据的样本数量
rxn = x_train.shape[0]
txn = x_test.shape[0]
# 将训练集和测试集的特征数据转换为适合LSTM模型输入的形状
# LSTM模型通常需要输入三维数据,形状为(样本数量, 时间步长, 特征数量)
x_train, x_test = x_train.reshape(rxn, num_in, -1), x_test.reshape(txn, num_in, -1)
# 打印转换后训练集特征数据的形状
print('\nx_train.shape,', x_train.shape)
# 打印转换后训练集特征数据的类型
print('\ntype(x_train),', type(x_train))

#
# 3
print('\n#3,model建立神经网络模型')
# 调用zks.lstm020typ函数创建一个LSTM模型,传入输入和输出的数量作为参数
mx = zks.lstm020typ(num_in, num_out)
# 打印模型的概要信息,包括模型的层数、每层的参数数量等
mx.summary()
# 绘制模型的结构示意图,并保存为'tmp1'目录下的'lstm0202_53.png'文件
plot_model(mx, to_file=os.path.join('tmp1', 'lstm0202_53.png'))

# 4 模型训练 
print('\n#4 模型训练 fit')  # 设置 profile_batch=0 禁用性能分析  verbose=0
# 创建一个TensorBoard回调函数,用于记录训练过程的日志信息
# log_dir指定日志文件的存储路径,write_graph表示是否记录模型的图结构,write_images表示是否记录模型的权重图像
# profile_batch=0表示禁用性能分析
tbCallBack = TensorBoard(log_dir=rlog, write_graph=True, write_images=True, profile_batch=0)
# 记录训练开始的时间
tn0 = arrow.now()
# 使用训练集数据对模型进行训练
# epochs表示训练的轮数,batch_size表示每个批次的样本数量,callbacks表示要使用的回调函数
mx.fit(x_train, y_train, epochs=50,  batch_size=512, callbacks=[tbCallBack])
# 计算训练所花费的时间,并打印出来
tn = zt.timNSec('', tn0, True)
# 确保保存模型的目录存在
model_save_dir = os.path.join('tmp1')
if not os.path.exists(model_save_dir):
    os.makedirs(model_save_dir)
# 定义模型保存的路径
model_save_path = os.path.join(model_save_dir, 'lstm0202_53.dat')
# 保存训练好的模型
mx.save(model_save_path)

# 5 利用模型进行预测 predict
print('\n#5 模型预测 predict')
# 记录预测开始的时间
tn0 = arrow.now()
# 使用训练好的模型对测试集数据进行预测,得到每个类别的概率值
y_pred0 = mx.predict(x_test)
# 计算预测所花费的时间,并打印出来
tn = zt.timNSec('', tn0, True)
# 找出每个样本中概率最大的类别的索引,并加1得到类别标签
y_pred = np.argmax(y_pred0, axis=1) + 1
# 将预测结果转换为适合DataFrame存储的格式,并添加到测试集的DataFrame中
df_test['y_pred'] = zdat.ds4x(y_pred, df_test.index, True)
# 将包含预测结果的测试集DataFrame保存为CSV文件
df_test.to_csv(os.path.join('tmp1', 'lstm0202_53.csv'), index=False)

#6
print('\n#6 acc准确度分析')
print('\nky0=10')
# 将测试集的DataFrame赋值给df变量
df = df_test
# 调用ztq.ai_acc_xed2ext函数对预测结果进行准确度分析
# df.y是测试集的真实标签,df.y_pred是模型的预测标签
# ky0是一个参数,可能用于控制分析的范围或精度,fgDebug=True表示开启调试模式
dacc, dfx, a10 = ztq.ai_acc_xed2ext(df.y, df.y_pred, ky0=10, fgDebug=True)

#4
print('\n#4 acc准确度分类分析')
# 统计测试集真实标签的类别分布
x1 = df['y'].value_counts()
# 统计测试集预测标签的类别分布
x2 = df['y_pred'].value_counts()
# 调用zt.prx函数打印真实标签的类别分布
zt.prx('x1', x1)
# 调用zt.prx函数打印预测标签的类别分布
zt.prx('x2', x2)

(4)程序涉及的函数

# 定义一个名为 lstm020typ 的函数,用于构建一个用于分类任务的 LSTM 神经网络模型
# num_in 是输入特征的数量,默认值为 10
# num_out 是输出类别的数量,默认值为 1
def lstm020typ(num_in=10, num_out=1):
    # 创建一个 Sequential 模型实例
    # Sequential 模型是 Keras 中最简单的模型类型,它是一个线性堆叠的层序列,我们可以按顺序依次添加不同的层
    model = Sequential()
    #

    # 向模型中添加第一个 LSTM 层
    # LSTM 层是长短期记忆网络的核心层,能够处理序列数据并捕捉长期依赖关系
    # num_in * 8 表示该 LSTM 层的神经元数量,通常根据输入特征数量进行一定倍数的扩展
    # return_sequences=True 表示返回每个时间步的输出序列,这在堆叠多个 LSTM 层时是必要的,因为下一层的 LSTM 层需要接收完整的序列作为输入
    # input_shape=(num_in, 1) 指定了输入数据的形状,num_in 表示时间步长,即每个样本包含的时间步数,1 表示每个时间步的特征数量
    model.add(LSTM(num_in * 8, return_sequences=True, input_shape=(num_in, 1)))

    # 向模型中添加一个 Dropout 层
    # Dropout 是一种正则化技术,用于防止过拟合
    # 0.2 表示随机将 20% 的输入单元在训练过程中置为 0,这样可以迫使网络学习更鲁棒的特征表示
    model.add(Dropout(0.2))
    #

    # 向模型中添加第二个 LSTM 层
    # 这里没有设置 return_sequences=True,因为这是最后一个 LSTM 层,我们只需要它输出最后一个时间步的结果
    # num_in * 4 表示该 LSTM 层的神经元数量
    model.add(LSTM(num_in * 4))

    # 再次添加一个 Dropout 层,同样是为了防止过拟合
    model.add(Dropout(0.2))
    #

    # 向模型中添加一个全连接层(Dense 层)
    # num_out 表示该层的神经元数量,也就是模型的输出维度,对应分类任务中的类别数量
    # activation='softmax' 表示使用 softmax 激活函数,softmax 函数将输出转换为概率分布,使得所有输出值的和为 1,常用于多分类问题
    model.add(Dense(num_out, activation='softmax'))
    #

    # 编译模型,为模型的训练配置损失函数、优化器和评估指标
    # loss='categorical_crossentropy' 表示使用分类交叉熵作为损失函数,它适用于多分类问题,衡量模型预测的概率分布与真实标签的概率分布之间的差异
    # optimizer='adam' 表示使用 Adam 优化器来更新模型的参数,Adam 是一种自适应学习率的优化算法,结合了 AdaGrad 和 RMSProp 的优点
    # metrics=['acc'] 表示在训练和评估过程中使用准确率(acc)作为评估指标,准确率表示模型预测正确的样本数占总样本数的比例
    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['acc'])
    #

    # 返回编译好的模型
    return model

发布者:股市刺客,转载请注明出处:https://www.95sca.cn/archives/907092
站内所有文章皆来自网络转载或读者投稿,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!

(0)
股市刺客的头像股市刺客
上一篇 1分钟前
下一篇 7秒前

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注