今天用了一晚上把决策树的ID3算法撸出来了。
首先推荐一发博客,说的感觉挺靠谱的...传送门
一、信息熵
高中化学里面有个概念讲的是分子的混乱程度(大概是这个...)。而信息熵就是香农借鉴了热力学的概念,将信息熵定义为“离散随机事件出现的概率”。
加入对于随机变量X={xi},每个xi的概率为pi,那么信息熵可以定义为:
二、信息增益
对于一个数据集S来说,其信息熵为Entropy(S)。对其中的一个特征T来说,这个特征中含有不同的特征值,那么在数据集S中的特征T的信息熵
其中,ti表示特征T的一个特征值的集合,集合仅含该特征和结果,H(ti)表示在ti数据集下的信息熵,P(ti)表示这个集合占T这个集合的大小。
所以信息增益IG(S|T) = Entropy(S)-Entropy(S|T)
三、决策树之ID3算法
ID3算法是一种很贪心的策略。每次找到信息增益最大的特征,以此建立一层。再用剩余的特征去建立剩下的树。
四、Python实现代码
# -*- encoding=utf-8 -*- import math from enum import Enum Outlook = Enum('Outlook', ('sunny', 'overcast', 'rain')) Temperature = Enum('Temperature', ('hot', 'mild', 'cool')) Humidity = Enum('Humidity', ('high', 'normal')) train_set = ( (Outlook.sunny, Temperature.hot, Humidity.high, False, False), (Outlook.sunny, Temperature.hot, Humidity.high, True, False), (Outlook.overcast, Temperature.hot, Humidity.high, False, True), (Outlook.rain, Temperature.mild, Humidity.high, False, True), (Outlook.rain, Temperature.cool, Humidity.normal, False, True), (Outlook.rain, Temperature.cool, Humidity.normal, True, False), (Outlook.overcast, Temperature.cool, Humidity.normal, True, True), (Outlook.sunny, Temperature.mild, Humidity.high, False, False), (Outlook.sunny, Temperature.cool, Humidity.normal, False, True), (Outlook.rain, Temperature.mild, Humidity.normal, False, True), (Outlook.sunny, Temperature.mild, Humidity.normal, True, True), (Outlook.overcast, Temperature.mild, Humidity.high, True, True), (Outlook.overcast, Temperature.hot, Humidity.normal, False, True), (Outlook.rain, Temperature.mild, Humidity.high, True, False), ) def entropy(c): ans, cas, total = 0, {}, len(c) for x in c: if x not in cas: cas[x] = 1 else: cas[x] += 1 for x in cas: tmp = cas[x] / total ans += tmp * math.log2(tmp) return -ans def cal_imformation_gain(t): ''' t: 特征集合,有两列,第一列是属性,第二列是结果 return: 在特征属性T下的条件熵 ''' # 将t分解成多个小集合 st = set() for row in t: if row[0] not in st: st.add(row[0]) mp = {x : [] for x in st} for row in t: mp[row[0]].append(row[1]) # 计算每个集合单独的信息熵 ans = 0 for key in mp: ans += len(mp[key]) / len(t) * entropy(mp[key]) return entropy([x[1] for x in t]) - ans def build_decision_tree(train_set): len_train_set = len(train_set[0]) tmp = set() for x in train_set: tmp.add(x[len_train_set-1]) if len(tmp) == 1: return "Yes" if tmp.pop() == True else "No" if len_train_set == 1: tmp = set() for x in train_set: tmp.add(x[0]) if len(tmp) == 1: return "Yes" if train_set[0][0] == True else "No" else: return [True, False] # 获取最大的信息增益 mx, inx = 0, 0 for i in range(len_train_set - 1): tmp = cal_imformation_gain([[x[i], x[len_train_set-1]] for x in train_set]) if tmp > mx: mx, inx = tmp, i # 递归构造决策树 tree = {} for x in train_set: tree[x[inx]] = {} for key in tree: new_train_set = [] for x in train_set: if x[inx] == key: tmp = [] for i in range(len_train_set): if i == inx: continue tmp.append(x[i]) new_train_set.append(tmp) tree[key] = build_decision_tree(new_train_set) return tree if __name__ == "__main__": tree = build_decision_tree(train_set) print (tree)
这篇博客写的很挫...刚入门机器学习...如有问题...还请各位dalao指出!