机器学习笔记之朴素贝叶斯分类算法

来源:互联网 发布:青岛太阳软件 编辑:程序博客网 时间:2024/06/11 01:47
朴素贝叶斯分类算法:
优点:在数据较少的情况下仍然有效,可以处理多分类问题。
缺点:对于输入数据的准备方式较为敏感。
适用数据类型:标称型数据(离散型数据)

算法原理:
对于某一个条件,这个条件下哪个类的个数最多,这个情况就可能是这个类的。其实就是max{P(y1|X),P(y2|X)...P(yn|X)},X是条件(属性),y是类。
ps:是不是感觉有点像k-近邻算法的概率表达形式,另外肯定有人会问朴素贝叶斯中的'朴素是什么意思',朴素要表达的意思就是其假设了各个特征之间是独立的。特征独立的好处是可以大大降低需要训练的特征样本数。

算法流程:
收集数据:即建立训练测试数据集。
准备数据:数据类型最好是转化成数值型或者布尔类型数据
分析数据:有大量数据特征是,由于是概率表示的原因绘制特征作用不大,用直方图表示效果更好
训练算法:计算不同的独立特征的条件概率
测试算法:即求出误差率
使用算法:朴素贝叶斯比较常用的分类场景是文档分类

说道贝叶斯公式,我们要先了解条件概率公司:

               

这个公式的意思就是在y事件成立是x事件发生的概率是多少。
下面我们就可以看看贝叶斯公式:



是不是感觉这个公式很简洁,但是在机器学习这个领域这个公式的用处那就太大了!
其实这个公式很容易理解,就是当你想求当y事件成立x事件发生的概率时,可以转换为求当x事件成立时y事件发生的概率,虽然你现在可能感觉不出这样的转换有什么便利,但是在实际问题中这样的转换可以大大的降低求解的难度

当这个y事件使用很多个子事件组成的时候,这个概率求起来还是很复杂的,但是如果这些子事件都是相互独立的呢?那就简单多了,这也就引出了朴素贝叶斯公式:



问题就这样被各个击破了。

下面让我们来看一个小例子:

最近直播网站非常火爆,这些网站中的弹幕功能也形成了一种弹幕文化,但是总会有一些喷子在里面随意说一些让人愤怒的话,我们能不能让机器自己去屏蔽他们呢。这就用上了朴素贝叶斯分类算法。

首先我们先抓取几条弹幕,并对它们进行简单的处理,如词汇切分,去标点符号等,由于我是用的pycharm IDE对中文支持不好,我把这些汉字变成了拼音编码(如果有拼错的请原谅我把,我小学语文是数学老师教的。。),因为这些是我们的训练数据,所以我们还要人为的判断它们是积极的弹幕还是消极的弹幕:0代表积极的弹幕,1代表消极的弹幕

def createDataSet():    myData=[['zhubo', 'de', 'jishu', 'wo', 'renwei', 'hen', 'lihai'],            # 主播 的 技术 我 认为 很 厉害           ['zhubo', 'shi', 'yi', 'ge', 'sb', 'laji', 'caib', 'hahaha'],            # 主播 是 一 个 sb 垃圾 菜b 哈哈哈           ['caozuo', 'shuiping', 'tai', 'laiji', 'zhege', 'fenduan', 'wo', 'suibianniu'],            #操作 水平 太 垃圾 这种 分段 我 随便虐           ['xinteng', 'zhubo', 'bieli', 'pinzi', 'jiayou'],            #心疼 主播 别理 喷子 加油           ['zhubo', 'wande', 'bucuo', 'nengbuneng', 'bang', 'wo', 'da', 'yiju', 'paiweisai'],            #主播 玩的 不错 能不能 帮 我 打 一局 排位赛           ['zhezhong', 'shuiping', 'haiyoulian', 'zhibo', 'sb', 'laji']]            #这种 水平 还有脸 直播 sb 垃圾    lables = [0,1,1,0,0,1]    return myData,lables

然后我们将由这几条弹幕建立一个词汇表,python里的set刚好是不重复容器。

def createVocabList(dataSet):    vocabSet = set([])      for document in dataSet:        vocabSet = vocabSet | set(document)     return list(vocabSet)

这样我们就建立了一个不重复的词汇表

['caozuo', 'ge', 'zhezhong', 'tai', 'zhege', 'paiweisai', 'jishu', 'pinzi', 'hen',
 'caib', 'yi', 'jiayou', 'laiji', 'wo', 'de', 'da', 'bang', 'zhibo', 'renwei', 'sb', 'bucuo',  'haiyoulian', 'laji', 'fenduan', 'wande', 'suibianniu', 'lihai', 'xinteng', 'zhubo', 'bieli',  'nengbuneng', 'yiju', 'hahaha', 'shi', 'shuiping']

然后我们需要一个函数,来判断每一条弹幕是否在这个词汇表中出现:

def showTimeInTheLine(data, dataMap):    result = [0]*len(data)    for pinyin in dataMap :        if pinyin  in data :           result [data .index(pinyin)] = 1        else: print "this pinyin: %s is not in my dataMap" % pinyin     return result

我们使用第一条弹幕进行一下测试,结果:

[0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0]
和我们的数据进行对比,结果是正确的

因为我们这是一个二分类问题,就是消极弹幕还是积极弹幕,所以我们要算出每一个结果的概率,以及我们的词汇表在消极弹幕结果下的概率和在积极弹幕结果下的概率:

def train(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    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           #在积极类中词汇表中每个词的概率    return p0Vect,p1Vect,pAbusive



经过计算可以看出,积极类的概率是0.5 即P(x)
然后程序算出了词汇表在积极类中每个词的概率:
[ 0.        ,          0.        ,          0.        ,         0.        ,          0.        ,
  0.04761905,  0.04761905,  0.04761905, 0.04761905,   0.        ,
  0.        ,          0.04761905,  0.        ,         0.0952381 ,    0.04761905,
  0.04761905,  0.04761905,  0.        ,         0.04761905,   0.        ,
  0.04761905,  0.        ,          0.        ,         0.        ,           0.04761905,
  0.        ,          0.04761905,  0.04761905, 0.14285714,   0.04761905,
  0.04761905,  0.04761905,  0.        ,         0.        ,           0.               ]

程序也算出了词汇表在积极类中每个词的概率:
[ 0.04545455,  0.04545455,  0.04545455,  0.04545455,  0.04545455,
  0.        ,          0.        ,          0.        ,         0.        ,          0.04545455,
  0.04545455,  0.        ,          0.04545455, 0.04545455,  0.        ,
  0.        ,          0.        ,          0.04545455, 0.        ,        0.09090909,
  0.        ,          0.04545455,  0.09090909, 0.04545455,  0.        ,
  0.04545455,  0.        ,          0.        ,         0.04545455,  0.        ,
  0.        ,          0.        ,          0.04545455, 0.04545455,  0.09090909]

这样我们便训练好了一个可以用来分类的分类概率组:

下面我们输入两组自己发的弹幕来测试一下我们的朴素贝叶斯分类器:

def testing():    myData,lebels = createDataSet()    myList = createVocabList(myData )    trainMat=[]    for posting in myData :        trainMat.append(showTimeInTheLine(myList  , posting  ))    p0,p1,plable = train(array(trainMat),array(listClasses))    testEntry01 = ['jiayou', 'bucuo', 'lihai']                 #加油  不错  厉害    thisDM = array(showTimeInTheLine (myList, testEntry01))    print testEntry,u'这条弹幕属于: ',classify(thisDM,p0V,p1V,pAb)    testEntry02 = ['sb', 'laji']                 #sb  垃圾    thisDM = array(showTimeInTheLine (myList, testEntry02))    print testEntry,u'这条弹幕属于: ' ,classify(thisDM ,p0V,p1V,pAb)

最后我们程序判断的结果是:



这就是朴素贝叶斯分类的故事啦~


1 0
原创粉丝点击