Python 數(shù)據(jù)科學(xué)手冊 5.8 決策樹和隨機(jī)森林

5.8 決策樹和隨機(jī)森林

原文:In-Depth: Decision Trees and Random Forests

譯者:飛龍

協(xié)議:CC BY-NC-SA 4.0

譯文沒有得到原作者授權(quán)纸型,不保證與原文的意思嚴(yán)格一致俏竞。

之前玻驻,我們深入研究了簡單的生成分類器(見樸素貝葉斯分類)和強(qiáng)大的辨別分類器(參見支持向量機(jī))冬殃。 這里我們來看看另一個(gè)強(qiáng)大的算法的動(dòng)機(jī) - 一種稱為隨機(jī)森林的非參數(shù)算法蒜田。 隨機(jī)森林是組合方法的一個(gè)例子赦政,這意味著它依賴于更簡單估計(jì)器的整體聚合結(jié)果官疲。 這種組合方法的結(jié)果令人驚訝搂漠,總和可以大于部分:即迂卢,多個(gè)估器中的多數(shù)表決最終可能比執(zhí)行表決的任何個(gè)體的估計(jì)更好! 我們將在以下部分中看到這個(gè)例子桐汤。 我們從標(biāo)準(zhǔn)導(dǎo)入開始:

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns; sns.set()

隨機(jī)森林是一個(gè)例子而克,建立在決策樹上的組合學(xué)習(xí)器。 因此怔毛,我們將首先討論決策樹本身员萍。

決策樹是分類或標(biāo)注對象的非常直觀的方法:您只需要詢問一系列問題,它們?yōu)榕宄诸惗O(shè)計(jì)拣度。 例如碎绎,如果您想建立一個(gè)決策樹,來分類您在遠(yuǎn)足時(shí)遇到的動(dòng)物抗果,則可以構(gòu)建如下所示的樹:

二元分割使其非常有效:在一個(gè)結(jié)構(gòu)良好的樹中筋帖,每個(gè)問題都會將選項(xiàng)數(shù)量減少一半,即使在大量分類中也很快縮小選項(xiàng)冤馏。 當(dāng)然日麸,這個(gè)技巧是決定在每個(gè)步驟中要問哪些問題。 在決策樹的機(jī)器學(xué)習(xí)實(shí)現(xiàn)中宿接,問題通常采用數(shù)據(jù)中軸對齊分割的形式:即赘淮,樹中的每個(gè)節(jié)點(diǎn)使用其中一個(gè)特征中的分割值將數(shù)據(jù)分成兩組。 現(xiàn)在來看一個(gè)例子睦霎。

創(chuàng)建決策樹

考慮以下二維數(shù)據(jù),它擁有四個(gè)標(biāo)簽之一:

from sklearn.datasets import make_blobs

X, y = make_blobs(n_samples=300, centers=4,
                  random_state=0, cluster_std=1.0)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='rainbow');

根據(jù)這些數(shù)據(jù)建立的一個(gè)簡單的決策樹走诞,將根據(jù)一些定量標(biāo)準(zhǔn)副女,沿著一個(gè)或另一個(gè)軸線迭代地分割數(shù)據(jù),并且在每個(gè)級別蚣旱,根據(jù)其中的多數(shù)表決來分配新區(qū)域的標(biāo)簽碑幅。 該圖顯示了該數(shù)據(jù)的決策樹分類器的前四個(gè)級別的可視化:

請注意戴陡,在第一次拆分之后,上部分支中的每個(gè)點(diǎn)保持不變沟涨,因此無需進(jìn)一步細(xì)分此分支恤批。 除了包含所有一種顏色的節(jié)點(diǎn),在每個(gè)級別裹赴,每個(gè)區(qū)域再次沿著兩個(gè)特征之一分裂喜庞。

將決策樹擬合到我們的數(shù)據(jù)的這個(gè)過程,可以在 Scikit-Learn 中使用DecisionTreeClassifier估計(jì)器來完成:

from sklearn.tree import DecisionTreeClassifier
tree = DecisionTreeClassifier().fit(X, y)

讓我們寫一個(gè)簡單的輔助函數(shù)棋返,幫助我們展示分類器的輸出:

def visualize_classifier(model, X, y, ax=None, cmap='rainbow'):
    ax = ax or plt.gca()
    
    # Plot the training points
    ax.scatter(X[:, 0], X[:, 1], c=y, s=30, cmap=cmap,
               clim=(y.min(), y.max()), zorder=3)
    ax.axis('tight')
    ax.axis('off')
    xlim = ax.get_xlim()
    ylim = ax.get_ylim()
    
    # fit the estimator
    model.fit(X, y)
    xx, yy = np.meshgrid(np.linspace(*xlim, num=200),
                         np.linspace(*ylim, num=200))
    Z = model.predict(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape)

    # Create a color plot with the results
    n_classes = len(np.unique(y))
    contours = ax.contourf(xx, yy, Z, alpha=0.3,
                           levels=np.arange(n_classes + 1) - 0.5,
                           cmap=cmap, clim=(y.min(), y.max()),
                           zorder=1)

    ax.set(xlim=xlim, ylim=ylim)

現(xiàn)在我們可以檢測延都,決策樹看起來是什么樣子:

visualize_classifier(DecisionTreeClassifier(), X, y)

如果您現(xiàn)在正在運(yùn)行這個(gè)筆記,您可以使用“在線附錄”中包含的幫助腳本睛竣,來啟動(dòng)決策樹構(gòu)建過程的交互式可視化:

# helpers_05_08 is found in the online appendix
import helpers_05_08
helpers_05_08.plot_tree_interactive(X, y);

請注意晰房,隨著深度的增加,我們傾向于獲得非常奇怪的分類區(qū)域; 例如射沟,在第五層殊者,黃色和藍(lán)色區(qū)域之間有一個(gè)高而瘦的紫色區(qū)域。 很明顯验夯,這不是真實(shí)的猖吴,固有的數(shù)據(jù)分布結(jié)果,更多的是數(shù)據(jù)的特定采樣或噪聲屬性的結(jié)果簿姨。 也就是說距误,這個(gè)決策樹,即使只有五個(gè)層次的深度扁位,顯然對我們的數(shù)據(jù)過擬合了准潭。

決策樹和過擬合

這種過度擬合是決策樹的一般屬性:在樹中很容易就走得太深,從而擬合特定數(shù)據(jù)的細(xì)節(jié)域仇,而不是抽取它們分布的整體屬性刑然。 查看這種過擬合的另一種方法是,查看在不同數(shù)據(jù)子集上訓(xùn)練的模型 - 例如暇务,在這個(gè)圖中泼掠,我們訓(xùn)練兩種不同的樹,每種都是原始數(shù)據(jù)的一半:

很明顯垦细,在一些地方择镇,兩棵樹產(chǎn)生一致的結(jié)果(例如在四個(gè)角落),而在其他地方括改,這兩棵樹給出非常不同的分類(例如腻豌,在任何兩個(gè)簇之間的區(qū)域中)。 關(guān)鍵觀察是,分類不太確定的地方吝梅,會發(fā)生不一致虱疏,因此通過使用這兩種樹的信息,我們可能會得到更好的結(jié)果苏携!

如果您正在運(yùn)行這個(gè)筆記做瞪,以下功能允許您交互顯示樹的擬合,在數(shù)據(jù)的隨機(jī)子集上訓(xùn)練:

# helpers_05_08 is found in the online appendix
import helpers_05_08
helpers_05_08.randomized_tree_interactive(X, y)

正如使用來自兩棵樹的信息右冻,改善了我們的結(jié)果装蓬,我們可能希望使用來自許多樹的信息,進(jìn)一步改善我們的結(jié)果国旷。

估計(jì)器的組合:隨機(jī)森林

這個(gè)概念 - 多個(gè)過擬合估計(jì)器可以組合矛物,來減少這種過擬合的影響 - 是一種稱為裝袋的組合方法。 這個(gè)方法使用了一組并行估計(jì)器跪但,每個(gè)都對數(shù)據(jù)過擬合履羞,并對結(jié)果進(jìn)行平均以找到更好的分類。 隨機(jī)決策樹的一個(gè)組合被稱為隨機(jī)森林屡久。

這種類型的裝袋分類忆首,可以使用 Scikit-Learn 的BaggingClassifier元估計(jì)器手動(dòng)進(jìn)行,如下所示:

from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import BaggingClassifier

tree = DecisionTreeClassifier()
bag = BaggingClassifier(tree, n_estimators=100, max_samples=0.8,
                        random_state=1)

bag.fit(X, y)
visualize_classifier(bag, X, y)

在這個(gè)例子中被环,我們將每個(gè)估計(jì)器擬合訓(xùn)練點(diǎn)的 80% 隨機(jī)子集進(jìn)行來隨機(jī)化數(shù)據(jù)糙及。 在實(shí)踐中,通過在選擇分割的方式中添加一些隨機(jī)性筛欢,來更有效地隨機(jī)化決策樹:這樣浸锨,所有數(shù)據(jù)每次都有助于擬合,但是擬合的結(jié)果仍然具有所需的隨機(jī)性版姑。 例如柱搜,當(dāng)確定要分割的特征時(shí),隨機(jī)化樹可以從前幾個(gè)特征中選擇剥险。 您可以在 Scikit-Learn 文檔中閱讀這些隨機(jī)策略的更多技術(shù)細(xì)節(jié)和參考聪蘸。

在 Scikit-Learn 中,隨機(jī)決策樹的優(yōu)化組合在RandomForestClassifier估計(jì)器中實(shí)現(xiàn)表制,它自動(dòng)地處理所有的隨機(jī)化健爬。 所有你需要做的是選擇一些估計(jì)器,它將很快(如果需要?jiǎng)t并行)擬合樹的組合:

from sklearn.ensemble import RandomForestClassifier

model = RandomForestClassifier(n_estimators=100, random_state=0)
visualize_classifier(model, X, y);

我們看到么介,通過對超過 100 個(gè)隨機(jī)擾動(dòng)的模型取平均娜遵,我們最終得到一個(gè)整體模型,更接近我們關(guān)于如何分割參數(shù)空間的直覺壤短。

隨機(jī)森林回歸

在上一節(jié)中魔熏,我們在分類范圍內(nèi)考慮了隨機(jī)森林衷咽。 隨機(jī)森林也可以用于回歸(即連續(xù)而不是分類變量)鸽扁。 用于此的估計(jì)器是RandomForestRegressor蒜绽,并且語法與我們之前看到的非常相似。

考慮以下數(shù)據(jù)桶现,由快速和慢速振蕩的組合產(chǎn)生:

rng = np.random.RandomState(42)
x = 10 * rng.rand(200)

def model(x, sigma=0.3):
    fast_oscillation = np.sin(5 * x)
    slow_oscillation = np.sin(0.5 * x)
    noise = sigma * rng.randn(len(x))

    return slow_oscillation + fast_oscillation + noise

y = model(x)
plt.errorbar(x, y, 0.3, fmt='o');

使用隨機(jī)森林回歸器躲雅,我們可以找到最佳擬合曲線,

這里的真實(shí)模型以灰色平滑曲線中顯示骡和,隨機(jī)森林模型由紅色鋸齒曲線顯示相赁。 可以看出,非參數(shù)隨機(jī)森林模型足夠靈活慰于,可以擬合多周期數(shù)據(jù)钮科,而不需要指定多周期模型!

示例:隨機(jī)森林?jǐn)?shù)字分類

早些時(shí)候我們快速瀏覽了手寫數(shù)字?jǐn)?shù)據(jù)(參見 Scikit-Learn 介紹)婆赠。 讓我們再次使用它绵脯,來看看如何在這個(gè)上下文中使用隨機(jī)森林分類器。

from sklearn.datasets import load_digits
digits = load_digits()
digits.keys()
# dict_keys(['target', 'data', 'target_names', 'DESCR', 'images'])

為了提醒我們休里,我們正在觀察什么蛆挫,我們展示前幾個(gè)數(shù)據(jù)點(diǎn)。

# set up the figure
fig = plt.figure(figsize=(6, 6))  # figure size in inches
fig.subplots_adjust(left=0, right=1, bottom=0, top=1, hspace=0.05, wspace=0.05)

# plot the digits: each image is 8x8 pixels
for i in range(64):
    ax = fig.add_subplot(8, 8, i + 1, xticks=[], yticks=[])
    ax.imshow(digits.images[i], cmap=plt.cm.binary, interpolation='nearest')
    
    # label the image with the target value
    ax.text(0, 7, str(digits.target[i]))

我們可以快速使用隨機(jī)森林對這些數(shù)字分類妙黍,像這樣:

from sklearn.cross_validation import train_test_split

Xtrain, Xtest, ytrain, ytest = train_test_split(digits.data, digits.target,
                                                random_state=0)
model = RandomForestClassifier(n_estimators=1000)
model.fit(Xtrain, ytrain)
ypred = model.predict(Xtest)

我們可以看一看分類器的分類報(bào)告:

from sklearn import metrics
print(metrics.classification_report(ypred, ytest))
             precision    recall  f1-score   support

          0       1.00      0.97      0.99        38
          1       1.00      0.98      0.99        44
          2       0.95      1.00      0.98        42
          3       0.98      0.96      0.97        46
          4       0.97      1.00      0.99        37
          5       0.98      0.96      0.97        49
          6       1.00      1.00      1.00        52
          7       1.00      0.96      0.98        50
          8       0.94      0.98      0.96        46
          9       0.96      0.98      0.97        46

avg / total       0.98      0.98      0.98       450

為了更好的度量悴侵,繪制混淆矩陣:

from sklearn.metrics import confusion_matrix
mat = confusion_matrix(ytest, ypred)
sns.heatmap(mat.T, square=True, annot=True, fmt='d', cbar=False)
plt.xlabel('true label')
plt.ylabel('predicted label');

我們發(fā)現(xiàn),簡單無調(diào)整的隨機(jī)森林拭嫁,產(chǎn)生了數(shù)據(jù)的非常準(zhǔn)確的分類可免。

隨機(jī)森林總結(jié)

本節(jié)簡要介紹了組合估計(jì)器的概念,特別是隨機(jī)森林 - 隨機(jī)決策樹的整體做粤。 隨機(jī)森林是一個(gè)強(qiáng)大的方法浇借,具有幾個(gè)優(yōu)點(diǎn):

  • 訓(xùn)練和預(yù)測都非常快驮宴,因?yàn)榈讓記Q策樹簡單逮刨。 此外,兩個(gè)任務(wù)都可以直接并行化堵泽,因?yàn)楦鱾€(gè)樹是完全獨(dú)立的實(shí)體修己。
  • 多個(gè)樹提供了概率分類:估計(jì)器之間的多數(shù)表決提供了概率估計(jì)(在 Scikit-Learn 中使用predict_proba()方法來訪問)。
  • 非參數(shù)模型是非常靈活的迎罗,因此可以在其他估計(jì)器擬合不足的任務(wù)上表現(xiàn)良好睬愤。

隨機(jī)森林的主要缺點(diǎn)是結(jié)果不容易解釋:即如果要對分類模型的含義作出總結(jié),隨機(jī)森林可能不是最佳選擇纹安。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末尤辱,一起剝皮案震驚了整個(gè)濱河市砂豌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌光督,老刑警劉巖阳距,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異结借,居然都是意外死亡筐摘,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進(jìn)店門船老,熙熙樓的掌柜王于貴愁眉苦臉地迎上來咖熟,“玉大人,你說我怎么就攤上這事柳畔♀晒埽” “怎么了?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵薪韩,是天一觀的道長确沸。 經(jīng)常有香客問我,道長躬存,這世上最難降的妖魔是什么张惹? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮岭洲,結(jié)果婚禮上宛逗,老公的妹妹穿的比我還像新娘。我一直安慰自己盾剩,他們只是感情好雷激,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著告私,像睡著了一般屎暇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上驻粟,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天根悼,我揣著相機(jī)與錄音,去河邊找鬼蜀撑。 笑死挤巡,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的酷麦。 我是一名探鬼主播矿卑,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼沃饶!你這毒婦竟也來了母廷?” 一聲冷哼從身側(cè)響起轻黑,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎琴昆,沒想到半個(gè)月后氓鄙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡椎咧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年玖详,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片勤讽。...
    茶點(diǎn)故事閱讀 39,953評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖拗踢,靈堂內(nèi)的尸體忽然破棺而出脚牍,到底是詐尸還是另有隱情,我是刑警寧澤巢墅,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布诸狭,位于F島的核電站,受9級特大地震影響君纫,放射性物質(zhì)發(fā)生泄漏驯遇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一蓄髓、第九天 我趴在偏房一處隱蔽的房頂上張望叉庐。 院中可真熱鬧,春花似錦会喝、人聲如沸陡叠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽枉阵。三九已至,卻和暖如春预茄,著一層夾襖步出監(jiān)牢的瞬間兴溜,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工耻陕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拙徽,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓淮蜈,卻偏偏與公主長得像斋攀,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子梧田,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內(nèi)容