一.基于贝叶斯决策理论的分类方法
朴素贝叶斯(Naive Bayes)是一种基于概率统计和特征独立性假设的分类算法。它基于贝叶斯定理,通过学习样本数据的特征与类别之间的条件概率关系,来进行分类预测。
朴素贝叶斯算法的核心思想是假设样本的特征之间相互独立,即每个特征对于分类的贡献是相互独立的。这是一个朴素的假设,因为在实际问题中,特征之间可能存在一定的相关性。尽管如此,朴素贝叶斯仍然在许多实际应用中表现良好。
朴素贝叶斯 |
优点:在数据较少的情况下仍然有效,可以处理多类别问题。 |
缺点:对于输入数据的准备方式较为敏感。 |
适用数据类型:标称型数据。 |
假设现在我们有一个数据集,它由两类数据组成,数据分布如下:
我们现在用p1(x,y)表示数据点(x,y)属于类别1(图中用圆点表示的类别)的概率,用p2(x,y)表示数据点(x,y)属于类别2(图中用三角形表示的类别)的概率,那么对于一个新数据点(x,y),可以用下面的规则来判断它的类别:
·如果p1(x,y)>p2(x,y),那么类别为1。
如果p2(x,y)>p1(x,y),那么类别为2。
也就是说,我们会选择高概率对应的类别。这就是贝叶斯决策理论的核心思想,即选择具有最高概率的决策。
二.贝叶斯原理
先验概率:基于以往历史经验和分析得到的结果,不需要依赖当前发生的条件。
后验概率:从条件概率而来,由因推果,是基于当下发生了事件之后计算的概率,依赖于当前发生的条件。
条件概率:记事件A发生的概率为P(A),事件B发生的概率为P(B),则在B事件发生的前提下,A事件发生的概率即为条件概率,记为P(A|B)。
贝叶斯公式:贝叶斯公式是基于条件概率,通过P(B|A)来求P(A|B),如下:
将A看成“规律”,B看成“现象”,那么贝叶斯公式看成:
全概率公式:表示若事件构成一个完备事件组且都有正概率,则对任意一个事件B都有公式成立:
将全概率公式代入贝叶斯公式中,得到:
三.拉普拉斯修正
若某个属性值在训练集中没有与某个类同时出现过,则训练后的模型会出现过拟合( over-fitting) 现象。比如训练集中没有该样例,因此连乘式计算的概率值为0,这显然不合理。因为样本中不存在(概率为0),不代该事件一定不可能发生。所以为了避免其他属性携带的信息,被训练集中未出现的属性值“ 抹去” ,在估计概率值时通常要进行“拉普拉斯修正”。
拉普拉斯修正通过对频数和总数进行微小的平滑处理,解决了频率为零的问题。其基本思想是在计算概率时,对每个可能的事件发生次数都加上一个常数(通常是1),并对分母加上所有可能的事件数量。这样做可以确保每个事件的概率都不会为零,并且总概率为1。
拉普拉斯修正可以用于各种统计推断和机器学习算法中,特别是在处理小样本数据和稀疏数据时,它能够提供更可靠的估计结果。
四.防溢出策略
条件概率乘法计算过程中,因子一般较小(均是小于1的实数)。当属性数量增多时候,会导致累乘结果下溢出的现象。
在代数中有,因此可以把条件概率累乘转化成对数累加。分类结果仅需对比概率的对数累加法运算后的数值,以确定划定的类别。
五、使用朴素贝叶斯过滤垃圾邮件
import nltk
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
# 下载停用词和训练数据
nltk.download('stopwords')
nltk.download('punkt')
# 加载数据集
spam_data = [
("Special offer! Get 50% off on your next purchase!", "spam"),
("Hey, how are you? Let's hang out sometime.", "not spam"),
("URGENT: Your account has been compromised. Please reset your password.", "spam"),
("Congratulations! You've won a free vacation package.", "spam"),
("Reminder: Meeting at 2 PM today.", "not spam"),
("Please review the attached document.", "not spam")
]
# 数据预处理
stop_words = set(stopwords.words('english'))
def preprocess(text):
tokens = word_tokenize(text.lower())
filtered_tokens = [token for token in tokens if token.isalnum() and token not in stop_words]
return ' '.join(filtered_tokens)
processed_data = [(preprocess(text), label) for text, label in spam_data]
# 特征提取
vectorizer = CountVectorizer()
texts = [text for text, label in processed_data]
labels = [label for text, label in processed_data]
features = vectorizer.fit_transform(texts)
# 拟合分类器
classifier = MultinomialNB()
classifier.fit(features, labels)
# 测试新数据
new_email = "Get a discount on your first purchase!"
new_email_processed = preprocess(new_email)
new_email_features = vectorizer.transform([new_email_processed])
prediction = classifier.predict(new_email_features)
print("预测结果:", prediction[0])
六.实验总结
利用朴素贝叶斯来进行垃圾邮件分类的好处就是,朴素贝叶斯模型发源于古典数学理论,有着坚实的数学基础,以及稳定的分类效率,并且算法也比较简单,容易实现,对于小规模的数据效果很不错。
如果我们使用了样本属性真实情况其实并不是相互独立性的,那么其实这样的分类效果可能不会很好。而且需要知道先验概率,且先验概率很多时候取决于假设,假设的模型可以有很多种,因此在某些时候,会由于假设的先验模型的原因导致预测效果不佳。