2026/6/20 5:00:12
网站建设
项目流程
个人博客网站开发的意义,网站的想法,电子商务网站建设学什么,个人微信管理系统大家好#xff0c;我是锋哥。最近发布一条【AI大模型舆情分析】微博舆情分析可视化系统(pytorch2基于BERT大模型训练微调flaskpandasecharts#xff09;高级实战。分上下节。实战简介#xff1a;前面的2026版【NLP舆情分析】基于python微博舆情分析可视化系统(flaskpandasec…大家好我是锋哥。最近发布一条【AI大模型舆情分析】微博舆情分析可视化系统(pytorch2基于BERT大模型训练微调flaskpandasecharts高级实战。分上下节。实战简介前面的2026版【NLP舆情分析】基于python微博舆情分析可视化系统(flaskpandasecharts爬虫) 二次开发前面课程舆情分析用得是snowNLP我们现在改用基于BERT开源大模型微调来实现舆情分析提高舆情分析的准确率。重点讲解基本BERT大模型实现舆情分析二分类问题。视频教程和源码领取链接https://pan.baidu.com/s/1_NzaNr0Wln6kv1rdiQnUTg提取码0000BERT大模型进行微调训练实现舆情分析功能基于BERT模型进行增量微调训练1自定义数据集我们首先要安装下datasets库。pip install datasets -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com然后我们准备下训练和测试数据。8千多条的训练集数据2千多条的测试集数据。我们之所以要自定义数据集是因为需要去适配训练模型需要的数据格式。自定义数据集参考代码from datasets import load_dataset from torch.utils.data import Dataset # 自定义数据集 class MyDataset(Dataset): def __init__(self, split): # 加载训练集 train_dataset load_dataset(pathcsv, data_filesweibo_senti_8k_train.csv) # 加载测试集 test_dataset load_dataset(pathcsv, data_filesweibo_senti_2k_test.csv) if split train: self.data train_dataset[train] elif split test: self.data test_dataset[train] # 获取数据集大小 def __len__(self): return len(self.data) # 获取数据集的某个元素 def __getitem__(self, index): sentence self.data[index][sentence] label self.data[index][label] return sentence, label if __name__ __main__: train_dataset MyDataset(train) test_dataset MyDataset(test) print(train_dataset[0]) print(test_dataset[0]) for data in test_dataset: print(data)运行结果2对训练输入文本进行编码对传入的数据进行训练之前我们需要对数据进行编码。我们通过分词器的batch_encode_plus方法进行批量编码实例代码from transformers import BertTokenizer import config # 加载分词器 tokenizer BertTokenizer.from_pretrained(config.model_path /Bert-base-chinese) # 准备测试文本 sents [床前明月光疑似地上霜举头望明月低头思故乡, 今天天气不错, 很开心] # 批量编码句子 out tokenizer.batch_encode_plus( batch_text_or_text_pairssents, # 输入的文本 add_special_tokensTrue, # 添加特殊标记 max_length10, # 最大长度 paddingmax_length, # 填充 truncationTrue, # 截断 return_tensorspt, # 返回pytorch张量 return_token_type_idsTrue, # 返回token_type_ids 区分不同句子或段落的类型标识 return_attention_maskTrue, # 返回attention_mask 标记有效token位置的掩码 return_special_tokens_maskTrue # 返回special_tokens_mask 标识特殊token如[CLS]、[SEP]的位置掩码 ) print(out) for k, v in out.items(): print(k, v) # 解码文本数据 for i in range(len(sents)): print(sents[i] --解码后, tokenizer.decode(out[input_ids][i]))运行输出{input_ids: tensor([[ 101, 2414, 1184, 3209, 3299, 1045, 8024, 4542, 849, 102], [ 101, 791, 1921, 1921, 3698, 679, 7231, 102, 0, 0], [ 101, 2523, 2458, 2552, 102, 0, 0, 0, 0, 0]]), token_type_ids: tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]), special_tokens_mask: tensor([[1, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 1, 1, 1], [1, 0, 0, 0, 1, 1, 1, 1, 1, 1]]), attention_mask: tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [1, 1, 1, 1, 1, 0, 0, 0, 0, 0]])} input_ids tensor([[ 101, 2414, 1184, 3209, 3299, 1045, 8024, 4542, 849, 102], [ 101, 791, 1921, 1921, 3698, 679, 7231, 102, 0, 0], [ 101, 2523, 2458, 2552, 102, 0, 0, 0, 0, 0]]) token_type_ids tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]) special_tokens_mask tensor([[1, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 1, 1, 1], [1, 0, 0, 0, 1, 1, 1, 1, 1, 1]]) attention_mask tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [1, 1, 1, 1, 1, 0, 0, 0, 0, 0]]) 床前明月光疑似地上霜举头望明月低头思故乡--编码后 [CLS] 床 前 明 月 光 疑 似 [SEP] 今天天气不错--编码后 [CLS] 今 天 天 气 不 错 [SEP] [PAD] [PAD] 很开心--解码后 [CLS] 很 开 心 [SEP] [PAD] [PAD] [PAD] [PAD] [PAD]3定义增量模型也就是下游任务我们定义增量模型主要是在Bert模型最后加一个全连接层实现二分类任务。进行前向传播的时候我们要使用torch.no_grad()冻结Bert模型参数不需计算梯度获取最后一层Bert隐藏层输出调用自定义的全连接层进行增量模型训练。示例代码# 使用设备GPU/CPU import torch from transformers import BertModel import config device torch.device(cuda if torch.cuda.is_available() else cpu) print(device) # 加载预训练模型 pretrained_model BertModel.from_pretrained(config.model_path /Bert-base-chinese).to(device) # 定义下游任务增量模型 class DownStreamModel(torch.nn.Module): def __init__(self): super(DownStreamModel, self).__init__() # 下游加一个全连接层实现二分类任务 self.fc torch.nn.Linear(768, 2) def forward(self, input_ids, attention_mask, token_type_ids): with torch.no_grad(): # 冻结Bert模型参数不需计算梯度 # 获取最后一层隐藏层输出 output pretrained_model(input_idsinput_ids, attention_maskattention_mask, token_type_idstoken_type_ids) # 增量模型参与训练 out self.fc(output.last_hidden_state[:, 0, :]) return outoutput.last_hidden_state[:, 0, :]是用来获取模型输出的隐藏状态通常是进入模型的最后一层隐藏状态的一个特定切片。让我们逐个参数进行详细解析1.outputoutput通常是通过对输入数据如文本、图像等运行某个深度学习模型例如 BERT、GPT、Transformers 等后返回的对象它包含多个属性其中一个重要的属性是last_hidden_state。2.last_hidden_statelast_hidden_state是模型最后一层的隐藏状态它的形状通常是(batch_size, sequence_length, hidden_size)具体的含义如下batch_size处理的样本数量。在一次前向传播中模型可以并行处理多个输入样本。sequence_length输入序列的长度。对于处理文本来说它表示词汇的数量可以是句子中词的个数。hidden_size每个隐藏状态的维度代表模型的输出特征维数。通常在模型架构中定义例如对于 BERT-base 隐藏大小为 768。3.[:, 0, :]这里的切片操作用来访问last_hidden_state的一部分具体解释如下:表示选择所有的样本。由于batch_size是第一个维度所以把:放在这个位置表示选取当前批次的所有样本。0表示选择第一个时刻的隐藏状态。在 NLP 中特别是像 BERT 这样的模型中第一位置的隐藏状态通常对应于[CLS]token分类 token它是用来进行句子级别的任务例如分类的。:表示选择所有的特征维度hidden_size。这意味着我们提取每个样本的第一个位置即[CLS]token对应的全部隐藏状态特征。综合因此output.last_hidden_state[:, 0, :]表示提取所有输入样本的[CLS]token 的隐藏状态向量这通常用于下游任务如文本分类、问答、情感分析等因为[CLS]token 的表示通常是整段文本的语义聚合。例子如果有一个输入批次大小为 4并且每个输入序列的隐藏状态大小为 768那么output.last_hidden_state[:, 0, :]的返回结果将是一个形状为(4, 768)的张量其中每一行对应一个输入样本的[CLS]token 的隐藏状态。4训练模型前面我们已经定义好了数据集以及文本编码处理包括增量模型定义。接下来我们来进行增量模型微调训练。实例代码import torch from datasets import load_dataset from torch.utils.data import Dataset, DataLoader from transformers import BertTokenizer, BertModel import config # 自定义数据集 class MyDataset(Dataset): def __init__(self, split): # 加载训练集 train_dataset load_dataset(pathcsv, data_filesweibo_senti_8k_train.csv) # 加载测试集 test_dataset load_dataset(pathcsv, data_filesweibo_senti_2k_test.csv) if split train: self.data train_dataset[train] elif split test: self.data test_dataset[train] # 获取数据集大小 def __len__(self): return len(self.data) # 获取数据集的某个元素 def __getitem__(self, index): sentence self.data[index][sentence] label self.data[index][label] return sentence, label # 加载分词器 tokenizer BertTokenizer.from_pretrained(config.model_path /Bert-base-chinese) # 使用设备GPU/CPU device torch.device(cuda if torch.cuda.is_available() else cpu) print(device) # 加载预训练模型 pretrained_model BertModel.from_pretrained(config.model_path /Bert-base-chinese).to(device) # 定义下游任务增量模型 class DownStreamModel(torch.nn.Module): def __init__(self): super(DownStreamModel, self).__init__() # 下游加一个全连接层实现二分类任务 self.fc torch.nn.Linear(768, 2) def forward(self, input_ids, attention_mask, token_type_ids): with torch.no_grad(): # 冻结Bert模型参数不需计算梯度 # 获取最后一层隐藏层输出 output pretrained_model(input_idsinput_ids, attention_maskattention_mask, token_type_idstoken_type_ids) # 增量模型参与训练 out self.fc(output.last_hidden_state[:, 0, :]) return out # 对传入数据进行编码 def collate_fn(data): sents [i[0] for i in data] labels [i[1] for i in data] # 编码 # 批量编码句子 out tokenizer.batch_encode_plus( batch_text_or_text_pairssents, # 输入的文本 add_special_tokensTrue, # 添加特殊标记 max_length80, # 最大长度 paddingmax_length, # 填充 truncationTrue, # 截断 return_tensorspt, # 返回pytorch张量 return_token_type_idsTrue, # 返回token_type_ids 区分不同句子或段落的类型标识 return_attention_maskTrue, # 返回attention_mask 标记有效token位置的掩码 return_special_tokens_maskTrue # 返回special_tokens_mask 标识特殊token如[CLS]、[SEP]的位置掩码 ) return out[input_ids], out[attention_mask], out[token_type_ids], torch.tensor(labels) # 创建数据集 train_dataset MyDataset(train) # 训练集 train_loader DataLoader( datasettrain_dataset, # 数据集 batch_size200, # 批次大小 shuffleTrue, # 是否打乱数据 drop_lastTrue, # 丢弃最后一个批次数据 collate_fncollate_fn # 对加载的数据进行编码 ) test_dataset MyDataset(test) # 测试集 test_loader DataLoader( datasettest_dataset, # 数据集 batch_size200, # 批次大小 shuffleTrue, # 是否打乱数据 drop_lastTrue, # 丢弃最后一个批次数据 collate_fncollate_fn # 对加载的数据进行编码 ) if __name__ __main__: model DownStreamModel().to(device) # 创建模型 optimizer torch.optim.AdamW(model.parameters()) # 优化器 criterion torch.nn.CrossEntropyLoss() # 定义损失函数 best_val_acc 0 # 保存最好的准确率 EPOCH 3 # 训练轮数 for epoch in range(EPOCH): # 训练轮数 for i, (input_ids, attention_mask, token_type_ids, labels) in enumerate(train_loader): # 批次数据 out model(input_idsinput_ids.to(device), attention_maskattention_mask.to(device), token_type_idstoken_type_ids.to(device)) # 模型输出 loss criterion(out, labels.to(device)) # 计算损失 optimizer.zero_grad() # 清空梯度 loss.backward() # 反向传播 optimizer.step() # 优化器更新参数 # 每隔5个批次输出训练结果 if i % 5 0: out out.argmax(dim1) # 获取预测结果 acc (out labels.to(device)).sum().item() / len(labels) # 计算准确率 print(EPOCH:{}--第{}批次--损失:{}--准确率:{}.format(epoch 1, i 1, loss.item(), acc))运行结果cuda EPOCH:1--第1批次--损失:0.5008983016014099--准确率:0.78 EPOCH:1--第6批次--损失:0.5052810907363892--准确率:0.75 EPOCH:1--第11批次--损失:0.4850313067436218--准确率:0.755 EPOCH:1--第16批次--损失:0.4301462471485138--准确率:0.83 EPOCH:1--第21批次--损失:0.39388778805732727--准确率:0.85 EPOCH:1--第26批次--损失:0.3695535361766815--准确率:0.855 EPOCH:1--第31批次--损失:0.35825812816619873--准确率:0.855 EPOCH:1--第36批次--损失:0.3288692533969879--准确率:0.875 EPOCH:2--第1批次--损失:0.31738394498825073--准确率:0.885 EPOCH:2--第6批次--损失:0.3121739625930786--准确率:0.87 EPOCH:2--第11批次--损失:0.30510687828063965--准确率:0.895 EPOCH:2--第16批次--损失:0.305753618478775--准确率:0.865 EPOCH:2--第21批次--损失:0.24456100165843964--准确率:0.92 EPOCH:2--第26批次--损失:0.2233615517616272--准确率:0.93 EPOCH:2--第31批次--损失:0.2816208302974701--准确率:0.89 EPOCH:2--第36批次--损失:0.24931633472442627--准确率:0.915 EPOCH:3--第1批次--损失:0.3053100109100342--准确率:0.885 EPOCH:3--第6批次--损失:0.2515011727809906--准确率:0.9 EPOCH:3--第11批次--损失:0.24241474270820618--准确率:0.915 EPOCH:3--第16批次--损失:0.2211739420890808--准确率:0.925 EPOCH:3--第21批次--损失:0.24276195466518402--准确率:0.91 EPOCH:3--第26批次--损失:0.27010777592658997--准确率:0.895 EPOCH:3--第31批次--损失:0.24304606020450592--准确率:0.9 EPOCH:3--第36批次--损失:0.26476508378982544--准确率:0.9055评估模型模型训练好之后我们要对模型进行性能评估以及保存最优模型参数。示例代码import torch from datasets import load_dataset from torch.utils.data import Dataset, DataLoader from transformers import BertTokenizer, BertModel import config # 自定义数据集 class MyDataset(Dataset): def __init__(self, split): # 加载训练集 train_dataset load_dataset(pathcsv, data_filesweibo_senti_8k_train.csv) # 加载测试集 test_dataset load_dataset(pathcsv, data_filesweibo_senti_2k_test.csv) if split train: self.data train_dataset[train] elif split test: self.data test_dataset[train] # 获取数据集大小 def __len__(self): return len(self.data) # 获取数据集的某个元素 def __getitem__(self, index): sentence self.data[index][sentence] label self.data[index][label] return sentence, label # 加载分词器 tokenizer BertTokenizer.from_pretrained(config.model_path /Bert-base-chinese) # 使用设备GPU/CPU device torch.device(cuda if torch.cuda.is_available() else cpu) print(device) # 加载预训练模型 pretrained_model BertModel.from_pretrained(config.model_path /Bert-base-chinese).to(device) # 定义下游任务增量模型 class DownStreamModel(torch.nn.Module): def __init__(self): super(DownStreamModel, self).__init__() # 下游加一个全连接层实现二分类任务 self.fc torch.nn.Linear(768, 2) def forward(self, input_ids, attention_mask, token_type_ids): with torch.no_grad(): # 冻结Bert模型参数不需计算梯度 # 获取最后一层隐藏层输出 output pretrained_model(input_idsinput_ids, attention_maskattention_mask, token_type_idstoken_type_ids) # 增量模型参与训练 out self.fc(output.last_hidden_state[:, 0, :]) return out # 对传入数据进行编码 def collate_fn(data): sents [i[0] for i in data] labels [i[1] for i in data] # 编码 # 批量编码句子 out tokenizer.batch_encode_plus( batch_text_or_text_pairssents, # 输入的文本 add_special_tokensTrue, # 添加特殊标记 max_length80, # 最大长度 paddingmax_length, # 填充 truncationTrue, # 截断 return_tensorspt, # 返回pytorch张量 return_token_type_idsTrue, # 返回token_type_ids 区分不同句子或段落的类型标识 return_attention_maskTrue, # 返回attention_mask 标记有效token位置的掩码 return_special_tokens_maskTrue # 返回special_tokens_mask 标识特殊token如[CLS]、[SEP]的位置掩码 ) return out[input_ids], out[attention_mask], out[token_type_ids], torch.tensor(labels) # 创建数据集 train_dataset MyDataset(train) # 训练集 train_loader DataLoader( datasettrain_dataset, # 数据集 batch_size200, # 批次大小 shuffleTrue, # 是否打乱数据 drop_lastTrue, # 丢弃最后一个批次数据 collate_fncollate_fn # 对加载的数据进行编码 ) test_dataset MyDataset(test) # 测试集 test_loader DataLoader( datasettest_dataset, # 数据集 batch_size200, # 批次大小 shuffleTrue, # 是否打乱数据 drop_lastTrue, # 丢弃最后一个批次数据 collate_fncollate_fn # 对加载的数据进行编码 ) if __name__ __main__: model DownStreamModel().to(device) # 创建模型 optimizer torch.optim.AdamW(model.parameters()) # 优化器 criterion torch.nn.CrossEntropyLoss() # 定义损失函数 best_val_acc 0 # 保存最好的准确率 EPOCH 3 # 训练轮数 for epoch in range(EPOCH): # 训练轮数 for i, (input_ids, attention_mask, token_type_ids, labels) in enumerate(train_loader): # 批次数据 out model(input_idsinput_ids.to(device), attention_maskattention_mask.to(device), token_type_idstoken_type_ids.to(device)) # 模型输出 loss criterion(out, labels.to(device)) # 计算损失 optimizer.zero_grad() # 清空梯度 loss.backward() # 反向传播 optimizer.step() # 优化器更新参数 # 每隔5个批次输出训练结果 if i % 5 0: out out.argmax(dim1) # 获取预测结果 acc (out labels.to(device)).sum().item() / len(labels) # 计算准确率 print(EPOCH:{}--第{}批次--损失:{}--准确率:{}.format(epoch 1, i 1, loss.item(), acc)) # 验证模型 model.eval() # 评估模式 Dropout关闭 with torch.no_grad(): # 评估模式不需要计算梯度 for i, (input_ids, attention_mask, token_type_ids, labels) in enumerate(test_loader): out model(input_idsinput_ids.to(device), attention_maskattention_mask.to(device), token_type_idstoken_type_ids.to(device)) out out.argmax(dim1) acc (out labels.to(device)).sum().item() / len(labels) if acc best_val_acc: best_val_acc acc torch.save(model.state_dict(), best_model.pth) print(f测试集准确率EPOCH{epoch}-第{i}批次:模型保存准确率:{acc}) # 保存最后一轮模型 torch.save(model.state_dict(), last_model.pth) print(f最后一轮模型保存:准确率:{acc})运行结果cuda EPOCH:1--第1批次--损失:0.6369971632957458--准确率:0.695 EPOCH:1--第6批次--损失:0.6052521467208862--准确率:0.685 EPOCH:1--第11批次--损失:0.5286625623703003--准确率:0.77 EPOCH:1--第16批次--损失:0.4174182415008545--准确率:0.83 EPOCH:1--第21批次--损失:0.41344115138053894--准确率:0.81 EPOCH:1--第26批次--损失:0.3910037875175476--准确率:0.87 EPOCH:1--第31批次--损失:0.3680213987827301--准确率:0.85 EPOCH:1--第36批次--损失:0.3817676901817322--准确率:0.855 EPOCH:2--第1批次--损失:0.3963841199874878--准确率:0.84 EPOCH:2--第6批次--损失:0.3516421914100647--准确率:0.85 EPOCH:2--第11批次--损失:0.330654114484787--准确率:0.845 EPOCH:2--第16批次--损失:0.3345922529697418--准确率:0.865 EPOCH:2--第21批次--损失:0.3087370693683624--准确率:0.885 EPOCH:2--第26批次--损失:0.25769323110580444--准确率:0.92 EPOCH:2--第31批次--损失:0.2792946696281433--准确率:0.885 EPOCH:2--第36批次--损失:0.29899129271507263--准确率:0.905 EPOCH:3--第1批次--损失:0.3139827847480774--准确率:0.855 EPOCH:3--第6批次--损失:0.27809959650039673--准确率:0.895 EPOCH:3--第11批次--损失:0.2725857198238373--准确率:0.885 EPOCH:3--第16批次--损失:0.30161210894584656--准确率:0.885 EPOCH:3--第21批次--损失:0.26055067777633667--准确率:0.925 EPOCH:3--第26批次--损失:0.22951321303844452--准确率:0.895 EPOCH:3--第31批次--损失:0.2995443642139435--准确率:0.87 EPOCH:3--第36批次--损失:0.3246515691280365--准确率:0.87 测试集准确率EPOCH2-第0批次:模型保存准确率:0.975 最后一轮模型保存:准确率:0.955把训练好的模型参数进行业务功能封装前面我们把模型参数训练好了接下来我们需要封装下一个接口方法提供给应用调用。llm目录下新建weibo_train.pyimport torch from transformers import BertTokenizer, BertModel import config # 加载分词器 tokenizer BertTokenizer.from_pretrained(config.model_path /Bert-base-chinese) # 使用设备GPU/CPU device torch.device(cuda if torch.cuda.is_available() else cpu) print(device) # 加载预训练模型 pretrained_model BertModel.from_pretrained(config.model_path /Bert-base-chinese).to(device) # 定义下游任务增量模型 class DownStreamModel(torch.nn.Module): def __init__(self): super(DownStreamModel, self).__init__() # 下游加一个全连接层实现二分类任务 self.fc torch.nn.Linear(768, 2) def forward(self, input_ids, attention_mask, token_type_ids): with torch.no_grad(): # 冻结Bert模型参数不需计算梯度 # 获取最后一层隐藏层输出 output pretrained_model(input_idsinput_ids, attention_maskattention_mask, token_type_idstoken_type_ids) # 增量模型参与训练 out self.fc(output.last_hidden_state[:, 0, :]) return out # 对传入数据进行编码 def collate_fn(data): # 编码 # 批量编码句子 out tokenizer.batch_encode_plus( batch_text_or_text_pairsdata, # 输入的文本 add_special_tokensTrue, # 添加特殊标记 max_length80, # 最大长度 paddingmax_length, # 填充 truncationTrue, # 截断 return_tensorspt, # 返回pytorch张量 return_token_type_idsTrue, # 返回token_type_ids 区分不同句子或段落的类型标识 return_attention_maskTrue, # 返回attention_mask 标记有效token位置的掩码 return_special_tokens_maskTrue # 返回special_tokens_mask 标识特殊token如[CLS]、[SEP]的位置掩码 ) return out[input_ids], out[attention_mask], out[token_type_ids] model DownStreamModel().to(device) # 创建模型 model.load_state_dict(torch.load(config.model_path /best_model.pth)) def check_data(data): # 验证模型 model.eval() # 评估模式 Dropout关闭 with torch.no_grad(): # 评估模式不需要计算梯度 input_ids, attention_mask, token_type_ids collate_fn(data) out model(input_idsinput_ids.to(device), attention_maskattention_mask.to(device), token_type_idstoken_type_ids.to(device)) output out.argmax(dim1) sentiment output.item() sentiment_label 正面 if sentiment 1 else 负面 return sentiment_label if __name__ __main__: result check_data([我非常难过]) print(result)运行结果使用BERT大模型微调对微博热词进行情感分析找到视图层业务逻辑代码改成# 改成使用大模型微调进行舆情分析 sentiments check_data([defaultHotWord])重启测试明显比之前大模型微调前的准确率提高很多。使用BERT大模型对微博文章内容进行情感分析找到微博舆情分析后端视图业务逻辑代码改成# 改成使用大模型微调进行舆情分析 sentiments check_data([article[1]])重启运行分析结果明显比大模型微调之前准确率高很多。使用BERT大模型对微博舆情分析以及可视化操作找到数据可视化微博舆情分析后端视图层业务逻辑代码包括柱状图树形图饼状图。代码都需要修改修改代码后pb.route(sentimentAnalysis) def sentimentAnalysis(): 舆情数据分析 :return: xHotBarData [正面, 负面] yHotBarData [0, 0] # 只读取前100条 df pd.read_csv(./fenci/comment_fre.csv, nrows100) for value in df.values: # 情感分析 # stc SnowNLP(value[0]).sentiments # if stc 0.6: # yHotBarData[0] 1 # elif stc 0.2: # yHotBarData[2] 1 # else: # yHotBarData[1] 1 # 使用大模型进行情感分析 # sentiment_label data_classfication(value[0]) # 使用大模型微调进行情感分析 sentiment_label check_data([value[0]]) if sentiment_label 正面: yHotBarData[0] 1 else: yHotBarData[1] 1 hotTreeMapData [{ name: xHotBarData[0], value: yHotBarData[0] }, { name: xHotBarData[1], value: yHotBarData[1] }] commentPieData [{ name: 正面, value: 0 }, { name: 负面, value: 0 }] articlePieData [{ name: 正面, value: 0 }, { name: 负面, value: 0 }] commentList commentDao.getAllComment() for comment in commentList: # 情感分析 # stc SnowNLP(comment[1]).sentiments # if stc 0.6: # commentPieData[0][value] 1 # elif stc 0.2: # commentPieData[2][value] 1 # else: # commentPieData[1][value] 1 # 使用大模型进行情感分析 # sentiment_label data_classfication(comment[1]) # 使用大模型微调进行情感分析 sentiment_label check_data([comment[1]]) if sentiment_label 正面: commentPieData[0][value] 1 else: commentPieData[1][value] 1 articleList articleDao.getAllArticle() for article in articleList: # 情感分析 # stc SnowNLP(article[1]).sentiments # if stc 0.6: # articlePieData[0][value] 1 # elif stc 0.2: # articlePieData[2][value] 1 # else: # articlePieData[1][value] 1 # 使用大模型进行情感分析 # sentiment_label data_classfication(article[1]) # 使用大模型微调进行情感分析 sentiment_label check_data([article[1]]) if sentiment_label 正面: articlePieData[0][value] 1 else: articlePieData[1][value] 1 df2 pd.read_csv(./fenci/comment_fre.csv, nrows15) xhotData15 [x[0] for x in df2.values][::-1] yhotData15 [x[1] for x in df2.values][::-1] return render_template(sentimentAnalysis.html, xHotBarDataxHotBarData, yHotBarDatayHotBarData, hotTreeMapDatahotTreeMapData, commentPieDatacommentPieData, articlePieDataarticlePieData, xhotData15xhotData15, yhotData15yhotData15)重启系统测试准备率得到了质的提升。应用系统进行【批量】调用大模型提高系统响应速度我们之前单个传入大模型进行情感分析效率略低我们一般建议批量的进行情感分析但是传入的数据量也不能太大。我们之前封装的可以传入一个列表但是我们不可以传入一个非常大的列表否则GPU内存会溢出。我们如果在业务层进行控制传入的元素量比较麻烦。所以我们封装一个批量导入的方法。打开weibo_train.pydef check_data(data): # 验证模型 model.eval() # 评估模式 Dropout关闭 with torch.no_grad(): # 评估模式不需要计算梯度 input_ids, attention_mask, token_type_ids collate_fn(data) out model(input_idsinput_ids.to(device), attention_maskattention_mask.to(device), token_type_idstoken_type_ids.to(device)) output out.argmax(dim1) # sentiment output.item() # sentiment_label 正面 if sentiment 1 else 负面 # print(预测结果, sentiment_label) return output.tolist() # 批量处理 def check_batch_datas(dataList, batch_num): outputList [] for i in range(0, len(dataList), batch_num): batch_data dataList[i:i batch_num] outputList.extend(check_data(batch_data)) return outputList我们以对微博文章进行大模型情感分析模块为例修改成批量调用pb.route(articleData) def articleData(): 微博舆情分析 :return: articleOldList articleDao.getAllArticle() # 获取所有帖子标题 articleTitleList [article[1] for article in articleOldList] # 批量使用大模型进行舆情分析 sentimentsList check_batch_datas(articleTitleList, batch_num10) # 追加情感分析属性 articleNewList [] for i in range(len(articleOldList)): if sentimentsList[i] 1: articleNewList.append(articleOldList[i] (正面,)) else: articleNewList.append(articleOldList[i] (负面,)) # for article in articleOldList: # article list(article) # 情感分析 sentiments # stc SnowNLP(article[1]).sentiments # if stc 0.6: # sentiments 正面 # elif stc 0.2: # sentiments 负面 # else: # sentiments 中性 # 改成使用大模型进行舆情分析 # sentiments data_classfication(article[1]) # 改成使用大模型微调进行舆情分析 # sentiments check_data([article[1]]) # article.append(sentiments) # articleNewList.append(article) return render_template(articleData.html, articleListarticleNewList)运行效果还是有显著提高的。