发现帮助新手入门机器学习的一篇好文,首先感谢博主!:用Python开始机器学习(2:决策树分类算法)
J. Ross Quinlan在1975提出将信息熵的概念引入决策树的构建,这就是鼎鼎大名的ID3算法。后续的C4.5, C5.0, CART等都是该方法的改进。
熵就是“无序,混乱”的程度。刚接触这个概念可能会有些迷惑。想快速了解如何用信息熵增益划分属性,可以参考这位兄弟的文章:http://blog.csdn.net/alvine008/article/details/37760639
数据集中信息熵的计算:
H(x) = E[I(xi)] = E[ log(2,1/p(xi)) ] = -∑p(xi)log(2,p(xi)) (i=1,2,..n)
以博主例子为例,直接上代码:
1. 数据集:
more fat.txt
1.5 thin
1.5 fat
1.6 thin
1.6 fat
1.7 thin
1.7 fat
1.8 thin
1.8 fat
1.9 thin
1.9 fat
2. 读入数据集
#!/usr/bin/env python
# coding=utf- import numpy as np
from sklearn import tree
from sklearn.metrics import precision_recall_curve
from sklearn.metrics import classification_report
from sklearn.cross_validation import train_test_split def loadDataSet():
data =[]
label= []
with open('./data/fat.txt') as file:
for line in file:
tokens = line.strip().split(' ')
data.append([float(tk) for tk in tokens[:-]])
label.append(tokens[-])
x = np.array(data)
label = np.array(label)
y = np.zeros(label.shape)
y[label=='fat']=
return x,y
3. 使用sklearn 中的现成库进行分类,简单而优雅
def decisionTreeClf():
x,y = loadDataSet() # 拆分数据集和训练集
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.2) # 使用信息熵作为划分标准
clf = tree.DecisionTreeClassifier(criterion='entropy')
print(clf)
clf.fit(x_train,y_train) # 将决策树写入文件
with open("tree.dot","w") as f:
f = tree.export_graphviz(clf,out_file=f) # 打印特征在分类起到的作用性
print(clf.feature_importances_) # 打印测试结果
answer = clf.predict(x_train)
print(x_train)
print(answer)
print(y_train)
print(np.mean(answer==y_train)) # 准确率与召回率
precision,recall,thresholds = precision_recall_curve(y_train,clf.predict(x_train)
)
answer = clf.predict_proba(x)[:,]
print(classification_report(y,answer,target_names=['thin','fat']))
结果显示:
>>> bayesDt.decisionTreeClf()
DecisionTreeClassifier(class_weight=None, criterion='entropy', max_depth=None,
max_features=None, max_leaf_nodes=None, min_samples_leaf=,
min_samples_split=, min_weight_fraction_leaf=0.0,
random_state=None, splitter='best')
[ 0.2488562 0.7511438]
[[ 1.9 . ]
[ 1.5 . ]
[ 1.5 . ]
[ 1.7 . ]
[ 1.9 . ]
[ 1.6 . ]
[ 1.8 . ]
[ 1.8 . ]]
[ . . . . . . . .]
[ . . . . . . . .]
1.0
precision recall f1-score support thin 0.83 1.00 0.91
fat 1.00 0.80 0.89 avg / total 0.92 0.90 0.90 >>>
这里有3点需要说明,这在以后的机器学习中都会用到。
1、拆分训练数据与测试数据。
这样做是为了方便做交叉检验。交叉检验是为了充分测试分类器的稳定性。代码中的0.2表示随机取20%的数据作为测试用。其余80%用于训练决策树。
也就是说10个样本中随机取8个训练。本文数据集小,多运行几次,可以看到由于取的训练数据随机,每次构建的决策树都不一样。
2、特征的不同影响因子。
样本的不同特征对分类的影响权重差异会很大。分类结束后看看每个样本对分类的影响度也是很重要的。
在本例中,身高的权重为0.25,体重为0.75,可以看到重量的重要性远远高于身高。对于胖瘦的判定而言,这也是相当符合逻辑的。
3、准确率与召回率。
这2个值是评判分类准确率的一个重要标准。比如代码的最后将所有10个样本输入分类器进行测试的结果:
测试结果:array([ 0., 1., 0., 1., 0., 1., 0., 1., 0., 0.])
真实结果:array([ 0., 1., 0., 1., 0., 1., 0., 1., 0., 1.])
分为thin的准确率为0.83。是因为分类器分出了6个thin,其中正确的有5个,因此分为thin的准确率为5/6=0.83。
分为thin的召回率为1.00。是因为数据集*有5个thin,而分类器把他们都分对了(虽然把一个fat分成了thin!),召回率5/5=1。
分为fat的准确率为1.00,召回率为0.80。是因为数据集*有5个fat,而分类器只分出了4个(把一个fat分成了thin!),召回率4/5=0.80。
很多时候,尤其是数据分类难度较大的情况,准确率与召回率往往是矛盾的。你可能需要根据你的需要找到最佳的一个平衡点。
比如本例中,你的目标是尽可能保证找出来的胖子是真胖子(准确率),还是保证尽可能找到更多的胖子(召回率)。