基于决策树(Decision Tree)的bagging算法:随机森林(Random Forest)(包括具体代码)

重点先跑模型:
数据:
http://sofasofa.io/competition.php?id=1
代码:
需要修改一下文件的地址:
代码运行的时候一步一步来:

# -*- coding: utf-8 -*-
# import 常用包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# 数据完整化和数据数值化
from sklearn.preprocessing import Imputer
from sklearn.preprocessing import LabelEncoder

# 特征提取和特征选择
from sklearn.feature_selection import f_regression
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.decomposition import PCA

# 数据归一化和数据标准化
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import Normalizer

# 数据分割
from sklearn.model_selection import train_test_split
from sklearn.model_selection import KFold

# 模型构建
from sklearn.ensemble import RandomForestRegressor
import lightgbm as lgb

# 误差评估
from sklearn.metrics import mean_squared_error
from sklearn.metrics import mean_absolute_error

# 参数调节
from sklearn.model_selection import GridSearchCV

# -----------------------------------------------加载数据,数据处理,特征提取,特征选择------------------------------------------------------
# 加载数据
train = pd.read_csv('E:/dataset/reg/bike/train.csv')
test = pd.read_csv('E:/dataset/reg/bike/test.csv')
submit = pd.read_csv('E:/dataset/reg/bike/sample_submit.csv')

# ----------------------------------------------------------------------数据分割和模型使用-------------------------------------------------------------------------
predictors = ['city', 'hour', 'is_workday', 'weather', 'temp_1', 'temp_2', 'wind']
X_train, X_test, Y_train, Y_test = train_test_split(train[predictors], train["y"], test_size=0.2)
model = RandomForestRegressor(
    n_estimators=240, criterion='mse', max_depth=None, min_samples_split=10, min_samples_leaf=3,
    min_weight_fraction_leaf=0.0,
    max_features=6, max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, bootstrap=True,
    oob_score=True, n_jobs=1, random_state=None, verbose=0, warm_start=False)
# model = lgb.LGBMRegressor(max_depth=6, num_leaves=10, bagging_fraction=1, bagging_freq=0, max_bin=255,
# feature_fraction = 1, learning_rate = 0.1, min_sum_hessian_in_leaf = 10, lambda_l1 = 0, lambda_l2 = 0,
# min_split_gain = 0, n_estimators = 500)
# model=xgb.XGBRegressor()
model.fit(X_train, Y_train)
accuracy1 = model.score(X_train, Y_train)
print("公共自行车使用量训练数据的准确性:\n", accuracy1)
accuracy2 = model.score(X_test, Y_test)
Y_predict = model.predict(X_test)
print("公共自行车使用量测试数据的准确性:\n", accuracy2)
error = mean_absolute_error(Y_predict, Y_test)
print("公共自行车使用量的RMSE\n", error)
print("袋外分数", model.oob_score_)

# -----------------------------------------------------------模型预测--------------------------------------------------------------
# 对预测数据进行与训练数据相同的预处理操作
print("前10行数据:\n", test.head(10))
print("数据的统计分析:\n", test.describe())
print("数据的情况:\n", test.info())
test['y'] = model.predict(test[predictors])
# 输出预测值
submit['y'] = np.array(test['y'])
submit.to_csv('E:/dataset/reg/bike/sample_submit.csv', index=False)
"""
# ----------------------------------------------------调参过程-------------------------------------------------------------
# 调节的参数有:n_estimators、min_samples_split和min_samples_leaf、'max_features'
if __name__ == '__main__':
    # 加载数据
    train = pd.read_csv('E:/dataset/reg/bike/train.csv')
    predictors = ['city', 'hour', 'is_workday', 'weather', 'temp_1', 'temp_2', 'wind']
    cv_params = {'max_features': range(3, 8)}

    other_params = {'n_estimators': 240, 'criterion': 'mse', 'max_depth': None, 'min_samples_split': 2,
                    'min_samples_leaf': 10, 'min_weight_fraction_leaf': 0.0, 'max_features': None,
                    'max_leaf_nodes': None, 'min_impurity_decrease': 0.0, 'min_impurity_split': None, 'bootstrap': True,
                    'oob_score': True, 'n_jobs': 1, 'random_state': None, 'verbose': 0, 'warm_start': False}

    other_params = {'n_estimators': 240, 'criterion': 'mse', 'max_depth': None, 'min_samples_split': 10,
                    'min_samples_leaf': 3, 'min_weight_fraction_leaf': 0.0,
                    'max_leaf_nodes': None, 'min_impurity_decrease': 0.0, 'min_impurity_split': None, 'bootstrap': True,
                    'oob_score': True, 'n_jobs': 1, 'random_state': None, 'verbose': 0, 'warm_start': False}
    model = RandomForestRegressor(**other_params)
    optimized_GBM = GridSearchCV(estimator=model, param_grid=cv_params, scoring='r2', cv=5, verbose=1, n_jobs=4)
    optimized_GBM.fit(train[predictors], train['y'])
    print('每轮迭代运行结果:{0}'.format(optimized_GBM.grid_scores_))
    print('参数的最佳取值:{0}'.format(optimized_GBM.best_params_))
    print('最佳模型得分:{0}'.format(optimized_GBM.best_score_))

1.随机森林

什么是随机森林?
随机森林被认为是所有数据科学问题的灵丹妙药 。有趣的是,当你想不出任何算法(无论情况如何)时,使用随机森林!
随机森林是一种多功能机器学习方法,能够执行回归和分类任务。它还采用降维方法,处理缺失值,异常值和数据探索的其他基本步骤,并且做得相当不错。它是一种集成学习方法,其中一组弱模型组合在一起形成一个强大的模型。

它是如何工作的?
基于Bagging的随机森林(Random Forest)是决策树集合。在随机森林中,我们收集了许多决策树(被称为“森林”)。为了根据属性对新对象进行分类,每个树都给出分类,然后对这些树的结果进行“投票”,最终选择投票得数最多的哪一类别。
每棵树按以下方法构建:
如果取 N 例训练样本作为来训练每棵树,则随机抽取1例样本,再有放回地进行下一次抽样。每次抽样得到的 N 个样本作为一棵树的训练数据。
如果存在 M 个输入变量(特征值),则指定一个数字 m(远小于 M),使得在每个节点处,随机地从 M 中选择 m 个特征,并使用这些m 个特征来对节点进行最佳分割。在森林生长过程中,m 的值保持不变。
每棵树都尽可能自由生长。没有修剪。

随机森林的优势
该算法可以解决两类问题,即分类和回归,并在两个方面进行了不错的估计。
最令我兴奋的随机森林的好处之一是处理具有更高维度的大数据集的能力。它可以处理数千个输入变量并识别最重要的变量,因此它被视为降维方法之一。此外,模型输出变量的重要性, 这可以是一个非常方便的功能(在一些随机数据集上)。
它有一种估算缺失数据的有效方法,并在大部分数据丢失时保持准确性。
它具有平衡类不平衡的数据集中的错误的方法。
上述功能可以扩展到未标记的数据,从而导致无监督的聚类,数据视图和异常值检测。
随机森林涉及输入数据的采样,替换称为自举采样。这里有三分之一的数据不用于培训,可用于测试。这些被称为袋外样品。对这些袋外样品的估计误差称为 袋外误差。通过Out of bag进行误差估计的研究,证明了袋外估计与使用与训练集相同大小的测试集一样准确。因此,使用out-of-bag误差估计消除了对预留测试集的需要。

随机森林的缺点
它确实在分类方面做得很好但不如回归问题好,因为它没有给出精确的连续性预测。在回归的情况下,它不会超出训练数据的范围进行预测,并且它们可能过度拟合特别嘈杂的数据集。
随机森林可以感觉像统计建模者的黑盒子方法 - 你几乎无法控制模型的作用。你最多可以尝试不同的参数和随机种子!

随机森林框架参数:(bagging)
(1)n_estimators:
也就是弱学习器的最大迭代次数,或者说最大的弱学习器的个数。一般来说n_estimators太小,容易过拟合,n_estimators太大,又容易欠拟合,一般选择一个适中的数值。默认是100。在实际调参的过程中,我们常常将n_estimators和下面介绍的参数learning_rate一起考虑。
(2)oob_score:
即是否采用袋外样本来评估模型的好坏。默认识False。个人推荐设置为True,因为袋外分数反应了一个模型拟合后的泛化能力。
(3)criterion:
即CART树做划分时对特征的评价标准。分类模型和回归模型的损失函数是不一样的。分类RF对应的CART分类树默认是基尼系数gini,另一个可选择的标准是entropy。回归RF对应的CART回归树默认是均方差mse,另一个可以选择的标准是绝对值差mae。一般来说选择默认的标准就已经很好的。

随机森林决策树参数
RF的决策树参数,它要调参的参数基本和GBDT相同,如下:
(1)max_features
决策树划分时考虑的最大特征数max_features:可以使用很多种类型的值,默认述的其他取值来控制划分时考虑的最大特征数,以控制决策树的生成时间。 是”None”,意味着划分时考虑所有的特征数;如果是”log2”意味着划分时最多考虑log2(n_features)个特征;如果是”sqrt”或者”auto”意味着划分时最多考虑sqrt(n_features) 个特征。如果是整数,代表考虑的特征绝对数。如果是浮点数,代表考虑特征百分比,即考虑(百分比xN)取整后的特征数。其中N为样本总特征数。一般来说,如果样本特征数不多,比如小于50,我们用默认的”None”就可以了,如果特征数非常多,我们可以灵活使用刚才描
参数效果:max_features 值越大,模型学习能学习到的信息越多,越容易过拟合。

(2)max_depth
决策树最大深度max_depth, 默认可以不输入,如果不输入的话,决策树在建立子树的时候不会限制子树的深度。一般来说,数据少或者特征少的时候可以不管这个值。如果模型样本量多,特征也多的情况下,推荐限制这个最大深度,具体的取值取决于数据的分布。常用的可以取值10-100之间。
参数效果:值越大,决策树越复杂,越容易过拟合。

(3)min_samples_split
内部节点再划分所需最小样本数min_samples_split: 这个值限制了子树继续划分的条件,如果某节点的样本数少于min_samples_split,则不会继续再尝试选择最优特征来进行划分。 默认是2.如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。
参数效果:值越大,决策树越简单,越不容易过拟合。

(4)min_samples_leaf
叶子节点最少样本数min_samples_leaf: 这个值限制了叶子节点最少的样本数,如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝。 默认是1,可以输入最少的样本数的整数,或者最少样本数占样本总数的百分比。如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。
参数效果:值越大,叶子节点越容易被被剪枝,决策树越简单,越不容易过拟合。

(5)min_weight_fraction_leaf
叶子节点最小的样本权重和min_weight_fraction_leaf:这个值限制了叶子节点所有样本权重和的最小值,如果小于这个值,则会和兄弟节点一起被剪枝。 默认是0,就是不考虑权重问题。一般来说,如果我们有较多样本有缺失值,或者分类树样本的分布类别偏差很大,就会引入样本权重,这时我们就要注意这个值了。

(6)max_leaf_nodes
最大叶子节点数max_leaf_nodes: 通过限制最大叶子节点数,可以防止过拟合,默认是”None”,即不限制最大的叶子节点数。如果加了限制,算法会建立在最大叶子节点数内最优的决策树。如果特征不多,可以不考虑这个值,但是如果特征分成多的话,可以加以限制,具体的值可以通过交叉验证得到。
参数效果:值越小,叶子节点个数越少,可以防止过拟合。

(7)min_impurity_split
节点划分最小不纯度min_impurity_split: 这个值限制了决策树的增长,如果某节点的不纯度(基于基尼系数,均方差)小于这个阈值,则该节点不再生成子节点。即为叶子节点 。一般不推荐改动默认值1e-7。

调参的过程
1、先用默认参数看预测结果
2、然后用gridsearchcv探索n_estimators的最佳值。
3、然后确定n_estimators,据此再搜索另外两个参数:再对内部节点再划分所需最小样本数min_samples_split和叶子节点最少样本数min_samples_leaf一起调参:
param_test3={‘min_samples_split’:range(80,150,20), ‘min_samples_leaf’:range(10,60,10)}
4、最后我们再对最大特征数max_features做调参: param_test4= {‘max_features’:range(3,11,2)}
5、最后用得到的参数再次带入模型,得到结果。

你可能感兴趣的:(机器学习)