機器學習--決策樹之分類樹

決策樹是機器學習的常見算法,分爲分類樹和迴歸樹。當對一個樣本的分類進行預測時使用分類樹,當對樣本的某一個值進行預測時使用迴歸樹。本文是有關決策樹的第一部分,主要介紹分類樹的幾種構建方法,以及如何使用分類樹測試分類。php

目錄以下:git

一、分類樹的基本概念算法

二、採用數據集說明機器學習

三、劃分數據集的幾種方式工具

四、構造分類樹學習

五、使用分類樹測試分類測試

六、寫在後面的話優化

 

一 分類樹的基本概念網站

分類樹classification tree)簡單地說,就是根據訓練數據集構造一個相似樹形的分類決策模型,而後用這個模型來輔助決策。spa

 例以下圖是一個簡單的是否舉行某個活動的決策樹(分類樹):

             

  

 

咱們能夠經過上面的決策樹進行預測,當天氣晴朗,交通暢通時,咱們預測該活動極可能要舉辦;當天下小雨交通擁擠時,咱們預測活動極可能被取消。

這只是一個簡單的小例子,真實中的決策樹方法包括如下幾個步驟:

  (1) 收集數據:能夠使用任何方法。
(2)準備數據:樹構造算法只適用於標稱型數據,所以數值型數據必須離散化。
(3)選取劃分算法:根據數據的特色,選取合適的劃分算法
(4)構造決策樹:使用選取的劃分算法構造樹形的決策模型
(5)測試算法:使用經驗樹計算錯誤率
(6)使用算法:使用決策樹模型預測決策

二 採用數據集說明

UCI數據集 是機器學習不錯的數據集網站,本文選取其中的 Balloons 數據集,將其內容用中文表示以下。

   

該數據主要是根據幾個因素預測氣球是否會破。

三 劃分數據集的幾種方式

決策樹的幾種經典實現方式是ID3,C4.5 和 CART

其中C4.5是對ID3的改進,C4.5和ID3都是分類樹,CART 便可用做分類樹,又可用於迴歸樹,當CART用做分類時使用基尼指數做爲劃分依據,當CART用做迴歸時使用最小方差做爲劃分依據。

信息熵

熵(entropy),也即信息熵,是度量樣本集合純度的一種指標。一個數據集的熵越大,則說明該數據分類的純度越純。

D表示數據集,假設D共有m個類別,Pk 表示第k個類別佔樣本總數的比例,數據集熵的公式以下:

  

如上面給出的關於氣球的數據集,只有 「會」 和 「不會」兩種分類,「會」有7個,「不會」有9個,佔比分別是 P1 =7/16 ,  P2=9/16

按照熵的公式 可得 Ent(D) = -P1 * log2P- P2*log2P2 = 0.989

代碼實現:

 1 from math import log
 2 import operator
 3 
 4 def calc_entropy(data_set):
 5     """計算數據集的熵"""
 6     count = len(data_set)
 7     label_counts = {}
 8 
 9     # 統計數據集中每種分類的個數
10     for row in data_set:
11         label = row[-1]
12         if label not in label_counts.keys():
13             label_counts[label] = 1
14         else:
15             label_counts[label] += 1
16 
17     # 計算熵
18     entropy = 0.0
19     for key in label_counts:
20         prob = float(label_counts[key]) / count
21         entropy -= prob * log(prob, 2)
22     return entropy

信息增益法

ID3算法使用信息增益做爲劃分數據集的依據。整個數據集的熵稱做 原始熵,數據集D根據某個特徵劃分以後的熵爲條件熵,信息增益 = 原始熵 - 條件熵   。用信息增益劃分的具體作法是:計算每一類特徵V對應的信息增益,而後挑選信息增益最小的特徵進行劃分。

信息增益公式爲:

  

其中v 爲特徵a的一個分類,pv 爲 v分類佔特徵a總個數的比例Dv 根據特徵a 的v分類進行劃分以後的數據集。

代碼實現:

 1 def choose_best_feature_1(data_set):
 2     """選取信息增益最高的特徵"""
 3     feature_count = len(data_set[0]) - 1
 4     # 數據集的原始熵
 5     base_entropy = calc_entropy(data_set)
 6     # 最大的信息增益
 7     best_gain = 0.0
 8     # 信息增益最大的特徵
 9     best_feature = -1
10 
11     # 遍歷計算每一個特徵
12     for i in range(feature_count):
13         feature = [example[i] for example in data_set]
14         feature_value_set = set(feature)
15         new_entropy = 0.0
16 
17         # 計算信息增益
18         for value in feature_value_set:
19             sub_data_set = split_data_set(data_set, i, value)
20             prob = len(sub_data_set) / float(len(data_set))
21             new_entropy += prob * calc_entropy(sub_data_set)
22         gain = base_entropy - new_entropy
23 
24         # 比較得出最大的信息增益
25         if gain > best_gain:
26             best_gain = gain
27             best_feature = i
28 
29     return best_feature

 

 增益率法

 ID3所採用的信息增益劃分數據集是可能對數目較多的屬性有偏好,C4.5 算法避免了這個問題,使用「增益率」來選擇最優化分屬性。

信息增益率公式:

其中Gain_ratio(D,a) 表示 根據特徵 a 劃分以後的信息增益率, IV(a)爲 特徵a 的固有值

代碼實現:

 1 def choose_best_feature_2(data_set):
 2     """根據增益率選取劃分特徵"""
 3     feature_count = len(data_set[0]) - 1
 4     # 數據集的原始熵
 5     base_entropy = calc_entropy(data_set)
 6     # 最大的信息增益率
 7     best_gain_ratio = 0.0
 8     # 信息增益率最大的特徵
 9     best_feature = -1
10 
11     # 遍歷計算每一個特徵
12     for i in range(feature_count):
13         feature = [example[i] for example in data_set]
14         feature_value_set = set(feature)
15         new_entropy = 0.0
16         # 固有值
17         intrinsic_value = 0.0
18 
19         # 計算信息增益
20         for value in feature_value_set:
21             sub_data_set = split_data_set(data_set, i, value)
22             prob = len(sub_data_set) / float(len(data_set))
23             new_entropy += prob * calc_entropy(sub_data_set)
24             intrinsic_value -= prob * log(prob, 2)
25         gain = base_entropy - new_entropy
26         gain_ratio = gain / intrinsic_value
27 
28         # 比較得出最大的信息增益率
29         if gain_ratio > best_gain_ratio:
30             best_gain_ratio = gain_ratio
31             best_feature = i
32 
33     return best_feature

基尼指數法

當CART用作分類樹時,使用「基尼指數」來選擇劃分特徵。基尼指數是另一種表示數據集純度的指標。

基尼值:

  

基尼指數:

代碼實現:

 1 def calc_gini(data_set):
 2     """計算數據集的基尼值"""
 3     count = len(data_set)
 4     label_counts = {}
 5 
 6     # 統計數據集中每種分類的個數
 7     for row in data_set:
 8         label = row[-1]
 9         if label not in label_counts.keys():
10             label_counts[label] = 1
11         else:
12             label_counts[label] += 1
13 
14     # 計算基尼值
15     gini = 1.0
16     for key in label_counts:
17         prob = float(label_counts[key]) / count
18         gini -= prob * prob
19     return gini
20 
21 
22 def choose_best_feature_3(data_set):
23     """根據基尼指數選擇劃分特徵"""
24     feature_count = len(data_set[0]) - 1
25     # 最小基尼指數
26     min_gini_index = 0.0
27     # 基尼指數最小的特徵
28     best_feature = -1
29 
30     # 遍歷計算每一個特徵
31     for i in range(feature_count):
32         feature = [example[i] for example in data_set]
33         feature_value_set = set(feature)
34 
35         # 基尼指數
36         gini_index = 0.0
37         # 計算基尼指數
38         for value in feature_value_set:
39             sub_data_set = split_data_set(data_set, i, value)
40             prob = len(sub_data_set) / float(len(data_set))
41             gini_index += prob * calc_gini(sub_data_set)
42 
43         # 比較得出最小的基尼指數
44         if gini_index < min_gini_index or min_gini_index == 0.0:
45             min_gini_index = gini_index
46             best_feature = i
47 
48     return best_feature

四 構造分類樹

每次根據劃分算法選出最佳的劃分特徵進行劃分,而後對子數據集進行遞歸劃分,直到全部子集的純度都爲1,即構成了決策樹。

構造決策樹代碼:

 1 def create_division_tree(data_set, labels):
 2     """建立決策樹"""
 3     class_list = [example[-1] for example in data_set]
 4 
 5     # 全部分類相同時返回
 6     if class_list.count(class_list[0]) == len(class_list):
 7         return class_list[0]
 8 
 9     # 已經遍歷完全部特徵
10     if len(data_set[0]) == 1:
11         return get_top_class(class_list)
12 
13     # 選取最好的特徵
14     best_feat = choose_best_feature_1(data_set)
15     best_feat_label = labels[best_feat]
16 
17     # 劃分
18     my_tree = {best_feat_label: {}}
19     del (labels[best_feat])
20     value_set = set([example[best_feat] for example in data_set])
21     for value in value_set:
22         sub_labels = labels[:]
23         my_tree[best_feat_label][value] = create_division_tree(split_data_set(data_set, best_feat, value), sub_labels)
24     return my_tree

 

構造的決策樹存在在Python 字典類型中,不能直觀地看清決策樹層次,這裏咱們使用Matplotlib 模塊提供的繪圖工具繪製出決策樹的模型以下:

                

咱們能夠看到使用不一樣的劃分算法,構造的決策樹是不同的。

 

五 使用決策樹測試分類

經過決策樹預測測試樣本時,就是根據測試樣本的特徵屬性 從決策樹根節點開始不斷向下遍歷,直到葉子節點。

 1 def classify(division_tree, feat_labels, test_vector):
 2     """遍歷決策樹對測試數據進行分類"""
 3     first_key = list(division_tree.keys())[0]
 4     second_dict = division_tree[first_key]
 5 
 6     feat_index = feat_labels.index(first_key)
 7     test_key = test_vector[feat_index]
 8 
 9     test_value = second_dict[test_key]
10 
11     if isinstance(test_value, dict):
12         class_label = classify(test_value, feat_labels, test_vector)
13     else:
14         class_label = test_value
15     return class_label

 六 寫在後面的話

本文完整代碼見https://gitee.com/beiyan/machine_learning/tree/master/decision_tree,本文只是分類樹方法的簡單實現,關於迴歸樹的介紹,以及決策樹的剪枝算法,數值型數據離散方法等 將在後序文章中介紹。

相關文章
相關標籤/搜索