Pytorch利用GRU、LSTM实现中文情感分类

请按照以下顺序逐一了解知识点,懂的就略过。

  1. 了解LSTM、GRU结构两者还是很相像的。
    人人都能看懂的GRU

  2. 了解文本预处理过程
    中文文本预处理过程

  3. 了解词向量
    什么是词向量

  4. 了解torchtext
    TorchText之文本数据集处理

  5. 根据上面的知识处理数据集处理成如下格式:在这里插入图片描述

  6. 下载中文预训练词向量
    预训练的词向量

  7. 下面就可以对模型进行训练了
    参考代码:

## 导入本章所需要的模块
import pandas as pd
from sklearn.metrics import accuracy_score,classification_report
from torch import nn, Tensor
import torch.optim as optim
from torchtext.data import Field, Example, Dataset, Iterator

from torchtext.vocab import Vectors
import torch



## 使用torchtext库进行数据准备
# 定义文件中对文本和标签所要做的操作
print('='*10+"start"+'='*10)
device = torch.device("cuda")
BATCH_SIZE = 128
epochs = 10
## 定义文本切分方法,直接使用空格切分即可
mytokenize = lambda x: x.split()


fld_label = Field()
fld_text = Field()
# 标签字段比较简答
fld_label.sequential = False     # 这个属性默认True
fld_label.use_vocab = False      # 这个属性默认True
fld_text .tokenize = mytokenize
# 特征字段
fld_text.sequential = True     # 这个属性默认True
fld_text.use_vocab = True      # 这个属性默认True
fld_text.batch_first = True
fld_text.fix_length = 1000
fields = [("text", fld_text),("label", fld_label)]   # 两个字段
vectors = Vectors("word.iter5", "/home/featurize/data/text_data0311")
def load_data(data_file):
    data = pd.read_csv(data_file)  # csv: Comma-Separated Values,tsv: Tab-Separated Values
    examples = []
    for txt, lab in zip(data["text"], data["label"]):
        one_example = Example.fromlist([txt, lab], fields)
        examples.append(one_example)

    dataset = Dataset(examples, fields)

    it_dataset, = Iterator.splits((dataset,), batch_sizes=(BATCH_SIZE,), shuffle=True)  # 每个批次过大,GPU容易溢出
    fld_text.build_vocab(dataset, vectors=vectors)  # 见上面的词向量
    # 标签是整数,不用词向量。
    fld_label.build_vocab(dataset)
    return it_dataset

it_train = load_data("/home/featurize/data/text_data0311/train0308.csv")
it_valid = load_data("/home/featurize/data/text_data0311/test0308.csv")

class GRUNet(nn.Module):
    def __init__(self, vocab_size, embedding_dim, hidden_dim, layer_dim, output_dim):
        """
        vocab_size:词典长度
        embedding_dim:词向量的维度
        hidden_dim: GRU神经元个数
        layer_dim: GRU的层数
        output_dim:隐藏层输出的维度(分类的数量)
        """
        super(GRUNet, self).__init__()
        self.hidden_dim = hidden_dim  ## GRU神经元个数
        self.layer_dim = layer_dim  ## GRU的层数
        ## 对文本进行词项量处理
        self.embedding = nn.Embedding(vocab_size, embedding_dim)
        # LSTM + 全连接层
        self.gru = nn.LSTM(embedding_dim, hidden_dim, layer_dim,
                          batch_first=True)
        self.fc1 = nn.Sequential(
            nn.Linear(hidden_dim, hidden_dim),
            torch.nn.Dropout(0.5),
            torch.nn.ReLU(),
            nn.Linear(hidden_dim, output_dim)
        )

    def forward(self, x):
        embeds = self.embedding(x)
        r_out, h_n = self.gru(embeds, None)  # None 表示初始的 hidden state 为0
        # 选取最后一个时间点的out输出
        out = self.fc1(r_out[:, -1, :])
        return out


## 初始化网络
vocab_size = len(fld_text.vocab)
embedding_dim = vectors.dim  # 词向量的维度
# embedding_dim = 128 #  词向量的维度
hidden_dim = 128
layer_dim = 1
output_dim = 2
grumodel = GRUNet(vocab_size, embedding_dim, hidden_dim, layer_dim, output_dim)
## 将导入的词项量作为embedding.weight的初始值
grumodel.embedding.weight.data.copy_(fld_text.vocab.vectors)
grumodel.to(device)
## 将无法识别的词'<unk>', '<pad>'的向量初始化为0
UNK_IDX = fld_text.vocab.stoi[fld_text.unk_token]
PAD_IDX = fld_text.vocab.stoi[fld_text.pad_token]
grumodel.embedding.weight.data[UNK_IDX] = torch.zeros(vectors.dim)
grumodel.embedding.weight.data[PAD_IDX] = torch.zeros(vectors.dim)



evaluate_loss = []
train_loss = []

## 定义网络的训练过程函数
def train(model, traindataloader, criterion, optimizer):
    learn_rate = []
    ## 设置等间隔调整学习率,每隔step_size个epoch,学习率缩小10倍
    all_label = torch.tensor([]).to(device)
    all_pre = torch.tensor([]).to(device)
    epoch_loss = 0.0
    model.train()  ## 设置模型为训练模式
    for step, batch in enumerate(traindataloader):
        textdata, target = batch.text, batch.label
        textdata, target = textdata.to(device), target.to(device)
        out = model(textdata)
        pre_lab = torch.argmax(out, 1)  # 预测的标签
        all_label = torch.cat((all_label, target), dim=0)
        all_pre = torch.cat((all_pre, pre_lab), dim=0)
        loss = criterion(out, target)  # 计算损失函数值
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        epoch_loss += loss.item()

    train_loss.append(epoch_loss)
    print('loss:{}'.format(epoch_loss))
    print(classification_report(Tensor.cpu(all_label), Tensor.cpu(all_pre), target_names=['normal', 'depressed'], digits=4))
    ## 计算一个epoch的训练后在验证集上的损失和精度



# 定义优化器
optimizer = optim.AdamW(grumodel.parameters(), lr=0.00005)
loss_func = nn.CrossEntropyLoss()  # 交叉熵作为损失函数
## 对模型进行迭代训练,对所有的数据训练EPOCH轮


def evaluate(model, testdataloader, criterion):
    model.eval()  ## 设置模型为训练模式评估模式
    all_label = torch.tensor([]).to(device)#目标标签
    all_pre = torch.tensor([]).to(device)#预测标签
    test_loss = 0.0
    for step, batch in enumerate(testdataloader):
        textdata, target = batch.text, batch.label.view(-1)
        textdata, target = textdata.to(device), target.to(device)
        out = model(textdata)
        loss = criterion(out, target)
        test_loss += loss.item() * len(target)
        pre_lab = torch.argmax(out, 1)
        all_label = torch.cat((all_label, target), dim=0)
        all_pre = torch.cat((all_pre, pre_lab), dim=0)
    evaluate_loss.append(test_loss)
    print('loss:{}'.format(test_loss))
    print(classification_report(Tensor.cpu(all_label), Tensor.cpu(all_pre), target_names=['normal', 'depressed'], digits=4))

# 训练轮数
for i in range(epochs):
    train(grumodel, it_train, loss_func, optimizer)
    evaluate(grumodel, it_valid, loss_func)


# 将训练过程的loss显示
import matplotlib.pyplot as plt
plt.plot(range(epochs), train_loss, color='blue')
plt.scatter(range(epochs), evaluate_loss, color='red')
plt.legend(['Train Loss', 'Test Loss'], loc='upper right')
plt.xlabel('number of training examples seen')
plt.ylabel('negative log likelihood loss')
plt.show()
  • 1
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
可以使用PyTorch实现LSTM-GRU模型,以下是一个简单的示例代码: ```python import torch import torch.nn as nn # 定义LSTM-GRU模型 class LSTM_GRU(nn.Module): def __init__(self, input_size, hidden_size, num_layers, num_classes): super(LSTM_GRU, self).__init__() self.num_layers = num_layers self.hidden_size = hidden_size self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True) self.gru = nn.GRU(hidden_size, hidden_size, num_layers, batch_first=True) self.fc = nn.Linear(hidden_size, num_classes) def forward(self, x): # LSTM部分 h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(device) c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(device) out, _ = self.lstm(x, (h0, c0)) # GRU部分 out, _ = self.gru(out) # 输出部分 out = self.fc(out[:, -1, :]) return out ``` 在这个示例代码中,我们定义了一个名为`LSTM_GRU`的类,它继承了`nn.Module`类,并实现了`__init__`和`forward`方法。 在`__init__`方法中,我们定义了模型的各个层,包括一个LSTM层、一个GRU层和一个全连接层。`input_size`表示LSTM层和GRU层的输入维度,`hidden_size`表示LSTM层和GRU层的隐藏层维度,`num_layers`表示LSTM层和GRU层的层数,`num_classes`表示模型输出的类别数。 在`forward`方法中,我们首先通过LSTM层对数据进行处理,然后将输出结果作为GRU层的输入,再进行一次处理。最后通过全连接层输出结果。 需要注意的是,这个示例代码中的数据都是二维的,如果要处理更高维度的数据,需要对代码进行相应的修改。另外,还需要根据具体的任务对模型的各个参数进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ズ神马都是浮云&スタ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值