數據挖掘算法和實踐(二):決策樹(iris鳶尾花數據集)

決策樹是直觀運用概率分析的樹形分類器,是很常用的分類方法,屬於監管學習,決策樹分類過程是從根節點開始,根據特徵屬性值選擇輸出分支,直到到達葉子節點,將葉子節點存放的類別作爲決策結果。

比如說買瓜的時候,根據瓜的某些特徵屬性直觀判斷瓜的好壞,下圖依次根據紋理清晰度、根蒂、色澤、觸感4個進行分類,生活中我們會將某個最重要或最明顯的分類屬性放在第一位,然後是次重要屬性,這很符合我們平常的判斷思維,這就是決策樹!

當然,在特徵屬性非常大的時候,就出現了首選哪個特徵屬性進行分類?如何剪枝?分類的層次是多少?....系列問題,這些就是決策樹構建的核心問題,而且不可能再通過生活直覺判,這時候就要運用數學思維。根據上面問題的不同解決方案,決策樹又分爲了ID3(熵增益)、C4.5(熵增益率)、CART幾種同類算法。

熵增益(ID3)

通信層面,信息熵衡量信息的不確定性,信息熵越大表明信息越不準確,可以用信息熵的減少值來衡量信息的價值。在決策樹模型中把信息確定性叫做熵增益,有了熵增益後,我們就可以根據熵增益來判斷特徵值的重要程度,從而選取最重要的特徵作爲第一次切分,再根據相同的方法用其他特徵進行切分,直到得到得到每個劃分的葉子節點。

信息熵的定義是:

以某個特徵屬性值切分後子集熵的和稱爲條件A下的熵,也叫做條件熵,可以如下表示:

分類前的信息熵減去條件熵,得到熵增益:

比如說有以下數據集(相親結果表lol..):

6條數據中相中(4個)與不想中(2個),暫且不關係如何進行分類,我們首先計算這個分類結果的信息熵:

其次,我們計算“富”屬性的條件信息熵,6條數據中“富”與否各半,其中3個“富”都被分類到“相中”,3個“不富”都被分到“不想中”:

兩者之差就是我們想要得到的熵增益:

計算各個特徵屬性的熵增益後,比較哪個熵增益最大,就選擇該屬性做第一分類特徵。

熵增益率(C4.5)

按照熵增益最大準則的ID3算法,遇到全部都是非重複值(類似ID)屬性容易造成過擬合,因爲如果根據ID這個屬性進行劃分發現此時的熵增益是最大的:

信息增益率定義爲:

其中info就是該特徵屬性中,屬性值的信息熵:

按照上面的例子計算,“富”的增益率爲:

剪枝處理

當訓練數據量大、特徵數量較多時構建的決策樹過於龐大時,可能對訓練集依賴過多,也就是對訓練數據過度擬合。從訓練數據集上看,擬合效果很好,但對於測試數據集或者新的實例來說,並不一定能夠準確預測出其結果。因此,對於決策樹的構建還需要最後一步--決策樹的修剪,主要分爲2種:預剪枝(Pre-Pruning)和後剪枝(Post-Pruning),這裏先不講。

鳶尾花(iris)分類模型

 Iris 鳶尾花數據集是一個經典數據集,在統計學習和機器學習領域都經常被用作示例。數據集內包含 3 類共 150 條記錄,每類各 50 個數據,每條記錄都有 4 項特徵:花萼長度、花萼寬度、花瓣長度、花瓣寬度,可以通過這4個特徵預測鳶尾花卉屬於(iris-setosa, iris-versicolour, iris-virginica)中的哪一品種,數據集地址:https://github.com/yezonggang/iris

首先我們數據探索,看看數據分佈和特性,seaborn是一個面向對象的數據可視化探索工具,通常會觀察單獨特徵屬性的分佈情況和多個屬性之間的相關性等,seaborn包數據分佈探索的使用方法可以參考:https://blog.csdn.net/qq_40195360/article/details/86605860

import pandas as pd
from pandas import DataFrame
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns
from sklearn.tree import DecisionTreeClassifier
from sklearn import metrics 

baseUrl="C:\\Users\\71781\\Desktop\\2020\\ML-20200422\\iris\\"
iris_df=pd.read_csv(baseUrl+"iris.csv")
iris_df.head()

iris_df.describe()

 數據分佈探索:

# pandas 自帶的散點圖
iris_df.plot(kind="scatter", x="Sepal.Length", y="Sepal.Width")

# seaborn 的聯合分佈圖
sns.jointplot(x="Sepal.Length", y="Sepal.Width", data=iris_df, height=5)

# 上面的兩個散點圖並不能顯示每一個點所屬的類別
# 所以,接下來用 seaborn 的 FacetGrid 函數按照Species花的種類來在散點圖上標上不同的顏色,hue英文是色彩的意思。
sns.FacetGrid(iris_df, hue="Species", height=5).map(plt.scatter, "Sepal.Length", "Sepal.Width").add_legend()

# 通過箱線圖來查看單個特徵的分佈
# 對 Numerical Variable,可以用 Box Plot 來直觀地查看不同花類型的分佈。
sns.boxplot(x="Species", y="Sepal.Length", data=iris_df)

# 下面的操作,將每一個Species所屬的點加到對應的位置,加上散點圖,
# 振動值jitter=True 使各個散點分開,要不然會是一條直線
# 注意此處要將座標圖用ax先保存起來,這樣第二次纔會在原來的基礎上加上散點圖
ax = sns.boxplot(x="Species", y="Sepal.Length", data=iris_df)
ax = sns.stripplot(x="Species", y="Sepal.Length", data=iris_df, jitter=True, edgecolor="gray")

# violinplot 小提琴圖,查看密度分佈,結合了前面的兩個圖,並且進行了簡化
# 數據越稠密越寬,越稀疏越窄
sns.violinplot(x="Species", y="Sepal.Length", data=iris_df, height=6)

# sns.kdeplot == kernel density 核密度圖(單個變量)
sns.FacetGrid(iris_df, hue="Species", height=6).map(sns.kdeplot, "Sepal.Length").add_legend()

# pairplot 任意兩個變量間的關係
sns.pairplot(iris_df, hue="Species", height=3)

train_df=test_df=iris_df.sample(frac=0.8,replace=False, random_state=None)
train_X=train_df.drop(['Species'],axis=1)
train_Y=train_df['Species']
# 由於麼有提供建模數據集,所以我們隨機從樣本集中選擇40%的數據集
# replace=False 無放回的抽取
# random-state 數據不能重複
test_df=iris_df.sample(frac=0.9,replace=False, random_state=None)
test_df.head()

test_X=test_df.drop(['Species'],axis=1)
test_Y=test_df['Species']

model=DecisionTreeClassifier()
model.fit(train_X, train_Y)
prediction = model.predict(test_X)
print('The accuracy of the Decision Tree is: {0}'.format(metrics.accuracy_score(prediction,test_Y)))

模型構建比較簡單,關鍵是模型的調參,分類決策樹總共有12個參數可以自己調整,這麼多參數一個個記起來太麻煩,我們可以把這些參數分成幾個類別:

1)分類策略:有兩個參數 ‘entropy’(熵) 和 ‘gini’(基尼係數)可選,默認爲gini。

2)max_depth(樹的最大深度):默認爲None,此時決策樹在建立子樹的時候不會限制子樹的深度。也可以設置具體的整數,一般來說,數據少或者特徵少的時候可以不管這個值。如果模型樣本量多,特徵也多的情況下,推薦限制這個最大深度,具體的取值取決於數據的分佈。常用的可以取值10-100之間。

3)min_samples_split(分割內部節點所需的最小樣本數):意思就是隻要在某個結點裏有k個以上的樣本,這個節點才需要繼續劃分,這個參數的默認值爲2,也就是說只要有2個以上的樣本被劃分在一個節點,如果這兩個樣本還可以細分,這個節點就會繼續細分

4)min_samples_leaf(葉子節點上的最小樣本數):當你劃分給某個葉子節點的樣本少於設定的個數時,這個葉子節點會被剪枝,這樣可以去除一些明顯異常的噪聲數據。默認爲1,也就是說只有有兩個樣本類別不一樣,就會繼續劃分。如果是int,那麼將min_samples_leaf視爲最小數量。如果爲float,則min_samples_leaf爲分數,ceil(min _ samples _ leaf * n _ samples)爲每個節點的最小樣本數。

詳細的需要參考sklearn的官方文檔;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章