贝叶斯分类器

贝叶斯分类器

判别模型和生成模型

判别模型,也就是根据特征值来求结果的概率。形式化表示为 p(y|x;\theta) p(y|x;θ) ,在参数\theta θ 确定的情况下,求解条件概率 p(y|x) p(y|x) 。通俗的解释为在给定特征后预测结果出现的概率。

比如说要确定一只羊是山羊还是绵羊,用判别模型的方法是先从历史数据中学习到模型,然后通过提取这只羊的特征来预测出这只羊是山羊或绵羊的概率。

换一种思路,我们可以先建立绵羊和山羊特征模型,然后对一只需要判断类型的羊,我们提取相应的特征,放到山羊概率是多少,再放到绵羊模型中看看概率,哪个大就是哪个。形式化表示为 p(x|y) p(x|y) ,y是类型,x是特征。

  • 常见的判别模型有:线性回归、对数回归、线性判别分析、支持向量机、boosting、条件随机场、神经网络等。

  • 常见的生产模型有隐马尔科夫模型、朴素贝叶斯模型、高斯混合模型、LDA、Restricted Boltzmann Machine 等。

贝叶斯分类器

实际中,p(x|y) p(x|y) 并不便于计算,所以我们利用贝叶斯公式将其转换为方便求的概率。贝叶斯公式如下:

p(y|x)=fracp(x|y)p(y)p(x)

p(x|y) 称为后验概率, p(y) 先验概率

由于我们关心的是哪一个 p(x=ci|y) 比较大(比如说绵羊和山羊的哪个的概率大),不关心起具体的值,并且朴素贝叶斯分类器一般见得个特征相互独立,所以上式改写为:

argminyp(y|x)===argminyp(x|y)p(y)p(x)argmaxyp(x|y)p(y)argmaxyp(x1)p(x2)p(xn)p(y)

贝叶斯分类器例子

一个医院早上收了六个门诊病人,如下表。

症状职业疾病
打喷嚏护士感冒
打喷嚏农夫过敏
头痛建筑工人脑震荡
头痛建筑工人感冒
打喷嚏教师感冒
头痛教师脑震荡

现在又来了第七个病人,是一个打喷嚏的建筑工人。请问他患上感冒的概率有多大?

求的是 P(|) ,根据贝叶斯公式:

P(|)==P(|)P()P()p(|)p(|)p()p()p()

其中 P(|)=23P(|)=13P()=12P()=12P()=13

P(|)=23×13×1212×13=23

贝叶斯进行文本分类

朴素贝叶斯的一个最著名的应用——电子邮件垃圾过滤:
给出已经人工分好类的文档,分别放在ham文件夹(有用邮件)和spam文件夹(垃圾邮件),每个文件夹有25封邮件。建立分类器来识别垃圾邮件。其中过程如下:

  1. 遍历所有训练数据,将文本解析成词条向量。
  2. 建立词条向量表,再次遍历每一条训练数据(这里是每一封邮件),对于每一条数据,在词条向量表中标记出现的单词。遍历时记录每种类别数据的数目,以及在类别C情况下词条次数。
  3. 计算每个类别下词条出现的概率即p(x|y)和每种类别出现的概率p(y)(此步需进行拉普拉斯平滑处理)
  4. 返回
  • 词条向量是一个包含训练数据中出现的每一个单词的集合。
  • 拉普拉斯平滑:对于某些不出现的词条,其概率为0,最后计算可能导致连乘积为0,所以,对所有词条数目进行加1,相应的,计算概率时分母加上类别总数。
  • 防止数值过小产生下溢,对概率取对数后计算

python代码如下


import numpy as np;
返回每种类别的概率和每个类别下单词出现的概率
def trainNB0(trainSet,trainClass):
    numTrainData = len(trainSet);
    numWords = len(trainSet[0]);
    pAb = sum(trainClass)/float(numTrainData);
    p0Num = np.ones(numWords);
    p1Num = np.ones(numWords);
    p0Denom =2.0;
    p1Denom =2.0;
    for i in range(numTrainData):
            if(trainClass[i] == 1):
                p1Num += trainSet[i];
                p1Denom += sum(trainSet[i]);
            else:
                p0Num += trainSet[i];
                p0Denom += sum(trainSet[i]);
    p1Vect = np.log(p1Num/p1Denom);
    p0Vect = np.log(p0Num/p0Denom);
    return p0Vect,p1Vect,pAb;


def classifyNB(v,p0Vec,p1Vec,pClass1):
    p0 = sum(v*p0Vec)+np.log(pClass1);
    p1 = sum(v*p1Vec)+np.log(1-pClass1);
    if (p1>p0):
        return 1;
    return 0;

#将词条转化为向量
def setOfWord2VecMN(vocList,inputSet):
    returnVec=[0]*len(vocList);
    for word in inputSet:
        if word in vocList:
            returnVec[vocList.index(word)] = +1;
        else:
            print("the word %s is not in my vocSet" %word);
    return returnVec;

#对词条预处理,丢弃标点符号和长度小于2的词条并将词条全部转换为小写
def textParse(bigString):
    import re;
    listofTokens = re.split(r'\W*',bigString);
    return [tok.lower() for tok in listofTokens if len(tok) > 2];

def spanTest():
    docList=[]; 
    classList=[];  #类别标签
    fullText=[];   #词条向量
    #读入数据,解析成词条向量   
    for i in range (1,26):
        wordList = textParse(open('./spam/%d.txt' %i).read());
        docList.append(wordList);
        fullText.extend(wordList);
        classList.append(1);
        wordList = textParse(open('./ham/%d.txt' %i).read());
        docList.append(wordList);
        fullText.extend(wordList);
        classList.append(0);
    voaList = createVocList(docList); #将词条向量去重,转化为集合,
    #交叉验证
    trainingSet = [i for i in range(50)];
    testSet=[];
    for i in range(10):
        randIndex = int(np.random.uniform(0,len(trainingSet)));
        testSet.append(trainingSet[randIndex]);
        del(trainingSet[randIndex]);
    trainMat=[];
    trainClasses=[];
    for docIndex in trainingSet:
        trainMat.append(setOfWord2VecMN(voaList,docList[docIndex]));
        trainClasses.append(classList[docIndex]);
    p0v,p1v,pSpam = trainNB0(np.array(trainMat),np.array(trainClasses));
    error = 0;
    for docIndex in  testSet :
        voc = setOfWord2VecMN(voaList,docList[docIndex]);
        tlabel = classifyNB(voc,p0v,p1v,pSpam);
        if(tlabel != classList[docIndex]):
            error+=1;
    print("error rate = ",float(error)/len(testSet));

spanTest();

附代码:点击这里
http://pan.baidu.com/s/1o6Dn4d8

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值