电影评论分类IMDB(二分类)--python深度学习

import keras
keras.__version__

‘2.7.0’

IMDB电影评论分类(二分类)

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

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

与 MNIST 数据集一样,IMDB 数据集也内置于 Keras 库。

  • 已经过预处理:评论(单词序列)

已经被转换为整数序列,其中每个整数代表字典中的某个单词

1.数据导入

# 加载 IMDB 数据集(第一次运行时会下载大约 80MB 的数据)
from keras.datasets import imdb

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

参数 num_words=10000 的意思是仅保留训练数据中前 10 000 个最常出现的单词。低频单
词将被舍弃。这样得到的向量数据不会太大,便于处理。

train_labelstest_labels 都是 0 和 1 组成的列表,其中 0
代表负面(negative),1 代表正面(positive)

由于限定为前 10 000 个最常见的单词,单词索引都不会超过 10 000。

max([max(sequence) for sequence in train_data])

9999

  • 将某条评论迅速解码为英文单词

将评论解码,索引减 3
因为 0、1、2是为“padding”(填充)、“start of sequence”(序列开始)、“unknown”(未知词)分别保留的索引

# word_index 是一个将单词映射为整数索引的字典
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]])

2.数据预处理

不能将整数序列直接输入神经网络。需要将列表转换为张量。转换方法有以下两种。

  • 1.填充列表,使其具有相同的长度,再将列表转换成形状为 (samples, word_indices)的整数张量,然后网络第一层使用Embedding 层
  • 2.对列表进行 one-hot 编码,将其转换为 0 和 1 组成的向量。然后网络第一层可以用 Dense 层,它能够处理浮点数向量数据

demo

seasons = ['Spring', 'Summer', 'Fall', 'Winter']
list(enumerate(seasons))

[(0, ‘Spring’), (1, ‘Summer’), (2, ‘Fall’), (3, ‘Winter’)]

a = np.zeros((3, 5))
b = [1,2,3]
for j, b in enumerate(b):
    a[j, b] = 1
a

array([[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 1., 0.]])

real

# one-hot 编码   (将整数序列编码为二进制矩阵)
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.  # 将指定位置设为 1
    return results

# 训练数据向量化
x_train = vectorize_sequences(train_data)
# 测试数据向量化
x_test = vectorize_sequences(test_data)
x_train[0]

array([0., 1., 1., …, 0., 0., 0.])

# 将标签向量化
y_train = np.asarray(train_labels).astype('float32')
y_test = np.asarray(test_labels).astype('float32')

3.模型构建

输入数据是向量,而标签是标量(1 和 0),这是你会遇到的最简单的情况。带有 relu 激活的全连接层(Dense)的简单堆叠在此类问题上表现好,比如Dense(16, activation='relu')

传入 Dense 层的参数(16)是该层隐藏单元的个数。一个隐藏单元(hidden unit)是该层
表示空间的一个维度。
output = relu(dot(W, input) + b)

中间层使用 relu 作为激活函数,最后一层使用 sigmoid 激活以输出一个 0~1 范围内的概率值

from keras import models
from keras import layers

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

面对一个二分类问题,网络输出是一个概率值(网络最后一层使用 sigmoid 激活函数,仅包含一个单元),那么最好使用 binary_crossentropy(二元交叉熵)损失。

还可以使用 mean_squared_error(均方误差)。但对于输出概率值的模型,交叉熵(crossentropy)往往是最好的选择。交叉熵是来自于信息论领域的概念,用于衡量概率分布之间的距离,在这个例子中就是真实分布与预测值之间的距离。

# Keras 内置
model.compile(optimizer='rmsprop',    # 自动调整学习率
              loss='binary_crossentropy',   # 二元交叉熵
              metrics=['accuracy'])
# 自定义优化器的参数
from tensorflow.keras import optimizers

model.compile(optimizer=optimizers.RMSprop(lr=0.001),
              loss='binary_crossentropy',
              metrics=['accuracy'])
# 自定义损失和指标
from keras import losses
from keras import metrics

model.compile(optimizer=optimizers.RMSprop(lr=0.001),
              loss=losses.binary_crossentropy,
              metrics=[metrics.binary_accuracy])

4.模型训练

# 从原始训练数据留出 10 000个样本作为验证集
x_val = x_train[:10000]
partial_x_train = x_train[10000:]

y_val = y_train[:10000]
partial_y_train = y_train[10000:]
15000/512

29.296875

history = model.fit(partial_x_train,
                    partial_y_train,
                    epochs=20,
                    batch_size=512,
                    validation_data=(x_val, y_val))

返回了一个History 对象。这个对象有一个成员 history,它是一个字典,包含训练过程中的所有数据。

history_dict = history.history
history_dict.keys()

dict_keys([‘loss’, ‘binary_accuracy’, ‘val_loss’, ‘val_binary_accuracy’])

5.结果可视化

import matplotlib.pyplot as plt
epochs = range(1, len(acc) + 1)

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

plt.plot(epochs, loss, 'bo', label='Training loss')   # 'bo' 表示蓝色圆点
plt.plot(epochs, val_loss, 'b', label='Validation loss')   # 'b' 表示蓝色实线
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')

plt.legend()   # 图例
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8uzn9YYy-1685261140241)(output_37_0.png)]

plt.clf()   # 清空图像
acc = history.history['binary_accuracy']
val_acc = history.history['val_binary_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()

在这里插入图片描述

overfitting,
重新训练

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'])

model.fit(x_train, y_train, epochs=4, batch_size=512)
results = model.evaluate(x_test, y_test)
results

[0.2904893457889557, 0.8834400177001953]

6.预测

model.predict(x_test)

网络对某些样本的结果非常确信(大于等于 0.99,或小于等于 0.01),但对其他
结果却不那么确信(0.6 或 0.4)

小结

在这里插入图片描述

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值