首页 > 其他分享 >基于RNN的NLP学习(附件一)

基于RNN的NLP学习(附件一)

时间:2024-04-18 14:46:03浏览次数:16  
标签:NLP RNN dim text 代码 batch 附件 文本 模型

附件:下面是一个基于RNN的非常简单的NLP实战案例,我们将使用PyTorch来实现一个情感分析模型。这个案例使用了IMDb电影评论数据集,该数据集包含正面和负面评论。

# 导入必要的库
"""
这些库是用于自然语言处理(NLP)任务,特别是在深度学习框架PyTorch中。下面是对这些库的简要说明:
1. `torch`: 这是PyTorch框架的基础库,提供了自动微分和高效的张量计算。
2. `torch.nn`: 这是PyTorch的神经网络库,提供了构建和训练神经网络所需的各种工具和函数。
3. `torch.optim`: 这是PyTorch的优化库,提供了各种优化算法,如SGD、Adam等,用于训练神经网络。
4. `torchtext`: 这是PyTorch的文本处理库,提供了处理文本数据所需的工具和函数。
5. `IMDB`: 这是torchtext提供的一个内置数据集,包含了来自IMDB的电影评论及其情感标签(正面或负面)。
6. `Field`: 这是torchtext的一个类,用于定义如何处理某种类型的文本数据,例如如何进行分词、建立词汇表等。
7. `LabelField`: 这是torchtext的一个类,用于定义如何处理标签数据。
8. `BucketIterator`: 这是torchtext的一个迭代器,用于在训练神经网络时提供批量数据。它会根据文本长度将相似长度的样本放在同一个批次中,以减少计算过程中的填充(padding)。
总的来说,这些库和工具提供了在PyTorch中处理和训练NLP模型所需的各种功能。
"""
import torch
import torch.nn as nn
from torchtext.datasets import IMDB
from torchtext.legacy.data import Field, LabelField, BucketIterator

"""
这两行代码定义了如何处理IMDB数据集中的文本和标签字段。`Field`和`LabelField`是`torchtext`库中的类,它们用于指定如何预处理和 numericalize(数字化)文本和标签数据。
1. `TEXT = Field(tokenize='spacy', lower=True, include_lengths=True)`
   这行代码定义了如何处理文本字段。`Field`类的参数指定了以下内容:
   - `tokenize='spacy'`: 使用`spacy`库进行文本分词。`spacy`是一个高性能的自然语言处理库,可以用于分词、词性标注、命名实体识别等任务。
   - `lower=True`: 在分词后将所有文本转换为小写。这是为了确保词汇表不区分大小写,从而减少词汇量。
   - `include_lengths=True`: 在迭代数据时,返回每个样本的文本长度。这有助于在创建批次时进行动态填充,因为每个批次的文本长度可能不同。
2. `LABEL = LabelField(dtype=torch.float)`
   这行代码定义了如何处理标签字段。`LabelField`是`Field`的一个子类,专门用于处理分类任务的标签。参数指定了以下内容:
   - `dtype=torch.float`: 将标签数据转换为浮点数。在分类任务中,标签通常会被转换为独热编码向量或整数索引,但在这里指定为浮点数可能是因为该数据集的标签已经是0.0(负面)和1.0(正面)的形式,或者是为了与损失函数兼容。
总结来说,这两行代码设置了文本和标签数据的预处理和数字化方法,这些设置将用于加载和迭代IMDB数据集,以便在PyTorch中训练文本分类模型。
"""
# 定义字段
TEXT = Field(tokenize='spacy', lower=True, include_lengths=True)
LABEL = LabelField(dtype=torch.float)

"""
这行代码使用`torchtext`库中的`IMDB`类来加载和分割IMDB数据集。`IMDB`是`torchtext`提供的一个内置数据集,它包含了来自互联网电影数据库(IMDb)的电影评论及其情感标签(正面或负面)。
`IMDB.splits(TEXT, LABEL)`方法的作用如下:
- `IMDB`: 指定要使用的数据集。
- `splits`: 这是一个类方法,用于将数据集分割为训练集和测试集。
- `TEXT`: 这是之前定义的`Field`对象,它指定了如何处理文本数据。
- `LABEL`: 这是之前定义的`LabelField`对象,它指定了如何处理标签数据。
执行这行代码后,`train_data`和`test_data`将分别包含训练集和测试集的数据。这些数据会根据`TEXT`和`LABEL`的定义进行预处理和数字化,以便在后续的模型训练和评估中使用。
"""
# 加载数据
train_data, test_data = IMDB.splits(TEXT, LABEL)

"""
这两行代码用于构建文本和标签的词汇表。
1. `TEXT.build_vocab(train_data, min_freq=5)`
   这行代码为文本字段构建词汇表。
   - `build_vocab`方法遍历训练数据集中的所有文本,并统计每个单词的出现频率。
   - 参数`min_freq=5`指定了最小频率,这意味着只有出现频率至少为5次的单词才会被包含在词汇表中。
     这个参数有助于过滤掉一些稀有的单词,从而减少词汇表的规模,这对于模型的训练和推理都是有利的。
     构建词汇表后,每个单词都会被分配一个唯一的索引,这个索引将用于后续的数字化过程。
2. `LABEL.build_vocab(train_data)`
   这行代码为标签字段构建词汇表。由于标签通常是固定的类别(例如正面和负面),因此不需要`min_freq`参数。
   - `build_vocab`方法会自动识别所有唯一的标签,并为每个标签分配一个唯一的索引。这个索引将用于将标签数据转换为数字形式,以便在训练模型时使用。
总结来说,这两行代码分别构建了文本和标签的词汇表,这些词汇表将用于将文本和标签数据转换为模型可以处理的数字形式。
"""
# 建立词汇表
TEXT.build_vocab(train_data, min_freq=5)
LABEL.build_vocab(train_data)

"""
这两行代码创建了两个`BucketIterator`对象,分别用于训练集和测试集。
`BucketIterator`是`torchtext`中的一个迭代器,它用于在训练神经网络时提供批量数据。
`BucketIterator`会根据指定的`sort_key`对数据进行排序,并将相似长度的样本放在同一个批次中,这样可以减少计算过程中的填充(padding)。
1. `train_loader = BucketIterator(train_data, batch_size=64, sort_key=lambda x: len(x.text), shuffle=True)`
   这行代码创建了一个用于训练集的`BucketIterator`对象:
   - `train_data`: 这是之前从IMDB数据集中分割出来的训练集数据。
   - `batch_size=64`: 指定每个批次中包含的样本数量。
   - `sort_key=lambda x: len(x.text)`: 指定排序的关键字。这里使用了一个lambda函数,它返回每个样本中文本字段的长度。
      这意味着`BucketIterator`会根据文本长度对样本进行排序,以便将相似长度的文本放在同一个批次中。
   - `shuffle=True`: 指定在每次迭代时是否对数据进行随机打乱。在训练过程中,通常希望打乱数据以提高模型的泛化能力。
2. `test_loader = BucketIterator(test_data, batch_size=64, sort_key=lambda x: len(x.text), shuffle=False)`
   这行代码创建了一个用于测试集的`BucketIterator`对象:
   - `test_data`: 这是之前从IMDB数据集中分割出来的测试集数据。
   - `batch_size=64`: 同样指定每个批次中包含的样本数量。
   - `sort_key=lambda x: len(x.text)`: 同样指定排序的关键字,这里也是根据文本长度进行排序。
   - `shuffle=False`: 在测试过程中,通常不希望打乱数据,因为需要按照原始顺序评估模型的性能。
总结来说,这两行代码创建了两个`BucketIterator`对象,分别用于训练和测试阶段的数据迭代。这些迭代器会根据文本长度对数据进行排序,并在每个批次中提供相似长度的样本,同时在训练过程中对数据进行随机打乱。
"""
# 创建数据迭代器
train_loader = BucketIterator(train_data, batch_size=64, sort_key=lambda x: len(x.text), shuffle=True)
test_loader = BucketIterator(test_data, batch_size=64, sort_key=lambda x: len(x.text), shuffle=False)

"""
这段代码定义了一个基于RNN(循环神经网络)的模型,用于文本分类任务。这个模型继承自`nn.Module`,是PyTorch中所有神经网络模块的基类。
下面是代码的详细解释:
1. `class RNNModel(nn.Module)`: 这行定义了一个新的类`RNNModel`,它继承自`nn.Module`。
2. `def __init__(self, vocab_size, embedding_dim, hidden_dim, output_dim)`: 这是类的构造函数,它接受四个参数:
   - `vocab_size`: 词向量的词汇量,即词汇表的大小。
   - `embedding_dim`: 词向量的维度。
   - `hidden_dim`: RNN隐藏层的维度。
   - `output_dim`: 输出层的维度,对于二分类问题,通常为1。
3. `super(RNNModel, self).__init__()`:这行调用父类`nn.Module`的构造函数。
4. `self.embedding = nn.Embedding(vocab_size, embedding_dim)`: 这行创建了一个嵌入层,它将单词索引映射为密集的向量表示。
5. `self.rnn = nn.RNN(embedding_dim, hidden_dim)`: 这行创建了一个基本的RNN层,它接受嵌入向量的维度作为输入维度,并输出指定维度的隐藏状态。
6. `self.fc = nn.Linear(hidden_dim, output_dim)`: 这行创建了一个全连接层,它将RNN的隐藏状态映射到输出维度,用于最终的分类。
7. `def forward(self, text, text_lengths)`: 这是模型的前向传播函数,它接受两个参数:
   - `text`: 输入的文本数据,形状为`seq_len x batch`,其中`seq_len`是序列的长度,`batch`是批次大小。
   - `text_lengths`: 文本的实际长度,用于处理不等长的序列。
8. `embedded = self.embedding(text)`: 这行将输入的文本数据通过嵌入层转换为嵌入向量。
9. `packed_embedded = nn.utils.rnn.pack_padded_sequence(embedded, text_lengths)`: 这行代码将嵌入向量打包,以忽略填充(padding)的部分,从而提高计算效率。
10. `packed_output, hidden = self.rnn(packed_embedded)`: 这行代码将打包后的嵌入向量输入到RNN层,并得到输出和最后一个时间步的隐藏状态。
11. `return self.fc(hidden[-1])`: 这行代码将最后一个时间步的隐藏状态通过全连接层映射到输出维度,并返回最终的分类结果。
总结来说,这个模型首先将输入的文本数据转换为嵌入向量,然后通过RNN层处理这些向量,最后通过全连接层输出分类结果。这个模型适用于文本分类任务,特别是当输入文本的长度不等时。
"""


# 定义模型
class RNNModel(nn.Module):
    def __init__(self, vocab_size, embedding_dim, hidden_dim, output_dim):
        super(RNNModel, self).__init__()
        self.embedding = nn.Embedding(vocab_size, embedding_dim)
        self.rnn = nn.RNN(embedding_dim, hidden_dim)
        self.fc = nn.Linear(hidden_dim, output_dim)

    def forward(self, text, text_lengths):
        embedded = self.embedding(text)
        packed_embedded = nn.utils.rnn.pack_padded_sequence(embedded, text_lengths)
        packed_output, hidden = self.rnn(packed_embedded)
        return self.fc(hidden[-1])


"""
这段代码是创建一个基于RNN的文本分类模型,并定义了损失函数和优化器。下面是代码的详细解释:
1. `vocab_size = len(TEXT.vocab)`: 这行代码获取了之前定义的`TEXT`字段的词汇表的大小,即词汇表中有多少个唯一的单词。这将作为嵌入层的第一个维度,用于将单词索引映射为嵌入向量。
2. `embedding_dim = 100`: 这行代码设置了嵌入向量的维度。每个单词将被映射为一个100维的密集向量。
3. `hidden_dim = 128`: 这行代码设置了RNN层的隐藏状态维度。RNN将有一个128维的隐藏层。
4. `output_dim = 1`: 这行代码设置了输出层的维度。由于这是一个二分类问题(正面或负面),输出层需要一个维度来预测两种类别。
5. `model = RNNModel(vocab_size, embedding_dim, hidden_dim, output_dim)`: 这行代码实例化了之前定义的`RNNModel`类,创建了一个模型对象。
6. `criterion = nn.BCEWithLogitsLoss()`: 这行代码定义了损失函数。`BCEWithLogitsLoss`结合了Sigmoid激活函数和二进制交叉熵损失函数,适用于二分类问题。
7. `optimizer = torch.optim.Adam(model.parameters())`: 这行代码创建了一个优化器对象。`Adam`是一种常用的优化算法,它结合了AdaGrad和RMSProp算法的优点。`model.parameters()`获取了模型中所有可学习的参数,这些参数将在训练过程中通过`optimizer`进行更新。
总结来说,这段代码首先定义了模型参数,然后创建了一个RNN模型、一个损失函数和一个优化器,这些都是训练文本分类模型所必需的组件。
"""
# 初始化模型、损失函数和优化器
vocab_size = len(TEXT.vocab)
embedding_dim = 100
hidden_dim = 128
output_dim = 1

model = RNNModel(vocab_size, embedding_dim, hidden_dim, output_dim)
criterion = nn.BCEWithLogitsLoss()
optimizer = torch.optim.Adam(model.parameters())

"""
这段代码是训练一个循环神经网络(RNN)模型的循环,用于文本分类任务。下面是代码的详细解释:
1. `num_epochs = 5`: 这行代码定义了训练周期数,即模型将遍历整个训练数据集5次。
2. `for epoch in range(num_epochs):`: 这行代码开始了一个外部循环,每次迭代对应一个训练周期。
3. `model.train()`: 这行代码将模型设置为训练模式。在某些模型中,训练模式和评估模式(例如dropout和batch normalization)的行为可能不同。
4. `for batch in train_loader:`: 这行代码开始了一个内部循环,每次迭代处理一个批次的数据。`train_loader`是之前创建的`BucketIterator`对象,它提供了批量数据。
5. `text, text_lengths = batch.text`: 这行代码从批处理数据中提取文本数据和文本长度。`batch.text`是一个元组,第一个元素是文本数据,第二个元素是文本长度。
6. `label = batch.label`: 这行代码从批处理数据中提取标签数据。
7. `optimizer.zero_grad()`: 这行代码清空了模型的梯度。在PyTorch中,梯度是累积的,因此在每次反向传播之前需要清空。
8. `predictions = model(text, text_lengths).squeeze(1)`: 这行代码通过模型进行前向传播,得到预测结果。`squeeze(1)`操作用于减少一个维度,因为输出可能是批大小x序列长度x1的形式,而我们需要批大小x序列长度的形式。
9. `loss = criterion(predictions, label)`: 这行代码计算了预测结果和真实标签之间的损失。
10. `loss.backward()`: 这行代码进行了反向传播,计算了模型参数的梯度。
11. `optimizer.step()`: 这行代码更新了模型的参数,即根据计算出的梯度进行一步优化。
总结来说,这段代码通过多个周期训练了一个RNN模型。在每个周期中,它遍历训练数据集的每个批次,进行前向传播、计算损失、反向传播和参数更新。
"""
# 训练模型
num_epochs = 5

for epoch in range(num_epochs):
    model.train()
    for batch in train_loader:
        text, text_lengths = batch.text
        label = batch.label
        optimizer.zero_grad()
        predictions = model(text, text_lengths).squeeze(1)
        loss = criterion(predictions, label)
        loss.backward()
        optimizer.step()

"""
这段代码是在评估一个训练好的循环神经网络(RNN)模型在测试集上的性能。下面是代码的详细解释:
1. `model.eval()`: 这行代码将模型设置为评估模式。在某些模型中,评估模式与训练模式(例如dropout和batch normalization)的行为可能不同。在评估模式下,模型不会更新权重。
2. `correct = 0`: 这行代码初始化了正确预测的数量。
3. `total = 0`: 这行代码初始化了总样本数量。
4. `with torch.no_grad():`: 这行代码开始了一个上下文,在这个上下文中,所有的张量操作都不会计算梯度。由于我们是在评估模型,不需要进行梯度计算,这样可以减少计算量。
5. `for batch in test_loader:`: 这行代码开始了一个循环,每次迭代处理测试数据集中的一个批次。
6. `text, text_lengths = batch.text`: 这行代码从批处理数据中提取文本数据和文本长度。
7. `label = batch.label`: 这行代码从批处理数据中提取标签数据。
8. `predictions = model(text, text_lengths).squeeze(1)`: 这行代码通过模型进行前向传播,得到预测结果。`squeeze(1)`操作用于减少一个维度,使得预测结果的形状与标签的形状一致。
9. `predicted = torch.round(torch.sigmoid(predictions))`: 这行代码首先通过`torch.sigmoid`函数将预测结果转换为概率值(范围在0到1之间),然后通过`torch.round`函数将概率值四舍五入为0或1,得到最终的预测类别。
10. `total += label.size(0)`: 这行代码更新总样本数量,`label.size(0)`返回当前批次中标签的数量。
11. `correct += (predicted == label).sum().item()`: 这行代码计算当前批次中正确预测的样本数量,并累加到`correct`变量中。`(predicted == label)`比较预测结果和真实标签,得到一个布尔张量,`sum().item()`将其中的True值(即正确预测的样本)累加为整数。
总结来说,这段代码在测试数据集上评估了模型的性能,通过计算正确预测的样本数量与总样本数量的比例,可以得到模型的准确率。
"""
# 评估模型
model.eval()
correct = 0
total = 0
with torch.no_grad():
    for batch in test_loader:
        text, text_lengths = batch.text
        label = batch.label
        predictions = model(text, text_lengths).squeeze(1)
        predicted = torch.round(torch.sigmoid(predictions))
        total += label.size(0)
        correct += (predicted == label).sum().item()

print(f'Accuracy of the network on the test texts: {100 * correct / total}%')

标签:NLP,RNN,dim,text,代码,batch,附件,文本,模型
From: https://www.cnblogs.com/zjw-lxj/p/18143463

相关文章

  • 基于RNN的NLP学习(四)
    继续按照第一节的规划,这节我们来了解深度学习和神经网络基础:1.学习神经网络的基本概念,包括神经元、激活函数、损失函数、反向传播等。我搜索了一下相关资料,发现网上关于神经网络的基本概念大多都晦涩难懂,很难不使我们对神经网络的学习望而却步,相对于这些晦涩难懂的概念,我写了自......
  • 基于RNN的NLP学习(二)
    首先,根据上一节说的,我对学习基于RNN的NLP有了一个大致的规划,现在我将从第一节开始学习:1.复习Python基础:确保你对Python的基础语法、数据结构(如列表、字典、集合)、控制流(如循环、条件语句)、函数和类有扎实的理解。学习使用Python的标准库,特别是与数据处理相关的库,如re(正则表达......
  • 基于RNN的NLP学习(一)
    目前从事RPA自动化机器人这方面的工作,今天了解到可以通过AI+RPA实现RPA的进阶,能够使RPA工作流程更简单完善,所以从今天开始学习基于RNN的NLP。个人认为要学习基于RNN的NLP,需要以下几个流程:1.复习Python基础:确保你对Python的基础语法、数据结构(如列表、字典、集合)、控制流(如循环......
  • NLP自然语言处理—主题模型LDA案例:挖掘人民网留言板文本数据|附代码数据
    全文链接:http://tecdat.cn/?p=2155最近我们被客户要求撰写关于NLP自然语言处理的研究报告,包括一些图形和统计输出。随着网民规模的不断扩大,互联网不仅是传统媒体和生活方式的补充,也是民意凸显的地带。领导干部参与网络问政的制度化正在成为一种发展趋势,这种趋势与互联网发展的时......
  • NLP自然语言处理—主题模型LDA回归可视化案例:挖掘智能门锁电商评价数据
    全文链接:http://tecdat.cn/?p=2175早在1995年比尔·盖茨就在《未来之路》里说过:未来没有配套智能家居的房子,就是毛坯房。现在人们生活越来越便捷,人们也更加倾向于智能化家居,当你还在纠结“人工智能”安利值不值得吃,最近不少朋友家里又出现智能门锁,相比传统门锁来说,究竟能有多智能......
  • 深度学习-nlp-NLP之sequence2sequence--73
    目录1.sequence2sequence任务特点2.编码器与解码器参考:https://zhuanlan.zhihu.com/p/38816145sequence2sequence模型发展到今天,根据不同任务有着不同的变体。了解了最基本的框架之后,再看别的模型就没有太大问题了。1.sequence2sequence任务特点输入输出时不定长的。比......
  • 深度学习-nlp-循环神经网络RNN--69
    目录1.概述2.RNN的模型参考:https://zhuanlan.zhihu.com/p/308449051.概述输出会反馈到输入的神经网络:循环神经网络(RecurrentNeuralNetworks,以下简称RNN),它广泛的用于自然语言处理中的语音识别,手写书别以及机器翻译等领域。在前面讲到的DNN和CNN中,训练样本的输入和输出......
  • Teamcenter 流程配置实现《部分发布功能附件》
    Teamcenter流程实现部分发布附件功能效果配置EPM-remove-objects描述从工作流程中移除指定的目标或引用对象。该处理程序可以使用一组参数来定义要移除或保留的对象,也可以使用值列表(LOV)来定义要移除的对象类型列表。-include_replica参数会保留或移除副本建议目标......
  • NLP简单项目实战——ChatBOT(二)
    二、Seq2Seq(一)Seq2Seq原理        Seq2seq模型中的encoder接收一个长度为M的序列,得到1个contextvector,之后decoder把这一个contextvector转化为长度为N的序列作为输出,从而构成一个MtoN的模型,能够处理很多不定长输入输出的问题(二)Seq2Seq实现    1.实现......
  • NLP学习路线指南总结
    当然可以,以下是一份较为详细的NLP学习路线指南,帮助你逐步掌握自然语言处理的核心技术和应用。一、基础知识与技能语言学基础:语言学基本概念:语音、语法、语义等。语言的层次与分类:语音学、音系学、句法学、语义学等。编程基础:掌握Python编程语言基础,包括变量、数据类......