import numpy as np
from math import *
import random
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']]
classVec=[0,1,0,1,0,1] #1表示侮辱性言论,0表示正常言论
return postingList,classVec
#构建词汇表生成函数creatVocabList
def createVocabList(dataSet):
vocabSet=set([])
for document in dataSet:
vocabSet=vocabSet|set(document) #取两个集合的并集
return list(vocabSet)
#对输入的词汇表构建词向量
#词集模型
def setOfWords2Vec(vocabList,inputSet):
returnVec=np.zeros(len(vocabList)) #生成零向量的array
for word in inputSet:
if word in vocabList:
returnVec[vocabList.index(word)]=1 #有单词,则该位置填充0
else: print('the word:%s is not in my Vocabulary!'% word)
return returnVec #返回全为0和1的向量
#这种构建词向量的方法,只记录了每个词是否出现,而没有记录词出现的次数,这样的模型
#叫做词集模型,如果在词向量中记录词出现的次数,每出现一次,则多记录一次,这样的词向
#量构建方法,被称为词袋模型,下面构建以一个词袋模型的词向量生成函数bagOfWord2VecMN:
#词袋模型
def bagOfWords2VecMN(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) #文档数目,此例为6
numWord=len(trainMatrix[0]) #词汇表词数目,即不重复词汇的总和
pAbusive=sum(trainCategory)/len(trainCategory) #p1,出现侮辱性评论的概率
p0Num=np.zeros(numWord)
p1Num=np.zeros(numWord)
p0Demon=0;p1Demon=0
for i in range(numTrainDocs):
if trainCategory[i]==0:
p0Num+=trainMatrix[i] #向量相加,该向量长度为词汇表词数目
p0Demon+=sum(trainMatrix[i]) #该向量中数值1的累加求和
else:
p1Num+=trainMatrix[i]
p1Demon+=sum(trainMatrix[i])
p0Vec=p0Num/p0Demon #p0/1Vec 向量长度为词汇表词数目,值为词汇表中每个词在
#正常/侮辱言论中所有词个数所占的比例
p1Vec=p1Num/p1Demon
return p0Vec,p1Vec,pAbusive
##算法漏洞:
##1.乘积为0
##我们看到,当某分类下某词项出现频次为0时,其概率也是0,因此在计算p(w0|ci)p(w1|ci)p(w2|ci)......p(wN|ci)
##会因为其中某个的概率为0而全部是0。 为了避免这样的情况发生,我们将所有词项出现的频次都初始化为1,
##某类所有词项数量初始化为2。
##2.因子太小导致结果溢出问题
##由于p(w0|ci)p(w1|ci)p(w2|ci)......p(wN|ci)中每个因子都很小,所有因子相乘,特别是因子数量多的时候,
##会导致结果溢出,从而得到错误的数据 避免溢出问题的发生,可以使用求自然对数的方法,自然对数和原本
##的数值同增同减,不会有任何损失,因此不会影响求得的概率结果。
def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1):
p1=sum(vec2Classify*p1Vec)+log(pClass1) #p1=sum(vec2Classify*p1Vec)+log(pClass1) 的数学原理是ln(a*b)=ln(a) +ln(b)
p0=sum(vec2Classify*p0Vec)+log(1-pClass1)
if p1>p0:
return 1
else:
return 0
def trainNB1(trainMatrix,trainCategory):
numTrainDocs=len(trainMatrix)
numWord=len(trainMatrix[0])
pAbusive=sum(trainCategory)/len(trainCategory)
p0Num=ones(numWord);p1Num=ones(numWord)# 初始化为1
p0Demon=2;p1Demon=2 #初始化为2
for i in range(numTrainDocs):
if trainCategory[i]==0:
p0Num+=trainMatrix[i]
p0Demon+=sum(trainMatrix[i])
else:
p1Num+=trainMatrix[i]
p1Demon+=sum(trainMatrix[i])
p0Vec=log(p0Num/p0Demon) #对结果求对数
p1Vec=log(p1Num/p1Demon) #对结果求自然对数
return p0Vec,p1Vec,pAbusive
#获取频率最高的词项
def calcMostFreq(vocabList,fullText):
import operator
freqDict={}
for word in vocabList:
freqDict[word]=fullText.count(word)
sortedFreq=sorted(freqDict.items(),key=operator.itemgetter(1),reverse=True) #reverse=True/False 降序/升序
return sortedFreq[:30] #operator模块提供的itemgetter函数用于获取对象的哪些维的数据,参数为一些序号(即需要获取的数据在对象中的序号)
def localWords(feed1,feed0):
import feedparser
docList=[];classList=[];fullText=[]
minLen=min(len(feed1['entries']),len(feed0['entries']))
print(minLen)
for i in range(minLen):
wordList=textParser(feed1['entries'][i]['summary'])
docList.append(wordList)
fullText.extend(wordList)
classList.append(1)
wordList=textParser(feed0['entries'][i]['summary'])
docList.append(wordList)
fullText.extend(wordList)
classList.append(0)
vocabList=createVocabList(docList)
top30words=calcMostFreq(vocabList,fullText) #选取频率最高的30个词
#去掉出现频率最高的30个词
for pairW in top30words:
if pairW[0] in vocabList:
vocabList.remove(pairW[0])
trainSet=list[range(2*minLen)]
testSet=[]
print(trainSet)
for i in range(20): #从原始数据中选出20个作为测试数据
randIndex=int(random.uniform(0,len(trainSet)))
testSet.append(trainSet[randIndex])
del(trainSet[randIndex])
trainMat=[];trainClasses=[]
for docIndex in trainSet:
trainMat.append(bagOfWords2VecMN(vocabList,docList[docIndex]))
trainClasses.append(classList[docIndex])
p0V,p1V,pSpam=trainNB1(trainMat,trainClasses)
errorCount=0
for docIndex in testSet:
wordVector=bagOfWords2VecMN(vocabList,docList[docIndex])
if classifyNB(wordVector,p0V,p1V,pSpam) !=classList[docIndex]:
errorCount+=1
print('the error rate is:',float(errorCount)/len(testSet))
return vocabList,p0V,p1V
#最具表征性的词汇表显示函数
def getTopWords(ny,sf,t=-6.0):
import operator
vocabList,p0V,p1V=localWords(ny,sf)
topNY=[];topSF=[]
for i in range(len(p0V)):
#选取一个阈值t
if p0V[i]>t:topSF.append((vocabList[i],p0V[i]))
if p1V[i]>t:topNY.append((vocabList[i],p1V[i]))
sortedSF=sorted(topSF,key=lambda x: x[1],reverse=True)
print('SF**SF**SF**SF**SF**SF**SF**SF**SF**SF**SF**SF')
for item in sortedSF:
print(item[0])
sortedNY=sorted(topNY,key=lambda pair: pair[1],reverse=True)
print('NY**NY**NY**NY**NY**NY**NY**NY**NY**NY**NY**NY')
for item in sortedNY:
print(item[0])