4、基于机器学习的摘要方法:朴素贝叶斯、支持向量机在文本分类与摘要中的应用
好,咱们进入第四章。这一章聊的,是机器学习在文本摘要里最经典的两个模型——朴素贝叶斯和支持向量机。
说实话,我刚入行那会儿,觉得深度学习才是王道,朴素贝叶斯这种“老古董”早该淘汰了。后来在做一个金融舆情摘要项目时,数据量不大,标注样本才几千条,深度学习模型怎么调都过拟合。最后是朴素贝叶斯救了我一命。嗯,从那以后我再也不敢小看这些经典模型了。
4.1 朴素贝叶斯:简单但高效的文本分类器
朴素贝叶斯,说白了就是基于贝叶斯定理,加上一个“朴素”的假设——特征之间相互独立。
你想想看,在文本里,这个词出现和那个词出现,真的独立吗?显然不。但神奇的是,就算这个假设不成立,朴素贝叶斯在文本分类任务上依然表现很好。我个人习惯把它当作基线模型,先跑一遍看看数据质量。
4.1.1 数学原理回顾
公式其实很简单:
P(类别|文本) = P(文本|类别) * P(类别) / P(文本)
我们实际计算时,分母都一样,所以只需要比较分子大小:
P(类别|文本) ∝ P(类别) * ∏ P(词_i|类别)
这里有个坑——如果某个词在训练集中没出现过,概率直接变0。我曾经在这个问题上栽过跟头,后来加了拉普拉斯平滑才解决。
4.1.2 在摘要提取中的应用
朴素贝叶斯在摘要里怎么用?主要有两种方式:
- 句子分类:把每个句子分成“该保留”和“该删除”两类
- 主题识别:判断句子属于哪个主题,再按主题抽取关键句
我给大家看一段我当时写的代码,虽然简单,但很实用:
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction.text import TfidfVectorizer
# 假设我们有标注好的句子数据
sentences = ["公司净利润同比增长20%", "市场风险提示", ...]
labels = [1, 0, ...] # 1表示保留,0表示删除
# 特征提取
vectorizer = TfidfVectorizer(max_features=5000)
X = vectorizer.fit_transform(sentences)
# 训练模型
model = MultinomialNB(alpha=1.0) # alpha就是拉普拉斯平滑参数
model.fit(X, labels)
# 对新句子做预测
new_sentence = ["本季度营收创历史新高"]
X_new = vectorizer.transform(new_sentence)
pred = model.predict(X_new) # 1表示应该保留
4.2 支持向量机:小样本下的王者
支持向量机,简称SVM。这玩意儿在深度学习火起来之前,是文本分类的扛把子。
为什么SVM适合文本摘要?因为文本特征维度通常很高(几千到几万维),而SVM天生擅长处理高维稀疏数据。我在一个金融研报摘要项目里,用SVM配合RBF核,在只有2000条标注数据的情况下,F1值达到了0.87。换成深度学习,同等数据量下只有0.79。
4.2.1 SVM的核心思想
SVM说白了就是找一个超平面,把不同类别的数据分开,而且让这个超平面离两边数据都尽可能远。
为什么会这样?因为间隔越大,泛化能力越强。你想想看,如果分类边界紧贴着某个样本点,新来一个稍微不同的样本就可能分错。
下面是我画的一张图,展示了SVM在文本分类中的工作流程:
4.2.2 代码实战:SVM做句子分类
下面是我在金融公告摘要项目中实际用过的代码,做了简化处理:
from sklearn.svm import SVC
from sklearn.pipeline import Pipeline
from sklearn.model_selection import GridSearchCV
# 构建pipeline
pipeline = Pipeline([
('tfidf', TfidfVectorizer(max_features=8000, ngram_range=(1,2))),
('svm', SVC(kernel='linear', C=1.0, class_weight='balanced'))
])
# 参数调优——我建议你一定要做这一步
param_grid = {
'svm__C': [0.1, 1.0, 10.0],
'svm__kernel': ['linear', 'rbf']
}
grid = GridSearchCV(pipeline, param_grid, cv=5, scoring='f1')
grid.fit(train_sentences, train_labels)
print(f"最佳参数: {grid.best_params_}")
print(f"最佳F1: {grid.best_score_:.4f}")
# 预测摘要句子
test_sentences = ["公司发布2023年年度报告", "本报告期内..." , ...]
predictions = grid.predict(test_sentences)
confidence = grid.decision_function(test_sentences) # 置信度
# 按置信度排序,取前3个句子作为摘要
summary_indices = np.argsort(confidence)[-3:][::-1]
4.3 朴素贝叶斯 vs SVM:怎么选?
这个问题我经常被问到。直接给结论:
| 对比维度 | 朴素贝叶斯 | 支持向量机 |
|---|---|---|
| 训练速度 | 极快,适合大规模数据 | 中等,数据量大时较慢 |
| 小样本表现 | 一般,需要较多数据 | 优秀,小样本也能出好效果 |
| 特征维度 | 适合高维,但特征独立性假设限制效果 | 非常适合高维稀疏数据 |
| 可解释性 | 强,可以看每个词的概率 | 中等,线性核可解释,RBF核较难 |
| 金融文本适用场景 | 快速原型、数据量大、特征独立性强 | 小样本、需要高精度、非线性关系 |
我个人习惯是:先用朴素贝叶斯跑一遍,看看数据质量和特征分布。如果效果不理想,再上SVM。说白了,朴素贝叶斯是“快而糙”,SVM是“慢而精”。
4.4 实际项目中的避坑经验
最后分享几个我在项目中踩过的坑:
- 特征选择别偷懒:我曾经只用了unigram(单个词),结果模型把“不”和“好”分开考虑,把“不好”当成了正面词。后来加了bigram,问题解决。
- 类别不平衡要处理:金融公告里,90%的句子都是“废话”,只有10%是核心信息。不做处理的话,模型会学成一个“全删模型”。
- 不要迷信默认参数:SVM的C参数、核函数参数,一定要调。我见过太多人直接用默认参数,效果差就说SVM不行。
- 评估指标要选对:准确率在摘要任务里基本没用。用F1或者ROUGE指标,才能真实反映模型好坏。
嗯,这一章就到这里。朴素贝叶斯和SVM虽然“老”,但在金融文本摘要这个场景下,它们依然是利器。关键是你要知道什么时候用哪个,怎么调参,怎么避坑。