随机森林就是通过集成学习的思想将多棵树集成的一种算法,它的基本单元是决策树,而它的本质属于机器学习的一大分支——集成学习(Ensemble Learning)方法。
目录
3,随机森林分类器sklearn代码——RandomForestClassifier
1,红酒
一、决策树
1,介绍
决策树(decision tree):是一种基本的分类与回归方法。基本原理是通过对一系列问题进行if/else的推导,最终实现相关决策。
通过连续的逻辑判断得出最后的结论,其关键在于如何建立这样一棵“树”。
2,Gini系数(CART决策树)
决策树模型的建树依据主要用到的是基尼系数的概念。
基尼系数(gini)用于计算一个系统中的失序现象,即系统的混乱程度(纯度)。基尼系数越高,系统的混乱程度就越高(不纯),建立决策树模型的目的就是降低系统的混乱程度(体高纯度),从而得到合适的数据分类效果。
其中为类别i在样本中出现的频率,即类别为的样本占总样本个数的比率。
就像,一个全部都是坏瓜的样本中只有一个类别——坏瓜,其出现的频率是100%,所以该系统的基尼系数为1-1^2=0,表示该系统没有混乱,或者说该系统的“纯度”很高。
而如果样本中一半是好瓜,另一半是坏瓜,那么类别个数为2,每个类别出现的频率都为50%,所以其基尼系数为1-(0.5^2+0.5^2)=0.5,即其混乱程度很高。
当引入某个用于分类的变量时,分类后的基尼系数为:
def Gini(data):
n0 = sum(data['好瓜']==0)
n1 = sum(data['好瓜']==1)
if n0==0 or n1==0:
return 0
else:
n = n0 + n1
p0 = n0/n
p1 = n1/n
return p0*(1-p0) + p1*(1-p1)
# return 1 - p0*p0 - p1*p1 # 这是另外一种写法
3,信息熵、信息增益
除了基尼系数,还有另一种衡量系统混乱程度的经典手段——信息熵。
在搭建决策树模型时,信息熵的作用和基尼系数是基本一致的,都可以帮助合理地划分节点。
信息熵H(X)的计算公式如下。
其中X表示随机变量,随机变量的取值为X1,X2,X3…,在n分类问题中便有n个取值
当引入某个用于进行分类的变量A,则根据变量A划分后的信息熵又称为条件熵,其计算公式如下。
其中S1、S2为划分后的两类各自的样本量,H(X1)、H(X2)为两类各自的信息熵。
def H(data):
n0 = sum(data['好瓜']==0)
n1 = sum(data['好瓜']==1)
if n0==0 or n1==0:
return 0
else:
n = n0 + n1
p0 = n0/n
p1 = n1/n
return p0*(-np.log(p0)) + p1*(-np.log(p1))
为了衡量不同划分方式降低信息熵的效果,还需要计算分类后信息熵的减少值(原系统的信息熵与分类后系统的信息熵之差),该减少值称为熵增益或信息增益,其值越大,说明分类后的系统混乱程度越低,即分类越准确。
or
4,决策树算法
ID3/C4.5/CART算法的区别在于选择特征作为判断节点时的数据纯度函数(标准)不同。ID3算法使用的是信息增益,C4.5算法使用的是信息增益比,CART算法使用的是基尼系数(GINI)。
1,CART算法思想
CART算法是一种二分递归分割方法,把当前样本划分为两个子样本,不断递归分割使得生成的每个非叶子结点都有两个分支。所以,CART算法生成的决策树是一个二叉树。由于二叉树的每个节点的选择都只有“是”和“否”两种,所以即使一个节点下需要多分类,也是把数据分成两部分。
2,ID3
ID3算法使用的数据特征函数(标准)为信息增益。
5,决策树题目
EG1
1)下列说法正确的是?
A、训练决策树的过程就是构建决策树的过程
B、ID3算法是根据信息增益来构建决策树——(Gain)
C、CART算法是根据基尼不纯度来构建决策树(Gini)
D、决策树模型的可理解性不高
EG2
2)下列说法错误的是?
A、从树的根节点开始,根据特征的值一步一步走到叶子节点的过程是决策树做决策的过程
B、决策树只能是一棵二叉树
C、非叶子节点分割集合所使用的特征,是使混乱度下降得最多的特征。
EG3
3)用决策树训练一个问题出现过拟合,怎么搞:
A,控制最大深度
B,限制节点中最大的样本中的最小数量
C,限制不纯度的最大值(最小值)
D,更改不纯度计算方法,即模型中的criterion参数
1)当决策树的深度特别深特别深以至于叶子节点中的对象只剩下一个或者很少,导致决策树的模型过于复杂,容易造成过拟合问题,泛化能力下降——控制最大深度(深度小造成欠拟合,深度大造成过拟合) 定义一个高度,当决策树达到该高度时就可以停止决策树的生长,这是一种最为简单的方法
2)达到某个结点的实例具有相同的特征向量,即使这些实例不属于同一类,也可以停止决策树的生长。这种方法对于处理数据中的数据冲突问题非常有效——限制叶子结点处样本的数目
3)定义一个阈值,当达到某个结点的实例个数小于该阈值时就可以停止决策树的生长
EG4
先算总的Gini(正例和负例)
再计算特征里面的类别(这里就1和0)的正例和负例的Gini
相减的时候,特征Gini要乘以特征的类别对应概率
选B
EG5
在ensemble里面,决策树在tree
EG6
回归器注意了,criterion参数默认是mse
分类器criterion参数默认是gini
EG7
D
EG8
重采样A
EG9
重采样B
EG10
二、西瓜数据集——决策树ID3
1.导入数据
2,信息增益:
以敲起来是否沉闷为分割,即以'敲声==0'是否成立来分割:
X1 = watermelon['敲声']
w1 = watermelon[X1==0]
w2 = watermelon[X1!=0]
1)以基尼系数为例,计算信息增益:
n1, n2 = len(w1), len(w2)
p1, p2 = n1/(n1+n2), n2/(n1+n2)
IG = Gini(watermelon) - p1*Gini(w1) - p2*Gini(w2)
2)以基尼系数为例,计算信息增益:
IG = H(watermelon) - p1*H(w1) - p2*H(w2)
3)尝试所有可能,看各种条件下的信息增益谁最大
# TODO: 尝试所有可能,即敲声分别为0/1/2、纹理为别为0/1/2,看各种条件下的信息增益谁最大
def CalculateIG(dataset, feature_name, value):
w1, w2 = splitDataset(dataset, feature_name, value)
# 计算分割出来的两个子集的比例
n1, n2 = len(w1), len(w2)
p1, p2 = n1/(n1+n2), n2/(n1+n2)
# 以熵为例,计算信息增益
IG = H(dataset) - p1*H(w1) - p2*H(w2)
return IG
print(CalculateIG(watermelon, '敲声', 0))
print(CalculateIG(watermelon, '敲声', 1))
print(CalculateIG(watermelon, '敲声', 2))
print(CalculateIG(watermelon, '纹理', 0))
print(CalculateIG(watermelon, '纹理', 1))
print(CalculateIG(watermelon, '纹理', 2))
4)找出最大收益的节点进行分割
可见是(watermelon, '纹理', 1)为最大收益节点
分割左右节点
def splitDataset(dataset, feature_name, value):
# 以 'feature_name == value' 是否成立来分割
series = dataset[feature_name]
part1 = dataset[series==value]
part2 = dataset[series!=value]
return part1, part2
w1, w2 = splitDataset(watermelon, '纹理', 1)
# 找出w1、w2最大收益的节点
print(CalculateIG(w1, '敲声', 0))
print(CalculateIG(w1, '敲声', 1))
print(CalculateIG(w1, '敲声', 2))
print(CalculateIG(w1, '纹理', 0))
print(CalculateIG(w1, '纹理', 2))
print("=================================")
print(CalculateIG(w2, '敲声', 0))
print(CalculateIG(w2, '敲声', 1))
print(CalculateIG(w2, '敲声', 2))
print(CalculateIG(w2, '纹理', 0))
print(CalculateIG(w2, '纹理', 2))
5)重复步骤四
w3, w4 = splitDataset(w1, '敲声', 2)
w5, w6 = splitDataset(w2, '敲声', 1)
# 找出w3、w4最大收益的节点
print(CalculateIG(w3, '敲声', 0))
print(CalculateIG(w3, '敲声', 1))
print(CalculateIG(w3, '纹理', 0))
print(CalculateIG(w3, '纹理', 2))
print("=================================")
print(CalculateIG(w4, '敲声', 0))
print(CalculateIG(w4, '敲声', 1))
print(CalculateIG(w4, '纹理', 0))
print(CalculateIG(w4, '纹理', 2))
# 找出w5、w6最大收益的节点
print(CalculateIG(w5, '敲声', 0))
print(CalculateIG(w5, '敲声', 2))
print(CalculateIG(w5, '纹理', 0))
print(CalculateIG(w5, '纹理', 2))
print("=================================")
print(CalculateIG(w6, '敲声', 0))
print(CalculateIG(w6, '敲声', 2))
print(CalculateIG(w6, '纹理', 0))
print(CalculateIG(w6, '纹理', 2))
w7, w8 = splitDataset(w5, '纹理', 0)
w9, w10 = splitDataset(w4, '敲声', 0)
print(CalculateIG(w7, '敲声', 0))
print(CalculateIG(w7, '敲声', 2))
print(CalculateIG(w7, '纹理', 2))
print("=================================")
print(CalculateIG(w8, '敲声', 0))
print(CalculateIG(w8, '敲声', 2))
print(CalculateIG(w8, '纹理', 2))
print("=================================")
print(CalculateIG(w9, '敲声', 1))
print(CalculateIG(w9, '纹理', 0))
print(CalculateIG(w9, '纹理', 2))
print("=================================")
print(CalculateIG(w10, '敲声', 1))
print(CalculateIG(w10, '纹理', 0))
print(CalculateIG(w10, '纹理', 2))
6)sklearn决策树
sklearn中决策树模型放在tree包里面
1)决策回归器:DecisionTreeRegressor
重要参数:
criterion="mse" #默认。
"mse"表示使用均方误差;
"friedman_mse"表示使用费尔德曼均方误差;
“mae”表示使用绝对平均误差
2)决策分类器:DecisionTreeClassifier
重要参数:
criterion 这个参数正是用来决定不纯度的计算方法的。sklearn提供了两种选择
1)输入”entropy“,使用信息熵(Entropy)
2)输入”gini“,使用基尼系数(Gini Impurity)(默认)
# 1.建立模型
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
model = DecisionTreeClassifier(criterion='entropy')
# 2.训练模型
X, y = watermelon[['敲声','纹理']], watermelon['好瓜']
model.fit(X, y)
# 3-4.评估模型
y_pred=model.predict(X)
accuracy_score(y, y_pred)
二,随机森林
1,介绍
随机森林(Random Forest,简称 RF ),是以决策树为基学习器的 Bagging 集成算法,它通过自助法(bootstrap)重采样技术,从原始训练样本集N中有放回地重复随机抽取k个样本生成新的训练样本集合,是Bagging 集成算法中性能最强的。
首先森林两个字是非常好理解的,随机森林的基学习器是决策树,成百上千棵决策树就构成了一个森林,这是一种形象的说法。学习到多棵决策树之后,再按照上面所写的 Bagging 中基学习器的结合方法,就可以得到分类或回归的最终预测结果。
随机森林中运用了两个“随机”:
一是样本随机,也就是一般的 Bagging 集成中通过自助采样所得到的效果,也叫做样本扰动,这体现了随机森林继承性的一面。
二是特征随机,也叫属性扰动,体现了随机森林创新的一面。假设训练数据集中的样本有 d 个属性(特征),构成一个属性集合,那么随机森林在构建一棵决策树的过程中,在每一个结点上选择属性进行分裂时,都先从属性集合中随机选择一个包含 k 个属性的属性子集( k<d ),再从这个子集中选择一个最优属性进行分裂。回想一下传统的决策树构建过程,在每一个结点上都是从完整的属性集合(包含 d 个属性)中,选择最佳的属性进行分裂。一般情况下,推荐 k 的值取。
所以随机森林中每棵树生成的规则是:
1、对于包含 m 个样本的原始数据集,通过自助采样得到同样包含 m 个样本的训练集;
2、每个样本有 d 个特征,那么选择一个小于 d 的整数 k ,随机地从 d 个特征中选择 k 个特征,然后决策树在每个结点上进行分裂时,从 k 个特征中选择最优的;
3、每棵树都生长到最大深度,不进行剪枝。
1、下列说法正确的是?
A、相比自助法,在初始数据量较小时交叉验证更常用。
B、自助法对集成学习方法有很大的好处
C、使用交叉验证能够增加模型泛化能力
D、在数据难以划分训练集测试集时,可以使用自助法
2)建立随机森林模型时,主要通过什么技术使得各个评估器各不相同:
A,使用可重复抽样得到不同的数据集。
B,使用不同的criterion策略
C,采用不同的剪枝策略
D,使用"random"进行分割策略
2,python实现
建立红酒数据单棵决策树:
data = load_wine()
X_train, X_test, y_train, y_test = train_test_split(data.data, data.target, test_size=0.3)
model = DecisionTreeClassifier(criterion='entropy')
model.fit(X_train, y_train)
pred_y = model.predict(X_test)
accuracy_score(y_test, pred_y)
# 1.建立多个决策树
models = [DecisionTreeClassifier(criterion='entropy') for i in range(9)]
predicts = []
for m in models:
# 2.训练每个决策树
X, _, y, _ = train_test_split(X_train, y_train, test_size=0.2) # 随机分割代替重采样。
m.fit(X, y)
# 3.得到每个决策树的测试结果
p = m.predict(X_test)
predicts.append(p)
ps = np.array(predicts).T
# 4.对多个结果进行投票
results=[]
for line in ps:
results.append(np.argmax(np.bincount(line)))
p = np.array(results)
# 5.对投票结果进行评估
accuracy_score(y_test, p)
3,随机森林分类器sklearn代码——RandomForestClassifier
sklearn中随机森林模型放在ensemble包里面
重要参数:
1,n_estimators=10:决策树的个数,越多越好,但是性能就会越差,至少100左右(具体数字忘记从哪里来的了)可以达到可接受的性能和误差率。
2,bootstrap=True:是否有放回的采样。
1,红酒
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
model = RandomForestClassifier(n_estimators=9)
model.fit(X_train, y_train)
pred_y = model.predict(X_test)
accuracy_score(y_test, pred_y)
2,西瓜
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
# 用随机森林对西瓜数据集进行学习
model = RandomForestClassifier(n_estimators=9)
X, y = watermelon[['敲声','纹理']], watermelon['好瓜']
model.fit(X, y)
y_pred = model.predict(X)
accuracy_score(y, y_pred)
三,延展算法
1,堆叠法——StackingClassifier
【基础模型+基础模型+...+基础模型】【元模型】
1,红酒
from sklearn.ensemble import StackingClassifier
# 1.
model = StackingClassifier(
estimators=[('LR', LogisticRegression(max_iter=1000)), ('NB', GaussianNB())],
final_estimator=DecisionTreeClassifier(),
)
# 2.
model.fit(X_train, y_train)
# 3.
y_pred = model.predict(X_test)
# 4.
accuracy_score(y_test, y_pred)
2,西瓜
from sklearn.ensemble import StackingClassifier
# 1.
model = StackingClassifier(
estimators=[('LR', LogisticRegression(max_iter=1000)), ('NB', GaussianNB())],
final_estimator=DecisionTreeClassifier(),
)
# 2.
model.fit(watermelon[['敲声','纹理']], watermelon['好瓜'])
# 3.
y_pred = model.predict(watermelon[['敲声','纹理']])
# 4.
accuracy_score(watermelon['好瓜'], y_pred)
2,AdaBoost推进法
自适应推进,核心思想是“前人栽树,后人乘凉”
1,红酒
from sklearn.ensemble import AdaBoostClassifier
model = AdaBoostClassifier(n_estimators=21, random_state=11)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
accuracy_score(y_test, y_pred)
2,西瓜
from sklearn.ensemble import AdaBoostClassifier
model = AdaBoostClassifier(n_estimators=10, random_state=10)
model.fit(watermelon[['敲声','纹理']], watermelon['好瓜'])
y_pred = model.predict(watermelon[['敲声','纹理']])
# 4.
accuracy_score(watermelon['好瓜'], y_pred)