Skip to content

情感分析(RNN版)

一、概述

这个章节我们用循环神经网络来做情感分析,因为之前的 IMDb 电影评论数据集不算大,所以我们用预训练好的词向量(比如 GloVe)来表示每个词,这样可以减少模型的过拟合。我们会用双向循环神经网络来编码文本,最后把文本转换成 "积极" 或 "消极" 的分类结果。 nlp-map-sa-rnn.svg

二、模型原理:用双向循环神经网络表示文本

我们的模型是一个双向循环神经网络(BiRNN),结构很简单:

  1. 嵌入层:把每个词转换成预训练好的 GloVe 向量,相当于用别人在大数据上训练好的词的语义表示,不用自己从零训练。

  2. 双向循环神经网络编码器:用双向的长短期记忆网络(LSTM)来读文本,它会从左到右和从右到左各读一遍文本,这样能同时考虑文本的上下文信息。然后把初始时间步和最终时间步的隐状态连起来,作为整个文本的表示。

  3. 全连接输出层:把文本的表示转换成两个输出,对应 "积极" 和 "消极" 两个类别。

简单来说,就是先把词变成有语义的向量,然后让网络从正反两个方向读文本,把文本的信息浓缩成一个向量,最后判断这个文本是好评还是差评。

三、代码实现

1. 定义双向循环神经网络模型

我们定义一个BiRNN类,包含嵌入层、双向 LSTM 编码器和全连接输出层:

python
import torch
from torch import nn
from d2l import torch as d2l

class BiRNN(nn.Module):
    def __init__(self, vocab_size, embed_size, num_hiddens, num_layers, **kwargs):
        super(BiRNN, self).__init__(**kwargs)
        # 嵌入层,把词索引转换成词向量
        self.embedding = nn.Embedding(vocab_size, embed_size)
        # 双向LSTM编码器,embed_size是输入的词向量维度,num_hiddens是隐藏单元数
        self.encoder = nn.LSTM(embed_size, num_hiddens, num_layers=num_layers, bidirectional=True)
        # 全连接层,因为双向LSTM的初始和最终隐状态连起来是4*num_hiddens维度,输出2个类别
        self.decoder = nn.Linear(4 * num_hiddens, 2)

    def forward(self, inputs):
        # 先把输入的词索引转换成词向量,inputs形状是(批量大小, 词数)
        embeddings = self.embedding(inputs.T)  # 转置成(词数, 批量大小, 词向量维度)
        # 用双向LSTM编码,得到所有时间步的隐状态
        outputs, _ = self.encoder(embeddings)
        # 把初始时间步和最终时间步的隐状态连起来,作为文本的表示
        encoding = torch.cat((outputs[0], outputs[-1]), dim=1)
        # 输出分类结果
        outs = self.decoder(encoding)
        return outs

2. 初始化模型

我们创建一个有 2 个隐藏层的双向循环神经网络,词向量维度设为 100,隐藏单元数设为 100:

python
# 假设vocab是之前处理好的词表
embed_size, num_hiddens, num_layers = 100, 100, 2
net = BiRNN(len(vocab), embed_size, num_hiddens, num_layers)

然后我们需要初始化模型的参数,比如用 Xavier 初始化,让参数的分布更合理,方便训练。

3. 训练模型

我们用 Adam 优化器,学习率设为 0.01,训练 5 个轮次:

python
lr, num_epochs = 0.01, 5
trainer = torch.optim.Adam(net.parameters(), lr=lr)
loss = nn.CrossEntropyLoss()
# train_iter和test_iter是之前处理好的IMDb数据集迭代器
d2l.train_ch13(net, train_iter, test_iter, loss, trainer, num_epochs, d2l.try_all_gpus())

四、实验结果

训练完成后,我们可以看到:

  • 训练准确率大概在 0.929 左右,测试准确率大概在 0.851 左右

  • 我们可以用训练好的模型预测文本的情感,比如:

    • 输入 "this movie is so great",模型会预测是 "positive"(积极)

    • 输入 "this movie is so bad",模型会预测是 "negative"(消极)

五、小结

  1. 我们可以用预训练好的词向量来表示文本里的词,这样能减少小数据集上的过拟合。

  2. 双向循环神经网络可以很好地表示文本,它会同时考虑文本的上下文信息,把初始和最终时间步的隐状态连起来作为文本的整体表示,最后用全连接层输出分类结果。

(注:文档部分内容可能由 AI 生成) 源地址

京ICP备2024093538号-1