根据尹成大佬的视频写的,并参考了其他博主介绍,代码注释加了一些自己遇到的问题,写的很乱,也不是特别完整,但是能运行。
可以参考:keras深度学习预测比特币走势
数据处理
标准化数据,自己理解一下
*数据的标准化(normalization)是将数据按比例缩放,使之落入一个小的特定区间。在某些比较和评价的指标处理中经常会用到,去除数据的单位限制,将其转化为无量纲的纯数值,便于不同单位或量级的指标能够进行比较和加权。
###规范化数据
def z_score(series):
result = (series - series.mean())/series.std(ddof = 0) #数列每个值减去 数列平均值 再除以数列的平均方差
return result
def point_relative_normalization(series): #数列每个值除以数列第一个数,再减去1, 这样第一个数就是0,从零开始
result = (series/series.values[0])-1
return result
def maximum_and_minimum_normalization(series, boundary=(0,1)): #最大最小规范化
range_min, range_max = boundary
standard_deviation = (series-series.min(axis=0))/(series.max(axis = 0)) #
result = standard_deviation*(range_max - range_min)+range_min
return result
数据集:bitcoin_historical_prices.csv
数据分割
import normalizations #自己定义的模块,用于对数据进行标准化
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
bitcoin = pd.read_csv('bitcoin_historical_prices.csv') #close列数据可能是货币格式,在表格中修改为数值格式
#print(bitcoin) #打印csv数据
bitcoin.set_index('date') #把csv中的'date'列作为标签,
# bitcoin.set_index('date')['close'].plot() #以‘date’为标签,绘制‘close’的数据 ,就是闭市的价格。.plot()是pandas里的函数
# bitcoin[bitcoin['date'] >= '2020-05-01'].set_index('date')['close'].plot() #截取不同时间段
# plt.show()
# # print(bitcoin.head())
bitcoin_recent = bitcoin[bitcoin['date'] >= '2017-12-31'] #,2019-1-1与2019-01-01的大小比较存在问题,换成01-01解决,如果csv无法处理,可以尝试xlsx
bitcoin_recent = bitcoin_recent[['date','iso_week','close','volume']] #提取csv中的四列数据
# .groupby分类,按照周分类,
# apply 对前面得到的数据执行函数,就是把每周的组内数据,进行处理,每周都是从零开始变化
# x:normalizations是对数据进行标准化
# 数据处理结果是每周内的数据波动情况,第一天为0,其余六天都在(0-1)之间变化
bitcoin_recent['close_point_relative_normalization'] = bitcoin_recent.groupby('iso_week')['close'].apply(
lambda x:normalizations.point_relative_normalization(x)
)
bitcoin_recent.set_index('date')['close_point_relative_normalization'].plot() # 标准化之后的数据
plt.show()
bd = int(0.8*bitcoin_recent['iso_week'].nunique()) #nunique iso_week种类数量,一共多少周,提取80%作为训练的数量
train_week_set = bitcoin_recent['iso_week'].unique()[:bd] # unique 返回作为训练数据的周,具体训练的数据在现在
# test_week_set = bitcoin_recent['iso_week'].unique()[bd:]
test_week_set = bitcoin_recent[~bitcoin_recent['iso_week'].isin(train_week_set)]['iso_week'].unique() #两条语句一样作用,测试的周,就是不在训练周的集合里。
print('\n****************train_data',train_week_set)
print('\n****************test_data',test_week_set)
train_data = bitcoin_recent[bitcoin_recent['iso_week'].isin(train_week_set)] #提取训练周的数据
test_data = bitcoin_recent[bitcoin_recent['iso_week'].isin(test_week_set)] #提取测似周的数据
bitcoin_recent.to_csv('E:\anzhuang\tu\list\bitcoin\bitcoin_recent.csv',index=False) #保存时,iso_week 2020-2,2020年第2周会自动变成日期,导致数据混乱,可以用下划线‘_’代替,或者用xlsx文件。
train_data.to_csv('E:\anzhuang\tu\list\bitcoin\train_data.csv',index=False)
test_data.to_csv('E:\anzhuang\tu\list\bitcoin\test_data.csv',index=False)
模型预测
from keras.models import Sequential, load_model
from keras.layers import Dense,LSTM,Activation
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
period_length = 7 # 周期长度,7天
number_of_period = 178 #根据自己的数据查看,一共有多少周,减去1 就是周期数
#建立模型
def creat_model():
model = Sequential()
model.add(LSTM(units=period_length,batch_input_shape=(1,number_of_period, period_length),
# input_shape=(number_of_period,period_length), #感觉去掉后没什么影响
return_sequences=False,
stateful= False
))
model.add(Dense(
units=period_length
))
model.add(Activation('linear'))
model.compile(loss='mse',optimizer='rmsprop') #rmsprop
return model
def creat_data(data, period=7): #7天一个周期,
last = list()
# print(len(data))
for i in range(0,len(data),7):
lastset = list(data[i:i+period]) #七天的数据,作为一组, 放入last中
if len(lastset) == period: #判断一组数据是不是满足7个,最后可能不足7个一组
last.append(np.array(lastset).reshape(1,period).tolist() ) #转变成array后再reshape,7天的数据作为一组训练数据,再转为list,list不断增加。
return np.array(last) #输出一个array数据,注意缩进
if __name__=='__main__':
train = pd.read_csv('bitcoin_recent.csv')
#模型是根据close_point_relative_normalization训练的,模型预测的也是标准化数据变化趋势。
#由于闭市价格变化趋势与标准化后的数据变化趋势一样,最后预测价格就是 根据上一周价格乘以变化趋势得到预测的价格
data = creat_data(train['close_point_relative_normalization'].values)
# x_train = data[:-1,:] #行数据从头到最后一个之前,所有列
y_validation = data[-1] #最后一个数据
print(data.shape)
# print(x_train.shape)
X_train = data[:-1, :].reshape(1, 178, 7) #一个179周,减1,每个周期7个数据
y_validation = data[-1].reshape (1,7) #最后一个周期
model = creat_model()
histiry = model.fit(x=X_train,y=y_validation,epochs = 10,batch_size=32)
pd.DataFrame(histiry.history['loss']).plot() #输出训练过程的loss误差变化情况
plt.show()
def denormalize(series, last_value):
result = last_value * (series + 1) #预测,上一周的价格,标准化数据的变化趋势与闭市价格变化趋势一样,所以直接相乘得到预测的后一周价格
return result
predictions = model.predict(x=X_train)[0] #
last_weeks_value = train[train['date'] == train['date'].max()]['close'].values[0]# 上一周闭市价格
denormalized_prediction = denormalize(predictions, last_weeks_value)
train = train.set_index('date',drop=False)
pd.DataFrame(denormalized_prediction).plot(linewidth=2, figsize=(6, 4), color='#d35400', grid=True)
full = list(train['close'].values) + list(denormalized_prediction)
pd.DataFrame(full[-7*50:]).plot(linewidth = 2,figsize=(14,4),color = '#d35400', grid =True)
# pd.DataFrame(full).plot(linewidth=2, figsize=(14, 4), color='#d35400', grid=True)
plt.axvline(len(full[-7*50:])-7) #从后面开始第7*50个数据
plt.show()
训练过程loss变化趋势
预测趋势