京东商品评论情感分析:基于LSTM的实战全流程解析

发布时间:2026/10/1 13:36:53

京东商品评论情感分析:基于LSTM的实战全流程解析 简介一套面向计算机专业毕业设计与课程作业的深度学习情感分析项目资料基于长短时记忆网络LSTM对京东商城评论数据进行情感分类完整覆盖数据爬取、清洗、预处理、模型训练与评估全流程。压缩包共39个文件含8个Python脚本、模型权重、数据分片、索引、检查点、训练结果图片及说明文档等整体大小164.28MB模块划分清晰便于直接运行与二次开发。已有173人浏览学习。资料内嵌京东商品评论爬虫与情感分析模型两大模块附带停用词表、结果图片和已训练模型通过研读代码与文档可深入理解LSTM中遗忘门、输入门、输出门如何解决长依赖问题并将其应用于电商评论情感识别。适合作为NLP课程设计、毕设课题或深度学习入门实践参考也可替换数据集快速迁移到其他领域。1. 这个毕设项目到底在做什么从京东评论到 LSTM 情感分类很多人拿到这个标题时以为难点在 LSTM 神经网络本身真正做下来才会发现基于深度学习LSTM的情感分析项目最花时间的是把京东商城数据洗成模型能吃的样子。这个毕设/课程作业要解决的事情很具体给一段京东买家评论让模型判断它是好评还是差评。项目可能只有几千条评论也可能有几十万条但流程几乎都一样清洗、分词、词表构建、LSTM 训练、评估。适合正在做深度学习课程设计、或者想用 NLP 方向项目做毕业设计的同学。我给你的第一条建议是先别急着调 LSTM 的层数先把清洗到序列化的数据管道跑通项目就成了八成了。2. 京东商城数据怎么处理成 LSTM 能吃的样子清洗、分词与序列化京东商城原始评论最常见的是一个 CSV一行一条记录。字段一般包含用户名、商品ID、评论内容、评分1~5、点赞数、评论时间等。有的数据包会提前给你打好评/差评标签有的只给评分和评论文本需要你自己构造标签。先明确目标LSTM 的输入是一段定长的整数索引序列输出是好评/差评的概率所以中间所有处理都是围绕“把字符串变成定长数字序列”来做。2.1 京东评论数据的常见字段与“脏数据”长什么样先读进来看一下。我用 pandas 读 CSV打印形状和前几行并统计 score 分布。import pandas as pd df pd.read_csv(jd_comments.csv, encodingutf-8-sig) print(df.shape) print(df.head(5)) print(df[score].value_counts())读取时会遇到的第一坑是编码。京东系爬下来的 CSV 经常是 gbk 或 utf-8-sig 而不是纯 utf-8。我一般直接写utf-8-sig它能自动吃掉开头的 BOM 头。如果文件是 gbk就改成encodinggbk再试。不要一个编码走到黑报UnicodeDecodeError就换。“脏数据”在评论区尤其多无意义的“此用户没有填写评价内容”夹杂“【赠品】”和“回复”链接和 HTMLemoji 表情还有大量完全重复的评论。另外 score 字段不一定和文本一致有人给 1 分却写“好用”也有人给 5 分写“垃圾”。要降低这种噪声如果做的是二分类建议把 score 为 3 分的中评丢掉因为“一般般”这类中性表达会让模型很困惑。如果数据包里已经给了 label 字段就优先用 label。2.2 清洗与去重为什么不能只做 strip常见误用是只str.strip()一下就去分词。文本里带着 HTML 和 URL分词后会产生大量“a”“href”这种噪声词。我的清洗函数处理四件事去掉 URL、去掉 HTML 标签、统一小写、把非中英文和数字的字符换成空格最后压缩连续空格。import re def clean_comment(text: str) - str: if not isinstance(text, str): return text re.sub(rhttp\S, , text) # 去掉URL text re.sub(r[^], , text) # 去掉HTML标签 text text.lower() # 统一小写避免Apple/apple分开 text re.sub(r[^\u4e00-\u9fa5a-zA-Z0-9], , text) text re.sub(r\s, , text).strip() return text df[comment_clean] df[comment].apply(clean_comment) df df[df[comment_clean].str.len() 2] # 去掉太短的评论 df df.drop_duplicates(subset[comment_clean]) if score in df.columns: df df[df[score] ! 3] # 二分类时去掉中评这里的关键点是不要直接删除标点而是替换成空格。比如“质量不错喜欢”和“质量不错。喜欢”直接删标点会变成“质量不错喜欢”句意还在但“不要”这种否定结构如果被粗暴删除字符词序会被破坏。替换成空格后标点变成天然的分词边界。清洗之后去重要用清洗后的文本不是原始文本。默认评论可以直接匹配字符串删掉。最后过滤掉长度小于 2 的样本“好”“行”这类单字评论没有足够上下文留着反而干扰训练。2.3 分词与停用词jieba 的自定义词典和停用表中文分词最常用的还是 jieba。京东评论里有很多品牌名和商品型号比如“iPhone”“ThinkPad”“海尔洗衣机”如果不加自定义词典jieba 会拆成“think”“pad”。我会准备一份用户词典jd_words.txt每行一个词格式是“词 词频 词性”例如海尔洗衣机 100 nt ThinkPad 50 nz iPhone 100 nzimport jieba jieba.load_userdict(jd_words.txt) def segment(text: str) - list: return list(jieba.lcut(text)) df[words] df[comment_clean].apply(segment) stopwords set() with open(stopwords.txt, encodingutf-8) as f: for line in f: stopwords.add(line.strip()) def filter_stop(words): return [w for w in words if w not in stopwords and w.strip()] df[words_filtered] df[words].apply(filter_stop)分词后做停用词过滤。注意停用词表不是越全越好。“不”“没”“别”“虽然”“但是”这些词绝对不能进停用表它们是情感转折的关键。很多同学复现时直接用网上下载的通用停用表把“不”也滤掉结果差评全变成好评这种翻车现场很常见。如果不想自己筛就只过滤标点和单字删除“的、了、吧、啊”这类虚词。2.4 序列化与 Padding把词变成索引把句子变成等长LSTM 要求一个 batch 内每条样本长度一致所以我要先把词表建出来。常见做法是统计词频每个词给一个下标保留两个特殊符号0 给pad1 给unk。为了控制词表大小只保留出现次数 2 的词低频词全映射到unk。from collections import Counter counter Counter() for words in df[words_filtered]: counter.update(words) vocab {pad: 0, unk: 1} for word, freq in counter.most_common(): if freq 2: vocab[word] len(vocab) def words_to_ids(words): return [vocab.get(w, vocab[unk]) for w in words] df[ids] df[words_filtered].apply(words_to_ids)接下来自己实现 padding顺便把训练和预测阶段都会用到的max_len定下来。我一般取 100因为京东评论 80% 以上都在 100 字以内太短会截掉转折句太长会增大无效 padding让 LSTM 多跑很多无意义的pad位置。import numpy as np max_len 100 def pad_ids(ids_list): X [] for ids in ids_list: if len(ids) max_len: ids ids[:max_len] else: ids ids [0] * (max_len - len(ids)) X.append(ids) return np.array(X, dtypenp.int64) X pad_ids(df[ids]) if label in df.columns: y df[label].astype(int).values else: y (df[score] 4).astype(int).values这里有两个边界参数值得注意。词表阈值设为 2表示只出现过一次的词全部变成unk优点是小词表、训练快缺点是测试集里的生僻词可能全部失效。如果你发现测试集准确率明显低于验证集先检查是不是 unk 太多。另一个是max_len不要为了凑模型输入把长度调到 200序列越长训练越慢性能也不一定更好。还有一点很重要构建词表只能用训练集不能拿全量数据去统计词频否则等于提前让模型看到测试集词汇这属于数据泄漏答辩时老师一追问就会露馅。词表和max_len一旦定下来训练、验证、测试全过程都要保持一致。3. 搭一个能跑通的 LSTM 情感分析模型PyTorch 实现与参数选择3.1 为什么选 LSTM 而不是 CNN 或直接用全连接情感判断高度依赖词序和上下文。比如“物流很快但质量差”如果把词序打乱或者只看局部窗口就很容易判错。LSTM 的循环结构能把前文的隐藏状态传递给下一步相当于带着记忆读完整句话所以处理这种带转折的句子比 CNN 更自然。CNN 可以捕捉局部 n-gram但感受野之外的依赖要叠很多层才能触及全连接则完全丢掉词序只能当词袋模型用。毕设里选择 LSTM除了效果还因为它的门控机制好讲、公式好画图导师不容易质疑。但代价也要知道LSTM 的训练速度比 CNN 慢在小数据集上更容易过拟合。所以后面参数选择上要刻意加约束不是网络越深越好。3.2 词嵌入层随机初始化还是预训练词向量词嵌入层本质是查表把词索引变成稠密向量。有两种初始化方式。随机初始化就是nn.Embedding默认随机生成让模型在训练中自己学词向量优点是省事和数据匹配度最高缺点是训练数据少时学不出足够好的语义关系。预训练词向量是用 gensim 加载中文 word2vec然后对模型词表里的每个词去预训练词典里查向量查不到的变成随机初始化向量。对几千条评论的课程作业预训练向量通常能让准确率提升 2~5 个点但需要处理词表对齐稍麻烦。常见做法是先用随机初始化把整个管道跑通确认 loss 能下降再决定要不要换预训练向量。如果一开始就加预训练变量太多排查问题会很痛苦。3.3 LSTM 层、Dropout 与全连接分类头的配合我的默认结构是Embedding(100维) - 双层LSTM(隐藏128) - 平均池化 - Dropout - 全连接输出2分类。下面这段是可以直接复制训练的最小模型。import torch import torch.nn as nn class LSTMClassifier(nn.Module): def __init__(self, vocab_size, embed_size100, hidden_size128, num_layers2, num_classes2, dropout0.3): super().__init__() self.embedding nn.Embedding(vocab_size, embed_size, padding_idx0) self.lstm nn.LSTM(embed_size, hidden_size, num_layers, batch_firstTrue, dropoutdropout if num_layers 1 else 0) self.dropout nn.Dropout(dropout) self.fc nn.Linear(hidden_size, num_classes) def forward(self, x): emb self.embedding(x) # [batch, seq_len, embed_size] out, _ self.lstm(emb) # out: [batch, seq_len, hidden_size] mask (x ! 0).unsqueeze(-1) # [batch, seq_len, 1] masked out * mask lengths mask.sum(dim1) # [batch, 1] pooled masked.sum(dim1) / lengths.clamp(min1) pooled self.dropout(pooled) return self.fc(pooled)说明一下为什么用平均池化而不是out[:, -1]。因为 padding 后句末是无数个padout[:, -1]基本是模型处理 pad 之后的状态没有信息量。平均池化把所有有效位置的状态取均值对 pad 不敏感。如果你想用最后一个真实词的隐状态需要借助pack_padded_sequence这里不展开但你知道有这个方案即可。hidden_size128是起步值数据量小就降到 64num_layers2表达能力更强但数据低于 2 万条建议单层起步不然容易过拟合。padding_idx0告诉 Embedding 层把pad位置的嵌入固定为 0 向量和 mask 配合才一致。3.4 损失函数、优化器与训练循环细节分类任务用交叉熵。京东评论好评通常远多于差评如果打开统计发现好评:差评 8:2就给差评样本加权重。CrossEntropyLoss的weight参数按类别频率的倒数设置比如差评权重 2.0好评 1.0。优化器建议用 AdamW学习率 1e-3配合weight_decay1e-4比 Adam 更能压住 LSTM 的过拟合。训练循环里有两个容易被忽略的点梯度裁剪和最优模型保存。LSTM 时序较长时容易梯度爆炸loss 跳到 nan用clip_grad_norm_把梯度范数限制在 5 以内就能避免。同时不要用最后一个 epoch 的模型要保存验证集准确率最高的那一轮因为情感分析任务在 10 轮左右就会过拟合最后几轮准确率反而下降。from torch.utils.data import DataLoader, TensorDataset, random_split X_t torch.tensor(X, dtypetorch.long) y_t torch.tensor(y, dtypetorch.long) dataset TensorDataset(X_t, y_t) split int(len(dataset) * 0.8) train_ds, val_ds random_split(dataset, [split, len(dataset) - split]) train_loader DataLoader(train_ds, batch_size64, shuffleTrue) val_loader DataLoader(val_ds, batch_size64, shuffleFalse) model LSTMClassifier(len(vocab)) weights torch.tensor([1.0, 2.0]) # 假设0差评, 1好评差评少时调高差评权重 loss_fn nn.CrossEntropyLoss(weightweights) optimizer torch.optim.AdamW(model.parameters(), lr1e-3, weight_decay1e-4) best_acc 0 for epoch in range(10): model.train() for xb, yb in train_loader: optimizer.zero_grad() out model(xb) loss loss_fn(out, yb) loss.backward() nn.utils.clip_grad_norm_(model.parameters(), max_norm5) optimizer.step() model.eval() correct total 0 with torch.no_grad(): for xb, yb in val_loader: pred model(xb).argmax(dim1) correct (pred yb).sum().item() total yb.size(0) acc correct / total print(fepoch {epoch1}: acc {acc:.4f}) if acc best_acc: best_acc acc torch.save({model: model.state_dict(), vocab: vocab, max_len: max_len}, best_model.pth)参数说明batch_size64在 CPU 上也能跑内存紧张就改 32。epoch10是起步值不要一上来就 50先看 val acc 在第几轮封顶如果第 8 轮还在涨可以再加 5 轮如果第 3 轮就开始跌说明过拟合调大 dropout 或者减少层数。保存模型时把vocab和max_len一起写进字典这是之后预测能复现的关键。如果你的数据集很大可以在训练前加一句if torch.cuda.is_available(): model model.to(cuda)同时把 xb、yb 也移到 cuda。CPU 训练 1 万条数据大概几分钟到十几分钟毕设完全够用。4. 训练过程中的避坑与血泪经验从 loss 不降到过拟合这一章写实际调这个项目时反复翻车的几个场景每一条都可以直接对照排查。LSTM 情感分析的训练过程有黑匣子属性出现问题不要盲目堆模型先按顺序检查数据、标签、序列化、训练参数。4.1 现象loss 一直不降准确率卡在 60% 附近现象训练 5 轮后 loss 几乎不变验证准确率一直 60% 上下比随机猜测好一点但明显没意义。原因这类项目 60% 卡住多数不是模型问题而是标签和文本对不上。比如评分 1~5 分有人把 score2 当差评、score4 当好评但数据包里的 label 字段是反的或者 score3 的中评没剔除中性样本把两个类别搅混。也可能是序列化出错所有句子被 padding 后某个位置输入全零模型学到的是预测多数类。解决先打印 20 条训练数据的comment_clean、分词结果、ids 序列、y 标签人工看一遍有没有明显错位。再做一次类别统计确认好评和差评都有足够样本。最省事的验证是挑选 50 条正负样本直接预测并输出前 5 个词看看模型到底有没有读到有效内容。4.2 现象训练集准确率 95%验证集只有 72%现象train acc 一路冲到 95%验证 acc 在第 3 轮达到 75% 然后下跌典型的过拟合。原因LSTM 模型参数量很大而京东评论课程作业往往只有几千到一两万条模型很容易把训练集“背”下来而不是学泛化特征。另外词表太大也会加剧过拟合低频词全部放进词表等于给模型提供了记忆训练样本的捷径。解决优先调小模型而不是加数据。把hidden_size从 128 降到 64num_layers从 2 降到 1dropout从 0.3 提高到 0.5优化器weight_decay从 1e-4 调到 5e-4同时把词表阈值从 2 提高到 3。如果仍然过拟合就提前停止保存验证集最高点的模型而不是最后一个 epoch。4.3 现象预测新评论时结果很差之前调的准确率都是假的现象测试集准确率 80%但拿几条真实评论去预测几乎全是好评或随机结果。原因最可能是测试集和真实评论不是同分布。比如训练数据来自手机品类测试评论是食品或服饰另一个常见原因是很多词在训练里没见过全部变成unk导致模型只能靠少数常见词做判断。解决预测时用和训练完全相同的clean_comment和分词函数不要另写一套。词表构建时把阈值降到 2 甚至 1保留更多低频词如果数据允许按品类划分训练/验证别让一个品类独占测试集。还可以在预测前统计新评论里unk的比例超过 20% 就说明词表需要重做。4.4 现象准确率很高但差评完全召回不了现象准确率 85%可差评的召回率只有 30%模型把大量差评判成好评。原因类别不平衡。京东商城好评远多于差评比例可能 9:1。模型学到“全部预测好评”就有 90% 准确率所以 loss 不惩罚它。解决损失函数加weight差评权重设为 2 或 3评估指标看F1而不是准确率在 DataLoader 里对差评过采样也就是重复抽差评样本。如果你做三分类还要考虑中性类的权重。答辩时“准确率高但差评漏报”是一个值得展开讲的问题别把只报准确率的短板留给自己。4.5 现象换一台电脑跑同样代码结果完全不一样现象训练脚本在室友电脑上跑出 0.90 准确率在自己电脑上只有 0.82或者 reload 模型后预测结果对不上。原因PyTorch 的默认初始化在每次运行时都不同包括 Dropout、数据切分也带随机性。如果不固定种子两次实验结果不能复现在课程作业里是硬伤。解决训练脚本开头固定所有随机源random、numpy、torch、torch.cuda并且设置torch.backends.cudnn.deterministic True。保存模型时把vocab、max_len、标签映射一起存下来这样从 checkpoint 恢复时不需要重新构建词表预测才一致。5. 项目交付时怎么让人信服评估指标、demo 与可复现性毕设或课程作业不只是“跑通”而是要让老师 3 分钟看懂你的结果并且相信它是真的。我通常按下面三步准备。5.1 用混淆矩阵和 F1 而不是只看准确率给导师打印混淆矩阵。好评差评的不平衡决定了准确率有欺骗性。from sklearn.metrics import confusion_matrix, classification_report with torch.no_grad(): y_true [] y_pred [] for xb, yb in val_loader: y_true.extend(yb.tolist()) y_pred.extend(model(xb).argmax(dim1).tolist()) print(classification_report(y_true, y_pred, target_names[差评, 好评])) print(confusion_matrix(y_true, y_pred))classification_report直接给出 precision、recall、F1混淆矩阵能看出错在哪一类。这一步比只贴 acc 有说服力得多。5.2 做一个命令行 demo 或简单 Web 接口我一般会在项目根目录放一个predict.py接收一条评论走同一个清洗、分词、词表映射流程加载保存的 checkpoint输出概率。这个 demo 决定答辩时能不能当场演示。最小命令就是python predict.py --comment 物流很快但是质量一般代码里核心是把vocab还原然后对输入句子走一遍和训练相同的预处理。注意预测时也要把序列 pad 到max_len并且 pad 在右边。如果忘做模型会直接报维度错误。5.3 固定随机种子和实验记录留个后悔药我的习惯是每次训练前把随机种子、词表大小、max_len、batch_size、epoch 写进一个config.py并在 README 里写明运行顺序clean - build_vocab - train - predict。看起来琐碎但课程作业跨两三个月重装环境、换机器后能直接恢复结果。固定随机种子之后同一个 checkpoint 在不同机器上的预测结果才一致否则答辩前突然变了自己都没法解释。这些不是加分项是基本盘。我自己曾被“换电脑后结果复现不了”坑过一整晚后来所有实验都先固定随机种子并保存完整词表。这个习惯也就成了我做这类项目的底线。希望帮到你。本文还有配套的精品资源点击获取
延伸阅读

更多相关文章

2026/10/1 13:31:53

WinForm自绘滚动条:可换色与线条/矩形双轨道样式实现

简介:这是一份面向C# Winform开发者的自定义滚动条实战源码,针对默认VScrollBar/HScrollBar外观单一、难以适配个性化界面主题的问题,通过继承原生控件并重写OnPaint方法,实现拖块颜色与轨道颜色的自由修改,同时提供线…

2026/10/1 13:31:53

AI辅助建模:Antigravity+Blender MCP打造智慧仓储数字孪生

Antigravity Blender MCP 这个组合,最近在3D数字孪生圈子里的讨论热度确实高。简单说,这套玩法就是让AI直接在你的Blender里动手建模,你只需要像聊天一样把需求描述清楚——比如“我要一个长30米、宽20米、高8米的智慧仓库,里面配…

2026/10/1 13:31:53

Python深度学习车牌识别系统实战:从两阶段检测到CRNN字符识别全流程

简介:这份Python项目源码面向计算机视觉与深度学习方向的课程设计、毕业设计学生及入门开发者,提供一套完整的车牌识别系统实现方案,可用于交通管理、智能停车场等场景的算法学习与二次开发。项目围绕车牌定位、字符分割与字符识别三大核心环…

2026/10/1 14:16:55

CSP信奥赛C++普及组第二轮认证【复赛防爆零】最全攻略

CSP信奥赛C普及组第二轮认证【复赛防爆零】最全攻略 CSP复赛的“爆零”往往并非因为题目完全不会,而是败在了一些非技术性的细节上。王老师青少年编程课堂的这份解析会从致命雷区、代码规范、策略与骗分、环境适应四个维度,帮你系统性地避开这些坑&…

2026/10/1 14:16:55

询问lightharness:咱们现在挂载了哪些插件和skill?

询问lightharness:咱们现在挂载了哪些插件和skill?lightharness的回答:早上好,都查完了。先说个前提:我这个会话的运行时其实只挂了一个工具——bash(而且底层是 Windows cmd.exe,不是真 bash)。所以下面这…

2026/10/1 14:16:55

LeetCode Hot 100栈题全攻略:从单调栈到表达式解析一网打尽

刷 LeetCode Hot 100 的人,大概都会经历这样一个阶段:数组、链表题还能靠记忆硬磨,可一旦看到标签里写着“栈”,心里就开始没底。栈的概念很简单——先进后出,可在真题里它一会儿出现在括号匹配,一会儿变成…

2026/10/1 14:16:55

VS Code集成通义灵码:AI编程助手安装配置与多语言实战指南

1. 项目动机与整体设计思路 1.1 为什么是 VS Code 加通义灵码 我最早接触 VS Code 还是好多年前,当时身边人把它当“高级记事本”用,装上插件之后才慢慢变成主力编辑器。这两年 AI 编程助手铺天盖地,从 GitHub Copilot 到各种国产助手&#…

2026/10/1 14:11:55

Model-Optimizer实战:搭建模型优化工作流与避坑指南

Model-Optimizer这个名字,算法圈子里的人应该不陌生。训练完一个模型只是第一步,真正让人头疼的是怎么把它塞进业务里跑得又快又稳,同时精度还不掉太多。我见过太多项目死在“训练精度97%,上线之后延迟超预算、显存爆掉”这个坎上…

2026/10/1 5:21:14

东莞市品牌网站建设报价常见报错与解决

东莞品牌网站建设报价单背后:一份保姆级建站教程避坑实录 网站做好了没人访问,这大概是很多老板最头疼的事。花了大几万做的品牌站,上线后流量惨淡,比路边摊还冷清。别急着骂外包公司,很多“东莞品牌网站建设报价”里藏着不少猫腻,比如用模板站冒充定制…

2026/9/29 21:48:03

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/10/1 10:48:55

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑