前面一篇大致讲解了一下有关决策树与随机森林的理论部分,这一篇我们就来电实际的,讲一下python怎么实现决策树与随机森林的,这部分的code有一点简单,应该可以更好的理解这个算法。
首先是模块的导入,涉及的模块有
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
from sklearn import tree
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
然后就是正文了。
如果要显示中文的话,需要再python代码里加入两行:
mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False
读取数据:
path = '' # 数据文件路径
data = np.loadtxt(path, dtype=float, delimiter=',', converters={4: iris_type})#原始数据的数据类型为float,分割符为逗号,第四列所有数据要转换通过iris_type函数。
x, y = np.split(data, (4,), axis=1)#axis=1,代表列,是要把data数据集中的所有数据按第四、五列之间分割为X集和Y集。
# 为了可视化,仅使用前两列特征
x = x[:, :2]
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=1)
#在这里讲一下:
sklearn.model_selection.train_test_split随机划分训练集和测试集
- 一般形式:
train_test_split是交叉验证中常用的函数,功能是从样本中随机的按比例选取train data和testdata,形式为:
X_train,X_test, y_train, y_test =
cross_validation.train_test_split(train_data,train_target,test_size=0.4, random_state=0)
- 参数解释:
train_data:所要划分的样本特征集
train_target:所要划分的样本结果
test_size:样本占比,如果是整数的话就是样本的数量
random_state:是随机数的种子。
随机数种子:其实就是该组随机数的编号,在需要重复试验的时候,保证得到一组一样的随机数。比如你每次都填1,其他参数一样的情况下你得到的随机数组是一样的。但填0或不填,每次都会不一样。
随机数的产生取决于种子,随机数和种子之间的关系遵从以下两个规则:
种子不同,产生不同的随机数;种子相同,即使实例不同也产生相同的随机数。
下面接着来,就是模型选择
('ss', StandardScaler()),
('DTC', DecisionTreeClassifier(criterion='entropy', max_depth=3))])
#criterion:string类型,可选(默认为"gini")
衡量分类的质量。支持的标准有"gini"代表的是Gini impurity(不纯度)与"entropy"代表的是information gain(信息增益)。
#max_depth:int or None,可选(默认为"None")
表示树的最大深度。如果是"None",则节点会一直扩展直到所有的叶子都是纯的或者所有的叶子节点都包含少于min_samples_split个样本点。忽视max_leaf_nodes是不是为None。
model = model.fit(x_train, y_train) # 拟合训练数据
y_test_hat = model.predict(x_test) # 测试数据(预测)
接下来我们来画图,直观的感受一下:
# 画图
N, M = 100, 100 # 横纵各采样多少个值
x1_min, x1_max = x[:, 0].min(), x[:, 0].max() # 第0列的范围
x2_min, x2_max = x[:, 1].min(), x[:, 1].max() # 第1列的范围
t1 = np.linspace(x1_min, x1_max, N)
t2 = np.linspace(x2_min, x2_max, M)
x1, x2 = np.meshgrid(t1, t2) # 生成网格采样点
x_show = np.stack((x1.flat, x2.flat), axis=1) # 测试点,stack() Join a sequence of arrays along a new axis.
# 训练集上的预测结果
y_test = y_test.reshape(-1)
print y_test_hat
print y_test
result = (y_test_hat == y_test) # True则预测正确,False则预测错误
acc = np.mean(result)
print '准确度: %.2f%%' % (100 * acc)
# 过拟合:错误率
depth = np.arange(1, 15)
err_list = []
for d in depth:
clf = DecisionTreeClassifier(criterion='entropy', max_depth=d)
clf = clf.fit(x_train, y_train)
y_test_hat = clf.predict(x_test) # 测试数据
result = (y_test_hat == y_test) # True则预测正确,False则预测错误
err = 1 - np.mean(result)
err_list.append(err)
print d, ' 准确度: %.2f%%' % (100 * err)
plt.figure(facecolor='w')
plt.plot(depth, err_list, 'ro-', lw=2)
plt.xlabel(u'决策树深度', fontsize=15)
plt.ylabel(u'错误率', fontsize=15)
plt.title(u'决策树深度与过拟合', fontsize=17)
plt.grid(True)
plt.show()
上面的代码大致讲解了一下决策树的应用,简单,而且易于理解。
==================================================================================
numpy中有一些常用的用来产生随机数的函数,randn()和rand()就属于这其中。
numpy.random.randn(d0, d1, …, dn)是从标准正态分布中返回一个或多个样本值。
numpy.random.rand(d0, d1, …, dn)的随机样本位于[0, 1)中。
代码:
import numpy as np
arr1 = np.random.randn(2,4)
print(arr1)
print('******************************************************************')
arr2 = np.random.rand(2,4)
print(arr2)
- 1
结果:
[[-1.03021018 0.5197033 0.52117459 -0.70102661]
[ 0.98268569 1.21940697 -1.095241 -0.38161758]]
******************************************************************
[[ 0.19947349 0.05282713 0.56704222 0.45479972]
[ 0.28827103 0.1643551 0.30486786 0.56386943]]
=======================================================================================
用决策树也可以解决回归问题:
导出的模块为
from sklearn.tree import DecisionTreeRegressor
reg = DecisionTreeRegressor(criterion='mse', max_depth=9)
dt = reg.fit(x, y)
x_test = np.linspace(-3, 3, 50).reshape(-1, 1)
y_hat = dt.predict(x_test)
plt.plot(x, y, 'r*', linewidth=2, label='Actual')
plt.plot(x_test, y_hat, 'g-', linewidth=2, label='Predict')
plt.legend(loc='upper left')
plt.grid()
plt.show()
==================================================================================
好,上面都是讲的是决策树,下面我们再来看一下随机森林:
导入模块:
from sklearn.ensemble import RandomForestClassifier
下面的读取数据就省略了
看模型选定:
clf = RandomForestClassifier(n_estimators=200, criterion='entropy', max_depth=4)
#参数
- sklearn.ensemble.RandomForestClassifier(n_estimators=10, crite-rion=’gini’, max_depth=None,
- min_samples_split=2, min_samples_leaf=1,
- min_weight_fraction_leaf=0.0,
- max_features=’auto’,
- max_leaf_nodes=None, bootstrap=True,
- oob_score=False, n_jobs=1, ran-dom_state=None, verbose=0,
- warm_start=False, class_weight=None)
criterion: ”gini” or “entropy”(default=”gini”)是计算属性的gini(基尼不纯度)还是entropy(信息增益),来选择最合适的节点。
splitter: ”best” or “random”(default=”best”)随机选择属性还是选择不纯度最大的属性,建议用默认。
max_features: 选择最适属性时划分的特征不能超过此值。
当为整数时,即最大特征数;当为小数时,训练集特征数*小数;
if “auto”, then max_features=sqrt(n_features).
If “sqrt”, thenmax_features=sqrt(n_features).
If “log2”, thenmax_features=log2(n_features).
If None, then max_features=n_features.
max_depth: (default=None)设置树的最大深度,默认为None,这样建树时,会使每一个叶节点只有一个类别,或是达到min_samples_split。
min_samples_split:根据属性划分节点时,每个划分最少的样本数。min_samples_leaf:叶子节点最少的样本数。
max_leaf_nodes: (default=None)叶子树的最大样本数。
min_weight_fraction_leaf: (default=0) 叶子节点所需要的最小权值
verbose:(default=0) 是否显示任务进程
n_estimators=10:决策树的个数,越多越好,但是性能就会越差,至少100左右(具体数字忘记从哪里来的了)可以达到可接受的性能和误差率。
bootstrap=True:是否有放回的采样。
oob_score=False:oob(out of band,带外)数据,即:在某次决策树训练中没有被bootstrap选中的数据。多单个模型的参数训练,我们知道可以用cross validation(cv)来进行,但是特别消耗时间,而且对于随机森林这种情况也没有大的必要,所以就用这个数据对决策树模型进行验证,算是一个简单的交叉验证。性能消耗小,但是效果不错。
n_jobs=1:并行job个数。这个在ensemble算法中非常重要,尤其是bagging(而非boosting,因为boosting的每次迭代之间有影响,所以很难进行并行化),因为可以并行从而提高性能。1=不并行;n:n个并行;-1:CPU有多少core,就启动多少job
warm_start=False:热启动,决定是否使用上次调用该类的结果然后增加新的。
class_weight=None:各个label的权重。
rf_clf = clf.fit(x, y.ravel()) #ravel()是列转行
# 画图
N, M = 500, 500 # 横纵各采样多少个值
x1_min, x1_max = x[:, 0].min(), x[:, 0].max() # 第0列的范围
x2_min, x2_max = x[:, 1].min(), x[:, 1].max() # 第1列的范围
t1 = np.linspace(x1_min, x1_max, N)
t2 = np.linspace(x2_min, x2_max, M)
x1, x2 = np.meshgrid(t1, t2) # 生成网格采样点
x_test = np.stack((x1.flat, x2.flat), axis=1) # 测试点
# 训练集上的预测结果
y_hat = rf_clf.predict(x)
y = y.reshape(-1)
c = np.count_nonzero(y_hat == y) # 统计预测正确的个数
print '特征: ', iris_feature[pair[0]], ' + ', iris_feature[pair[1]],
print '\t预测正确数目:', c,
print '\t准确率: %.2f%%' % (100 * float(c) / float(len(y)))
其他的代码部分就胜率了,核心的随机森林代码上面就是了,先就写这些,待以后再补充说明。