哈尔滨做设计和网站的公司,优化二十条措施建议,定制购物平台,网站可以制作ios本文参考
PyTorch深度学习项目实战100例
https://weibaohang.blog.csdn.net/article/details/127154284?spm1001.2014.3001.5501 文章目录 本文参考任务介绍做数据的导入 环境介绍导入必要的包介绍torchnet和keras做数据的导入给必要的参数命名加载文本数据数据前处理模型训…本文参考
PyTorch深度学习项目实战100例
https://weibaohang.blog.csdn.net/article/details/127154284?spm1001.2014.3001.5501 文章目录 本文参考任务介绍做数据的导入 环境介绍导入必要的包介绍torchnet和keras做数据的导入给必要的参数命名加载文本数据数据前处理模型训练验证 任务介绍
基于PyTorch使用LSTM实现新闻文本分类任务的概况如下
任务描述新闻文本分类是一种常见的自然语言处理任务旨在将新闻文章分为不同的类别如政治、体育、科技等。
方法使用深度学习模型中的LSTM长短时记忆网络来处理文本序列数据。LSTM能够捕获文本中的长期依赖关系适应不定长文本自动提取特征适应多类别分类并在大型数据集上表现出色。
做数据的导入
数据代码 https://download.csdn.net/download/weixin_55982578/88323618?spm1001.2014.3001.5503
环境介绍
通俗的说 直接白嫖 Google colab
优雅的说 Google ColabColaboratory是一种基于云的免费Jupyter笔记本环境具有以下优点和好处
免费使用Colab提供免费的GPU和TPUTensor Processing Unit资源使用户能够免费运行深度学习和机器学习任务而无需担心硬件成本。 Google ColabColaboratory是一种基于云的免费Jupyter笔记本环境具有以下优点和好处
免费使用Colab提供免费的GPU和TPUTensor Processing Unit资源使用户能够免费运行深度学习和机器学习任务而无需担心硬件成本。
导入必要的包
介绍torchnet和keras
Torchnet 是一个轻量级框架旨在为 PyTorch 提供一些抽象和实用工具以简化常见的深度学习研究任务。Torchnet 的设计是模块化和扩展性的这使得研究者可以更轻松地尝试新的思路和方法。
Keras 是一个开源深度学习框架最初由François Chollet创建并维护。它是一个高级神经网络API旨在使深度学习模型的设计和训练变得简单而快速
!pip install torchnet
!pip install kerasimport pickle
import numpy as np
import pandas as pd
import torch
import torch.nn as nn
from tensorflow.keras.preprocessing.sequence import pad_sequences
from sklearn.model_selection import train_test_split
from torch.utils.data import TensorDataset
from torch import optim
from torchnet import meter
from tqdm import tqdm做数据的导入
数据代码
类别
# {0: 法治,
# 1: 国际,
# 2: 国内,
# 3: 健康,
# 4: 教育,
# 5: 经济,
# 6: 军事,
# 7: 科技,
# 8: 农经,
# 9: 三农,
# 10: 人物,
# 11: 社会,
# 12: 生活,
# 13: 书画,
# 14: 文娱}给必要的参数命名
# config file
# 模型输入参数需要自己根据需要调整
num_layers 1 # LSTM的层数
hidden_dim 100 # LSTM中的隐层大小
epochs 50 # 迭代次数
batch_size 32 # 每个批次样本大小
embedding_dim 15 # 每个字形成的嵌入向量大小
output_dim 15 # 输出维度因为是二分类
lr 0.01 # 学习率
import torch# 检查是否有可用的GPU
device torch.device(cuda)
file_path ./news.csv # 数据路径
input_shape 80 # 每句话的词的个数如果不够需要使用0进行填充加载文本数据 # 加载文本数据
def load_data(file_path, input_shape20):df pd.read_csv(file_path, encodinggbk)# 标签及词汇表labels, vocabulary list(df[label].unique()), list(df[brief].unique())# 构造字符级别的特征string for word in vocabulary:string word# 所有的词汇表vocabulary set(string)# word2idx 将字映射为索引 你:0word2idx {word: i 1 for i, word in enumerate(vocabulary)}with open(word2idx.pk, wb) as f:pickle.dump(word2idx, f)# idx2word 将索引映射为字 0:你idx2word {i 1: word for i, word in enumerate(vocabulary)}with open(idx2word.pk, wb) as f:pickle.dump(idx2word, f)# label2idx 将正反面映射为0和1 法治:0label2idx {label: i for i, label in enumerate(labels)}with open(label2idx.pk, wb) as f:pickle.dump(label2idx, f)# idx2label 将0和1映射为正反面 0:法治idx2label {i: labels for i, labels in enumerate(labels)}with open(idx2label.pk, wb) as f:pickle.dump(idx2label, f)# 训练数据中所有词的个数vocab_size len(word2idx.keys()) # 词汇表大小# 标签类别分别为法治、健康等label_size len(label2idx.keys()) # 标签类别数量# 序列填充按input_shape填充长度不足的按0补充# 将一句话映射成对应的索引 [0,24,63...]x [[word2idx[word] for word in sent] for sent in df[brief]]# 如果长度不够input_shape使用0进行填充x pad_sequences(maxleninput_shape, sequencesx, paddingpost, value0)# 形成标签0和1y [[label2idx[sent]] for sent in df[label]]# y [np_utils.to_categorical(label, num_classeslabel_size) for label in y]y np.array(y)return x, y, idx2label, vocab_size, label_size, idx2word读取数据返回参数
变量名描述x包含了填充后的文本数据字符索引的序列y包含了标签数据idx2label用于将模型的输出索引映射回标签vocab_size存储词汇表大小label_size存储标签类别数量idx2word用于将字符索引映射回字符
生成
字典名称描述word2idx字符映射为索引例如 ‘你’ 映射为 0idx2word索引映射回字符例如 0 映射回 ‘你’label2idx标签映射为索引例如 ‘法治’ 映射为 0idx2label索引映射回标签例如 0 映射回 ‘法治’
代码里面提供了可视化的方法
创建LSTM 网路结构
LSTMLong Short-Term Memory是一种循环神经网络Recurrent Neural NetworkRNN的变种它在处理序列数据时具有很好的性能特别是在长序列上能够更好地捕捉长期依赖关系。下面是关于LSTM网络结构的说明
背景LSTM是为了解决传统RNN中的梯度消失和梯度爆炸问题而提出的。它引入了特殊的记忆单元来维护和控制信息的流动以更好地捕捉序列数据中的长期依赖关系。
LSTM单元LSTM网络的基本构建单元是LSTM单元。每个LSTM单元包括以下组件
输入门Input Gate控制新信息的输入。遗忘门Forget Gate控制过去信息的遗忘。输出门Output Gate控制输出的生成。细胞状态Cell State用于维护长期依赖关系的记忆。
记忆细胞LSTM单元内部的细胞状态是其核心。它可以看作一个传送带可以在不同时间步骤上添加或删除信息。通过输入门、遗忘门和输出门来控制信息的读取、写入和遗忘以保持对序列中重要信息的长期记忆。
输入门输入门决定了在当前时间步骤中新的输入信息中哪些部分将会更新细胞状态。输入门通常由一个Sigmoid激活函数和一个tanh激活函数组成用于产生0到1之间的权重和-1到1之间的新候选值。
遗忘门遗忘门决定了哪些信息应该从细胞状态中丢弃。它使用Sigmoid激活函数来产生0到1之间的权重控制细胞状态中哪些信息应该保留。
输出门输出门决定了基于当前细胞状态和输入信息LSTM单元应该输出什么。它使用Sigmoid激活函数来确定输出的哪些部分应该激活并使用tanh激活函数来生成可能的输出值。
# 定义网络结构
class LSTM(nn.Module):def __init__(self, vocab_size, hidden_dim, num_layers, embedding_dim, output_dim):super(LSTM, self).__init__()self.hidden_dim hidden_dim # 隐层大小self.num_layers num_layers # LSTM层数# 嵌入层会对所有词形成一个连续型嵌入向量该向量的维度为embedding_dim# 然后利用这个向量来表示该字而不是用索引继续表示self.embeddings nn.Embedding(vocab_size 1, embedding_dim)# 定义LSTM层第一个参数为每个时间步的特征大小这里就是每个字的维度# 第二个参数为隐层大小# 第三个参数为LSTM的层数self.lstm nn.LSTM(embedding_dim, hidden_dim, num_layers)# 利用全连接层将其映射为2维即正反面的概率self.fc nn.Linear(hidden_dim, output_dim)def forward(self, x):# 1.首先形成嵌入向量embeds self.embeddings(x)# 2.将嵌入向量导入到LSTM层output, (h_n, c_n) self.lstm(embeds)# 获取输出的形状timestep, batch_size, hidden_dim output.shape# 3.将其导入全连接层output output.reshape(-1, hidden_dim)output self.fc(output) # 形状为batch_size * timestep, 15# 重新调整输出的形状使其变为 timestep x batch_size x output_dimoutput output.reshape(timestep, batch_size, -1)# 返回最后一个时间片的输出维度为 batch_size x output_dimreturn output[-1]
数据前处理
# 1.获取训练数据
x, y, idx2label, vocab_size, label_size, idx2word load_data(file_path, input_shape)# 2.划分训练、测试数据
x_train, x_test, y_train, y_test train_test_split(x, y, test_size0.1, random_state42)# 3.将numpy转成tensor
x_train torch.from_numpy(x_train).to(torch.int32)
y_train torch.from_numpy(y_train).to(torch.float32)
x_test torch.from_numpy(x_test).to(torch.int32)
y_test torch.from_numpy(y_test).to(torch.float32)# 将训练数据和标签移到GPU上加速
x_train x_train.to(cuda:0)
y_train y_train.to(cuda:0)
x_test x_test.to(cuda:0)
y_test y_test.to(cuda:0)使用torch中的Dataloader的方法
# 4.形成训练数据集
train_data TensorDataset(x_train, y_train)
test_data TensorDataset(x_test, y_test)# 5.将数据加载成迭代器
train_loader torch.utils.data.DataLoader(train_data,batch_size,True)test_loader torch.utils.data.DataLoader(test_data,batch_size,False)模型训练
# 6.模型训练
model LSTM(vocab_sizevocab_size, hidden_dimhidden_dim, num_layersnum_layers,embedding_dimembedding_dim, output_dimoutput_dim)Configimizer optim.Adam(model.parameters(), lrlr) # 优化器
criterion nn.CrossEntropyLoss() # 多分类损失函数model.to(device)
loss_meter meter.AverageValueMeter()best_acc 0 # 保存最好准确率
best_model None # 保存对应最好准确率的模型参数for epoch in range(epochs):model.train() # 开启训练模式epoch_acc 0 # 每个epoch的准确率epoch_acc_count 0 # 每个epoch训练的样本数train_count 0 # 用于计算总的样本数方便求准确率loss_meter.reset()train_bar tqdm(train_loader) # 形成进度条for data in train_bar:x_train, y_train data # 解包迭代器中的X和Yx_input x_train.long().transpose(1, 0).contiguous()x_input x_input.to(device)Configimizer.zero_grad()# 形成预测结果output_ model(x_input).to(device)# 计算损失loss criterion(output_, y_train.long().view(-1))loss.backward()Configimizer.step()loss_meter.add(loss.item())# 计算每个epoch正确的个数epoch_acc_count (output_.argmax(axis1) y_train.view(-1)).sum()train_count len(x_train)# 每个epoch对应的准确率epoch_acc epoch_acc_count / train_count# 打印信息print(【EPOCH: 】%s % str(epoch 1))print(训练损失为%s % (str(loss_meter.mean)))print(训练精度为%s % (str(epoch_acc.item() * 100)[:5]) %)# 保存模型及相关信息if epoch_acc best_acc:best_acc epoch_accbest_model model.state_dict()# 在训练结束保存最优的模型参数if epoch epochs - 1:# 保存模型torch.save(best_model, ./best_model.pkl)# 打印测试集精度
test_accuracy (model(x_test.long().transpose(1, 0).contiguous()).argmax(axis1) y_test.view(-1)).sum() / len(y_test)
print(【训练精度为】%s % (str(test_accuracy.item() * 100)[:5]) %)验证 # 导入字典用于形成编码
with open(word2idx.pk, rb) as f:word2idx pickle.load(f)
with open(label2idx.pk, rb) as f:label2idx pickle.load(f)
with open(idx2word.pk, rb) as f:idx2word pickle.load(f)
with open(idx2label.pk, rb) as f:idx2label pickle.load(f)try:# 数据预处理input_shape 80 # 序列长度就是时间步大小也就是这里的每句话中的词的个数# 用于测试的话sent 陈金英一位家住浙江丽水的耄耋老人。今年这个年陈金英过得格外舒心因为春节前她耗费10年凭借自己的努力不拖不欠终于还清了所有欠款。# 将对应的字转化为相应的序号x [[word2idx[word] for word in sent]]# 如果长度不够180使用0进行填充x pad_sequences(maxleninput_shape, sequencesx, paddingpost, value0)x torch.from_numpy(x)# 加载模型model_path ./best_model.pklmodel LSTM(vocab_sizevocab_size, hidden_dimhidden_dim, num_layersnum_layers,embedding_dimembedding_dim, output_dimoutput_dim)model.load_state_dict(torch.load(model_path, cpu))# 模型预测注意输入的数据第一个input_shape,就是180y_pred model(x.long().transpose(1, 0))print(输入语句: %s % sent)print(新闻分类结果: %s % idx2label[y_pred.argmax().item()])except KeyError as err:print(您输入的句子有汉字不在词汇表中请重新输入)print(不在词汇表中的单词为%s. % err)
弄成函数好调用
def classify_news_sentiment(sent):# 导入字典用于形成编码with open(word2idx.pk, rb) as f:word2idx pickle.load(f)with open(label2idx.pk, rb) as f:label2idx pickle.load(f)with open(idx2word.pk, rb) as f:idx2word pickle.load(f)with open(idx2label.pk, rb) as f:idx2label pickle.load(f)try:# 数据预处理input_shape 80 # 序列长度就是时间步大小也就是这里的每句话中的词的个数# 将对应的字转化为相应的序号x [[word2idx[word] for word in sent]]# 如果长度不够180使用0进行填充x pad_sequences(maxleninput_shape, sequencesx, paddingpost, value0)x torch.from_numpy(x)# 加载模型model_path ./best_model.pklmodel LSTM(vocab_sizevocab_size, hidden_dimhidden_dim, num_layersnum_layers,embedding_dimembedding_dim, output_dimoutput_dim)model.load_state_dict(torch.load(model_path, cpu))# 模型预测注意输入的数据第一个input_shape,就是180y_pred model(x.long().transpose(1, 0))result_label idx2label[y_pred.argmax().item()]return result_labelexcept KeyError as err:return f您输入的句子有汉字不在词汇表中请重新输入\n不在词汇表中的单词为{err}
测试
sent 陈金英一位家住浙江丽水的耄耋老人。今年这个年陈金英过得格外舒心因为春节前她耗费10年凭借自己的努力不拖不欠终于还清了所有欠款。
classify_news_sentiment(sent)结果
人物