当前位置:   article > 正文

【深度学习、工程实践】深度学习进行情感分析(2)--LSTM_tabulardataset

tabulardataset

目录

一.导入需要的库

二.数据读取并查看

 三.使用word2vector生成词向量

1.先将评论转化为列表

 2.使用w2v进行词向量的生成

 3.查看生成的词向量

 四.将数据集划分为训练集和验证集

 五.借助Torchtext建立vocabulary,把每个单词映射到数字id

1.创建Filed对象

2.使用TabularDataset方法生成数据集

3.构建词表

 4.构建词嵌入矩阵

 六.创建Iterator,每个itartion都是返回一个batch的样本

七.搭建神经网络,以Bi-LSTM为例

1.参数说明

八.构建训练函数和验证函数

1.训练函数

2.验证函数

九.初始化参数

1.设置超参数

2.实例化模型

3.嵌入词向量

4.统计模型参数

5.查看模型基础架构

十.定义组件

1.定义优化器和损失函数

2.定义统计时间组件

 十一.开始训练

十二. 读入模型

1.载入模型

2.使用测试集测试结果

3.测试结果

十三.创建组件

1.建立组件将未知的句子转换成id进行预测

2.预测

3.查看预测结果


一.导入需要的库

  1. import collections
  2. import os
  3. import random
  4. import time
  5. from tqdm import tqdm
  6. import numpy as np
  7. import torch
  8. from torch import nn
  9. import torchtext.vocab as Vocab
  10. import torch.utils.data as Data
  11. import torch.nn.functional as F
  12. import matplotlib.pyplot as plt
  13. import seaborn as sns
  14. #os.environ["CUDA_VISIBLE_DEVICES"] = "6"
  15. #使用GPU运算
  16. device=torch.device("cuda:6" if torch.cuda.is_available() else "cpu")

二.数据读取并查看

  1. #读取处理好的数据
  2. import pandas as pd
  3. data=pd.read_csv("/root/Jupyter/Data_cleaning/Cleaned_data.csv")
  4. #查看数据
  5. data

 三.使用word2vector生成词向量

1.先将评论转化为列表

  1. #首先将comment_processed中的每一条评论转换为列表
  2. word_list=[str(s).split() for s in data["comment_processed"]]
  3. print(word_list)

 2.使用w2v进行词向量的生成

  1. from gensim.models import word2vec
  2. import time
  3. start = time.time()
  4. #窗口大小设置为3,词的最小出现次数为1
  5. model_w2v = word2vec.Word2Vec(word_list, window = 3, iter = 5,size=256,min_count=1)
  6. print('完成')
  7. end = time.time()
  8. print('花费时间:', end - start)
  9. print(model_w2v)
  10. #将模型保存
  11. model_w2v.save('w2v')

 3.查看生成的词向量

  1. #查看词向量的生成效果
  2. #查看词向量的维度
  3. print(len(model_w2v['手机']))
  4. print(model_w2v['手机'])

  1. #查看与手机相近的词
  2. model_w2v.most_similar(["充电"])

 

 四.将数据集划分为训练集和验证集

  • 由于现在只有split只能创建train、valid这两个分类,所以我们需要创建一个新的test set。我们可以使用.split()创建新的分类。
  • 默认的数据分割是 70、30,如果我们声明split_ratio,可以改变split之间的比例,test_size=0.2表示80%的数据是训练集,20%是验证集。
  • 我们还声明random_state这个参数,确保我们每次分割的数据集都是一样的。
  1. from sklearn.model_selection import train_test_split
  2. Temp_trin, valid_data = train_test_split(data,test_size=0.2, random_state=42) #默认split_ratio=0.7
  3. train_data,test_data = train_test_split(Temp_trin,test_size=0.2, random_state=42)
  4. train_data.to_csv("/root/Jupyter/Data_cleaning/train_data.csv",index=False,header=True,encoding="utf-8")
  5. valid_data.to_csv("/root/Jupyter/Data_cleaning/valid_data.csv",index=False,header=True,encoding="utf-8")
  6. test_data.to_csv("/root/Jupyter/Data_cleaning/test_data.csv",index=False,header=True,encoding="utf-8")

        查看划分训练集、验证集、测试集后的数据量大小

  1. print(f'Number of training examples: {len(train_data)}')
  2. print(f'Number of validation examples: {len(valid_data)}')
  3. print(f'Number of testing examples: {len(test_data)}')

 五.借助Torchtext建立vocabulary,把每个单词映射到数字id

1.创建Filed对象

  1. import torch
  2. import torchtext
  3. from torchtext.data import TabularDataset
  4. torch.backends.cudnn.deterministic = True #在程序刚开始加这条语句可以提升一点训练速度,没什么额外开销。
  5. #首先,我们要创建两个Field 对象:这两个对象包含了我们打算如何预处理文本数据的信息。
  6. #TEXT = data.Field(tokenize='spacy')#torchtext.data.Field : 用来定义字段的处理方法(文本字段,标签字段)
  7. TEXT = torchtext.data.Field(sequential=True)
  8. LABEL = torchtext.data.Field(sequential=False, dtype=torch.long, use_vocab=False)

2.使用TabularDataset方法生成数据集

  1. # 读取文件生成数据集
  2. fields = [ ('label', LABEL),('comment_processed',TEXT)]
  3. train, valid,test = TabularDataset.splits(
  4. path='/root/Jupyter/Data_cleaning/', format='csv',
  5. train='train_data.csv',
  6. validation = "valid_data.csv",
  7. test='test_data.csv',
  8. skip_header=True, fields=fields)

3.构建词表

  1. # 构建词表
  2. TEXT.build_vocab(train)
  3. # print(train[0].__dict__.keys())
  4. print(vars(train.examples[0]))
  5. print(vars(test.examples[0]))
  6. #语料库单词频率越高,索引越靠前。前两个默认为unk和pad。
  7. print(TEXT.vocab.stoi)
  8. #查看训练数据集中最常见的单词。
  9. print(TEXT.vocab.freqs.most_common(20))
  10. print(TEXT.vocab.itos[:10]) #查看TEXT单词表

 4.构建词嵌入矩阵

        将词向量和词id进行对应构建矩阵,比如手机的词id为2,在构建的矩阵中,第二行对应的就是手机的词向量。整个矩阵的大小为8491*256,代表通过建立此表一共存在8491个词id,每个词向量的维度为256。

  1. #生成词嵌入矩阵
  2. import numpy as np
  3. embedding_dic = dict(zip(model_w2v.wv.index2word, model_w2v.wv.vectors))
  4. embedding_matrix = np.zeros((len(TEXT.vocab), 256))
  5. for w, i in TEXT.vocab.stoi.items():
  6. embedding_vec = embedding_dic.get(w)
  7. if embedding_vec is not None:
  8. embedding_matrix[i] = embedding_vec
  9. print(embedding_matrix.shape)

 六.创建Iterator,每个itartion都是返回一个batch的样本

  • 最后一步数据的准备是创建iterators。每个itartion都会返回一个batch的examples。
  • 我们会使用BucketIteratorBucketIterator会把长度差不多的句子放到同一个batch中,确保每个batch中不出现太多的padding。
  1. from torchtext.data import Iterator, BucketIterator
  2. train_batch_size = 64
  3. val_batch_size = 64
  4. test_batch_size = 64
  5. #相当于把样本划分batch,只是多做了一步,把相等长度的单词尽可能的划分到一个batch,不够长的就用padding。
  6. # 同时对训练集和验证集进行迭代器构建
  7. train_iterator, valid_iterator = BucketIterator.splits(
  8. (train, valid),
  9. batch_sizes=(train_batch_size, val_batch_size),
  10. device=device,
  11. sort_key=lambda x: len(x.comment_processed),
  12. sort_within_batch=False,
  13. repeat=False)
  14. # 对测试集进行迭代器构建
  15. test_iterator = Iterator(
  16. test,
  17. batch_size=test_batch_size,
  18. device=device,
  19. sort=False,
  20. sort_within_batch=False,
  21. repeat=False)
  • 查看batch的信息。
  • 查看通过Field格式化之后的文本。
  1. for batch in train_iterator:
  2. print(batch)

{TEXT.vocab.itos[i] for i in batch.comment_processed[:,0]}

七.搭建神经网络,以Bi-LSTM为例

1.参数说明

   embedding_dim:每个单词维度
   hidden_size:隐藏层维度
   num_layers:神经网络深度,纵向深度
   bidirectional:是否双向循环

  1. import torch.nn as nn
  2. import torch.nn.functional as F
  3. class LSTMmodel(nn.Module):
  4. def __init__(self,embedding_size,hidden_size,output_size):
  5. super(LSTMmodel,self).__init__()
  6. self.embedding=nn.Embedding(len(TEXT.vocab),256)
  7. self.lstm=nn.LSTM(embedding_size,hidden_size,num_layers=2,bidirectional=True)
  8. self.fc=nn.Linear(hidden_size*2,output_size)
  9. #向前传播
  10. def forward(self,text):
  11. embedded=self.embedding(text)
  12. output,(hidden,c)=self.lstm(embedded)
  13. #hidden的维度是(num_layers * num_directions, batch, hidden_size)取最后一层的前向和后向输出,[4,64,hidden_size]
  14. h = torch.cat((hidden[-1, :, :], hidden[-2, :, :]), dim=1)
  15. #print("h",h)
  16. #print(h.shape)
  17. output=self.fc(h)
  18. return output

八.构建训练函数和验证函数

1.训练函数

  1. def train(model, iterator, optimizer, criterion):
  2. epoch_loss = 0
  3. epoch_acc = 0
  4. total_len = 0
  5. count = 0
  6. model.train() #model.train()代表了训练模式
  7. #这步一定要加,是为了区分model训练和测试的模式的。
  8. #有时候训练时会用到dropout、归一化等方法,但是测试的时候不能用dropout等方法。
  9. for batch in iterator: #iterator为train_iterator
  10. optimizer.zero_grad() #加这步防止梯度叠加
  11. predictions = model(batch.comment_processed)
  12. #print("predictions",predictions)
  13. #batch.comment_processed comment_processed
  14. loss = criterion(predictions, batch.label)
  15. epoch_loss += loss.item()
  16. loss.backward() #反向传播
  17. optimizer.step() #梯度下降
  18. epoch_acc += ((predictions.argmax(axis = 1)) == batch.label).sum().item()
  19. #(acc.item():一个batch的正确率) *batch数 = 正确数
  20. #train_iterator所有batch的正确数累加。
  21. total_len += len(batch.label)
  22. #计算train_iterator所有样本的数量
  23. count += 1
  24. print(f'训练了{count}个batch')
  25. return epoch_loss / total_len, epoch_acc / total_len
  26. #epoch_loss / total_len :train_iterator所有batch的损失
  27. #epoch_acc / total_len :train_iterator所有batch的正确率

2.验证函数

  1. def evaluate(model, iterator, criterion):
  2. epoch_loss = 0
  3. epoch_acc = 0
  4. total_len = 0
  5. count = 0
  6. model.eval()
  7. #转换成测试模式,冻结dropout层或其他层。
  8. with torch.no_grad():
  9. for batch in iterator:
  10. #iterator为valid_iterator
  11. #没有反向传播和梯度下降
  12. predictions = model(batch.comment_processed)
  13. loss = criterion(predictions, batch.label)
  14. epoch_loss += loss.item()
  15. epoch_acc += ((predictions.argmax(axis = 1)) == batch.label).sum().item()
  16. total_len += len(batch.label)
  17. count += 1
  18. model.train() #调回训练模式
  19. print(f'验证了{count}个batch')
  20. return epoch_loss / total_len, epoch_acc / total_len

九.初始化参数

1.设置超参数

  1. #设置超参数
  2. EMBEDDING_SIZE = 256
  3. HIDDEN_SIZE = 128
  4. OUTPUT_SIZE = 5

2.实例化模型

  1. #实例化模型
  2. model = LSTMmodel(embedding_size = EMBEDDING_SIZE,
  3. hidden_size = HIDDEN_SIZE,
  4. output_size = OUTPUT_SIZE,).to(device)

3.嵌入词向量

  1. #模型词向量初始化成预训练的词向量
  2. #from_munpy ndarray和tensor转换
  3. #将生成的词向量-id矩阵嵌入到我们的网络模型中
  4. model.embedding.weight.data.copy_(torch.from_numpy(embedding_matrix))[2:10]

4.统计模型参数

  1. def count_parameters(model): #统计模型参数
  2. return sum(p.numel() for p in model.parameters() if p.requires_grad)
  3. print(f'The model has {count_parameters(model):,} trainable parameters')

5.查看模型基础架构

  1. #查看模型基础架构
  2. print(model)

十.定义组件

1.定义优化器和损失函数

  1. import torch.optim as optim
  2. optimizer = optim.Adam(model.parameters()) #定义优化器
  3. criterion = nn.CrossEntropyLoss() #定义损失函数,交叉熵损失函数
  4. model = model.to(device) #送到gpu上去
  5. criterion = criterion.to(device) #送到gpu上去

2.定义统计时间组件

  1. import time
  2. def epoch_time(start_time, end_time): #查看每个epoch的时间
  3. elapsed_time = end_time - start_time
  4. elapsed_mins = int(elapsed_time / 60)
  5. elapsed_secs = int(elapsed_time - (elapsed_mins * 60))
  6. return elapsed_mins, elapsed_secs

 十一.开始训练

        定义训练10个轮次,并且保存效果最好的模型。

  1. N_EPOCHS = 10
  2. best_valid_loss = float('inf') #无穷大
  3. for epoch in tqdm(range (N_EPOCHS),desc='Processing'):
  4. start_time = time.time()
  5. train_loss, train_acc = train(model, train_iterator, optimizer, criterion)
  6. valid_loss, valid_acc = evaluate(model, valid_iterator, criterion)
  7. end_time = time.time()
  8. epoch_mins, epoch_secs = epoch_time(start_time, end_time)
  9. if valid_loss < best_valid_loss: #只要模型效果变好,就存模型
  10. best_valid_loss = valid_loss
  11. torch.save(model.state_dict(), 'Best-Checkpoint.pt')
  12. print(f'Epoch: {epoch+1:02} | Epoch Time: {epoch_mins}m {epoch_secs}s')
  13. print(f'\tTrain Loss: {train_loss:.3f} | Train Acc: {train_acc*100:.2f}%')
  14. print(f'\t Val. Loss: {valid_loss:.3f} | Val. Acc: {valid_acc*100:.2f}%')

十二. 读入模型

1.载入模型

  1. #用保存的模型参数预测数据
  2. model.load_state_dict(torch.load("Best-Checkpoint.pt"))

2.使用测试集测试结果

  1. model.load_state_dict(torch.load('Best-Checkpoint.pt'))
  2. test_loss, test_acc = evaluate(model, test_iterator, criterion)
  3. print(f'Test Loss: {test_loss:.3f} | Test Acc: {test_acc*100:.2f}%')

3.测试结果

十三.创建组件

1.建立组件将未知的句子转换成id进行预测

  1. import spacy #分词工具,跟NLTK类似
  2. nlp = spacy.load('zh_core_web_md')
  3. def predict_sentiment(sentence):
  4. tokenized = [tok.text for tok in nlp.tokenizer(sentence)]#分词
  5. indexed = [TEXT.vocab.stoi[t] for t in tokenized]
  6. #sentence的索引
  7. tensor = torch.LongTensor(indexed).to(device) #seq_len
  8. tensor = tensor.unsqueeze(1)
  9. #seq_len * batch_size1
  10. prediction = torch.sigmoid(model(tensor))
  11. #tensor与text一样的tensor
  12. #print(prediction)
  13. #转换成numpy
  14. #print(prediction.detach().numpy())
  15. #直接取出numpy中最大的对应位置作为预测值
  16. final_prediction = prediction.detach().numpy().argmax(axis = 1)
  17. #return final_prediction
  18. if final_prediction+1 >= 3:
  19. print(f'手机评论:{sentence}的评价等级为{final_prediction+1}星好评')
  20. else :
  21. print(f'手机评论:{sentence}的评价等级为{final_prediction+1}星差评')

2.预测

  1. predict_sentiment("手机不错,非常好用")
  2. predict_sentiment("手机不好用,掉电严重,并且发烫严重")

3.查看预测结果

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/576620
推荐阅读
相关标签
  

闽ICP备14008679号