文章大綱
介紹
決策樹
如何構建決策樹
樹木構建演算法
分類問題中裂縫的其他質量標準
決策樹如何與數字特徵一起工作
關鍵樹引數
類
DecisionTreeClassifier
在Scikit學習迴歸問題中的決策樹
3.最近鄰法
真實應用中最近鄰方法
類
KNeighborsClassifier
在Scikit學習
4.選擇模型引數和交叉驗證
5.應用例項和複雜案例
客戶流失預測任務中的決策樹和最近鄰法
決策樹的複雜案例
MNIST手寫數字識別任務中的決策樹和k-NN
最近鄰法的複雜案例
6.決策樹的優缺點和最近鄰法
7.作業#3
8.有用的資源
以下材料最好用Jupyter notebook 閱讀,如果您克隆course repository,可以使用Jupyter在本地複製。
1.簡介
在我們深入研究本週文章的材料之前,讓我們先談談我們要解決的問題型別以及它在激動人心的機器學習領域的地位。T. Mitchell的書“
在各種問題設定中,
根據其特徵將例項分類到其中一個類別;
迴歸 - 基於例項的其他特徵預測數值目標特徵;
聚類 - 根據這些例項的特徵識別例項的分組,以便組內的成員彼此更相似,而不是其他組中的成員;
異常檢測 - 搜尋與樣本的其餘部分或某些例項組“非常不同”的例項;
等等。
“深度學習”中的“機器學習基礎”一章提供了很好的概述(Ian Goodfellow,Yoshua Bengio,Aaron Courville,2016)。
經驗
例
分類和迴歸是監督學習問題。例如,作為信貸機構,我們可能希望根據客戶累積的資料預測貸款違約。在這裡,經驗
最後,機器學習定義中使用的第三個術語是演算法效能評估
讓我們來看看兩個監督的學習問題:分類和迴歸。
2.決策樹
我們從最受歡迎的分類和迴歸方法之一決策樹開始介紹。決策樹用於日常生活決策,而不僅僅用於機器學習。流程圖實際上是決策樹的視覺化表示。例如,高等經濟學院釋出資訊圖表,使員工的生活更輕鬆。以下是在Institution入口網站上釋出論文的一小段說明。
在機器學習方面,人們可以將其視為一種簡單的分類器,根據內容(書籍,小冊子,論文),期刊型別,原始出版物型別(科學期刊,會議記錄)等確定適當的出版形式(書籍,文章,書籍章節,預印本,出版物)。
決策樹通常是專家經驗的概括,是分享特定過程知識的一種手段。例如,在引入可擴充套件機器學習演算法之前,銀行業的信用評分任務由專家解決。授予貸款的決定是基於一些直觀(或經驗)衍生的規則,可以表示為決策樹。
在我們的下一個案例中,我們以“年齡”,“房屋所有權”,“收入”和“教育”為由解決了二元分類問題(批准/拒絕貸款)。
作為機器學習演算法的決策樹與上面所示的圖基本相同; 我們合併類似“特徵a的值小於x和特徵
正如我們稍後將看到的,許多其他模型雖然更準確,但沒有這個屬性,可以被視為更多的“黑盒子”方法,在這種方法中,更難以解釋輸入資料如何轉換為輸出。由於這種“可理解性”和人類決策的相似性(您可以輕鬆地向您的老闆解釋您的模型),決策樹已經獲得了極大的普及。C4.5,是分類方法的代表,甚至位列10個最佳的資料探勘演算法列表(“十大演算法在資料探勘”,知識和資訊系統,2008 PDF)。
如何構建決策樹
早些時候,我們看到放貸款的決定是根據年齡,資產,收入和其他變數做出的。但首先要看哪個變數?讓我們討論一個簡單的例子,其中所有變數都是二進位制的。
回想一下“20個問題”的遊戲,這在引入決策樹時經常被引用。你可能已經玩過這個遊戲 - 一個人想到一個名人,而另一個人試圖通過只問“是”或“否”問題來猜測。猜測者首先會問什麼問題?當然,他們會問那個最多縮小剩餘選項數量的人。詢問“這是安吉麗娜朱莉嗎?”,如果是否定的迴應,將除了一個名人之外的所有人留在可能的範圍內。相比之下,問“名人是女人嗎?”會將可能性減少到大約一半。也就是說,“性別”功能將名人資料集分離得比“安吉麗娜朱莉”,“西班牙語”或“熱愛足球”等其他功能更好。這種推理對應於基於熵的資訊增益概念。
熵
Shannon的熵是針對具有N種可能狀態的系統定義的,如下所示:
其中
玩具示例
為了說明熵如何幫助我們確定構建決策樹的好特徵,讓我們來看一個玩具示例。我們將根據其位置預測球的顏色。
來源(俄文)
有9個藍色球和11個黃色球。如果我們隨機抽出一個球,那麼它將是藍色,概率為p1 = 9/20,黃色概率為p2 = 11/20,這給了我們一個熵S0 = -9/20 log2(9/20) - 11 / 20 log2(11/20)≈1。這個值本身可能不會告訴我們太多,但讓我們看看如果我們將球分成兩組,值如何變化:位置小於或等於12且大於12。
來源(俄文)
左組有13個球,8個藍色和5個黃色。該組的熵是S1 = -5 / 13log2(5/13) - 8/13 log2(8/13)≈0.96。右側組有7個球,1個藍色和6個黃色。右組的熵是S2 = -1 / 7log2(1/7) - 6/7 log2(6/7)≈0.6。正如您所看到的,兩組中的熵都有所下降,右側組則更多。由於熵實際上是系統中的混沌程度(或不確定性),因此熵的減少稱為資訊增益。形式上,基於變數
其中
事實證明,通過在“座標小於或等於12”上分裂將球分成兩組,這給了我們一個更有序的系統。讓我們繼續將它們分成小組,直到每組中的球都是相同的顏色。
對於正確的組,我們可以很容易地看到我們只需要使用“座標小於或等於18”的額外分割槽。但是,對於左派,我們還需要三個。注意,所有球是相同顏色的組的熵等於0(log2(1)= 0)。
我們已成功構建了一個決策樹,可根據其位置預測球的顏色。如果我們新增任何球,這個決策樹可能不會很好,因為它完全適合訓練集(最初的20個球)。如果我們想在這種情況下做得好,那麼具有較少“問題”或分裂的樹將更準確,即使它不完全適合訓練集。我們稍後會討論過度擬合的問題。
決策樹構建演算法
我們可以確保前一個例子中構建的樹是最優的:只需要5個“問題”(以變數
決策樹構造的流行演算法(如ID3或C4.5)的核心在於資訊增益的貪婪最大化原則:在每一步,演算法選擇在分裂時提供最大資訊增益的變數。然後遞迴地重複該過程,直到熵為零(或者一些小的值來解釋過度擬合)。不同的演算法使用不同的啟發法來“提前停止”或“切斷”以避免構造過度擬合的樹。
分類問題中裂縫的其他質量標準
我們討論了熵如何允許我們在樹中形式化分割槽。但這只是一種啟發式方法; 還有其他方式。
基尼係數不確定性(基尼雜質)
最大化此標準可以解釋為同一子樹中同一類物件的數量最大化(不要與Gini索引混淆)。
錯誤分類錯誤
在實踐中,幾乎從不使用錯誤分類錯誤,並且基尼係數不確定性和資訊增益的工作方式類似。
對於二進位制分類,熵和基尼不確定性採用以下形式:
其中(
如果我們根據引數
例
讓我們考慮將決策樹擬合到一些合成資料中。我們將從兩個類生成樣本,包括正態分佈但具有不同的均值。
# first classnp.random.seed(17)train_data = np.random.normal(size=(100, 2))train_labels = np.zeros(100)# adding second classtrain_data = np.r_[train_data, np.random.normal(size=(100, 2), loc=2)]train_labels = np.r_[train_labels, np.ones(100)]view raw複製程式碼
讓我們繪製資料。非正式地,在這種情況下的分類問題是建立一些將兩個類別分開的“好”邊界(紅點與黃色)。這種情況下的機器學習歸結為選擇一個良好的分離邊界。直線太簡單,而每個紅點的一些複雜曲線蜿蜒過於複雜,會導致我們在新樣本上出錯。直觀地,一些平滑的邊界,或者至少是直線或超平面,可以很好地用於新資料。
plt.rcParams['figure.figsize'] = (10,8)plt.scatter(train_data[:, 0], train_data[:, 1], c=train_labels, s=100, cmap='autumn', edgecolors='black', linewidth=1.5);plt.plot(range(-2,5), range(4,-3,-1));複製程式碼
讓我們嘗試通過訓練Sklearn
決策樹來分離這兩個類。我們將使用max_depth
限制樹深度的引數。讓我們視覺化的產生分離邊界。
from sklearn.tree import DecisionTreeClassifier# Let’s write an auxiliary function that will return grid for further visualization.def get_grid(data): x_min, x_max = data[:, 0].min() - 1, data[:, 0].max() + 1 y_min, y_max = data[:, 1].min() - 1, data[:, 1].max() + 1 return np.meshgrid(np.arange(x_min, x_max, 0.01), np.arange(y_min, y_max, 0.01))clf_tree = DecisionTreeClassifier(criterion='entropy', max_depth=3, random_state=17)# training the treeclf_tree.fit(train_data, train_labels)# some code to depict separating surfacexx, yy = get_grid(train_data)predicted = clf_tree.predict(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape)plt.pcolormesh(xx, yy, predicted, cmap='autumn')plt.scatter(train_data[:, 0], train_data[:, 1], c=train_labels, s=100, cmap='autumn', edgecolors='black', linewidth=1.5);複製程式碼
樹本身看起來如何?我們看到樹將“空間”切割成8個矩形,即樹有8個葉子。在每個矩形內,樹將根據其中物件的多數標籤進行預測。
# use .dot format to visualize a treefrom ipywidgets import Imagefrom io import StringIOimport pydotplus #pip install pydotplusfrom sklearn.tree import export_graphvizdot_data = StringIO()export_graphviz(clf_tree, feature_names=['x1', 'x2'], out_file=dot_data, filled=True)graph = pydotplus.graph_from_dot_data(dot_data.getvalue()) Image(value=graph.create_png())view raw複製程式碼
我們怎樣才能“讀”這樣一棵樹?
最初,有200個樣本(例項),每個類100個。初始狀態的熵是最大的,S = 1。然後,通過將
決策樹如何與數字特徵一起工作
假設我們有一個數字特徵“Age”,它有很多獨特的值。決策樹將通過檢查諸如“Age <17”,“Age <22.87”等二進位制屬性來尋找最佳(根據一些資訊增益標準)。但如果年齡範圍很大怎麼辦?或者,如果另一個量化變數“薪水”也可以在很多方面“削減”呢?在樹構造期間,在每個步驟中將有太多二進位制屬性可供選擇。為解決此問題,通常使用啟發式方法來限制我們比較定量變數的閾值數。
讓我們考慮一個例子。假設我們有以下資料集:
data = pd.DataFrame({'Age': [17,64,18,20,38,49,55,25,29,31,33], 'Loan Default': [1,0,1,0,1,0,0,1,1,0,1]})# Let's sort it by age in ascending order.data.sort_values('Age')複製程式碼
age_tree = DecisionTreeClassifier(random_state=17)age_tree.fit(data['Age'].values.reshape(-1, 1), data['Loan Default'].values)dot_data = StringIO()export_graphviz(age_tree, feature_names=['Age'], out_file=dot_data, filled=True)graph = pydotplus.graph_from_dot_data(dot_data.getvalue())Image(value=graph.create_png())複製程式碼
我們看到樹使用以下5個值來評估年齡:43.5,19,22.5,30和32年。如果你仔細觀察,這些正是目標類從1到0或0到1的年齡之間的平均值。為了進一步說明,43.5是38和49年的平均值; 一名38歲的客戶未能退還貸款,而這位49歲的客戶卻沒有。樹查詢目標類將其值切換為“切割”定量變數的閾值的值。
鑑於這些資訊,為什麼你認為考慮像“年齡<17.5”這樣的功能是沒有意義的?
讓我們通過新增“薪水”變數(每年數千美元)來考慮一個更復雜的例子。
data2 = pd.DataFrame({'Age': [17,64,18,20,38,49,55,25,29,31,33], 'Salary': [25,80,22,36,37,59,74,70,33,102,88], 'Loan Default': [1,0,1,0,1,0,0,1,1,0,1]})data2.sort_values('Age')複製程式碼
如果按年齡排序,目標類(“貸款預設值”)將切換(從1到0或反之亦然)5次。如果我們按工資排序,它會切換7次。樹現在如何選擇功能?讓我們來看看。
age_sal_tree = DecisionTreeClassifier(random_state=17)age_sal_tree.fit(data2[['Age', 'Salary']].values, data2['Loan Default'].values)dot_data = StringIO()export_graphviz(age_sal_tree, feature_names=['Age', 'Salary'], out_file=dot_data, filled=True)graph = pydotplus.graph_from_dot_data(dot_data.getvalue())Image(value=graph.create_png())複製程式碼
我們看到樹由工資和年齡劃分。此外,特徵比較的閾值分別為43.5和22.5歲,每年95k和30.5k。再次,我們看到95是88到102之間的平均值; 工資88k的個人證明是“壞”,而102k的個人是“好”。同樣適用於30.5k。也就是說,只搜尋了幾個按年齡和工資進行比較的值。樹為什麼選擇這些功能?因為他們給出了更好的分割槽(根據基尼的不確定性)。
結論:在決策樹中處理數字特徵的最簡單的啟發式方法是按升序對其值進行排序,並僅檢查目標變數值發生變化的閾值。
此外,當資料集中存在大量數字特徵時,每個特徵具有許多唯一值,僅選擇上述閾值的前N個,即僅使用提供最大增益的前N個。該過程是構建深度為1的樹,計算熵(或基尼不確定性),並選擇最佳閾值進行比較。
為了說明,如果我們按“工資≤34.5”分割,則左子組的熵為0(所有客戶端均為“壞”),右側子組的熵為0.954(3“壞”和5“良好) “,你可以自己檢查,因為它將成為任務的一部分)。資訊增益大約為0.3。如果我們用“Salary≤95”分割,則左子組的熵為0.97(6“bad”和4“good”),右邊的熵為0(一組只包含一個物件)。資訊增益約為0.11。如果我們以這種方式計算每個分割槽的資訊增益,我們可以在構建大樹之前選擇用於比較每個數字特徵的閾值(使用所有特徵)。
更多數字特徵離散化的例子可以在這樣或這樣的帖子中找到。關於該主題的最著名的科學論文之一是“關於在決策樹生成中處理連續值屬性”(UM Fayyad.KB Irani,“Machine Learning”,1992)。
關鍵樹引數
從技術上講,您可以構建一個決策樹,直到每個葉子只有一個例項,但這在構建單個樹時實際上並不常見,因為它將
有兩種例外情況,樹木被構建到最大深度:
隨機森林(一組樹)平均構建到最大深度的單個樹的響應(稍後我們將討論為什麼要這樣做)
- 修剪樹木。在這種方法中,樹首先被構造成最大深度。然後,從下到上,通過比較具有和不具有該分割槽的樹的質量來移除樹的一些節點(使用交叉驗證進行比較,更多關於此在下面)。
下圖是在過度裝配樹中構建的分隔邊框的示例。
處理決策樹中過度擬合的最常見方法如下:
人工限制葉子的深度或最小數量的樣本:樹的構造在某一點停止;
修剪樹。
Scikit-learn中的類DecisionTreeClassifier
sklearn.tree.DecisionTreeClassifier
該類的主要引數是:
max_depth
- 樹的最大深度;max_features
- 用於搜尋最佳分割槽的最大功能數量(這對於大量功能來說是必需的,因為搜尋所有功能的分割槽是“昂貴的” );min_samples_leaf
- 葉子中的最小樣本數量。此引數可防止建立樹,其中任何葉只有少數成員。
樹的引數需要根據輸入資料進行設定,通常通過
後續持續更新...
點選英文原文連結
更多文章歡迎訪問: http://www.apexyun.com
公眾號:銀河系1號
聯絡郵箱:public@space-explore.com
(未經同意,請勿轉載)