首先,在之前毫无深度学习基础的情况下,花费了近11小时(包括在火车上读了一小时代码),最终完成本次大作业。
接下来这篇文章将完整叙述一个只有linux基础的菜鸟是如何完成这项大作业任务的。
文章也不再以严谨的科技论文写作格式进行,同时代码将托管在github上,文章同时发布在CSDN上,谨以此希望更多的中国学生可以将自己的成果,在不泄密的情况下,敢于分享,让更多人受益,交流,debug系统。
1 搭环境
基于linux的很多工作,都是要配置环境的,也是最烦的地方。在没有docker帮助的情况下,有一个fresh的环境是比较舒服的,这次作业使用的电脑CPU为intel i7-4710MQ,GPU为NVDIA GTX 950M。配置一般,而且是双显卡,笔记本电脑进行深度学习的研究一个痛点是,现在大多笔记本电脑是双显卡,集成显卡肯定是不适合cuda的,所以如果用到GPU的话,还需自己设置一番,屏蔽集显之类,网上有博客参考https://blog.csdn.net/DaqianC/article/details/76647923。
笔者使用的系统是ubuntu 14.04,环境较为干净,只装了cuda7.5和另一个与看上去与深度学习系统无关的Kintinous。有一个较为fresh的环境之后,我们要开始配置相关了
(1)安装anaconda
具体细节肯定是问百度了,这里我提供我的版本作为参考,图1所示为anaconda的版本,python版本和各个组件版本,是此时的最新版本,组件的版本目测是可以向下兼容的,所以可以放心更新。Sklean版本需要0.19.1,放心更新好了。
图1 各种版本供参考
(2)安装Keras
只要一条指令就可以解决的问题,还查了半天,这里感谢一下金晟,
conda installkeras-gpu
因为我解决了双显卡的问题,这里我选择了gpu版本,也可以选择cpu版本
condainstall keras
中间貌似是碰到了一个问题,实在记不起来了,不过正常应该也不会遇到,遇到就把错误提示百度一下吧。
至此,环境是搭建好了,大约花了4h左右。
3选系统
个人感觉选择系统是比较考验内功的一环,是真正能分辨出内行和萌新的重要指标。是不是真正了解,是不是经验丰富,是不是阅读了文献,也体现于此。
LSTM是一种时间递归神经网络,它出现的原因是为了解决RNN的一个致命的缺陷。原生的RNN会遇到一个很大的问题,叫做Thevanishing gradient problem for RNNs,也就是后面时间的节点会出现老年痴呆症,也就是忘事儿,这使得RNN在很长一段时间内都没有受到关注,网络只要一深就没法训练。后来有些大牛们开始使用递归神经网络来对时间关系进行建模。而根据深度学习三大牛的阐述,LSTM网络已被证明比传统的RNNS更加有效。
适合多输入变量的神经网络模型一直让开发人员很头痛,但基于(LSTM)的循环神经网络能够几乎可以完美的解决多个输入变量的问题。基于(LSTM)的循环神经网络可以很好的利用在时间序列预测上,因为很多古典的线性方法难以适应多变量或多输入预测问题。
4电力预测
(0)数据预处理
原始数据包涵了日期date,时间hour,负载load和温度T,我们可以用这些数据构建一个预测问题,首先是将日期时间信息整合为一个日期时间,以便我们可以将其用作Pandas的索引。然后将温度信息和负载信息plot出来,如图2所示。
图2 温度和负载曲线
(1) LSTM数据准备
将数据集视为监督学习问题并对输入变量进行归一化处理。考虑到上一个时间段的温度和负载,我们将把监督学习问题作为预测当前时刻(t)的污染情况。根据过去的温度和负载,预测下一个小时的负载,并给予下一个小时的“预期”温度。可以使用series_to_supervised()函数来转换数据集。
首先,加载“ dian.csv ”数据集。接下来,所有功能都被规范化,然后将数据集转换为监督学习问题。
完整的代码清单如下:
# convertseries to supervised learning
defseries_to_supervised(data, n_in=1, n_out=1, dropnan=True):
n_vars= 1iftype(data) islistelsedata.shape[1]
df= DataFrame(data)
cols,names = list(), list()
# input sequence (t-n, ... t-1)
for i inrange(n_in, 0, -1):
cols.append(df.shift(i))
names+= [('var%d(t-%d)' % (j+1, i)) for j inrange(n_vars)]
# forecast sequence (t, t+1, ... t+n)
for i inrange(0, n_out):
cols.append(df.shift(-i))
if i == 0:
names+= [('var%d(t)' % (j+1)) for j inrange(n_vars)]
else:
names+= [('var%d(t+%d)' % (j+1, i)) for j inrange(n_vars)]
# put it all together
agg= concat(cols, axis=1)
agg.columns= names
# drop rows with NaN values
if dropnan:
agg.dropna(inplace=True)
return agg
# loaddataset
dataset =read_csv('dian.csv', header=0, index_col=0)
values =dataset.values
# integerencode direction
encoder =LabelEncoder()
#values[:,4]= encoder.fit_transform(values[:,4])
# ensureall data is float
values =values.astype('float32')
#normalize features
scaler =MinMaxScaler(feature_range=(0, 1))
scaled =scaler.fit_transform(values)
# frame assupervised learning
reframed =series_to_supervised(scaled, 1, 1)
# dropcolumns we don't want to predict
#reframed.drop(reframed.columns[[9,10,11,12,13,14,15]],axis=1, inplace=True)
print(reframed.head())
(2) 定义和拟合模型
首先,将准备好的数据集分成训练集和测试集。使用前4年11个月的数据来拟合模型,然后对剩下一个月的数据进行评估。下面将数据集分成训练集和测试集,然后将训练集和测试集分成输入和输出变量。使用了Theano的框架。
# splitinto train and test sets
values =reframed.values
n_train_hours= 365 * 24 *4 +7920+150
train =values[:n_train_hours, :]
test = values[n_train_hours:,:]
# splitinto input and outputs
train_X,train_y = train[:, :-1], train[:, -1]
test_X,test_y = test[:, :-1], test[:, -1]
# reshapeinput to be 3D [samples, timesteps, features]
train_X =train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
test_X =test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))
print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)
现在定义和拟合我们的LSTM模型。在第一个隐层中定义具有50个神经元的LSTM和用于预测污染的输出层中的1个神经元。输入形状是1个时间步长,具有8个特征。在我们的模型中使用平均绝对误差(MAE)损失函数。该模型将拟合50个批量大小为72的训练时期。最后,通过在fit()函数中设置validation_data参数来跟踪训练过程中的训练和测试失败。在运行结束时,绘制训练和测试损失。
# designnetwork
model =Sequential()
model.add(LSTM(5, input_shape=(train_X.shape[1], train_X.shape[2])))
model.add(Dense(1))
model.compile(loss='mae', optimizer='adam')
# fitnetwork
history =model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X,test_y), verbose=2, shuffle=False)
# evaluatethe model
scores =model.evaluate(test_X, test_y)
(3) 评估模型与结果预测
运行示例首先创建一个绘图,显示训练中的训练损失和测试损失:
图3 系统训练损失和测试损失
可以看到测试损失低于训练损失,该模型可能过度拟合训练数据。
随后预测最后一个月的电力负载。
图4 12月电力负载预测
模型拟合后,可以预测整个测试数据集。将预测的数据集与测试数据集相结合,并反演缩放。还可以用预期的污染数字来反演测试数据集的缩放。使用预测值和实际值,可以计算模型的误差分数。并且我们还可以计算出与变量本身相同的单位产生误差的均方根误差(RMSE)。
图5 系统RMSE
训练损失和测试损失在每个训练时期结束时打印。在运行结束时,打印测试数据集上模型的最终RMSE。可以看到,该模型实现了可观的RMSE:0.013。
5 总结
从只会linux基础的深度学习小白,变成了会搭环境、简单使用系统的小白,运行了基于keras的LSTM进行了电力预测。