这一节我们将使用Keras构建一个用于分析情感极性的神经网络模型,我们使用的是IMDB数据集,其中包含了50000条严重两极分化的评论。我们将从数据的准备开始,一步一步地讨论深度学习的实践方法论。
数据准备
Keras内置了下载IMDB数据的接口,但由于网络权限的原因,我们采用浏览器事先从网络上下载IMDB数据,把它放到我们的工程的corpus目录下,并在调用接口时指定加载数据的路径(注意一定要使用绝对路径)。该接口直接以元组的形式返回了(训练数据, 对应标签)以及(测试数据, 对应标签)。
1 | from keras.datasets import imdb |
参数num_words=10000表示仅保留训练数据中前10000个常出现的单词,较低频的词将被舍弃掉。
1 | print(train_data[0], train_labels[0]) |
我们分别输出一条训练数据与对应的标签,可以看出每条评论被表示为单词的索引编号的序列,而标签对应于0/1的整数表示负面(negative)与正面(positive)。显然,用单词索引编号序列表示的每条评论数据是不等长的,并不能用作神经网络的输入,我们需要将其转换为张量。一种最简单的张量转换方法就是one-hot编码,这种方法把每一条评论对应为一个词汇表大小的向量,出现过单词多对应的位置被置为1,其他位置为0。
1 | import numpy as np |
当然,对应的标签也应该向量化作为神经网络的目标值,只需要将它们转换为Numpy数组就行:
1 | y_train = np.asarray(train_labels).astype('float32') |
至此,我们完成了数据的准备工作,受益于使用了Keras的内置函数,我们省去了自行对数据进行训练集与测试集的划分。对于输入神经网络的数据,我们需要将它们都向量化。
构建网络
我们设计这样一个网络,它包含两个中间层,每一层都有16个隐藏单元;第三层输出一个标量,预测当前评论的情感,这个值在0~1的范围内,越接近0表示负向极性,越接近1表示正向极性。
1 | from keras import models |
一个隐藏单元是对应的层所拥有的表示空间的一个维度,我们设计的中间层相当于做了这样一个运算:
output = relu(dot(W, input) + b)
其中W是一个形状为(input_dimension, 16)的权重矩阵,与W做点积相当于将输入数据投影到一个16维的表示空间中,再加上一个偏置变量b,为了让变换后的表示空间具有更多样性,把点积与相加后的线性变化结果输入relu激活函数进行一定的非线性变换。
然后,我们选择二元交叉熵损失函数与RMSprop优化器来配置模型,并且监控精度。
1 | model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['accuracy']) |
验证方法
为了在训练过程中监控模型在前所未见的数据上的精度,我们需要从训练数据中拨出一部分样本作为验证集,我们简单地选择前10000条。
1 | x_val = x_train[:10000] |
现在可以开始训练了,我们让512个样本组成一个小批量,将模型训练20个轮次。
1 | history = model.fit(partial_x_train, partial_y_train, |
20次的迭代很快就完成了,fit()函数执行后返回一个History对象,该对象有一个history成员,它是一个字典,包含了训练过程中的相关数据。
1 | print(history.history.keys()) |
我们使用Matplotlib在同一张图上绘制训练损失与验证过程中监控的指标,从图上直观地观察模型的表现。首先,绘制训练损失与验证损失:
1 | import matplotlib.pyplot as plt |
接着,我们再来绘制训练精度与验证精度:
1 | plt.clf() |
图中反应训练数据的折线走势与我们的预期是一致的,训练损失每轮都在降低,训练精度每轮都在提升;但是,验证数据的折线并不是这样,验证损失和验证精度似乎在第四轮达到了最佳值。也就是说,我们的训练过程从第五轮后就出现了过拟合:模型在训练数据上的表现越来越好,但在前所未见的数据上并没有这样的表现。为了避免过拟合,我们把模型训练的轮数设置为4,从头重新训练这个网络,并在测试集上进行评估。
完整代码
1 | import numpy as np |
很激动吧,我们仅仅用了不到三十行代码就到达了87%的精度,如果我们换用更复杂的模型,会有更好的结果。
总结
我们把这个实例的实践步骤总结一下,可以作为我们进行深度学习建模的方法论,按部就班地开展相关的实验与工程:
- 数据处理:划分训练集与测试集,把数据转换为适合输入神经网络的张量形式
- 构建网络:按照业务的具体需求,选择合适的网络结构、损失函数与优化器,构建一个完整的网络模型
- 验证方法:从训练集中拨出一部分数据作为验证集,将训练集与验证集同时放入fit()函数,指定相关的观测值,用训练记录绘制相关指标在训练集与验证集上的表现图
- 调整模型:根据表现图调整模型的超参数(如:迭代轮数、网络复杂度)或设计一定的正则化策略
- 固化系统:把性能最好的网络结构、参数用来训练最终的模型,固化为系统,并用测试集进行评测