其他分享
首页 > 其他分享> > 使用Keras处理深度学习中的二分类问题——Imdb影评分类

使用Keras处理深度学习中的二分类问题——Imdb影评分类

作者:互联网

简介


二分类问题是应用很广泛的机器学习问题,它根据输入,回答yes/no。

IMDB数据集,包含来自互联网电影数据库(IMDB)的50000条严重两极分化的评论。

数据集被分为用于训练的25000条评论和用于测试的25000条评论,训练集和测试集中都包括50%的正面评价和50%的负面评价。

IMDB数据集内置于Keras库中,它已经过预处理,单词序列的评论已经被转换为整数序列,其中每个整数代表字典中的某个单词。

下面开始。

加载数据


直接加载IMDB数据:

from keras.datasets import imdb

# 仅保留训练数据中前10000个最常出现的单词,舍弃低频单词
(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words = 10000)

train_data/test_data变量是评论组成的列表,每条评论又是单词索引组成的列表,表示的是一系列的单词。

train_labels/test_labels是0和1组成的列表,其中0表示负面,1表示正面评论。

查看数据如下:

在这里插入图片描述

为了进行测试,可以使用正面的代码把某条评论数据解码为英文单词:

# 解码评论为英文单词
word_index = imdb.get_word_index()
reverse_word_index = dict([(value, key) for (key, value) in word_index.items()])
decoded_review = ' '.join([reverse_word_index.get(i - 3, '?') for i in train_data[0]])

注意,第一行中的get_word_index()函数默认会从网络下载名称为imdb_word_index.json的文件。

该文件是一个将单词映射为整数索引的字典。

如果网络不好,经常会遇到下载失败的问题:TimeoutError: [WinError 10060] 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败

建议先行下载数据到本地,加载数据时在参数中指定路径即可:

path = r"E:\practice\tf2\imdb_moive_2_classcify\imdb_word_index.json"
word_index = imdb.get_word_index(path)

如果不指定路径,会使用默认路径,一般Linux下是~/.keras/datasets/filename,windows是C:\\用户\\用户名\\

指定绝对路径后,数据会下载在该路径下,函数在下载会先从该目录下查找文件,如果找到了有效的文件,就不再下载。

准备数据


我们不能直接将整数数据直接输入神经网络,需要先将列表转换为张量。

这里对列表进行one-hot编码,将其转换为0和1组成的向量。

代码如下:

# 将整数序列编码为二进制矩阵
import numpy as np
def vectorize_sequences(sequences, dimension = 10000):
	results = np.zeros((len(sequences), dimension))
	for i, sequence in enumerate(sequences):
		results[i, sequence] = 1.
	return results
	
x_train = vectorize_sequences(train_data) # 向量化训练数据
x_test = vectorize_sequences(test_data) # 向量化测试数据
y_train = np.asarray(train_labels).astype('float32')
y_test = np.asarray(test_labels).astype('float32')

数据现在变成了这个样子:

在这里插入图片描述

构建网络


输入数据是向量,输出数据是标量,使用带有relu激活的全连接层(Dense)的简单堆叠就能很好地处理这个问题,如Dense(16, activation = 'relu')

每个带有relu激活的Dense层都实现了下列张量运算:

output = relu(dot(W, input) + b)

16个隐藏单元对应的权重矩阵W的形状为(input_dimension, 16),与W做点积相当于将输入数据投影到16维表示空间中。

隐藏单元越多,网络越能够学习到更加复杂的表示,但网络的计算代价也会越高,而且可能会导致学到不好的模式。

对于Dense层的堆叠,需要确定两个关键架构:网络的层数、每层的隐藏单元个数。

本例中使用的网络是三层,每层使用16个隐藏单元。

构建网络代码如下:

from keras import models
from keras import layers

# 模型由两个中间层(每层16个隐藏单元)和一个输出层(输出标量)组成
model = models.Sequential()
model.add(layers.Dense(16, activation = 'relu', input_shape = (10000,)))
model.add(layers.Dense(16, activation = 'relu'))
model.add(layers.Dense(1, activation = 'sigmoid'))

# 编译模型,使用内置的优化器、损失函数
model.compile(optimizer = 'rmsprop', loss = 'binary_crossentropy', metrics = ['accuracy'])

验证结果


直接上代码:

# 验证数据
x_val = x_train[:10000]
partial_x_train = x_train[10000:]
y_val = y_train[:10000]
partial_y_train = y_train[10000:]
	
# 训练模型,每批次512条样本,共20次迭代,把训练过程中的数据保存在history
history = model.fit(partial_x_train, partial_y_train, epochs = 20, batch_size = 512, validation_data = (x_val, y_val))

训练过程如下:

在这里插入图片描述

查看训练过程中的数据:

在这里插入图片描述

下面把结果绘制成图形,来展示效果。

  1. 训练损失和验证损失
# 绘制训练损失和验证损失
import matplotlib.pyplot as plt

history_dict = history.history
loss_values = history_dict['loss']
val_loss_values = history_dict['val_loss']

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

plt.plot(epochs, loss_values, 'bo', label = 'Training loss')
plt.plot(epochs, val_loss_values, 'b', label = 'Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()

plt.show()

得到下图:

在这里插入图片描述

  1. 训练精度和验证精度
# 绘制训练精度和验证精度
plt.clf() # clear the pic
acc = history_dict['accuracy']
val_acc = history_dict['val_accuracy']

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()

结果如下图:

在这里插入图片描述

如你所见,训练损失每轮都在降低,训练精度每轮都在提升。

这正是梯度下降优化的预期结果——希望最小化的量随着每次迭代越来越小。

但验证损失和验证精度并非如此,它们好像在第4轮就达到最优值。这种现象就是过拟合。

通俗地说,模型在训练数据上的表现越来越好,但在前所未有的数据上不一定表现的也越来越好。

在第二轮之后,对训练数据的过度优化,最终学到的表示仅针对训练数据,无法泛化到训练数据集之外的数据。

防止过拟合,是深度学习中的重要议题,有多种方法可以达到这个目的,对于本例,在第3轮之后停止训练就可以做到了。

使用训练好的网络在新数据上预测结果


把训练好的网络用于实践,是一件令人激动的事情。predict方法可以帮你完成:

model.predict(x_test)

结果如下:

在这里插入图片描述

小结


本文描述了训练二分类网络的完整步骤,但并非是最佳模型。

即使是使用本例中相同的模型,仍然具有一定的改进空间,如:

参考资料

《Python深度学习》

标签:loss,plt,word,训练,Keras,分类,train,Imdb,数据
来源: https://blog.csdn.net/guotianqing/article/details/110775897