(机器学习算法应用篇:随机森林)
前段时间做国创项目,用到了随机森林算法,今天来总结一下相关知识以及实现过程。
1.信息,熵,信息增益:
1)信息:对机器学习中的决策树而言,如果带分类的事物集合可以划分为多个类别当中,则某个类(xi)的信息可以定义如下
2)熵:熵是用来度量不确定性的,当熵越大,X=xi的不确定性越大,反之越小。
3)信息增益:信息增益在决策树算法中是用来选择特征的指标,信息增益越大,则这个特征的选择性越好。
2.自助法(bootstrap):自助法顾名思义,即从样本自身中再生成很多可用的同等规模的新样本,从自己中产生和自己类似的,所以叫做自助,即不借助其他样本数据。
3.自集成(bagging):bagging方法将训练集分成m个新的训练集,然后在每个新训练集上构建一个模型,各自不相干,最后预测时我们将这个m个模型的结果进行整合,得到最终结果。
4.决策树(Decision Tree):决策树是用树的结构来构建分类模型,每个节点代表着一个属性,常用的决策树有ID4,C4.5,CART等,可以用信息增益,增益率,以及基尼系数等指标来衡量选取。
5.随机森林(Random Forest):简单来说,随机森林就是用bootstrap方法生成m个训练集,然后,对于每个训练集,构造一颗决策树,在节点找特征进行分裂的时候,在特征中随机抽取一部分特征,在抽到的特征中间找到最优解,应用于节点,进行分裂。随机森林的方法由于有了bagging,也就是集成的思想在,实际上相当于对于样本和特征都进行了采样(如果把训练数据看成矩阵,就像实际中常见的那样,那么就是一个行和列都进行采样的过程),所以可以避免过拟合。
1.树:如果训练集大小为N,对于每棵树而言,随机且有放回地从训练集中的抽取N个训练样本,作为该树的训练集。
问题1:为什么要随机抽样训练集?
如果不进行随机抽样,每棵树的训练集都一样,那么最终训练出的树分类结果也是完全一样的。
问题2:为什么要有放回地抽样?
如果不是有放回的抽样,那么每棵树的训练样本都是不同的,每棵树训练出来可能有很大的差异。
2.随机森林:
1)从原始训练集中使用Bootstraping方法随机有放回采样选出m个样本,共进行n_tree次采样,生成n_tree个训练集
2)对于n_tree个训练集,我们分别训练n_tree个决策树模型
3)对于单个决策树模型,假设训练样本特征的个数为n,那么每次分裂时根据信息增益/信息增益比/基尼指数选择最好的特征进行分裂
4)每棵树都一直这样分裂下去,直到该节点的所有训练样例都属于同一类。在决策树的分裂过程中不需要剪枝
5)将生成的多棵决策树组成随机森林。对于分类问题,按多棵树分类器投票决定最终分类结果;对于回归问题,由多棵树预测值的均值决定最终预测结果.
项目中用到的是随机森林预测算法,所以代码是基于预测的。
需要导入的包(py3)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
import csv
import random
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import RandomForestRegressor
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import confusion_matrix
from sklearn.metrics import classification_report
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import RandomizedSearchCV
from sklearn.metrics import mean_squared_error, explained_variance_score,mean_absolute_error,r2_score
1.数据集的划分
数据集一般划分为训练集和测试集,用到了train_test_split函数。
#数据处理,将有效的标签值提取出来,赋值给data
data = data.loc[:, ~data.columns.str.contains('Unnamed')]
#划分测试集和训练集,test_size为测试集占比
data_train,data_test=train_test_split(data,test_size=0.1,random_state=1)
2.模型参数的选择
criterion=['mae','mse']
n_estimators = [int(x) for x in np.linspace(start = 200, stop = 2000, num = 10)]
max_features = ['auto', 'sqrt']
max_depth = [int(x) for x in np.linspace(10, 100, num = 10)]
max_depth.append(None)
min_samples_split = [2, 5, 10]
min_samples_leaf = [1, 2, 4]
bootstrap = [True, False]
random_grid = {
'criterion':criterion,
'n_estimators': n_estimators,
'max_features': max_features,
'max_depth': max_depth,
'min_samples_split': min_samples_split,
'min_samples_leaf': min_samples_leaf,
'bootstrap': bootstrap}
3.构建模型
clf= RandomForestRegressor()
clf_random = RandomizedSearchCV(estimator=clf, param_distributions=random_grid,
n_iter = 50,
cv = 5, verbose=2, random_state=42, n_jobs=-1)
4.最优参数选取
clf_random.fit(X_train,y_train)
print (clf_random.best_params_)
5.模型训练、验证和评估
rf=RandomForestRegressor(criterion='mse',bootstrap=False,max_features='sqrt', max_depth=20,min_samples_split=10, n_estimators=1200,min_samples_leaf=2)
rf.fit(X_train,y_train)
y_train_pred=rf.predict(X_train)
y_test_pred=rf.predict(X_test)
print("Decision tree model evaluation -- training set:") #决策树模型评估--训练集
print('trainr^2:',rf.score(X_train,y_train))#训练r^2
print('Mean square deviation:',mean_squared_error(y_train,y_train_pred))#均方差
print('Absolute difference:',mean_absolute_error(y_train,y_train_pred))#绝对差
print('Degree of interpretation',explained_variance_score(y_train,y_train_pred))#解释度
print("Decision tree model evaluation -- Verification set:")#决策树模型评估--验证集
print('verificationr^2:',rf.score(X_test,y_test))#验证r^2
print('Mean square deviation',mean_squared_error(y_test,y_test_pred))#均方差
print('Absolute difference',mean_absolute_error(y_test,y_test_pred))#绝对差
print('Degree of interpretation',explained_variance_score(y_test,y_test_pred))#解释度
6.参数解释
1)n_estimators:森林中数的个数。
这个属性是典型的模型表现与模型效率成反比的影响因子,即便如此,你还是应该尽可能提高这个数字,以让你的模型更准确更稳定。
2)criterion :度量分裂的标准。可选值:“mse”,均方差(mean squared error);“mae”,平均绝对值误差(mean absolute error)
3)max_features :寻找最佳分裂点时考虑的属性数目。可选值,int(具体的数目),float(数目的百分比),string(“auto”, “sqrt”,“log2”).
这一属性是对单个树来设置的,通常来讲,这个值越大单棵树可以考虑的属性越多,则模型的表现就越好。但是这也不是肯定的,不过有一点是肯定的,增加这个值会导致算法运行速度变慢,所以需要我们考虑去达到一个平衡。
4)max_depth : integer或者None。数的最大深度,如果None,节点扩展直到所有叶子是纯的或者所有叶子节点包含的样例数小于min_samples_split
5)min_samples_split : 分裂内部节点需要的最少样例数。int(具体数目),float(数目的百分比)
6)min_samples_leaf :叶子节点上应有的最少样例数。int(具体数目),float(数目的百分比)。
更少的节点数使得模型更容易遭受noise data的影响,我通常设置这个值大于50,但是你需要寻找最适合你的数值。
7)max_leaf_nodes :以”最优优先方式”(best-first fashion),最优节点定义为:纯度的相对减少.如果None则不限制叶子节点个数;[float]
8)min_impurity_split : 树增长提前结束的阈值.对于当前节点,大于这个阈值将分裂,否则就看做叶子节点; [float]
9)min_impurity_decrease :一个阈值,表示一个节点分裂的条件是:如果这次分裂纯度的减少大于等于这这个值.
10)bootstrap :构建数是不是采用有放回样本的方式(bootstrap samples); [True/False]