利用朴素贝叶斯分类器实现垃圾邮件分类

一、基本概念

1.贝叶斯公式

贝叶斯公式:

P(B|A)=\frac{P(A|B)P(B)}{P(A)}

其中:P(A),P(B)分别为事件A,B发生的概率;P(B|A) 为事件A已经发生的前提下,事件B发生的概率;P(A|B) 为事件B已经发生的前提下,事件A发生的概率。

一般认为,在上述公式中,P(A),P(B)是先验概率,P(B|A)是似然概率,P(A|B) 是后验概率。

2.朴素贝叶斯分类器(naive Bayes classifier)

朴素贝叶斯分类器,所谓“朴素”,是假定所有输入事件之间是相互独立。进行这个假设是因为独立事件间的概率计算更简单。

在基于P(B|A)=\frac{P(A|B)P(B)}{P(A)}来估计P(B|A)的主要困难在于类条件概率P(A|B)是所有属性上的联合概率,难以从有限的训练样本直接估计而得。为了避开这个障碍,就可以使用朴素贝叶斯分类器采用了“属性条件独立性假设”(attribute conditional independence assumption):对已知类别,假设所有属性相互独立。换言之假设每个属性独立地对分类结果发生影响。

基于属性条件独立性假设,P(B|A)=\frac{P(A|B)P(B)}{P(A)}可以重写为

P(B|A)=\frac{P(A|B)P(B)}{P(A)}=\frac{P(B)}{P(A)}\prod_{i=1}^{d}P(A_{i}| B)

其中 d为属性数目, A_{i}A 在第 i个属性上的取值。

二、实现垃圾邮件分类器

基本过程
  1. 加载数据集:使用load_data函数加载数据集。该函数接收一个文件夹路径作为参数,遍历文件夹中的所有文件,将文件内容读取到X列表中,将标签(0表示正常邮件,1表示垃圾邮件)读取到y列表中。

  2. 合并数据集:将正常邮件和垃圾邮件的X和y列表合并为一个大列表X和y。

  3. 提取特征:使用CountVectorizer对X列表中的文本进行特征提取,将文本转换为向量表示。

  4. 分割训练集和测试集:将整个数据集分割为训练集和测试集,其中80%的数据用于训练,20%的数据用于测试。

  5. 训练模型:使用MultinomialNB训练朴素贝叶斯分类器。

  6. 预测测试集:使用训练好的模型对测试集进行预测。

  7. 输出准确率:计算模型在测试集上的准确率。

  8. 输出混淆矩阵:使用混淆矩阵评估模型性能。

  9. 输出分类报告:使用分类报告评估模型性能。

代码实现

这里使用本地数据集,其中ham的文件夹用于存储正常邮件,spam的文件夹用于存储垃圾邮件

首先,加载需要的头文件

import os
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import confusion_matrix, classification_report

然后,加载数据集,将数据集中的正常邮件和垃圾邮件内容读取到列表中,并进行合并。

# 加载数据集
def load_data(folder):
    X = []
    y = []
    for filename in os.listdir(folder):
        with open(os.path.join(folder, filename), 'r', encoding='utf-8', errors='ignore') as f:
            content = f.read()
            X.append(content)
            y.append(1 if folder.endswith('spam') else 0)
    return X, y

# 加载正常邮件和垃圾邮件
ham_folder = 'D:\ml\Ch04\email\ham'  
spam_folder = 'D:\ml\Ch04\email\spam'  
ham_X, ham_y = load_data(ham_folder)
spam_X, spam_y = load_data(spam_folder)

# 将数据集合并
X = np.array(ham_X + spam_X)
y = np.array(ham_y + spam_y)

接着,使用CountVectorizer对文本进行特征提取,将文本转换为向量表示。然后,将整个数据集分割为训练集和测试集,其中80%的数据用于训练,20%的数据用于测试。

# 提取特征
vectorizer = CountVectorizer()
X = vectorizer.fit_transform(X)

# 分割训练集和测试集
train_size = int(len(y) * 0.8)
X_train, y_train = X[:train_size], y[:train_size]
X_test, y_test = X[train_size:], y[train_size:]

接下来,我们使用MultinomialNB来训练朴素贝叶斯分类器,并使用训练好的模型对测试集进行预测。

# 训练朴素贝叶斯分类器
clf = MultinomialNB()
clf.fit(X_train, y_train)

# 预测测试集
y_pred = clf.predict(X_test)

最后,我们计算模型在测试集上的准确率,并输出分类

# 输出准确率
accuracy = np.mean(y_pred == y_test)
print('Accuracy:', accuracy)

# 输出混淆矩阵
conf_mat = confusion_matrix(y_test, y_pred)
print('Confusion Matrix:')
print(conf_mat)

# 输出分类报告
class_rep = classification_report(y_test, y_pred)
print('Classification Report:')
print(class_rep)

 运行结果:

结果输出了一个输出准确率,混淆矩阵和分类报告

完整代码:

import os
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import confusion_matrix, classification_report

# 加载数据集
def load_data(folder):
    X = []
    y = []
    for filename in os.listdir(folder):
        with open(os.path.join(folder, filename), 'r', encoding='utf-8', errors='ignore') as f:
            content = f.read()
            X.append(content)
            y.append(1 if folder.endswith('spam') else 0)
    return X, y

# 加载正常邮件和垃圾邮件
ham_folder = 'D:\ml\Ch04\email\ham'  
spam_folder = 'D:\ml\Ch04\email\spam'  
ham_X, ham_y = load_data(ham_folder)
spam_X, spam_y = load_data(spam_folder)

# 将数据集合并
X = np.array(ham_X + spam_X)
y = np.array(ham_y + spam_y)

# 提取特征
vectorizer = CountVectorizer()
X = vectorizer.fit_transform(X)

# 分割训练集和测试集
train_size = int(len(y) * 0.8)
X_train, y_train = X[:train_size], y[:train_size]
X_test, y_test = X[train_size:], y[train_size:]

# 训练朴素贝叶斯分类器
clf = MultinomialNB()
clf.fit(X_train, y_train)

# 预测测试集
y_pred = clf.predict(X_test)

# 输出准确率
accuracy = np.mean(y_pred == y_test)
print('Accuracy:', accuracy)

# 输出混淆矩阵
conf_mat = confusion_matrix(y_test, y_pred)
print('Confusion Matrix:')
print(conf_mat)

# 输出分类报告
class_rep = classification_report(y_test, y_pred)
print('Classification Report:')
print(class_rep)

优化性能:

这里提出一个问题,如何优化朴素贝叶斯分类器的性能,具体可以根据以下两种办法

1.平滑技术

在计算条件概率时,如果某个单词在训练集中没有出现过,那么使用极大似然估计将会得到为零的概率,这将会导致分类器的性能下降。因此需要对概率进行平滑处理,常见的平滑方法有拉普拉斯平滑和Lidstone平滑。

具体在实现上,可以在构造MultinomialNB分类器时,设置alpha参数进行平滑处理。

例如,可以将代码修改为::

clf = MultinomialNB(alpha=1.0)

2.特征选择方法

特征选择可以帮助我们从大量的特征中选择最具有区分度的特征,从而提高分类器的性能。常见的特征选择方法有卡方检验、互信息、信息增益等。

在具体实现中,可以通过修改CountVectorizer类中的参数来使用不同的特征选择方法。

例如,可以将代码修改为:

vectorizer = CountVectorizer(max_features=2000, analyzer='word', ngram_range=(1,2), stop_words='english')

其中,max_features参数指定了选择的特征数量,analyzer参数指定了特征提取的方式,ngram_range参数指定了n-gram模型的范围,stop_words参数指定了停用词列表。

三、总结

通过对该算法原理和实现步骤的详细介绍,可以发现朴素贝叶斯分类器具有简单高效、易于实现和良好的分类效果等优点。尽管朴素贝叶斯分类器在某些情况下可能存在一定的局限性,但它仍然是一种重要的垃圾邮件分类算法。未来,可以进一步优化该算法,结合其他技术手段,提高垃圾邮件分类的准确性和效率。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值