zoukankan      html  css  js  c++  java
  • 朴素贝叶斯

    介绍

    朴素贝叶斯是监督学习分类算法
    分类方法:比如已知一个数据集由两类数据(类A,类B)组成,对于一个数据x,如果x属于A的概率大于x属于B的概率,那么x属于A类。
    如何计算相关概率:使用条件概率进行分类
    条件概率
    在事件B发生的条件下事件A发生的概率(p(A|B))
    (p(A|B)=frac{p(A cap B)}{p(B)})
    (p(A cap B)=p(A|B){p(B)})
    (p(A cap B)=p(B|A){p(A)})
    所以可得贝叶斯公式
    (P(A | B)=frac{P(A) P(B | A)}{P(B)})
    其中先验概率p(A)后验概率p(A|B)


    所以通过贝叶斯公式求得(p(x|A))(p(a|B))的值进行比较,因为公式中p(x)都是相同的,所以实际只需要分别计算(P(A) P(x | A))(P(B) P(x | B))比较即可
    朴素的含义
    在此算法中,是假定每一个属性是独立的,所以对于(p(w_{i}|B))可由(p(w_{1}|B)p(w_{2}|B)···p(w_{n}|B))得到
    朴素贝叶斯实现方式
    一种是贝努利模型(只考虑出不出现),一种是多项式模型(考虑属性出现的次数)
    一篇贝叶斯算法的推导文章https://www.cnblogs.com/liuwu265/p/4685361.html

    示例

    采用多项式模型
    比如有已知3篇文章
    第一篇文章包含love,it,love是A类
    第二篇文章包含it,dirty,ugly是B类
    第三篇文章包含not,ugly是B类
    现在第四篇文章包含love未知类,要判断它的类
    1、统计词集
    即将所有文章的词都加在这个集合中为{love,it,dirty,not,ugly}
    2、转化为词向量
    如第一篇文章有2个love,1个it
    [[2 1 0 0 0 ]
    [0 1 1 0 1]
    [0 0 0 1 1]]
    类别向量为[A,B,B]
    3、计算类别概率
    p(A)=(frac{1}{3})p(B)=(frac{2}{3})
    每一个类中各词在该类所占的比例如第一行为(p(w_{i}|A))
    [[(frac{2}{3}) (frac{1}{3}) 0 0 0]
    [0 (frac{1}{5}) (frac{1}{5}) (frac{1}{5}) (frac{2}{5})]]
    4、进行判断
    对于第四篇也转换为向量为
    [1 0 0 0 0 ]
    计算(P(A) P(x | A))(frac{1}{3}(frac{2}{3} imes 1+0+0+0+0)=frac{2}{9})
    (P(B) P(x | B))(frac{2}{3}(0 imes1 +0+0+0+0)=0)
    比较大小所以是A类

    对垃圾邮件过滤程序

    以下是对垃圾邮件分类的程序实例,数据来自《机器学习项目实战》第四章所附资源

    import random
    import numpy as np
    import math
    import re
    
    
    # 用于统计所有的单词,输入从所有文档中提取的单词,输出这些文档的词集
    def wordList(dataSet):
        # 字典的值不可重复,所以采用字典
        wordSet = set([])
        for i in dataSet:
            wordSet = wordSet | set(i)
        return list(wordSet)
    
    
    # 对每一篇文档的词,用于统计其是否在词集中,若在词集中次数加1,输入每一篇文档的词,输出词次数的向量
    def signWord(wordVec, dataSet):
        signVec = np.zeros(len(wordVec))
        for word in dataSet:
            if word in wordVec:
                signVec[wordVec.index(word)] += 1
        return signVec
    
    
    # 训练函数,对于每一类,计算该类文档在所有文档中的比例(即每一类的概率),计算每一类的所有词(即属性)所占该类词集的比例(即已知这一类的情况下,该词的概率)
    # 输入包含文档的一个数组,每一列代表一个文档,输入每一个文档所对应的的属性的数组,返回每一类的所有词所占该类词集的比例(以数组形式输出,每一行代表一类)和每一类的概率(以字典形式输出,键为类名,值为比列)
    def train(trainData, trainCategory):
        numDoc, numWord = np.shape(trainData)  # 得到数组的行数和列数,其实分别代表文档的个数,和词集所包含词的个数
        # 用于统计每个类的个数
        classCount = {}
        for key in trainCategory:
            classCount[key] = classCount.get(key, 0) + 1
        # 用于计算每个类的概率
        p_class = {}
        for key in classCount:
            p_class[key] = classCount[key] / len(trainCategory)
        p_num = np.ones((len(p_class), numWord))  # 防止下溢出初始化时不用0
        p_sum = np.ones(len(p_class)) + 1
        # 生成一个包含类名的列表
        keys = list(p_class)
        # 遍历每一个文档
        for i in range(numDoc):
            # 对每一个文档,查看是属于哪一个类
            for j in range(len(p_class)):
                if trainCategory[i] == keys[j]:
                    # 用于统计,该类中每个词的个数,对应的词上加上对应的词的个数
                    p_num[j] += trainData[i]
                    # 用于统计该类所有的词数
                    p_sum[j] += sum(trainData[i])
                    break
        p_sum = p_sum.repeat(numWord).reshape(np.shape(p_num))  # 将其扩展为和p_num一样的形状,便于数组间计算
        return np.log(p_num / p_sum), p_class  # 防止下溢出,采用log
    
    
    # 分类函数,输出测试数据和train()输出的p和p_class,计算测试数据在每一类的概率,选择概率最大的,返回对应的类名
    def classfy(testData, p, p_class):
        keys = list(p_class)
        classArrary = np.sum(testData * p, axis=1)
        classList = []
        for i in range(len(p_class)):
            classList.append(classArrary[i] + math.log(p_class[keys[i]]))
        return keys[classList.index(max(classList))]
    
    
    # 用于提取文档的内容
    def getData(str):
        # 去除任何非单词字符
        data = re.split('W+', str)
        return [word.lower() for word in data if len(word) > 0]
    
    
    # 对50封邮件的分类测试
    def trainData():
        wordsList = []  # 用于存放词集
        docList = []  # 用于存放每篇文档的每个词,每一行代表一篇文档
        classList = []  # 用于,存放每篇文档所对应的类别
        for i in range(1, 26):
            str = getData(
                open(r'C:UsersDesktop我的文件机器学习实战machinelearninginactionCh04emailham\%d.txt' % i,
                     encoding='utf8', errors='ignore').read())  # 对于一些识别不了的词,用errors='ignore'忽略
            docList.append(str)
            wordsList.extend(str)
            classList.append(1)
            str = getData(
                open(r'C:UsersDesktop我的文件机器学习实战machinelearninginactionCh04emailspam\%d.txt' % i,
                     encoding='utf8', errors='ignore').read())
            docList.append(str)
            wordsList.extend(str)
            classList.append(0)
        wordVec = wordList(wordsList)
        trainSet = list(range(50))  # 存放用于训练的文档的在docList中的序号
        testSet = []  # 存放用于测试的文档的在docList中的序号
        # 随机选取测试文档序号
        for i in range(10):
            randIndex = int(random.uniform(0, len(trainSet)))
            testSet.append(trainSet[randIndex])
            del (trainSet[randIndex])
        # 进行训练
        trainData = []
        trainClass = []
        for doc in trainSet:
            trainData.append(signWord(wordVec, docList[doc]))
            trainClass.append(classList[doc])
        p, p_class = train(np.array(trainData), np.array(trainClass))
        # 进行测试
        errorCount = 0
        for doc in testSet:
            testWordVec = signWord(wordVec, docList[doc])
            if classfy(np.array(testWordVec), p, p_class) != classList[doc]:
                errorCount += 1
        # 输出识别错误的概率
        print(errorCount / len(testSet))
    
    
    trainData()
    
  • 相关阅读:
    Redis
    多线程相关
    selenium操作浏览器的基本方法
    selenium之 webdriver与三大浏览器版本映射表(更新至v2.29)
    selenium安装及官方文档
    Python(3)_python对Json进行操作
    python类中的self参数和cls参数
    python3中shuffle函数
    Python3中assert断言
    python2和python3中range的区别
  • 原文地址:https://www.cnblogs.com/Qi-Lin/p/12274001.html
Copyright © 2011-2022 走看看