Path: blob/master/site/zh-cn/hub/tutorials/tf2_text_classification.ipynb
25118 views
Copyright 2019 The TensorFlow Hub Authors.
Licensed under the Apache License, Version 2.0 (the "License");
电影评论文本分类
此笔记本利用评论文本将电影评论分类为正面或负面评价。这是一个二元(或二类)分类示例,也是一个重要且应用广泛的机器学习问题。
我们将使用包含 Internet Movie Database 中的 50,000 条电影评论文本的 IMDB 数据集。先将这些评论分为两组,其中 25,000 条用于训练,另外 25,000 条用于测试。训练组和测试组是均衡的,也就是说其中包含相等数量的正面评价和负面评价。
此笔记本在 TensorFlow 和 TensorFlow Hub(一个用于迁移学习的库和平台)中使用高级 API tf.keras 来构建和训练模型。有关使用 tf.keras
的更高级文本分类教程,请参阅 MLCC 文本分类指南。
更多模型
这里可以找到更具表现力或性能的模型,您可以使用这些模型来生成文本嵌入向量。
安装
下载 IMDB 数据集
TensorFlow 数据集上提供了 IMDB 数据集。以下代码可将 IMDB 数据集下载到您的计算机(或 Colab 运行时)上:
探索数据
我们花一点时间来了解数据的格式。每个样本都是一个代表电影评论的句子和一个相应的标签。句子未经过任何预处理。标签是一个整数值(0 或 1),其中 0 表示负面评价,1 表示正面评价。
我们打印前 10 个样本。
我们再打印前 10 个标签。
构建模型
神经网络是通过堆叠层创建的,这需要确定三个主要架构决策:
如何表示文本?
在模型中使用多少个层?
为每个层使用多少个隐藏神经元?
在本例中,输入数据由句子组成。要预测的标签要么是 0,要么是 1。
表示文本的一种方法是将句子转换为嵌入向量。我们可以将预训练的文本嵌入向量作为第一层,这有两个优势:
不必担心文本预处理。
可以从迁移学习获益。
对于本示例,我们将使用 TensorFlow Hub 中名为 google/nnlm-en-dim50/2 的模型。
为了学习本教程,还要测试另外两个模型:
google/nnlm-en-dim50-with-normalization/2 - 与 google/nnlm-en-dim50/2 相同,但进行了更多文本标准化以移除标点。这样有助于更好地覆盖您的输入文本上词例的词汇内嵌入向量。
google/nnlm-en-dim128-with-normalization/2 - 更大的模型,嵌入向量维度为 128,而不是 50。
我们先创建一个使用 TensorFlow Hub 模型嵌入语句的 Keras 层,并使用几个输入样本试试效果。请注意,产生的嵌入向量的输出形状是预期的:(num_examples, embedding_dimension)
。
现在构建整个模型:
按顺序堆叠层以构建分类器:
第一层是 TensorFlow Hub 层。该层使用预训练的 SaveModel 将句子映射到其嵌入向量。我们使用的模型 (google/nnlm-en-dim50/2) 可将句子拆分为词例,嵌入每个词例,然后组合嵌入向量。生成的维度是:
(num_examples, embedding_dimension)
。此定长输出向量通过一个有 16 个隐藏单元的全连接 (
Dense
) 层传输。最后一层与单个输出节点密集连接。这会输出 logits:真类的对数几率(根据模型而定)。
隐藏神经元
上述模型在输入和输出之间有两个中间(或称“隐藏”)层。输出(单元、节点或神经元)的数量是层的表示空间的维度。换言之,即网络学习内部表示时允许的自由度。
模型的隐藏单元越多(更高维度的表示空间)和/或层越多,则网络可以学习的表示越复杂。但是,这会导致网络的计算开销增加,并且可能导致学习不需要的模式——提高在训练数据(而不是测试数据)上的性能的模式。这就叫过拟合,我们稍后将进行探讨。
损失函数和优化器
模型训练需要一个损失函数和一个优化器。由于这是二元分类问题,并且模型输出概率(具有 Sigmoid 激活的单一单元层),我们将使用 binary_crossentropy
损失函数。
这并非损失函数的唯一选择,比如,您还可以选择 mean_squared_error
。但是,一般来说,binary_crossentropy
更适合处理概率问题,它可以测量概率分布之间的“距离”,或者在我们的用例中,是指真实分布与预测值之间的差距。
稍后我们研究回归问题时(比如说,预测一套房子的价格),我们将看到如何使用另一个称为均方误差的损失函数。
现在,配置模型以使用优化器和损失函数:
创建验证集
训练时,我们希望检验该模型在未见过的数据上的准确率。为此,需要将原始训练数据中的 10,000 个样本分离出来,创建一个验证集。(为何现在不使用测试集?因为我们的目标是仅使用训练数据开发和调整模型,然后只使用一次测试数据来评估准确率)。
训练模型
使用包含 512 个样本的 mini-batch 对模型进行 40 个周期的训练,也就是在 x_train
和 y_train
张量中对所有样本进行 40 次迭代。在训练时,监测模型在验证集的 10,000 个样本上的损失和准确率:
评估模型
我们来看一下模型的性能如何。将返回两个值。损失值(一个表示误差的数字,值越低越好)与准确率。
这种相当简单的方法可以达到 87% 的准确率。对于更高级的方法,模型的准确率应该会接近 95%。
创建准确率和损失随时间变化的图表
model.fit()
会返回包含一个字典的 History
对象。该字典包含训练过程中产生的所有信息:
其中有四个条目:每个条目代表训练和验证过程中的一项监测指标。我们可以使用这些指标来绘制用于比较的训练和验证图表,以及训练和验证准确率图表:
在该图表中,虚线代表训练损失和准确率,实线代表验证损失和准确率。
请注意,训练损失会逐周期下降,而训练准确率则逐周期上升。使用梯度下降优化时,这是预期结果,它应该在每次迭代中最大限度减少所需的数量。
但是,对验证损失和准确率来说则不然——它们似乎会在经过 20 个周期后达到顶点。这是过拟合的一个例子:模型在训练数据上的表现要好于在之前从未见过的数据上的表现。经过这一点之后,模型会过度优化和学习特定于训练数据的表示,但无法泛化到测试数据。
对于这种特殊情况,我们只需在经过 20 个左右的周期后停止训练即可防止过拟合。稍后您将看到如何使用回调自动执行该操作。