0


基于Transformer(卷积神经网络、循环神经网络)的情感分类研究

Requirements:

  • Python: 3.8.5
  • PyTorch: 1.8.0
  • Transformers: 4.9.0
  • NLTK: 3.5
  • LTP: 4.0

** Model:**

Attention:

论文解读参考:

https://blog.csdn.net/Magical_Bubble/article/details/89083225

实验步骤:

1)下载VSstudio2019

注意:安装时勾选“Python开发”和“C++桌面开发”

2) 下载和安装nvidia显卡驱动

下载之后就是简单的下一步直到完成。

完成之后,在cmd中输入执行:

nvidia-smi

如果有错误:

'nvidia-smi' 不是内部或外部命令,也不是可运行的程序

或批处理文件。

把C:\Program Files\NVIDIA Corporation\NVSMI添加到环境变量的path中。再重新打开cmd窗口。

3) 下载和安装CUDA和cuDNN

安装完后,可以执行nvcc -V 来验证gpu是否可以等待应用,下图表示cuda安装好了

4) 安装Anaconda

搭建虚拟环境和pytorch软件平台


5)添加Aanaconda国内镜像配置

清华TUNA提供了 Anaconda 仓库的镜像,运行以下命令:

conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/

conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/

conda config --set show_channel_urls yes

6)建立虚拟环境,安装软件pytorch,transformer

(这个很重要,可以保证不同版本的包独立环境)

创建虚拟环境:conda create -n nlp-book python=3.8.5(虚拟环境安装不上的话:conda config --add channels conda-forge)

激活虚拟环境nlp-book,输入: conda activate nlp-book

删除虚拟环境:conda remove -n your_env_name --all

**激活虚拟环境nlp-book: **

在所创建的pytorch环境下安装pytorch, 执行命令:

(conda install pytorch=1.8 torchvision cudatoolkit=10.2 -c pytorch)

conda install pytorch=1.8.0 torchvision cudatoolkit -c pytorch(笔记本)

conda install pytorch==1.8.0 torchvision==0.9.0 torchaudio==0.8.0 cudatoolkit=11.1 -c pytorch -c conda-forge(台式机)

【注意:在虚拟环境下,安装pytorch,可能会碰到包的不兼容性,会报错

anaconda search -t conda libcublas >=11.10.1.25,<11.11.3.6

                            (and similarly for the other packages)

于是在cmd命令行,输入:

anaconda search -t conda pytorch

结果只有1.8.2版本,也就是在不同的cuda版本下,对应的pytorch库居然不一样

于是输入安装命令: conda install -c https://conda.anaconda.org/conda-forge pytorch=1.8.2

不断地报错,不断通过类似以下命令安装补全: D:\nlp-code-main\chp5> conda install -c https://conda.anaconda.org/conda-forge python_abi

之后,就可以安装pytorch。特别是之前安装的pytorch版本过高,无法兼容新的项目下的pytorch,就必须在虚拟环境下重新安装。

小结:(1)在安装pytorch曾出现多种版本大小不兼容的情况,改了很久无法纠错,于是后来重新卸载anaconda,缘由是自带的python3.5版本,无法满足后面高版本的python所需要的库,重新安装了最新版的anaconda,之后创建虚拟环境,安装pytorch都可以。

** (2)查看安装的版本,pytorch,transformers
import torch
import numpy as np
import transformers
print(torch.version)
print(transformers.version) **

接下来安装模型

conda install transformer=4.9.0

安装时报错:

缺乏镜像

执行安装命令

pip install transformers==4.9.0 -i https://pypi.doubanio.com/simple

pip install nltk==3.5 -i https://pypi.doubanio.com/simple

pip install ltp==4.0.2 -i https://pypi.doubanio.com/simple

7)进入项目所在目录

(nlp-book) D:\nlp-book-master\chp4>python transformer_sent_polarity.py

报错

   无法在线下载sentence_polarity数据,通常无法下载这个包nltk_data下的很多数据集以及xml文件。一般的方法可以自己下载放到本地目录。链接地址:GitHub - nltk/nltk_data: NLTK Data

于是改正上面报错:

解决方法:
离线下载
github:nltk_data(或pip install nltk -i https://pypi.tuna.tsinghua.edu.cn/simple)进入清华镜像安装后,也无法安装预训练的情感数据集,于是还是进入gitub下载

GitHub - nltk/nltk_data: NLTK Data,

   进入下载页面:/tree/gh-pages/packages/corpora,在corpora下面可以进行下载具体的数据集格式,

  将下载的文件中的sentence_polarity.zip放在上面报错中的目录的任意一个子目录下,程序调用时依次搜寻这些路径,一旦在某个路径下,找到数据格式,即可完成数据的加载。

   这里报错是无法加载到数据:

加载数据2023.4.7(见transformers代码)

train_data, test_data, vocab = load_sentence_polarity()

   数据包下载后,大概整个nltk_data有706兆,于是把该包放在项目所在的环境目录env下的D:\\soft\\anaconda3\\envs\\nlp-book\\nltk_data下面,之前这里通过清华镜像没有安装到位。这里有个奇怪的现象,进入包的子目录下下载sentence_polarity.zip,无法下载,但是整个包nltk_data可以全部下载到位。这个在上机的实践课上要小心一点。2023.4.7中广班

   复制包的数据后重新执行 python transformer_sent_polarity.py还是报错,类似前一个错误,无法加载数据。根据报错提示Attempted to load corpora/sentence_polarity.zip/sentence_polarity/。于是改写路径目录nltk_data/corpora/sentence_polarity

   现在可以执行了,也就是可以加载数据了。

  **8)训练,测试数据**

加载情感数据集sentence_polarity,然后分割数据集

9)结果:

Testing: 100%|██████████| 2662/2662 [00:05<00:00, 468.51it/s]
Acc: 0.68

附录:transformer情感分类代码

import math
import torch
from torch import nn, optim
from torch.nn import functional as F
from torch.utils.data import Dataset, DataLoader
from torch.nn.utils.rnn import pad_sequence, pack_padded_sequence
from collections import defaultdict
from vocab import Vocab
from utils import load_sentence_polarity, length_to_mask

tqdm是一个Pyth模块,能以进度条的方式显式迭代的进度

from tqdm.auto import tqdm

class TransformerDataset(Dataset):
def init(self, data):
self.data = data
def len(self):
return len(self.data)
def getitem(self, i):
return self.data[i]

def collate_fn(examples):
lengths = torch.tensor([len(ex[0]) for ex in examples])
inputs = [torch.tensor(ex[0]) for ex in examples]
targets = torch.tensor([ex[1] for ex in examples], dtype=torch.long)
# 对batch内的样本进行padding,使其具有相同长度
inputs = pad_sequence(inputs, batch_first=True)
return inputs, lengths, targets

class PositionalEncoding(nn.Module):
def init(self, d_model, dropout=0.1, max_len=512):
super(PositionalEncoding, self).init()

    pe = torch.zeros(max_len, d_model)
     position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
     div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))
     pe[:, 0::2] = torch.sin(position * div_term)
     pe[:, 1::2] = torch.cos(position * div_term)
     pe = pe.unsqueeze(0).transpose(0, 1)
     self.register_buffer('pe', pe)

def forward(self, x):
     x = x + self.pe[:x.size(0), :]
     return x

class Transformer(nn.Module):
def init(self, vocab_size, embedding_dim, hidden_dim, num_class,
dim_feedforward=512, num_head=2, num_layers=2, dropout=0.1, max_len=128, activation: str = "relu"):
super(Transformer, self).init()
# 词嵌入层
self.embedding_dim = embedding_dim
self.embeddings = nn.Embedding(vocab_size, embedding_dim)
self.position_embedding = PositionalEncoding(embedding_dim, dropout, max_len)
# 编码层:使用Transformer
encoder_layer = nn.TransformerEncoderLayer(hidden_dim, num_head, dim_feedforward, dropout, activation)
self.transformer = nn.TransformerEncoder(encoder_layer, num_layers)
# 输出层
self.output = nn.Linear(hidden_dim, num_class)

 def forward(self, inputs, lengths):
     inputs = torch.transpose(inputs, 0, 1)
     hidden_states = self.embeddings(inputs)
     hidden_states = self.position_embedding(hidden_states)
     attention_mask = length_to_mask(lengths) == False
     hidden_states = self.transformer(hidden_states, src_key_padding_mask=attention_mask)
     hidden_states = hidden_states[0, :, :]
     output = self.output(hidden_states)
     log_probs = F.log_softmax(output, dim=1)
     return log_probs

embedding_dim = 128
hidden_dim = 128
num_class = 2
batch_size = 32
num_epoch = 5

加载数据

train_data, test_data, vocab = load_sentence_polarity()
train_dataset = TransformerDataset(train_data)
test_dataset = TransformerDataset(test_data)
train_data_loader = DataLoader(train_dataset, batch_size=batch_size, collate_fn=collate_fn, shuffle=True)
test_data_loader = DataLoader(test_dataset, batch_size=1, collate_fn=collate_fn, shuffle=False)

加载模型

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = Transformer(len(vocab), embedding_dim, hidden_dim, num_class)
model.to(device) # 将模型加载到GPU中(如果已经正确安装)

训练过程

nll_loss = nn.NLLLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001) # 使用Adam优化器

model.train()
for epoch in range(num_epoch):
total_loss = 0
for batch in tqdm(train_data_loader, desc=f"Training Epoch {epoch}"):
inputs, lengths, targets = [x.to(device) for x in batch]
log_probs = model(inputs, lengths)
loss = nll_loss(log_probs, targets)
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_loss += loss.item()
print(f"Loss: {total_loss:.2f}")

测试过程

acc = 0
for batch in tqdm(test_data_loader, desc=f"Testing"):
inputs, lengths, targets = [x.to(device) for x in batch]
with torch.no_grad():
output = model(inputs, lengths)
acc += (output.argmax(dim=1) == targets).sum().item()

输出在测试集上的准确率

print(f"Acc: {acc / len(test_data_loader):.2f}")

项目总结:

(1)

在执行代码 python transformer_sent_polarity.py 可能会报错。

RuntimeError: Expected all tensors to be on the same device, but found at least two devices, cuda:0 and cpu!

仔细想了一下,参考了车万翔老师的建议。

在下列位置修改了代码:

def length_to_mask(lengths):
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    max_len = torch.max(lengths)**.to(device)**
    mask = torch.arange(max_len).expand(lengths.shape[0], max_len)**.to(device)**< lengths.unsqueeze(1)**.to(device)**
    return mask

目的是将torch.arrange(max_len)的设备加载到gpu。然后运行就成功了

(2) 执行lstm_postag.py 长短期记忆神经网络数据标注时会报错,length是一维的cpu设备计算的,此时必须修改代码:

for epoch in range(num_epoch):
    total_loss = 0
    for batch in tqdm(train_data_loader, desc=f"Training Epoch {epoch}"):
        inputs, lengths, targets, mask =** [x for x in batch]**
        # 因为lengths是cpu设备
     **   inputs=inputs.to(device)
        targets=targets.to(device)**

修改后,代码可以完成训练测试标注。

3)在3070显卡上通过skipgram生成word2vec, 需要十分钟。但是在笔记本上执行要6个小时。

下载修改好的代码:

(363条消息) transformer执行情感分析,CBOW,Skipgram生成词向量代码资源-CSDN文库


本文转载自: https://blog.csdn.net/zql1009/article/details/129948340
版权归原作者 雨下成一朵花 所有, 如有侵权,请联系我们删除。

“基于Transformer(卷积神经网络、循环神经网络)的情感分类研究”的评论:

还没有评论