做智能网站软件,你知道的在线视频观看的,搭建网站硬件要求,建立一个企业网站#x1f368; 本文为#x1f517;365天深度学习训练营 中的学习记录博客#x1f356; 原作者#xff1a;K同学啊 目录 任务描述步骤环境设置数据准备模型设计模型训练模型效果展示 总结与心得体会 任务描述
在上周的任务中#xff0c;我们使用torchtext下载了托管的英文的… 本文为365天深度学习训练营 中的学习记录博客 原作者K同学啊 目录 任务描述步骤环境设置数据准备模型设计模型训练模型效果展示 总结与心得体会 任务描述
在上周的任务中我们使用torchtext下载了托管的英文的AG News数据集 进行了分类任务。本周我们来对中文的自定义数据集来进行分类任务。
自定义数据集的格式是csv格式我们先用pandas进行读取创建数据集对象。然后后面的步骤就和上周基本上一致了。
步骤
环境设置
import torch
import warningswarnings.filterwarnings(ignore) # 忽略警告# 创建全局设备对象
device torch.device(cuda if torch.cuda.is_available() else cpu)
device数据准备
使用pandas读取数据
import pandas as pd
train_data pd.read_csv(train.csv, sep\t, headerNone)
train_data.head()可以看到数据有两列第一列是文字内容第二列是所属的标签。
接下来编写一个迭代器函数每次迭代返回一对内容和标签
def custom_data_iter(texts, labels):for x, y in zip(texts, labels):yield x, y
train_iter custom_data_iter(train_data[0].values[:], train_data[1].values[:])然后创建词典使用torchtext中的build_vocab_from_iterator工具函数
from torchtext.vocab import build_vocab_from_iterator
import jieba# 使用jieba库来做分词器
tokenizer jieba.lcut # lcut直接返回列表, cut 返回一个迭代器# 编写一个迭代函数每次返回一句内容的分词结果
def yield_tokens(data_iter):for text, _ in data_iter: # 每次返回一句内容和对应标签yield tokenizer(text) # 返回该句内容的分词列表# 创建词典
vocab build_vocab_from_iterator(yield_tokens(train_iter), specials[unk])
vocab.set_default_index(vocab[unk])# 测试词典
vocab([我, 想, 看, 和平, 精英, 上, 战神, 必备, 技巧, 的, 游戏, 视频])获取所有的标签名
label_name list(set(train_data[1].values[:]))
print(label_name)编写函数将内容和标签分别转换成数值
text_pipeline lambda x: vocab(tokenizer(x))
label_pipeline lambda x: label_name.index(x)print(text_pipeline(我想看和平精英上战神必备技巧的游戏视频))
print(label_pipeline(Video-Play))编写文本的批处理函数用于数据集与模型之间将一个批次的文本数据转换为数值还需要生成EmbeddingBag输入时的offsets参数。
from torch.utils.data import DataLoaderdef collate_batch(batch):label_list, text_list, offsets [], [], [0]for (_text, _label) in batch:# 标签列表label_list.append(label_pipeline(_label))# 文本列表processed_text torch.tensor(text_pipeline(_text), dtypetorch.int64)text_list.append(processed_text)# 偏移列表offsets.append(len(processed_text))label_list torch.tensor(label_list, dtypetorch.int64)text_list torch.cat(text_list)offsets torch.tensor(offsets[:-1]).cumsum(dim0)return text_list.to(device), label_list.to(device), offsets.to(device)dataloader DataLoader(train_iter, batch_size8, shuffleFalse, collate_fncollate_batch)模型设计
和上节一样一个EmbeddingBag层跟着一个全连接层就可以了
from torch import nnclass TextClassificationModel(nn.Module):# 参数随后设置def __init__(self, vocab_size, embed_dim, num_classes):super().__init__()self.embedding nn.EmbeddingBag(vocab_size, embed_dim, sparseFalse)self.fc nn.Linear(embed_dim, num_classes)self.init_weights()# 自定义的权重初始化操作def init_weights(self):initrange 0.5self.embedding.weight.data.uniform_(-initrange, initrange)self.fc.weight.data.uniform_(-initrange, initrange)self.fc.bias.data.zero_()# 向前传播def forward(self, text, offsets):embedded self.embedding(text, offsets)return self.fc(embedded)创建模型对象
num_classes len(label_name) # 分类数量
vocab_size len(vocab) # 词典大小
embedding_size 64 # 嵌入向量的维度
model TextClassificationModel(vocab_size, embedding_size, num_classes).to(device)
model可以看到这个模型简单的很。
模型训练
首先编写训练和评估函数
def train(dataloader):model.train()total_acc, train_loss, total_count 0, 0, 0log_interval 50start_time time.time()for idx, (text, label, offsets) in enumerate(dataloader):predicted_label model(text, offsets)optimizer.zero_grad()loss criterion(predicted_label, label)loss.backward()nn.utils.clip_grad_norm_(model.parameters(), 0.1) #梯度裁剪optimizer.step()total_acc (predicted_label.argmax(1) label).sum().item()train_loss loss.item()total_count label.size(0)if idx % log_interval 0 and idx 0:elapsed time.time() - start_timeprint(| epoch {:1d} | {:4d}/{:4d} batches | train_acc {:4.3f} train_loss {:4.5f}.format(epoch, idx, len(dataloader), total_acc/total_count, train_loss, total_count))total_acc, train_loss, total_count 0, 0, 0start_time time.time()def evaluate(dataloader):model.eval()total_acc, train_loss, total_count 0, 0, 0with torch.no_grad():for idx, (text, label, offsets) in enumerate(dataloader):predicted_label model(text, offsets)loss criterion(predicted_label, label)total_acc (predicted_label.argmax(1) label).sum().item()train_loss loss.item()total_count label.size(0)return total_acc/total_count, train_loss/total_count开始训练
from torch.utils.data import random_split
from torchtext.data.functional import to_map_style_dataset# 迭代次数
EPOCHS 20
# 学习率
LR 5
# 批次大小
BATCH_SIZE 64criterion nn.CrossEntropyLoss()
optimizer torch.optim.SGD(model.parameters(), lrLR)
scheduler torch.optim.lr_scheduler.StepLR(optimizer, 1.0, gamma0.1)total_accu None
train_iter custom_data_iter(train_data[0].values[:], train_data[1].values[:])
train_dataset to_map_style_dataset(train_iter)train_size int(len(train_dataset)*0.8)
split_train_, split_valid_ random_split(train_dataset, [train_size, len(train_dataset) - train_size])train_dataloader DataLoader(split_train_, batch_sizeBATCH_SIZE, shuffleTrue, collate_fncollate_batch)
valid_dataloader DataLoader(split_valid_, batch_sizeBATCH_SIZE, shuffleTrue, collate_fncollate_batch)for epoch in range(1, EPOCHS1):epoch_start_time time.time()train(train_dataloader)val_acc, val_loss evaluate(valid_dataloader)lr optimizer.state_dict()[param_groups][0][lr]if total_accu is not None and total_accu val_acc:scheduler.step()else:total_accu val_accprint(-*69)print(| epoch {:1d} | time: {:4.2f}s | valid_acc {:4.3f} valid_loss {:4.3f} | lr {:4.6f}.format(epoch, time.time() - epoch_start_time, val_acc, val_loss, lr))print(-*69)训练结束后打印一下模型的准确度
model model.to(device)
test_acc, test_loss evaluate(valid_dataloader)
print(模型准确率为: {:5.4f}.format(test_acc))模型效果展示
自己写一句话让模型跑一下看看效果
def predict(text, text_pipeline):with torch.no_grad():text torch.tensor(text_pipeline(text))output model(text, torch.tensor([0]))return output.argmax(1).item()ex_text_str 不要让一个男人听懂《水星记》# 切换成CPU推理
model model.to(cpu)
print(文本的分类是: %s % label_name[predict(ex_text_str, text_pipeline)])总结与心得体会
通过测试发现这个模型的效果还是不错的。大部分的句子可以给出正确的分类。和上节相比中文数据集的文本分类任务和英文数据集的文本分类主要差异在tokenizer分词器上。英文的分词非常简单英文的词之间天然有间隔所以可以直接使用标点和空格来分割。中文就不太一样中文需要一个好的断句工具才行jieba库就是这么一个工具。在大部分的中文自然语言处理任务中都可以看到它的身影。我在想是不是可以直接使用深度学习来进行分词来达到更好的效果或者直接使用大语言模型经过Prompt直接变成分词工具来使用只不过成本太高了希望有时间可以尝试一下。