大家好,我是Loong,今天给大家分享一个关于客户评价分类的NLP项目。这个项目,主要利用NLP技术对客户输入的评价进行分析并且进行一个简单的二分类——正向/负向。可以参考学习!
目录
前言
NLP(自然语言处理)任务是指使用计算机程序和算法来理解、解释和生成人类语言的各项任务。以下是一些常见的NLP任务:
1. 文本分类:将文本数据分配到一个或多个类别中,例如垃圾邮件检测、情感分析。
2. 情感分析:识别文本中的情感倾向,如正面、负面或中性。
3. 实体识别(NER):从文本中识别出具有特定意义的实体,如人名、地点、组织名等。
4. 词性标注:为文本中的每个单词标注正确的词性,如名词、动词、形容词等。
5. 句法分析:分析文本的句法结构,确定单词之间的关系,如主谓宾结构。
6. 机器翻译:将一种语言的文本自动翻译成另一种语言。
7. 文本摘要:从长文本中提取关键信息,生成简洁的摘要。
8. 问答系统:根据给定的问题,从一组文档中找到最合适的答案。
9. 文本生成:自动生成文本,如撰写新闻报道、生成诗歌等。
10. 对话系统:创建能够与人类进行交流的聊天机器人。
11. 语义理解:理解句子或文本的含义,而不仅仅是字面意思。
12. 语音识别:将语音信号转换为文本。
13. 关键词提取:从文本中提取出代表文档主题的关键词。
14. 文本相似度:计算两段文本之间的相似度,用于文档聚类或重复内容检测。
15. 自然语言生成(NLG):从数据生成自然语言描述,常用于报告生成。
一、下载数据集
-
注意:如果是在线下载需要科学上网(后期更新会讲到如何科学上网)
from datasets import load_dataset
# 加载 ChnSentiCorp 数据集并指定缓存目录为 /root/240620code/first_nlp_project/data/test 目录
dataset = load_dataset('seamew/ChnSentiCorp', cache_dir='/root/240620code/first_nlp_project/data/test')
二、测试数据集是否下载成功
from datasets import list_datasets, load_dataset, load_from_disk
# # 设置data_files
# data_files = {
# 'train': '/root/240620code/first_nlp_project/data/ChnSentiCorp/chn_senti_corp-train.arrow',
# 'test': '/root/240620code/first_nlp_project/data/ChnSentiCorp/chn_senti_corp-test.arrow',
# 'validation': '/root/240620code/first_nlp_project/data/ChnSentiCorp/chn_senti_corp-validation.arrow'}
# # 加载arrow数据集
# dataset = load_dataset('arrow', data_files=data_files)
# # 保存至本地
# dataset.save_to_disk('/root/240620code/first_nlp_project/datasets/chn_senti_corp')
# # 从本地加载数据集
dataset = load_from_disk("/root/240620code/first_nlp_project/datasets/ChnSentiCorp")
# 查看一下训练集
train_datas = dataset["train"]
for train_data in train_datas:
print(train_data)
三、构建模型
import torch
from transformers import BertModel
from torch import nn
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
pretrained = BertModel.from_pretrained("bert-base-chinese").to(DEVICE)
# print(pretrained)
# 定义下游任务模型
class MyModel(nn.Module):
def __init__(self):
super().__init__()
self.fc = nn.Linear(768, 2)
def forward(self, input_ids, attention_mask, token_type_ids):
with torch.no_grad():
out = pretrained(input_ids=input_ids, attention_mask=attention_mask, token_type_ids=token_type_ids)
out = self.fc(out.last_hidden_state[:, 0])
out = out.softmax(dim=1)
return out
四、加载数据集
from torch.utils.data import Dataset
from datasets import load_from_disk
class MyDataset(Dataset):
def __init__(self, split):
# 1、从huggingface官网下拉取数据集(网络好)
# self.dataset = load_dataset(path='seamew/ChnSentiCorp', split="train")
# 2、从本地加载数据集
self.dataset = load_from_disk("/root/240620code/first_nlp_project/datasets/ChnSentiCorp")
if split == "trian":
self.dataset = self.dataset["train"]
elif split == "validation":
self.dataset = self.dataset["validation"]
else:
self.dataset = self.dataset["test"]
def __len__(self):
return len(self.dataset)
def __getitem__(self, item):
text = self.dataset[item]["text"]
label = self.dataset[item]["label"]
return text, label
if __name__ == '__main__':
myDataset = MyDataset("train")
for data in myDataset:
print(data)
五、开启训练
import torch
from torch import nn
from mydata import MyDataset
from torch.utils.data import DataLoader
from net import MyModel
from transformers import AdamW, BertTokenizer
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
EPOCH = 30000
token = BertTokenizer.from_pretrained("bert-base-chinese")
def collate_fn(data):
sents = [i[0] for i in data]
label = [i[1] for i in data]
# 编码
data = token.batch_encode_plus(
batch_text_or_text_pairs = sents,
# 当句子长度大于max_length时,截断
truncation = True,
# 一律补齐到max_length长度
padding = "max_length",
max_length = 500,
return_tensors = "pt",
return_length = True
)
input_ids = data["input_ids"]
attention_mask = data["attention_mask"]
token_type_ids = data["token_type_ids"]
labels = torch.LongTensor(label)
return input_ids, attention_mask, token_type_ids, labels
# 创建数据集
train_date = MyDataset("train")
# 加载数据 drop_last:不满足要求的数据集直接丢弃 collate_fn:对加载进来的数据进行处理 -> 编码处理
train_loader = DataLoader(dataset=train_date, batch_size=32, shuffle=True, drop_last=True, collate_fn=collate_fn)
def train():
model = MyModel().to(DEVICE)
optimizer = AdamW(model.parameters(), lr=5e-4)
loss_func = nn.CrossEntropyLoss()
# 开始训练
model.train()
for epoch in range(EPOCH):
for i, (input_ids, attention_mask, token_type_ids, labels) in enumerate(train_loader):
input_ids = input_ids.to(DEVICE)
attention_mask = attention_mask.to(DEVICE)
token_type_ids = token_type_ids.to(DEVICE)
labels = labels.to(DEVICE)
out = model(input_ids, attention_mask, token_type_ids)
loss = loss_func(out, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if i % 5 == 0:
out = out.argmax(dim=1)
acc = (out == labels).sum().item() / len(labels)
print("epoch======>", epoch, i, "loss======>", loss.item(), "acc======>", acc)
torch.save(model.state_dict(), f"/root/240620code/first_nlp_project/params/{epoch}bert01.pth")
print(epoch, "参数保存成功!")
if __name__ == '__main__':
train()
# for i, (input_ids, attention_mask, token_type_ids, labels) in enumerate(train_loader):
# print(i)
# print("input_ids:", input_ids.shape)
# print("attention_mask:", attention_mask.shape)
# print("token_type_ids:", token_type_ids.shape)
# print("labels:", labels.shape)
六、测试
import torch
from torch import nn
from mydata import MyDataset
from torch.utils.data import DataLoader
from net import MyModel
from transformers import AdamW, BertTokenizer
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
token = BertTokenizer.from_pretrained("bert-base-chinese")
def collate_fn(data):
sents = [i[0] for i in data]
label = [i[1] for i in data]
# 编码
data = token.batch_encode_plus(
batch_text_or_text_pairs = sents,
# 当句子长度大于max_length时,截断
truncation = True,
# 一律补齐到max_length长度
padding = "max_length",
max_length = 500,
return_tensors = "pt",
return_length = True
)
input_ids = data["input_ids"]
attention_mask = data["attention_mask"]
token_type_ids = data["token_type_ids"]
labels = torch.LongTensor(label)
return input_ids, attention_mask, token_type_ids, labels
# 创建数据集
test_date = MyDataset("test")
# 加载数据 drop_last:不满足要求的数据集直接丢弃 collate_fn:对加载进来的数据进行处理 -> 编码处理
test_loader = DataLoader(dataset=test_date, batch_size=32, shuffle=True, drop_last=True, collate_fn=collate_fn)
def test():
model = MyModel().to(DEVICE)
model.load_state_dict(torch.load("/root/240620code/first_nlp_project/params/16bert01.pth"))
# 开始测试
model.eval()
acc = 0
total = 0
for i, (input_ids, attention_mask, token_type_ids, labels) in enumerate(test_loader):
input_ids = input_ids.to(DEVICE)
attention_mask = attention_mask.to(DEVICE)
token_type_ids = token_type_ids.to(DEVICE)
labels = labels.to(DEVICE)
out = model(input_ids, attention_mask, token_type_ids)
out = out.argmax(dim=1)
acc += (out == labels).sum().item()
total += len(labels)
print(acc / total)
if __name__ == '__main__':
test()
七、验证效果
import torch
from net import MyModel
from transformers import BertTokenizer
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
names = ["负向评价", "正向评价"]
model = MyModel().to(DEVICE)
token = BertTokenizer.from_pretrained("bert-base-chinese")
def collate_fn(data):
sents = []
sents.append(data)
# 编码
data = token.batch_encode_plus(
batch_text_or_text_pairs = sents,
# 当句子长度大于max_length时,截断
truncation = True,
# 一律补齐到max_length长度
padding = "max_length",
max_length = 500,
return_tensors = "pt",
return_length = True
)
input_ids = data["input_ids"]
attention_mask = data["attention_mask"]
token_type_ids = data["token_type_ids"]
return input_ids, attention_mask, token_type_ids
def val():
model.load_state_dict(torch.load("/root/240620code/first_nlp_project/params/16bert01.pth"))
# 开始验证
model.eval()
while True:
data = input("请输入测试数据(输入'q'退出):")
if data == "q":
print("测试结束!")
break
input_ids, attention_mask, token_type_ids = collate_fn(data=data)
input_ids = input_ids.to(DEVICE)
attention_mask = attention_mask.to(DEVICE)
token_type_ids = token_type_ids.to(DEVICE)
with torch.no_grad():
out = model(input_ids, attention_mask, token_type_ids)
out = out.argmax(dim=1)
print("模型判定:", names[out], "\n")
if __name__ == '__main__':
val()
八、结果展示
结语
本次分享就到这了,如果上面代码对您有帮助,欢迎点个赞!!!