决策树引入
逻辑回归是一种线性有监督离散型分类模型
决策树是一种非线性有监督离散型分类模型
随机森林也是一种非线性有监督离散型分类模型
离散化
案例分析: 离散化
数据类型
-
离散的数据 需指明取值数量 2^M 种分割方式
天气 : 晴天 雨天 多云
学历: 高中 本科 研究生 -
连续的数据 需离散化, 需指明离散化后的数量
车速:
低速 (60)中速 (80 )高速
M+1种分割方式
决策树是通过固定的条件来对类别进行判断:
决策树的生成:
数据在不断分裂的递归过程,每一次分裂,尽可能让类别一样的数据在树的一边,当树的叶子节点的数据都是一类的时候,则停止分裂(if lese语句)
计算纯度的方式
基尼系数,熵越大,方差越大,数据集越不一样,纯度越高
基尼系数
基尼系数是指国际上通用的、用以衡量一个国家或地区居民收入差距的常用指标
- 若低于0.2表示指数等级极低;(高度平均)
- 0.2-0.29表示指数等级低;(比较平均)
- 0.3-0.39表示指数等级中;(相对合理)
- 0.4-0.59表示指数等级高;(差距较大)
- 0.6以上表示指数等级极高。(差距悬殊)
一般发达国家的基尼指数在0.24到0.36之间,美国偏高,为0.45。中国国家统计局公布基尼系数2012年为0.474,2013年为0.473,2014年为0.469,2015年为0.462,2016年为0.465
熵和方差我们前面讲过,这里不再赘述
决策树的分割方式:非线性
单颗决策树的缺陷
单颗决策树的缺点:
运算量大,需要一次加载所有数据进内存。并且找寻分割条件是一个极耗资源的工作
训练样本中出现异常数据时,将会对决策树产生很大影响。抗干扰能力差
解决方法:
减少决策树所需训练样本(减少列或者减少行)
随机采样,降低异常数据的影响
逻辑回归的优点:
和逻辑回归比,逻辑回归可以给告诉我们概率(或者设置阈值),二决策树只能0, 1
随机森林
森林:由树组成
随机:生成树的数据都是从数据集中随机选取的
当数据集很大的时候,我们随机选取数据集的一部分,生成一颗树,重复上述过程,我们可以生成一堆
形态各异的树,这些树放在一起就叫森林
随机森林VS逻辑回归
剪枝
预剪枝: 在这棵树还没开始分裂的时候,提前设定好一些条件,在达到这些条件以后就不长了
后剪枝:先长,长完了再去掉(比如合并叶子节点)
预剪枝的方式:
(1)控制分裂的层次
(2)控制叶子节点的样本数量
剪枝保证了模型的通用性
决策树做回归
通过求均值的方式来让分类结果可数
代码实现
决策树
# encoding:utf-8
import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
# 决策数的分类器
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
iris = load_iris()
data = pd.DataFrame(iris.data)
data.columns = iris.feature_names
data['Species'] = iris.target
# print(data)
# 花萼长度和宽度
x = data.iloc[:, :2]
y = data.iloc[:, -1]
# 对数据集进行切分
# 相同的随机种子产生的随机数是一样
# 不同的随机种子产生的随机数不一样
x_train, x_test, y_train, y_test = train_test_split(x, y, train_size=0.75, random_state=42)
# 创建一个决策数的模型
tree_clf = DecisionTreeClassifier(max_depth=4, criterion='entropy')
tree_clf.fit(x_train, y_train)
y_test_hat = tree_clf.predict(x_test)
print("acc score:", accuracy_score(y_test, y_test_hat))
depth = np.arange(1, 15)
err_list = []
"""
splitter: 分裂的方式
best 找最好的维度进行分裂
random 随机找维度进行分裂
feature: splitter方法中,找best分割维度的时候,需要在多少个维度中找那个最好的
none 就是不限制找的数量
int 就是找n个数进行考量
float就是找0.5(50%)去试
sqrt就是找所有特征数开根号个特征
max_depth: 树分裂的最大深度 none
min_sample_split:分裂前我需要保证这个叶子有几个样本
int就是要保证叶子里的样本数大于n,
float 就是要保证叶子里的样本数大于某个百分比
min_sample_leaf: 分裂后需要保证每个分裂的叶子有几个样本
min_weight_fraction_leaf:每个叶子节点里的样本数,必须是所有样本的10%
max_leaf_nodes:最多的叶子数
min_impurity_split:每个叶子节点里的不纯度,这个参数是为了保证树不会过早的停止生长;达不到指标就会继续往下分裂
"""
for d in depth:
clf = DecisionTreeClassifier(criterion='entropy', max_depth=d)
clf.fit(x_train, y_train)
y_test_hat = clf.predict(x_test)
result = (y_test_hat == y_test)
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('Decision Tree Depth', fontsize=15)
plt.ylabel('Error Rate', fontsize=15)
plt.title('Decision Tree Depth & Over Fit', fontsize=18)
plt.grid(True)
plt.show()
随机森林
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.ensemble import BaggingClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn.datasets import load_iris
iris = load_iris()
X = iris.data[:, :2] # 花萼的长度和宽度(因为选花瓣的长宽的话,分类效果太好了)
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=43)
# n_estimators指的是用多少颗树, max_leaf_1des指树的复杂程度, n_jobs指用多少个线程
rnd_clf = RandomForestClassifier(n_estimators=30, max_leaf_nodes=16, n_jobs=1)
rnd_clf.fit(X_train, y_train)
# bagging:并行思想,bagging的决策树和随机森林其实是等价的
# max_samples 训练时用所有的样本 splitter=random 指的是虽然每课小树取使用所有样本,但是我只使用随机出来的一部分维度来训练每棵小树
bag_clf = BaggingClassifier(
DecisionTreeClassifier(splitter="random", max_leaf_nodes=16),
n_estimators=30, max_samples=1.0, bootstrap=True, n_jobs=1
)
bag_clf.fit(X_train, y_train)
y_pred_rf = rnd_clf.predict(X_test)
y_pred_bag = bag_clf.predict(X_test)
print(accuracy_score(y_test, y_pred_rf))
print(accuracy_score(y_test, y_pred_bag))
# Feature Importance 用随机森林选择出来重要的特征,也就是分裂效果好的特征,也就是和y相关性大的特征
# 一般来说,相关性越大的特征,应该出现在树的上层
iris = load_iris()
# -1 表示有多少线程用多少线程
rnd_clf = RandomForestClassifier(n_estimators=500, n_jobs=-1)
rnd_clf.fit(iris["data"], iris['target'])
for name, score in zip(iris['feature_names'], rnd_clf.feature_importances_):
print(name, score)
'''
Xgbost: 并行
GDBT:串行
公司中,特征提取会用到树的算法
'''
总结
决策树和随机森林
1.决策树
(1)决策树是一个有监督的机器学习算法,做分类用的,而且是非线性的。
(2)决策树的建模过程,不是创造一个方程了,而是构建一棵树。这棵树不一定只是二叉树
(3)损失函数:
- 基尼系数
- 熵
- 方差
这三种,都是值越大,纯度越高
纯度:当我们应用一个特征(比如说头发长度)对数据(男女)进行分类的时候,如果这个特征能把数据都分到一边去(全部男,或者全部女),我们就说这个特征可分类的纯度高
有很多参数都在围绕纯度进行调式:splitter (best, random)…
(4) 决策树的参数:都是为了构建一个优秀的决策树,提供的支持
max_leaf_node, max_depth…
(5)剪枝:就是决策数的正则化
为了减少过拟合的现象
预剪枝:在树没有生成前,通过对将要生成树的判断,来进行限制max_depth
后剪枝:在树生成之后,通过对某些叶子节点的删除,来进行限制max_leaf_perc
2.随机森林
随机森林,就是由很多决策树构成的
(1)并行思想:因为随机森林中的树都是相互独立的,所以这些树可以在不同的机器上,或者CPU,GPU上运行,这样能极大缩短建模的时间