偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

機器學習之用Python從零實現(xiàn)貝葉斯分類器

開發(fā) 后端 機器學習
通過本教程,你將學到樸素貝葉斯算法的原理和Python版本的逐步實現(xiàn)。

樸素貝葉斯算法簡單高效,在處理分類問題上,是應該首先考慮的方法之一。

通過本教程,你將學到樸素貝葉斯算法的原理和Python版本的逐步實現(xiàn)。

更新:查看后續(xù)的關于樸素貝葉斯使用技巧的文章“Better Naive Bayes: 12 Tips To Get The Most From The Naive Bayes Algorithm” 

 

 

[[194741]] 

樸素貝葉斯分類器,Matt Buck保留部分版權

關于樸素貝葉斯

樸素貝葉斯算法是一個直觀的方法,使用每個屬性歸屬于某個類的概率來做預測。你可以使用這種監(jiān)督性學習方法,對一個預測性建模問題進行概率建模。

給定一個類,樸素貝葉斯假設每個屬性歸屬于此類的概率獨立于其余所有屬性,從而簡化了概率的計算。這種強假定產(chǎn)生了一個快速、有效的方法。

給定一個屬性值,其屬于某個類的概率叫做條件概率。對于一個給定的類值,將每個屬性的條件概率相乘,便得到一個數(shù)據(jù)樣本屬于某個類的概率。

我們可以通過計算樣本歸屬于每個類的概率,然后選擇具有最高概率的類來做預測。

通常,我們使用分類數(shù)據(jù)來描述樸素貝葉斯,因為這樣容易通過比率來描述、計算。一個符合我們目的、比較有用的算法需要支持數(shù)值屬性,同時假設每一個數(shù)值屬性服從正態(tài)分布(分布在一個鐘形曲線上),這又是一個強假設,但是依然能夠給出一個健壯的結果。

預測糖尿病的發(fā)生

本文使用的測試問題是“皮馬印第安人糖尿病問題”。

這個問題包括768個對于皮馬印第安患者的醫(yī)療觀測細節(jié),記錄所描述的瞬時測量取自諸如患者的年紀,懷孕和血液檢查的次數(shù)。所有患者都是21歲以上(含21歲)的女性,所有屬性都是數(shù)值型,而且屬性的單位各不相同。

每一個記錄歸屬于一個類,這個類指明以測量時間為止,患者是否是在5年之內(nèi)感染的糖尿病。如果是,則為1,否則為0。

機器學習文獻中已經(jīng)多次研究了這個標準數(shù)據(jù)集,好的預測精度為70%-76%。

下面是pima-indians.data.csv文件中的一個樣本,了解一下我們將要使用的數(shù)據(jù)。

注意:下載文件,然后以.csv擴展名保存(如:pima-indians-diabetes.data.csv)。查看文件中所有屬性的描述。

  1. 6,148,72,35,0,33.6,0.627,50,1 
  2.  
  3. 1,85,66,29,0,26.6,0.351,31,0 
  4.  
  5. 8,183,64,0,0,23.3,0.672,32,1 
  6.  
  7. 1,89,66,23,94,28.1,0.167,21,0 
  8.  
  9. 0,137,40,35,168,43.1,2.288,33,1  

樸素貝葉斯算法教程

教程分為如下幾步:

1.處理數(shù)據(jù):從CSV文件中載入數(shù)據(jù),然后劃分為訓練集和測試集。

2.提取數(shù)據(jù)特征:提取訓練數(shù)據(jù)集的屬性特征,以便我們計算概率并做出預測。

3.單一預測:使用數(shù)據(jù)集的特征生成單個預測。

4.多重預測:基于給定測試數(shù)據(jù)集和一個已提取特征的訓練數(shù)據(jù)集生成預測。

5.評估精度:評估對于測試數(shù)據(jù)集的預測精度作為預測正確率。

6.合并代碼:使用所有代碼呈現(xiàn)一個完整的、獨立的樸素貝葉斯算法的實現(xiàn)。

1.處理數(shù)據(jù)

首先加載數(shù)據(jù)文件。CSV格式的數(shù)據(jù)沒有標題行和任何引號。我們可以使用csv模塊中的open函數(shù)打開文件,使用reader函數(shù)讀取行數(shù)據(jù)。

我們也需要將以字符串類型加載進來屬性轉換為我們可以使用的數(shù)字。下面是用來加載匹馬印第安人數(shù)據(jù)集(Pima indians dataset)的loadCsv()函數(shù)。

  1. import csv 
  2.  
  3. def loadCsv(filename): 
  4.  
  5. lines = csv.reader(open(filename, "rb")) 
  6.  
  7. dataset = list(lines) 
  8.  
  9. for i in range(len(dataset)): 
  10.  
  11. dataset[i] = [float(x) for x in dataset[i]] 
  12.  
  13. return dataset  

我們可以通過加載皮馬印第安人數(shù)據(jù)集,然后打印出數(shù)據(jù)樣本的個數(shù),以此測試這個函數(shù)。

  1. filename = 'pima-indians-diabetes.data.csv' 
  2.  
  3. dataset = loadCsv(filename) 
  4.  
  5. print('Loaded data file {0} with {1} rows').format(filename, len(dataset))  

運行測試,你會看到如下結果: 

  1. Loaded data file iris.data.csv with 150 rows 

下一步,我們將數(shù)據(jù)分為用于樸素貝葉斯預測的訓練數(shù)據(jù)集,以及用來評估模型精度的測試數(shù)據(jù)集。我們需要將數(shù)據(jù)集隨機分為包含67%的訓練集合和包含33%的測試集(這是在此數(shù)據(jù)集上測試算法的通常比率)。

下面是splitDataset()函數(shù),它以給定的劃分比例將數(shù)據(jù)集進行劃分。

  1. import random 
  2.  
  3. def splitDataset(dataset, splitRatio): 
  4.  
  5.     trainSize = int(len(dataset) * splitRatio) 
  6.  
  7.     trainSet = [] 
  8.  
  9.     copy = list(dataset) 
  10.  
  11.     while len(trainSet) < trainSize: 
  12.  
  13.         index = random.randrange(len(copy)) 
  14.  
  15.         trainSet.append(copy.pop(index)) 
  16.  
  17.     return [trainSet, copy]  

我們可以定義一個具有5個樣例的數(shù)據(jù)集來進行測試,首先它分為訓練數(shù)據(jù)集和測試數(shù)據(jù)集,然后打印出來,看看每個數(shù)據(jù)樣本最終落在哪個數(shù)據(jù)集。

  1. dataset = [[1], [2], [3], [4], [5]] 
  2.  
  3. splitRatio = 0.67 
  4.  
  5. train, test = splitDataset(dataset, splitRatio) 
  6.  
  7. print('Split {0} rows into train with {1} and test with {2}').format(len(dataset), train, test)  

運行測試,你會看到如下結果:

  1. Split 5 rows into train with [[4], [3], [5]] and test with [[1], [2]] 

提取數(shù)據(jù)特征

樸素貝葉斯模型包含訓練數(shù)據(jù)集中數(shù)據(jù)的特征,然后使用這個數(shù)據(jù)特征來做預測。

所收集的訓練數(shù)據(jù)的特征,包含相對于每個類的每個屬性的均值和標準差。舉例來說,如果如果有2個類和7個數(shù)值屬性,然后我們需要每一個屬性(7)和類(2)的組合的均值和標準差,也就是14個屬性特征。

在對特定的屬性歸屬于每個類的概率做計算、預測時,將用到這些特征。

我們將數(shù)據(jù)特征的獲取劃分為以下的子任務:

  1. 按類別劃分數(shù)據(jù)
  2. 計算均值
  3. 計算標準差
  4. 提取數(shù)據(jù)集特征
  5. 按類別提取屬性特征

按類別劃分數(shù)據(jù)

首先將訓練數(shù)據(jù)集中的樣本按照類別進行劃分,然后計算出每個類的統(tǒng)計數(shù)據(jù)。我們可以創(chuàng)建一個類別到屬于此類別的樣本列表的的映射,并將整個數(shù)據(jù)集中的樣本分類到相應的列表。

下面的SeparateByClass()函數(shù)可以完成這個任務:

  1. def separateByClass(dataset): 
  2.  
  3.     separated = {} 
  4.  
  5.     for i in range(len(dataset)): 
  6.  
  7.         vector = dataset[i] 
  8.  
  9.         if (vector[-1] not in separated): 
  10.  
  11.             separated[vector[-1]] = [] 
  12.  
  13.         separated[vector[-1]].append(vector) 
  14.  
  15.     return separated  

可以看出,函數(shù)假設樣本中最后一個屬性(-1)為類別值,返回一個類別值到數(shù)據(jù)樣本列表的映射。

我們可以用一些樣本數(shù)據(jù)測試如下:

  1. dataset = [[1,20,1], [2,21,0], [3,22,1]] 
  2.  
  3. separated = separateByClass(dataset) 
  4.  
  5. print('Separated instances: {0}').format(separated)  

運行測試,你會看到如下結果:

  1. Separated instances: {0: [[2, 21, 0]], 1: [[1, 20, 1], [3, 22, 1]]} 

計算均值

我們需要計算在每個類中每個屬性的均值。均值是數(shù)據(jù)的中點或者集中趨勢,在計算概率時,我們用它作為高斯分布的中值。

我們也需要計算每個類中每個屬性的標準差。標準差描述了數(shù)據(jù)散布的偏差,在計算概率時,我們用它來刻畫高斯分布中,每個屬性所期望的散布。

標準差是方差的平方根。方差是每個屬性值與均值的離差平方的平均數(shù)。注意我們使用N-1的方法(譯者注:參見無偏估計),也就是在在計算方差時,屬性值的個數(shù)減1。

  1. import math 
  2.  
  3. def mean(numbers): 
  4.  
  5.     return sum(numbers)/float(len(numbers)) 
  6.  
  7.   
  8.  
  9. def stdev(numbers): 
  10.  
  11.     avg = mean(numbers) 
  12.  
  13.     variance = sum([pow(x-avg,2) for x in numbers])/float(len(numbers)-1) 
  14.  
  15.     return math.sqrt(variance)  

通過計算從1到5這5個數(shù)的均值來測試函數(shù)。

  1. numbers = [1,2,3,4,5] 
  2.  
  3. print('Summary of {0}: mean={1}, stdev={2}').format(numbers, mean(numbers), stdev(numbers))  

運行測試,你會看到如下結果:

  1. Summary of [1, 2, 3, 4, 5]: mean=3.0, stdev=1.58113883008 

提取數(shù)據(jù)集的特征

現(xiàn)在我們可以提取數(shù)據(jù)集特征。對于一個給定的樣本列表(對應于某個類),我們可以計算每個屬性的均值和標準差。

zip函數(shù)將數(shù)據(jù)樣本按照屬性分組為一個個列表,然后可以對每個屬性計算均值和標準差。

  1. def summarize(dataset): 
  2.  
  3. summaries = [(mean(attribute), stdev(attribute)) for attribute in zip(*dataset)] 
  4.  
  5. del summaries[-1] 
  6.  
  7. return summaries  

我們可以使用一些測試數(shù)據(jù)來測試這個summarize()函數(shù),測試數(shù)據(jù)對于第一個和第二個數(shù)據(jù)屬性的均值和標準差顯示出顯著的不同。

  1. dataset = [[1,20,0], [2,21,1], [3,22,0]] 
  2.  
  3. summary = summarize(dataset) 
  4.  
  5. print('Attribute summaries: {0}').format(summary)  

運行測試,你會看到如下結果:

  1. Attribute summaries: [(2.0, 1.0), (21.0, 1.0)] 

按類別提取屬性特征

合并代碼,我們首先將訓練數(shù)據(jù)集按照類別進行劃分,然后計算每個屬性的摘要。

  1. def summarizeByClass(dataset): 
  2.  
  3.     separated = separateByClass(dataset) 
  4.  
  5.     summaries = {} 
  6.  
  7.     for classValue, instances in separated.iteritems(): 
  8.  
  9.         summaries[classValue] = summarize(instances) 
  10.  
  11.     return summaries  

使用小的測試數(shù)據(jù)集來測試summarizeByClass()函數(shù)。

  1. dataset = [[1,20,1], [2,21,0], [3,22,1], [4,22,0]] 
  2.  
  3. summary = summarizeByClass(dataset) 
  4.  
  5. print('Summary by class value: {0}').format(summary)  

運行測試,你會看到如下結果:

  1. Summary by class value: 
  2.  
  3. {0: [(3.0, 1.4142135623730951), (21.5, 0.7071067811865476)], 
  4.  
  5. 1: [(2.0, 1.4142135623730951), (21.0, 1.4142135623730951)]}  

預測

我們現(xiàn)在可以使用從訓練數(shù)據(jù)中得到的摘要來做預測。做預測涉及到對于給定的數(shù)據(jù)樣本,計算其歸屬于每個類的概率,然后選擇具有最大概率的類作為預測結果。

我們可以將這部分劃分成以下任務:

  1. 計算高斯概率密度函數(shù)
  2. 計算對應類的概率
  3. 單一預測
  4. 評估精度

計算高斯概率密度函數(shù)

給定來自訓練數(shù)據(jù)中已知屬性的均值和標準差,我們可以使用高斯函數(shù)來評估一個給定的屬性值的概率。

已知每個屬性和類值的屬性特征,在給定類值的條件下,可以得到給定屬性值的條件概率。

關于高斯概率密度函數(shù),可以查看參考文獻??傊?,我們要把已知的細節(jié)融入到高斯函數(shù)(屬性值,均值,標準差),并得到屬性值歸屬于某個類的似然(譯者注:即可能性)。

在calculateProbability()函數(shù)中,我們首先計算指數(shù)部分,然后計算等式的主干。這樣可以將其很好地組織成2行。

  1. import math 
  2.  
  3. def calculateProbability(x, mean, stdev): 
  4.  
  5.     exponent = math.exp(-(math.pow(x-mean,2)/(2*math.pow(stdev,2)))) 
  6.  
  7.     return (1 / (math.sqrt(2*math.pi) * stdev)) * exponent  

使用一些簡單的數(shù)據(jù)測試如下:

  1. x = 71.5 
  2.  
  3. mean = 73 
  4.  
  5. stdev = 6.2 
  6.  
  7. probability = calculateProbability(x, mean, stdev) 
  8.  
  9. print('Probability of belonging to this class: {0}').format(probability)  

運行測試,你會看到如下結果:

  1. Probability of belonging to this class: 0.0624896575937 

計算所屬類的概率

既然我們可以計算一個屬性屬于某個類的概率,那么合并一個數(shù)據(jù)樣本中所有屬性的概率,最后便得到整個數(shù)據(jù)樣本屬于某個類的概率。

使用乘法合并概率,在下面的calculClassProbilities()函數(shù)中,給定一個數(shù)據(jù)樣本,它所屬每個類別的概率,可以通過將其屬性概率相乘得到。結果是一個類值到概率的映射。

  1. def calculateClassProbabilities(summaries, inputVector): 
  2.  
  3.     probabilities = {} 
  4.  
  5.     for classValue, classSummaries in summaries.iteritems(): 
  6.  
  7.         probabilities[classValue] = 1 
  8.  
  9.         for i in range(len(classSummaries)): 
  10.  
  11.             mean, stdev = classSummaries[i] 
  12.  
  13.             x = inputVector[i] 
  14.  
  15.             probabilities[classValue] *= calculateProbability(x, mean, stdev) 
  16.  
  17.     return probabilities  

測試calculateClassProbabilities()函數(shù)。

  1. summaries = {0:[(1, 0.5)], 1:[(20, 5.0)]} 
  2.  
  3. inputVector = [1.1, '?'
  4.  
  5. probabilities = calculateClassProbabilities(summaries, inputVector) 
  6.  
  7. print('Probabilities for each class: {0}').format(probabilities)  

運行測試,你會看到如下結果:

  1. Probabilities for each class: {0: 0.7820853879509118, 1: 6.298736258150442e-05} 

單一預測

既然可以計算一個數(shù)據(jù)樣本屬于每個類的概率,那么我們可以找到最大的概率值,并返回關聯(lián)的類。

下面的predict()函數(shù)可以完成以上任務。

  1. def predict(summaries, inputVector): 
  2.  
  3.     probabilities = calculateClassProbabilities(summaries, inputVector) 
  4.  
  5.     bestLabel, bestProb = None, -1 
  6.  
  7.     for classValue, probability in probabilities.iteritems(): 
  8.  
  9.         if bestLabel is None or probability > bestProb: 
  10.  
  11.             bestProb = probability 
  12.  
  13.             bestLabel = classValue 
  14.  
  15.     return bestLabel  

測試predict()函數(shù)如下:

  1. summaries = {'A':[(1, 0.5)], 'B':[(20, 5.0)]} 
  2.  
  3. inputVector = [1.1, '?'
  4.  
  5. result = predict(summaries, inputVector) 
  6.  
  7. print('Prediction: {0}').format(result)  

運行測試,你會得到如下結果:

  1. Prediction: A 

多重預測

最后,通過對測試數(shù)據(jù)集中每個數(shù)據(jù)樣本的預測,我們可以評估模型精度。getPredictions()函數(shù)可以實現(xiàn)這個功能,并返回每個測試樣本的預測列表。

  1. def getPredictions(summaries, testSet): 
  2.  
  3.     predictions = [] 
  4.  
  5.     for i in range(len(testSet)): 
  6.  
  7.         result = predict(summaries, testSet[i]) 
  8.  
  9.         predictions.append(result) 
  10.  
  11.     return predictions  

測試getPredictions()函數(shù)如下。

  1. summaries = {'A':[(1, 0.5)], 'B':[(20, 5.0)]} 
  2.  
  3. testSet = [[1.1, '?'], [19.1, '?']] 
  4.  
  5. predictions = getPredictions(summaries, testSet) 
  6.  
  7. print('Predictions: {0}').format(predictions)  

運行測試,你會看到如下結果:

  1. Predictions: ['A''B'

計算精度

預測值和測試數(shù)據(jù)集中的類別值進行比較,可以計算得到一個介于0%~100%精確率作為分類的精確度。getAccuracy()函數(shù)可以計算出這個精確率。

  1. def getAccuracy(testSet, predictions): 
  2.  
  3.     correct = 0 
  4.  
  5.     for x in range(len(testSet)): 
  6.  
  7.         if testSet[x][-1] == predictions[x]: 
  8.  
  9.             correct += 1 
  10.  
  11.     return (correct/float(len(testSet))) * 100.0  

我們可以使用如下簡單的代碼來測試getAccuracy()函數(shù)。

  1. testSet = [[1,1,1,'a'], [2,2,2,'a'], [3,3,3,'b']] 
  2.  
  3. predictions = ['a''a''a'
  4.  
  5. accuracy = getAccuracy(testSet, predictions) 
  6.  
  7. print('Accuracy: {0}').format(accuracy)  

運行測試,你會得到如下結果:

  1. Accuracy: 66.6666666667 

合并代碼

最后,我們需要將代碼連貫起來。

下面是樸素貝葉斯Python版的逐步實現(xiàn)的全部代碼。

 

運行示例,得到如下輸出:

  1. Split 768 rows into train=514 and test=254 rows 
  2.  
  3. Accuracy: 76.3779527559%  

實現(xiàn)擴展

這一部分為你提供了擴展思路,你可以將其作為教程的一部分,使用你已經(jīng)實現(xiàn)的Python代碼,進行應用研究。

到此,你已經(jīng)使用Python一步步完成了高斯版本的樸素貝葉斯。

你可以進一步擴展算法實現(xiàn):

計算所屬類的概率:將一個數(shù)據(jù)樣本歸屬于每個類的概率更新為一個比率。計算上就是將一個樣本數(shù)據(jù)歸屬于某個類的概率,比上其歸屬于每一個類的概率的和。舉例來說,一個樣本屬于類A的概率時0.02,屬于類B的概率時0.001,那么樣本屬于類A的可能性是(0.02/(0.02+0.001))*100 大約為95.23%。

對數(shù)概率:對于一個給定的屬性值,每個類的條件概率很小。當將其相乘時結果會更小,那么存在浮點溢出的可能(數(shù)值太小,以至于在Python中不能表示)。一個常用的修復方案是,合并其概率的對數(shù)值??梢匝芯繉崿F(xiàn)下這個改進。

名詞屬性:改進算法實現(xiàn),使其支持名詞屬性。這是十分相似的,你所收集的每個屬性的摘要信息是對于每個類的類別值的比率。潛心學習參考文獻來獲取更多信息。

不同的密度函數(shù)(伯努利或者多項式):我們已經(jīng)嘗試了高斯樸素貝葉斯,你也可以嘗試下其他分布。實現(xiàn)一個不同的分布諸如多項分布、伯努利分布或者內(nèi)核樸素貝葉斯,他們對于屬性值的分布 和/或 與類值之間的關系有不同的假設。

學習資源及深入閱讀

這一部分提供了一些用于學習更多樸素貝葉斯算法的資源,包括算法理論和工作原理,以及代碼實現(xiàn)中的實際問題。

問題

更多學習預測糖尿病發(fā)作問題的資源

  • Pima Indians Diabetes Data Set:這個頁面提供數(shù)據(jù)集文件,同時描述了各個屬性,也列出了使用該數(shù)據(jù)集的論文列表
  • Dataset File:數(shù)據(jù)集文件
  • Dataset Summary:數(shù)據(jù)集屬性的描述
  • Diabetes Dataset Results:許多標準算法在該數(shù)據(jù)集上的精度

代碼

這一部分包含流行的機器學習庫中的樸素貝葉斯的開源實現(xiàn)。如果你在考慮實現(xiàn)自己的用于實際使用的版本,可以查閱這些

  • Naive Bayes in Scikit-Learn:scikit-learn庫中樸素貝葉斯的實現(xiàn)
  • Naive Bayes documentation:scikit-learn庫中關于樸素貝葉斯的文檔和樣例代碼
  • Simple Naive Bayes in Weka:樸素貝葉斯的Weka實現(xiàn)

書籍

你應該有幾本機器學習應用的書籍。這一部分高亮出了常用機器學習書籍中關于樸素貝葉斯的章節(jié)。

  • Applied Predictive Modeling, page 353
  • Data Mining: Practical Machine Learning Tools and Techniques, page 94
  • Machine Learning for Hackers, page 78
  • An Introduction to Statistical Learning: with Applications in R, page 138
  • Machine Learning: An Algorithmic Perspective, page 171
  • Machine Learning in Action, page 61 (Chapter 4)
  • Machine Learning, page 177 (chapter 6) 
責任編輯:龐桂玉 來源: Python開發(fā)者
相關推薦

2024-12-09 09:44:34

機器學習模型分類器

2023-11-07 14:30:28

Python開發(fā)

2015-07-23 14:53:50

貝葉斯分類器

2018-11-14 07:41:58

機器學習算法感知器

2022-06-05 21:16:08

機器學習Python

2025-01-20 09:41:29

2017-04-25 16:45:11

2024-09-11 08:34:28

2021-02-14 14:31:35

機器學習Python模型

2021-07-29 13:06:29

Python機器學習編程語言

2019-04-24 15:06:37

Http服務器協(xié)議

2024-08-23 08:57:13

PyTorch視覺轉換器ViT

2022-08-15 15:16:20

機器學習圖片深度學習

2021-03-10 14:21:33

人工智能機器學習算法

2019-01-23 11:45:47

機器學習人工智能機器人

2017-05-09 08:48:44

機器學習

2017-11-01 17:00:13

機器學習算法MiniFlow

2020-12-24 06:54:45

Python機器學習多類分類邏輯回歸

2024-09-29 09:32:58

2020-09-24 11:46:03

Promise
點贊
收藏

51CTO技術棧公眾號