这是我最近整理的一次项目复盘,主题是一个中文垃圾短信识别系统。
一开始做这个项目,目标其实很直接:不靠固定关键词规则,而是让模型自己去学习短信文本里的语义特征,自动判断一条短信是正常消息,还是营销、诈骗一类的垃圾短信。
现在回头看,这个项目最有价值的地方,不只是“做出了一个模型”,而是让我第一次比较完整地走完了中文文本分类项目从数据处理、模型训练到问题定位的全流程。
项目想解决什么问题
移动通信已经很普及了,但垃圾短信和诈骗短信还是很常见。它们不仅影响日常体验,有些时候还会直接带来财产风险。
所以这个项目想做的是一个端侧轻量化的短信过滤系统,核心目标有四个:
- 对中文短信做基础清洗、分词和预处理。
- 把文本转换成可训练的数字特征。
- 用模型自动完成正常短信和垃圾短信的二分类。
- 支持批量测试,并输出准确率、精确率这类常见指标。
如果把它压缩成一句话,就是:让短信风控从“硬编码规则”走向“数据驱动识别”。
我是怎么把它串起来的
这个项目的主体流程可以拆成四个部分。
1. 词表与文本数字化
第一步是把原始短信文本转成模型能处理的数据格式。
完整流程大致是:
原始短信文本 -> 清洗与分词 -> 统计词汇并去重 -> 构建词和数字 ID 的映射 -> 把文本转成数字序列
这个阶段的意义很基础,但也最关键。因为后面的神经网络看不懂自然语言,它只能处理数字,所以这一步就是整个训练链路的入口。
2. 数据读取与数据集封装
在预处理之后,我把标签和短信文本拆开,再统计样本比例、最大文本长度,并通过自定义 Dataset 的方式,把数据统一整理成 PyTorch 可直接加载的格式。
这个阶段做的事情包括:
- 拆分标签与文本内容。
- 对短信序列进行截断或补零。
- 统一张量格式,方便后续分批训练。
它解决的不是“模型聪不聪明”的问题,而是“数据能不能顺利稳定地喂给模型”的问题。
3. 构建 RNN 二分类模型
模型部分我使用的是一个比较基础的 RNN 结构,主链路可以概括成:
词嵌入层 -> RNN 循环层 -> 全连接层 -> 二分类输出
这部分负责从数字 ID 中提取时序语义特征,再将最后的特征映射成分类结果。虽然结构不复杂,但已经能完整跑通文本分类任务。
4. 训练、评估与保存模型
训练脚本把前面的模块全部串起来:
- 加载词表与数据集。
- 划分训练集和测试集。
- 初始化损失函数和优化器。
- 执行多轮训练并打印日志。
- 评估测试集效果。
- 保存训练好的模型权重。
到这里为止,一个能训练、能评估、能导出结果的项目基本就闭环了。
这次复盘里最重要的发现
真正让我印象最深的,其实不是模型结构,而是训练流程里暴露出来的几个问题。
测试集发生了信息泄漏
这是这次复盘里最关键的一点。
我发现词表是在划分训练集和测试集之前,用全部短信一起构建的。这样一来,测试集中的词汇信息其实已经提前泄漏给模型了。
更严重的是,数据里还有不少重复短信。随机切分之后,测试集中有一部分文本也同时出现在训练集中。这样得到的测试结果会比真实效果更乐观。
这让我意识到,评估不准比模型不强更危险。因为一个“看起来准确率不错”的模型,可能只是数据切分方式有问题。
模型保存得还不够完整
训练脚本只保存了模型权重,但没有把词表、最大长度、模型参数配置、标签含义一起保存下来。
这意味着模型虽然训练完了,但单独拿出去做推理会不稳定。因为新短信在部署时未必还能用和训练阶段完全一致的方式转成输入。
也就是说,它更像一个“训练实验结果”,还不能算一个真正可交付的推理组件。
一些模块耦合过重
还有一个比较实际的问题是:有的模块在导入时就会直接读取完整数据,甚至打印大量内容。
这种写法在刚开始练项目时很常见,但一旦项目变大,就会让调试和复用都变得很难受。复盘时再看,会明显感觉到代码边界不够干净。
这套方案的局限在哪里
这个项目能跑通,但它并不是一个终点。
目前最明显的局限有三类。
1. 模型结构偏基础
传统 RNN 在长文本上容易出现长距离依赖丢失和梯度问题,对复杂上下文的表达能力也有限。和 LSTM、GRU、Transformer 相比,上限会低很多。
2. 文本预处理还比较粗
目前主要还是基础分词,没有把停用词过滤、特殊符号清洗、噪声字符处理这些步骤做得足够细。
如果数据本身噪声比较多,模型很容易把注意力浪费在无效信息上。
3. 数据集构建方式还可以更严谨
固定长度补零虽然简单,但也会引入很多无效位置。再加上重复样本和切分策略的问题,都会影响模型最终的泛化能力。
如果继续做下去,我会怎么优化
如果给这个项目继续迭代,我会优先做四件事:
- 先按文本去重,再重新划分训练、验证和测试集。
- 只使用训练集构建词表,避免测试信息泄漏。
- 升级模型结构,从基础 RNN 往 GRU、LSTM 甚至 Transformer 方向走。
- 把推理所需的词表、最大长度、标签映射和模型配置一并保存,做成真正可部署的推理链路。
这篇复盘对我自己的意义
这次项目复盘让我更清楚地意识到,做机器学习项目不能只盯着“模型搭起来了没有”。
数据怎么处理、切分方式是否合理、评估是否可信、模型能不能真正被部署,这些问题往往比单纯跑出一个准确率更重要。
一个项目的质量,很多时候不是由最亮眼的那一层模型决定的,而是由那些容易被忽略的基础环节决定的。
这也是我想把这篇文章发出来的原因:把一次真实项目里踩过的坑、看见的问题和下一步打算,认认真真留档。