一、概述
- 情感分类是自然语言处理中的经典任务,是典型的二分类问题。
- 本示例使用 MindSpore 实现基于 RNN 网络的情感分类模型,能够对输入的影评进行正负情感的判断。
二、原理公式
- LSTM 公式
h_{0:t}, (h_t, c_t) = LSTM(x_{0:t}, (h_0, c_0))
- 其中,
h_{0:t}
表示每个时间步的隐状态拼接而成的矩阵,h_t
和c_t
分别表示最后一个时间步对应的隐状态和细胞状态。
三、推理流程
- 输入影评句子,进行分词处理。
- 通过词表将单词转换为对应的 index id 。
- 将 index id 序列输入模型的 Embedding 层,转换为向量表示。
- 向量进入 RNN 层进行特征提取,获取最后一个时间步的隐状态。
- 隐状态输入 Dense 层,得到预测结果。
- 通过 Sigmoid 函数将预测结果映射到 0 到 1 之间,根据阈值判断情感类别。
四、数据准备
- 数据集
- 使用 IMDB 影评数据集,包含 Positive 和 Negative 两类。
- 数据集已分割为 train 和 test 两部分,且每部分包含 neg 和 pos 两个分类的文件夹。
- 数据下载模块
- 利用
requests
库进行 http 请求,并通过tqdm
库对下载百分比进行可视化。 - 使用
IO
的方式下载临时文件,而后保存至指定的路径。 - 相关函数:
http_get(url, temp_file)
- 参数:
url
(数据下载链接),temp_file
(临时文件对象)。 - 功能:使用
requests
库下载数据,并使用tqdm
库进行流程可视化。 - 例句:
http_get('https://example.com/data', temp_file)
- 参数:
download(file_name, url)
- 参数:
file_name
(保存的文件名),url
(数据下载链接)。 - 功能:下载数据并存为指定名称。
- 例句:
download('data.zip', 'https://example.com/data.zip')
- 参数:
- 利用
- 加载 IMDB 数据集
- 使用
tarfile
库读取 tar.gz 文件,将数据和标签分别存放。 - 定义
IMDBData
类来处理数据加载。 - 使用
load_imdb
函数将 train 和 test 分别使用GeneratorDataset
进行加载,并指定列名。
- 使用
- 加载预训练词向量
- 使用 Glove 词向量作为 Embedding。
- 相关函数:
load_glove(glove_path)
- 参数:
glove_path
(Glove 词向量文件路径)。 - 功能:加载 Glove 词向量,生成词表和词向量权重矩阵。
- 例句:
load_glove('/path/to/glove.6B.txt')
- 参数:
五、数据集预处理
- 包含将 Token 处理为 index id,统一文本序列长度等操作。
- 使用
text.Lookup
接口将 Token 转换为 index id,使用PadEnd
接口统一文本序列长度。 - 将 label 数据转为
float32
格式。 - 手动将数据集分割为训练和验证两部分。
- 指定数据集的 batch 大小。
六、模型构建
- 整体结构:
nn.Embedding -> nn.RNN -> nn.Dense
- Embedding 层
- 作用是使用 index id 对权重矩阵对应 id 的向量进行查找。
- 相关函数:
nn.Embedding(vocab_size, embedding_dim, embedding_table=ms.Tensor(embeddings), padding_idx=pad_idx)
- 参数:
vocab_size
(词表大小),embedding_dim
(嵌入维度),embedding_table
(预训练词向量矩阵),padding_idx
(填充索引)。 - 功能:创建 Embedding 层。
- 例句:
embedding = nn.Embedding(1000, 100, embedding_table=pre_trained_embeddings, padding_idx=0)
- 参数:
- RNN 层
- 选择 LSTM 变种做特征提取来规避梯度消失问题。
- 相关函数:
nn.LSTM(embedding_dim, hidden_dim, num_layers=n_layers, bidirectional=bidirectional, batch_first=True)
- 参数:
embedding_dim
(输入维度),hidden_dim
(隐藏层维度),num_layers
(层数),bidirectional
(是否双向),batch_first
(是否 batch 在前)。 - 功能:创建 LSTM 层。
- 例句:
rnn = nn.LSTM(128, 256, num_layers=2, bidirectional=True, batch_first=True)
- 参数:
- Dense 层
- 将特征维度变换为二分类所需的维度 1。
- 相关函数:
nn.Dense(hidden_dim * 2, output_dim, weight_init=weight_init, bias_init=bias_init)
- 参数:
hidden_dim * 2
(输入维度),output_dim
(输出维度),weight_init
(权重初始化),bias_init
(偏置初始化)。 - 功能:创建全连接层。
- 例句:
dense = nn.Dense(512, 1, weight_init=HeUniform(), bias_init=Uniform())
- 参数:
七、损失函数与优化器
- 针对二分类问题,选择
nn.BCEWithLogitsLoss
作为损失函数。- 相关函数:
nn.BCEWithLogitsLoss(reduction='mean')
- 参数:
reduction
(损失计算方式,如'mean'
计算均值)。 - 功能:创建二分类交叉熵损失函数。
- 例句:
loss_fn = nn.BCEWithLogitsLoss(reduction='mean')
- 参数:
- 相关函数:
- 使用
nn.Adam
作为优化器。- 相关函数:
nn.Adam(model.trainable_params(), learning_rate=lr)
- 参数:
model.trainable_params()
(模型可训练参数),learning_rate
(学习率)。 - 功能:创建 Adam 优化器。
- 例句:
optimizer = nn.Adam(model.trainable_params(), learning_rate=0.001)
- 参数:
- 相关函数:
八、训练逻辑
- 定义
forward_fn
函数进行正向计算和损失计算。- 相关函数:
forward_fn(data, label)
- 参数:
data
(输入数据),label
(标签)。 - 功能:计算模型的预测值和损失。
- 例句:
loss = forward_fn(input_data, target_label)
- 参数:
- 相关函数:
- 通过
ms.value_and_grad
得到grad_fn
,用于计算梯度。- 相关函数:
ms.value_and_grad(forward_fn, None, optimizer.parameters)
- 参数:
forward_fn
(前向计算和损失函数),None
(不需要计算梯度的输入),optimizer.parameters
(优化器的参数)。 - 功能:获取梯度计算函数。
- 例句:
grad_fn = ms.value_and_grad(forward_fn, None, optimizer.parameters)
- 参数:
- 相关函数:
train_step
函数执行梯度更新和损失返回。- 相关函数:
train_step(data, label)
- 参数:
data
(输入数据),label
(标签)。 - 功能:执行一步训练,更新参数并返回损失。
- 例句:
loss = train_step(input_data, target_label)
- 参数:
- 相关函数:
train_one_epoch
函数实现一个 epoch 的训练。- 相关函数:
train_one_epoch(model, train_dataset, epoch=0)
- 参数:
model
(模型),train_dataset
(训练数据集),epoch
(轮数,默认为 0)。 - 功能:完成一个 epoch 的训练。
- 例句:
train_one_epoch(model, train_data, epoch=1)
- 参数:
- 相关函数:
九、评估指标和逻辑
binary_accuracy
函数计算每个 batch 的准确率。- 相关函数:
binary_accuracy(preds, y)
- 参数:
preds
(预测值),y
(真实标签)。 - 功能:计算准确率。
- 例句:
accuracy = binary_accuracy(predictions, labels)
- 参数:
- 相关函数:
evaluate
函数实现评估逻辑,计算准确率和损失。- 相关函数:
evaluate(model, test_dataset, criterion, epoch=0)
- 参数:
model
(模型),test_dataset
(测试数据集),criterion
(损失函数),epoch
(轮数,默认为 0)。 - 功能:评估模型在测试集上的性能。
- 例句:
loss, accuracy = evaluate(model, test_data, loss_fn, epoch=2)
- 参数:
- 相关函数:
十、模型训练与保存
- 设置训练轮数为 5 轮。
- 维护
best_valid_loss
变量保存最优模型。
十一、模型加载与测试
- 使用
ms.load_checkpoint
和ms.load_param_into_net
加载模型。- 相关函数:
ms.load_checkpoint(ckpt_file_name)
- 参数:
ckpt_file_name
(检查点文件路径)。 - 功能:加载检查点。
- 例句:
param_dict = ms.load_checkpoint('model.ckpt')
- 参数:
ms.load_param_into_net(model, param_dict)
- 参数:
model
(模型),param_dict
(参数字典)。 - 功能:将参数加载到模型中。
- 例句:
ms.load_param_into_net(model, params)
- 参数:
- 相关函数:
- 对测试集进行评估。
十二、自定义输入测试
- 定义
predict_sentiment
函数进行自定义输入的情感分类预测。- 相关函数:
predict_sentiment(model, vocab, sentence)
- 参数:
model
(模型),vocab
(词表),sentence
(输入句子)。 - 功能:预测输入句子的情感类别。
- 例句:
prediction = predict_sentiment(model, vocab, 'This movie is amazing!')
- 参数:
- 相关函数:
十三、操作流程
- 准备数据:
- 下载 IMDB 数据集和 Glove 词向量。
- 加载并处理数据集,包括分词、转换为 index id、统一长度等。
- 构建模型:
- 定义 RNN 模型结构,包括 Embedding 层、RNN 层和 Dense 层。
- 定义损失函数和优化器。
- 训练模型:
- 设计训练逻辑,包括正向计算、梯度计算和参数更新。
- 进行多轮训练,保存最优模型。
- 评估模型:
- 设计评估逻辑,计算准确率和损失。
- 模型加载与测试:
- 加载训练好的模型。
- 对测试集进行评估。
- 进行自定义输入的预测。
十四、调用库及功能
mindspore
:构建模型、计算梯度、优化参数等。mindspore.dataset
:处理和加载数据集,进行数据增强操作。requests
:用于发送 http 请求进行数据下载。tqdm
:可视化数据下载进度。