机器学习——使用朴素贝叶斯分类器实现垃圾邮件检测(python代码+数据集)

这篇具有很好参考价值的文章主要介绍了机器学习——使用朴素贝叶斯分类器实现垃圾邮件检测(python代码+数据集)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

系列文章目录

机器学习——scikit-learn库学习、应用
机器学习——最小二乘法拟合曲线、正则化
机器学习——使用朴素贝叶斯分类器实现垃圾邮件检测(python代码+数据集)



1、概念阐述

贝叶斯公式: P ( A ∣ B ) = P ( A ) P ( B ∣ A ) P ( B ) P(A \mid B)=\frac{P(A) P(B \mid A)}{P(B)} P(AB)=P(B)P(A)P(BA)
贝叶斯概念可以参考这个视频,我觉得还不错。
对于垃圾邮件分类预测,简单来说就是判断一封邮件是垃圾邮件的概率和是正常邮件的概率,哪一个概率大就判定为是哪一种类型的邮件。以 h + h^{+} h+为垃圾邮件, h − h^{-} h为正常邮件,D代表需要验证的邮件,d代表邮件里面的的单词如下:
D = d 1 , d 2 , d 3 , d 4 , d 5 . . . d n D = d_{1} ,d_{2} ,d_{3} ,d_{4} ,d_{5} ...d_{n} D=d1,d2,d3,d4,d5...dn
则一封测试邮件为垃圾邮件和正常邮件的概率公式如下: P ( h + ∣ D ) = P ( h + ) ∗ P ( D ∣ h + ) P ( D ) P\left(h^{+} \mid D\right)=\frac{P\left(h^{+}\right) * P\left(D \mid h^{+}\right)}{P(D)} P(h+D)=P(D)P(h+)P(Dh+)
P ( h − ∣ D ) = P ( h − ) ∗ P ( D ∣ h − ) P ( D ) P\left(h^{-} \mid D\right)=\frac{P\left(h^{-}\right) * P\left(D \mid h^{-}\right)}{P(D)} P(hD)=P(D)P(h)P(Dh)
P ( h − ∣ D ) P\left(h^{-} \mid D\right) P(hD) :测试邮件为正常邮件的概率
P ( h + ∣ D ) P\left(h^{+} \mid D\right) P(h+D) :测试邮件为垃圾邮件的概率
P ( h − ) P\left(h^{-}\right) P(h) :一封邮件为正常邮件的概率(先验数据集)
P ( h + ) P\left(h^{+}\right) P(h+):一封邮件为垃圾邮件的概率(先验数据集)
下面三个公式描述的可能不太对
P ( D ∣ h + ) P\left(D \mid h^{+}\right) P(Dh+) :垃圾邮件是测试邮件的概率
P ( D ∣ h − ) P\left(D \mid h^{-}\right) P(Dh) :正常邮件是测试邮件的概率
P ( D ) P(D) P(D) :测试邮件的概率

因为独立事件间的概率计算更加简单,为了简便计算,朴素贝叶斯假定所有输入事件之间是相互独立的。也就是邮件里的每个单词相互独立与出现的先后顺序无关。由朴素贝叶斯定理公式可以分解为如下:
P ( h + ∣ D ) = P ( h + ) ∗ P ( d 1 ∣ h + ) ∗ P ( d 2 ∣ h + ) ∗ . . . ∗ P ( d n ∣ h + ) P ( d 1 ) ∗ P ( d 2 ) ∗ . . . ∗ P ( d n ) P\left(h^{+} \mid D\right)=\frac{P\left(h^{+}\right) * P\left(d_{1 } \mid h^{+}\right)* P\left(d_{2 } \mid h^{+}\right)*...* P\left(d_{n } \mid h^{+}\right)}{P(d_{1})*P(d_{2})*...*P(d_{n})} P(h+D)=P(d1)P(d2)...P(dn)P(h+)P(d1h+)P(d2h+)...P(dnh+)
P ( h − ∣ D ) = P ( h − ) ∗ P ( d 1 ∣ h − ) ∗ P ( d 2 ∣ h − ) ∗ . . . ∗ P ( d n ∣ h − ) P ( d 1 ) ∗ P ( d 2 ) ∗ . . . ∗ P ( d n ) P\left(h^{-} \mid D\right)=\frac{P\left(h^{-}\right) * P\left(d_{1 } \mid h^{-}\right)* P\left(d_{2 } \mid h^{-}\right)*...* P\left(d_{n } \mid h^{-}\right)}{P(d_{1})*P(d_{2})*...*P(d_{n})} P(hD)=P(d1)P(d2)...P(dn)P(h)P(d1h)P(d2h)...P(dnh)
P ( d n ∣ h + ) P\left(d_{n } \mid h^{+}\right) P(dnh+):代表了测试邮件中的一个单词在垃圾邮件邮件中刚出现的概率(先验数据集), P ( d n ∣ h − ) P\left(d_{n } \mid h^{-}\right) P(dnh)同理。
P ( h + ∣ D ) P\left(h^{+} \mid D\right) P(h+D)整个式子就是求:( P ( h − ) P\left(h^{-}\right) P(h)乘测试邮件中的每个单词在垃圾邮件中出现的概率) 除上(每个单词在垃圾邮件和正常邮件中出现的概率) P ( h − ∣ D ) P\left(h^{-} \mid D\right) P(hD)同理。

但在实际计算中为了防止概率太小导致最后结果四舍五入约等于0,会把上面的概率取log再相加。
因为 P ( h + ∣ D ) P\left(h^{+} \mid D\right) P(h+D) P ( h − ∣ D ) P\left(h^{-} \mid D\right) P(hD)的分母一样,我们的目的是比较两者的概率大小,为了方便计算把分母省略了。
以上参考了B站唐宇迪的讲解。

这段代码实现了一个朴素贝叶斯分类器来对电子邮件进行分类,其中包括读取数据、文本预处理、训练分类器和预测新邮件的过程。 具体来说,代码中使用get_data 函数从指定目录 DATA_DIR 中读取数据,并将 Spam 和 Ham 的电子邮件内容分别存储在 data 和 target 列表中。在数据预处理过程中,使用 preprocess 函数对文本进行处理,包括转为小写、去除标点符号和停用词等操作。接下来实现了 NaiveBayesClassifier 类的 fit 和 predict 方法,其中 fit方法用于训练朴素贝叶斯分类器,predict 方法用于对新邮件进行分类。 在 fit 方法中,首先定义了四个 defaultdict类型的变量,包括每个类别的文档数 class_total,每个类别中所有单词出现次数之和 word_total,每个类别中每个单词出现次数word_given_class 和词汇表 vocabulary。然后遍历训练集 X 和标签 y,使用 preprocess 函数对文本进行处理,将处理后的文本和标签一起用于更新 class_total、word_total、word_given_class 和vocabulary 等变量。 在 predict方法中,首先使用训练集中每个类别的文档数计算了每个类别的先验概率的对数,这样可以避免概率值太小而导致下溢。然后遍历待分类邮件 X,使用preprocess 函数对文本进行处理,计算该邮件属于每个类别的概率的对数,最终选择概率最大值对应的类别作为预测结果。

2、代码

代码中的一些函数使用说明参考:http://t.csdn.cn/VGQjB

读取数据

DATA_DIR = 'enron'  # 数据集地址
target_names = ['ham', 'spam']  # 正常、 垃圾 
stopwords = set(open('stopwords.txt', 'r').read().splitlines())   # .splitlines() 按换行符分割

def get_data(DATA_DIR):
    subfolders = ['enron%d' % i for i in range(1,7)]  # 返回enron1-enron7列表
    data = []
    target = []
    for subfolder in subfolders: # 对enron1-enron7依次遍历
        # spam
        spam_files = os.listdir(os.path.join(DATA_DIR, subfolder, 'spam')) # 获文件夹下的所有文件 返回一个列表
        for spam_file in spam_files: # 依次打开返回的文件
            with open(os.path.join(DATA_DIR, subfolder, 'spam', spam_file), encoding="latin-1") as f:
                data.append(f.read())
                target.append(1)  # 垃圾邮件标签 为1
        # ham
        ham_files = os.listdir(os.path.join(DATA_DIR, subfolder, 'ham'))
        for ham_file in ham_files:
            with open(os.path.join(DATA_DIR, subfolder, 'ham', ham_file), encoding="latin-1") as f:
                data.append(f.read())
                target.append(0)  # 正常邮件标签 为0
    return data, target

数据转换

def preprocess(text):
    """
    对文本进行处理,包括去除标点、转为小写、去除停用词等操作。
    """
    text = text.lower()  # 转为小写
    text = re.sub(f'[{string.punctuation}]', ' ', text)  # 去除标点符号
    text = [word for word in text.split() if word not in stopwords]  # 去除停用词
    return text

朴素贝叶斯函数

训练和预测

class NaiveBayesClassifier():
    def __init__(self):
        self.vocabulary = set()  # 词汇表
        self.class_total = defaultdict(int)  # 每个类别的文档数
        self.word_total = defaultdict(int)  # 每个类别中所有单词出现次数之和
        self.word_given_class = defaultdict(lambda: defaultdict(int))  # 每个类别中每个单词出现次数

    def fit(self, X, y):
        """
        训练分类器,其中 X 为训练集数据,y 为训练集标签。
        """
        for text, label in zip(X, y):
            words = preprocess(text)  # 对文本进行处理,包括去除标点、转为小写、去除停用词等操作。
            self.class_total[label] += 1   # 该类别文档数加1
            for word in words:             # 遍历每一个单词
                self.vocabulary.add(word)   # 加入词汇表
                self.word_given_class[label][word] += 1  # 该类别中该单词出现次数加1
                self.word_total[label] += 1  # 该类别所有单词出现次数之和加1

    def predict(self, X):
        """
        对新邮件进行分类,其中 X 为待分类邮件。
        """
        log_priors = {}  # 存储每个类别的先验概率的对数(用于避免下溢)
        for c in self.class_total.keys():
            #  log(每个类别的文档数/文档数)  也就是训练集正常邮件和垃圾邮件占总邮件的比例
            log_priors[c] = math.log(self.class_total[c] / sum(self.class_total.values())) 

        predictions = []
        for text in X:  # 遍历测试集的每一个邮件
            words = preprocess(text) # 对文本进行处理,包括去除标点、转为小写、去除停用词等操作。

            log_probs = {}
            for c in self.class_total.keys(): #遍历两个类别  正常和垃圾邮件类别
                log_probs[c] = log_priors[c]
                for word in words:  # 遍历每个单词
                    if word in self.vocabulary:  # 如果测试邮件的这个单词在对应类别词汇表中
                        # 计算条件概率的对数
                        # 这里需要说明一下: +1是为了防止有些单词在测试样本中出现而垃圾邮件或正常邮件中没有导致概率为0 的情况
                        # 取log是为了防止概率太小 导致最后结果约等于0
                        log_probs[c] += math.log((self.word_given_class[c][word] + 1) / (self.word_total[c] + len(self.vocabulary)))  
            predictions.append(max(log_probs, key=log_probs.get))  # 取概率最大值对应的类别为预测结果

        return predictions

测试准确率

# 读取数据
X, y = get_data(DATA_DIR)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)  # 划分测试集和训练集

# 训练分类器
clf = NaiveBayesClassifier() # 实例化分类器
clf.fit(X_train, y_train)    # 送入数据训练
predictions = clf.predict(X_test)

#模型准确率
accuracy = np.sum(np.array(predictions) == np.array(y_test)) / len(y_test) # 计算准确率
print(f'Accuracy: {accuracy:.2f}')

预测新邮件

# 预测新邮件,并输出分类结果和准确率
new_email = 'Subject: et & s photo contest - announcing the winners\nCongratulations to the following winners of the 2001 ET & S photo contest. Over 200 entries were submitted! The winning photos will be displayed in the 2001 ET & S public education calendar.'
prediction = clf.predict([new_email])[0]
predictions = clf.predict(X_test)
accuracy = np.sum(np.array(predictions) == np.array(y_test)) / len(y_test)

print(f'Prediction: {target_names[prediction]}')
print(f'Accuracy: {accuracy:.2f}')

总代码

代码几乎每一行都加了注释,这里就不解释了。

import os
import re
import string
import math
import numpy as np
from collections import defaultdict
from sklearn.model_selection import train_test_split


DATA_DIR = 'enron'  # 数据集地址
target_names = ['ham', 'spam']  # 正常、 垃圾 
stopwords = set(open('stopwords.txt', 'r').read().splitlines())   # .splitlines() 按换行符分割


def get_data(DATA_DIR):
    subfolders = ['enron%d' % i for i in range(1,7)]  # 返回enron1-enron7列表
    data = []
    target = []
    for subfolder in subfolders: # 对enron1-enron7依次遍历
        # spam
        spam_files = os.listdir(os.path.join(DATA_DIR, subfolder, 'spam')) # 获文件夹下的所有文件 返回一个列表
        for spam_file in spam_files: # 依次打开返回的文件
            with open(os.path.join(DATA_DIR, subfolder, 'spam', spam_file), encoding="latin-1") as f:
                data.append(f.read())
                target.append(1)  # 垃圾邮件标签 为1
        # ham
        ham_files = os.listdir(os.path.join(DATA_DIR, subfolder, 'ham'))
        for ham_file in ham_files:
            with open(os.path.join(DATA_DIR, subfolder, 'ham', ham_file), encoding="latin-1") as f:
                data.append(f.read())
                target.append(0)  # 正常邮件标签 为0
    return data, target


def preprocess(text):
    """
    对文本进行处理,包括去除标点、转为小写、去除停用词等操作。
    """
    text = text.lower()  # 转为小写
    text = re.sub(f'[{string.punctuation}]', ' ', text)  # 去除标点符号
    text = [word for word in text.split() if word not in stopwords]  # 去除停用词
    return text


class NaiveBayesClassifier():
    def __init__(self):
        self.vocabulary = set()  # 词汇表
        self.class_total = defaultdict(int)  # 每个类别的文档数
        self.word_total = defaultdict(int)  # 每个类别中所有单词出现次数之和
        self.word_given_class = defaultdict(lambda: defaultdict(int))  # 每个类别中每个单词出现次数

    def fit(self, X, y):
        """
        训练分类器,其中 X 为训练集数据,y 为训练集标签。
        """
        for text, label in zip(X, y):
            words = preprocess(text)  # 对文本进行处理,包括去除标点、转为小写、去除停用词等操作。
            self.class_total[label] += 1   # 该类别文档数加1
            for word in words:             # 遍历每一个单词
                self.vocabulary.add(word)   # 加入词汇表
                self.word_given_class[label][word] += 1  # 该类别中该单词出现次数加1
                self.word_total[label] += 1  # 该类别所有单词出现次数之和加1

    def predict(self, X):
        """
        对新邮件进行分类,其中 X 为待分类邮件。
        """
        log_priors = {}  # 存储每个类别的先验概率的对数(用于避免下溢)
        for c in self.class_total.keys():
            #  log(每个类别的文档数/文档数)  也就是训练集正常邮件和垃圾邮件占总邮件的比例
            log_priors[c] = math.log(self.class_total[c] / sum(self.class_total.values())) 

        predictions = []
        for text in X:  # 遍历测试集的每一个邮件
            words = preprocess(text) # 对文本进行处理,包括去除标点、转为小写、去除停用词等操作。

            log_probs = {}
            for c in self.class_total.keys(): #遍历两个类别
                log_probs[c] = log_priors[c]
                for word in words:  # 遍历每个单词
                    if word in self.vocabulary:  # 如果测试邮件的这个单词在对应类别词汇表中
                        # 计算条件概率的对数
                        log_probs[c] += math.log((self.word_given_class[c][word] + 1) / (self.word_total[c] + len(self.vocabulary)))  
            predictions.append(max(log_probs, key=log_probs.get))  # 取概率最大值对应的类别为预测结果

        return predictions
# 预测新邮件,并输出分类结果和准确率
new_email = 'Subject: et & s photo contest - announcing the winners\nCongratulations to the following winners of the 2001 ET & S photo contest. Over 200 entries were submitted! The winning photos will be displayed in the 2001 ET & S public education calendar.'
prediction = clf.predict([new_email])[0]
predictions = clf.predict(X_test)
accuracy = np.sum(np.array(predictions) == np.array(y_test)) / len(y_test)

print(f'Prediction: {target_names[prediction]}')
print(f'Accuracy: {accuracy:.2f}')

数据集加工程文件

软件: anaconda python环境
链接:https://download.csdn.net/download/weixin_45464524/87689982


总结

终于水完了,,,文章来源地址https://www.toymoban.com/news/detail-496123.html

到了这里,关于机器学习——使用朴素贝叶斯分类器实现垃圾邮件检测(python代码+数据集)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 机器学习-朴素贝叶斯过滤垃圾邮件

    什么是朴素贝叶斯算法:用贝叶斯定理来预测一个未知类别的样本属于各个类别的可能性,选择可能性最大的一个类别作为该样本的最终类别。 用这个算法处理垃圾邮件就可以理解为:用贝叶斯定理来预测一封由若干个单词组成的不知道是否为垃圾邮件的邮件,它是垃圾邮件

    2024年02月09日
    浏览(45)
  • 基于朴素贝叶斯的垃圾邮件分类Python实现

    垃圾邮件的问题一直困扰着人们,传统的垃圾邮件分类的方法主要有\\\"法\\\"和\\\"校验码法\\\"等,然而这两种方法效果并不理想。其中,如果使用的是“”法,垃圾邮件中如果这个被拆开则可能识别不了,比如,“中奖”如果被拆成“中 ~~~ 奖”可能会识别不了。

    2024年02月02日
    浏览(43)
  • 朴素贝叶斯(垃圾邮件分类)

      朴素贝叶斯是经典的机器学习算法之一,也是为数不多的基于概率论的分类算法。对于大多数的分类算法,在所有的机器学习分类算法中,朴素贝叶斯和其他绝大多数的分类算法都不同。比如决策树,KNN,逻辑回归,支持向量机等,他们都是判别方法,也就是直接学习出特

    2024年02月07日
    浏览(50)
  • python:基于朴素贝叶斯算法的垃圾邮件过滤分类

    目录 一、朴素贝叶斯算法 1.概述 2.推导过程 二、实现垃圾邮件过滤分类 1.垃圾邮件问题背景 2.朴素贝叶斯算法实现垃圾邮件分类的步骤 3.python实现 参考学习网址:https://blog.csdn.net/weixin_59450364/article/details/124343350 1.概述        朴素贝叶斯法(Naive Bayes model)是基于贝叶斯定

    2024年02月07日
    浏览(87)
  • 机器学习算法——贝叶斯分类器3(朴素贝叶斯分类器)

    基于贝叶斯公式来估计后验概率P(c|x)的主要困难在于:类条件概率P(x|c)是所有属性上的联合概率,难以从有限的训练样本直接估计而得。 为避开这个障碍,朴素贝叶斯分类器(Naive Bayes classfier)采用了“ 属性条件独立性假设 ”:对已知类别,假设所有属性相互独立。换句话

    2023年04月22日
    浏览(58)
  • 毕设 垃圾邮件(短信)分类算法实现 机器学习 深度学习

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天

    2024年01月22日
    浏览(57)
  • 竞赛 垃圾邮件(短信)分类算法实现 机器学习 深度学习

    🔥 优质竞赛项目系列,今天要分享的是 🚩 垃圾邮件(短信)分类算法实现 机器学习 深度学习 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分 工作量:3分 创新点:4分 🧿 更多资料, 项目分享: https:

    2024年04月17日
    浏览(32)
  • 机器学习--朴素贝叶斯分类器

    第1关:条件概率 什么是条件概率 概率指的是某一事件 A 发生的可能性,表示为 P(A) 。而条件概率指的是某一事件 A 已经发生了条件下,另一事件 B 发生的可能性,表示为 P(B|A) ,举个例子: 今天有 25% 的可能性下雨,即 P(下雨)=0.25 ; 今天 75% 的可能性是晴天,即 P(晴天)=0.7

    2024年02月08日
    浏览(64)
  • 机器学习实验 - 朴素贝叶斯分类器

    报告内容仅供学习参考,请独立完成作业和实验喔~ 1.1 实验要求 (1)了解朴素贝叶斯与半朴素贝叶斯的区别与联系,掌握高斯分布、多项式分布和伯努利分布的朴素贝叶斯计算方法。 (2)编程实现朴素贝叶斯分类器,基于多分类数据集,使用朴素贝叶斯分类器实现多分类预

    2024年02月09日
    浏览(52)
  • 【机器学习】分类算法 - 朴素贝叶斯 MultinomialNB

    「作者主页」: 士别三日wyx 「作者简介」: CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」: 对网络安全感兴趣的小伙伴可以关注专栏《网络安全入门到精通》 md5() 可以计算字符串的 「MD5散列值」 。 语法 参数 $str :需要计算的字符串

    2024年02月14日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包