Python 朴素贝叶斯练习:计数、先验与平滑
朴素贝叶斯大部分工作就是细致地计数。这些练习构造计数表、转成平滑概率、在对数空间比较类别,并在未参与训练的文本上检查结果。
练习:为每个类别建立计数表
标签不是特征。先按标签拆分训练文档,再在每个组内统计词元。所有文档必须使用相同的分词规则。
docs = [("good movie", "pos"), ("great film", "pos"), ("bad movie", "neg"), ("boring film", "neg")]
counts = {}
for text, label in docs:
counts.setdefault(label, {})
for word in text.split():
counts[label][word] = counts[label].get(word, 0) + 1
print(counts["pos"])
print(counts["neg"])按标签分组的证据
练习:计算类别先验
先验是某个类别在文档中的占比。当类别极不平衡时,它尤其重要。打印两个先验,并检查它们之和为一。
labels = ["pos", "pos", "neg", "neg"]
for label in ("pos", "neg"):
print(label, labels.count(label) / len(labels))每个类别有多常见?
练习:平滑一个没见过的词
不做平滑时,某类别从未出现的词会让整个乘积变成零。给每个计数加一,并在分母加上词表大小。
counts = {"great": 0}
total = 4
vocab_size = 6
probability = (counts.get("great", 0) + 1) / (total + vocab_size)
print(round(probability, 2))是很小的概率,不是零
练习:比较对数分数
类别分数等于对数先验加上每个词的对数似然。比较两个候选分数,不需要连乘很小的数。分数更大者获胜,同时要规定确定性的平局规则。
import math
pos = math.log(0.5) + math.log(0.2) + math.log(0.2)
neg = math.log(0.5) + math.log(0.1) + math.log(0.1)
print(round(pos, 2), round(neg, 2))
print("pos" if pos > neg else "neg")先加对数,再比较
练习:预测留出文本
用训练文档建立模型,再给新文档分类。两个例子上的准确率只是快速检查,不能证明生产质量。
import math
train = [("good movie", "pos"), ("great film", "pos"), ("bad movie", "neg"), ("boring film", "neg")]
tests = [("great movie", "pos"), ("boring movie", "neg")]
vocab = sorted({word for text, _ in train for word in text.split()})
counts = {}
priors = {}
for text, label in train:
priors[label] = priors.get(label, 0) + 1
counts.setdefault(label, {})
for word in text.split():
counts[label][word] = counts[label].get(word, 0) + 1
def predict(text):
scores = {}
for label in counts:
total = sum(counts[label].values())
score = math.log(priors[label] / len(train))
for word in text.split():
score += math.log((counts[label].get(word, 0) + 1) / (total + len(vocab)))
scores[label] = score
return max(scores, key=scores.get)
correct = sum(predict(text) == label for text, label in tests)
print(correct / len(tests))一次快速检查,不是基准测试
你的练习清单
- 训练和预测使用同一个分词器。
- 不要把标签放进特征词表。
- 对词表中的每个词都做拉普拉斯平滑。
- 在对数空间计分,并规定平局规则。
- 在留出文本上评估,并报告样本量。
常见问题
朴素贝叶斯需要神经网络吗?
不需要。它是基于计数的概率分类器,也是许多文本任务的强基线。
词不在词表里怎么办?
常见做法是忽略它,或映射到训练时已经存在的未知词元特征。要在评估前定好。
为什么对数分数都是负数?
概率最大为一,所以对数最大为零。比较相对大小即可,不必纠结符号。
练习计数与计分
12 道题,覆盖计数、先验、平滑、对数分数与留出预测。
继续阅读: