機器學習實戰---朴素貝葉斯算法使用K折交叉驗證


一:訓練模型、實現預測函數

import numpy as np
import re
import random

def loadDataSet():
    DataSetList=[]  #全部數據集
    classVec = []    #標簽值

    #獲取數據
    SpamPath = "email/spam/{}.txt"  #獲取文件路徑
    HamPath = "email/ham/{}.txt"

    for i in range(1,26): #兩個路徑各有25個文件
        documentData = open(SpamPath.format(i),'r', encoding='ISO-8859-1').read()
        #使用正則進行分割,除了空格、還有標點都可以用於分割
        WordVec = re.split(r"\W+",documentData)  #\W*表示匹配多個非字母、數字、下划線的字符
        DataSetList.append([item for item in WordVec if len(item)>0])
        classVec.append(1)
        documentData = open(HamPath.format(i), 'r', encoding='ISO-8859-1').read()
        # 使用正則進行分割,除了空格、還有標點都可以用於分割
        WordVec = re.split(r"\W+", documentData)  # \W*表示匹配多個非字母、數字、下划線的字符
        DataSetList.append([item for item in WordVec if len(item)>0])
        classVec.append(0)
    return DataSetList,classVec

def createVocabList(dataSet):   #創建詞匯列表 將多個文檔單詞歸為一個
    VocabSet = set([]) #使用集合,方便去重
    for document in dataSet:
        VocabSet = VocabSet | set(document)   #保持同類型
    VocabList = list(VocabSet)
    VocabList.sort()
    return VocabList

def WordSet2Vec(VocaList,inputSet):  #根據我們上面得到的全部詞匯列表,將我們輸入得inputSet文檔向量化
    returnVec = [0]*len(VocaList)
    for word in inputSet:
        if word in VocaList:
            returnVec[VocaList.index(word)] = 1
        else:
            print("the word: %s is not in my Vocabulary!"%word)
    return returnVec

def trainNB0(trainMatrix,trainCategory):    #訓練朴素貝葉斯模型 傳入numpy數組類型 trainMatrix所有文檔詞匯向量矩陣(m*n矩陣 m個文檔,每個文檔都是n列,代表詞匯向量大小),trainCategory每篇文檔得標簽
    numTrainDoc = len(trainMatrix)  #文檔數量
    pC1 = np.sum(trainCategory)/numTrainDoc    #p(c1)得概率   p(c0)=1-p(c1)
    wordVecNum = len(trainMatrix[0])    #因為每個文檔轉換為詞匯向量后都是一樣得長度

    #初始化p1,p0概率向量---改進為拉普拉斯平滑
    p1VecNum,p0VecNum = np.ones(wordVecNum),np.ones(wordVecNum)
    p1Sum,p0Sum = 2.0,2.0   #N*1    N表示分類數

    #循環每一個文檔
    for i in range(numTrainDoc):
        if trainCategory[i] == 1: #侮辱性文檔
            p1VecNum += trainMatrix[i]  #統計侮辱性文檔中,每個單詞出現頻率
            p1Sum += np.sum(trainMatrix[i]) #統計侮辱性文檔中出現得全部單詞數   每個單詞出現概率就是單詞出現頻率/全部單詞
        else:   #正常文檔
            p0VecNum += trainMatrix[i]
            p0Sum += np.sum(trainMatrix[i])

    p1Vect = np.log(p1VecNum / p1Sum)   #統計各類文檔中的單詞出現頻率
    p0Vect = np.log(p0VecNum / p0Sum)   #使用對數避免下溢

    return p1Vect,p0Vect,pC1

def classifyNB(testVec,p0Vec,p1Vec,pC1):
    p1 = sum(testVec*p1Vec)+np.log(pC1) #使用對數之后變為求和
    p0 = sum(testVec*p0Vec)+np.log(1-pC1)
    if p1 > p0:
        return 1
    else:
        return 0

二:實現K折交叉驗證法---k=5

def OneCrossValidate(trainSet,trainCls,testSet,testCls):
    #訓練模型
    p1Vect,p0Vect,pC1 = trainNB0(np.array(trainSet),np.array(trainCls))
    err_count = 0
    #驗證集進行測試
    for i in range(10):
        c = classifyNB(np.array(testSet[i]),p0Vect,p1Vect,pC1)
        if c != testCls[i]:
            err_count += 1

    return err_count/10


def KCrossValidate(trainMat,trainClassVec):    #K折交叉驗證 5
    randIdx = list(range(50))
    random.shuffle(randIdx)
    error_radio = 0.0

    for i in range(5):  #5次
        rdInd = randIdx #隨機索引
        #選取訓練集、驗證集索引
        trainSet = []
        trainCls = []
        testSet = []
        testCls = []
        testSetIdx = set(randIdx[10*i:10*i+10])  # 訓練集
        trainSetIdx = set(rdInd)-testSetIdx  # 驗證集
        #選取訓練集、驗證集數據
        for idx in trainSetIdx:
            trainSet.append(trainMat[idx])
            trainCls.append(trainClassVec[idx])

        for idx in testSetIdx:
            testSet.append(trainMat[idx])
            testCls.append(trainClassVec[idx])
        print(OneCrossValidate(trainSet,trainCls,testSet,testCls))
        error_radio += OneCrossValidate(trainSet,trainCls,testSet,testCls)

    return error_radio/5

DocData,classVec = loadDataSet()
voclist = createVocabList(DocData)

#獲取全部文檔詞匯向量矩陣
trainMulList = []
for doc in DocData:
    trainMulList.append(WordSet2Vec(voclist,doc))

print(KCrossValidate(trainMulList,classVec))

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM