Machine Learning in Action::Naive Bayes           

Machine Learning in Action::Naive Bayes


Naive Bayes 概述

	关键词:分类·监督学习
	
	原理: 基于概率论的分类方式。通过计算后验概率,来选择可能性最大的一个分类。
		这里使用的概率解释属于贝叶斯概率理论的范畴,该理论非常流行且效果良好。贝叶斯概率引入了先验知识逻辑推理来处理不确定命题。也就是:
		 后验概率 = 先验概率 × 似然  
	

相关函数

[1] 由文本构建“词集”向量

	要从文本中获取特征,首先要拆分文本。这里的特征也是来自文本的词条(token),一个词条是字符的任意组合。可以把词条想象为单词,也可以使用非单词词条(如URL,IP地址
	或者任意其他字符。然后将每一个文本片段表示为一个词条向量,其中值为 1 表示词条出现在文档中, 0 表示尚未出现在文档中。
	

def loadDataSet():
	# 六条评论.split()
	postingList = [ ['my','dog','has','flea','problem','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'] ]
	
	# 人工标注 1代表含有侮辱性文字 0 代表正常言论
	classVec = [0,1,0,1,0,1]
	return postingList,classVec


#构建词集向量坐标
def createVocabList(dataSet):
	vocabSet = set([])
	
	for document in dataSet:
		vocabSet = vocabSet | set(documentList)
	
	return vocabSet;




#构建词集向量
def setOfWords2Vec(vocabList,inputSet):
	returnVec = [0] * len(vocabList)
	
	for elem in inputSet:
		if elem in vocabList:
			returnVec[vocabList.index(elem)] = 1
		else:
			print "the word : %s is not in my vocabulary! " %elem
	
	return returnVec

--------------------------------------------------------------------------------

[2] 朴素贝叶斯分类器训练函数

函数名称:
	trainNB0(trainMatrix,trainCategory)
函数功能:
	朴素贝叶斯分类训练
输入参数:
	trainMatrix : 训练特征集 : mat
	trainCategory : 训练标签集 : list
输出参数:
	p0Vec,p1Vec,pAbusive : 0-class似然值 1-class似然值 A先验概率



def trainNB0(trainMatrix,trainCategory):

	#训练文本数	
	numTrainDocs = len(trainMatrix)
	#词集向量维度
	numWords = len(trainMatrix[0])
	
	#先验概率P(A)
	pAbusive = sum(trainCategory)/float(numTrainDocs)
	#标记为0的文本所含词条累计
	p0Num = zeros(numWords)
	#标记为1的文本所含词条累计
	p1Num = zeros(numWords)
	
	#标记为0的文本计数
	p0Denom = 0.0
	#标记为1的文本计数
	p1Denom = 0.0
	

	for i in range(numTrainDocs):
		# 如果文本被标记为1
		if trainCategory[i] == 1:
			p1Num += trainMatrix[i]
			p1Denom += sum(trainMatrix[i])
		else:
			p0Num += trainMatrix[i]
			p1Denom += sum(trainMatrix[i])

	# P( D | Hi  ) =nm=0   P( Dm | Hi  )
 	p0Vec = p0Num/p0Denom   #change to log()
	p1Vec = p1Num/p1Denom	#change to log()
	
	return p0Vec,p1Vec,pAbusive
			
--------------------------------------------------------------------------------

[3] 进一步修改分类器

	(1) 概率为零。似然计算nm=0   P( Dm | Hi  ) 如果其中一个概率值为0,那么最后的乘积也为零。为降低这种影响,可以将所有词
	的出现次数初始化为1,并将分母初始化为2.

modefy:

	#标记为0的文本所含词条累计
        p0Num = [1] * numWords
        #标记为1的文本所含词条累计
        p1Num = [1] * numWords
	
	 #标记为0的文本计数
        p0Denom = 2
        #标记为1的文本计数
        p1Denom = 2

	
	(2) 数据下溢出,这是由于太多很小的数相乘造成的。当计算乘积nm=0   P( Dm | Hi  ) 时,由于大部分因子都非常小,所以程序会下溢出或者得不到正确的答案。
	一个解决办法是对乘积取自然对数。在代数中,有 ln(a*b) = ln(a) + ln(b)。于是通过求对数可以避免下溢出或者浮点数舍入导致的错误。
	同时,采用自然对数进行处理不会有任何损失。它们的取值虽然不同,但不影响最终结果。

modefy:
	
	p0Vect = log(p0Num/p0Denom)
	p1Vect = log(p1Num/p1Denom)

-------------------------------------------------------------------------------

[4] 朴素贝叶斯分类函数

函数名称:
	classifyNB(vec2Classify,p0Vec,p1Vec,pClass1)
函数功能:
	利用先验概率已经似然性,进行朴素贝叶斯分类
输入参数:
	vec2Classify : 要分类样本的特征向量 : arrary  or mat
	p0Vec : 特征向量|0-class 的概率 : array 
	p1Vec : 特征向量|1-class 的概率 : array
	pClass1 : 1-class 的先验概率 : float

输出参数:
	0 : 分类为0-class 
	1 : 分类为1-class


def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
	
	
	p0 = sum(vec2Classify * p0Vec) + log(1-pClass1)
	p1 = sum(vec2Classify * p1Vec) + log(pClass1)
	
	if p0 > p1 :
		return 0
	else:
		return 1


-------------------------------------------------------------------------------

[5] 词袋模型

	到目前为止,我们将每个词的出现与否作为一个特征,这可以被描述为词集模型(set-of-words model)。如果一个词在文档中不止出现一次,这可能意味着包含该词是否出现在文档中所不能表达的信息,
	这钟方法被称为词袋模型(bag-of-words model)。在词袋中,每个单词可以多次,而在词集中,每个词只能出现一次。


def bagOfWords2VecMN(vocabList,inputSet):
	returnVec = [1] * len(vocabList)
	
	for words in inputSet:
		if words in vocabList:
			returnVec[vocabList.index(words)] += 1
	
	return returnVec

-------------------------------------------------------------------------------

[6] 交叉验证

	分类器所需要的概率计算只利用训练集中的文档来完成。随机选择数据的一部分作为训练集,而剩余部分作为测试集的过程为留存交叉验证(hold-out cross validation).

------------------------------------------------------------------------------

[7] 文本处理的一些小问题

	停用词表词汇表中的一小部分单词缺占据了所有文本用词的一大部分。产生这种现象的原因是因为语言中的大部分都是冗余和结构辅助性内容。常用的方法移除高频词,同时从某个预订词表中移除
	结构上的辅助词。

Welcome to contact me,the friends who like Machine-Learning and Data-Mining.

:)

04 Nov 2014