机器学习算法之三——分类(二)

1 朴素贝叶斯介绍

    我们假设有一个二分类问题,现有一个新的样本点x,我们用贝叶斯决策理论来判断新的样本点应该属于二分类(A,B)的哪一类:如果x属于A类的概率大于属于B类的概率,那么x就属于A类;反之则属于B类。对于多分类ci,那么只需要计算x属于各个分类的概率p,然后找到max(p(c_1|x),p(c_2|x),...,p(c_n|x)),其对于的最大概率标签,就是x的分类。那么如何计算每个分类p(ci| x)。

没错,就是贝叶斯公式:

p(c_i|x) = \frac{p(x|c_i)p(c_i)}{p(x)}

这里就用到了朴素贝叶斯的假设:假设所有xj(各特征属性)相互条件独立,则进一步拆分上面的公式,并且分母对于所有类别都是常数,所有将分母最大化,那么就可以得到:

p(c_i|x) = p(x|c_i)p(ci) = p(c_i)\prod_{j=1}^{m}p(x_j|c_i)

    那么朴素贝叶斯分类的流程如下:

      1、设x=\{x_1,x_2,...,x_m\}为一个待分类项,而每个a为x的一个特征属性。

      2、有类别集合c=\{ c_1,c_2,...,c_n\}

      3、计算p(x_j|c_i)

      4、如果p(c_k|x) = max(p(c_1|x),p(c_2|x),...,p(c_n|x)),则 x\subseteq c_k

2 运行实例

    实际应用场景可以有:文本分类;垃圾邮件过滤;病人分类;拼写检查等。

    朴素贝叶斯常用的模型:高斯模型(特征是连续型变量);多项式模型(特征是离散的);伯努利模型(特征是离散的且为布尔类型(1/0))。

   本文使用他来过滤恶意评论(恶意的为1,非恶意的为0):

# coding=utf-8
from numpy import *

# 创建一个实验样本
def loadDataSet():
    postingList = [['my','dog','has','flea','problems','help','please'],
                   ['maybe','not','take','him','to','dog','park','stupid'],
                   ['my','dalmation','is','so','cute','I','love','him'],
                   ['stop','posting','stupid','worthless','garbage'],
                   ['mr','licks','ate','my','steak','how','to','stop','him'],
                   ['quit','buying','worthless','dog','food','stupid']]
    classVec = [0,1,0,1,0,1]
    return postingList, classVec

# 创建一个包含在所有文档中出现的不重复词的列表
def createVocabList(dataSet):
    vocabSet = set([])      # 创建一个空集
    for document in dataSet:
        vocabSet = vocabSet | set(document)   # 创建两个集合的并集
    return list(vocabSet)
    
# 将文档词条转换成词向量
def setOfWords2Vec(vocabList, inputSet):
    returnVec = [0]*len(vocabList)        # 创建一个其中所含元素都为0的向量
    for word in inputSet:
        if word in vocabList:
            # returnVec[vocabList.index(word)] = 1     # index函数在字符串里找到字符第一次出现的位置  词集模型
            returnVec[vocabList.index(word)] += 1      # 文档的词袋模型    每个单词可以出现多次
        else: print "the word: %s is not in my Vocabulary!" % word
    return returnVec

# 朴素贝叶斯分类器训练函数   从词向量计算概率
def trainNB0(trainMatrix, trainCategory):
    numTrainDocs = len(trainMatrix)
    numWords = len(trainMatrix[0])
    pAbusive = sum(trainCategory)/float(numTrainDocs)
    # p0Num = zeros(numWords); p1Num = zeros(numWords)
    # p0Denom = 0.0; p1Denom = 0.0
    p0Num = ones(numWords);   # 避免一个概率值为0,最后的乘积也为0
    p1Num = ones(numWords);   # 用来统计两类数据中,各词的词频
    p0Denom = 2.0;  # 用于统计0类中的总数
    p1Denom = 2.0  # 用于统计1类中的总数
    for i in range(numTrainDocs):
        if trainCategory[i] == 1:
            p1Num += trainMatrix[i]
            p1Denom += sum(trainMatrix[i])
        else:
            p0Num += trainMatrix[i]
            p0Denom += sum(trainMatrix[i])
            # p1Vect = p1Num / p1Denom
            # p0Vect = p0Num / p0Denom
    p1Vect = log(p1Num / p1Denom)    # 在类1中,每个次的发生概率
    p0Vect = log(p0Num / p0Denom)      # 避免下溢出或者浮点数舍入导致的错误   下溢出是由太多很小的数相乘得到的
    return p0Vect, p1Vect, pAbusive

# 朴素贝叶斯分类器
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
    p1 = sum(vec2Classify*p1Vec) + log(pClass1)
    p0 = sum(vec2Classify*p0Vec) + log(1.0-pClass1)
    if p1 > p0:
        return 1
    else:
        return 0

def testingNB():
    listOPosts, listClasses = loadDataSet()
    myVocabList = createVocabList(listOPosts)
    trainMat = []
    for postinDoc in listOPosts:
        trainMat.append(setOfWords2Vec(myVocabList, postinDoc))
    p0V, p1V, pAb = trainNB0(array(trainMat), array(listClasses))
    testEntry = ['love','my','dalmation']
    thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
    print testEntry, 'classified as: ', classifyNB(thisDoc, p0V, p1V, pAb)
    testEntry = ['stupid','garbage']
    thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
    print testEntry, 'classified as: ', classifyNB(thisDoc, p0V, p1V, pAb)

# 调用测试方法----------------------------------------------------------------------
testingNB()
发布了30 篇原创文章 · 获赞 17 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/selinaqqqq/article/details/89454133