zoukankan      html  css  js  c++  java
  • 机器学习-决策树 ID3算法

    今天用了一晚上把决策树的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指出!


  • 相关阅读:
    通信编程:WSAEventSelect 模型通信
    VMware 安装 Red Hat 6 虚拟机
    通信编程:Select 模型通信
    Android:隐式 Intent 调用标准 Action
    Android:显式 Intent
    Linux(CentOS)用户修改密码有效期
    linux 系统中断信息
    qt udp 聊天
    docker更改镜像存储位置
    通过dockerfile构建singularity镜像
  • 原文地址:https://www.cnblogs.com/wiklvrain/p/8179323.html
Copyright © 2011-2022 走看看