一.贝叶斯公式
1.先验概率
P(cj)代表还没有训练模型之前,根据历史数据/经验估算cj拥有的初始概率。P(cj)常被称为cj的先验概率(prior probability) ,它反映了cj的概率分布,该分布独立于样本。
通常可以用样例中属于cj的样例数|cj|比上总样例数|D|来近似,即:
2.后验概率
给定数据样本x时cj成立的概率P(cj | x )被称为后验概率(posterior probability),因为它反映了在看到数据样本 x后 cj 成立的置信度。(大部分机器学习模型尝试得到后验概率。)
3.贝叶斯定理
已知两个独立事件A和B,事件B发生的前提下,事件A发生的概率可以表示为P(A|B),即上图中橙色部分占红色部分的比例,即:
4.机器学习两大视角
·生成式模型:
估计的是联合概率分布,然后求出条件概率分布P(Y|X)作为预测的模型,即生成模型:P(Y|X)= P(X,Y)/ P(X)。
生成方法关心的是给定输入x产生输出y的生成关系。
·判别式模型:
估计的是条件概率分布,有数据直接学得决策函数P(X)或者条件概率分布P(Y|X)作为预测的模型。
判别式方法关心的是给定输入X,应该预测什么样的输出Y。
二.基于贝叶斯的垃圾邮件分类
·基本流程
1.准备数据集:收集一定数量的垃圾邮件和正常邮件,并标记好它们的分类。
2.分词:对每封邮件进行分词处理,将邮件内容拆分成单词。
3.统计词频:统计每个单词在垃圾邮件和正常邮件中出现的频率,并计算其在垃圾邮件和正常邮件中出现的概率。
4.计算联合概率:对于每封邮件,根据其包含的单词及其出现概率,计算它属于垃圾邮件和正常邮件的联合概率。
5.决策分类:选择联合概率更高的分类作为该封邮件的分类。
·代码如下
import os
import nltk
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
# 下载停用词列表
nltk.download('stopwords')
# 加载英语停用词
stop_words = set(stopwords.words('english'))
# 定义文本处理函数
def process_text(text):
# 将文本转换为小写
text = text.lower()
# 分词
tokens = word_tokenize(text)
# 去除停用词
tokens = [token for token in tokens if token not in stop_words]
# 仅保留字母字符
tokens = [token for token in tokens if token.isalpha()]
# 将词汇转换为词干
stemmer = nltk.PorterStemmer()
tokens = [stemmer.stem(token) for token in tokens]
# 将所有词汇连接为一个字符串
text = ' '.join(tokens)
return text
# 定义读取文件函数
def read_file(file_path):
with open(file_path, 'r', encoding='utf-8') as f:
text = f.read()
return text
# 定义获取文件列表函数
# 定义获取文件列表函数
def get_files(data_dir):
spam_files = [os.path.join(data_dir, 'spam', file) for file in os.listdir(os.path.join(data_dir, 'spam'))]
ham_files = [os.path.join(data_dir, 'ham', file) for file in os.listdir(os.path.join(data_dir, 'ham'))]
return spam_files, ham_files
# 使用新的文件路径调用函数
data_dir = r'D:\新建文件夹\pythonTest\email'
spam_files, ham_files = get_files(data_dir)
print(spam_files)
print(ham_files)
# 定义生成特征集函数
def get_features(text):
features = {}
for word in text.split():
features[word] = True
return features
# 加载数据集
data_dir = './email'
spam_files, ham_files = get_files(data_dir)
# 处理文本并生成特征集
spam_data = [(get_features(process_text(read_file(file))), 'spam') for file in spam_files]
ham_data = [(get_features(process_text(read_file(file))), 'ham') for file in ham_files]
all_data = spam_data + ham_data
# 划分训练集和测试集
train_size = int(len(all_data) * 0.8)
train_data = all_data[:train_size]
test_data = all_data[train_size:]
# 训练朴素贝叶斯分类器
classifier = nltk.NaiveBayesClassifier.train(train_data)
# 在测试集上评估分类器的性能
accuracy = nltk.classify.accuracy(classifier, test_data)
print('Accuracy:', accuracy)
# 对新邮件进行分类
new_email = 'Dear customer, your account has been selected to receive a prize of $1,000,000! Click here to claim your prize now!'
new_email_features = get_features(process_text(new_email))
prediction = classifier.classify(new_email_features)
print('Prediction:', prediction)
·代码解析
- 定义文本处理函数
process_text()
,用于将文本转换为小写、分词、去除停用词、只保留字母字符、将词汇转换为词干等操作,以减少特征数量。 - 定义读取文件函数
read_file()
,用于读取指定文件的内容。 - 定义获取文件列表函数
get_files()
,用于获取指定文件夹中的所有文件路径列表。 - 定义生成特征集函数
get_features()
,用于将文本转换为特征集,其中特征为单词,值为True或False,表示单词是否在文本中出现过。 - 加载数据集,包括垃圾邮件和非垃圾邮件,对每个邮件生成特征集,并按照80%的比例划分训练集和测试集。
- 使用朴素贝叶斯分类器训练模型,并在测试集上评估模型的性能。
- 对新邮件进行分类,并输出结果。
·运行结果
从输出结果可以看出,数据集已成功加载,并且训练集和测试集已正确划分。模型在测试集上的准确率为0.975,预测一封新邮件为垃圾邮件。
三.实验小结
1.我们可能发生的错误
由于涉及到数据集问题,我们要将正确的数据集路径写进代码,否则很可能就会出现我这样的问题
2.在处理 NLTK stopwords
资源加载错误时,大概率就是资源加载路径的问题,我也查询了很多资料,这个命令会输出所有 NLTK 数据的路径列表:
import nltk
print(nltk.data.path)
希望大家共同进步!