
简介在自然语言处理领域文本分类是基础且应用广泛的子任务其核心目标是将非结构化文本自动归入预定义类别。传统机器学习方法依赖人工特征工程而神经网络技术通过嵌入层与循环神经网络如LSTM能够自动捕获语义与上下文依赖关系显著提升分类性能。虚假评论识别正是文本分类的典型工业场景广泛存在于电商平台、外卖服务、社交媒体内容审核中对维护信息真实性与用户信任至关重要。本文以一套可运行的毕业设计项目为蓝本系统拆解了从数据清洗、中文分词、词表构建到LSTM模型训练的完整流程并深入讲解参数配置、模型评估指标及训练陷阱处理。无论是准备毕设答辩还是入门实践深度学习文本分类本文均可作为高效参考。 很巧我最近正好帮一个学弟把他的本科毕业设计重新整理了一遍题目就是“基于神经网络的虚假评论识别系统”。他当时从网上找的源码压缩包里面代码能跑但论文写得稀碎答辩PPT更是惨不忍睹。我陪着他改了三个晚上最后拿到个不错的成绩。今天就借着这个话题把这个项目的里里外外拆开揉碎讲一遍从数据集怎么处理、模型怎么选、代码怎么写到答辩时老师最爱问哪些问题全部盘一遍。不管你是直接拿这份源码改还是想自己从零写一个这篇文章都能给你省下大量瞎折腾的时间。需要说明的是我不会贴整段完整代码那篇文章会变成几万字也没人看得完而是把核心模块的代码骨架、关键逻辑和参数配置思路讲清楚你拿到源码后能快速看懂每一层在干什么想改哪里、怎么改心里有数。1. 项目整体拆解一个典型的文本二分类任务先把这个项目是什么讲清楚。虚假评论识别本质上就是一个文本二分类问题给定一条评论文本判断它是真实的用户评价normal还是刷出来的虚假评价fake。用神经网络来做就是让模型从大量标注好的数据里自己学习“什么样的评论像假的”而不是靠人工去总结规则。这个项目能用在很多地方电商平台过滤刷单评论、外卖平台识别恶意差评、社交平台清理垃圾内容、影评网站过滤水军短评。虽然毕业设计的规模不需要做到工业级但你要明白你做的这个东西对应到真实业务里是哪个环节。1.1 系统的核心模块整套系统拆开来看由五个模块组成数据加载与清洗模块负责读取原始评论数据做去重、去空、文本清洗、标签处理。特征工程与分词模块对中文评论做分词或英文评论做tokenize构建词表将文本转换成神经网络能处理的数值向量。模型构建模块搭建神经网络结构包括嵌入层、序列编码层LSTM或CNN、全连接分类层。训练与验证模块划分训练集和验证集配置优化器和损失函数执行训练并保存最优模型。预测与评估模块加载已训练模型对新的评论进行预测输出概率和类别并给出准确率、精确率、召回率等指标。源码zip里通常会有一个主脚本比如main.py或train.py、一个模型定义文件model.py、一个数据处理文件data_loader.py以及训练好的模型权重文件.h5或.pth外加一份README说明文档。1.2 技术选型背后的逻辑很多大四学生在选技术栈的时候是迷茫的看到什么火就选什么。但你要清楚毕业设计的评分标准不是“你用了多先进的技术”而是“你是否清楚自己为什么选这个技术”。这份源码里最核心的选型是这三个Python自然语言处理领域的绝对主力语言第三方库生态极其完善TensorFlow、PyTorch、Keras、scikit-learn、jieba这些库全部有成熟的Python接口。用Python写神经网络代码可以把精力集中在模型结构本身而不需要像用C那样去手动管理大量底层细节。版本选择上建议使用Python 3.7~3.9之间太新的版本比如3.11、3.12有时候兼容不了旧版TensorFlow。神经网络模型这里用的不是那种几十层上百层的深度残差网络而是一个相对轻量的结构通常由Embedding层LSTM或双向LSTM组成。为什么用这种结构而不直接上BERT关键原因有两条第一BERT这种预训练模型参数量巨大训练和推理都需要较高显存普通学生用CPU或入门级GPU跑起来非常吃力第二也是更重要的毕业设计的核心考察点是你是否理解神经网络的基本原理如果你直接用BERT然后说自己做了“基于深度学习的评论识别”但连Transformer的QKV是什么都答不上来答辩现场会被老师问得非常难堪。LSTM结构经典、原理清晰、训练速度快是毕设级别的稳妥选择。Keras/TensorFlow或PyTorch两个主流框架都行但大多数从网上下载的源码是基于Keras的早期很多教程用Keras也有不少新源码用PyTorch。如果你只有CPU环境推荐KerasTensorFlow 2.x内置如果你有NVIDIA显卡且CUDA环境配置好了PyTorch用起来更顺手。这里需要提醒一下如果你拿到的源码是TensorFlow 1.x版本的Keras也就是tf.keras还没整合的时候在现在的环境里跑会报一堆API弃用的警告甚至直接报错处理起来比较头疼。解决办法是安装对应版本的TensorFlow或者手动改写import语句。2. 数据是干这个项目的关键命脉2.1 数据集从哪来网上流传的这份虚假评论识别项目最常见的配套数据集是酒店评论数据集。这份数据在学术界非常有名是康奈尔大学的研究人员收集标注的包含真实评论和虚假评论两大类原始文件通常是文本文件每条评论一行带有标签字段。除了酒店评论数据集还有几个也能用的公开数据集亚马逊商品评论数据集规模大但有标注的虚假评论子集不好找很多需要自己去构建伪标签。价格不菲。中文电商评论数据集京东、淘宝等平台早期的评论数据在某些开源平台上有共享但质量参差不齐很多没标注。自己爬数据然后人工标注这个方法不建议在毕设里做原因很现实——标注3000条评论一个人可能要花整整一周而且主观性极强你自己都拿不准某条评论到底是不是刷的。这个工作量和时间成本对于毕设来说不划算。2.2 数据预处理的实操细节拿到原始数据后第一件事是把它读进来每条评论对应一个标签。原始读取代码的骨架是import pandas as pd # 假设数据是CSV格式两列text和label df pd.read_csv(reviews.csv, encodingutf-8) print(df.head()) print(df[label].value_counts())标签列通常是0和10表示真实评论1表示虚假评论。有的数据集里用的是字符串标签如“truthful”和“deceptive”需要做映射。接下来是文本清洗。这一步决定了模型能不能学到有效特征但很多学生完全忽略它。具体要做四件事去HTML标签有些数据是从网页上抓下来的评论里可能残留br、p等标签需要用正则表达式删除。去除特殊符号包括表情符号、连续标点、乱码字符。注意中文评论里的句号和逗号可以保留但连续的感叹号“”最好统一为一个“”或者直接删除。因为虚假评论经常用夸张标点但保留单个标点和删除的取舍会影响模型效果建议做对比实验哪种结果好用哪种。去除停用词中文里的“的、了、吗、呢、啊、是、就”这类高频但语义价值低的词在统计特征时代很重要但在神经网络时代停用词的作用变得复杂。LSTM这类模型本身能学习到词与词之间的依赖关系简单去掉停用词反而可能丢掉有用的语法信息。我的建议是对于神经网络模型可以不去停用词或者只去掉最基础的一小部分比如语气词。这个不用人云亦云自己做个实验对比就行。文本长度统一神经网络的输入是定长的需要把所有评论截断或填充到同一个长度。对酒店评论来说一般设置最大长度为100~200个字符中文按字切开或50~80个词按词切开。过短的真实评论只有“推荐很好”四个字填充到200就全是0浪费计算资源过长的评论超过100个词的情况截断掉对分类影响也不大因为虚假评论的特征通常已经在前半部分暴露了。清洗代码骨架import re def clean_text(text): text re.sub(r[^], , text) # 去HTML标签 text re.sub(r[a-zA-Z0-9], , text) # 去掉英文和数字中文场景 text re.sub(r\s, , text) # 去掉空白字符 return text.strip() df[cleaned_text] df[text].apply(clean_text)2.3 中文分词与词表构建中文没有天然的空格分词需要借助分词工具。最常见的方案是结巴分词jieba安装简单、速度也够快pip install jieba使用方式import jieba def cut_text(text): return .join(jieba.cut(text)) df[cut_text] df[cleaned_text].apply(cut_text)分词之后构建词表。词表的构建思路是统计所有评论中出现过的词按频率排序保留出现次数最多的前N个词比如20000个剩下的低频词统一映射成一个特殊的“未知词”标记UNK。为什么要截断到20000因为词表太大意味着嵌入层参数多模型内存占用大训练也会变慢。而高频词已经覆盖了绝大多数语义信息低频词对分类的贡献有限还容易带来噪声。from collections import Counter # 统计所有词频 all_words [] for line in df[cut_text]: all_words.extend(line.split()) word_count Counter(all_words) vocab [word for word, count in word_count.most_common(20000)] word2idx {word: idx 2 for idx, word in enumerate(vocab)} word2idx[PAD] 0 # 填充符 word2idx[UNK] 1 # 未知词紧接着是序列转换把分词后的一句话变成一列数字索引长度不够补0超过截断。from tensorflow.keras.preprocessing.sequence import pad_sequences max_len 100 sequences [[word2idx.get(word, word2idx[UNK]) for word in line.split()] for line in df[cut_text]] X pad_sequences(sequences, maxlenmax_len, valueword2idx[PAD], paddingpost, truncatingpost) y df[label].values这里有个容易踩坑的细节pad_sequences的value参数如果不显式设置为word2idx[PAD]默认是用0填充。如果你的词表里0恰好是某个有意义的词比如你从1开始编号那就会出问题。规范做法是把PAD固定在0号位置UNK固定在1号位置真实词从2开始。2.4 训练集和验证集的划分数据划分不能直接随机切。因为虚假评论检测有一个特性同一家酒店或同一个商品下的假评论和真评论高度相似模型可能学会“这家店的评论基本都是假的”这种走捷径的模式而不是真正学到语言特征。严谨的做法是按评论的源ID或商品ID分组再划分训练/验证集。但大多数毕设源码里没做这一步直接用train_test_split随机切分了。这在毕设答辩时是一个被老师追问的高频点你要能说出这样划分的问题在哪里以及你做了哪些改进比如按照评论来源分组切分。如果你时间来得及建议在代码里加上分组划分from sklearn.model_selection import train_test_split # 假设df有user_id列 train_idx, val_idx train_test_split( df.index, test_size0.2, stratifydf[label], random_state42 ) X_train, X_val X[train_idx], X[val_idx] y_train, y_val y[train_idx], y[val_idx]stratify参数保证划分后训练集和验证集中真假评论的比例一致避免出现验证集里全是某一种类别的情况。3. 神经网络模型的搭建与参数选择3.1 Embedding层把词变成向量神经网络的输入不能是整数索引需要先经过嵌入层Embedding Layer转换成稠密向量。Embedding层做的事情其实就是在训练过程中为词表里的每一个词学习一个固定长度的向量表达比如100维或128维意思相近的词它们的向量在空间里距离更近。为什么不用one-hot因为如果词表有20000个词one-hot向量就是20000维不仅稀疏而且无法表示词之间的语义相似性。Embedding就是把高维稀疏向量压缩成低维稠密向量同时让语义信息在向量空间里有了位置关系。在Keras中定义嵌入层from tensorflow.keras.layers import Embedding embedding_layer Embedding( input_dimlen(word2idx), # 词表大小 output_dim100, # 每个词映射为100维向量 input_lengthmax_len, # 输入序列长度 trainableTrue # 嵌入层参数随训练更新 )有一个可选的优化是使用预训练词向量比如腾讯的word2vec中文词向量但加载大规模词向量文件对于毕设来说性价比不高增加了代码复杂度效果提升还不一定明显。直接随机初始化并让模型自己学对这份数据完全够用。3.2 主体网络LSTM还是CNN虚假评论识别任务网络主体通常有两种选择。方案ALSTM长短时记忆网络LSTM适合处理序列数据能捕捉评论中词语的顺序关系和长距离依赖。一句“位置很好但房间实在太脏了枕头上有头发床单上还有不明污渍绝对不会再来第二次”包含了先扬后抑的转折LSTM能够记住前面“位置很好”的内容并在读到后面的负面信息时综合判断。Keras中搭建LSTM的代码from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Embedding, LSTM, Dense, Dropout model Sequential() model.add(Embedding(len(word2idx), 100, input_lengthmax_len)) model.add(LSTM(128, return_sequencesFalse)) model.add(Dropout(0.5)) model.add(Dense(64, activationrelu)) model.add(Dropout(0.3)) model.add(Dense(1, activationsigmoid))核心参数说明LSTM的units128表示隐藏状态维度是128这是我们让模型自己学习到的“记忆容量”。容量越大模型能记住的信息越多但训练时间更长也更容易过拟合。128是文本分类中比较常用的一个折中值。return_sequencesFalse表示只返回LSTM最后一个时间步的输出。如果你要堆叠两层LSTM那第一层必须设为True否则第二层收到的不是序列数据会报错。Dropout是常用的正则化手段。在训练时随机让一部分神经元不工作迫使网络不能过度依赖某几个节点从而减少过拟合。0.5是在这个任务上实测效果不错的比例。方案BCNN卷积神经网络CNN原本是图像领域的但用在文本分类上同样有效。核心思路是用一个滑动窗口去扫描评论里连续的n个词比如3个词组成的窗口提取局部特征。比如“极差”“垃圾”“骗人”这些词频繁连续出现组合窗口扫描到的n-gram特征就能捕捉到。用卷积网络做文本分类的Keras代码from tensorflow.keras.layers import Conv1D, MaxPooling1D, GlobalMaxPooling1D model Sequential() model.add(Embedding(len(word2idx), 100, input_lengthmax_len)) model.add(Conv1D(filters128, kernel_size3, activationrelu)) model.add(MaxPooling1D(pool_size2)) model.add(Conv1D(filters64, kernel_size3, activationrelu)) model.add(GlobalMaxPooling1D()) model.add(Dense(64, activationrelu)) model.add(Dropout(0.5)) model.add(Dense(1, activationsigmoid))很多源码里同时包含LSTM和CNN两种模型或者用混合结构比如先CNN抽取局部特征再输入LSTM捕捉顺序关系。混合结构的代码复杂度更高但效果不一定比单独一种好到哪去。建议以LSTM为主线如果论文需要对比实验再把CNN模型作为baseline对比项。3.3 损失函数与优化器二分类问题的标准配置是输出层一个神经元sigmoid激活函数输出0到1之间的概率损失函数用二元交叉熵binary_crossentropy优化器用Adam。model.compile( optimizeradam, lossbinary_crossentropy, metrics[accuracy] )Adam优化器的默认学习率是0.001通常不需要改动。如果你发现训练过程中loss震荡很剧烈可以尝试把学习率降到0.0003或0.0001。from tensorflow.keras.optimizers import Adam model.compile( optimizerAdam(learning_rate0.0005), lossbinary_crossentropy, metrics[accuracy] )3.4 训练过程的细节训练参数不能盲目套别人的要结合实际数据量调整。常见配置history model.fit( X_train, y_train, validation_data(X_val, y_val), batch_size64, epochs15, callbacks[ EarlyStopping(patience3, restore_best_weightsTrue), ModelCheckpoint(best_model.h5, save_best_onlyTrue, monitorval_accuracy) ] )几个关键点batch_size每批次送入64条样本更新一次参数。数据总量2000条左右时64是一个训练速度和梯度稳定性的平衡点。如果batch_size太大比如256模型收敛快但泛化能力可能变差太小比如8训练不稳定且耗时。用显存时batch_size还受显存约束如果显存不足就调小到32或16。epochs训练轮数。15轮是保守起步值配合EarlyStopping使用最终可能在第7~10轮就停止。早期停止的意思是当验证集准确率连续多轮patience3不再提升时就停止训练并回滚到最优权重防止过拟合。为什么必须用EarlyStopping因为这个数据集规模不大通常2000~4000条模型很容易过拟合——训练集准确率已经到99%但验证集只有80%还在继续往下降。没有早停机制你保存的可能是最后一轮效果糟糕的模型权重。训练集和验证集划分比例8:2或7:3是常见选择。数据量超过1万条时可以适当减少验证集比例到15%但数据量只有一两千条时建议用20%保证验证集有足够的样本量来评估模型。4. 完整的训练与预测流程梳理4.1 主脚本的整体流程一个典型的整体训练脚本结构# main.py import pandas as pd import numpy as np from sklearn.model_selection import train_test_split from data_preprocess import load_and_clean_data, build_vocab, text_to_sequences from model import build_lstm_model # 1. 加载数据 df load_and_clean_data(data/hotel_reviews.csv) # 2. 构建词表和序列 word2idx, X build_vocab_and_sequences(df) # 3. 划分数据集 X_train, X_val, y_train, y_val train_test_split( X, df[label].values, test_size0.2, random_state42, stratifydf[label] ) # 4. 构建模型 model build_lstm_model(len(word2idx), max_len100) # 5. 训练 history model.fit(X_train, y_train, ...) # 6. 评估 loss, acc model.evaluate(X_val, y_val) print(f验证集损失: {loss:.4f}, 准确率: {acc:.4f})这套流程建议你把各个函数模块化拆分而不是单独写一堆脚本手动复制粘贴。模块化代码的好处有三个一是每个部分可以单独测试数据清洗有问题、词表构建有问题不用跑完整训练就能定位二是论文里画系统架构图时可以直接对应模块三是导师让你调整参数时你知道改哪里。4.2 模型保存与加载训练完成后模型权重保存为HDF5文件Keras或.pt文件PyTorchmodel.save(fake_review_model.h5)预测新评论时需要重新构建词表和加载模型并且对新评论执行完全相同的预处理流程from tensorflow.keras.models import load_model # 加载模型 model load_model(fake_review_model.h5) def predict_review(text): cleaned clean_text(text) cut .join(jieba.cut(cleaned)) seq [word2idx.get(word, word2idx[UNK]) for word in cut.split()] padded pad_sequences([seq], maxlenmax_len, valueword2idx[PAD], paddingpost) prob model.predict(padded)[0][0] label 虚假评论 if prob 0.5 else 真实评论 confidence prob if prob 0.5 else 1 - prob return label, confidence这里有一个特别容易犯的错误加载模型时词表必须和训练时完全一致。有的同学换了数据集重新训练词表变了但预测脚本还在用旧词表导致输入数字序列错位预测结果一塌糊涂。解决方案是把word2idx对象保存成json文件预测时直接加载不要重新构建import json with open(word2idx.json, w, encodingutf-8) as f: json.dump(word2idx, f, ensure_asciiFalse) # 预测时 with open(word2idx.json, r, encodingutf-8) as f: word2idx json.load(f)4.3 模型评估的多维指标只看准确率不够虚假评论识别还有一个关键问题如果数据集中90%是真实评论、10%是虚假评论那么一个“永远预测真实”的傻瓜模型准确率也有90%但毫无实际意义。因此必须看精确率Precision、召回率Recall和F1值精确率预测为虚假的评论中有多少是真正的虚假评论。精确率低说明模型误伤了很多真实评论。召回率所有虚假评论中有多少被模型找出来了。召回率低说明很多假评论漏掉了。F1值精确率和召回率的调和平均综合衡量两个指标。from sklearn.metrics import classification_report y_pred (model.predict(X_val) 0.5).astype(int) print(classification_report(y_val, y_pred, target_names[真实, 虚假]))如果只看准确率你的模型可能在答辩时被老师用一句“样本不均衡情况下准确率没有参考价值”直接问倒。能说出精确率和召回率的区别并知道它们在这个任务中的意义是答辩的加分项。此外还有一个可用但要慎用的评估工具混淆矩阵。它可以帮你直观地看到模型把哪些真实评论误判成了虚假评论哪些虚假评论漏掉了。在论文的实验分析部分画一个混淆矩阵热力图视觉效果也不错。5. 源码里常见的坑与修复方案从网上下载的源码zip十个里面至少有七个存在环境或代码兼容性问题。这里把我实际踩过的坑和对应的修复方法列一遍。5.1 解压问题很多人拿到的是zip压缩包解压时如果遇到“file is not a zip file”之类的报错通常有两种可能一是下载文件不完整建议重新下载二是文件本身不是zip格式比如实际上是7z或rar或者直接从网页下载的HTML改一下扩展名可能就行。在Linux下解压时建议用unzip命令不要用tar -xf处理zip因为tar工具不擅长识别zip格式容易解压出各种权限和中文文件名问题。5.2 Python版本与依赖冲突这是最最常见的问题。这个项目用到的核心依赖tensorflow2.0 numpy1.19 pandas1.0 scikit-learn0.24 jieba0.42 matplotlib3.3不同版本的TensorFlow API变化很大。如果你拿到的是旧版TensorFlow 1.x的代码里面有tf.placeholder、tf.Session这类写法在TensorFlow 2.x环境下跑会直接报错。有两个解决办法# 方法一装老版本TensorFlow推荐CPU环境 pip install tensorflow1.15 # 方法二兼容模式不推荐问题很多 import tensorflow.compat.v1 as tf tf.disable_v2_behavior()如果你使用的是2.x的Kerasimport tensorflow as tf; from tensorflow.keras...则在当前环境基本兼容。唯一需要注意的是tf.keras.backend里某些函数名的变动比如tf.keras.backend.get_session()在2.x中默认不可用需要开启运行时的某些设置才能工作。另一个高频坑是NumPy版本问题。新版NumPy1.24删除了部分旧接口如果你遇到module numpy has no attribute float这样的报错解决办法是pip install numpy1.23.5这个坑在TensorFlow 2.9之前的老版本里非常常见值得记住。5.3 内存不足与OOM如果训练时出现ResourceExhaustedError或OOM when allocating tensor说明显存或内存不够了。解决办法按优先级排列减小batch_size从64降到32或16减小max_len从100降到80或50减小Embedding维度从100降到50如果用的是CPU建议把LSTM的units从128降到64。5.4 训练出来的模型准确率一直徘徊在50%这说明模型根本没有学到任何有效特征。排查方向标签是否对应正确。检查数据读入后df[label].value_counts()的分布看是不是标签编码反了比如0和1搞反了或者标签列读成了字符串导致模型无法处理。文本是否几乎为空。如果你做数据清洗时把数字、英文、标点全部删掉有些短文本可能只剩一两个词。检查一下清洗后的平均文本长度如果太短要放宽清洗规则。词表构建是否正确。看看X[:3]里的数字序列是否大部分是0填充符或1未知词如果一条评论里80%的词都映射成了UNK说明词表和训练数据不匹配或者分词没有正确执行。数据没有shuffle。如果你的代码没有随机打乱数据模型可能一直在学习同一个类别连续出现的数据分布导致拟合不到真实规律。在train_test_split之后、训练之前建议用np.random.shuffle打乱索引。6. 答辩现场的常见问题准备毕业设计不只是把代码跑通答辩环节的表现往往决定了最终分数。这里整理几个和这个题目绑定的高频问题提前做好准备。6.1 “你为什么要用神经网络而不是传统机器学习方法”答辩老师十有八九会问这个问题。你得能列出对比点和具体数据比如传统机器学习如朴素贝叶斯、SVM需要手动设计特征比如词频统计TF-IDF、评论长度、标点符号数量、重复词比例等。这些手工特征捕捉不了语义层面的虚假信号例如“这家酒店很差但是我是因为出差才来的”这种复杂的语境。神经网络通过Embedding学到了词与词之间的语义关联LSTM能建模上下文信息模型可以自动发现“免费”“加微信”“代购”等词语在虚假评论中出现的模式。在实验对比中LSTM模型的准确率能达到85%~90%而传统TF-IDF逻辑回归大概在78%~83%提升是实打实的。6.2 “LSTM为什么能解决RNN的梯度消失问题”这个问题如果答不出来会有很大减分。要点是传统RNN在反向传播时梯度是连乘的序列变长后梯度会指数级缩小梯度消失或增大梯度爆炸。LSTM引入了细胞状态cell state和三个门控机制输入门、遗忘门、输出门通过门控结构让梯度可以在细胞状态这条“传送带”上跨多个时间步传递从而缓解了长距离依赖问题。你可以用生活化类比来解释细胞状态就像一条高速公路信息在上面直通门就是高速公路上的收费站决定哪些信息通过、哪些被拦下、哪些旧信息要被清理掉。遗忘门决定忘掉多少旧信息输入门决定写入多少新信息输出门决定当前时刻输出给下一层什么信息。6.3 “如果你的数据里面虚假评论和真实评论数量差很多怎么办”这是少数需要你主动准备答案的问题。建议回答实验层面可以采用类别权重class_weight调整损失函数让模型对少数类样本的惩罚更大或者使用SMOTE等过采样方法但这个在文本上效果不稳定。评价层面不要只看准确率要综合看精确率、召回率和F1值重点关注虚假评论的召回率。数据层面更建议收集更多标注数据但从毕设角度不现实所以更推荐在训练时给少数类样本设置更高的权重。在代码层面可以这样实现类别权重class_weight {0: 1.0, 1: 1.5} # 虚假评论的权重设为1.5 model.fit(X_train, y_train, class_weightclass_weight, ...)6.4 “你的模型泛化能力怎么样”这个问题也很常问。你需要准备好验证集的结果并且承认模型可能在新数据上表现会下降原因包括训练数据本身规模不大、数据集领域单一只针对某个特定类型的商品、以及深度学习模型固有的数据偏差问题。如果你有时间做一个跨领域数据集的小测试比如用酒店评论训练的模型去预测电影评论展示结果并分析原因这会让你的毕设上一个档次。7. 写在最后的一点实际经验这个项目我前后陪三个学生改过整体感受是基于神经网络的虚假评论识别是个比较标准的文本分类课题难度适中工作量可控非常适合本科毕设。但绝大多数网上源码的本质只是一个能跑通的demo离“合格的毕业论文”还差得很远。你要做的不是让代码跑通就完事而是把每个模块背后的原理、参数选择的理由、数据处理的细节都搞清楚然后把这些写进论文里。有几个常见疑问这里统一回复一下是否一定要用自己的数据集重新训练推荐做。你可以从网上收集某个特定平台比如京东、淘宝的评论自己标注几百到一千条在预训练好的模型上做微调fine-tuning这样论文里的“数据与实验部分”会显得更有工作量。需要用到GPU吗不需要。这份数据集规模不大LSTM网络参数也不多用CPU训练两千条评论十五轮大概十几分钟就能跑完。如果你用GPU反而需要处理CUDA、cuDNN这些环境问题增加无谓的复杂度。要不要用中文数据如果有中文配套数据更好但很多经典数据集是英文或翻译成多语言的。从中文酒店评论数据集开始做对导师和答辩老师来说更直观展示效果也更好。如果只能用英文数据就把界面和论文里的例子翻译成中文。模型效果一定要做到多少准确率才算合格通常两个类别真实/虚假的二分类做到85%以上的准确率和F1值在本科毕设里就算不错的了。不用追求90%以上那通常是数据规模不同导致的结果不是你的模型问题。系统源码里要不要包含GUI界面纯控制台脚本也能通过毕设但如果你愿意做一个简单的Web页面Flask或Streamlit都行都很快让用户在浏览器里输入一句评论然后显示判断结果答辩时展示效果会好很多。Streamlit做这种小项目非常合适几百行代码就能搞定而且演示起来很自然。最后再分享一个我做这个小项目时觉得特别实用的经验把所有的实验记录记在一个文档里包括你调过哪些参数、改了什么规则、准确率从多少提升到了多少。一方面写论文的实验分析章节时这个文档直接就是素材库另一方面答辩时当老师问“你为什么不试试更大的batch_size”时你能直接回答“我试过从64改到128后验证集准确率下降了两个点考虑是数据量太少、大batch导致收敛不稳定”这个回答比任何理论分析都有说服力。好这篇就写到这了。如果你正在改这份源码建议按这个文章的顺序把代码里的每一步都过一遍确保自己真的明白每一行在干什么。这样到了答辩现场不管老师怎么问你都能接得住。本文还有配套的精品资源点击获取