# -*- coding: utf-8 -*-
import numpy as np
def readMatrix(file):
fd = open(file, 'r')
hdr = fd.readline() #第一行數據
rows, cols = [int(s) for s in fd.readline().strip().split()] #讀取第二行數據,以空格分割轉化爲列表s儲存並讓rows等於列表中第一個元素,並讓cols爲列表中第二個元素
tokens = fd.readline().strip().split() #讀取第三行數據,以空格分開儲存在列表tokens中
matrix = np.zeros((rows, cols))
Y = []
for i, line in enumerate(fd): #i代表位置,line代表字母
nums = [int(x) for x in line.strip().split()] #nums是提取的數字
Y.append(nums[0]) #Y代表是否爲垃圾郵件
kv = np.array(nums[1:]) #kv爲後列數據
k = np.cumsum(kv[:-1:2])
v = kv[1::2]
matrix[i, k] = v #訓練數據中matrix爲2144*1448,tokens爲1448,y爲2144,一共2144個數據,1448個特徵x
def nb_train(matrix, list,category):
state0 = [0] * len(list)
state1 = [0] * len(list)
count_state0=0
count_state1=0
for i in range(len(matrix)):
if category[i]== 0:
state0 = state0 + matrix[i]
count_state0=count_state0+1
else:
state1 = state1 + matrix[i]
count_state1=count_state1+1
state0=state0/(len(matrix)*len(matrix[0]))
state1=state1/(len(matrix)*len(matrix[0]))
for i in range(len(state0)): #laplace平滑
if state0[i]==0:
state0[i]=float(1)/(len(matrix)*len(matrix[0])+len(matrix))
for i in range(len(state1)): #laplace平滑
if state1[i]==0:
state1[i]=float(1)/(len(matrix)*len(matrix[0])+len(matrix))
proportion_state0=float(count_state0)/(count_state0+count_state1)
proportion_state1=float(count_state1)/(count_state0+count_state1)
return state0,state1,proportion_state0,proportion_state1
def nb_test(matrix,state0, state1, proportion_state0, proportion_state1): #測試數據中matrix爲800*1448,tokens爲1448,y爲800,一共800個數據,1448個特徵x
output = np.zeros(matrix.shape[0]) #對於普通概率取對數
output0=[]
output1=[]
for i in range(len(matrix)):
possibility0=0
possibility1=0
for j in range(len(matrix[0])):
while matrix[i][j]>=1:
possibility0 = possibility0+np.log(state0[j])
possibility1 = possibility1+np.log(state1[j])
matrix[i][j] = matrix[i][j]-1
possibility0=possibility0+np.log(proportion_state0)
possibility1=possibility1+np.log(proportion_state1)
output0.append(possibility0)
output1.append(possibility1)
for i in range(len(output1)):
if output0[i]<output1[i]:
output[i]=1
else:
output[i]=0
return output
# def nb_test(matrix,state0, state1, proportion_state0, proportion_state1): #測試數據中matrix爲800*1448,tokens爲1448,y爲800,一共800個數據,1448個特徵x
# output1 = np.zeros(matrix.shape[0]) #利用普通樸素貝葉斯算法,出現了過多概率爲0的位置
# for i in range(len(matrix)):
# possibility=1
# for j in range(len(matrix[0])):
# while matrix[i][j]>=1 :
# possibility=possibility*state0[j]
# matrix[i][j] = matrix[i][j]-1
# possibility=possibility*proportion_state0
# output[i]=possibility
# return output
def evaluate(output, label):
error = (output != label).sum() * 1. / len(output)
print 'Error: %1.4f' % error
def main():
trainMatrix, tokenlist, trainCategory = readMatrix('MATRIX.TRAIN')
testMatrix, tokenlist, testCategory = readMatrix('MATRIX.TEST')
state0, state1, proportion_state0, proportion_state1 = nb_train(trainMatrix,tokenlist,trainCategory)
output = nb_test(testMatrix,state0, state1, proportion_state0, proportion_state1)
evaluate(output, testCategory)
return
if __name__ == '__main__':
main()
斯坦福大學機器學習作業題Problem Set #2 Spam classication
本次作業題的內容是利用樸素貝葉斯分類器識別是否爲垃圾郵件,關於文本的提取,分詞,和標註都是已成形的數據,只需要寫個樸素貝葉斯分類器驗證正確率就可以。
關於樸素貝葉斯的模型可以參考http://blog.csdn.net/longxinchen_ml/article/details/50597149,講的很清楚,ng在視頻中講的樸素貝葉斯分類器用的是伯努利模型,即只計算某個詞受否存在,而忽略了關於詞頻,而本道作業題使用的多項式模型。
在本次作業中有幾個注意的點:
1.需使用laplace平滑,因爲有些詞語可能在我們的訓練數據中從未出現過,就會導致概率爲0的情況,而樸素貝葉斯模型中分子是一些概率連乘積,如果有一項爲0,會導致答案爲0。
2.樸素貝葉斯模型中分子是一些概率連乘積,而每一項都很小,會導致連乘積很小,出現越界的情況,導致爲0,這裏對於概率取對數,概率的連乘積也變成對數相加,由於對數和x是正相關的,在最後判斷的時候只需比較取對數後的結果大小即可。
3.我們通常是運用這個式子進行計算,但是由於分母一樣,所以我們常常會捨去分母,但是這樣的話是否爲垃圾郵件的概率兩者想加不爲1,所以要都計算,在比大小,判斷是否爲垃圾郵件
可以看出樸素貝葉斯模型的誤差還是比較小的,有95%左右的正確率。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.