決策樹
決策樹里面最重要的就是節(jié)點(diǎn)和分裂條件,直接決定了一棵樹的好壞。用一個(gè)簡單的例子先說明一下:
來一段情景對話:
母親:女兒,你也不小了,還沒對象!媽很揪心啊,這不托人給你找了個(gè)對象,明兒去見個(gè)面吧!
女兒:年紀(jì)多大了?
母親:25
女兒:長的帥不帥?
母親:挺帥的!
女兒:收入高不高?有沒有上進(jìn)心?
母親:收入還行,蠻有上進(jìn)心!
???
就這樣女兒建立了一棵決策樹:

這種簡單的決策樹,處處可見。女兒一步步選擇重要特征(年齡、長相、收入等)并構(gòu)建特征分割方式(年紀(jì)大小、長相帥不帥、收入高不高),讓自己進(jìn)行最優(yōu)的決策。
-
決策樹的構(gòu)建過程
很顯然,由上面的例子可以看到構(gòu)建一個(gè)決策樹需要如下步驟:
1、收集樣本
沒有要決策的對象,一切都是扯淡。就是例子中母親托人找對象的過程。
2、選擇特征-----構(gòu)建節(jié)點(diǎn)
根據(jù)特征的重要度,來構(gòu)建子節(jié)點(diǎn),越重要的特征越靠近根節(jié)點(diǎn)。也就是女兒覺得那些條件最重要,當(dāng)最重要的條件不滿足,就沒必要繼續(xù)了。
3、特征的分裂方式-----分裂節(jié)點(diǎn)
根據(jù)特征的分裂方式,來劃分?jǐn)?shù)據(jù)集,也就是根據(jù)條件區(qū)別對待。就是年紀(jì)太大的壓根就不予考慮,年齡合適的才進(jìn)一步考察。
其實(shí)在實(shí)際構(gòu)建樹模型的時(shí)候,2和3是通過遍歷的方式同時(shí)進(jìn)行的。
上面的例子是主觀的分裂節(jié)點(diǎn),那么如何科學(xué)的構(gòu)建節(jié)點(diǎn)分裂呢?下面來說明:
我們覺得什么樣才算好,通俗來說就是通過越少的分裂,達(dá)到更好的區(qū)分度。用術(shù)語說就是當(dāng)選擇了這個(gè)條件之后,系統(tǒng)的不確定度下降最多。這個(gè)特征就是我們要重視的feature!在這里就不得不引入信息論中的一些知識(shí)了,主要是信息熵和不純度,詳情請參考我在語雀中總結(jié)的一一篇文檔。
主要是通過以下幾種算法來實(shí)現(xiàn)最優(yōu)分裂的效果:
ID3算法
系統(tǒng)的信息熵是,分別計(jì)算每個(gè)特征的條件熵
,然后得到每個(gè)條件的信息增益
。通過判斷每個(gè)特征的
的大小來決定特征的重要度。所以ID3算法是基于信息增益,信息增益大,則越適合用來分類。在具體的特征分裂的時(shí)候,每個(gè)條件的分裂是遍歷了所有的可能(離散值有多少個(gè)就有多少個(gè)可能),這是一種貪心算法。所以這個(gè)算法不支持連續(xù)特征,也是缺點(diǎn)之一。
C4.5算法
與ID3算法的思路基本相同,只是解決了ID3算法中的一些缺點(diǎn),比如將連續(xù)值離散化從而支持連續(xù)型特征,采用信息增益比來代替ID3算法的信息增益,解決了信息增益偏向分支過多的特征。也補(bǔ)充了剪枝和補(bǔ)全缺失值的操作。
CART算法
簡單來說,CART算法是不斷的生成二叉樹,能分類也能回歸,因此也叫分類回歸樹。在生成分類樹時(shí),采用的是基尼系數(shù),也叫不純度。生成回歸樹則采用的是節(jié)點(diǎn)樣本的方差
來做分裂標(biāo)準(zhǔn)。這些過程,3種算法都差不多,有區(qū)別的是CART算法如何生成二叉樹?
CART對連續(xù)型屬性的處理與C4.5差不多,也是先離散化。而對于離散型屬性,理論上有多少個(gè)離散值就應(yīng)該分裂成多少個(gè)節(jié)點(diǎn)。但CART是一棵二叉樹,每一次分裂只會(huì)產(chǎn)生兩個(gè)節(jié)點(diǎn),怎么辦呢?很簡單,只要將其中一個(gè)離散值獨(dú)立作為一個(gè)節(jié)點(diǎn),其他的離散值生成另外一個(gè)節(jié)點(diǎn)即可。這種分裂方案有多少個(gè)離散值就有多少種劃分的方法,舉一個(gè)簡單的例子:如果某離散屬性一個(gè)有三個(gè)離散值x,y,z,則該屬性的分裂方法有【x、(y,z)】,【y、(z,x)】,【z,(x,y)】,分別計(jì)算每種劃分方法的基尼值或者樣本方差確定最優(yōu)的方法。原則就是通過一個(gè)條件將樣本空間一分為二。
決策樹的評價(jià)
分類樹:
假定某個(gè)樣本空間有類,對于生成好的一棵決策樹的某葉子結(jié)點(diǎn),假定該葉結(jié)點(diǎn)含有樣本數(shù)目為
,可以分別統(tǒng)計(jì)該葉子節(jié)點(diǎn)下每個(gè)分類的頻數(shù)
。每個(gè)類別的概率
,于是這個(gè)葉子節(jié)點(diǎn)的信息熵就是
。信息熵越小,系統(tǒng)的區(qū)分度越明顯。所以最終對于一棵分類樹的評價(jià)可以用下面的公式來評判(
葉子節(jié)點(diǎn)的權(quán)重,可以更具樣本數(shù)目來決定):
對于不同的算法,并不完全都是用信息熵,也可以采用基尼系數(shù)來代替信息熵。
回歸樹:
假定某個(gè)樣本空間,對于生成好的一棵決策樹的某葉子結(jié)點(diǎn),假定該葉結(jié)點(diǎn)含有樣本數(shù)目為,計(jì)算這個(gè)葉子節(jié)點(diǎn)的方差
。所以最終對于一棵回歸樹的評價(jià)可以用下面的公式來評判(
葉子節(jié)點(diǎn)的權(quán)重,可以更具樣本數(shù)目來決定):
決策樹的剪枝
決策樹對訓(xùn)練屬于有很好的分類能力,但是對于未知的測試集未必有好的分類能力,泛化能力弱,即可能發(fā)生過擬合現(xiàn)象。為防止過擬合,我們需要進(jìn)行剪枝。三種決策樹的剪枝過程算法相同,區(qū)別是對于當(dāng)前樹的評價(jià)標(biāo)準(zhǔn)不同。
剪枝分為預(yù)剪枝和后剪枝:
預(yù)剪枝:
在樹還沒有完全分裂完成的時(shí)候,設(shè)定閾值,停止分裂,比如:
(1)每一個(gè)結(jié)點(diǎn)所包含的最小樣本數(shù)目,例如10,則該結(jié)點(diǎn)總樣本數(shù)小于10時(shí),則不再分;
(2)指定樹的高度或者深度,例如樹的最大深度為6;
(3)指定結(jié)點(diǎn)的熵小于某個(gè)值,不再劃分。
后剪枝:
在樹已經(jīng)完全分裂之后,進(jìn)行剪枝:
由完全樹開始,剪枝部分結(jié)點(diǎn)(葉子節(jié)點(diǎn),或者子節(jié)點(diǎn))得到
,再次剪枝部分結(jié)點(diǎn)得到
...,直到剩下樹根的樹(就是根節(jié)點(diǎn))
;在驗(yàn)證數(shù)據(jù)集上對這
個(gè)樹分別評價(jià),選擇損失函數(shù)最小的樹
。
C4.5采用悲觀剪枝方法(PEP)
悲觀剪枝認(rèn)為如果決策樹的精度在剪枝前后沒有影響的話,則進(jìn)行剪枝。怎樣才算是沒有影響?如果剪枝后的誤差小于剪枝前經(jīng)度的上限,則說明剪枝后的效果更佳,此時(shí)需要子樹進(jìn)行剪枝操作。
CART采用代價(jià)復(fù)雜度剪枝方法(CCP)
代價(jià)復(fù)雜度選擇節(jié)點(diǎn)表面誤差率增益值最小的非葉子節(jié)點(diǎn),刪除該非葉子節(jié)點(diǎn)的左右子節(jié)點(diǎn),若有多個(gè)非葉子節(jié)點(diǎn)的表面誤差率增益值相同小,則選擇非葉子節(jié)點(diǎn)中子節(jié)點(diǎn)數(shù)最多的非葉子節(jié)點(diǎn)進(jìn)行剪枝。
- 決策好的一棵樹,除去葉子節(jié)點(diǎn)后有
- 計(jì)算每個(gè)子節(jié)點(diǎn)剪枝后的表面誤差率增益
剪枝后的損失函數(shù)
剪枝前的損失函數(shù)
剪枝前T節(jié)點(diǎn)下面的葉子節(jié)點(diǎn)數(shù)
-
= Min(
),剪枝最小的子節(jié)點(diǎn)
。
隨機(jī)森林----一片決策樹森林
這個(gè)可以當(dāng)作是決策樹解決過擬合的一種方式。隨機(jī)的采用樣本的某些特征構(gòu)建多棵簡單的決策樹,然后預(yù)測結(jié)果是這么多棵決策樹預(yù)測結(jié)果的綜合。用于分類就多數(shù)表決,用于回歸就是取平均值。不想多說。
決策樹單獨(dú)作為一個(gè)算法的效果不是特別好,更多的是在集成算法種充當(dāng)內(nèi)核。比如xgboost、adboost之類的。
code
基于sklearn.tree模塊
分類樹:
from sklearn import datasets
from sklearn.tree import DecisionTreeClassifier
# 使用自帶的iris數(shù)據(jù)
iris = datasets.load_iris()
X = iris.data[:, [0, 2]]
y = iris.target
# 創(chuàng)建模型
'''
常用參數(shù)說明:
criterion="gini" ---- 'entropy'-->信息熵,'gini'-->基尼系數(shù)
splitter="best" ---- 'best'-->全局最優(yōu)分裂,'random'-->隨機(jī)選擇局部最優(yōu)點(diǎn)
max_depth=None ---- 設(shè)定樹深度
min_samples_split=2 ---- 內(nèi)部節(jié)點(diǎn)停止分裂的最小樣本數(shù)
min_samples_leaf=1 ---- 葉子節(jié)點(diǎn)的最小樣本數(shù),如果實(shí)際值小于它,則會(huì)和兄弟節(jié)點(diǎn)一起被剪枝
max_features=None, ---- 分裂的時(shí)候要考慮的樣本特征比例
max_leaf_nodes=None,---- 最大葉子節(jié)點(diǎn)數(shù)
'''
clf = DecisionTreeClassifier(max_depth=4)
# 訓(xùn)練模型
clf.fit(X, y)
回歸樹:
from sklearn.datasets.california_housing import fetch_california_housing
from sklearn.tree import DecisionTreeRegressor
# 使用波士頓房價(jià)數(shù)據(jù)
housing = fetch_california_housing()
X = housing.data[:, [6, 7]]
y = housing.target
'''
criterion="mse" ---- 和分類樹一樣,評價(jià)指標(biāo),'mse'是均方誤差,'mae'是絕對值誤差
'''
# 創(chuàng)建模型
dtr = tree.DecisionTreeRegressor(max_depth = 2)
# 訓(xùn)練模型
dtr.fit(x, y)
隨機(jī)森林:
from sklearn.ensemble import RandomForestClassifier
from sklearn import datasets
# 使用自帶的iris數(shù)據(jù)
iris = datasets.load_iris()
X = iris.data
y = iris.target
'''
樹的基本參數(shù)設(shè)定和分類樹差不多
n_estimators=10, ---- 建立多少棵樹
bootstrap=True, ---- 是統(tǒng)計(jì)學(xué)中的一種重采樣技術(shù),可以簡單理解成是有放回地抽樣
oob_score=False, ---- 是否使用帶外樣本進(jìn)行模型驗(yàn)證
n_jobs=1, ---- 并行job個(gè)數(shù),1:CPU有多少core,就啟動(dòng)多少job
warm_start=False, ---- 熱啟動(dòng),決定是否使用上次調(diào)用該類的結(jié)果然后增加新的。
'''
rftcl = RandomForestClassifier()
rftcl.fit(x,y)
參考總結(jié)前人的資料和自己的一些想法,僅供學(xué)習(xí)交流,不妥之處請大佬們批評指正。
參考