機器學習&深度學習基礎(機器學習基礎的算法概述及代碼)

參考:機器學習&深度學習算法及代碼實現

Python3機器學習html

傳統機器學習算法

決策樹、K鄰近算法、支持向量機、樸素貝葉斯、神經網絡、Logistic迴歸算法,聚類等。node

1、機器學習算法及代碼實現–決策樹git

決策樹學習筆記(Decision Tree)

引自:Python3《機器學習實戰》學習筆記(二):決策樹基礎篇之讓咱們從相親提及

github:https://github.com/Jack-Cherish/Machine-Learning/tree/master/Decision%20Treegithub

決策樹(decision tree)是一種基本的分類與迴歸方法。算法

決策樹算法的核心在於決策樹的構建,每次選擇讓總體數據香農熵(描述數據的混亂程度)減少最多的特徵,使用其特徵值對數據進行劃分,每次消耗一個特徵,不斷迭代分類,直到全部特徵消耗完(選擇剩下數據中出現次數最多的類別做爲這堆數據的類別),或剩下的數據全爲同一類別,沒必要繼續劃分,至此決策樹構建完成,以後咱們依照這顆決策樹對新進數據進行分類。網絡

一個相親的例子:數據結構

結點和模塊的概念:app

 一個決策樹,長方形表明判斷模塊(decision block),橢圓造成表明終止模塊(terminating block),表示已經得出結論,能夠終止運行。從判斷模塊引出的左右箭頭稱做爲分支(branch),它能夠達到另外一個判斷模塊或者終止模塊。咱們還能夠這樣理解,分類決策樹模型是一種描述對實例進行分類的樹形結構。決策樹由結點(node)和有向邊(directed edge)組成。結點有兩種類型:內部結點(internal node)和葉結點(leaf node)。內部結點表示一個特徵或屬性,葉結點表示一個類。如圖所示的決策樹,長方形和橢圓形都是結點。長方形的結點屬於內部結點,橢圓形的結點屬於葉結點,從結點引出的左右箭頭就是有向邊。而最上面的結點就是決策樹的根結點(root node)。機器學習

 使用決策樹作預測須要如下過程:函數

  • 收集數據:可使用任何方法。好比想構建一個相親系統,咱們能夠從媒婆那裏,或者經過參訪相親對象獲取數據。根據他們考慮的因素和最終的選擇結果,就能夠獲得一些供咱們利用的數據了。
  • 準備數據:收集完的數據,咱們要進行整理,將這些全部收集的信息按照必定規則整理出來,並排版,方便咱們進行後續處理。
  • 分析數據:可使用任何方法,決策樹構造完成以後,咱們能夠檢查決策樹圖形是否符合預期。
  • 訓練算法:這個過程也就是構造決策樹,一樣也能夠說是決策樹學習,就是構造一個決策樹的數據結構。
  • 測試算法:使用經驗樹計算錯誤率。當錯誤率達到了可接收範圍,這個決策樹就能夠投放使用了。
  • 使用算法:此步驟可使用適用於任何監督學習算法,而使用決策樹能夠更好地理解數據的內在含義。

 決策樹構建的準備工做

3個步驟:特徵選擇、決策樹的生成和決策樹的修剪。

1 特徵選擇

    特徵選擇在於選取對訓練數據具備分類能力的特徵。這樣能夠提升決策樹學習的效率,若是利用一個特徵進行分類的結果與隨機分類的結果沒有很大差異,則稱這個特徵是沒有分類能力的。經驗上扔掉這樣的特徵對決策樹學習的精度影響不大。一般特徵選擇的標準是信息增益(information gain)或信息增益比,爲了簡單,本文章使用信息增益做爲選擇特徵的標準。那麼,什麼是信息增益?在講解信息增益以前,讓咱們看一組實例,貸款申請樣本數據表。

ID 年齡 有工做 有本身的房子 信貸狀況 類別(是否個給貸款)
1 青年 通常
2 青年
3 青年
4 青年 通常
5 青年 通常
6 中年 通常
7 中年
8 中年
9 中年 很是好
10 中年 很是好
11 老年 很是好
12 老年
13 老年
14 老年 很是好
15 老年 通常

 

    但願經過所給的訓練數據學習一個貸款申請的決策樹,用以對將來的貸款申請進行分類,即當新的客戶提出貸款申請時,根據申請人的特徵利用決策樹決定是否批准貸款申請。

    特徵選擇就是決定用哪一個特徵來劃分特徵空間。好比,咱們經過上述數據表獲得兩個可能的決策樹,分別由兩個不一樣特徵的根結點構成。

 圖(a)所示的根結點的特徵是年齡,有3個取值,對應於不一樣的取值有不一樣的子結點。圖(b)所示的根節點的特徵是工做,有2個取值,對應於不一樣的取值有不一樣的子結點。兩個決策樹均可以今後延續下去。

問題是:究竟選擇哪一個特徵更好些?這就要求肯定選擇特徵的準則。直觀上,若是一個特徵具備更好的分類能力,或者說,按照這一特徵將訓練數據集分割成子集,使得各個子集在當前條件下有最好的分類,那麼就更應該選擇這個特徵。信息增益就可以很好地表示這一直觀的準則。

    什麼是信息增益呢?在劃分數據集以前以後信息發生的變化成爲信息增益,知道如何計算信息增益,咱們就能夠計算每一個特徵值劃分數據集得到的信息增益,得到信息增益最高的特徵就是最好的選擇。

香農熵

     如何計算信息增益。集合信息的度量方式成爲香農熵或者簡稱爲熵(entropy),

    熵定義爲信息的指望值。在信息論與機率統計中,熵是表示隨機變量不肯定性的度量。若是待分類的事務可能劃分在多個分類之中,則符號xi的信息定義爲 

其中p(xi)是選擇該分類的機率。

  經過上式,咱們能夠獲得全部類別的信息。爲了計算熵,咱們須要計算全部類別全部可能值包含的信息指望值(數學指望),經過下面的公式獲得: 

   期中n是分類的數目。熵越大,隨機變量的不肯定性就越大。

    當熵中的機率由數據估計(特別是最大似然估計)獲得時,所對應的熵稱爲經驗熵(empirical entropy)。什麼叫由數據估計?好比有10個數據,一共有兩個類別,A類和B類。其中有7個數據屬於A類,則該A類的機率即爲十分之七。其中有3個數據屬於B類,則該B類的機率即爲十分之三。淺顯的解釋就是,這機率是咱們根據數據數出來的。咱們定義貸款申請樣本數據表中的數據爲訓練數據集D,則訓練數據集D的經驗熵爲H(D),|D|表示其樣本容量,及樣本個數。設有K個類Ck,k = 1,2,3,···,K,|Ck|爲屬於類Ck的樣本個數,這經驗熵公式能夠寫爲 

根據此公式計算經驗熵H(D),分析貸款申請樣本數據表中的數據。最終分類結果只有兩類,即放貸和不放貸。根據表中的數據統計可知,在15個數據中,9個數據的結果爲放貸,6個數據的結果爲不放貸。因此數據集D的經驗熵H(D)爲: 

 通過計算可知,數據集D的經驗熵H(D)的值爲0.971。

3.1.2 編寫代碼計算經驗熵

    在編寫代碼以前,咱們先對數據集進行屬性標註。

  • 年齡:0表明青年,1表明中年,2表明老年;
  • 有工做:0表明否,1表明是;
  • 有本身的房子:0表明否,1表明是;
  • 信貸狀況:0表明通常,1表明好,2表明很是好;
  • 類別(是否給貸款):no表明否,yes表明是。

    肯定這些以後,咱們就能夠建立數據集,並計算經驗熵了,代碼編寫以下:

# -*- coding: UTF-8 -*-
from math import log """ 函數說明:建立測試數據集 Parameters: 無 Returns: dataSet - 數據集 labels - 分類屬性 Author: Jack Cui Modify: 2017-07-20
""" def createDataSet(): dataSet = [[0, 0, 0, 0, 'no'], #數據集 [0, 0, 0, 1, 'no'], [0, 1, 0, 1, 'yes'], [0, 1, 1, 0, 'yes'], [0, 0, 0, 0, 'no'], [1, 0, 0, 0, 'no'], [1, 0, 0, 1, 'no'], [1, 1, 1, 1, 'yes'], [1, 0, 1, 2, 'yes'], [1, 0, 1, 2, 'yes'], [2, 0, 1, 2, 'yes'], [2, 0, 1, 1, 'yes'], [2, 1, 0, 1, 'yes'], [2, 1, 0, 2, 'yes'], [2, 0, 0, 0, 'no']] labels = ['年齡', '有工做', '有本身的房子', '信貸狀況'] #分類屬性 return dataSet, labels #返回數據集和分類屬性 """ 函數說明:計算給定數據集的經驗熵(香農熵) Parameters: dataSet - 數據集 Returns: shannonEnt - 經驗熵(香農熵)
""" def calcShannonEnt(dataSet): numEntires = len(dataSet) #返回數據集的行數 labelCounts = {} #保存每一個標籤(Label)出現次數的字典 for featVec in dataSet: #對每組特徵向量進行統計 currentLabel = featVec[-1] #提取標籤(Label)信息 if currentLabel not in labelCounts.keys(): #若是標籤(Label)沒有放入統計次數的字典,添加進去 labelCounts[currentLabel] = 0 labelCounts[currentLabel] += 1 #Label計數 shannonEnt = 0.0 #經驗熵(香農熵) for key in labelCounts: #計算香農熵 prob = float(labelCounts[key]) / numEntires #選擇該標籤(Label)的機率 shannonEnt -= prob * log(prob, 2) #利用公式計算 return shannonEnt #返回經驗熵(香農熵) if __name__ == '__main__': dataSet, features = createDataSet() print(dataSet) print(calcShannonEnt(dataSet))

 

信息增益

    在上面,咱們已經說過,如何選擇特徵,須要看信息增益。也就是說,信息增益是相對於特徵而言的,信息增益越大,特徵對最終的分類結果影響也就越大,咱們就應該選擇對最終分類結果影響最大的那個特徵做爲咱們的分類特徵。

,信息增益是相對於特徵而言的。因此,特徵A對訓練數據集D的信息增益g(D,A),定義爲集合D的經驗熵H(D)與特徵A給定條件下D的經驗條件熵H(D|A)之差,即

 

編寫代碼計算信息增益

# -*- coding: UTF-8 -*-
from math import log """ 函數說明:計算給定數據集的經驗熵(香農熵) Parameters: dataSet - 數據集 Returns: shannonEnt - 經驗熵(香農熵) Author: Jack Cui Modify: 2017-03-29
""" def calcShannonEnt(dataSet): numEntires = len(dataSet) #返回數據集的行數 labelCounts = {} #保存每一個標籤(Label)出現次數的字典 for featVec in dataSet: #對每組特徵向量進行統計 currentLabel = featVec[-1] #提取標籤(Label)信息 if currentLabel not in labelCounts.keys(): #若是標籤(Label)沒有放入統計次數的字典,添加進去 labelCounts[currentLabel] = 0 labelCounts[currentLabel] += 1 #Label計數 shannonEnt = 0.0 #經驗熵(香農熵) for key in labelCounts: #計算香農熵 prob = float(labelCounts[key]) / numEntires #選擇該標籤(Label)的機率 shannonEnt -= prob * log(prob, 2) #利用公式計算 return shannonEnt #返回經驗熵(香農熵) """ 函數說明:建立測試數據集 Parameters: 無 Returns: dataSet - 數據集 labels - 分類屬性 Author: Jack Cui Modify: 2017-07-20
""" def createDataSet(): dataSet = [[0, 0, 0, 0, 'no'], #數據集 [0, 0, 0, 1, 'no'], [0, 1, 0, 1, 'yes'], [0, 1, 1, 0, 'yes'], [0, 0, 0, 0, 'no'], [1, 0, 0, 0, 'no'], [1, 0, 0, 1, 'no'], [1, 1, 1, 1, 'yes'], [1, 0, 1, 2, 'yes'], [1, 0, 1, 2, 'yes'], [2, 0, 1, 2, 'yes'], [2, 0, 1, 1, 'yes'], [2, 1, 0, 1, 'yes'], [2, 1, 0, 2, 'yes'], [2, 0, 0, 0, 'no']] labels = ['年齡', '有工做', '有本身的房子', '信貸狀況'] #分類屬性 return dataSet, labels #返回數據集和分類屬性 """ 函數說明:按照給定特徵劃分數據集 Parameters: dataSet - 待劃分的數據集 axis - 劃分數據集的特徵 value - 須要返回的特徵的值 Returns: 無 Author: Jack Cui Modify: 2017-03-30
""" def splitDataSet(dataSet, axis, value): retDataSet = [] #建立返回的數據集列表 for featVec in dataSet: #遍歷數據集 if featVec[axis] == value: reducedFeatVec = featVec[:axis] #去掉axis特徵 reducedFeatVec.extend(featVec[axis+1:]) #將符合條件的添加到返回的數據集 retDataSet.append(reducedFeatVec) return retDataSet #返回劃分後的數據集 """ 函數說明:選擇最優特徵 Parameters: dataSet - 數據集 Returns: bestFeature - 信息增益最大的(最優)特徵的索引值
""" def chooseBestFeatureToSplit(dataSet): numFeatures = len(dataSet[0]) - 1 #特徵數量 baseEntropy = calcShannonEnt(dataSet) #計算數據集的香農熵 bestInfoGain = 0.0 #信息增益 bestFeature = -1 #最優特徵的索引值 for i in range(numFeatures): #遍歷全部特徵 #獲取dataSet的第i個全部特徵 featList = [example[i] for example in dataSet] uniqueVals = set(featList) #建立set集合{},元素不可重複 newEntropy = 0.0 #經驗條件熵 for value in uniqueVals: #計算信息增益 subDataSet = splitDataSet(dataSet, i, value) #subDataSet劃分後的子集 prob = len(subDataSet) / float(len(dataSet)) #計算子集的機率 newEntropy += prob * calcShannonEnt(subDataSet) #根據公式計算經驗條件熵 infoGain = baseEntropy - newEntropy #信息增益 print("第%d個特徵的增益爲%.3f" % (i, infoGain)) #打印每一個特徵的信息增益 if (infoGain > bestInfoGain): #計算信息增益 bestInfoGain = infoGain #更新信息增益,找到最大的信息增益 bestFeature = i #記錄信息增益最大的特徵的索引值 return bestFeature #返回信息增益最大的特徵的索引值 if __name__ == '__main__': dataSet, features = createDataSet() print("最優特徵索引值:" + str(chooseBestFeatureToSplit(dataSet)))
相關文章
相關標籤/搜索