使用递归神经网络进行文章分类
这一次,我们将着眼于使用神经网络对发表的文章进行分类。卷积神经网络不适用于这种情况 - 主要用于图像数据。
本次练习的数据集是Keras内置的路透社数据集,其中包含来自该出版物超过46种不同类别的超过11,000篇文章。
from keras.datasets import reuters
from keras.preprocessing import sequence
import numpy as np
max_features = 20000 # number of words to consider as features
maxlen = 1000 # cut texts after this number of words (among top max_features most common words)
batch_size = 32
print('Loading data...')
(input_train, y_train), (input_test, y_test) = reuters.load_data(num_words=max_features)
print(len(input_train), 'train sequences')
print(len(input_test), 'test sequences')
print('Pad sequences (samples x time)')
input_train = sequence.pad_sequences(input_train, maxlen=maxlen)
input_test = sequence.pad_sequences(input_test, maxlen=maxlen)
print('input_train shape:', input_train.shape)
print('input_test shape:', input_test.shape)
num_classes = np.max(y_train) + 1
print(num_classes, 'classes')
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)
print('y_train shape:', y_train.shape)
print('y_test shape:', y_test.shape)
出于特征嵌入的目的,我们只考虑给定文章中的前1000个单词,只有前200个单词将被视为特征。随着数据的清理和准备,现在是构建初始模型的时候了。
from keras.layers import Dense, Dropout, Embedding, SimpleRNN
from keras.models import Sequential
model = Sequential()
model.add(Embedding(max_features, 128))
model.add(SimpleRNN(128, return_sequences=True))
model.add(SimpleRNN(128))
model.add(Dropout(0.5))
model.add(Dense(46, activation='sigmoid'))
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['acc'])
history = model.fit(input_train, y_train,
epochs=10,
batch_size=128,
validation_split=0.2)
首先将一个嵌入层添加到模型中。本质上,该层将每个文档的单词嵌入转换为128-element的矢量。接下来,应用两个循环神经网络层。递归神经网络是神经网络,它包含迄今计算出的“memory”,根据模型迄今为止看到多少个样本来改变计算过程。在这种情况下,每个单词将被分开处理,每次处理一个单词。这减少了需要学习的参数的数量,同时允许将上下文信息应用于权重。出于显而易见的原因,这对于语言来说非常重要,因为它不存在其他类型的问题。最后,
不幸的是,这个模型并没有表现得特别好。这与基于梯度的学习模型的共同问题:消失梯度问题有关。本质上,重复的反向传播可以导致梯度的绝对值变得非常小。这限制或直接阻止受影响的权重改变其值的能力,从而导致迭代的回报递减。
幸运的是,对于递归神经网络,我们还有其他的选择。其中一个是长短记忆层,简称LSTM。这种改进的递归神经网络层特征在于使用点积和偏置加法对递归连接进行变换。结果是一个具有“内存门”的层,它可以选择性地将过去的信息应用到当前迭代中。让我们看看性能如何提高。
from keras.layers import LSTM
model = Sequential()
model.add(Embedding(max_features, 128))
model.add(LSTM(128))
model.add(Dropout(0.5))
model.add(Dense(46, activation='sigmoid'))
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['acc'])
history = model.fit(input_train, y_train,
epochs=10,
batch_size=128,
validation_split=0.2)
在第三个epoch之后的训练集中,准确度稳步提高,在验证集上也有类似的改进。