1.信息熵
熵在信息論中代表隨機變量“不確定度”的度量。一個離散型隨機變量的熵H(X)定義爲:
直覺上,信息量等於傳輸該信息所用的代價,這個也是通信中考慮最多的問題。比如說:賭馬比賽中,有4匹馬{A,B,C,D},獲勝概率分別爲{1/2,1/4,1/8,1/8}。接下來,讓我們將哪一匹馬獲勝視爲一個隨機變量X∈{A,B,C,D}。假定我們需要用盡可能少的二元問題來確定隨機變量X的取值。
例如:
問題1:A獲勝了嗎?
問題2:B獲勝了嗎?
問題3:C獲勝了嗎?
最後我們可以通過最多3個二元問題,來確定X的取值,即哪一匹馬贏得了比賽。
如果X=A,那麼需要問1次,概率爲1/2;
如果X=B,那麼需要問2次,概率爲1/4;
如果X=C,那麼需要問3次,概率爲1/8;
如果X=D,那麼同樣需要問3次,概率爲1/8;
那麼很容易計算,在這種問法之下,爲確定X取值的二元問題數量爲:
那麼我們回到信息熵的定義,會發現通過之前的信息熵公式,神奇地得到了:
在二進制計算機中,一個比特爲0或1,其實就代表了一個二元問題的回答。也就是說,在計算機中,我們給哪一匹馬奪冠這個事件進行編碼,所需要的平均碼長爲1.75個比特。
2.聯合熵和條件熵
兩個隨機變量X,Y的聯合分佈,可以形成聯合熵JointEntropy,用H(X,Y)表示。
H(X,Y) – H(Y)
(X,Y)發生所包含的信息熵,減去Y單獨發生包含的信息熵等於在Y發生的前提下,X發生的信息熵。
該式子定義爲Y發生前提下,X的熵:
條件熵H(X|Y) = H(X,Y) – H(Y)
3.信息增益
- 概念:當熵和條件熵中的概率由數據估計(特別是極大似然估計)得到時,所對應的熵和條件熵分別稱爲經驗熵和經驗條件熵。
- 信息增益表示得知特徵A的信息而使得類X的信息的不確定性減少的程度。
- 定義:特徵A對訓練數據集D的信息增益g(D,A),定義爲集合D的經驗熵H(D)與特徵A給定條件下D的經驗條件熵H(D|A)只差,即:
-g(D,A)=H(D)-H(D|A)
4.信息增益比
單純的信息增益只是個相對值,因爲這依賴於H(D)的大小,所以信息增益比更能客觀反映信息增益。特徵A對訓練數據集D的信息增益比gR(D,A)定義爲其信息增益g(D,A)與訓練數據集D關於特徵A的值的熵HA(D)之比,即
其中,,n時特徵A取值的個數。
5.決策樹學習的生成算法
建立決策樹的關鍵,即在當前狀態下選擇哪個屬性作爲分類依據。根據不同的目標函數,建立決策樹主要有以下三種算法。
ID3
C4.5
CART
6.代碼實現
package com.dengdan
import org.apache.log4j.{Level, Logger}
import org.apache.spark.mllib.tree.DecisionTree
import org.apache.spark.mllib.tree.model.DecisionTreeModel
import org.apache.spark.mllib.util.MLUtils
import org.apache.spark.{SparkConf, SparkContext}
object DecisionTreeApp extends App {
//屏蔽日誌
Logger.getLogger("org.apache.spark").setLevel(Level.ERROR)
Logger.getLogger("org.eclipse.jetty.server").setLevel(Level.OFF)
//創建SparkContext
val conf = new SparkConf().setMaster("local[4]").setAppName("DecisionTree")
val sc = new SparkContext(conf)
val path = "D:\\idea_workspace2020\\spark\\sparkMLib\\decision_tree\\src\\main\\resources\\data.txt";
//加載數據
val data = MLUtils.loadLibSVMFile(sc, path)
//將數據集切分成70%的訓練數據集和30%的測試數據集
val splits = data.randomSplit(Array(0.7, 0.3))
val (trainingData, testData) = (splits(0), splits(1))
//訓練決策樹模型
//空的categoricalFeaturesInfo表示所有特徵都是連續的。
val numClasses = 2
val categoricalFeaturesInfo = Map[Int, Int]()
val impurity = "gini"
val maxDepath = 5
val maxBins = 32
val model = DecisionTree.trainClassifier(trainingData, numClasses, categoricalFeaturesInfo, impurity, maxDepath, maxBins)
//評估模型
val labelAndPreds = testData.map { point =>
val prediction = model.predict(point.features)
(point.label, prediction)
}
//模型錯誤率
val testErr = labelAndPreds.filter(r => r._1 != r._2).count.toDouble / testData.count()
println(s"分類錯誤率=${testErr}")
println(s"訓練的決策樹模型:\n${model.toDebugString}")
val modelPath = "target/tmp/myDecisionTreeClassificationModel"
//保存決策樹模型
model.save(sc, modelPath)
//重新讀取決策樹模型
val sameModel = DecisionTreeModel.load(sc, modelPath)
sc.stop()
}