ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Python电商评论情感分析:从数据预处理到TextCNN/BERT模型实战

Python电商评论情感分析:从数据预处理到TextCNN/BERT模型实战 简介本资源为基于Python的电商买家评论数据情感分析完整课程设计包面向计算机、人工智能、软件工程等专业学生及教师适合课程大作业、毕业设计或项目初期立项参考。包内共1379个文件以478个py源码、237个csv评论数据集、178个txt说明、125个html页面及模型文件为主压缩包约53.95MB涵盖数据爬取、情感分类、主题建模与可视化全流程。项目选用美的热水器等多品牌商品评论兼顾好评差评与时间跨度涉及评论分数与内容不吻合、关键词提取、情感分数计算、装饰器计时与log、config配置、训练测试集划分等细节并附代码注释与开发文档。运行入口为streamlit run ./Comment_analysis/Streamlit/streamlitEXP.py可快速启动图形化界面演示。已有1119人学习下载适合小白借鉴或在此基础上扩展BERT情感分类、pyLDAvis可视化等功能。1. 从一份课程大作业说起电商评论情感分析到底在做什么打开任何一个电商平台的商品页评论区里藏着大量真实用户反馈。有人写“质量很好物流快下次还来”也有人写“收到货就后悔了色差严重客服还不理人”。对商家来说这些文本是改进产品和运营的线索对平台来说是风控和推荐的重要信号。但靠人工一条条看几万条评论根本翻不过来。基于 Python 的电商买家评论数据情感分析要解决的就是这件事把非结构化的中文评论自动分成正面、负面有时还有中性并给出可解释的置信度。这套源码模型数据集代码注释的组合适合正在做课程大作业的学生也适合想快速搭一个评论分析原型的初级工程师。它不追求工业级吞吐但胜在链路完整、注释清楚能让你从数据读入一路跑到模型评估把“情感分析”这四个字从概念变成能跑起来的代码。2. 数据准备与中文评论预处理从原始 CSV 到模型可吃的张量2.1 拿到数据集先别急着训练先看清三件事课程大作业给的数据集通常是 CSV 或 Excel字段一般包含评论内容、评分、时间、商品 ID。我拿到手第一件事不是写模型而是用 pandas 做三查查类别分布、查文本长度分布、查缺失值。电商评论有个特点好评远多于差评如果直接训练模型会倾向于把所有评论判成正面准确率看着高但差评召回率惨不忍睹。所以先统计正负样本比例后面再决定要不要做重采样或类别权重。import pandas as pd df pd.read_csv(ecommerce_comments.csv, encodingutf-8) print(df[label].value_counts()) # 看正负样本是否均衡 print(df[comment].str.len().describe()) # 看文本长度决定截断长度 print(df.isnull().sum()) # 看缺失值分布这段代码输出三个关键信息类别分布决定是否要处理不均衡长度分布决定 padding 的最大长度一般取 95 分位数避免为了几条超长评论浪费显存缺失值决定是删除还是填充。参数上encoding在 Windows 上常遇到 gbk如果报 UnicodeDecodeError换成gb18030基本能解决。2.2 中文分词与停用词jieba 的三种模式和自定义词典中文不像英文有空格必须分词。常见做法是用 jieba它有三种模式精确模式适合文本分析全模式会把“乒乓球拍卖完了”切成“乒乓/乒乓球/球拍/拍卖/卖完/完了”搜索引擎模式介于两者之间。情感分析我一般用精确模式再加载一个电商领域的自定义词典把“性价比”“物流快”“色差”这类词固定下来避免被切碎。import jieba jieba.load_userdict(ecommerce_dict.txt) # 每行一个词如性价比、物流快 stopwords set(open(stopwords.txt, encodingutf-8).read().splitlines()) def cut_text(text): words jieba.lcut(str(text), cut_allFalse) # 精确模式 return .join([w for w in words if w not in stopwords and len(w) 1]) df[cut_comment] df[comment].apply(cut_text)cut_allFalse表示精确模式len(w) 1过滤单字因为单字在情感分析里噪声大停用词表要包含“的、了、是、就”这类高频无意义词。注意不要用全模式否则特征维度会爆炸训练变慢且容易过拟合。2.3 标签怎么定评分映射还是人工标注如果数据集自带评分1 到 5 星常见做法是 4 到 5 星映射为正面1 到 2 星映射为负面3 星丢弃或单独做中性类。但这里有个坑有些用户打 5 星却写“还行吧”文本和标签矛盾。课程大作业里如果数据量不大建议抽样 200 条人工核对一下映射规则是否合理。如果数据集已经给了 label 字段直接用但要看清楚 0 代表正面还是负面别训练完发现标签反了。def score_to_label(score): if score 4: return 1 # 正面 elif score 2: return 0 # 负面 else: return -1 # 中性后续可丢弃 df[label] df[score].apply(score_to_label) df df[df[label] ! -1].reset_index(dropTrue)这段逻辑简单但参数边界要根据实际评分分布调整。如果 3 星占比很高直接丢掉会损失大量数据可以考虑把 3 星归入负面或单独训练一个三分类模型。3. 模型选型与训练TextCNN、BiLSTM 和 BERT 到底选哪个3.1 课程大作业的算力现实先跑通 TextCNN如果你只有笔记本 CPU 或者一块入门级显卡别一上来就 BERT。TextCNN 结构简单、训练快、效果在电商评论这种短文本上并不差。它的思路是用不同尺寸的卷积核捕捉 n-gram 特征比如“质量好”“不推荐”“物流太慢”这种局部模式。源码包里如果有 TextCNN 实现重点看 embedding 维度、卷积核尺寸和 dropout 设置。import torch import torch.nn as nn class TextCNN(nn.Module): def __init__(self, vocab_size, embed_dim128, num_filters128, kernel_sizes[2,3,4], num_classes2): super().__init__() self.embedding nn.Embedding(vocab_size, embed_dim, padding_idx0) self.convs nn.ModuleList([ nn.Conv2d(1, num_filters, (k, embed_dim)) for k in kernel_sizes ]) self.dropout nn.Dropout(0.5) self.fc nn.Linear(num_filters * len(kernel_sizes), num_classes) def forward(self, x): x self.embedding(x) # [batch, seq_len, embed_dim] x x.unsqueeze(1) # [batch, 1, seq_len, embed_dim] x [torch.relu(conv(x)).squeeze(3) for conv in self.convs] x [torch.max_pool1d(i, i.size(2)).squeeze(2) for i in x] x torch.cat(x, 1) x self.dropout(x) return self.fc(x)embed_dim128是常见起点评论短文本够用kernel_sizes[2,3,4]分别捕捉二元、三元、四元词组dropout0.5防止过拟合。如果显存不够把num_filters降到 64。训练时用 Adam学习率 1e-3batch size 64 或 128。3.2 BiLSTM 适合捕捉否定和转折但别忽略序列长度电商评论里“质量不错但是客服太差”这种转折句TextCNN 的局部卷积可能只抓到“质量不错”。BiLSTM 按顺序读入能保留上下文信息对否定词和转折词更敏感。但 LSTM 训练慢且对序列长度敏感。我一般把最大长度截到 128超过的截断不足的补零。class BiLSTM(nn.Module): def __init__(self, vocab_size, embed_dim128, hidden_dim128, num_classes2): super().__init__() self.embedding nn.Embedding(vocab_size, embed_dim, padding_idx0) self.lstm nn.LSTM(embed_dim, hidden_dim, batch_firstTrue, bidirectionalTrue) self.fc nn.Linear(hidden_dim * 2, num_classes) def forward(self, x): x self.embedding(x) out, _ self.lstm(x) out out[:, -1, :] # 取最后一个时间步 return self.fc(out)bidirectionalTrue让模型同时看正向和反向上下文取最后一个时间步是因为它聚合了整句信息。如果效果不好可以改成对时间步做平均池化。注意 padding 的位置用pack_padded_sequence能避免 padding 影响 LSTM 输出但代码会复杂一些课程大作业里可以先不引入。3.3 想冲高准确率再上 BERT但要算清显存和时间BERT 在中文情感分析上通常比 TextCNN 高 3 到 5 个百分点但代价是显存至少 8G 起步训练时间翻几倍。如果作业允许用预训练模型可以用bert-base-chinese把分类层换成二分类。常见做法是冻结前几层只微调后面几层降低显存占用。from transformers import BertTokenizer, BertForSequenceClassification tokenizer BertTokenizer.from_pretrained(bert-base-chinese) model BertForSequenceClassification.from_pretrained(bert-base-chinese, num_labels2) inputs tokenizer(df[comment].tolist(), paddingTrue, truncationTrue, max_length128, return_tensorspt)max_length128覆盖绝大多数电商评论truncationTrue自动截断超长文本。训练时学习率要调小一般 2e-5 到 5e-5否则容易灾难性遗忘。如果显存不够把 batch size 降到 16 或 8再用梯度累积。4. 避坑与排查电商评论情感分析里最容易翻车的五件事4.1 准确率 95% 但差评全漏类别不均衡没处理现象训练完准确率很高但拿几条差评测试全判成正面。原因好评样本远多于差评模型学会了“全猜正面”这个偷懒策略。解决在损失函数里加类别权重nn.CrossEntropyLoss(weighttorch.tensor([1.0, 3.0]))或者对少数类做随机过采样。更稳妥的是看 F1 分数和混淆矩阵别只看准确率。4.2 分词后“不”字被停用词表删了否定词丢失现象模型对“不好”“不满意”判断反了。原因停用词表里包含了“不”分词后否定词消失。解决停用词表里必须保留否定词和程度副词如“不、没、很、太、非常”。我一般会单独维护一个“情感保留词表”在过滤时优先保留。4.3 训练集和测试集来自同一批商品数据泄漏现象测试集准确率奇高换一批评论就崩。原因划分数据时没有按商品 ID 分组同一个商品的评论同时出现在训练集和测试集模型记住了商品特征而不是情感。解决用GroupShuffleSplit按商品 ID 划分确保同一商品的评论只出现在一边。4.4 学习率设成 0.1模型直接不收敛现象loss 震荡或变成 nan。原因学习率太大梯度爆炸。解决Adam 默认 1e-3BERT 微调用 2e-5。如果 loss 变成 nan先检查输入里有没有空字符串或异常字符再降低学习率。4.5 预测时忘了加model.eval()dropout 还在起作用现象同一句话预测两次结果不一样。原因模型还在训练模式dropout 随机丢弃神经元。解决预测前加model.eval()并用with torch.no_grad():包住推理代码既保证结果稳定又省显存。5. 把模型用起来批量预测、置信度过滤和持续迭代的小技巧训练完模型只是第一步真正要用起来得把它接进一个能批量处理评论的脚本。我一般会写一个predict.py读入 CSV输出每条评论的预测标签和置信度再用置信度做一层过滤低于 0.7 的交给人工复核高于 0.9 的直接入库。这样既能保证自动化效率又不会让模棱两可的评论污染分析结果。import torch import pandas as pd from torch.utils.data import DataLoader model.eval() results [] with torch.no_grad(): for batch in DataLoader(test_dataset, batch_size64): logits model(batch[input_ids]) probs torch.softmax(logits, dim1) preds torch.argmax(probs, dim1) for text, pred, prob in zip(batch[text], preds, probs): results.append({ comment: text, label: int(pred), confidence: float(prob[pred]) }) df_out pd.DataFrame(results) df_out[need_review] df_out[confidence] 0.7 df_out.to_csv(predict_result.csv, indexFalse, encodingutf-8-sig)torch.no_grad()关闭梯度计算推理速度提升明显confidence取的是预测类别的概率need_review标记低置信度样本。encodingutf-8-sig保证 Excel 打开不乱码。这个脚本跑完你就能拿着结果去写作业报告或者给运营同学做初步筛选。还有一个容易被忽略的点模型不是训练一次就完事。电商评论的语言会变今天流行“绝绝子”明天流行“yyds”旧模型可能没见过。我习惯每隔一个月把新评论抽样人工标注 200 条加入训练集重新微调一轮。不用全量重训只微调最后一层分类器半小时就能跑完。这个习惯让我避免了好几次“模型突然变笨”的尴尬。希望帮到你。本文还有配套的精品资源点击获取
返回列表