《机器学习实战》学习笔记:基于朴素贝叶斯的分类方法

概率是许多机器学习算法的基础,在前面生成决策树的过程中使用了一小部分关于概率的知识,即统计特征在数据集中取某个特定值的次数,然后除以数据集的实例总数,得到特征取该值的概率。

目录:

  • 一.基于贝叶斯理论的分类方法
  • 二.关于朴素贝叶斯的应用场景
  • 三.基于Python和朴素贝叶斯的文本分类

    1.准备数据

    2.训练算法

    3.测试算法

  • 四.小结

以下进入正文:

一.基于贝叶斯理论的分类方法

假设有两类数据组成的数据集如下:

其中,假设两个概率分布的参数已知,并用p1(x,y)表示当前数据点(x,y)属于类别一的概率;用p2(x,y)表示当前数据点(x,y)属于类别二的概率。

贝叶斯决策理论的核心思想是:选择高概率所对应的类别,选择具有最高概率的决策。有时也被总结成“多数占优”的原则。

具体到实例,对于一个数据点(x,y),可以用如下规则判定它的类别:

p1(x,y)>p2(x,y),那么点(x,y)被判定为类别一。

p1(x,y)<p2(x,y),那么点(x,y)被判定为类别二。

当然,在实际情况中,单单依靠以上的判定无法解决所有的问题,因为以上准则还不是贝叶斯决策理论的所有内容,使用p1(x,y)p2(x,y) 只是为了简化描述。更多的,我们使用p(ci|x,y) 来确定给定坐标的点(x,y),该数据点来自类别ci的概率是多少。具体地,应用贝叶斯准则可得到,该准则可以通过已知的三个概率值来计算未知的概率值:

则以上判定法则可转化为:

p(c1|x,y)>p(c2|x,y),那么点(x,y)被判定为类别一。

p(c1|x,y)<p(c2|x,y),那么点(x,y)被判定为类别二。

二.关于朴素贝叶斯的应用场景

机器学习的一个重要应用就是文档的自动分类,而朴素贝叶斯正是文档分类的常用算法。基本步骤是遍历并记录下文档中出现的词,并把每个词的出现或者不出现作为一个特征。这样便有跟文档中出现过词汇的个数一样多的特征。若有大量特征时,使用直方图效果更好。以下是朴素贝叶斯的一般过程:

  1. 收集数据:这里使用RSS源
  2. 准备数据:需要数值型&布尔型数据
  3. 分析数据:有大量特征时,绘制特征的作用不大,此时使用直方图效果更好
  4. 训练算法:计算不同的独立特征的条件概率
  5. 测试算法:计算错误率
  6. 使用算法:如文档分类

讲到这里,你也许还会带着疑问,为什么贝叶斯前会加上“朴素”,其实,这是基于朴素贝叶斯的一个假设,即:特征之间相互(统计意义上)独立,如一个单词出现的可能性与其他单词相邻没有关系,当然这在实际情况中不一定是正确的,但无数实验表明,这种假设是有必要的,而且朴素贝叶斯的实际效果其实很好。

朴素贝叶斯的另外一个假设是:每个特征同等重要。当然,这个假设也有问题(不然就不叫假设了……),但确实有用的假设。

三.基于Python和朴素贝叶斯的文本分类

从文本中提取特征,首先需要将文本进行拆分,转化为词向量,某个词存在表示为1,不存在表示为0,这样,原来一大串字符串便转为简单的0,1序列的向量。这种情况下只考虑某个词是否出现,当然,你也可以使用记录词的出现次数作为向量,或者记录不同词出现的频率等等。

1.准备数据:从文本中构建词向量,这里考虑出现在所有文档中的所有单词,并将每一篇文档转化为词汇表上的向量。下面的代码实现了功能,其中:

函数loadDataSet() 创建了一些实验样本postingList和对应的标签listClass,有一些样本被标签为带有侮辱性文字;

函数createNonRepeatedList() 统计并保存一个列表vocList,该列表包含所有文档中出现的词(不重复),这里使用了Python的set函数;

函数detectInput(vocList, inputStream)使用了词列表vocListinputStream为待检测的word串,输出文档向量,向量的每一元素为10,分别表示词汇表中的单词在输入文档中是否出现。

# -*- coding: utf-8 -*-
"""
Created on Tue Sep 08 16:12:55 2015

@author: Administrator
"""

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‘]]
    listClass = [0, 1, 0, 1, 0, 1] # 1代表存在侮辱性的文字,0代表不存在
    return postingList, listClass

# 将所有文档所有词都存到一个列表中,用set()函数去除重复出现的词
def createNonRepeatedList(data):
    vocList = set([])
    for doc in data:
        vocList = vocList | set(doc) # 两集合的并集
    return list(vocList)

def detectInput(vocList, inputStream):
    returnVec = [0]*len(vocList) # 创建和vocabList一样长度的全0列表
    for word in inputStream:
        if word in vocList: # 针对某段words进行处理
            returnVec[vocList.index(word)] = 1 # ?
        else:
            print "The word :%s is not in the vocabulary!" % word
    return returnVec

2.训练算法:从词向量计算概率,将之前的贝叶斯准则中的(x,y)改为向量w, 其长度为词向量的长度,如以下公式:

计算分为类别ci的概率p(ci)。通过类别i中的文档数除以总的文档数可计算。及label_i/sum(label)

已知某个类别c,计算w在类别ci中的概率p(w|ci)。由于朴素贝叶斯假设所有特征相互独立,故有:

p(w|ci) = p(w0,w1,...,wn|ci) = p(w0|ci)*p(w1|ci)*...*p(w0|ci)计算每个词wj在已知类别i的概率,然后再相乘。

伪代码如下:

计算每个类别中的文档数目
对每篇训练文档:
     对每个类别:
          如果词条出现在文档中 -> 增加该词条的计数值
         增加所有词条的计数值
     对每个类别:
          将该词条的数目除以总词条数目得到条件概率
     返回每个类别的条件概率

贝叶斯分类器训练函数代码如下:

def trainNaiveBayes(trainMatrix, classLabel):
    numTrainDocs = len(trainMatrix)
    numWords = len(trainMatrix[0])
    pBase = sum(classLabel) / float(numTrainDocs)
    # The following Settings aim at avoiding the probability of 0
    p0Num = ones(numWords)
    p1Num = ones(numWords)
    p0Denom = 2.0
    p1Denom = 2.0
    for i in range(numTrainDocs):
        if classLabel[i] == 1:
            p1Num += trainMatrix[i]
            p1Denom += sum(trainMatrix[i])
        else:
            p0Num += trainMatrix[i]
            p0Denom += sum(trainMatrix[i])
    p0 = log(p0Num / p0Denom)
    p1 = log(p1Num / p1Denom)
    return p0, p1, pBase

3.测试算法:测试分类器的效果

p(w0|ci)*p(w1|ci)*...p(w0|ci)中,如果某个值为0,则会使得最后的乘积为0,故将所有词初始化为至少出现一次。分母初始化为2,这样不改变实际效果。同时,p(w0|ci)*p(w1|ci)*...*p(w0|ci) 取对数,得到:ln(p(w0|ci))+ln(p(w1|ci))+...+ln(p(w0|ci)), 由于对数函数ln(x)为单调递增函数,因此在计算过程中对乘法取对数对概率曲线的单调性没有影响(高等数学中常用的性质)。修改代码后进行测试:

def trainNaiveBayes(trainMatrix, classLabel):
    numTrainDocs = len(trainMatrix)
    numWords = len(trainMatrix[0])
    pBase = sum(classLabel) / float(numTrainDocs)
    # The following Settings aim at avoiding the probability of 0
    p0Num = ones(numWords)
    p1Num = ones(numWords)
    p0Denom = 2.0
    p1Denom = 2.0
    for i in range(numTrainDocs):
        if classLabel[i] == 1:
            p1Num += trainMatrix[i]
            p1Denom += sum(trainMatrix[i])
        else:
            p0Num += trainMatrix[i]
            p0Denom += sum(trainMatrix[i])
    p0 = log(p0Num / p0Denom)
    p1 = log(p1Num / p1Denom)
    return p0, p1, pBase

trainMat = []
for doc in loadData:
    trainMat.append(detectInput(vocList, doc))

p0,p1,pBase = trainNaiveBayes(trainMat, dataLabel)
#print "trainMat : "
#print trainMat

# test the algorithm
def naiveBayesClassify(vec2Classify, p0, p1, pBase):
    p0res = sum(vec2Classify * p0) + log(1 - pBase)
    p1res = sum(vec2Classify * p1) + log(pBase)
    if p1res > p0res:
        return 1
    else:
        return 0

def testNaiveBayes():
    loadData, classLabel = loadDataSet()
    vocList = createNonRepeatedList(loadData)
    trainMat = []
    for doc in loadData:
         trainMat.append(detectInput(vocList, doc))
    p0, p1, pBase = trainNaiveBayes(array(trainMat), array(classLabel))
    testInput = [‘love‘, ‘my‘, ‘dalmation‘]
    thisDoc = array(detectInput(vocList, testInput))
    print testInput, ‘the classified as: ‘, naiveBayesClassify(thisDoc, p0, p1, pBase)
    testInput = [‘stupid‘, ‘garbage‘]
    thisDoc = array(detectInput(vocList, testInput))
    print testInput, ‘the classified as: ‘, naiveBayesClassify(thisDoc, p0, p1, pBase)

testNaiveBayes()

最后,对两组word串进行检测,第一段被判定为非侮辱性用语,而第二段则被判定为侮辱性用语,分类正确。

四.小结

以上实验基本实现了朴素贝叶斯分类器,并正确执行了文本分类,后面要进一步学习,将朴素贝叶斯运用到垃圾邮件过滤、个人广告获取区域倾向等实际应用。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 09-11

《机器学习实战》学习笔记:基于朴素贝叶斯的分类方法的相关文章

机器学习之基于朴素贝叶斯文本分类算法

原理 在分类(classification)问题中,常常需要把一个事物分到某个类别.一个事物具有很多属性,把它的众多属性看做一个向量,即x=(x1,x2,x3,-,xn),用x这个向量来代表这个事物.类别也是有很多种,用集合Y=y1,y2,-ym表示.如果x属于y1类别,就可以给x打上y1标签,意思是说x属于y1类别.这就是所谓的分类(Classification). x的集合记为X,称为属性集.一般X和Y的关系是不确定的,你只能在某种程度上说x有多大可能性属于类y1,比如说x有80%的可能性属

基于朴素贝叶斯的文本分类

前言:学习机器学习的过程意识到,数学是工科的基石.很多数学公式似懂非懂,因此有了这篇博客,想在学习每个模型的过程中搞懂其中的数学理论. 贝叶斯决策论 1.前置知识:先验概率与后验概率 先验概率P(B):根据以往经验和分析得到的概率 先验概率是一种常识性.经验性认知,比如抛硬币正反面的概率是1/2. 后验概率P(A|B):某个因素的到来影响了对某个结果发生可能性的判断 后验概率是基于已知,对结果发生的可能性一种推测. 比如:文本分类中,假设文章类别为3类,没有数据时,观测到类别c的概率是先验概率P

基于朴素贝叶斯的内容推荐算法

论文出处: http://www.cs.utexas.edu/~ml/papers/libra-sigir-wkshp-99.pdf 引言 这篇文章里面将会详细介绍基于多项式贝叶斯的内容推荐算法的符号以及术语,公式推导以及核心思想,学习如何从文本分类的角度来实现物品推荐.详细了解算法过程后,你应该可以利用里面的公式来计算出某个用户对于单词级别的喜好强度列表(profile),根据这个强度大小来对其他物品(需先用该强度来对该物品做加权算出该物品的喜好强度)做一个推荐的排序,从而得到用户可能最喜欢的

详解基于朴素贝叶斯的情感分析及 Python 实现

相对于「 基于词典的分析 」,「 基于机器学习 」的就不需要大量标注的词典,但是需要大量标记的数据,比如: 还是下面这句话,如果它的标签是: 服务质量 - 中 (共有三个级别,好.中.差) ╮(╯-╰)╭,其是机器学习,通过大量已经标签的数据训练出一个模型, 然后你在输入一条评论,来判断标签级别 宁馨的点评 国庆活动,用62开头的信用卡可以6.2元买一个印有银联卡标记的冰淇淋, 有香草,巧克力和抹茶三种口味可选,我选的是香草口味,味道很浓郁. 另外任意消费都可以10元买两个马卡龙,个头虽不是很大

机器学习实战学习笔记(一)

1.k-近邻算法 算法原理: 存在一个样本数据集(训练样本集),并且我们知道样本集中的每个数据与其所属分类的对应关系.输入未知类别的数据后将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似(最近邻)的k组数据.然后将k组数据中出现次数最多的分类,来作为新数据的分类. 算法步骤: 计算已知类别数据集中的每一个点与当前点之前的距离.(相似度度量) 按照距离递增次序排序 选取与当前点距离最小的k个点 确定k个点所在类别的出现频率 返回频率最高的类别作为当前点的分类 py

(数据挖掘-入门-8)基于朴素贝叶斯的文本分类器

主要内容: 1.动机 2.基于朴素贝叶斯的文本分类器 3.python实现 一.动机 之前介绍的朴素贝叶斯分类器所使用的都是结构化的数据集,即每行代表一个样本,每列代表一个特征属性. 但在实际中,尤其是网页中,爬虫所采集到的数据都是非结构化的,如新闻.微博.帖子等,如果要对对这一类数据进行分类,应该怎么办呢?例如,新闻分类,微博情感分析等. 本文就介绍一种基于朴素贝叶斯的文本分类器. 二.基于朴素贝叶斯的文本分类器 目标:对非结构化的文本进行分类 首先,回顾一下朴素贝叶斯公式: 特征.特征处理:

基于朴素贝叶斯的定位算法

1 定位背景介绍 一说到定位大家都会想到gps,然而gps定位有首次定位缓慢(具体可以参考之前的博文<LBS定位技术>).室内不能使用.耗电等缺陷,这些缺陷大大限制了gps的使用.在大多数移动互联网应用例如google地图.百度地图等,往往基于wifi.基站来进行定位. 一般APP在请求定位的时候会上报探测到的wifi信号.基站信号.以wifi为例,手机会探测到周围各个wifi(mac地址)对应的信号强度(RSSI),即收集到信号向量(<WF1, RSSI1> <WF2, R

朴素贝叶斯新闻分类,新浪SAE碰到的问题

1 如何将高版本的jdk通过Eclipse编译为较低版本的 2 当前SAE支持的jdk版本是1.6还有web项目war包不能是3.0版本及以上,必须编译为较低版本 3  No context on this server matched or handled this request问题:有的是jdk版本问题,还有是多了tomcat的servlet-api包的问题 4 文件读取中文乱码问题 br = new BufferedReader(new InputStreamReader( new Fi

《机器学习实战》学习笔记:基于朴素贝叶斯的垃圾邮件过滤

概率是许多机器学习算法的基础,在前面生成决策树的过程中使用了一小部分关于概率的知识,即统计特征在数据集中取某个特定值的次数,然后除以数据集的实例总数,得到特征取该值的概率. 之前的基础实验中简单实现了朴素贝叶斯分类器,并正确执行了文本分类,这一节将贝叶斯运用到实际场景,垃圾邮件过滤这一实际应用. 实例:使用朴素贝叶斯过滤垃圾邮件 在上一节:http://blog.csdn.net/liyuefeilong/article/details/48383175中,使用了简单的文本文件,并从中提取了字符