一、简介
对于连续值,最简单得方法就是采用二分法对连续属性进行处理,这正是C4.5决策树算法中采用的机制。
那要取哪个值进行二分呢?简单的用中位数的方法可能会使得训练不如预期,所以我们要选择划分之后信息增益最大的划分点。对于属性a,我们有下面n-1个元素可以被选作划分点。
信息增益定义为:
其中Gain(D,a,t)是样本集D基于划分点t划分后的信息增益 。
在我自己的实现中,考虑到一些数据集的数据量很大,上万甚至十万,所以我设置了一个步长(stride),意味着当我们遍历n-1个划分点的时候,以一定的步长去遍历。
二、实现
import numpy as np
def find_best_split(attr, label, base_entropy, stride):
data0 = np.c_[attr, label]
data = data0[np.argsort(data0[:,0])]
if not stride:
stride = int(len(attr)/100) + 1
max_info_gain = 0
max_gain_index = 0
for i in range(0, data.shape[0]-1, stride):
entropy1 = cal_entropy(data[:i,1])
entropy2 = cal_entropy(data[i:,1])
proportion = float(i)/data.shape[0]
info_gain = proportion*entropy1+(1-proportion)*entropy2 - \
base_entropy
if info_gain > max_info_gain:
max_info_gain = info_gain
max_gain_index = i
return (data[max_gain_index, 0]+data[max_gain_index+1, 0]) / 2
def binaryzation_features(data, label, columns, stride=None):
data = np.array(data)
label = np.array(label)
base_entropy = cal_entropy(label)
for column in columns:
print("[INFO]: doing binaryzation of feature %s ..."%column)
split_point = find_best_split(data[:,column], label, \
base_entropy, stride)
print("[INFO]: best split point of column %s is %s"%(column,split_point))
data[data[:, column] < split_point, column] = 0
data[data[:, column] >= split_point, column] = 1
return data, label
使用:
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
#%%
data = load_iris()
x = data['data']
y = data['target']
# columns指定二值化哪几列,stride表示步长
data, label = binaryzation_features(x, y, columns=[0,1,2,3], stride=1)
二分后的树结构(注:该树结构的定义在文章 机器学习:决策树(一) ——决策树、树剪枝的原理及代码实现 中)
关于决策树的可视化,可以参考:机器学习:决策树(三)——决策树的可视化
二值化后 二值化前
三、参考文献
【1】《机器学习》周志华