文本分类

    注意:本教程需要TensorFlow版本>= 2.1

    本教程根据影评文本将影评分为正面或负面。这是一个二元或两类分类的例子,这是一个重要的和广泛应用的机器学习问题。

    我们将使用IMDB数据集里面有5万篇电影评论的文本互联网电影数据库.它们被分成25000个用于培训的评审和25000个用于测试的评审。训练和测试集是平衡的,这意味着它们包含相同数量的正面和负面评价。

    让我们启动并加载Keras以及其他一些必需的库。

    图书馆(keras)图书馆(dplyr)图书馆(ggplot2)图书馆(purrr)

    下载电影评论数据集

    我们将使用由Bo Pang和Lillian Lee创建的电影评论数据集。该数据集是在获得作者许可的情况下使用NLTK重新分发的。

    可以找到该数据集在这里,可从Kaggle UI下载或使用包中。

    如果你要用遵循这个教程注册Kaggle董事会。然后你可以运行:

    现在我们把它读给Rread_csvfuncntion从readr包中。

    使用列规范解析:## cols(## fold_id = col_double(), ## cv_tag = col_character(), ## html_id = col_double(), ## sent_id = col_double(), ## text = col_character(), ## tag = col_character() ##)
    (df)
    # # #一个宠物猫:6 x 6 # # fold_id cv_tag html_id sent_id文本标签# # <双> <空空的> <双> <双> <空空的> < >从而向# # 1 0 cv000 29590 0电影改编自漫画…pos # # 2 0 cv000 29590 1对初学者来说,它是由阿尔…pos # # 3 0 cv000 29590 2说摩尔和坎贝尔thoroughl…pos # # 4 0 cv000 29590 3”这本书(或\”漫画小说,\…pos # # 5 0 cv000 29590 4换句话说,不要小看这…pos # # 6 0 cv000 29590 5如果你能穿过整个漫画…pos

    探索数据

    让我们花点时间来理解数据的格式。该数据集有60k行,每一行代表一个电影评论。的文本专栏有实际的回顾和标签代表向我们展示了分类的情绪。

    df% > %(标签)
    ## # A tibble: 2 x 2 ## tag n ##   ## 1 neg 31783 ## 2 pos 32937

    大约一半的评论是负面的,另一半是正面的。下面是一个回顾的例子:

    “根据漫画改编的电影已经取得了很大的成功,无论是关于超级英雄(蝙蝠侠、超人、spawn),还是面向儿童(casper)或艺术电影人群(幽灵世界),但之前从未有过一部来自地狱的漫画书。”

    让我们将数据集分为训练和测试:

    找出每篇文章的字数分布也很有用。

    df文本% > %strsplit”“% > %酸式焦磷酸钠(长度)% > %总结()
    ##最小1曲,中值平均3曲,最大值。## 1.00 14.00 21.00 23.06 30.00 179.00

    准备数据

    在输入神经网络之前,评论(文本)必须转换为张量。首先,我们创建一个字典,用一个整数表示10,000个最常见的单词中的每一个。在这种情况下,每次评审都将由一个整数序列表示。

    然后我们可以用几种方式表示评论:

    • 对数组进行1 -热编码,将它们转换为0和1的向量。例如,序列[3,5]将变成一个10,000维的向量,除了指标3和5是1之外,它都是0。然后,把这个作为网络的第一层- a密集的层——可以处理浮点向量数据。但是,这种方法是内存密集型的,需要一个num_words * num_reviews大小的矩阵。

    • 或者,我们可以填充数组,使它们都具有相同的长度,然后创建一个形状的整数张量num_examples * max_length.我们可以使用一个能够处理这种形状的嵌入层作为网络中的第一层。

    在本教程中,我们将使用第二种方法。现在,让我们定义我们的文本矢量化层,它将负责获取字符串输入并将其转换为一个张量。

    现在,我们需要适应文本矢量化层。这是我们打电话的时候适应该层将学习数据集中唯一的单词,并为每个单词分配一个整数值。

    我们现在可以看到词汇表在文本向量化层中。

    你可以看到文本向量化层如何转换它的输入:

    text_vectorization矩阵(df文本(1),ncol =1))
    # #特遣部队。张量(## [[68 2835 30 359 1662 33 91 1056 5 632 631 321 41 7803 ## 709 4865 1767 48 7600 1337 398 5161 48 21 1808 1800 148 ## 17 140 109 90 69 3 359 408 40 30 503 142 00 ## 00 00 0]],shape=(1,50), dtype=int64)

    构建模型

    神经网络是通过堆叠层创建的——这需要两个主要的架构决策:

    • 在模型中使用多少层?
    • 每个图层使用多少隐藏单位?

    在本例中,输入数据由一个单词索引数组组成。要预测的标签是0或1。让我们为这个问题建立一个模型:

    输入< -layer_input形状=c1),dtype =“字符串”输出< -输入% > %text_vectorization()% > %layer_embeddinginput_dim =num_words+1output_dim =16% > %layer_global_average_pooling_1d()% > %layer_dense单位=16激活=“relu”% > %layer_dropout0.5% > %layer_dense单位=1激活=“乙状结肠”模型< -keras_model(输入、输出)

    这些层按顺序堆叠以构建分类器:

    • 第一层是嵌入层。这一层采用整数编码的词汇表,并为每个单词索引查找嵌入向量。这些向量被学习为模型列车。这些向量向输出数组添加了一个维度。得到的维度是:(批处理、序列嵌入).
    • 接下来,一个global_average_pooling_1dLayer通过在序列维度上取平均值,为每个示例返回一个固定长度的输出向量。这允许模型以最简单的方式处理可变长度的输入。
    • 这个固定长度的输出向量通过一个完全连接的(密集的)层有16个隐藏单位。
    • 最后一层与单个输出节点紧密连接。使用乙状结肠激活函数,这个值是一个介于0和1之间的浮点数,表示一个概率,或置信水平。

    隐藏的单位

    上面的模型在输入和输出之间有两个中间层或“隐藏”层。输出的数量(单元、节点或神经元)是该层的表示空间的维度。换句话说,当学习一个内部表示时,网络被允许的自由度。

    如果一个模型有更多的隐藏单元(高维表示空间)和/或更多的层,那么网络就可以学习更复杂的表示。然而,它使网络的计算成本更高,并可能导致学习不需要的模式——这些模式提高了训练数据的性能,但不能提高测试数据的性能。这被称为过拟合,我们将在后面讨论它。

    损失函数和优化器

    一个模型需要一个损失函数和一个训练优化器。由于这是一个二元分类问题,并且模型输出一个概率(具有sigmoid激活的单个单元层),因此我们将使用binary_crossentropy损失函数。

    这不是损失函数的唯一选择,举个例子,你可以选择mean_squared_error.但是,一般来说,binary_crossenropy更适合于处理概率——它度量概率分布之间的“距离”,或者在我们的例子中,度量基本真理分布和预测之间的“距离”。

    稍后,当我们探索回归问题(比如,预测房子的价格)时,我们将看到如何使用另一个损失函数,称为均方误差。

    现在,配置模型使用优化器和损失函数:

    火车模型

    在512个样本的小批次中训练模型的20个epoch。这是对x_train和y_train张量中所有样本的20次迭代。在训练时,监控模型在验证集中的10,000个样本上的损失和准确性:

    # #火车在41420个样本,验证10356个样本# #时代1/10 # # 41420/41420 - 1 s -损失:0.6921 -准确性:0.5185 - val_loss: 0.6898 - val_accuracy: 0.5410 # #时代# # 41420/41420——2/10 0 -损失:0.6862 -准确性:0.5600 - val_loss: 0.6805 - val_accuracy: 0.5965 # #时代# # 41420/41420——3/10 0 -损失:0.6716 -准确性:0.6050 - val_loss: 0.6633 - val_accuracy: 0.6400 # #时代# # 41420/41420——4/10 0 -损失:0.6468 -准确性:0.6515 - val_loss: 0.6399 - val_accuracy:0.6619 # #时代# # 41420/41420——5/10 0 -损失:0.6161 -准确性:0.6796 - val_loss: 0.6184 - val_accuracy: 0.6747 # #时代# # 41420/41420——6/10 0 -损失:0.5875 -准确性:0.7029 - val_loss: 0.6039 - val_accuracy: 0.6808 # #时代7/10 # # 41420/41420 - 1 s -损失:0.5632 -准确性:0.7212 - val_loss: 0.5963 - val_accuracy: 0.6831 # #时代# # 41420/41420——8/10 0 -损失:0.5448 -准确性:0.7336 - val_loss: 0.5917 - val_accuracy: 0.6863 # #时代# # 41420/41420——9/10 0 -损失:0.5297 -精度:0.7442 - val_loss: 0.5937 - val_accuracy: 0.6842 ##纪元10/10 ## 41420/41420 - 0s -损耗:0.5165 -精度:0.7539 - val_loss: 0.5953 - val_accuracy: 0.6868

    评估模型

    让我们看看模型的表现。将返回两个值。损失(一个代表我们错误的数字,数值越低越好)和准确性。

    结果< -模型% > %评估(测试文本,as.numeric(测试标签= =“pos”),verbose =0结果
    # # # #[1]美元损失精度0.5940198 # # # # # # 0.6830192 [1]

    这种相当简单的方法获得了约68%的准确性。使用更先进的方法,模型应该接近85%。

    创建一个准确性和损失随时间变化的图表

    适合返回一个keras_training_history的对象指标槽包含训练过程中记录的损耗和度量值。你可以像这样绘制损失和指标曲线:

    情节(历史)

    在RStudio Viewer窗格的训练过程中,也可以看到损失和度量的演变。英格兰vs伊朗让球

    注意训练损耗随时间的增加而减小,训练精度随时间的增加而增加。当使用梯度下降优化时,这是预期的——它应该在每次迭代中最小化所需的数量。