我重生了,上一世因为没有好好学习,流浪街头,这一世,我要好好学习,逆天改命!
由于我抢夺了别人的修炼资源,被下了挑战信,现在,我要想办法吧他们都当作垃圾邮件处理了。
朴素贝叶斯
朴素贝叶斯(Naive Bayes)是一种基于贝叶斯定理和特征条件独立假设的分类算法。它被广泛应用于文本分类、垃圾邮件过滤、情感分析等领域。
在朴素贝叶斯分类中,我们首先需要建立一个训练集,该训练集包含了一系列带有标签的样本数据。然后,我们需要提取这些样本的特征。对于文本分类任务,特征可以是单词、词组或其他文本相关的属性。接下来,利用贝叶斯定理和条件独立性假设,通过计算每个类别在给定特征下的概率,来进行分类预测。
朴素贝叶斯算法之所以被称为"朴素",是因为它假设所有特征都是相互独立的,这意味着每个特征对于分类的影响是独立的。尽管这个假设在现实世界中并不总是成立,但在实际应用中,朴素贝叶斯表现良好,并且具有快速的训练和预测速度。
优点:在数据较少的情况下仍然有效,可以处理多类别问题。
缺点:对于输入数据的准备方式较为敏感。
适用数据类型:标称型数据
一、垃圾邮件
垃圾邮件分类是朴素贝叶斯算法的一个典型应用场景。在垃圾邮件分类中,我们可以利用朴素贝叶斯算法对邮件进行自动分类,将其区分为“垃圾邮件”和“非垃圾邮件”。
首先,我们需要准备一个用于训练的数据集,该数据集包含已经标记好的邮件样本,以及与每封邮件相关联的特征,比如单词、短语或其他文本相关的属性。这些特征可以通过文本处理技术如词袋模型(Bag of Words)或 TF-IDF 等方法进行提取。
接下来,利用朴素贝叶斯算法,计算每个特征对应于“垃圾邮件”和“非垃圾邮件”的条件概率。根据贝叶斯定理,结合这些条件概率和特征在待分类邮件中出现的频率,我们可以计算出待分类邮件属于“垃圾邮件”和“非垃圾邮件”的概率。最终,通过比较这两种概率,就可以对待分类邮件进行有效的分类判断。
朴素贝叶斯算法在垃圾邮件分类中的应用具有以下优势:
- 高效性:朴素贝叶斯算法具有快速的训练和预测速度,适用于处理大规模的邮件数据。
- 准确性:在实际应用中,朴素贝叶斯算法在垃圾邮件分类任务中通常表现良好,能够有效地识别垃圾邮件。
- 简单性:算法本身简单易懂,实现起来相对容易,对于初学者也比较友好。
导包
import os
import re
import string
import math
import numpy as np
过滤数字
# 过滤数字
def replace_num(txt_str):
txt_str = re.sub(r'\d+', '', txt_str)
return txt_str
def get_filtered_str(category):
email_list = []
translator = str.maketrans('', '', string.punctuation)
for curDir, dirs, files in os.walk(f'./email/{category}'):
for file in files:
file_name = os.path.join(curDir, file)
with open(file_name, 'r', encoding='utf-8') as f:
txt_str = f.read()
进行过滤
# 全部小写
txt_str = txt_str.lower()
# 过滤掉所有符号
txt_str = txt_str.translate(translator)
# 过滤掉全部数字
txt_str = replace_num(txt_str)
# 把全体的邮件文本 根据换行符把string划分成列表
txt_str_list = txt_str.splitlines()
转换字符串
# 把获取的全体单词句子列表转成字符串
txt_str = ''.join(txt_str_list)
email_list.append(txt_str)
return email_list
def get_dict_w(email_list):
all_email_words = []
word_set = set()
for email_str in email_list:
email_words = email_str.split(' ')
all_email_words.append(email_words)
word_set.update(email_words)
word_dict = {}
for word in word_set:
word_dict[word] = 0
for email_words in all_email_words:
if word in email_words:
word_dict[word] += 1
return word_dict
计算词典出现概率
def get_X_probability(word_dict, email_file):
translator = str.maketrans('', '', string.punctuation)
with open(email_file, 'r', encoding='utf-8') as f:
txt_str = f.read()
txt_str = txt_str.lower()
txt_str = txt_str.translate(translator)
txt_str = replace_num(txt_str)
email_words = txt_str.split(' ')
x_set = set(word for word in email_words if word != '')
x_num = [word_dict[word] for word in x_set if word in word_dict]
w_appear_sum_num = sum(x_num) + 1
return w_appear_sum_num / (len(word_dict) + 2)
对测试邮件进行分类
def email_test(spam_w_dict, ham_w_dict):
for curDir, dirs, files in os.walk(f'./email/test'):
for file in files:
file_name = os.path.join(curDir, file)
print('---------------------------------------------------------------')
print(f'测试邮件: {file}')
p_X_c1 = get_X_probability(spam_w_dict, file_name)
p_X_c2 = get_X_probability(ham_w_dict, file_name)
A = np.log(p_X_c1) + np.log(1 / 2)
B = np.log(p_X_c2) + np.log(1 / 2)
print(f'p1={A},p2={B}')
if A > B:
print('p1>p2,所以是垃圾邮件.')
else:
print('p1<p2,所以是正常邮件.')
if __name__ == '__main__':
spam_email_list = get_filtered_str('spam')
ham_email_list = get_filtered_str('ham')
spam_w_dict = get_dict_w(spam_email_list)
ham_w_dict = get_dict_w(ham_email_list)
email_test(spam_w_dict, ham_w_dict)
完整代码
import os
import re
import string
import math
import numpy as np
# 过滤数字
def replace_num(txt_str):
txt_str = re.sub(r'\d+', '', txt_str)
return txt_str
def get_filtered_str(category):
email_list = []
translator = str.maketrans('', '', string.punctuation)
for curDir, dirs, files in os.walk(f'./email/{category}'):
for file in files:
file_name = os.path.join(curDir, file)
with open(file_name, 'r', encoding='utf-8') as f:
txt_str = f.read()
# 全部小写
txt_str = txt_str.lower()
# 过滤掉所有符号
txt_str = txt_str.translate(translator)
# 过滤掉全部数字
txt_str = replace_num(txt_str)
# 把全体的邮件文本 根据换行符把string划分成列表
txt_str_list = txt_str.splitlines()
# 把获取的全体单词句子列表转成字符串
txt_str = ''.join(txt_str_list)
email_list.append(txt_str)
return email_list
def get_dict_w(email_list):
all_email_words = []
word_set = set()
for email_str in email_list:
email_words = email_str.split(' ')
all_email_words.append(email_words)
word_set.update(email_words)
word_dict = {}
for word in word_set:
word_dict[word] = 0
for email_words in all_email_words:
if word in email_words:
word_dict[word] += 1
return word_dict
def get_X_probability(word_dict, email_file):
translator = str.maketrans('', '', string.punctuation)
with open(email_file, 'r', encoding='utf-8') as f:
txt_str = f.read()
txt_str = txt_str.lower()
txt_str = txt_str.translate(translator)
txt_str = replace_num(txt_str)
email_words = txt_str.split(' ')
x_set = set(word for word in email_words if word != '')
x_num = [word_dict[word] for word in x_set if word in word_dict]
w_appear_sum_num = sum(x_num) + 1
return w_appear_sum_num / (len(word_dict) + 2)
def email_test(spam_w_dict, ham_w_dict):
for curDir, dirs, files in os.walk(f'./email/test'):
for file in files:
file_name = os.path.join(curDir, file)
print('---------------------------------------------------------------')
print(f'测试邮件: {file}')
p_X_c1 = get_X_probability(spam_w_dict, file_name)
p_X_c2 = get_X_probability(ham_w_dict, file_name)
A = np.log(p_X_c1) + np.log(1 / 2)
B = np.log(p_X_c2) + np.log(1 / 2)
print(f'p1={A},p2={B}')
if A > B:
print('p1>p2,所以是垃圾邮件.')
else:
print('p1<p2,所以是正常邮件.')
if __name__ == '__main__':
spam_email_list = get_filtered_str('spam')
ham_email_list = get_filtered_str('ham')
spam_w_dict = get_dict_w(spam_email_list)
ham_w_dict = get_dict_w(ham_email_list)
email_test(spam_w_dict, ham_w_dict)
总结
实现了一个简单的垃圾邮件分类器。它包括以下几个主要步骤:
replace_num()
函数用于过滤掉文本中的数字。get_filtered_str()
函数通过遍历指定目录下的垃圾邮件和正常邮件文件,将文本转换为小写并过滤掉标点符号、数字,最后返回包含所有邮件文本的列表。get_dict_w()
函数根据邮件文本列表生成词频字典,统计单词在垃圾邮件和正常邮件中出现的次数。get_X_probability()
函数计算给定邮件文件中每个单词在对应分类(垃圾邮件或正常邮件)中出现的概率。email_test()
函数进行测试邮件分类。对于每个测试邮件文件,通过调用get_X_probability()
函数计算垃圾邮件和正常邮件的概率,并比较两者的结果,根据概率大小判断邮件的分类。- 在主程序中,首先获取经过过滤的垃圾邮件和正常邮件文本列表,然后分别生成垃圾邮件和正常邮件的词频字典。最后调用
email_test()
函数进行测试邮件分类。