1. 程式人生 > >決策樹的一般思路分析(機器學習實戰)

決策樹的一般思路分析(機器學習實戰)

'''決策樹:
在構造決策樹時最重要的是確定劃分資料時,哪個特徵起決定性作用
為了確定起決定性作用的特徵,必須先計算資訊的增益,獲得資訊增益
最高的特徵就是最好的選擇


集合資訊的度量方式稱為熵————資訊的期望
資訊的定義:若待分類事物存在多個劃分,則符號xi的資訊定義為
l(xi)=log2 (p(xi)), 其中p(xi)是選擇該類的概率
熵是資訊的期望:H= -∑ p(xi)*log2 (p(xi)),從1到n求和 n為分類的數目'''




from math import log
from numpy import *


def calculate_entropy(data_set):  #計算熵
    num_entries=len(data_set)
    laber_counst={}
    for feature_vector in data_set:
        current_laber=feature_vector[-1]
        if current_laber not in laber_counts.key():
            laber_counts[current_laber]=0
        laber_counts[currnt_laber]=1
    entrop=0.0
    for key in laber_counts:
        prob=float(laber_counts[key])/num_entries
        entrop-=prob*log(prob,2)
    return entrop


# 劃分資料集
#split_dataset的輸入引數(資料集,劃分資料的特徵,滿足劃分的特徵的值)
#輸出時 元資料集上減去(列數減少—除去了特徵的那一列,元素減少—挑出是滿足value的那些元素)滿足劃分特徵後的剩餘集
def split_dataset(dataset, axis, value):
    ret_dataset=[]
    for feauret_vector in dateset:
        if feature_vector[axis]==vlaue:
            reduce_feature_vector=feature_vector[:axis]
            reduce_feature_vector.exdend(feature_vector[axis+1:])
            ret_dataset.append(reduce_feature_vector)
    return ret_dataset


#選擇最好的資料劃分方式
#返回的是最好的劃分特徵,依據每個特徵的熵(資訊的增益)計算出
def choose_best_feature_to_split(dataset):
    num_feature=len(dataset[0])-1  #dataset的最後一列是標籤
    base_entropy=calculat_entrop(dataset)
    best_info_gain, best_feature=0.0, -1
    for i in range(num_feature):
        feature_list=[example[i] for example in dataset]
        unique_vals=set(feature_list)
        new_entropy=0.0
        for value in unique_vals:
            subdataset=split_dataset(dataset,i,value)  #待劃分資料集,劃分特徵,返回的特徵值
            prob=len(subdataset)/float(len(dataset))
            new_entropy+=prob*calculate_entropy(subdataset)
            info_gain=base_entropy-new_entropy
            if infogain>dest_info_gain:
                best_info_gain=info_gain
                best_feature=i
    return best_feature


def majority_cnt(class_list):  #返回的是頻數最高的類別的名稱
    class_count={}
    for vote in class_list:
        if vote not in calss_count.key():
            class_count[vote]=0
        else:
            class_count[vote]=1
    sorted_calss_count=sorted(class_count.items(),key=operator.itemgetter(1),reverse=True)
    return sorted_class_count[0][0]


def creat_tree(dataset,laber):  #構造決策樹,採用的是字典資料結構
    class_list=[example[-1] for example in dataset]
    if class_list.count(class_list[0])==len(class_list):
        return class_list[0]
    if len(dataset)==1:
        return majority_cunt(class_list)
    best_feature=choose_best_feature_to_split(dataset)
    best_feature_laber=laber[best_feature]
    my_tree={best_feature_laber:{}}
    del(laber[best_feature])
    feature_value=[example[best_feature] for example in dataset]
    unique_values=set(feature_value)
    for vlaue in unique_values:
        sublabers=laber[:]
        my_tree[best_feature_laber][value]=craet_tree(split_dataset(dataset,best_feature,value),sublabers)
    return my_tree