最近在学习自然语言处理,做了一个文本分类的demo,主要是基于朴素贝叶斯算法和TF-IDF方法的文本分类挖掘,下面的代码如下:
# -*- coding:utf-8 -*-
import numpy as np
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','my'],
['stop','posting','stupid','worthless','garbage'],
['mr','licks','ate','my','steak','how','to','stop','stupid'],
['quit','buying','worthless','dog','food','stupid']]
classVec=[0,1,0,1,0,1]
return postingList,classVec
class NBayes(object):
def __init__(self): #初始化生成所需要的值
self.vocabulary=[]#字典
self.idf=0 #词典的idf权重向量
self.tf=0 #训练集的全值矩阵
self.Pcates={} #类别字典
self.labels=[] #对应每个文本的分类
self.doclenth=0 #训练集文本数
self.vocablen=0 #词典的词长
self.testset=0 #测试集
def train_set(self,trainset,classVec): #倒入训练集,生成算法必须的参数和数据结构
self.cate_prob(classVec)#计算每个类别在总类别中出现的概率
self.doclenth=len(trainset) #计算类别的文本数
tempset=set()
[tempset.add(word) for doc in trainset for word in doc] #生成词典,也就是生成词的总数
self.vocabulary=list(tempset) #将其转换为list 的数据类型
self.vocablen=len(self.vocabulary) #输出此时的字典的总长度
self.calc_wordfreq(trainset) #计算词频数据集
self.build_tdm() #按分类累计向量空间的每维值
def cate_prob(self,classVec):#计算数据集中每个分类的频率
self.labels=classVec #将标签的数据集给类别标签
labeltemps=set(self.labels) #获取类别标签中不同的类,利用里面提到set函数
for labeltemp in labeltemps:
#self.labels.count(labeltemp)这段代码用于统计重复分类的次数
self.Pcates[labeltemp]=float(self.labels.count(labeltemp))/float(len(self.labels))#输出每个类别出现的频率
#生成普通的词频向量
def calc_wordfreq(self,trainset):
self.idf=np.zeros([1,self.vocablen]) #生成词向量
self.tf=np.zeros([self.doclenth,self.vocablen])#训练样本文件数
for indx in range(self.doclenth): #遍历所有文本
for word in trainset[indx]: #遍历文本中的每个词
self.tf[indx,self.vocabulary.index(word)]+=1
#找到文本词在词典中的位置+1
for signleword in set(trainset[indx]): #看看这句话的含义
self.idf[0,self.vocabulary.index(signleword)]+=1 #计算在词典中的词中出现的总数,文件数
#按分类累计向量空间的每维值:
def build_tdm(self):
self.tdm=np.zeros([len(self.Pcates),self.vocablen])#类别行+词典列
sumlist=np.zeros([len(self.Pcates),1]) #统计每个分类的总值
for indx in range(self.doclenth):
self.tdm[self.labels[indx]]+=self.tf[indx] #将同一类别的此向量加总
#统计每个分类的总值——是一个标量
sumlist[self.labels[indx]]=np.sum(self.tdm[self.labels[indx]])
self.tdm=self.tdm/sumlist #
def map2vecab(self,testdata):#将测试集映射到当前的词典
self.testset=np.zeros([1,self.vocablen])
for word in testdata:
self.testset[0,self.vocabulary.index(word)]+=1
def predict(self,testset): #预测分了结果,输出预测的分类类别
if np.shape(testset)[1]!=self.vocablen: #如果测试集长度与字典不相等,则退出程序 说明其超出了词袋的长度
print("输入错误")
exit(0)
predvalue=0 #初始化类别概率
predclass="" #初始化类别名称
for tdm_vect,keyclass in zip(self.tdm,self.Pcates):
temp=np.sum(testset*tdm_vect*self.Pcates[keyclass])
if temp >predvalue:
predvalue=temp
predclass=keyclass
return predclass
def calc_tfidf(self,trainset):
self.idf=np.zeros([1,self.vocablen])
self.tf=np.zeros([self.doclenth,self.vocablen])
for indx in range(self.doclenth):
for word in trainset[indx]:
self.tf[indx,self.vocabulary.index(word)]+=1
#消除不同句长产生的偏差
self.tf[indx]=self.tf[indx]/float(len(trainset[indx]))
for signleword in set(trainset[indx]):
self.idf[0,self.vocabulary.index(signleword)]+=1
self.idf=np.log(float(self.doclenth)/self.idf)
self.tf=np.multiply(self.tf,self.idf)
主程序的运行:
# -*- coding: utf-8 -*-
import sys
import os
from numpy import *
import numpy as np
from Nbays_lib import *
dataSet,listClasses=loadDataSet()#倒入外部的数据集
#dataSet:句子的词向量
#listrClass是句子所处的类别
nb=NBayes()
nb.train_set(dataSet,listClasses)
nb.map2vecab(dataSet[1])
print(nb.predict(nb.testset))
输出的结果为
1