眩しさだけは、忘れなかった。|

【机器学习】朴素贝叶斯分类器

源代码文件请点击此处

条件概率的定义和公式

  • 条件概率:事件 B 已发生条件下事件 A 发生的概率,记为 P(A|B),即

P(A|B)=P(AB)P(B)

  • 乘法定理:

P(AB)=P(A)P(B|A)

  • 全概率公式:

P(B)=P(A1)P(B|A1)+P(A2)P(B|A2)+...+P(An)P(B|An)=i=1nP(Ai)P(B|Ai)

  • 贝叶斯(Bayes)公式(逆概率公式):

P(Ai|B)=P(AiB)P(B)=P(Ai)P(B|Ai)P(A1)P(B|A1)+P(A2)P(B|A2)+...+P(An)P(B|An)=P(Ai)P(B|Ai)i=1nP(Ai)P(B|Ai)

  • 独立概率的乘法规则:事件 A 和事件 B 必须相互独立,即一个事件的发生不会影响另一个事件的发生,此时有

P(AB)=P(A)P(B)P(A|B)=P(A|B¯)=P(A)P(B|A)=P(B|A¯)=P(B)

  • 一些小技巧:
    • P(A)=P(A|B)+P(A|B¯)
    • P(AB|C)=P(A|C)P(B|C)

先验概率和后验概率

定义:

  • 先验概率:开始时,我们手中没有任何信息,只能计算一个初始概率。
  • 事件:新的事件发生,有了新的信息。
  • 后验概率:根据这些新信息和先验概率可以得到更好的概率估计。

例如,我们想得知今天下雨的概率:

  • 先验概率:开始时,我们手中没有任何信息,只能粗略估计今天下雨的概率为 20%。
  • 事件:我们在亚马逊雨林中。
  • 后验概率:因此,今天下雨的概率被修正为 70%。

让我们再看以下例子。

【例】某种诊断癌症的试验具有如下效果:被诊断者有癌症,试验反应为阳性的概率为0.95;被诊断者没有癌症,试验反应为阴性的概率为 0.95。现对自然人群进行普查,设被试验的人群中患有癌症的概率为0.005,求:已知试验反应为阳性,该被诊断者确有癌症的概率。

【解】概率树如下:

0.005

0.995

0.95

0.05

0.05

0.95

所有患者

患有癌症

没有癌症

试验反应为阳性

试验反应为阴性

试验反应为阳性

试验反应为阴性

A 表示“患有癌症”,A¯ 表示“患有癌症”;B 表示“试验反应为阳性”,B¯ 表示“试验反应为阴性”。由题意得

P(A)=0.005,P(A¯)=0.995P(B|A)=0.95,P(B¯|A¯)=0.05P(B|A¯)=1P(B¯|A¯)=0.95

由贝叶斯公式得:

P(A|B)=P(AB)P(B)=P(A)P(B|A)P(A)P(B|A)+P(A¯)P(B|A¯)=0.087

通过以上例子可知:

  • 先验概率:根据对自然人群的普查,被试验的人群中患有癌症的概率为0.005(同样,没有癌症的概率为0.995)。
  • 事件:患者接受了试验,且结果为阳性。
  • 后验概率:在得到试验反应为阳性后,该被诊断者确有癌症的概率被修正为 0.087。

使用朴素贝叶斯(Naive Bayes)算法检测垃圾邮件

设电子邮件有 n 个单词 x1,x2,...,xn,则邮件是垃圾邮件的概率为:

P(|x1,x2,...,xn)=P(x1,x2,...,xn|)P()P(x1,x2,...,xn|)P()+P(x1,x2,...,xn|)P()

假设所有单词的出现都是独立的,则有:

P(x1,x2,...,xn|)=P(x1|)P(x2|)...P(xn|)=inP(xi|)P(x1,x2,...,xn|)=P(x1|)P(x2|)...P(xn|)=inP(xi|)

根据条件概率公式有:

P(xi|)=P(xi)P()=xi=xiP(xi|)=xi

所以:

P(|x1,x2,...,xn)=inxiinxi+inxi

化简得:

P(|x1,x2,...,xn)=inxiinxi+inxi

代码如下:

import pandas as pd
import numpy as np
import pickle
import os

pkl_dir = os.path.dirname(os.path.abspath(__file__))
pkl_file = 'emails_words_count.pkl'

'''
该函数用于将邮件中所有单词变为小写,并将出现过的单词转换为列表
输出如下所示:左边为邮件文本,右边为出现过的单词的列表
 text  ...                                              words
0  Subject: naturally irresistible your corporate...  ...  [love, are, 100, even, isguite, %, to, and, yo...
1  Subject: the stock trading gunslinger  fanny i...  ...  [group, penultimate, tanzania, bedtime, edt, s...
2  Subject: unbelievable new homes made easy  im ...  ...  [complete, loan, rate, this, subject:, 3, adva...
'''
def process_email(text):
    text = text.lower()
    return list(set(text.split()))


'''
【建立模型】记录每个单词分别在垃圾邮件和非垃圾邮件中的出现次数
输入:
  - emails:电子邮件数据集
输出:
  - model:二维数组,大小为 (每个邮件的不重复单词个数, 2)
    - [word]['spam']:记录该单词出现在垃圾邮件中的个数
    - [word]['ham']:记录该单词出现在非垃圾邮件中的个数
'''
def words_count(emails):
    pkl_path = pkl_dir + '/' + pkl_file
    if os.path.exists(pkl_path):
        with open(pkl_path, 'rb') as f:
            model = pickle.load(f)
        return model

    model = {} # 该字典记录了每个单词分别在垃圾邮件和非垃圾邮件中的出现次数

    for index, email in emails.iterrows(): # 遍历所有的邮件
        for word in email['words']: # 检测该邮件中的每一个单词
            if word not in model:  # 如果字典中没有这个单词
                model[word] = {'spam': 1, 'ham': 1}  # 初始化为 1,防止后面计算概率时除数为零
            else:                  # 如果字典中已有这个单词
                if email['spam'] == 1:  # 如果该邮件是垃圾邮件
                    model[word]['spam'] += 1
                else:               # 如果该邮件是非垃圾邮件
                    model[word]['ham'] += 1

    with open(pkl_path, 'wb') as f:
        pickle.dump(model, f)

    return model


'''
【推理预测】预测指定邮件是否为垃圾邮件
输入:
  - email:待预测的电子邮件文本
  - model:
  - num_spam:数据集中垃圾邮件的总数
  - num_ham:数据集中非垃圾邮件的总数
'''
def predict_naive_bayes(email, model, num_spam, num_ham):
    email = email.lower() # 待预测邮件文本全部小写化
    words = set(email.split()) # 生成单词列表

    # 计算邮件的总数
    # total = num_ham + num_spam

    # 计算概率
    spams, hams = [1.0], [1.0]
    for word in words:
        if word in model:
            spams.append(model[word]['spam'] / num_spam)
            hams.append(model[word]['ham'] / num_ham)
        # np.prod():计算数组中所有元素的乘积
        prod_spams = np.prod(spams) * num_spam
        prod_hams = np.prod(hams) * num_ham

    return prod_spams / (prod_hams + prod_spams)

# ============================= 主程序 main ===================================
if __name__ == '__main__':
    emails = pd.read_csv('emails.csv')
    emails['words'] = emails['text'].apply(process_email)

    num_emails = len(emails)
    num_spam = sum(emails['spam'])
    num_ham = num_emails - num_spam

    print("邮件总数:", num_emails)
    print("垃圾邮件数:", num_spam)
    print("邮件是垃圾邮件的先验概率:", num_spam / num_emails) # 计算先验概率
    print()

    # 记录每个单词分别在垃圾邮件和非垃圾邮件中的出现次数
    model = words_count(emails)

    # 出现单词 lottery 的邮件是垃圾邮件的概率?
    sum = model['lottery']['spam'] + model['lottery']['ham']
    print("单词 lottery 出现在邮件的次数:", model['lottery'])
    print("出现单词 lottery 的邮件是垃圾邮件的概率:", model['lottery']['spam'] / sum)

    # 出现单词 sale 的邮件是垃圾邮件的概率?
    sum = model['sale']['spam'] + model['sale']['ham']
    print("单词 sale 出现在邮件的次数:", model['sale'])
    print("出现单词 sale 的邮件是垃圾邮件的概率:", model['sale']['spam'] / sum)

    email1 = "Hi mom how are you"
    email2 = "buy cheap lottery easy money now"
    email3 = "meet me at the lobby of the hotel at nine am"
    email4 = "asdfgh"  # 不包含字典中任何一个单词,其为垃圾邮件的概率等于先验概率
    email5 = "As the sun rose, I packed my bags with essentials like a camera, a water bottle, and a few snacks. Excited and ready for the adventure, I hopped into my car and set the GPS to Laojun Mountain. The drive was a pleasant one, with lush green fields and rolling hills passing by the window."

    result = predict_naive_bayes(email5, model, num_spam, num_ham)
    print(result)

本文作者:漫舞八月(Mount256)

本文链接:https://www.cnblogs.com/Mount256/p/18234739

版权声明:本作品采用CC 4.0 BY-SA许可协议进行许可。

posted @   漫舞八月(Mount256)  阅读(7)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开
  1. 1 Main Menu Theme Syd Matters
  2. 2 Luminous Memory (Acyanxi Remix) Acyanxi
  3. 3 夏影 麻枝准
  4. 4 潮騒の香り 水月陵
  5. 5 stand still 井口裕香 (いぐち ゆか)
  6. 6 流星雨 麻枝准
  7. 7 Summer Fantasy 傅许
  8. 8 失う 米白
  9. 9 epilogue 霜月はるか
  10. 10 夏に君を待ちながら 小原好美
  11. 11 桜のような恋でした 鹿乃 (かの)
  12. 12 風は微かに、熱を残し… 水月陵
  13. 13 夏凪ぎ 麻枝准/やなぎなぎ
  14. 14 空に光る 戸越まごめ
  15. 15 木漏れ日 riya
  16. 16 Songbirds Homecomings (ホームカミングス)
  17. 17 宝物になった日 麻枝准/やなぎなぎ
  18. 18 夏影~あの飛行機雲を超えた、その先へ~ 雪桜草 (雪樱草)
  19. 19 快晴 Orangestar (蜜柑星P),初音未来 (初音ミク)
  20. 20 永遠 霜月はるか
  21. 21 Sion 天門
  22. 22 遙かな年月-piano- 麻枝准
  23. 23 夏恋慕 kobasolo/春茶
  24. 24 夏凪ぎ-piano ver.- MANYO/麻枝准
  25. 25 Goodbye Seven Seas -piano ver.- MANYO/麻枝准
  26. 26 Light Years 麻枝准/やなぎなぎ
  27. 27 優しさの記憶 鹿乃 (かの)
Luminous Memory (Acyanxi Remix) - Acyanxi
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.