大家好,我技术人Howzit,这是深度学习入门系列第十九篇,欢迎大家一起交流!
深度学习入门系列1:多层感知器概述
深度学习入门系列2:用TensorFlow构建你的第一个神经网络
深度学习入门系列3:深度学习模型的性能评价方法
深度学习入门系列4:用scikit-learn找到最好的模型
深度学习入门系列5项目实战:用深度学习识别鸢尾花种类
深度学习入门系列6项目实战:声纳回声识别
深度学习入门系列7项目实战:波士顿房屋价格回归
深度学习入门系列8:用序列化保存模型便于继续训练
深度学习入门系列9:用检查点保存训练期间最好的模型
深度学习入门系列10:从绘制记录中理解训练期间的模型行为
深度学习入门系列11:用Dropout正则减少过拟合
深度学习入门系列12:使用学习规划来提升性能
深度学习入门系列13:卷积神经网络概述
深度学习入门系列14:项目实战:基于CNN的手写数字识别
深度学习入门系列15:用图像增强改善模型性能
深度学习入门系列16:项目实战:图像中目标识别
深度学习入门系列17:项目实战:从电影评论预测情感
深度学习入门系列18:循环神经网络概述
深度学习入门系列19:基于窗口(window)的多层感知器解决时序问题
深度学习入门系列20:LSTM循环神经网络解决国际航空乘客预测问题
深度学习入门系列21:项目:用LSTM+CNN对电影评论分类
深度学习入门系列22:从猜字母游戏中理解有状态的LSTM递归神经网络
深度学习入门系列23:项目:用爱丽丝梦游仙境生成文本
时序预测很难用机器学习的来解决,在这节课,你将学习如何在Python中使用Keras深度学习库针对时序问题的开发神经网络模型。读完之后,你将了解:
- 关于国际航空乘客的单变量时序预测问题。
- 如何将时序预测问题转化为回归问题,并为之开发神经网络模型。
- 如何用时间滞差来构建时序预测问题,并为之开发神经网络模型。
让我们开始吧。
1 问题描述:时序问题预测
我们在这节课看到的问题是国际航空公司乘客预测问题。这个问题是以年和月为单位,任务是预测1000个单元中国际航空公司的乘客数量。数据从1949年1月到1960年12月,即12年,144个观察值。数据集在DataMarket网页上可以下载,文件名为international-airline-passengers.csv[需要翻墙]。下面是数据集的前几行:
"Month","International airline passengers: monthly totals in thousands. Jan 49 ? Dec 60"
"1949-01",112
"1949-02",118
"1949-03",132
"1949-04",129
"1949-05",121
我们可以通过Pandas库轻松加载这个数据集。我们对日期并不感兴趣,鉴于每个观察值都是通过一个月进行分割的。因此当我们加载这些数据时,可以将第一行进行排查在外,通过pandas.read csv() 读取数据并设置skipfooter=3。一旦加载我们就能绘制整个数据集,加载数据和绘制数据的代码如下:
from pandas import read_csv
import matplotlib.pyplot as plt
dataset = read_csv('international-airline-passengers.csv', usecols=[1],engine='python', skipfooter=3)
plt.plot(dataset)
plt.show()
你能够在图中看到有个向上的趋势,你也能够看到数据的周期性,可能对应着南半球暑假的周期。
我们将这些事情进行简化并且按原样处理数据,一般来说,较好的做法就是使用不同的数据预处理技术来调整数据的规模便于做统计。
2 多层感知器回归
我们将时序预测问题转为回归问题。也就是说,给定这个月乘客人数(1000为单位),我知道下个月的乘客人数。我们能够写个简单的函数将单列数据转成双列数据,第一列包含这个月(t)乘客人数),第二列为下个月(t+1)的人数,要预测的。在我们开始之前,先导入所需要的函数和要使用的类。
import numpy
import matplotlib.pyplot as plt
from pandas import read_csv
import math
from keras.models import Sequential
from keras.layers import Dense
# fix random seed for reproducibility
numpy.random.seed(7)
我们用上部分代码中的Pandas dataframe来加载数据集。我们从dataframe中抽取Numpy数组并转化为浮点型的数组,让其适用于神经网络的建模。
# load the dataset
dataframe = read_csv('international-airline-passengers.csv', usecols=[1], engine='python', skipfooter=3)
dataset = dataframe.values
dataset = dataset.astype('float32')
在建模数据和在训练数据估计模型训练技法后,我们需要了解模型在新的未知数据上的技法。对于一般的分类或者回归问题,我们使用K折交叉验证。对于时序数据,时序是很重要的。一个简单的方法就是,我们将有序的数据集分为训练和测试集。下面的代码计算了分离点并将数据集分为训练集和测试集,67% 用于训练我们的模型和剩下 33% 用于测试这个模型。
# split into train and test sets
train_size = int(len(dataset) * 0.67)
test_size = len(dataset) - train_size
train, test = dataset[0:train_size,:], dataset[train_size:len(dataset),:]
print(len(train), len(test))
现在我们按照上面描述的定义一个函数,为了创建一个新的数据集。这个函数有两个入参,Numpy数组格式的数据集,就是我们要转的数据集,和look_back是上一步用作为输入变量来预测下一步的数量,在这个例子中,默认为1。这个默认值将创建一个数据集,它的 X 代表给定时间(t) 的乘客人数和Y是下一个时间(t+1) 的乘客数量。它是可以配置的并且在下个部分我们将构建不同大小的数据集。
# convert an array of values into a dataset matrix
def create_dataset(dataset, look_back=1):
dataX, dataY = [], []
for i in range(len(dataset)-look_back-1):
a = dataset[i:(i+look_back), 0]
dataX.append(a)
dataY.append(dataset[i + look_back, 0])
return numpy.array(dataX), numpy.array(dataY)
让我们在数据集的前几行看下这个函数的效果,
X Y
112 118
118 132
132 129
129 121
121 135
如何你把这个数据和上面例子中列举的数据进行对比,你能够发现X=t和Y=t+1这种模式。让我们使用这个函数来预处理训练集和测试集,为建模左准备。
# reshape into X=t and Y=t+1 look_back = 1
trainX, trainY = create_dataset(train, look_back)
testX, testY = create_dataset(test, look_back)
现在我们可以将多层感知器在训练数据上拟合。我们使用了一个简单的网络,1个输入端,1层8个神经元的隐藏层和输出层。如果我们取数据集单位的错误评分平方根,那么模型就使用均方差进行拟合。我尝试了几个粗略的参数并且设置了如下的配置,但是列出来的网络绝不会被优化。
# create and fit Multilayer Perceptron
model model = Sequential()
model.add(Dense(8, input_dim=look_back, activation='relu'))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
model.fit(trainX, trainY, epochs=200, batch_size=2, verbose=2)
一旦模型拟合,我们就能在训练集和测试集上评估模型的性能。在这个点上,我们将和新的模型进行比较。
# Estimate model performance
trainScore = model.evaluate(trainX, trainY, verbose=0)
print('Train Score: %.2f MSE (%.2f RMSE)' % (trainScore, math.sqrt(trainScore)))
testScore = model.evaluate(testX, testY, verbose=0)
print('Test Score: %.2f MSE (%.2f RMSE)' % (testScore, math.sqrt(testScore)))
最后,我们使用模型来生成预测,目的是为了让训练集和测试集获得模型技法的可视化。由于数据准备的方式,我们必须转变预测以至于他们的x轴和原始数据对齐。一旦准备了,数据就会被绘制,原始数据用蓝色显示,在未知数据上的预测用红色显示,在训练集上预测的用绿色显示。
# generate predictions for training
trainPredict = model.predict(trainX)
testPredict = model.predict(testX)
# shift train predictions for plotting
trainPredictPlot = numpy.empty_like(dataset)
trainPredictPlot[:, :] = numpy.nan
trainPredictPlot[look_back:len(trainPredict)+look_back, :] = trainPredict
# shift test predictions for plotting
testPredictPlot = numpy.empty_like(dataset)
testPredictPlot[:, :] = numpy.nan
testPredictPlot[len(trainPredict)+(look_back*2)+1:len(dataset)-1, :] = testPredict
# plot baseline and predictions
plt.plot(dataset)
plt.plot(trainPredictPlot)
plt.plot(testPredictPlot)
plt.show()
我们能够看到,模型在训练集和测试集上拟合工作并不是很好。他基本预测了输出值和输入值一样。图标使得预测看起来不错,但是实际上,在预测结果的变化导致技法评分差。
# Multilayer Perceptron to Predict International Airline Passengers (t+1, given t) import math
import matplotlib.pyplot as plt
import numpy
from keras.layers import Dense
from keras.models import Sequential
from pandas import read_csv
# convert an array of values into a dataset matrix
def create_dataset(dataset, look_back=1):
dataX, dataY = [], []
for i in range(len(dataset) - look_back - 1):
a = dataset[i:(i + look_back), 0]
dataX.append(a)
dataY.append(dataset[i + look_back, 0])
return numpy.array(dataX), numpy.array(dataY)
# fix random seed for reproducibility numpy.random.seed(7)
# load the dataset
dataframe = read_csv('data/international-airline-passengers.csv', usecols=[1], engine='python', skipfooter=3)
dataset = dataframe.values
dataset = dataset.astype('float32')
# split into train and test sets train_size = int(len(dataset) * 0.67)
test_size = len(dataset) - train_size
train, test = dataset[0:train_size, :], dataset[train_size:len(dataset), :]
# reshape into X=t and Y=t+1
look_back = 1
trainX, trainY = create_dataset(train, look_back)
testX, testY = create_dataset(test, look_back)
# create and fit Multilayer Perceptron model model = Sequential()
model.add(Dense(8, input_dim=look_back, activation='relu'))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
model.fit(trainX, trainY, epochs=200, batch_size=2, verbose=2)
# Estimate model performance trainScore = model.evaluate(trainX, trainY, verbose=0)
print('Train Score: %.2f MSE (%.2f RMSE)' % (trainScore, math.sqrt(trainScore)))
testScore = model.evaluate(testX, testY, verbose=0)
print('Test Score: %.2f MSE (%.2f RMSE)' % (testScore, math.sqrt(testScore)))
# generate predictions for training trainPredict = model.predict(trainX)
testPredict = model.predict(testX)
# shift train predictions for plotting trainPredictPlot = numpy.empty_like(dataset)
trainPredictPlot[:, :] = numpy.nan
trainPredictPlot[look_back:len(trainPredict) + look_back, :] = trainPredict
# shift test predictions for plotting testPredictPlot = numpy.empty_like(dataset)
testPredictPlot[:, :] = numpy.nan
testPredictPlot[len(trainPredict) + (look_back * 2) + 1:len(dataset) - 1, :] = testPredict
# plot baseline and predictions plt.plot(dataset)
plt.plot(trainPredictPlot)
plt.plot(testPredictPlot)
plt.show()
运行上面的代码,得到下面的结果:
...
Epoch 195/200 0s - loss: 535.3075
Epoch 196/200 0s - loss: 551.2694
Epoch 197/200 0s - loss: 543.7834
Epoch 198/200 0s - loss: 538.5886
Epoch 199/200 0s - loss: 539.1434
Epoch 200/200 0s - loss: 533.8347
Train Score: 531.71 MSE (23.06 RMSE)
Test Score: 2355.06 MSE (48.53 RMSE)
取性能估计的平方根,我们能够看到,模型在训练集上评价误差在23个乘客(1000中),在测试集误差为48个乘客(1000个)。
3 使用窗口法(window)的多层感知器
我们也分析了问题以至于用最近时间多步来对下一步做预测,我们称之为窗口方法,而且窗口的大小随着问题进行调节。举个例子,给定当前时间(t),我们在序列(t+1)中预测下个时间的值,我们使用当前时间t,和前两个时间(t-1),(t-2) 来预测。当表述为回归问题时,输入变量是 t-2,t-1,t 和输出变量是t+1。
上个部分我们写的create_dataset() 函数允许我们创建这个时序问题,通过将look_back从1增加到3。数据集的样例如下:
X1 X2 X3 Y
112 118 132 129
118 132 129 121
132 129 121 135
129 121 135 148
121 135 148 148
我们重新用大的窗口运行上面的例子。我们将增加网络的容量来处理额外的信息。第一层增加到14个神经元,第二层添加了8个神经元,迭代周期增加到400。整个代码如下:
# Multilayer Perceptron to Predict International Airline Passengers (t+1, given t)
import math
import matplotlib.pyplot as plt
import numpy
from keras.layers import Dense
from keras.models import Sequential
from pandas import read_csv
# convert an array of values into a dataset matrix
def create_dataset(dataset, look_back=1):
dataX, dataY = [], []
for i in range(len(dataset) - look_back - 1):
a = dataset[i:(i + look_back), 0]
dataX.append(a)
dataY.append(dataset[i + look_back, 0])
return numpy.array(dataX), numpy.array(dataY)
# fix random seed for reproducibility
numpy.random.seed(7)
# load the dataset
dataframe = read_csv('myworkspace/translate_tutorial/data/international-airline-passengers.csv', usecols=[1], engine='python', skipfooter=3)
dataset = dataframe.values
dataset = dataset.astype('float32')
# split into train and test sets
train_size = int(len(dataset) * 0.67)
test_size = len(dataset) - train_size
train, test = dataset[0:train_size, :], dataset[train_size:len(dataset), :]
# reshape into X=t and Y=t+1
look_back = 3
trainX, trainY = create_dataset(train, look_back)
testX, testY = create_dataset(test, look_back)
# create and fit Multilayer Perceptron model
model = Sequential()
model.add(Dense(12, input_dim=look_back, activation='relu'))
model.add(Dense(8))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
model.fit(trainX, trainY, epochs=400, batch_size=2, verbose=2)
# Estimate model performance
trainScore = model.evaluate(trainX, trainY, verbose=0)
print('Train Score: %.2f MSE (%.2f RMSE)' % (trainScore, math.sqrt(trainScore)))
testScore = model.evaluate(testX, testY, verbose=0)
print('Test Score: %.2f MSE (%.2f RMSE)' % (testScore, math.sqrt(testScore)))
# generate predictions for training
trainPredict = model.predict(trainX)
testPredict = model.predict(testX)
# shift train predictions for plotting
trainPredictPlot = numpy.empty_like(dataset)
trainPredictPlot[:, :] = numpy.nan
trainPredictPlot[look_back:len(trainPredict) + look_back, :] = trainPredict
# shift test predictions for plotting
testPredictPlot = numpy.empty_like(dataset)
testPredictPlot[:, :] = numpy.nan
testPredictPlot[len(trainPredict) + (look_back * 2) + 1:len(dataset) - 1, :] = testPredict
# plot baseline and predictions
plt.plot(dataset)
plt.plot(trainPredictPlot)
plt.plot(testPredictPlot)
plt.show()
运行上面的代码得到如下结果:
...
Epoch 395/400 0s - loss: 485.3482
Epoch 396/400 0s - loss: 479.9485
Epoch 397/400 0s - loss: 497.2707
Epoch 398/400 0s - loss: 489.5670
Epoch 399/400 0s - loss: 490.8099
Epoch 400/400 0s - loss: 493.6544
Train Score: 564.03 MSE (23.75 RMSE)
Test Score: 2244.82 MSE (47.38 RMSE)
我们能够看到和上部分相比误差有所减少。窗口大小和网络结构没有做调整,这仅仅一个如何解决时序问题的展示。取性能评价的平方根,我们能够看到在训练集的平均误差为23乘客(1000个/月中),在测试机上的平均误差为47个乘客(1000个/月中)。
4 总结
在这节课中,你已经学习了如何用Keras深度学习库为时序问题开发神经网络模型。完成整个课程之后,你现在了解:
- 关于国际航空乘客预测时序数据集。
- 如何将时序系列预测问题转述为回归问题并开发相应的模型。
- 如何使用**窗口(window)**来解决时序问题并开发相应的神经网络模型。
4.1 接下里
在这节课中,你已经学习了如何能够针对时序预测问题开发简单的多层感知器模型。在下节课中,你将学习用LSTM递归神经网络来解决时序预测问题。