参考资料:朴素贝叶斯、用LDA处理文本(Python)、SVM做文本分类详细操作流程
1、朴素贝叶斯
1.1 原理
x代表事物,x的集合记为X,成为属性集。C={c1,c2,…cm}。朴素贝叶斯公式,是用C的后验概率P(C|X)最大值来进行分类,后验概率计算是由先验概率与类条件概率的乘积得出,先验概率P©和类条件概率要通过训练数据集得出(朴素贝叶斯分类模型),将其保存为中间结果,测试文档进行分类时调用这个中间见结果得出后验概率P(C|X)=P(X|C)P©/P(X)。
朴素贝叶斯分类器是有监督学习,常见两种模型,多项式模型(multinomial model)即词频型和伯努利模型(Bernouli model)即文档型,还有一种高斯模型。
1.2 利用朴素贝叶斯模型进行文本分类
# -*- coding:utf-8 -*-
# __author__ = 'Administrator'
import numpy as np
def loadDataSet():#数据格式
postingList = []
for line in open("data.txt"):
postingList.append(line.split())
print(postingList)
'''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]#1 侮辱性文字 , 0 代表正常言论
return postingList,classVec
def createVocabList(dataSet):#创建词汇表
vocabSet = set([])
for document in dataSet:
vocabSet = vocabSet | set(document) #创建并集
return list(vocabSet)
def bagOfWord2VecMN(vocabList,inputSet):#根据词汇表,讲句子转化为向量
returnVec = [0]*len(vocabList)
for word in inputSet:
if word in vocabList:
returnVec[vocabList.index(word)] += 1
return returnVec
def trainNB0(trainMatrix,trainCategory):
numTrainDocs = len(trainMatrix) #向量的个数
numWords = len(trainMatrix[0]) #总共32个词
pAbusive = sum(trainCategory)/float(numTrainDocs) #Category = 1 所占比例(先验概率)
p0Num = np.ones(numWords); p1Num = np.ones(numWords)#计算频数初始化为1
p0Denom = 2.0; p1Denom = 2.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 = np.log(p1Num/p1Denom)#注意 计算单词出现的概率 分母是这一类所有词的个数
p0Vect = np.log(p0Num/p0Denom)#注意
return p0Vect,p1Vect,pAbusive#返回各类对应特征的条件概率向量
#和各类的先验概率
def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1):
p1 = sum(vec2Classify * p1Vec) + np.log(pClass1)#注意
p0 = sum(vec2Classify * p0Vec) + np.log(1-pClass1)#注意
if p1 > p0:
return 1
else:
return 0
def testingNB():#流程展示
listOPosts,listClasses = loadDataSet()#加载数据
myVocabList = createVocabList(listOPosts)#建立词汇表
trainMat = []
for postinDoc in listOPosts:
trainMat.append(bagOfWord2VecMN(myVocabList,postinDoc))
p0V,p1V,pAb = trainNB0(trainMat,listClasses)#训练
#测试
#testEntry = ['love','my','dalmation','dog','stupid']
testEntry = ['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid']
thisDoc = bagOfWord2VecMN(myVocabList,testEntry)
print( testEntry,'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb))
testingNB()
2、SVM模型
2.1 原理
SVM(Suport Vector Machine)支持向量机,将样本转化为向量的形式,是一种二分线性分类模型。
2.2 利用朴素贝叶斯模型进行文本分类
&emps;步骤为:①文本预处理(去除停用词等);②测试集、验证集抽取;③分词处理;④文本标注;⑤特征提取,采用卡方、互信息等方法提取词的特征;⑥向量化,归一化;⑦训练模型;⑧得到预测结果并进行评估。
3、LDA主题模型
3.1 pLDA、共轭先验分布
LDA(Latent Dirichlet Allocation)文档主题生成模型,又称三层贝叶斯概率模型,包含词、主题和文档三层结构。生成模型指的是,认为一篇文章的每个词都是通过“一定概率选择了某个主题,并在此主题中以一定概率选择某词汇”的过程,概率均服从多项式分布。
LDA是非监督机器学习技术,采用词袋模型,将每一篇文档视为一个词频向量。
3.2 使用LDA生成主题特征进行文本分类
(1)对每一篇文档,从主题分布中抽取一个主题;
(2)从上述被抽到的主题所对应的单词分布中抽取一个单词;
(3)重复上述过程直至遍历文档中的每一个单词。
import numpy as np
import lda
X = np.genfromtxt("data\\source_wzp_lda_1.txt", skip_header=1, dtype = np.int)
#the vocab
file_vocab = open("data\\vectoritems_lda_3.txt", "r")
vocab = (file_vocab.read().decode("utf-8").split("\n"))[0:-1]
print len(vocab)
# 训练指定11个主题,500次迭代
model = lda.LDA(random_state=1, n_topics=11, n_iter=1000)
model.fit(X)
#主题-单词(topic-word)分布
topic_word = model.topic_word_
print("type(topic_word): {}".format(type(topic_word)))
print("shape: {}".format(topic_word.shape))
#获取每个topic下权重最高的10个单词
n = 10
for i, topic_dist in enumerate(topic_word):
topic_words = np.array(vocab)[np.argsort(topic_dist)][:-(n+1):-1]
print("topic {}\n- {}".format(i, ('-'.join(topic_words)).encode("utf-8")))
#文档主题(Document-Topic)分布:
doc_topic = model.doc_topic_
print("type(doc_topic): {}".format(type(doc_topic)))
print("shape: {}".format(doc_topic.shape))
#一篇文章对应一行,每行的和为1
#输入前10篇文章最可能的Topic
for n in range(20):
'''
for i in doc_topic[n]:
print i
'''
topic_most_pr = doc_topic[n].argmax()
print("doc: {} topic: {}".format(n, topic_most_pr))