机器学习值决策树算法(上)-ID3实现
2016-04-25 11:47
141 查看
决策树算法简介
决策树算法特点及应用
信息概念介绍
生成决策树
总结
参考
决策树算法是监督学习算法的其中一种,用于根据已有数据训练数据针对未知数据进行分类的一种算法,该算法的核心理念是通过不断的判断,递归,判断,来计算数据的分类。
举例说明
概念可能不大好理解,举例就会清楚直观了,相信大多数人都有过生病的体验,找医生看病的时候,医生就会让你伸出舌头看看,摸摸你的额头等,这就是根据症状来判断是什么病,如果你患了感冒,医生会首先问你是否有腹泻,然后让你伸出舌头,看看你的舌苔,之后会问你是否头痛,发冷,根据这一系列的数据,医生便可以推断你的感冒类型,对症下药。
计算复杂度不高
输出结果便于理解
适用于分类,适合标称数值
应用:
之前在微信里,朋友发给我一个链接,点进去是一个机器人来根据你的问题答案猜测是哪位明星的问题,当时觉得非常的神奇,在学习了决策树之后,才明白了其中的道理,当然这也是我猜测,首先,这个网站会收藏很多的问题作为特征值,并收集很多明星的信息,把该信息录入本地数据集,例如上面的发热,腹泻等特征,然后抽取问题1,根据答案来选择下一个提出的问题(如果选择不知道则忽略该特征),直到指定特征被用完(答完10个问题),根据最后结果集中出现次数最多作为答案。
信息是反映一个事件出现概率的单位(曾经在大学学的通信原理已经忘得一干二净),首先列出公式,下面再分析。
- 信息 = log2(概率)
上述的发热症状,无论哪种感冒都存在发热现象,那么这个信息其实对我们分析病情是无关紧要,所以他的信息是0,也许大家不能理解这个公式的计算方式,但我们并不准确需要这个值,我们只需要信息与概率的对应关系,无论是log3或者log4,对数据分类不造成影响,如果出现概率不为1的话,概率越大,信息量也就越小。
信息熵概念:
信息熵是反映一组数据的不确定性,就好比掷骰子,扔12面的骰子比6面的骰子结果不确定性就会高很多,信息熵就是用来反映这个不确定性的单位,计算公式如下:
- 信息熵 = sum(-概率1*log2(概率1), -概率2*log2(概率2),……)
从公式可能不太容易看出什么,不如我们用数值代入,6面骰子,有6种情况,每一种都是1/6,那么结果就是log2(6)=0.778,12面骰子就是log2(12)=1.079,不确定性高了之后,信息熵也得到了上涨,下面列出计算信息熵的python代码。
信息增益:
信息增益是通过其他条件来降低这一组数据的不确定性,就好比朋友养了一条小狗,朋友告诉你这条狗是萨摩耶,吉娃娃,京巴,二哈,阿拉斯加和中华田园犬中的一种,让你去猜,如果直接猜,猜中的几率是1/6,但是如果知道这条狗的毛发颜色,那么猜中的几率就会提高,白色是萨摩耶,黄色是京巴,吉娃娃和中华田园犬,黑白配是二哈和阿拉斯加,这个条件所降低的不确定性则是信息增益,计算公式如下。
定义:
信息增益 = B - sum(P1*S1, P2*S2,……)
Px指类型x在该组数据中占到的比例(例如黑白配有2种(二哈和阿拉斯加),一共有6种犬类,比例就是1/3)。
Sx当类型为x,得到的信息熵。
B无任何分类时的信息熵(6种犬类,和上面6面骰子的信息熵一样)。
最优分类(最大信息增益):
接着上面的例子,小狗我们可以根据毛发颜色,体型,甚至眉心是否有火字印记(这是区分二哈和阿拉斯加的条件)等条件来对这几种犬分类,如果朋友只能回答你一个问题,让你猜测犬类,那么你就需要一个最优分类,通过计算这几种分类方式带来的信息增益,选择最大者则是最大信息增益,该分类方式则是最优分类。
以下是python计算最佳分类的方法:
本文中选用ID3方法生成决策树,生成方法大致为:根据数据集计算最优分类列,根据该类的每一个值作为key,对应的value通过该方法递归生成。
当根据某一个特征值划分出来的数据是全部重复的数据,程序不存在继续划分的意义,递归停止,当所有特征值已经使用完,仍有多样数据时,取数据集中出现频率最高值作为分类结果。
直接上代码:
下一篇文章会介绍如何使用matplotlib根据决策图绘制图形,以及如何使用决策树进行分类。
本文中,没有强制要求结果为哪一列,所以数据都是以最后一列来划分,如果有指定列,计算最优分类时,指定该列即可。
当分类数据过多且不确定性较高时,决策树匹配消耗的时间较多,当数据变动性不大时,可以将决策树进行存储,在需要时取出树进行分析,下一篇文章会介绍如何使用pickle存储决策树。
决策树算法特点及应用
信息概念介绍
生成决策树
总结
参考
1.决策树算法简介
决策树概念介绍决策树算法是监督学习算法的其中一种,用于根据已有数据训练数据针对未知数据进行分类的一种算法,该算法的核心理念是通过不断的判断,递归,判断,来计算数据的分类。
举例说明
概念可能不大好理解,举例就会清楚直观了,相信大多数人都有过生病的体验,找医生看病的时候,医生就会让你伸出舌头看看,摸摸你的额头等,这就是根据症状来判断是什么病,如果你患了感冒,医生会首先问你是否有腹泻,然后让你伸出舌头,看看你的舌苔,之后会问你是否头痛,发冷,根据这一系列的数据,医生便可以推断你的感冒类型,对症下药。
发热 | 腹泻 | 舌苔黄 | 头痛 | 畏寒 | 感冒类型 |
---|---|---|---|---|---|
是 | 否 | 轻微 | 是 | 轻微 | 风热型感冒 |
是 | 否 | 否 | 是 | 是 | 风寒型感冒 |
是 | 是 | 轻微 | 是 | 是 | 暑湿型感冒 |
是 | 否 | 是 | 是 | 是 | 时行感冒 |
2.决策树算法特点及应用
特点:计算复杂度不高
输出结果便于理解
适用于分类,适合标称数值
应用:
之前在微信里,朋友发给我一个链接,点进去是一个机器人来根据你的问题答案猜测是哪位明星的问题,当时觉得非常的神奇,在学习了决策树之后,才明白了其中的道理,当然这也是我猜测,首先,这个网站会收藏很多的问题作为特征值,并收集很多明星的信息,把该信息录入本地数据集,例如上面的发热,腹泻等特征,然后抽取问题1,根据答案来选择下一个提出的问题(如果选择不知道则忽略该特征),直到指定特征被用完(答完10个问题),根据最后结果集中出现次数最多作为答案。
3.信息概念介绍
信息概念:信息是反映一个事件出现概率的单位(曾经在大学学的通信原理已经忘得一干二净),首先列出公式,下面再分析。
- 信息 = log2(概率)
上述的发热症状,无论哪种感冒都存在发热现象,那么这个信息其实对我们分析病情是无关紧要,所以他的信息是0,也许大家不能理解这个公式的计算方式,但我们并不准确需要这个值,我们只需要信息与概率的对应关系,无论是log3或者log4,对数据分类不造成影响,如果出现概率不为1的话,概率越大,信息量也就越小。
信息熵概念:
信息熵是反映一组数据的不确定性,就好比掷骰子,扔12面的骰子比6面的骰子结果不确定性就会高很多,信息熵就是用来反映这个不确定性的单位,计算公式如下:
- 信息熵 = sum(-概率1*log2(概率1), -概率2*log2(概率2),……)
从公式可能不太容易看出什么,不如我们用数值代入,6面骰子,有6种情况,每一种都是1/6,那么结果就是log2(6)=0.778,12面骰子就是log2(12)=1.079,不确定性高了之后,信息熵也得到了上涨,下面列出计算信息熵的python代码。
from math import log from collections import Counter def calc_shannon_ent(data_set): last_item_set = [item[-1] for item in data_set] # 抽取需要计算信息熵的列,这里直接取最后一列来计算 data_length = len(last_item_set) # 计算数据集的长度 counter_data = Counter(last_item_set) # 使用Counter来计算出现概率,counter_data的值是字典,例如{'a': 5, 'b': 2} shannon_ent = 0.0 for item_s in counter_data.iteritems(): probability = item_s[1] / float(data_length) info = log(probability, 2) shannon_ent -= info * probability return shannon_ent >>> data = [[1, 2, 'yes'], [2, 3, 'unknown'], [4, 15, 'no'], [12, 2, 'no'], [2, 3, 'yes'], [2, 4, 'unknown']] >>> calc_shannon_ent(data) 1.58496250072
信息增益:
信息增益是通过其他条件来降低这一组数据的不确定性,就好比朋友养了一条小狗,朋友告诉你这条狗是萨摩耶,吉娃娃,京巴,二哈,阿拉斯加和中华田园犬中的一种,让你去猜,如果直接猜,猜中的几率是1/6,但是如果知道这条狗的毛发颜色,那么猜中的几率就会提高,白色是萨摩耶,黄色是京巴,吉娃娃和中华田园犬,黑白配是二哈和阿拉斯加,这个条件所降低的不确定性则是信息增益,计算公式如下。
定义:
信息增益 = B - sum(P1*S1, P2*S2,……)
Px指类型x在该组数据中占到的比例(例如黑白配有2种(二哈和阿拉斯加),一共有6种犬类,比例就是1/3)。
Sx当类型为x,得到的信息熵。
B无任何分类时的信息熵(6种犬类,和上面6面骰子的信息熵一样)。
最优分类(最大信息增益):
接着上面的例子,小狗我们可以根据毛发颜色,体型,甚至眉心是否有火字印记(这是区分二哈和阿拉斯加的条件)等条件来对这几种犬分类,如果朋友只能回答你一个问题,让你猜测犬类,那么你就需要一个最优分类,通过计算这几种分类方式带来的信息增益,选择最大者则是最大信息增益,该分类方式则是最优分类。
以下是python计算最佳分类的方法:
from calc_shannon_ent import calc_shannon_ent """该方法是根据选中某一列的值来划分数据集,例如数据为[[1, 1, 'yes'], [2, 2, 'yes'], [3, 3, 'no'], [4, 4, 'unknown']],那么根据第2列,值为yes来划分得到的数据为[[1, 1], [2, 2]]""" def split_data_by_value(data_set, axis, value): sub_data_set = [] for item in data_set: if item[axis] == value: sub_item = item[:axis] + item[axis + 1:] # 拆分再组合 把[1, 2, 3]组合成[1, 3] sub_data_set.append(sub_item) return sub_data_set def choose_best_feature(data_set): feature_nums = len(data_set[0]) # 获取特征数(就是数据集的列数) base_ent = calc_shannon_ent(data_set) # 计算基础信息熵 base_gain = 0.0 base_choose = -1 for i in range(feature_nums): # 对所有特征进行遍历 feature_values = [item[i] for item in data_set] # 取出特征列所有值 unique_values = set(feature_values) # 去除重复值 sub_ent = 0.0 for item_unq in unique_values: # 对唯一特征值进行遍历 sub_data_set = split_data_by_value(data_set, i, item_unq) #根据该特征值划分数据集 sub_data_ent = calc_shannon_ent(sub_data_set) # 对子数据集计算信息熵 probability = len(sub_data_set) / float(len(data_set)) # 计算该特征值在所有特征值中的比例 sub_ent += sub_data_ent * probability # 累加计算总信息熵 data_gain = base_ent - sub_ent # 计算信息增益 if data_gain > base_gain: # 计算最大信息增益 base_gain = data_gain base_choose = i return base_choose # 返回最大信息增益的特征列 >>> data = [[1, 2, 'yes'], [2, 3, 'unknown'], [4, 15, 'no'], [12, 2, 'no'], [2, 3, 'yes'], [2, 4, 'unknown']] >>> choose_best_feature(data) 0 # 第一列是最佳列,因为该列为2时,最后一列2个都为unknown >>> data = [[1, 3, 'yes'], [2, 2, 'unknown'], [4, 15, 'no'], [12, 2, 'no'], [2, 3, 'yes'], [2, 2, 'unknown']] >>> choose_best_feature(data) 2 # 修改了一下data,让最后一列与倒数第二列建立对应关系,最后一列成为最佳分类
4.生成决策树
生成方法:本文中选用ID3方法生成决策树,生成方法大致为:根据数据集计算最优分类列,根据该类的每一个值作为key,对应的value通过该方法递归生成。
当根据某一个特征值划分出来的数据是全部重复的数据,程序不存在继续划分的意义,递归停止,当所有特征值已经使用完,仍有多样数据时,取数据集中出现频率最高值作为分类结果。
直接上代码:
import json from collections import Counter from split_best_feat import choose_best_feature, split_data_by_value def create_tree_data(): # 这是我在网上找到的关于犬类 体型 食量 寿命的对应关系 data = [ ['small', 'large', 12], ['big', 'big', 10], ['big', 'big', 10], ['small', 'small', 12], ['small', 'small', 15], ['medium', 'small', 12], ['big', 'medium', 15], ['medium', 'medium', 11], ['medium', 'big', 11], ['medium', 'small', 13], ] labels = ['体型', '食量', '寿命'] return data, labels def count_most_data(data_set): # 计算一个数据集中,出现频率最高的值 class_count = {} for item in data_set: class_count[item[0]] = class_count.get(item[0], 0) + 1 sort_count = sorted(class_count.iteritems(), key=lambda x: x[1], reverse=True) return sort_count[0][0] def strategy_tree(data, labels): temp_data_list = [item[-1] for item in data] if len(Counter(temp_data_list)) == 1: return temp_data_list[0] # 如果数值全部统一,则停止递归 if len(data[0]) == 1: return count_most_data(data) # 如果特征已经用完,则停止递归 best_feature = choose_best_feature(data) # 选择最优分类列 data_list = [item[best_feature] for item in data] # 取最优分类列的各个数值 label = labels[best_feature] # 取最优分类列的标签 labels.remove(label) # 移除该标签,用于下次递归 sub_labels = labels[:] unique_values = set(data_list) # 取最优分类列的唯一值 ret_data = {} ret_data[label] = {} for unq_item in unique_values: sub_data_set = split_data_by_value(data, best_feature, unq_item) # 根据最优分类列的值切分子数据集 ret_data[label][unq_item] = strategy_tree(sub_data_set, sub_labels[:]) # 对子数据集递归处理 return ret_data >>> data, label = create_tree_data() >>> tree = strategy_tree(data, label) 0 # 第一列是最佳列,因为该列为2时,最后一列2个都为unknown >>> json.dumps(tree, ensure_ascii=False) { "寿命": { "10": "big", "11": { "食量": { "big": "medium", "medium": "medium" } }, "12": { "体型": { "small": "large", "medium": "small" } }, "13": "small", "15": { "体型": { "small": "small", "big": "medium" } } } }
5.总结
本文介绍了决策树的相关概念,并介绍了有关信息等概念,以及如何创建决策树。下一篇文章会介绍如何使用matplotlib根据决策图绘制图形,以及如何使用决策树进行分类。
本文中,没有强制要求结果为哪一列,所以数据都是以最后一列来划分,如果有指定列,计算最优分类时,指定该列即可。
当分类数据过多且不确定性较高时,决策树匹配消耗的时间较多,当数据变动性不大时,可以将决策树进行存储,在需要时取出树进行分析,下一篇文章会介绍如何使用pickle存储决策树。
6.参考
[机器学习实战]相关文章推荐
- UE4 蓝图 实现 数组的边遍历边删除
- linux sed 命令详解
- ElasticSearch教程(二)——ElasticSearch基本插件head
- ElasticSearch教程(二)——ElasticSearch基本插件head
- C#学习——简单socket、多线程
- java.lang.NoSuchMethodError: org.apache.hadoop.hbase.HTableDescriptor.addFamily(Lorg/apache/hadoop/h
- 相机模型-计算机视觉
- SVD建模
- 160422、Highcharts后台获取数据
- UVa #11582 Colossal Fibonacci Numbers!
- 【机器学习算法】基于R语言的多元线性回归分析
- main函数——命令行参数与环境变量
- python re 模块
- 值班记录本
- 联想Lenove台式机进入BIOS,设置U盘为启动项+破解电脑密码(老毛桃+cmd)
- Java语法糖2:自动装箱和自动拆箱
- 鸟哥私房菜linux基础学习笔记 6
- android studio如何创建并依赖library module
- java中RSA加解密的实现
- JSP的执行过程及其异常处理机制