[NLP入门]基于 Dense 层的电影评论分类

Daisy ·
更新时间:2024-09-20
· 909 次阅读

最近在学习自然语言处理(NLP)IMDB 电影评论分类问题也算是一道入门题了,帮助自己熟悉神经网络的构建流程以及基本操作,跟大家分享一下。主要参考书目《Python深度学习》

一、任务描述

使用 IMDB 数据集中预处理后的电影评论,训练模型使之能够分辨电影评论为正面的还是负面的达到 85%85\%85% 以上的精度

1. 原始数据

评论

每条 评论 已经被转换为整数序列,对应 字典 中的某个单词。

标签

同时,每条评论也有与之对应的 标签。该标签是由 0,1 组成的列表,其中 0 代表负面,1 代表正面

2. 网络架构

使用全连接层(Dense层)作为网络的基本架构,并且只有 2 个中间层使用 relu 作为激活函数,每层需要有 16 个隐藏单元

3. 目标

使训练后的模型在测试集上能达到 85%85\%85% 以上的精度,并使用 maptplotlib 作出训练损失和验证损失随着迭代次数变化的图像,对过程进行分析与优化

二、详细设计 1. 准备数据 1)加载 IMDB 数据集

[Snippest 1] 加载 IMDB 数据集

from keras.datasets import imdb (train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)

train_data[i]: 为评论 i 的整数序列;

train_labels[i]:指示评论 i 为正面评论还是负面评论。

其样例如下:

print(train_data[0], "\n") print(train_labels[0]) [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 2)预处理数据

由于原始的评论数据是整数序列,是变长的整数列表,不能作为网络层的输入。可以考虑对其进行 one-hot 编码,转为高维的向量。

由于:

单词序列的范围为 [0,9999][0, 9999][0,9999]

对于单条评论中的单词重复项可以忽略,对结果影响不大

从而可以得到编码公式:

result[i][wordIndex]=1 result[i][wordIndex] = 1 result[i][wordIndex]=1

例如,假定单词序列范围为 [0,4][0, 4][0,4] 若 remark[i] = [1, 3],则编码后的 result[i] = [0, 1, 0, 1, 0],即索引 1、3 处为 1,其余均为 0

[Snippest 2] 评论序列独热编码

import numpy as np def remark2onehot(remark_seqs, dimension=10000): results = np.zeros((len(remark_seqs), dimension)) for i, wordIndex in enumerate(remark_seqs): results[i][wordIndex] = 1 return results train_data = remark2onehot(train_data) test_data = remark2onehot(test_data) # Test one-hot encoding print("train_data[0] = \n", train_data[0]) print("test_data [0] = \n", test_data [0]) train_data[0] = [0. 1. 1. ... 0. 0. 0.] test_data [0] = [0. 1. 1. ... 0. 0. 0.]

还要将标签转为 numpy 的数组

[Snippest 3] 标签向量化

train_labels = np.asarray((train_labels).astype('f4')) test_labels = np.asarray((test_labels).astype('f4')) train_labels array([1., 0., 0., ..., 0., 1., 0.], dtype=float32) 2. 构建网络 1)网络层级构建

依照任务描述,除了输入层外共有三层网络,每层均为 Dense:

中间层1:以上一层 输入层 作为输入,需指定输入形状为 (10000,)(10000, )(10000,) 的元组。每层有 16 个隐藏单元

中间层2:以上一层 中间层1 作为输入,自动识别输入形状无需指定。每层有 16 个隐藏单元

输出层 :以上一层 中间层2 作为输入,自动识别输入形状无需指定。输出结果为 1 维标量,取值为 0 或 1,进而需要使用 sigmoid 函数激活

[Snippest 4] 网络层级构建

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')) model.summary() Model: "sequential_5" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense_13 (Dense) (None, 16) 160016 _________________________________________________________________ dense_14 (Dense) (None, 16) 272 _________________________________________________________________ dense_15 (Dense) (None, 1) 17 ================================================================= Total params: 160,305 Trainable params: 160,305 Non-trainable params: 0 _________________________________________________________________ 2)层级参数个数分析

基本分析

在构建好网络的层次之后,发现中间层1竟然有 160016160016160016 个参数,这是为什么呢?我们来试着分析一下。

如下图,我画出了网络的前两层架构,包括输入层和中间层1。对于中间层1的每个单元 hih_ihi​,都是相互独立的,需要接收所有输入层单元传递的值并分别加权,最后经过激活(activate)处理才能得到 hih_ihi​ 的值。我们定义第 iii 个单元的权重向量为 θi\theta_iθi​。从而,在这个网络中 hih_ihi​ 可以用如下公式示意:

hi=relu(x1∗θi,1+x2∗θi,2+...+xi,10000∗θi,10000) h_i = relu(x_1*\theta_{i, 1} + x_2*\theta_{i, 2} + ... + x_{i, 10000}*\theta_{i, 10000}) hi​=relu(x1​∗θi,1​+x2​∗θi,2​+...+xi,10000​∗θi,10000​)

原创文章 4获赞 4访问量 442 关注 私信 展开阅读全文
作者:京海丰



电影 分类 nlp

需要 登录 后方可回复, 如果你还没有账号请 注册新账号
相关文章