您的位置:首页 > 其它

机器学习值决策树算法(上)-ID3实现

2016-04-25 11:47 141 查看
决策树算法简介

决策树算法特点及应用

信息概念介绍

生成决策树

总结

参考

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.参考

[机器学习实战]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: