机器深度学习二分类电影的情感问题
作者:无风听海 发布时间:2022-07-17 06:13:28
二分类问题可能是应用最广泛的机器学习问题。今天我们将学习根据电影评论的文字内容将其划分为正面或负面。
一、数据集来源
我们使用的是IMDB数据集,它包含来自互联网电影数据库(IMDB)的50000条严重两极分化的评论。为了避免模型过拟合只记住训练数据,我们将数据集分为用于训练的25000条评论与用于测试的25000条评论,训练集和测试集都包含50%的正面评论和50%的负面评论。
与MNIST数据集一样,IMDB数据集也内置于Keras库。它已经过预处理:评论(单词序列)已经被转换为整数序列,其中每个整数代表字典中的某个单词。
通过以下代码加载数据集并限制每条评论最多取前一万个常用的word,以便于我们进行向量处理。
import tensorflow as tf
imdb = tf.keras.datasets.imdb
(train_data, train_labels),(test_data, test_labels) = imdb.load_data(num_words=10000)
print(train_data[0])
print(train_labels[0])
通过输出可以看到,train_data和test_data是评论记录的集合,每条评论记录又是由众多的单词索引组成的集合。
train_labels和test_labels是针对评论的分类的集合,其中0表示负面评论,1表示正面评论。
[1, 14, 22, 16, 43, 530, 973, 1622, 1385, 65, 458, 4468, 66, 3941, 4, 173, 36, 256, 5, 25, 100, 43, 838, 112, 50, 670, 2, 9, 35, 480, 284, 5, 150, 4, 172, 112, 167, 2, 336, 385, 39, 4, 172, 4536, 1111, 17, 546, 38, 13, 447, 4, 192, 50, 16, 6, 147, 2025, 19, 14, 22, 4, 1920, 4613, 469, 4, 22, 71, 87, 12, 16, 43, 530, 38, 76, 15, 13, 1247, 4, 22, 17, 515, 17, 12, 16, 626, 18, 2, 5, 62, 386, 12, 8, 316, 8, 106, 5, 4, 2223, 5244, 16, 480, 66, 3785, 33, 4, 130, 12, 16, 38, 619, 5, 25, 124, 51, 36, 135, 48, 25, 1415, 33, 6, 22, 12, 215, 28, 77, 52, 5, 14, 407, 16, 82, 2, 8, 4, 107, 117, 5952, 15, 256, 4, 2, 7, 3766, 5, 723, 36, 71, 43, 530, 476, 26, 400, 317, 46, 7, 4, 2, 1029, 13, 104, 88, 4, 381, 15, 297, 98, 32, 2071, 56, 26, 141, 6, 194, 7486, 18, 4, 226, 22, 21, 134, 476, 26, 480, 5, 144, 30, 5535, 18, 51, 36, 28, 224, 92, 25, 104, 4, 226, 65, 16, 38, 1334, 88, 12, 16, 283, 5, 16, 4472, 113, 103, 32, 15, 16, 5345, 19, 178, 32]
1
我们可以通过word与编号的映射关系将评论的内容转化为具体的文本
def get_text(comment_num):
"""将数字形式的评论转化为文本"""
# word_index = tf.keras.datasets.imdb.get_word_index()
word_index = imdb.get_word_index()
reverse_word_index = dict([(value, key) for (key, value) in word_index.items()])
text = ' '.join([reverse_word_index.get(i - 3, '?') for i in comment_num])
return text
comment = get_text(train_data[0])
print(comment)
第一条电影评论的内容
? this film was just brilliant casting location scenery story direction everyone's really suited the part they played and you could just imagine being there robert ? is an amazing actor and now the same being director ?
二、格式化输入数据
由于我们无法直接将整数序列输入神经网络,所以需要将其转换为张量。可以通过以下两种方式进行转化
填充列表,使其具有相同的长度,然后将列表转化为(samples, word_index)的2D形状的整数张量。对列表进行one-hot编码,将其转化为0和1组成的向量。
这里我们采用one-hot进行编码处理
def vectorize_sequences(sequences, diamension = 10000):
results = np.zeros((len(sequences), diamension))
for i, sequence in enumerate(sequences):
results[i, sequence] = 1
return results
x_train = vectorize_sequences(train_data)
print(x_train[0])
print(len(x_train[0]))
x_test = vectorize_sequences(test_data)
print(x_test[0])
print(len(x_test[0]))
转化完成的输入结果
[0. 1. 1. ... 0. 0. 0.]
10000
[0. 1. 1. ... 0. 0. 0.]
将标签进行向量化处理
y_train = np.asarray(train_labels).astype('float32')
y_test = np.asarray(test_labels).astype('float32')
三、构建神经网络
针对这里二分类单标签,我们可以直接使用带有relu激活函数的全连接层的简单堆叠。
我们使用了两个具有16个隐藏单元的中间层和具有一个隐藏单元的层。中间层使用的relu激活函数负责将所有的负值归零,最后一层使用sigmoid函数将任意值压缩到[0,1]之间并作为预测结果的概率。
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'))
这里的Dense层实现了如下的张量计算,传入Dense层的参数16表示隐藏单元的个数,同时也表示这个层输出的数据的维度数量。隐藏单元越多,网络越能够学习到更加复杂的表示,但是网络计算的代价就越高。
output = relu(dot(W, input) + b)
我们使用rmsprop优化器和binary_crossentropy损失函数来配置模型。
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['accuracy'])
四、训练模型
将训练数据分出一小部分作为校验数据,同时将512个样本作为一批量处理,并进行20轮的训练,同时出入validation_data来监控校验样本上的损失和计算精度。
x_val = x_train[:10000]
partial_x_train = x_train[10000:]
y_val = y_train[:10000]
partial_y_train = y_train[10000:]
history = model.fit(partial_x_train, partial_y_train, epochs= 20, batch_size=512, validation_data=(x_val, y_val))
调用fit()返回的history对象包含训练过程的所有数据
history_dict = history.history
print(history_dict.keys())
字典中包含4个条目,对应训练过程和校验过程的指标,其中loss是训练过程中损失指标,accuracy是训练过程的准确性指标,而val_loss是校验过程的损失指标,val_accuracy是校验过程的准确性指标。
dict_keys(['loss', 'accuracy', 'val_loss', 'val_accuracy'])
我们使用Matplotlib画出训练损失和校验损失的情况
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()
从图中可以看到整个训练过程,损失函数值一直在不断的变小,但是校验过程的损失函数值却先变小后变大,在2.5-5之间的某个点达到最小值。
我们使用Matplotlib画出训练精度和校验精度的情况
plt.clf()
acc = history_dict['accuracy']
val_acc = history_dict['val_accuracy']
plt.plot(epochs, acc, 'bo', label='Training accuracy')
plt.plot(epochs, val_acc, 'b', label='Validation accuracy')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.show()
从图中可以看到整个训练过程,准确度值一直在不断的升高,但是校验过程的精度数值却在不断的进行波动,在2.5-5之间的某个点达到最大值。
通过对训练和校验指标的分析,可以看到训练的损失每轮都在降低,训练的精度每轮都在提升。但是校验损失和校验精度基本上在第4轮左右达到最佳值。为了防止这种过拟合的情况,我们可以在第四轮完成之后直接停止训练。
history = model.fit(partial_x_train, partial_y_train, epochs= 4, batch_size=512, validation_data=(x_val, y_val))
results = model.evaluate(x_test, y_test)
print(results)
重新执行可以看到模型的精度可以达到87%
782/782 [==============================] - 1s 876us/step - loss: 0.3137 - accuracy: 0.8729
[0.3137112557888031, 0.8728799819946289]
五、使用测试数据预测结果
使用训练的模型对test数据集进行预测
result = model.predict(x_test)
print(result)
[[0.31683978]
[0.9997941 ]
[0.9842608 ]
...
[0.18170357]
[0.23360077]
六、小结
需要对原始数据进行预处理并转化为符合要求的张量。
对于二分类问题,最后一层使用sigmoid作为激活函数,并输出0-1的标量来表示结果出现的概率。
对于二分类问题的sigmoid标量输出,应该使用binary_crossentropy损失函数。
随着训练过程的进行,很容易出现过拟合现象,我们需要时刻监控模型在非训练数据集的表现。
来源:https://www.cnblogs.com/wufengtinghai/p/14655608.html


猜你喜欢
- 使用Northwind 数据库首先查询Employees表查询结果:city列里面只有5个城市使用ROW_NUMBER() OVER(PAR
- Go批处理语句用于同时执行多个语句使用、切换数据库use mastergo创建、删除数据库方法1、--判断是否存在该数据库,存在就删除if
- Django是一种基于Python的Web开发框架一、在命令行中创建Django项目(Windows平台、python3.6)1、建立虚拟环
- 前言本文主要介绍的是关于python 3用BeautifulSoup抓取div标签的方法示例,分享出来供大家参考学习,下面来看看详细的介绍:
- 本文实例讲述了MySQL 表数据的导入导出操作。分享给大家供大家参考,具体如下:数据导出1. 使用 SELECT ..
- # -*- coding: utf8 -*-'''Created on 2013-12-19@author: goo
- GetRepeatTimes(TheChar,TheString) 得到一个字符串在另一个字符串当中出现几次的函数(新)如:response
- Twig是一款快速、安全、灵活的PHP模板引擎,它内置了许多filter和tags,并且支持模板继承,能让你用最简洁的代码来描述你的模板。他
- PS: 传送门——自定义Colorbars教程自定义colorbar(draw colorbar w
- SecureFile功能是oracle 11g中对大对象(LOB)存储格式的完全重新设计实现,原来的LOB存储格式现在通称为BASIXFIL
- Blender 并不是唯一一款允许你为场景编程和自动化任务的3D软件; 随着每一个新版本的推出,Blender 正逐渐成为一个可靠的 CG
- 本文实例为大家分享了Python密码强弱判断的具体代码,供大家参考,具体内容如下程序说明:通过获取用户输入,判断密码长度是否大于8,同时判断
- python的一个加速器包,这里不讲原理,只讲应用过程,以及给出几个小例子,直接写就行了; 另外还给出了numba如何定义使用List1、最
- 目录元组1.什么是元组tuple2.元组tuple支持什么数据类型3.元组tuple的基本特征4.如何声明一个元组tuple5.玩转元组tu
- 为了给导航栏添加响应式特性,您要折叠的内容必须包裹在带有 classes .collapse、.navbar-collapse 的 <
- 通常我们会用wc -l来统计文件行数,不过用Python统计也很简单。要快速统计一个文本文件中的行数,其实就是要统计这个文本文件中换行符的个
- 在这篇文章(不敢妄称教程,最多称之为学习笔记)里,我会从头开始实现客户端模板的效果。不过你不要期望能够在这里找到可以直接拿去使用直接复用灵活
- 本文实例讲述了php获取文章内容第一张图片的方法。分享给大家供大家参考,具体如下:<?php$temp=mt_rand(1,4);$p
- 获取数据(四种方式)1. url: 需要正则去匹配 url(r'^index/(num)/$&#
- Session作用Session的根本作用就是在服务端存储用户和服务器会话的一些信息。典型的应用有:1、判断用户是否登录。2、购物车功能。s