99999久久久久久亚洲,欧美人与禽猛交狂配,高清日韩av在线影院,一个人在线高清免费观看,啦啦啦在线视频免费观看www

熱線電話:13121318867

登錄
首頁精彩閱讀用Python從零實(shí)現(xiàn)貝葉斯分類器的機(jī)器學(xué)習(xí)的教程
用Python從零實(shí)現(xiàn)貝葉斯分類器的機(jī)器學(xué)習(xí)的教程
2018-01-12
收藏

用Python從零實(shí)現(xiàn)貝葉斯分類器的機(jī)器學(xué)習(xí)的教程

關(guān)于樸素貝葉斯

樸素貝葉斯算法是一個直觀的方法,使用每個屬性歸屬于某個類的概率來做預(yù)測。你可以使用這種監(jiān)督性學(xué)習(xí)方法,對一個預(yù)測性建模問題進(jìn)行概率建模。
給定一個類,樸素貝葉斯假設(shè)每個屬性歸屬于此類的概率獨(dú)立于其余所有屬性,從而簡化了概率的計算。這種強(qiáng)假定產(chǎn)生了一個快速、有效的方法。
給定一個屬性值,其屬于某個類的概率叫做條件概率。對于一個給定的類值,將每個屬性的條件概率相乘,便得到一個數(shù)據(jù)樣本屬于某個類的概率。
我們可以通過計算樣本歸屬于每個類的概率,然后選擇具有最高概率的類來做預(yù)測。
通常,我們使用分類數(shù)據(jù)來描述樸素貝葉斯,因?yàn)檫@樣容易通過比率來描述、計算。一個符合我們目的、比較有用的算法需要支持?jǐn)?shù)值屬性,同時假設(shè)每一個數(shù)值屬性服從正態(tài)分布(分布在一個鐘形曲線上),這又是一個強(qiáng)假設(shè),但是依然能夠給出一個健壯的結(jié)果。
預(yù)測糖尿病的發(fā)生
本文使用的測試問題是“皮馬印第安人糖尿病問題”。
這個問題包括768個對于皮馬印第安患者的醫(yī)療觀測細(xì)節(jié),記錄所描述的瞬時測量取自諸如患者的年紀(jì),懷孕和血液檢查的次數(shù)。所有患者都是21歲以上(含21歲)的女性,所有屬性都是數(shù)值型,而且屬性的單位各不相同。
每一個記錄歸屬于一個類,這個類指明以測量時間為止,患者是否是在5年之內(nèi)感染的糖尿病。如果是,則為1,否則為0。
機(jī)器學(xué)習(xí)文獻(xiàn)中已經(jīng)多次研究了這個標(biāo)準(zhǔn)數(shù)據(jù)集,好的預(yù)測精度為70%-76%。
下面是pima-indians.data.csv文件中的一個樣本,了解一下我們將要使用的數(shù)據(jù)。
注意:下載文件,然后以.csv擴(kuò)展名保存(如:pima-indians-diabetes.data.csv)。查看文件中所有屬性的描述。    
6,148,72,35,0,33.6,0.627,50,1
1,85,66,29,0,26.6,0.351,31,0
8,183,64,0,0,23.3,0.672,32,1
1,89,66,23,94,28.1,0.167,21,0
0,137,40,35,168,43.1,2.288,33,1

樸素貝葉斯算法教程

教程分為如下幾步:
1.處理數(shù)據(jù):從CSV文件中載入數(shù)據(jù),然后劃分為訓(xùn)練集和測試集。
2.提取數(shù)據(jù)特征:提取訓(xùn)練數(shù)據(jù)集的屬性特征,以便我們計算概率并做出預(yù)測。
3.單一預(yù)測:使用數(shù)據(jù)集的特征生成單個預(yù)測。
4.多重預(yù)測:基于給定測試數(shù)據(jù)集和一個已提取特征的訓(xùn)練數(shù)據(jù)集生成預(yù)測。
5.評估精度:評估對于測試數(shù)據(jù)集的預(yù)測精度作為預(yù)測正確率。
6.合并代碼:使用所有代碼呈現(xiàn)一個完整的、獨(dú)立的樸素貝葉斯算法的實(shí)現(xiàn)。
1.處理數(shù)據(jù)

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

我們也需要將以字符串類型加載進(jìn)來屬性轉(zhuǎn)換為我們可以使用的數(shù)字。下面是用來加載匹馬印第安人數(shù)據(jù)集(Pima indians dataset)的loadCsv()函數(shù)。    
import csv
def loadCsv(filename):
  lines = csv.reader(open(filename, "rb"))
  dataset = list(lines)
  for i in range(len(dataset)):
    dataset[i] = [float(x) for x in dataset[i]]
  return dataset

我們可以通過加載皮馬印第安人數(shù)據(jù)集,然后打印出數(shù)據(jù)樣本的個數(shù),以此測試這個函數(shù)。    
filename = 'pima-indians-diabetes.data.csv'
dataset = loadCsv(filename)
print('Loaded data file {0} with {1} rows').format(filename, len(dataset))

運(yùn)行測試,你會看到如下結(jié)果:    
Loaded data file iris.data.csv with 150 rows

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

下面是splitDataset()函數(shù),它以給定的劃分比例將數(shù)據(jù)集進(jìn)行劃分。    
import random
def splitDataset(dataset, splitRatio):
  trainSize = int(len(dataset) * splitRatio)
  trainSet = []
  copy = list(dataset)
  while len(trainSet) < trainSize:
    index = random.randrange(len(copy))
    trainSet.append(copy.pop(index))
  return [trainSet, copy]

我們可以定義一個具有5個樣例的數(shù)據(jù)集來進(jìn)行測試,首先它分為訓(xùn)練數(shù)據(jù)集和測試數(shù)據(jù)集,然后打印出來,看看每個數(shù)據(jù)樣本最終落在哪個數(shù)據(jù)集。    
dataset = [[1], [2], [3], [4], [5]]
splitRatio = 0.67
train, test = splitDataset(dataset, splitRatio)
print('Split {0} rows into train with {1} and test with {2}').format(len(dataset), train, test)

運(yùn)行測試,你會看到如下結(jié)果:    
Split 5 rows into train with [[4], [3], [5]] and test with [[1], [2]]

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

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

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

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

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

    按類別劃分?jǐn)?shù)據(jù)
    計算均值
    計算標(biāo)準(zhǔn)差
    提取數(shù)據(jù)集特征
    按類別提取屬性特征

按類別劃分?jǐn)?shù)據(jù)

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

下面的SeparateByClass()函數(shù)可以完成這個任務(wù):    
def separateByClass(dataset):
  separated = {}
  for i in range(len(dataset)):
    vector = dataset[i]
    if (vector[-1] not in separated):
      separated[vector[-1]] = []
    separated[vector[-1]].append(vector)
  return separated

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

我們可以用一些樣本數(shù)據(jù)測試如下:    
dataset = [[1,20,1], [2,21,0], [3,22,1]]
separated = separateByClass(dataset)
print('Separated instances: {0}').format(separated)

運(yùn)行測試,你會看到如下結(jié)果:    
Separated instances: {0: [[2, 21, 0]], 1: [[1, 20, 1], [3, 22, 1]]}

計算均值

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

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

標(biāo)準(zhǔn)差方差的平方根。方差是每個屬性值與均值的離差平方的平均數(shù)。注意我們使用N-1的方法(譯者注:參見無偏估計),也就是在在計算方差時,屬性值的個數(shù)減1。    
import math
def mean(numbers):
  return sum(numbers)/float(len(numbers))
 
def stdev(numbers):
  avg = mean(numbers)
  variance = sum([pow(x-avg,2) for x in numbers])/float(len(numbers)-1)
  return math.sqrt(variance)

通過計算從1到5這5個數(shù)的均值來測試函數(shù)。    
numbers = [1,2,3,4,5]
print('Summary of {0}: mean={1}, stdev={2}').format(numbers, mean(numbers), stdev(numbers))

運(yùn)行測試,你會看到如下結(jié)果:    
Summary of [1, 2, 3, 4, 5]: mean=3.0, stdev=1.58113883008

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

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

zip函數(shù)將數(shù)據(jù)樣本按照屬性分組為一個個列表,然后可以對每個屬性計算均值和標(biāo)準(zhǔn)差。    
def summarize(dataset):
  summaries = [(mean(attribute), stdev(attribute)) for attribute in zip(*dataset)]
  del summaries[-1]
  return summaries

我們可以使用一些測試數(shù)據(jù)來測試這個summarize()函數(shù),測試數(shù)據(jù)對于第一個和第二個數(shù)據(jù)屬性的均值和標(biāo)準(zhǔn)差顯示出顯著的不同。    
dataset = [[1,20,0], [2,21,1], [3,22,0]]
summary = summarize(dataset)
print('Attribute summaries: {0}').format(summary)

運(yùn)行測試,你會看到如下結(jié)果:    
Attribute summaries: [(2.0, 1.0), (21.0, 1.0)]

按類別提取屬性特征

合并代碼,我們首先將訓(xùn)練數(shù)據(jù)集按照類別進(jìn)行劃分,然后計算每個屬性的摘要。    
def summarizeByClass(dataset):
  separated = separateByClass(dataset)
  summaries = {}
  for classValue, instances in separated.iteritems():
    summaries[classValue] = summarize(instances)
  return summaries

使用小的測試數(shù)據(jù)集來測試summarizeByClass()函數(shù)。    
dataset = [[1,20,1], [2,21,0], [3,22,1], [4,22,0]]
summary = summarizeByClass(dataset)
print('Summary by class value: {0}').format(summary)

運(yùn)行測試,你會看到如下結(jié)果:    
Summary by class value:
{0: [(3.0, 1.4142135623730951), (21.5, 0.7071067811865476)],
1: [(2.0, 1.4142135623730951), (21.0, 1.4142135623730951)]}

預(yù)測

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

我們可以將這部分劃分成以下任務(wù):

    計算高斯概率密度函數(shù)
    計算對應(yīng)類的概率
    單一預(yù)測
    評估精度

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

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

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

關(guān)于高斯概率密度函數(shù),可以查看參考文獻(xiàn)。總之,我們要把已知的細(xì)節(jié)融入到高斯函數(shù)(屬性值,均值,標(biāo)準(zhǔn)差),并得到屬性值歸屬于某個類的似然(譯者注:即可能性)。

在calculateProbability()函數(shù)中,我們首先計算指數(shù)部分,然后計算等式的主干。這樣可以將其很好地組織成2行。    
import math
def calculateProbability(x, mean, stdev):
  exponent = math.exp(-(math.pow(x-mean,2)/(2*math.pow(stdev,2))))
  return (1 / (math.sqrt(2*math.pi) * stdev)) * exponent

使用一些簡單的數(shù)據(jù)測試如下:    
x = 71.5
mean = 73
stdev = 6.2
probability = calculateProbability(x, mean, stdev)
print('Probability of belonging to this class: {0}').format(probability)

運(yùn)行測試,你會看到如下結(jié)果:    
Probability of belonging to this class: 0.0624896575937

計算所屬類的概率

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

使用乘法合并概率,在下面的calculClassProbilities()函數(shù)中,給定一個數(shù)據(jù)樣本,它所屬每個類別的概率,可以通過將其屬性概率相乘得到。結(jié)果是一個類值到概率的映射。    
def calculateClassProbabilities(summaries, inputVector):
  probabilities = {}
  for classValue, classSummaries in summaries.iteritems():
    probabilities[classValue] = 1
    for i in range(len(classSummaries)):
      mean, stdev = classSummaries[i]
      x = inputVector[i]
      probabilities[classValue] *= calculateProbability(x, mean, stdev)
  return probabilities

測試calculateClassProbabilities()函數(shù)。    
summaries = {0:[(1, 0.5)], 1:[(20, 5.0)]}
inputVector = [1.1, '?']
probabilities = calculateClassProbabilities(summaries, inputVector)
print('Probabilities for each class: {0}').format(probabilities)

運(yùn)行測試,你會看到如下結(jié)果:    
Probabilities for each class: {0: 0.7820853879509118, 1: 6.298736258150442e-05}

單一預(yù)測

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

下面的predict()函數(shù)可以完成以上任務(wù)。    
def predict(summaries, inputVector):
  probabilities = calculateClassProbabilities(summaries, inputVector)
  bestLabel, bestProb = None, -1
  for classValue, probability in probabilities.iteritems():
    if bestLabel is None or probability > bestProb:
      bestProb = probability
      bestLabel = classValue
  return bestLabel

測試predict()函數(shù)如下:    
summaries = {'A':[(1, 0.5)], 'B':[(20, 5.0)]}
inputVector = [1.1, '?']
result = predict(summaries, inputVector)
print('Prediction: {0}').format(result)

運(yùn)行測試,你會得到如下結(jié)果:    
Prediction: A

多重預(yù)測

最后,通過對測試數(shù)據(jù)集中每個數(shù)據(jù)樣本的預(yù)測,我們可以評估模型精度。getPredictions()函數(shù)可以實(shí)現(xiàn)這個功能,并返回每個測試樣本的預(yù)測列表。    
def getPredictions(summaries, testSet):
  predictions = []
  for i in range(len(testSet)):
    result = predict(summaries, testSet[i])
    predictions.append(result)
  return predictions

測試getPredictions()函數(shù)如下。    
summaries = {'A':[(1, 0.5)], 'B':[(20, 5.0)]}
testSet = [[1.1, '?'], [19.1, '?']]
predictions = getPredictions(summaries, testSet)
print('Predictions: {0}').format(predictions)

運(yùn)行測試,你會看到如下結(jié)果:    
Predictions: ['A', 'B']

計算精度

預(yù)測值和測試數(shù)據(jù)集中的類別值進(jìn)行比較,可以計算得到一個介于0%~100%精確率作為分類的精確度。getAccuracy()函數(shù)可以計算出這個精確率。    
def getAccuracy(testSet, predictions):
  correct = 0
  for x in range(len(testSet)):
    if testSet[x][-1] == predictions[x]:
      correct += 1
  return (correct/float(len(testSet))) * 100.0

我們可以使用如下簡單的代碼來測試getAccuracy()函數(shù)。    
testSet = [[1,1,1,'a'], [2,2,2,'a'], [3,3,3,'b']]
predictions = ['a', 'a', 'a']
accuracy = getAccuracy(testSet, predictions)
print('Accuracy: {0}').format(accuracy)

運(yùn)行測試,你會得到如下結(jié)果:    
Accuracy: 66.6666666667

合并代碼

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

下面是樸素貝葉斯Python版的逐步實(shí)現(xiàn)的全部代碼。    
# Example of Naive Bayes implemented from Scratch in Python
import csv
import random
import math
 
def loadCsv(filename):
  lines = csv.reader(open(filename, "rb"))
  dataset = list(lines)
  for i in range(len(dataset)):
    dataset[i] = [float(x) for x in dataset[i]]
  return dataset
 
def splitDataset(dataset, splitRatio):
  trainSize = int(len(dataset) * splitRatio)
  trainSet = []
  copy = list(dataset)
  while len(trainSet) < trainSize:
    index = random.randrange(len(copy))
    trainSet.append(copy.pop(index))
  return [trainSet, copy]
 
def separateByClass(dataset):
  separated = {}
  for i in range(len(dataset)):
    vector = dataset[i]
    if (vector[-1] not in separated):
      separated[vector[-1]] = []
    separated[vector[-1]].append(vector)
  return separated
 
def mean(numbers):
  return sum(numbers)/float(len(numbers))
 
def stdev(numbers):
  avg = mean(numbers)
  variance = sum([pow(x-avg,2) for x in numbers])/float(len(numbers)-1)
  return math.sqrt(variance)
 
def summarize(dataset):
  summaries = [(mean(attribute), stdev(attribute)) for attribute in zip(*dataset)]
  del summaries[-1]
  return summaries
 
def summarizeByClass(dataset):
  separated = separateByClass(dataset)
  summaries = {}
  for classValue, instances in separated.iteritems():
    summaries[classValue] = summarize(instances)
  return summaries
 
def calculateProbability(x, mean, stdev):
  exponent = math.exp(-(math.pow(x-mean,2)/(2*math.pow(stdev,2))))
  return (1 / (math.sqrt(2*math.pi) * stdev)) * exponent
 
def calculateClassProbabilities(summaries, inputVector):
  probabilities = {}
  for classValue, classSummaries in summaries.iteritems():
    probabilities[classValue] = 1
    for i in range(len(classSummaries)):
      mean, stdev = classSummaries[i]
      x = inputVector[i]
      probabilities[classValue] *= calculateProbability(x, mean, stdev)
  return probabilities
 
def predict(summaries, inputVector):
  probabilities = calculateClassProbabilities(summaries, inputVector)
  bestLabel, bestProb = None, -1
  for classValue, probability in probabilities.iteritems():
    if bestLabel is None or probability > bestProb:
      bestProb = probability
      bestLabel = classValue
  return bestLabel
 
def getPredictions(summaries, testSet):
  predictions = []
  for i in range(len(testSet)):
    result = predict(summaries, testSet[i])
    predictions.append(result)
  return predictions
 
def getAccuracy(testSet, predictions):
  correct = 0
  for i in range(len(testSet)):
    if testSet[i][-1] == predictions[i]:
      correct += 1
  return (correct/float(len(testSet))) * 100.0
 
def main():
  filename = 'pima-indians-diabetes.data.csv'
  splitRatio = 0.67
  dataset = loadCsv(filename)
  trainingSet, testSet = splitDataset(dataset, splitRatio)
  print('Split {0} rows into train={1} and test={2} rows').format(len(dataset), len(trainingSet), len(testSet))
  # prepare model
  summaries = summarizeByClass(trainingSet)
  # test model
  predictions = getPredictions(summaries, testSet)
  accuracy = getAccuracy(testSet, predictions)
  print('Accuracy: {0}%').format(accuracy)
 
main()

運(yùn)行示例,得到如下輸出:    
Split 768 rows into train=514 and test=254 rows
Accuracy: 76.3779527559%

數(shù)據(jù)分析咨詢請掃描二維碼

若不方便掃碼,搜微信號:CDAshujufenxi

數(shù)據(jù)分析師資訊
更多

OK
客服在線
立即咨詢
客服在線
立即咨詢
') } function initGt() { var handler = function (captchaObj) { captchaObj.appendTo('#captcha'); captchaObj.onReady(function () { $("#wait").hide(); }).onSuccess(function(){ $('.getcheckcode').removeClass('dis'); $('.getcheckcode').trigger('click'); }); window.captchaObj = captchaObj; }; $('#captcha').show(); $.ajax({ url: "/login/gtstart?t=" + (new Date()).getTime(), // 加隨機(jī)數(shù)防止緩存 type: "get", dataType: "json", success: function (data) { $('#text').hide(); $('#wait').show(); // 調(diào)用 initGeetest 進(jìn)行初始化 // 參數(shù)1:配置參數(shù) // 參數(shù)2:回調(diào),回調(diào)的第一個參數(shù)驗(yàn)證碼對象,之后可以使用它調(diào)用相應(yīng)的接口 initGeetest({ // 以下 4 個配置參數(shù)為必須,不能缺少 gt: data.gt, challenge: data.challenge, offline: !data.success, // 表示用戶后臺檢測極驗(yàn)服務(wù)器是否宕機(jī) new_captcha: data.new_captcha, // 用于宕機(jī)時表示是新驗(yàn)證碼的宕機(jī) product: "float", // 產(chǎn)品形式,包括:float,popup width: "280px", https: true // 更多配置參數(shù)說明請參見:http://docs.geetest.com/install/client/web-front/ }, handler); } }); } function codeCutdown() { if(_wait == 0){ //倒計時完成 $(".getcheckcode").removeClass('dis').html("重新獲取"); }else{ $(".getcheckcode").addClass('dis').html("重新獲取("+_wait+"s)"); _wait--; setTimeout(function () { codeCutdown(); },1000); } } function inputValidate(ele,telInput) { var oInput = ele; var inputVal = oInput.val(); var oType = ele.attr('data-type'); var oEtag = $('#etag').val(); var oErr = oInput.closest('.form_box').next('.err_txt'); var empTxt = '請輸入'+oInput.attr('placeholder')+'!'; var errTxt = '請輸入正確的'+oInput.attr('placeholder')+'!'; var pattern; if(inputVal==""){ if(!telInput){ errFun(oErr,empTxt); } return false; }else { switch (oType){ case 'login_mobile': pattern = /^1[3456789]\d{9}$/; if(inputVal.length==11) { $.ajax({ url: '/login/checkmobile', type: "post", dataType: "json", data: { mobile: inputVal, etag: oEtag, page_ur: window.location.href, page_referer: document.referrer }, success: function (data) { } }); } break; case 'login_yzm': pattern = /^\d{6}$/; break; } if(oType=='login_mobile'){ } if(!!validateFun(pattern,inputVal)){ errFun(oErr,'') if(telInput){ $('.getcheckcode').removeClass('dis'); } }else { if(!telInput) { errFun(oErr, errTxt); }else { $('.getcheckcode').addClass('dis'); } return false; } } return true; } function errFun(obj,msg) { obj.html(msg); if(msg==''){ $('.login_submit').removeClass('dis'); }else { $('.login_submit').addClass('dis'); } } function validateFun(pat,val) { return pat.test(val); }