有监督的机器学习从数学角度看就是在拟合一个从特征空间到目标空间的映射,机器学习过程就是寻找或逼近这个映射。下面用循环神经网路来拟合上证指数,看一下循环神经网络的学习能力。
我们要拟合的映射关系是前n天的交易数据对应之后第m天后的收盘价,其中交易数据包括:收盘价 最高价、 最低价、 开盘价、 前收盘、 涨跌额、 涨跌幅、 成交量、 成交金额。n天的记录组成一个(n,9)的时间序列。
上证指数交易数据从网易下载,包含从第一天(1990-12-19)到2018-12-27的数据,下载后文件名为000001.csv。其中有些记录中包含None,需要删除掉这样的记录,然后按时间顺序排列。处理方式如下:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import keras
from keras.models import Sequential
from keras.layers import Dense,Dropout,LSTM
data = pd.read_csv('d:/downloads/000001.csv',encoding='gbk')
data = data[(data['涨跌额']!='None') & (data['成交金额']!='None')]
data.sort_values(by='日期',ascending=True,inplace=True)
data.head()
输出为
日期 股票代码 名称 收盘价 最高价 最低价 开盘价 前收盘 涨跌额 涨跌幅 成交量 成交金额
6853 1990-12-20 '000001 上证指数 104.39 104.39 99.98 104.30 99.98 4.41 4.4109 197 84000.0
6852 1990-12-21 '000001 上证指数 109.13 109.13 103.73 109.07 104.39 4.74 4.5407 28 16000.0
6851 1990-12-24 '000001 上证指数 114.55 114.55 109.13 113.57 109.13 5.42 4.9666 32 31000.0
6850 1990-12-25 '000001 上证指数 120.25 120.25 114.55 120.09 114.55 5.7 4.976 15 6000.0
6849 1990-12-26 '000001 上证指数 125.27 125.27 120.25 125.27 120.25 5.02 4.1746 100 53000.0
注意,日期前的数字为索引,因为重新排序了,索引从大到小显示。特征只取从收盘价到成交金额的9个字段,并将类型设为float32
x = data.values[:,3:]
x = x.astype('float32')
把收盘价用曲线显示一下
plt.plot(x[:,0])
plt.show()

设置训练集大小为6500,并用训练集的均值和标准差对全部数据进行标准化处理。
train_size = 6500
tr_mean = np.mean(x[0:train_size],axis=0)
tr_std = np.std(x[0:train_size],axis=0)
x-=tr_mean
x/=tr_std
定义一个函数来生成前lookback天的交易记录和第delay天后的收盘价的映射关系。
def generate_timestep_data(x,lookback=10,delay=3,step=1):
seq_ls = []
target_ls = []
for i in range(0,x.shape[0]-lookback-delay+1,step):
seq_ls.append(x[i:i+lookback])
target_ls.append(x[i+lookback+delay-1,0])
x_seq = np.asarray(seq_ls)
y = np.asarray(target_ls)
return x_seq,y
step是两个时间序列之间的隔天数,这里取1。
在训练集和测试集上调用这个函数,生成循环神经网络需要的数据映射关系。这里生成的映射是前10天交易记录对应之后第3天的收盘价。
x_train,y_train = generate_timestep_data(x[0:train_size],10,3,1)
x_test,y_test = generate_timestep_data(x[train_size:],10,3,1)
用keras的LSTM建立一个学习模型,并在训练集上进行训练,验证集取训练集的10%。
model = Sequential()
model.add(LSTM(128,input_shape=(x_train.shape[1:]),activation='tanh',kernel_regularizer='l2'))
#model.add(Dropout(0.5))
model.add(Dense(1))
model.summary()
model.compile(loss='mse',optimizer='adam',metrics=['mae'])
history=model.fit(x_train,y_train,validation_split=0.1,epochs=10,batch_size=64)
plt.plot(history.history['loss'],label='loss')
plt.plot(history.history['val_loss'],label='val_loss')
plt.legend()
损失函数随训练次数的变化如下:

用训练好的模型在测试集上进行预测,并与真实值进行比较。
y_pred = model.predict(x_test)
y_pred = y_pred*tr_std[0]+tr_mean[0] #恢复到原有尺度数据
y_true = y_test*tr_std[0]+tr_mean[0] #恢复到原有尺度数据
plt.plot(y_true[:],label='true')
plt.plot(y_pred[:],label='pred')
plt.legend()

从对比情况可以看出,循环神经网络模型能够学到事先定义的映射关系,并且具有较好的泛化能力。
但这不表示可以用这个模型来预测上证指数走势,因为决定其走势的不是前几天的交易数据。这里只是说明循环神经网络模型对于时间序列具有的拟合能力。
网友评论