赞
踩
定义模型:使用RNNClassifier
类定义了一个简单的循环神经网络模型,其中包括一个嵌入层、一个循环层和一个全连接层。
准备数据:定义了prepare_sequence
函数,将文本数据转换为模型可接受的张量形式,并构建了单词到索引的映射word_to_ix
和标签到索引的映射label_to_ix
。
定义超参数:定义了嵌入维度、隐藏状态维度、词汇表大小和输出类别数等超参数。
实例化模型、损失函数和优化器:创建了模型实例、交叉熵损失函数实例和随机梯度下降(SGD)优化器实例。
训练模型:使用双重循环进行了模型训练,外部循环控制训练轮数,内部循环遍历训练数据并更新模型参数。
测试模型:使用训练好的模型对训练数据进行了简单的测试,输出了每个句子的情感分类结果。
-
- class RNNClassifier(nn.Module):
- def __init__(self, input_size, hidden_size, output_size=2):
- super(RNNClassifier, self).__init__()
- self.hidden_size = hidden_size
- self.embedding = nn.Embedding(input_size, hidden_size)
- self.rnn = nn.RNN(hidden_size, hidden_size, batch_first=True)
- self.fc = nn.Linear(hidden_size, output_size)
-
- def forward(self, input):
- embedded = self.embedding(input)
- output, hidden = self.rnn(embedded.view(1, -1, self.hidden_size))
-
- # 移除维度为1的维度
- output = torch.squeeze(output, 0)
-
- output = self.fc(output)
- return output
-
-
在初始化函数__init__中,定义了模型的输入大小input_size、隐藏层大小hidden_size和输出大小output_size,默认为2。在初始化过程中调用了父类的初始化方法super(RNNClassifier, self).init(),并定义了模型的隐藏层大小、词嵌入层、RNN层和全连接层。
forward方法定义了模型的前向传播过程。首先将输入input通过词嵌入层embedding进行词嵌入操作,然后将嵌入后的数据传入RNN层中进行处理,得到输出output和隐藏状态hidden。接着通过压缩维度操作torch.squeeze去除维度为1的维度,再将输出数据传入全连接层fc中,得到最终的输出结果。最后返回输出结果output。
- def prepare_sequence(seq, to_ix):
- idxs = [to_ix[w] for w in seq]
- return torch.tensor(idxs, dtype=torch.long)
将文本序列转换为数值序列,这对于将单词输入到神经网络中是必要的,因为神经网络无法直接处理字符串或文本数据。相反,需要将这些单词转换为数字表示(索引),以便可以在嵌入层等结构中使用。
EMBEDDING_DIM = 10
:表示词嵌入的维度,即将词语映射到稠密向量空间的维度大小为10。
HIDDEN_DIM = 10
:表示RNN隐藏状态的维度,即RNN模型中隐藏状态的维度大小为10。
VOCAB_SIZE = len(word_to_ix)
:表示词汇表的大小,即训练数据中所有不同单词的数量。
OUTPUT_SIZE = len(label_to_ix)
:表示输出类别的数量,即训练数据中所有不同标签的数量。
超参数是指在训练模型之前需要设置的参数,这些参数不是通过训练数据学习得到的,而是需要手动设置的。通过定义超参数,我们可以根据具体的任务需求和实验结果来调整模型的性能和效果。
这段代码实现了迭代训练轮数,遍历训练数据,模型参数梯度清零,输入数据,获取模型输出数据,计算损失,反向传播梯度更新。
- for epoch in range(300):
- for sentence, label in training_data:
- model.zero_grad()
- inputs = prepare_sequence(sentence.split(), word_to_ix)
-
- # 扩展目标标签的维度以匹配模型输出的形状
- target = torch.tensor([label_to_ix[label]] * len(inputs), dtype=torch.long)
-
- output = model(inputs)
- loss = loss_function(output, target)
- loss.backward()
- optimizer.step()
- with torch.no_grad():
- for sentence, _ in training_data:
- inputs = prepare_sequence(sentence.split(), word_to_ix)
- output = model(inputs)
- predicted_label = torch.argmax(output).item()
- print(f"Sentence: {sentence}, Predicted Label: {'positive' if predicted_label == 0 else 'negative'}")
通过rnn模型进行情感的预测
- import torch
- import torch.nn as nn
- import torch.optim as optim
- import numpy as np
-
-
- # 构建 RNN 模型
- class RNNClassifier(nn.Module):
- def __init__(self, input_size, hidden_size, output_size=2):
- super(RNNClassifier, self).__init__()
- self.hidden_size = hidden_size
- self.embedding = nn.Embedding(input_size, hidden_size)
- self.rnn = nn.RNN(hidden_size, hidden_size, batch_first=True)
- self.fc = nn.Linear(hidden_size, output_size)
-
- def forward(self, input):
- embedded = self.embedding(input)
- output, hidden = self.rnn(embedded.view(1, -1, self.hidden_size))
-
- # 移除维度为1的维度
- output = torch.squeeze(output, 0)
-
- output = self.fc(output)
- return output
-
-
- # 准备数据
- def prepare_sequence(seq, to_ix):
- idxs = [to_ix[w] for w in seq]
- return torch.tensor(idxs, dtype=torch.long)
-
-
- training_data = [
- ("I love PyTorch", "positive"),
- ("I hate TensorFlow", "negative"),
- ("PyTorch is awesome", "positive"),
- ("TensorFlow is okay", "negative")
- ]
-
- word_to_ix = {}
- for sent, _ in training_data:
- for word in sent.split():
- if word not in word_to_ix:
- word_to_ix[word] = len(word_to_ix)
-
- label_to_ix = {"positive": 0, "negative": 1}
-
- # 定义超参数
- EMBEDDING_DIM = 10
- HIDDEN_DIM = 10
- VOCAB_SIZE = len(word_to_ix)
- OUTPUT_SIZE = len(label_to_ix)
-
- # 实例化模型、损失函数和优化器
- model = RNNClassifier(VOCAB_SIZE, HIDDEN_DIM, OUTPUT_SIZE)
- loss_function = nn.CrossEntropyLoss()
- optimizer = optim.SGD(model.parameters(), lr=0.1)
-
- # 训练模型
- # 训练模型
- for epoch in range(300):
- for sentence, label in training_data:
- model.zero_grad()
- inputs = prepare_sequence(sentence.split(), word_to_ix)
-
- # 扩展目标标签的维度以匹配模型输出的形状
- target = torch.tensor([label_to_ix[label]] * len(inputs), dtype=torch.long)
-
- output = model(inputs)
- loss = loss_function(output, target)
- loss.backward()
- optimizer.step()
-
- # 测试模型
- with torch.no_grad():
- for sentence, _ in training_data:
- inputs = prepare_sequence(sentence.split(), word_to_ix)
- output = model(inputs)
- predicted_label = torch.argmax(output).item()
- print(f"Sentence: {sentence}, Predicted Label: {'positive' if predicted_label == 0 else 'negative'}")
RNN网络会不可避免地带来一个问题:最后的输出结果受最近的输入较大,而之前较远的输入可能无法影响结果,这就是信息瓶颈问题,为了解决这个问题引入了双向LSTM。双向LSTM不仅增加了反向信息传播,而且每一轮的都会有一个输出,将这些输出进行组合之后再传给全连接层。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。