斯坦福大學機器學習作業題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%左右的正確率。
# -*- 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()


發佈了32 篇原創文章 · 獲贊 3 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章