国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

【數(shù)據(jù)科學(xué)系統(tǒng)學(xué)習(xí)】機(jī)器學(xué)習(xí)算法 # 西瓜書學(xué)習(xí)記錄 [6] 樸素貝葉斯實(shí)踐

leanxi / 2906人閱讀

摘要:本篇內(nèi)容為機(jī)器學(xué)習(xí)實(shí)戰(zhàn)第章基于概率論的分類方法樸素貝葉斯程序清單。樸素貝葉斯優(yōu)點(diǎn)在數(shù)據(jù)較少的情況下仍然有效,可以處理多類別問題。參考鏈接機(jī)器學(xué)習(xí)實(shí)戰(zhàn)筆記之四基于概率論的分類方法樸素貝葉斯不足之處,歡迎指正。

本篇內(nèi)容為《機(jī)器學(xué)習(xí)實(shí)戰(zhàn)》第 4 章 基于概率論的分類方法:樸素貝葉斯程序清單。所用代碼為 python3。


樸素貝葉斯

優(yōu)點(diǎn):在數(shù)據(jù)較少的情況下仍然有效,可以處理多類別問題。
缺點(diǎn):對于輸入數(shù)據(jù)的準(zhǔn)備方式較為敏感。
適用數(shù)據(jù)類型:標(biāo)稱型數(shù)據(jù)。


使用 Python 進(jìn)行文本分類

簡單描述這個(gè)過程為:從文本中獲取特征,構(gòu)建分類器,進(jìn)行分類輸出結(jié)果。這里的特征是來自文本的詞條 (token),需要將每一個(gè)文本片段表示為一個(gè)詞條向量,其中值為 1 表示詞條出現(xiàn)在文檔中,0 表示詞條未出現(xiàn)。

接下來給出將文本轉(zhuǎn)換為數(shù)字向量的過程,然后基于這些向量來計(jì)算條件概率,并在此基礎(chǔ)上構(gòu)建分類器。

下面我們以在線社區(qū)的留言板為例,給出一個(gè)用來過濾的例子。
為了不影響社區(qū)的發(fā)展,我們需要屏蔽侮辱性的言論,所以要構(gòu)建一個(gè)快速過濾器,如果某條留言使用來負(fù)面或者侮辱性的語言,就將該留言標(biāo)識為內(nèi)容不當(dāng)。對此問題建立兩個(gè)類別:侮辱類和非侮辱類,分別使用 1 和 0 來表示。
準(zhǔn)備數(shù)據(jù):從文本中構(gòu)建詞向量 程序清單 4-1 詞表到向量的轉(zhuǎn)換函數(shù)
"""
Created on Sep 10, 2018

@author: yufei
"""

# coding=utf-8
from numpy import *

# 創(chuàng)建一些實(shí)例樣本
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 代表正常言論

    """
    變量 postingList 返回的是進(jìn)行詞條切分后的文檔集合。
    留言文本被切分成一些列詞條集合,標(biāo)點(diǎn)符號從文本中去掉
    變量 classVec 返回一個(gè)類別標(biāo)簽的集合。
    這些文本的類別由人工標(biāo)注,標(biāo)注信息用于訓(xùn)練程序以便自動(dòng)檢測侮辱性留言。
    """
    return postingList, classVec

"""
創(chuàng)建一個(gè)包含在所有文檔中出現(xiàn)的不重復(fù)詞的列表
是用python的 Set 數(shù)據(jù)類型
將詞條列表輸給 Set 構(gòu)造函數(shù),set 就會返回一個(gè)不重復(fù)詞表
"""
def createVocabList(dataSet):
    # 創(chuàng)建一個(gè)空集合
    vocabSet = set([])
    # 將每篇文檔返回的新詞集合添加進(jìn)去,即創(chuàng)建兩個(gè)集合的并集
    for document in dataSet:
        vocabSet = vocabSet | set(document)
    # 獲得詞匯表
    return list(vocabSet)

# 參數(shù):詞匯表,某個(gè)文檔
def setOfWords2Vec(vocabList, inputSet):
    # 創(chuàng)建一個(gè)和詞匯表等長的向量,將其元素都設(shè)置為 0
    returnVec = [0] * len(vocabList)
    # 遍歷文檔中所有單詞
    for word in inputSet:
        # 如果出現(xiàn)詞匯表中的單詞,將輸出的文檔向量中的對應(yīng)值設(shè)為 1
        if word in vocabList:
            returnVec[vocabList.index(word)] = 1
        else:
            print("the word: %s is not in my Vocabulary!" % word)
    # 輸出文檔向量,向量元素為 1 或 0
    return returnVec

在 python 提示符下,執(zhí)行代碼并得到結(jié)果:

>>> import bayes
>>> list0Posts, listClasses = bayes.loadDataSet()
>>> myVocabList = bayes.createVocabList(list0Posts)
>>> myVocabList
["problems", "mr", "ate", "buying", "not", "garbage", "how", "maybe", "stupid", "cute", "stop", "help", "dalmation", "take", "is", "worthless", "him", "flea", "park", "my", "I", "to", "licks", "steak", "dog", "love", "quit", "so", "please", "posting", "has", "food"]

即可得到的一個(gè)不會出現(xiàn)重復(fù)單詞的詞表myVocabList,目前該詞表還沒有排序。

繼續(xù)執(zhí)行代碼:

>>> bayes.setOfWords2Vec(myVocabList, list0Posts[3])
[0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
>>> bayes.setOfWords2Vec(myVocabList, list0Posts[0])
[0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0]

函數(shù)setOfWords2Vec使用詞匯表或者說想要檢查的所有單詞作為輸入,然后為其中每一個(gè)單詞構(gòu)建一個(gè)特征。一旦給定一篇文章(本例中指一條留言),該文檔就會被轉(zhuǎn)換為詞向量。

訓(xùn)練算法:從詞向量計(jì)算概率

函數(shù)偽代碼如下:

··· 計(jì)算每個(gè)類別中的文檔數(shù)目
··· 對每篇訓(xùn)練文檔:
······ 對每個(gè)類別:
········· 如果詞條出現(xiàn)在文檔中—>增加該詞條的計(jì)數(shù)值
········· 增加所有詞條的計(jì)數(shù)值
······ 對每個(gè)類別:
········· 對每個(gè)詞條:
············ 將該詞條對數(shù)目除以總詞條數(shù)目得到條件概率
······ 返回每個(gè)類別對條件概率
程序清單 4-2 樸素貝葉斯分類器訓(xùn)練函數(shù)
"""
Created on Sep 11, 2018

@author: yufei
"""
# 參數(shù):文檔矩陣 trainMatrix,每篇文檔的類別標(biāo)簽所構(gòu)成的向量 trainCategory
def trainNB0(trainMatrix, trainCategory):
    numTrainDocs = len(trainMatrix) #文檔的個(gè)數(shù)
    numWords = len(trainMatrix[0])  #獲取第一篇文檔的單詞長度

    """
    計(jì)算文檔屬于侮辱性文檔的概率
    用類別為1的個(gè)數(shù)除以總篇數(shù)
    sum([0,1,0,1,0,1])=3,也即是 trainCategory 里面 1 的個(gè)數(shù)
    """
    pAbusive = sum(trainCategory) / float(numTrainDocs)

    """
    初始化概率
    當(dāng)利用貝葉斯分類器對文檔分類時(shí),計(jì)算多個(gè)概率的乘積以獲得屬于某個(gè)類別的概率
    把所有詞出現(xiàn)次數(shù)初始化為1,分母初始化為2,用log避免數(shù)太小被約掉
    """
    p0Num = ones(numWords)
    p1Num = ones(numWords)

    p0Denom = 2.0
    p1Denom = 2.0

    # 遍歷訓(xùn)練集 trainMatrix 中的所有文檔
    for i in range(numTrainDocs):
        # 侮辱性詞語在某個(gè)文檔中出現(xiàn)
        if trainCategory[i] == 1:
            # 該詞對應(yīng)個(gè)數(shù)加一,即分子把所有的文檔向量按位置累加
            # trainMatrix[2] = [1,0,1,1,0,0,0];trainMatrix[3] = [1,1,0,0,0,1,1]
            p1Num += trainMatrix[i]
            # 文檔總詞數(shù)加一,即對于分母
            # 把trainMatrix[2]中的值先加起來為3,再把所有這個(gè)類別的向量都這樣累加起來,這個(gè)是計(jì)算單詞總數(shù)目
            p1Denom += sum(trainMatrix[i])
        # 正常詞語在某個(gè)文檔中出現(xiàn),同上
        else:
            p0Num += trainMatrix[i]
            p0Denom +=sum(trainMatrix[i])

    """
    對每個(gè)元素除以該類別的總詞數(shù),得條件概率
    防止太多的很小的數(shù)相乘造成下溢。對乘積取對數(shù)
    # p1Vect = log(p1Num / p1Denom)
    # p0Vect = log(p0Num / p0Denom)
    """
    
    p1Vect = p1Num / p1Denom
    p0Vect = p0Num / p0Denom

    """
    函數(shù)返回兩個(gè)向量和一個(gè)概率
    返回每個(gè)類別的條件概率,是一個(gè)向量
    在向量里面和詞匯表向量長度相同
    每個(gè)位置代表這個(gè)單詞在這個(gè)類別中的概率
    """
    return p0Vect, p1Vect, pAbusive

在 python 提示符下,執(zhí)行代碼并得到結(jié)果:

>>> from numpy import *
>>> importlib.reload(bayes)

>>> list0Posts, listClasses = bayes.loadDataSet()
>>> myVocabList = bayes.createVocabList(list0Posts)

以上,調(diào)入數(shù)據(jù)后構(gòu)建了一個(gè)包含所有詞的列表myVocabList

>>> trainMat = []
>>> for postinDoc in list0Posts:
...     trainMat.append(bayes.setOfWords2Vec(myVocabList, postinDoc))

這個(gè)for循環(huán)使用詞向量來填充trainMat列表。

繼續(xù)給出屬于侮辱性文檔的概率以及兩個(gè)類別的概率向量。

>>> p0V, p1V, pAb = bayes.trainNB0(trainMat, listClasses)

查看變量的內(nèi)部值

>>> pAb
0.5
>>> p0V
array([0.03846154, 0.07692308, 0.03846154, 0.07692308, 0.07692308,
       0.07692308, 0.07692308, 0.03846154, 0.03846154, 0.03846154,
       0.07692308, 0.07692308, 0.15384615, 0.07692308, 0.07692308,
       0.07692308, 0.03846154, 0.07692308, 0.07692308, 0.07692308,
       0.07692308, 0.07692308, 0.03846154, 0.07692308, 0.11538462,
       0.07692308, 0.07692308, 0.03846154, 0.03846154, 0.03846154,
       0.07692308, 0.03846154])
>>> p1V
array([0.0952381 , 0.04761905, 0.0952381 , 0.0952381 , 0.14285714,
       0.04761905, 0.04761905, 0.0952381 , 0.0952381 , 0.14285714,
       0.04761905, 0.04761905, 0.04761905, 0.04761905, 0.04761905,
       0.04761905, 0.0952381 , 0.04761905, 0.04761905, 0.04761905,
       0.0952381 , 0.04761905, 0.0952381 , 0.04761905, 0.0952381 ,
       0.04761905, 0.04761905, 0.19047619, 0.0952381 , 0.0952381 ,
       0.04761905, 0.0952381 ])

我們發(fā)現(xiàn)文檔屬于侮辱類的概率pAb為 0.5,查看pV1的最大值 0.19047619,它出現(xiàn)在第 27 個(gè)下標(biāo)位置,查看myVocabList的第 27 個(gè)下標(biāo)位置該詞為 stupid,說明這是最能表征類別 1 的單詞。

測試算法:根據(jù)現(xiàn)實(shí)情況修改分類器 程序清單 4-3 樸素貝葉斯分類函數(shù)
"""
Created on Sep 11, 2018

@author: yufei
"""
# vec2Classify: 要分類的向量
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
    p1 = sum(vec2Classify * p1Vec) + log(pClass1)
    p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1)
    if p1 > p0:
        return 1
    else:
        return 0

def  testingNB():
    list0Posts, listClasses = loadDataSet()
    myVocabList = createVocabList(list0Posts)
    trainMat = []
    for posinDoc in list0Posts:
        trainMat.append(setOfWords2Vec(myVocabList, posinDoc))
    p0V, p1V, pAb = trainNB0(array(trainMat), array(listClasses))

    testEntry = ["love", "my","dalmation"]
    thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
    print(testEntry, "classified as: ", classifyNB(thisDoc, p0V, p1V, pAb))
    testEntry = ["stupid", "garbage"]
    thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
    print(testEntry, "classified as: ", classifyNB(thisDoc, p0V, p1V, pAb))

在 python 提示符下,執(zhí)行代碼并得到結(jié)果:

>>> importlib.reload(bayes)

>>> bayes.testingNB()
["love", "my", "dalmation"] classified as:  0
["stupid", "garbage"] classified as:  1

分類器輸出結(jié)果,分類正確。

準(zhǔn)備數(shù)據(jù):文檔詞袋模型

詞集模型:將每個(gè)詞的出現(xiàn)與否作為一個(gè)特征。即我們上面所用到的。
詞袋模型:將每個(gè)詞出現(xiàn)次數(shù)作為一個(gè)特征。每遇到一個(gè)單詞,其詞向量對應(yīng)值 +1,而不是全設(shè)置為 1。

對函數(shù)setOfWords2Vec()進(jìn)行修改,修改后的函數(shù)為bagOfWords2VecMN

程序清單 4-4 樸素貝葉斯詞袋模型
def bagOfWords2VecMN(vocabList, inputSet):
    returnVec = [0] * len(vocabList)
    for word in inputSet:
        if word in inputSet:
            returnVec[vocabList.index(word)] += 1
    return returnVec

修改的地方為:每當(dāng)遇到一個(gè)單詞時(shí),它會增加詞向量中的對應(yīng)值,而不只是將對應(yīng)的數(shù)值設(shè)為 1。

下面我們將利用該分類器來過濾垃圾郵件。


示例:使用樸素貝葉斯過濾垃圾郵件 測試算法:使用樸素貝葉斯進(jìn)行交叉驗(yàn)證 程序清單 4-5 文件解析及完整的垃圾郵件測試函數(shù)
"""
Created on Sep 11, 2018

@author: yufei
"""

"""
接受一個(gè)大字符串并將其解析為字符串列表
"""
def textParse(bigString):    #input is big string, #output is word list
    import re
    listOfTokens = re.split(r"W*", bigString)
    # 去掉小于兩個(gè)字符的字符串,并將所有字符串轉(zhuǎn)換為小寫
    return [tok.lower() for tok in listOfTokens if len(tok) > 2]

"""
對貝葉斯垃圾郵件分類器進(jìn)行自動(dòng)化處理
"""
def spamTest():
    docList=[]; classList = []; fullText =[]
    #導(dǎo)入并解析文本文件為詞列表
    for i in range(1,26):
        wordList = textParse(open("email/spam/%d.txt" % i, encoding="ISO-8859-1").read())
        docList.append(wordList)
        fullText.extend(wordList)
        classList.append(1)
        
        wordList = textParse(open("email/ham/%d.txt" % i, encoding="ISO-8859-1").read())
        docList.append(wordList)
        fullText.extend(wordList)
        classList.append(0)
    vocabList = createVocabList(docList)#create vocabulary
    trainingSet = list(range(50)); testSet=[]           #create test set
    
    for i in range(10):
        randIndex = int(random.uniform(0,len(trainingSet)))
        testSet.append(trainingSet[randIndex])
        del(trainingSet[randIndex])
        
    trainMat=[]; trainClasses = []
    
    # 遍歷訓(xùn)練集的所有文檔,對每封郵件基于詞匯表并使用 bagOfWords2VecMN 來構(gòu)建詞向量
    for docIndex in trainingSet:#train the classifier (get probs) trainNB0
        trainMat.append(bagOfWords2VecMN(vocabList, docList[docIndex]))
        trainClasses.append(classList[docIndex])
    # 用上面得到的詞在 trainNB0 函數(shù)中計(jì)算分類所需的概率
    p0V,p1V,pSpam = trainNB0(array(trainMat),array(trainClasses))
    errorCount = 0
    
    # 對測試集分類
    for docIndex in testSet:        #classify the remaining items
        wordVector = bagOfWords2VecMN(vocabList, docList[docIndex])
        # 如果郵件分類錯(cuò)誤,錯(cuò)誤數(shù)加 1 
        if classifyNB(array(wordVector),p0V,p1V,pSpam) != classList[docIndex]:
            errorCount += 1
            print ("classification error",docList[docIndex])
    # 給出總的錯(cuò)誤百分比
    print ("the error rate is: ",float(errorCount)/len(testSet))
    #return vocabList,fullText

在 python 提示符下,執(zhí)行代碼并得到結(jié)果:

>>> importlib.reload(bayes)

>>> bayes.spamTest()
classification error ["home", "based", "business", "opportunity", "knocking", "your", "door", "don", "rude", "and", "let", "this", "chance", "you", "can", "earn", "great", "income", "and", "find", "your", "financial", "life", "transformed", "learn", "more", "here", "your", "success", "work", "from", "home", "finder", "experts"]
the error rate is:  0.1

函數(shù)spamTest()會輸出在 10 封隨機(jī)選擇的電子郵件上的分類錯(cuò)誤率。由于是隨機(jī)選擇的,所以每次的輸出結(jié)果可能有些差別。如果想要更好地估計(jì)錯(cuò)誤率,那么就應(yīng)該將上述過程重復(fù)多次求平均值。

這里的代碼需要注意的兩個(gè)地方是:

1、直接使用語句 wordList = textParse(open("email/spam/%d.txt" % i).read()) 報(bào)錯(cuò) UnicodeDecodeError: "utf-8" codec can"t decode byte 0x92 in position 884: invalid start byte。這是因?yàn)樵谖募锟赡艽嬖诓皇且?utf-8 格式保存的字符,需改為wordList = textParse(open("email/spam/%d.txt" % i, encoding="ISO-8859-1").read())

2、將隨機(jī)選出的文檔添加到測試集后,要同時(shí)將其從訓(xùn)練集中刪除,使用語句 del(trainingSet[randIndex]),此時(shí)會報(bào)錯(cuò) TypeError: "range" object doesn"t support item deletion,這是由于 python2 和 python3 的不同而導(dǎo)致的。在 python2 中可以直接執(zhí)行,而在 python3 中需將 trainingSet 設(shè)為 trainingSet = list(range(50)),而不是 trainingSet = range(50),即必須讓它是一個(gè) list 再進(jìn)行刪除操作。


以上,我們就用樸素貝葉斯對文檔進(jìn)行了分類。


參考鏈接:
《機(jī)器學(xué)習(xí)實(shí)戰(zhàn)》筆記之四——基于概率論的分類方法:樸素貝葉斯
UnicodeDecodeError: "utf-8" codec can"t decode byte 0x92 in position 884: invalid start byte

不足之處,歡迎指正。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/42429.html

相關(guān)文章

  • 數(shù)據(jù)學(xué)系統(tǒng)學(xué)習(xí)機(jī)器學(xué)習(xí)算法 # 西瓜學(xué)習(xí)記錄 [5] 支持向量機(jī)實(shí)踐

    摘要:本篇內(nèi)容為機(jī)器學(xué)習(xí)實(shí)戰(zhàn)第章支持向量機(jī)部分程序清單。支持向量機(jī)優(yōu)點(diǎn)泛化錯(cuò)誤率低,計(jì)算開銷不大,結(jié)果易解釋。注以上給出的僅是簡化版算法的實(shí)現(xiàn),關(guān)于完整的算法加速優(yōu)化并應(yīng)用核函數(shù),請參照機(jī)器學(xué)習(xí)實(shí)戰(zhàn)第頁。 本篇內(nèi)容為《機(jī)器學(xué)習(xí)實(shí)戰(zhàn)》第 6 章 支持向量機(jī)部分程序清單。所用代碼為 python3。 支持向量機(jī)優(yōu)點(diǎn):泛化錯(cuò)誤率低,計(jì)算開銷不大,結(jié)果易解釋。 缺點(diǎn):對參數(shù)調(diào)節(jié)和核函數(shù)的選擇敏感,...

    RebeccaZhong 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<