NLP基础教程task_1

1.IMDB数据下载

下载IMDB数据集,由tensorflow自带,这个数据集已经进行了预处理,即将影评的字词顺序作为特征,每个整数代表字典中的一个特定字词。

imdb = keras.datasets.imdb
(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)

通过 num_words=10000,保留训练数据中出现频次在前10000为的字词。

2.数据探索

这个数据集每个样本都是一个整数数组,表示影评中的字词。每个标签都是整数值 0 或 1,其中 0 表示负面影评,1 表示正面影评。

print("lenth of training entries: {}, labels: {}".format(len(train_data), len(train_labels)))

Training entries: 25000, labels: 25000

再查看一下train_data的大致数据结构:

print(train_data[0])

[1, 14, 22, 16, 43, 530, 973, 1622, 1385, …],这里每一个数字都代表了字典中的字词,按照这样的顺序连接,这也说明了可以将数字转换为字词。

3.将整数转换为字词

有时候我们需要将整数再次转换为字词,可以更清晰地理解数据。

word_index = imdb.get_word_index()
word_index = {k:(v+3) for k,v in word_index.items()}
word_index['<PAD>'] = 0
word_index['<START>'] = 1
word_index['<UNK>'] = 2  #Unknow
word_index['<UNUSED>'] = 3

reverse_word_index = dict([(value, key) for (key, value) in word_index.items()])

def decode_review(text):
    return ' '.join([reverse_word_index.get(i, '?') for i in text])
decode_review(train_data[0])

4.数据准备

因为这个数据集中,每个文本分割成字词后长度并不一致,但是我们知道机器学习中,所学习的矩阵index与columns必须长度一致,因此可以采取两种方式进行处理。

one-hot

对数组进行独热编码,将它们转换为由 0 和 1 构成的向量。例如,序列 [3, 5] 将变成一个 10000 维的向量,除索引 3 和 5 转换为 1 之外,其余全转换为 0。然后,将它作为网络的第一层,一个可以处理浮点向量数据的密集层。不过,这种方法会占用大量内存,需要一个大小为 num_words * num_reviews 的矩阵。

数组填充

可以填充数组,使它们都具有相同的长度,然后创建一个形状为 max_length * num_reviews 的整数张量。我们可以使用一个能够处理这种形状的嵌入层作为网络中的第一层。通过下面代码可以将数据填充至一样长度(256)。

train_data = keras.preprocessing.sequence.pad_sequences(train_data,
                                                       value=word_index['<PAD>'],
                                                       padding='post', 
                                                       maxlen=256)
test_data = keras.preprocessing.sequence.pad_sequences(test_data,
                                                       value=word_index['<PAD>'],
                                                       padding='post', 
                                                       maxlen=256)

5.模型构建

神经网络模型分为输入层,隐藏层以及输出层,如何对这三者合理安排参数是关键。下面代码给出一个简单的解答。

vocab_size = 10000

model = keras.Sequential()
model.add(keras.layers.Embedding(vocab_size, 16))  
model.add(keras.layers.GlobalAveragePooling1D())
model.add(keras.layers.Dense(16, activation=tf.nn.relu))
model.add(keras.layers.Dense(1, activation=tf.nn.sigmoid))

model.summary()
Model: "sequential_3"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_3 (Embedding)      (None, None, 16)          160000    
_________________________________________________________________
global_average_pooling1d_3 ( (None, 16)                0         
_________________________________________________________________
dense_6 (Dense)              (None, 16)                272       
_________________________________________________________________
dense_7 (Dense)              (None, 1)                 17        
=================================================================
Total params: 160,289
Trainable params: 160,289
Non-trainable params: 0
_________________________________________________________________

按顺序堆叠各个层以构建分类器:
(1)第一层是 Embedding 层。该层会在整数编码的词汇表中查找每个字词-索引的嵌入向量。模型在接受训练时会学习这些向量。这些向量会向输出数组添加一个维度。生成的维度为:(batch, sequence, embedding)。
(2)接下来,一个 GlobalAveragePooling1D 层通过对序列维度求平均值,针对每个样本返回一个长度固定的输出向量。这样,模型便能够以尽可能简单的方式处理各种长度的输入。
(3)该长度固定的输出向量会传入一个全连接 (Dense) 层(包含 16 个隐藏单元)。relu激活函数
(4)最后一层与单个输出节点密集连接。应用 sigmoid 激活函数后,结果是介于 0 到 1 之间的浮点值,表示概率或置信水平。

隐藏层:
如果模型具有更多隐藏单元(更高维度的表示空间)和/或更多层,则说明网络可以学习更复杂的表示法。不过,这会使网络耗费更多计算资源,甚至会造成过拟合。

损失函数和优化器:
这是一个二元分类问题,因此我们采用binary_crossentropy损失函数,至于为什么不采用MSE等损失函数,简单来说就是如果采用MSE或者RMSE,会产生梯度消失,这里不再赘述。
现在,配置模型以使用优化器和损失函数:

model.compile(optimizer=tf.train.AdamOptimizer(),
             loss='binary_crossentropy',
             metrics=['accuracy'])

6.数据创建及建模

首先构建训练集与验证集:

x_val = train_data[:10000]
partial_x_train = train_data[10000:]

y_val = train_labels[:10000]
partial_y_train = train_labels[10000:]

模型训练

用有 512 个样本的小批次训练模型 40 个周期。这将对 x_train 和 y_train 张量中的所有样本进行 40 次迭代。在训练期间,监控模型在验证集的 10000 个样本上的损失和准确率:

history = model.fit(partial_x_train, 
                   partial_y_train, 
                   epochs=40,
                   batch_size=512,
                   validation_data=(x_val, y_val),
                   verbose=1)
Train on 15000 samples, validate on 10000 samples
Epoch 1/40
15000/15000 [==============================] - 1s 58us/sample - loss: 0.6913 - acc: 0.5911 - val_loss: 0.6888 - val_acc: 0.7350
Epoch 2/40
15000/15000 [==============================] - 1s 49us/sample - loss: 0.6841 - acc: 0.7569 - val_loss: 0.6792 - val_acc: 0.7411
Epoch 3/40
15000/15000 [==============================] - 1s 50us/sample - loss: 0.6691 - acc: 0.7697 - val_loss: 0.6605 - val_acc: 0.7623
Epoch 4/40
15000/15000 [==============================] - 1s 52us/sample - loss: 0.6431 - acc: 0.7839 - val_loss: 0.6317 - val_acc: 0.7723
Epoch 5/40
15000/15000 [==============================] - 1s 50us/sample - loss: 0.6058 - acc: 0.7999 - val_loss: 0.5930 - val_acc: 0.7887
Epoch 6/40
15000/15000 [==============================] - 1s 52us/sample - loss: 0.5587 - acc: 0.8172 - val_loss: 0.5475 - val_acc: 0.8090
Epoch 7/40
15000/15000 [==============================] - 1s 52us/sample - loss: 0.5083 - acc: 0.8378 - val_loss: 0.5021 - val_acc: 0.8251
Epoch 8/40
15000/15000 [==============================] - 1s 49us/sample - loss: 0.4592 - acc: 0.8532 - val_loss: 0.4604 - val_acc: 0.8385
Epoch 9/40
15000/15000 [==============================] - 1s 49us/sample - loss: 0.4154 - acc: 0.8682 - val_loss: 0.4258 - val_acc: 0.8450
Epoch 10/40
15000/15000 [==============================] - 1s 51us/sample - loss: 0.3779 - acc: 0.8782 - val_loss: 0.3960 - val_acc: 0.8556
Epoch 11/40
15000/15000 [==============================] - 1s 49us/sample - loss: 0.3471 - acc: 0.8865 - val_loss: 0.3737 - val_acc: 0.8594
Epoch 12/40
15000/15000 [==============================] - 1s 49us/sample - loss: 0.3212 - acc: 0.8931 - val_loss: 0.3555 - val_acc: 0.8659
Epoch 13/40
15000/15000 [==============================] - 1s 54us/sample - loss: 0.2989 - acc: 0.8998 - val_loss: 0.3415 - val_acc: 0.8705
Epoch 14/40
15000/15000 [==============================] - 1s 51us/sample - loss: 0.2802 - acc: 0.9051 - val_loss: 0.3291 - val_acc: 0.8753
Epoch 15/40
15000/15000 [==============================] - 1s 50us/sample - loss: 0.2634 - acc: 0.9103 - val_loss: 0.3193 - val_acc: 0.8778
Epoch 16/40
15000/15000 [==============================] - 1s 51us/sample - loss: 0.2487 - acc: 0.9153 - val_loss: 0.3118 - val_acc: 0.8804
Epoch 17/40
15000/15000 [==============================] - 1s 49us/sample - loss: 0.2355 - acc: 0.9211 - val_loss: 0.3060 - val_acc: 0.8801
Epoch 18/40
15000/15000 [==============================] - 1s 49us/sample - loss: 0.2236 - acc: 0.9234 - val_loss: 0.3016 - val_acc: 0.8804
Epoch 19/40
15000/15000 [==============================] - 1s 49us/sample - loss: 0.2125 - acc: 0.9271 - val_loss: 0.2963 - val_acc: 0.8831
Epoch 20/40
15000/15000 [==============================] - 1s 54us/sample - loss: 0.2024 - acc: 0.9305 - val_loss: 0.2931 - val_acc: 0.8836
Epoch 21/40
15000/15000 [==============================] - 1s 51us/sample - loss: 0.1932 - acc: 0.9349 - val_loss: 0.2903 - val_acc: 0.8848
Epoch 22/40
15000/15000 [==============================] - 1s 49us/sample - loss: 0.1842 - acc: 0.9393 - val_loss: 0.2886 - val_acc: 0.8850
Epoch 23/40
15000/15000 [==============================] - 1s 49us/sample - loss: 0.1761 - acc: 0.9429 - val_loss: 0.2871 - val_acc: 0.8854
Epoch 24/40
15000/15000 [==============================] - 1s 49us/sample - loss: 0.1684 - acc: 0.9465 - val_loss: 0.2885 - val_acc: 0.8818
Epoch 25/40
15000/15000 [==============================] - 1s 49us/sample - loss: 0.1617 - acc: 0.9493 - val_loss: 0.2858 - val_acc: 0.8859
Epoch 26/40
15000/15000 [==============================] - 1s 49us/sample - loss: 0.1547 - acc: 0.9530 - val_loss: 0.2856 - val_acc: 0.8864
Epoch 27/40
15000/15000 [==============================] - 1s 51us/sample - loss: 0.1481 - acc: 0.9555 - val_loss: 0.2865 - val_acc: 0.8862
Epoch 28/40
15000/15000 [==============================] - 1s 49us/sample - loss: 0.1422 - acc: 0.9573 - val_loss: 0.2884 - val_acc: 0.8859
Epoch 29/40
15000/15000 [==============================] - 1s 50us/sample - loss: 0.1361 - acc: 0.9601 - val_loss: 0.2879 - val_acc: 0.8863
Epoch 30/40
15000/15000 [==============================] - 1s 49us/sample - loss: 0.1305 - acc: 0.9626 - val_loss: 0.2895 - val_acc: 0.8865
Epoch 31/40
15000/15000 [==============================] - 1s 49us/sample - loss: 0.1253 - acc: 0.9647 - val_loss: 0.2909 - val_acc: 0.8863
Epoch 32/40
15000/15000 [==============================] - 1s 50us/sample - loss: 0.1204 - acc: 0.9666 - val_loss: 0.2933 - val_acc: 0.8863
Epoch 33/40
15000/15000 [==============================] - 1s 52us/sample - loss: 0.1157 - acc: 0.9677 - val_loss: 0.2954 - val_acc: 0.8852
Epoch 34/40
15000/15000 [==============================] - 1s 53us/sample - loss: 0.1113 - acc: 0.9700 - val_loss: 0.2973 - val_acc: 0.8854
Epoch 35/40
15000/15000 [==============================] - 1s 49us/sample - loss: 0.1065 - acc: 0.9715 - val_loss: 0.3012 - val_acc: 0.8836
Epoch 36/40
15000/15000 [==============================] - 1s 50us/sample - loss: 0.1024 - acc: 0.9728 - val_loss: 0.3028 - val_acc: 0.8837
Epoch 37/40
15000/15000 [==============================] - 1s 49us/sample - loss: 0.0985 - acc: 0.9735 - val_loss: 0.3057 - val_acc: 0.8838
Epoch 38/40
15000/15000 [==============================] - 1s 49us/sample - loss: 0.0948 - acc: 0.9753 - val_loss: 0.3092 - val_acc: 0.8827
Epoch 39/40
15000/15000 [==============================] - 1s 51us/sample - loss: 0.0909 - acc: 0.9769 - val_loss: 0.3134 - val_acc: 0.8816
Epoch 40/40
15000/15000 [==============================] - 1s 50us/sample - loss: 0.0874 - acc: 0.9784 - val_loss: 0.3163 - val_acc: 0.8809

评估模型

看看模型的表现如何。模型会返回两个值:损失(表示误差的数字,越低越好)和准确率。

results = model.evaluate(test_data, test_labels)
print(results)
25000/25000 [==============================] - 0s 15us/sample - loss: 0.3372 - acc: 0.8711
[0.3372363602924347, 0.87112]

使用这种相当简单的方法可实现约 87% 的准确率。

创建准确率和损失随时间变化的图

model.fit() 返回一个 History 对象,该对象包含一个字典,其中包括训练期间发生的所有情况:

history_dict = history.history
history_dict.keys()
dict_keys(['loss', 'val_loss', 'val_acc', 'acc'])

一共有 4 个条目:每个条目对应训练和验证期间的一个受监控指标。我们可以使用这些指标绘制训练损失与验证损失图表以进行对比,并绘制训练准确率与验证准确率图表。

import matplotlib.pyplot as plt

acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(1, len(acc) + 1)

# "bo" is for "blue dot"
plt.plot(epochs, loss, 'bo', label='Training loss')
# b is for "solid blue line"
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()

plt.show()

在这里插入图片描述

plt.clf()   # clear figure
acc_values = history_dict['acc']
val_acc_values = history_dict['val_acc']

plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()

plt.show()

在这里插入图片描述
在该图表中,圆点表示训练损失和准确率,实线表示验证损失和准确率。
可以注意到,在20个周期之后,训练集的误差一直在减小,精确度一直在提高,而验证集却表现平平,几乎不再变化,这也说明,模型复杂度不断提高,模型会过度优化训练集,而无法拟合到测试集的数据。因此可以将训练次数限定在20次,防止出现过拟合。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值