机器学习(NLP文本分类)标准项目流程

第一阶段:环境搭建与数据工程
依赖库导入与环境配置:加载数据处理(Pandas)、自然语言处理(Jieba)、机器学习框架(Scikit-learn)等必要的第三方库,并配置系统参数(如忽略警告、设置日志级别)以优化运行环境。
数据收集与加载:获取原始语料库,构建结构化的数据集(如DataFrame),明确样本数据(Text)与对应的真实标签(Label/Ground Truth)。
第二阶段:特征工程
3. 文本预处理与清洗:针对非结构化的文本数据进行规范化处理。包括统一大小写、去除特殊符号等,以降低数据噪声。
4. 中文分词:由于中文语义的连续性,需调用专用分词工具(如Jieba)将连续的文本序列切分为独立的词汇单元,为后续的特征提取奠定基础。
5. 特征向量化:将处理后的文本数据转化为计算机可计算的数值型矩阵。通过特征提取算法(如TF-IDF)构建特征空间,生成特征矩阵(X)与标签向量(y),完成从“自然语言”到“机器语言”的映射。
第三阶段:模型构建与训练
6. 数据集划分:采用随机抽样方法,将整体数据集按比例(如8:2)划分为训练集(用于模型学习)和测试集(用于效果评估),确保模型评估的客观性。
7. 模型初始化与拟合:实例化具体的机器学习算法(如多项式朴素贝叶斯分类器),并将训练集的特征与标签输入模型。通过算法迭代,使模型自动学习数据中的潜在规律与分类边界。
第四阶段:模型评估与推理
8. 模型预测与性能评估:利用训练完毕的模型对测试集特征进行推理预测,并将预测结果与测试集的真实标签进行比对。通过准确率(Accuracy)、精确率(Precision)、召回率(Recall)等量化指标,全面评估模型的泛化能力。
9. 实战推理与泛化验证:构建全新的、模型从未见过的独立样本,经过完全一致的预处理与向量化流程后输入模型。通过实际预测结果,进一步验证模型在真实业务场景下的鲁棒性,并排查是否存在过拟合或欠拟合现象。

第一步:导入工具包(相当于把做菜需要的锅碗瓢盆、调料都准备好)

1
2
3
4
5
6
7
8
9
10
11
import warnings
warnings.filterwarnings('ignore') # 忽略一些不影响运行的警告信息,让控制台输出更干净

import pandas as pd # 导入数据处理工具 pandas,用来制作和管理表格数据
import jieba # 导入中文分词工具 jieba(你之前提到的“街霸”就是它啦)
from sklearn.feature_extraction.text import TfidfVectorizer # 导入特征提取工具,负责把文字转换成计算机能懂的数字矩阵
from sklearn.naive_bayes import MultinomialNB # 导入朴素贝叶斯分类器,这是我们用来训练的核心AI模型
from sklearn.model_selection import train_test_split # 导入数据集划分工具,用来把数据分成“练习题”和“考试题”
from sklearn.metrics import accuracy_score, classification_report # 导入评估工具,用来给模型打分和出详细的成绩单

jieba.setLogLevel(20) # 设置结巴分词的日志级别,避免它输出太多无关的调试信息干扰我们

第二步:准备数据(相当于给 AI 准备学习的课本)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
data = {
'text': [
# 下面是25条垃圾邮件样本(特征通常包含:中奖、免费、点击、账户异常、发票等)
'Hi, you have won a lottery, click here to claim',
'URGENT! Your account has been compromised!',
'Free Viagra, cheap Cialis, order now!',
'恭喜您中奖!请点击链接领取大奖!',
'【xx贷】急用钱?马上到账!',
'发票,代开,增值税。',
'免费领取iPhone15,仅需支付运费',
'您的包裹已到达,请点击确认收货',
'【银行】您的账户异常,请立即验证',
'兼职赚钱,日入500,无需经验',
'恭喜您获得1000元购物券,限时领取',
'您的订单已发货,请查收',
'【腾讯】您的QQ号存在风险,请验证',
'免费试用,不满意全额退款',
'您的积分即将过期,请尽快兑换',
'【支付宝】您的账户有异常交易',
'中奖通知:您已获得500万大奖',
'您的快递已到达,请签收',
'【10086】您的手机欠费,请充值',
'免费领取精美礼品,仅限前100名',
'您的账户存在风险,请立即处理',
'兼职刷单,轻松赚钱',
'您的订单已取消,请重新下单',
'【银行】您的信用卡额度已提升',
'免费体验高级会员,立即开通',

# 下面是25条正常邮件样本(特征通常包含:会议、附件、项目、查收、讨论等)
'Lunch meeting tomorrow at 12pm?',
'Can you please review the document?',
'你好,下周的会议纪要发你了。',
'周末一起去打球吗?',
'关于项目进度的更新,请查收',
'明天的会议安排已确认',
'请查收附件中的合同文件',
'客户反馈的问题已解决',
'本周工作计划,请审阅',
'关于预算调整的讨论',
'你好,附件是你要的资料',
'下周的出差安排已确认',
'请确认收到此邮件',
'关于产品发布的讨论',
'你好,会议时间已调整',
'请查收项目进度报告',
'关于合同条款的修改建议',
'你好,附件是会议记录',
'请确认下周的会议安排',
'关于产品功能的讨论',
'你好,这是你要的文档',
'请查收客户反馈报告',
'关于项目预算的讨论',
'你好,会议纪要已整理',
'请确认收到此信息'
],
# 标签列:1代表垃圾邮件,0代表正常邮件。前25个对应上面的垃圾邮件,后25个对应正常邮件
'label': [1]*25 + [0]*25
}

# 把上面的字典数据转换成一个标准的表格(DataFrame),方便我们后续处理
df = pd.DataFrame(data)
print("原始数据:")
print(df.head(10)) # 打印表格的前10行看看样子
# 打印数据集的基本统计信息
print(f"数据集总大小: {len(df)}条 (垃圾邮件: {sum(df['label'])}条, 正常邮件: {len(df)-sum(df['label'])}条)")
print("-" * 50)data = {
'text': [
# 下面是25条垃圾邮件样本(特征通常包含:中奖、免费、点击、账户异常、发票等)
'Hi, you have won a lottery, click here to claim',
'URGENT! Your account has been compromised!',
'Free Viagra, cheap Cialis, order now!',
'恭喜您中奖!请点击链接领取大奖!',
'【xx贷】急用钱?马上到账!',
'发票,代开,增值税。',
'免费领取iPhone15,仅需支付运费',
'您的包裹已到达,请点击确认收货',
'【银行】您的账户异常,请立即验证',
'兼职赚钱,日入500,无需经验',
'恭喜您获得1000元购物券,限时领取',
'您的订单已发货,请查收',
'【腾讯】您的QQ号存在风险,请验证',
'免费试用,不满意全额退款',
'您的积分即将过期,请尽快兑换',
'【支付宝】您的账户有异常交易',
'中奖通知:您已获得500万大奖',
'您的快递已到达,请签收',
'【10086】您的手机欠费,请充值',
'免费领取精美礼品,仅限前100名',
'您的账户存在风险,请立即处理',
'兼职刷单,轻松赚钱',
'您的订单已取消,请重新下单',
'【银行】您的信用卡额度已提升',
'免费体验高级会员,立即开通',

# 下面是25条正常邮件样本(特征通常包含:会议、附件、项目、查收、讨论等)
'Lunch meeting tomorrow at 12pm?',
'Can you please review the document?',
'你好,下周的会议纪要发你了。',
'周末一起去打球吗?',
'关于项目进度的更新,请查收',
'明天的会议安排已确认',
'请查收附件中的合同文件',
'客户反馈的问题已解决',
'本周工作计划,请审阅',
'关于预算调整的讨论',
'你好,附件是你要的资料',
'下周的出差安排已确认',
'请确认收到此邮件',
'关于产品发布的讨论',
'你好,会议时间已调整',
'请查收项目进度报告',
'关于合同条款的修改建议',
'你好,附件是会议记录',
'请确认下周的会议安排',
'关于产品功能的讨论',
'你好,这是你要的文档',
'请查收客户反馈报告',
'关于项目预算的讨论',
'你好,会议纪要已整理',
'请确认收到此信息'
],
# 标签列:1代表垃圾邮件,0代表正常邮件。前25个对应上面的垃圾邮件,后25个对应正常邮件
'label': [1]*25 + [0]*25
}

# 把上面的字典数据转换成一个标准的表格(DataFrame),方便我们后续处理
df = pd.DataFrame(data)
print("原始数据:")
print(df.head(10)) # 打印表格的前10行看看样子
# 打印数据集的基本统计信息
print(f"数据集总大小: {len(df)}条 (垃圾邮件: {sum(df['label'])}条, 正常邮件: {len(df)-sum(df['label'])}条)")
print("-" * 50)

第三步:文本预处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 定义一个中文停用词集合。这些词(如“的”、“了”)在邮件里到处都是,但对区分垃圾邮件毫无帮助,反而像噪音一样干扰模型
stop_words = {'的', '了', '吗', '你', '我', '他', '是', '在', '有', '和', '就', '不', '人', '都', '一', '一个', '上', '也', '很', '到', '说', '要', '去', '会', '着', '没有', '看', '好', '自己', '这', '请', '点击'}

# 定义预处理函数,这个函数会应用到每一条邮件文本上
def preprocess(text):
text = text.lower() # 1. 把所有英文字母转成小写(避免 Computer 和 computer 被当成两个词)
words = jieba.cut(text) # 2. 使用结巴分词把句子切成一个个独立的词语
# 3. 核心优化:过滤掉停用词,并且过滤掉长度小于等于1的单字(单字通常信息量太少)
filtered_words = [w for w in words if w not in stop_words and len(w) > 1]
return " ".join(filtered_words) # 4. 把过滤后的词语用空格连起来,变成 "恭喜 中奖 领取" 这种格式

# 使用 apply 方法,把表格中 'text' 列的每一条数据都扔进 preprocess 函数里处理,结果存入新的一列 'processed'
df['processed'] = df['text'].apply(preprocess)
print("\n优化后的预处理数据:")
print(df[['text', 'label', 'processed']].head(10)) # 看看处理前后的对比
print("-" * 50)

第四步:特征提取(把文字变成计算机能计算的数字矩阵)

1
2
3
4
5
# 实例化一个 TF-IDF 向量化工具。max_features=30 表示我们只提取最重要的30个特征词,避免矩阵太大
vectorizer = TfidfVectorizer(max_features=30)
# fit_transform 是核心动作:它先学习整个文本库的词汇规律(fit),然后把文本转换成数字矩阵(transform)
X = vectorizer.fit_transform(df['processed']) # X 就是转换后的数字特征矩阵(相当于考试的题目)
y = df['label'] # y 是每条数据对应的标签(相当于题目的标准答案)

第五步:划分数据集

1
2
3
4
5
6
# test_size=0.2 表示拿出 20% 的数据作为测试集(考试题),剩下的 80% 作为训练集(练习题)
# random_state=0 是一个随机种子,保证每次运行代码时,划分出来的题目和答案都是一模一样的,方便复现结果
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

# 打印划分后的数据量。注意:X 是稀疏矩阵,不能用 len(),要用 .shape[0] 来获取行数
print(f"\n训练集大小: {X_train.shape[0]}条, 测试集大小: {X_test.shape[0]}条")

第六步:训练模型

1
2
model = MultinomialNB() # 实例化一个多项式朴素贝叶斯分类器(这个模型特别适合处理文本词频类的数据)
model.fit(X_train, y_train) # 调用 fit 方法,把训练集的题目(X_train)和答案(y_train)喂给模型,让它开始学习

第七步:预测与评估

1
2
3
4
5
6
7
8
9
10
11
12
y_pred = model.predict(X_test) # 让训练好的模型对测试集(X_test)进行预测,得到它认为的答案(y_pred)
accuracy = accuracy_score(y_test, y_pred) # 将模型预测的答案(y_pred)和真实答案(y_test)进行比对,计算准确率
print(f"\n优化预处理后,模型在测试集上的准确率:{accuracy * 100:.2f}%")

# 打印更详细的分类报告(包含精确率、召回率、F1值,能看出模型在抓垃圾邮件和放过正常邮件上的具体能力)
print("\n详细分类报告:")
print(classification_report(y_test, y_pred, target_names=['正常邮件', '垃圾邮件']))

# 逐条打印测试集的预测结果,方便我们肉眼检查模型到底是在哪些题上犯了错
print("\n测试集详细预测结果:")
for i, (true, pred) in enumerate(zip(y_test, y_pred)):
print(f"样本 {i+1}: 真实标签={true}, 预测标签={pred}")

第八步:实际场景测试

1
2
3
4
5
6
7
8
9
new_text = preprocess("恭喜你中了彩票大奖") # 1. 新句子必须先经过和训练数据一模一样的预处理(分词、去停用词)
new_text_vec = vectorizer.transform([new_text]) # 2. 把预处理后的新句子转换成数字向量(注意这里只用 transform,因为规则之前已经 fit 过了)
prediction = model.predict(new_text_vec) # 3. 让模型进行预测

# 根据预测结果(1或0)打印出人类能看懂的结论
if prediction[0] == 1:
print(f"\n测试句子:'{new_text}' -> 预测结果:垃圾邮件")
else:
print(f"\n测试句子:'{new_text}' -> 预测结果:正常邮件")
核心知识点详细解释关键注意事项
df[‘processed’] = df[‘text’].apply(preprocess)这行代码是 Pandas 里非常经典的用法。apply 就像是一个流水线工人,它会把 df[‘text’] 这一列里的每一条文本,都拿出来扔进 preprocess 这个函数里加工一遍,最后把加工好的结果整齐地放回 df[‘processed’] 这一新列中。批量处理整列数据,是文本预处理最高效的写法
fit_transform 与 transform 区别fit_transform:用在训练阶段。它既负责 “学习” 词汇规则(比如哪个词对应矩阵的第几列),又负责 “转换” 数据。
transform:用在预测阶段。因为规则已经在训练阶段学好了,这里只需要按照同样的规则把新句子转换成数字即可。
预测阶段禁止二次 fit,否则词汇索引错乱,模型失效
X_train.shape[0]X 经过 TfidfVectorizer 转换后,变成了一个稀疏矩阵(一种专门存大量 0 的特殊矩阵,为了省内存)。这种矩阵不能用普通的 len() 测量长度,必须用 .shape 属性查看它的形状(行数,列数),[0] 就代表取行数。稀疏矩阵禁用 len(),统一使用 .shape[0] 统计样本数量