【博客的主要內容主要是自己的學習筆記,并結合個人的理解,供各位在學習過程中參考,若有疑問,歡迎提出;若有侵權,請告知博主刪除,原創文章轉載還請注明出處。】
[機器學習實戰:文本過濾器]
實例一:在線社區留言板過濾器
1 需求描述:
為維護在線社區留言板的正常次序,需屏蔽侮辱性的言論,需構建一個快速過濾器,如果某條留言使用了負面或侮辱性的言語,那么就將該留言標識為內容不當。
2 算法分析:【自問的過程】
1、擁有數據樣本情況?
有若干條數據樣本,其中每條“言論”均標識所屬類別(即侮辱性言語或非侮辱性言語)
2、程序如何判斷言語為侮辱性和非侮辱性?
- 樸素貝葉斯
將使用樸素貝葉斯公式:
c 表示分類類別即:侮辱性言語和非侮辱性言語
對每個類別分母都一樣,即需計算$P(w|c_i)$ 和 $P(c_i)$,在樸素貝葉斯中假設事件是相互獨立的,故:
$P(w|c_i)=P(w_0|c_i)P(w_1|c_i)...P(w_n|c_i)$
需要計算什么?
$P(w|c_i)=P(w_0|c_i)P(w_1|c_i)...*P(w_n|c_i)$
以上用文字描述:計算每個類別下各個單詞出現的概率。由此,需要統計內容:
a)每條言論下各個單詞出現的次數;
b)每個類別的單詞總數;數據分析:現有數據什么樣?需要對數據如何處理?
a、對每條言語轉換成向量數組;
b、制定“詞典集合”,將每條言語做并集,去除重復單詞;并將“詞典集合”轉換為向量數組;
- 特殊情況分析:
-
a、由于$P(w|c_i)=P(w_0|c_i)P(w_1|c_i)...*P(w_n|c_i)$ 是做乘法運算,若其中一個單詞概率為0,則該言語概率為0。
- [解決方法]將所有詞出現數初始化為1,分母初始化為2。
-
b、太多很小數相乘,結果將趨近為0.
- [解決方法]對乘積取自然對數。在代數中有ln(a*b) = ln(a) + ln(b)。
3 算法實現
#1、將文本轉換為數字向量
##a、建立不重復的詞匯表
def createVocabList(dataSet):
vocabSet = set([])
for document in dataSet:
vocabSet = vocabSet | set(document)
return list(vocabSet)
#test
myVocabLists = createVocabList(postingLists)
##b、將每條言語轉換為數字向量:建立與詞匯表同等大小的言語向量,若言語中的詞匯在詞匯表中出現則標記為1,否則為0.
#vocabList:單詞字典集合
#inputSet:單條文本
def setOfWords2Vec(vocabList,inputSet):
returnVec = [0]*len(vocabList)
for word in inputSet:
if word in vocabList:
returnVec[vocabList.index(word)] = 1
else:
print "the word :%s is not in my vocabulary!" % word
return returnVec
#test
wordsVec=[]
for postingList in postingLists:
wordsVec.append(setOfWords2Vec(myVocabLists,postingList))
#trainMainx - 輸入文檔矩陣
#trainCategory - 由每篇文檔類別標簽所構成的向量
def trainNB0(trainMatrix,trainCategory):
numTrainDocs = len(trainMatrix)
numWords = len(trainMatrix[0])
pAbusive = sum(trainCategory)/float(numTrainDocs)
#初始化概率
p0Num = ones(numWords)
p1Num = ones(numWords)
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 = log(p1Num / p1Denom)
p0Vect = log(p0Num / p0Denom)
return p0Vect,p1Vect,pAbusive
##test
p0Vect,p1Vect,pAbusive=trainNB0(wordsVec,classLists)
2 實例二:電子郵件垃圾過濾
如何從文本文檔中構建自己的詞列表
隨機選擇數據的一部分作為訓練集,剩余部分作為測試集的過程稱為“留存交叉驗證”(hold-out cross validation)
思路:
1)構建詞列表:對文本文檔進行按詞切分
2)交叉驗證:對現有數據劃分為訓練集和測試集
3)樸素貝葉斯算法計算獨立事件概率
- 計算算法準確率
5)多次重復實驗,提高正確率
textParse()接受一個大字符串并將其解析為字符串列表;
spamTest()對垃圾郵件分類器進行自動處理。主要:
1)解析文本文件編制成詞列表;
2)構建測試集合訓練集
######電子郵件垃圾過濾######
def textParse(bigString):
import re
listOfTokens = re.split(r'\W*',bigString)
return [tok.lower() for tok in listOfTokens if len(tok) > 2]
def spamTest():
docList=[]; classList=[]; fullText=[]
#創建詞匯表
for i in range(1,26):
wordList = textParse(open('email/spam/%d.txt'%i).read())
docList.append(workList)
fullText.extend(workList)
classList.append(1)
wordList = textParse(open('email/ham/%d.txt'%i).read())
docList.append(wordList)
fullText.extend(wordList)
classList.append(0)
vocabList = createVocabList(docList)
#劃分測試集 和 訓練集
trainingSet = range(50);
testSet=[]
for i in range(10):
randIndex = int(random.uniform(0,len(trainingSet)))
testSet.append(trainingSet[randIndex])
del(trainingSet[randIndex])
#樸素貝葉斯計算概率
trainMat = [];trainClasses=[]
for docIndex in trainingSet:
trainMat.append(bagOfWord2VecMN(vocabList,docList[docIndex]))
trainClasses.append(classList[docIndex])
p0V,p1V,pSpam=trainNB(array(trainMat),array(trainClasses))
#統計錯誤率
errorCount = 0
for docIndex in testSet:
wordVector = bagOfWord2VecMN(vocabList,docList[docIndex])
if classifyNB(array(wordVector),p0V,p1V,pSpam) != classList[docIndex]:
errorCount +=1
print "classification error:",docList[docIndex]
print "the error rate is:", float(errorCount)/len(testSet)
3 實例三:使用樸素貝葉斯分類器從個人廣告中獲取區域傾向
對兩個城市所發布的征婚廣告信息,來比較這兩個城市的人們在廣告用詞上是否不同。
如果結論是不同,那么他們各自常用的詞是那些?
從人們的用詞中,能否對不同城市的人所關心的內容有所了解?
該實例目的:通過觀察單詞和條件概率值來發現與特定城市相關的內容
calcMostFreq() 遍歷詞匯表中每個詞并統計它在文本中出現的次數,然后根據出現次數從高到低對詞典進行排序,最后返回排序最高的100個單詞。
localWords() 主要:1)解析文本詞列表;2)構建測試集合訓練集
getTopWords() 訓練并測試樸素貝葉斯分類器,返回使用的概率值。