【机器学习基础】数学推导+纯Python实现机器学习算法4:决策树之ID3算法
?????
Python機器學習算法實現
Author:louwill
?????
???? 作為機器學習中的一大類模型,樹模型一直以來都頗受學界和業界的重視。目前無論是各大比賽各種大殺器的XGBoost、lightgbm還是像隨機森林、Adaboost等典型集成學習模型,都是以決策樹模型為基礎的。傳統的經典決策樹算法包括ID3算法、C4.5算法以及GBDT的基分類器CART算法。
???? 三大經典決策樹算法最主要的區別在于其特征選擇準則的不同。ID3算法選擇特征的依據是信息增益、C4.5是信息增益比,而CART則是Gini指數。作為一種基礎的分類和回歸方法,決策樹可以有如下兩種理解方式。一種是我們可以將決策樹看作是一組if-then規則的集合,另一種則是給定特征條件下類的條件概率分布。關于這兩種理解方式,讀者朋友可深入閱讀相關教材進行理解,筆者這里補詳細展開。
???? 根據上述兩種理解方式,我們既可以將決策樹的本質視作從訓練數據集中歸納出一組分類規則,也可以將其看作是根據訓練數據集估計條件概率模型。整個決策樹的學習過程就是一個遞歸地選擇最優特征,并根據該特征對數據集進行劃分,使得各個樣本都得到一個最好的分類的過程。
ID3算法理論
???? 所以這里的關鍵在于如何選擇最優特征對數據集進行劃分。答案就是前面提到的信息增益、信息增益比和Gini指數。因為本篇針對的是ID3算法,所以這里筆者僅對信息增益進行詳細的表述。
???? 在講信息增益之前,這里我們必須先介紹下熵的概念。在信息論里面,熵是一種表示隨機變量不確定性的度量方式。若離散隨機變量X的概率分布為:
???? 則隨機變量X的熵定義為:
???? 同理,對于連續型隨機變量Y,其熵可定義為:
???? 當給定隨機變量X的條件下隨機變量Y的熵可定義為條件熵H(Y|X):
? ? ?所謂信息增益就是數據在得到特征X的信息時使得類Y的信息不確定性減少的程度。假設數據集D的信息熵為H(D),給定特征A之后的條件熵為H(D|A),則特征A對于數據集的信息增益g(D,A)可表示為:
g(D,A) = H(D) - H(D|A)
???? 信息增益越大,則該特征對數據集確定性貢獻越大,表示該特征對數據有較強的分類能力。信息增益的計算示例如下:
1).計算目標特征的信息熵。
2).計算加入某個特征之后的條件熵。
3).計算信息增益。
???? 以上就是ID3算法的核心理論部分,至于如何基于ID3構造決策樹,我們在代碼實例中來看。
ID3算法實現
???? 先讀入示例數據集:
import numpy as np import pandas as pd from math import logdf = pd.read_csv('./example_data.csv') df定義熵的計算函數:
計算示例:
然后我們需要定義根據特征和特征值進行數據劃分的方法:
def split_dataframe(data, col): ? ?'''function: split pandas dataframe to sub-df based on data and column.input: dataframe, column name.output: a dict of splited dataframe.'''# unique value of columnunique_values = data[col].unique() ? ?# empty dict of dataframeresult_dict = {elem : pd.DataFrame for elem in unique_values} ? ?# split dataframe based on column valuefor key in result_dict.keys():result_dict[key] = data[:][data[col] == key] ? ?return result_dict根據temp和其三個特征值的數據集劃分示例:
???? 然后就是根據熵計算公式和數據集劃分方法計算信息增益來選擇最佳特征的過程:
def choose_best_col(df, label): ? ?'''funtion: choose the best column based on infomation gain.input: datafram, labeloutput: max infomation gain, best column,splited dataframe dict based on best column.'''# Calculating label's entropyentropy_D = entropy(df[label].tolist()) ? ?# columns list except labelcols = [col for col in df.columns if col not in [label]] ? ?# initialize the max infomation gain, best column and best splited dictmax_value, best_col = -999, Nonemax_splited = None# split data based on different columnfor col in cols:splited_set = split_dataframe(df, col)entropy_DA = 0for subset_col, subset in splited_set.items(): ? ? ? ? ? ?# calculating splited dataframe label's entropyentropy_Di = entropy(subset[label].tolist()) ? ? ? ? ? ?# calculating entropy of current featureentropy_DA += len(subset)/len(df) * entropy_Di ? ? ? ?# calculating infomation gain of current featureinfo_gain = entropy_D - entropy_DA ? ? ? ?if info_gain > max_value:max_value, best_col = info_gain, colmax_splited = splited_set ? ?return max_value, best_col, max_splited???? 最先選到的信息增益最大的特征是outlook:
???? 決策樹基本要素定義好后,我們即可根據以上函數來定義一個ID3算法類,在類里面定義構造ID3決策樹的方法:
class ID3Tree: ? ?# define a Node classclass Node: ? ? ? ?def __init__(self, name):self.name = nameself.connections = {} ? ?def connect(self, label, node):self.connections[label] = node ? ?def __init__(self, data, label):self.columns = data.columnsself.data = dataself.label = labelself.root = self.Node("Root") ? ?# print tree methoddef print_tree(self, node, tabs):print(tabs + node.name) ? ? ? ?for connection, child_node in node.connections.items():print(tabs + "\t" + "(" + connection + ")")self.print_tree(child_node, tabs + "\t\t") ? ?def construct_tree(self):self.construct(self.root, "", self.data, self.columns) ? ?# construct treedef construct(self, parent_node, parent_connection_label, input_data, columns):max_value, best_col, max_splited = choose_best_col(input_data[columns], self.label) ? ? ? ?if not best_col:node = self.Node(input_data[self.label].iloc[0])parent_node.connect(parent_connection_label, node) ? ? ? ? ? ?returnnode = self.Node(best_col)parent_node.connect(parent_connection_label, node)new_columns = [col for col in columns if col != best_col] ? ? ? ?# Recursively constructing decision treesfor splited_value, splited_data in max_splited.items():self.construct(node, splited_value, splited_data, new_columns)???? 根據上述代碼和示例數據集構造一個ID3決策樹:
???? 以上便是ID3算法的手寫過程。sklearn中tree模塊為我們提供了決策樹的實現方式,參考代碼如下:
from sklearn.datasets import load_iris from sklearn import tree import graphviziris = load_iris() # criterion選擇entropy,這里表示選擇ID3算法 clf = tree.DecisionTreeClassifier(criterion='entropy', splitter='best') clf = clf.fit(iris.data, iris.target)dot_data = tree.export_graphviz(clf, out_file=None,feature_names=iris.feature_names,class_names=iris.target_names,filled=True,rounded=True,special_characters=True) graph = graphviz.Source(dot_data) graph???? 以上便是本篇的全部內容,完整版代碼和數據請移步本人github:
https://github.com/luwill/machine-learning-code-writing
參考資料:
李航 統計學習方法
https://github.com/heolin123/id3/blob/master
往期精彩:
數學推導+純Python實現機器學習算法3:k近鄰
數學推導+純Python實現機器學習算法2:邏輯回歸
數學推導+純Python實現機器學習算法1:線性回歸
往期精彩回顧適合初學者入門人工智能的路線及資料下載機器學習及深度學習筆記等資料打印機器學習在線手冊深度學習筆記專輯《統計學習方法》的代碼復現專輯 AI基礎下載機器學習的數學基礎專輯獲取一折本站知識星球優惠券,復制鏈接直接打開:https://t.zsxq.com/yFQV7am本站qq群1003271085。加入微信群請掃碼進群:總結
以上是生活随笔為你收集整理的【机器学习基础】数学推导+纯Python实现机器学习算法4:决策树之ID3算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【机器学习基础】数学推导+纯Python
- 下一篇: 【机器学习基础】数学推导+纯Python