重生指从0开始的机器学习生涯(朴素贝叶斯——垃圾邮件)

我重生了,上一世因为没有好好学习,流浪街头,这一世,我要好好学习,逆天改命!

由于我抢夺了别人的修炼资源,被下了挑战信,现在,我要想办法吧他们都当作垃圾邮件处理了。


朴素贝叶斯

朴素贝叶斯(Naive Bayes)是一种基于贝叶斯定理和特征条件独立假设的分类算法。它被广泛应用于文本分类、垃圾邮件过滤、情感分析等领域。

在朴素贝叶斯分类中,我们首先需要建立一个训练集,该训练集包含了一系列带有标签的样本数据。然后,我们需要提取这些样本的特征。对于文本分类任务,特征可以是单词、词组或其他文本相关的属性。接下来,利用贝叶斯定理和条件独立性假设,通过计算每个类别在给定特征下的概率,来进行分类预测。

朴素贝叶斯算法之所以被称为"朴素",是因为它假设所有特征都是相互独立的,这意味着每个特征对于分类的影响是独立的。尽管这个假设在现实世界中并不总是成立,但在实际应用中,朴素贝叶斯表现良好,并且具有快速的训练和预测速度。

优点:在数据较少的情况下仍然有效,可以处理多类别问题。

缺点:对于输入数据的准备方式较为敏感。

适用数据类型:标称型数据

一、垃圾邮件

垃圾邮件分类是朴素贝叶斯算法的一个典型应用场景。在垃圾邮件分类中,我们可以利用朴素贝叶斯算法对邮件进行自动分类,将其区分为“垃圾邮件”和“非垃圾邮件”。

首先,我们需要准备一个用于训练的数据集,该数据集包含已经标记好的邮件样本,以及与每封邮件相关联的特征,比如单词、短语或其他文本相关的属性。这些特征可以通过文本处理技术如词袋模型(Bag of Words)或 TF-IDF 等方法进行提取。

接下来,利用朴素贝叶斯算法,计算每个特征对应于“垃圾邮件”和“非垃圾邮件”的条件概率。根据贝叶斯定理,结合这些条件概率和特征在待分类邮件中出现的频率,我们可以计算出待分类邮件属于“垃圾邮件”和“非垃圾邮件”的概率。最终,通过比较这两种概率,就可以对待分类邮件进行有效的分类判断。

朴素贝叶斯算法在垃圾邮件分类中的应用具有以下优势:

  1. 高效性:朴素贝叶斯算法具有快速的训练和预测速度,适用于处理大规模的邮件数据。
  2. 准确性:在实际应用中,朴素贝叶斯算法在垃圾邮件分类任务中通常表现良好,能够有效地识别垃圾邮件。
  3. 简单性:算法本身简单易懂,实现起来相对容易,对于初学者也比较友好。

导包

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)

 

总结

实现了一个简单的垃圾邮件分类器。它包括以下几个主要步骤:

  1. replace_num()函数用于过滤掉文本中的数字。
  2. get_filtered_str()函数通过遍历指定目录下的垃圾邮件和正常邮件文件,将文本转换为小写并过滤掉标点符号、数字,最后返回包含所有邮件文本的列表。
  3. get_dict_w()函数根据邮件文本列表生成词频字典,统计单词在垃圾邮件和正常邮件中出现的次数。
  4. get_X_probability()函数计算给定邮件文件中每个单词在对应分类(垃圾邮件或正常邮件)中出现的概率。
  5. email_test()函数进行测试邮件分类。对于每个测试邮件文件,通过调用get_X_probability()函数计算垃圾邮件和正常邮件的概率,并比较两者的结果,根据概率大小判断邮件的分类。
  6. 在主程序中,首先获取经过过滤的垃圾邮件和正常邮件文本列表,然后分别生成垃圾邮件和正常邮件的词频字典。最后调用email_test()函数进行测试邮件分类。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值