機器學習之決策樹——學習總結

決策樹學習總結

機器學習的應用越來越廣泛,特別是在數據分析領域。本文是我學習決策樹算法的一些總結。

機器學習簡介

機器學習 (Machine Learning) 是近 20 多年興起的一門多領域交叉學科,涉及概率論、統計學、逼近論、凸分析、算法複雜度理論等多門學科。簡而言之,機器學習是通過學習老知識(訓練樣本),得出自己的認知(模型),去預測未知的結果。

  • 學習方式
    • 監督式學習
      • 從給定的訓練數據集中學習出一個函數,當新的數據到來時,可以根據此函數預測結果。訓練數據集中的目標由人標註的。常見的算法有迴歸分析和統計分類
    • 非監督式學習
      • 與監督式學習相比,訓練集沒有人爲標註的結果,常見的算法有聚類
    • 半監督式學習
      • 訓練集部分被標識,部分沒有被標識。常見的算法有SVM
    • 強化學習
      • 輸入數據作爲模型的反饋,模型對此作出調整。常見的算法有時間差學習
  • 機器學習算法分類
    • 決策樹算法
      • 根據數據屬性,採用樹狀結構建立決策模型。常用來解決分類和迴歸問題。
      • 常見算法:CART(Classification And Regression Tree),ID3,C4.5,隨機森林等
    • 迴歸算法
      • 對連續值預測,如邏輯迴歸LR等
    • 分類算法
      • 對離散值預測,事前已經知道分類,如k-近鄰算法
    • 聚類算法
      • 對離散值預測,事前對分類未知,如k-means算法
    • 神經網絡
      • 模擬生物神經網絡,可以用來解決分類和迴歸問題
      • 感知器神經網絡(Perceptron Neural Network) ,反向傳遞(Back Propagation)和深度學習(DL)
    • 集成算法
      • 集成幾種學習模型進行學習,將最終預測結果進行彙總
      • Boosting、Bagging、AdaBoost、隨機森林 (Random Forest) 等

決策樹算法

  • 初識決策樹
    決策樹算法是藉助於樹的分支結構實現分類。以相親約會決策爲例,下圖是建立好的決策樹模型,數據的屬性有4個:年齡、長相、收入、是否公務員,根據此模型,可以得到最終是見或者不見。
    這裏寫圖片描述
    這樣,我們對決策樹有個初步認識:

    • 葉子節點:存放決策結果
    • 非葉子節點:特徵屬性,及其對應輸出,按照輸出選擇分支
    • 決策過程:從根節點出發,根據數據的各個屬性,計算結果,選擇對應的輸出分支,直到到達葉子節點,得到結果
  • 構建決策樹
    通過上述例子,構建過程的關鍵步驟是選擇分裂屬性,即年齡、長相、收入、公務員這4個屬性的選擇先後次序。分裂屬性是在某個節點處按照某一特徵屬性的不同劃分構造不同的分支,其目標是讓各個分裂子集儘可能的“純”,即每個子集儘量都屬於同一分類項。分裂屬性分3種情況:

    • 屬性是離散值且不要求生成二叉樹
      • 屬性的每個值作爲一個分支
    • 屬性是離散值且要求生成二叉樹
      • 按照“屬於”和“不屬於”分成2個分支
    • 屬性是連續值
      • 確定一個分裂點split_point,按照>split_point和<=split_point生成2個分支

    注意,決策樹使用自頂向下遞歸分治法,並採用不回溯的貪心策略分裂屬性的選擇算法很多,這裏介紹3種常用的算法:信息增益(Information gain)、增益比率(gain ratio)、基尼指數(Gini index)

  • 信息增益(Information Gain)
    基於香濃的信息論,信息熵表示不確定度,均勻分佈時,不確定度最大,此時熵就最大。當選擇某個特徵對數據集進行分類時,數據集分類後的信息熵會比分類前的小,其差值即爲信息增益。信息增益可以衡量某個特徵對分類結果的影響大小,越大越好。
    • 典型算法:ID3
    • 數據集D中,有m個類別,\( p_i \)表示D中屬於類別i的概率,此數據集的信息熵定義爲:
      Info(D)=_i=1mp_ilog_2(p_i)
    • 以屬性R作爲分裂屬性,R有k個不同的取值,將數據D劃分成k組,按R分裂後的數據集的信息熵爲:
      Info_R(D)=_j=1k|D_j||D|×Info(D_j)
    • 信息增益,即爲劃分前後,信息熵之差:
      Gain(R)=Info(D)InfoR(D)
    • 在每層分裂時,選擇使得Gain(R)最大的屬性作爲分裂屬性
    • 缺點:此公式偏向數據量多的屬性,如果樣本分佈不均,則會導致過擬合。假如上述例子中包括人名屬性,每個人名均不同,顯然以此屬性作爲劃分,信息增益最高,但是,很明顯,以此屬性作爲劃分毫無意義
  • 信息增益比率(Gain Ratio)
    針對上述方法問題,此方法引入分裂信息
    SplitInfo_R(D)=_j=1k|D_j|D×log_2(|D_j|D))

    • 典型算法:C4.5
    • 信息增益比率定義爲:
      GainRatio(R)=Gain(R)SplitInfo_R(D)
    • 缺點:\( SplitInfo_R(D) \)可能取值爲0,此時無意義;當期趨於0時,GainRatio也不可信,改進措施是在分母加一個平滑,這裏加所有分裂信息的平均值\( GainRatio(R)=\frac{Gain(R)}{\overline{SplitInfo(D)}+SplitInfo_R(D)} \)
  • 基尼指數(Gini index)
    另外一種數據不純度的度量方法,定義爲:
    Gini(D)=1_i=1mp_i2

    其中,m爲數據集D中類別的個數,\( p_i \)表示D中屬於類別i的概率,如果所有記錄都屬於同一個類中,則P1=1,Gini(D)=0。
    • 典型算法:CART
    • 以屬性R作爲分裂屬性,R有k個不同的取值,將數據D劃分成k組,按R分裂後的數據集的基尼指數爲:
      Gini_R(D)=_i=1k|D_i||D|Gini(D_i)
    • 計算劃分前後基尼指數之差
      Gini(R)=Gini(D)Gini_R(D)
      計算Gini(R)增量最大的屬性作爲最佳分裂屬性。

spark中實現

具體代碼參考spark源碼包下的org.apache.spark.examples.mllib.DecisionTreeClassificationExampleDecisionTree.trainClassifier的實現步驟,核心代碼在RandomForest.run()方法

  • 根據輸入數據,構建RDD[LabeledPoint],保存label和features
  • 根據數據,構建metaData,包括feature個數、樣本數據條數、分類個數等
    • val metadata =
      DecisionTreeMetadata.buildMetadata(retaggedInput, strategy, numTrees, featureSubsetStrategy)
  • 計算每個feature的可能劃分點split1、split2。。。split(n-1)劃分成n個bin
    • val splits = findSplits(retaggedInput, metadata, seed)
    • 連續值:取樣數據,根據不同值個數和步長進行劃分
    • 離散:
      • unorder:特徵種類爲binsNum(分類個數不大,且爲多分類)
      • order:迴歸、二分類、多分類且數量很大,都使用二分類
  • 根據feature的split,計算每條數據在每個feature下所在的bin,生成新的RDD[TreePoint(Label, featuresBin[])]
    • val treeInput = TreePoint.convertToTreeRDD(retaggedInput, splits, metadata)
  • bagging取樣(示例中,不需要取樣,因爲只生成一個tree)
    • val baggedInput = BaggedPoint
      .convertToBaggedRDD(treeInput, strategy.subsamplingRate, numTrees, withReplacement, seed)
      .persist(StorageLevel.MEMORY_AND_DISK)
  • 新建樹根root,放到queue中,循環直到隊列爲空
    • 選擇多個訓練樹節點,同時進行訓練,根據指定的maxMemoryUsage進行個數計算
      • val (nodesForGroup, treeToNodeToIndexInfo) =
        RandomForest.selectNodesToSplit(nodeQueue, maxMemoryUsage, metadata, rng)
    • 按照Gini係數,找到當前樹節點中,最佳的feature分裂點和最佳bin分割點
      • RandomForest.findBestSplits(baggedInput, metadata, topNodes, nodesForGroup,
        treeToNodeToIndexInfo, splits, nodeQueue, timer, nodeIdCache)
      • 遍歷數據,mapPartition,每個樹節點LearnNode維護一個DTStatsAggregator(存放,每個feature的每個bin的數據個數)
      • 進行DTStatsAggregator的聚合merge
      • 按照Gini係數,找到最佳的feature下的最佳split

參數設置

可以通過設置一些參數,調整算法或調優,詳細參考spark官網介紹

  • 算法設置
    • algo:決策樹類型,分類或迴歸,Classification or Regression
    • numClasses: 分類問題設置分類個數
    • categoricalFeaturesInfo:指定哪些feature是離散值,並指定離散值的個數
  • 停止條件設置
    • maxDepth:樹最大深度
    • minInstancesPerNode:每個樹節點最小的訓練數據個數,如果小於此值,則不進行分裂
    • minInfoGain:最小信息增益,決定當前樹節點是否進行分裂
  • 調優參數
    • maxBins:用於連續特徵值的分散化,最多劃分類個數
    • maxMemoryInMB:增大,可以提高同時訓練的樹節點的個數,從而減少訓練時間,但是,每次訓練會增大數據的傳輸量
    • subsamplingRate:訓練森林時使用,每次採樣的比例
    • impurity:純度度量函數,必須和算法algo相匹配

參考文檔

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章