2、机器学习中的调参:随机搜索和网格搜索

机器学习中的调参

前言

超参数调优是机器学习中的重要一环,拿随机森林算法而言,树的个数,数的深度,剪枝参数等等需要找到最优的参数组合,超参数较少时,我们可以采用for循环遍历所有参数的可能组合,但参数很多时,最优参数的搜寻将会变得困难,本文介绍了常用的调参方法随机搜索和网格搜索,后续如果学到还会更新其他调参算法。其中网格搜索法和随机搜索法采用的是sklearn中的GridSearchCV类和RandomizedSearchCV类,所用实例的数据集点击这下载,数据集为爱荷华州住房数据集,为了更好的理解,本文选用超参数很多的随机森林算法作为实例。

1、随机搜索

在参数很多时,一般先使用随机搜索缩小参数搜索空间。
第一步:导入相关库

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import train_test_split

第二步:对数据集进行分析与处理
①导入训练文件和测试文件并查看

train_X = pd.read_csv('train.csv')
train_X.info()

在这里插入图片描述

test_X = pd.read_csv('test.csv')
test_X.info()

在这里插入图片描述
对比查看可知,最终的预测结果列是ScalePrice。同时我们还可以知道,特征中包括int64、object、float64这三种数值类型,且包含缺失值。因此需要进行处理。
②处理缺失值
提取三种不同数值类型的特征数据,填补确实值之后在合并,对于缺失值较多的,直接删除即可。

# 删除缺失值太多的无用特征列
train_X = train_X.drop(['MiscVal','Fence','PoolQC','FireplaceQu',
              'Alley','MiscFeature'],axis=1)
test_X = test_X.drop(['MiscVal','Fence','PoolQC','FireplaceQu',
              'Alley','MiscFeature'],axis=1)

按照不同的数值类型对训练集和测试集进行缺失值填补:

# 提取object类型
train_X_copy = train_X.copy()
test_X_copy = test_X.copy()
Object_feature_train = train_X_copy.select_dtypes(include='object')
Object_feature_test = test_X.select_dtypes(include='object')


# 对object类型进行缺失值填补和数值类型转换
from sklearn.preprocessing import OrdinalEncoder
from sklearn.impute import SimpleImputer
imputer = SimpleImputer(strategy="most_frequent")
Object_feature = imputer.fit_transform(Object_feature_train)
Object_feature_test = imputer.fit_transform(Object_feature_test)
Object_feature_train = OrdinalEncoder().fit_transform(Object_feature)
Object_feature_test = OrdinalEncoder().fit_transform(Object_feature_test)
Object_feature_train
Object_feature_test

显示结果如下:
在这里插入图片描述

# 对int64和float类型的数值进行提取和处理
Number_feature_train = train_X.select_dtypes(include="number").drop("SalePrice", axis=1)
Number_feature_test = test_X.select_dtypes(include='number')
Number_feature_train
# 单独提取出目标变量y
y = train_X.SalePrice
y
# 对int64和float类型数值进行缺失值填补
imputer = SimpleImputer(strategy="mean")
Number_feature_train = imputer.fit_transform(Number_feature_train)
Number_feature_test = imputer.fit_transform(Number_feature_test)
Number_feature_train

③对处理后的object、int64等不同类型的数值特征进行合并

X_train = np.hstack((Object_feature_train,Number_feature_train))
X_test = np.hstack((Object_feature_test,Number_feature_test))
X_train

显示结果如下:
在这里插入图片描述
④对矩阵X_train和X_test以及目标y进行标准化操作

# 标准化操作
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit_transform(X_train)
scaler.fit_transform(X_test)
X_train

显示结果如下:
在这里插入图片描述

y = (y - y.min(axis=0)) / (y.max(axis=0) - y.min(axis=0))
y

显示结果如下:
在这里插入图片描述
第三步:不使用调参算法的初步实现

from sklearn.ensemble import RandomForestRegressor
X_train, X_test, y_train, y_test = train_test_split(X_train, y, test_size=0.3)
RFR = RandomForestRegressor().fit(X_train,y_train)
print(f"R2 for training set: {RFR.score(X_train, y_train)}")
print(f"R2 for training set: {RFR.score(X_test, y_test)}")

训练结果如下:
在这里插入图片描述
可以看到,在不进行调参时,模型训练集评分为0.979,测试集上评分仅为0.847,出现过拟合。
第四步:参数调节
一般来说,

# 查看当前超参数,可以看到RFR有18个超参数,但不会调节所有的
RFR.get_params()

显示结果如下:
在这里插入图片描述

'''
使用Scikit-learn提供的RandomizedSearchCV类实现随机搜索。他需要两个参数来建立:
一个估计器和超参数的可能值集,也叫参数网络或空间
'''
n_estimators = np.arange(100, 2000, step=100)
max_features = ["auto", "sqrt", "log2"]
max_depth = list(np.arange(10, 100, step=10)) + [None]
min_samples_split = np.arange(2, 10, step=2)
min_samples_leaf = [1, 2, 4]
bootstrap = [True, False]
param_grid = {
    "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,
}
param_grid

运行结果如下:
在这里插入图片描述

from sklearn.model_selection import RandomizedSearchCV
import time
start = time.clock()
forest = RandomForestRegressor()

random_cv = RandomizedSearchCV(
    forest, param_grid, n_iter=100, cv=3, scoring="r2", n_jobs=-1
)

_ = random_cv.fit(train_X,train_y)
elapsed = (time.clock()-start)
print(time.clock()-start)
print('Best params:\n')
print(random_cv.best_params_)

由此我们可以得到一下结论:
在这里插入图片描述
我们已经利用随机搜索的方法确定了最优参数的可能存在范围,下面我们还可以用网格搜索进一步精确查找合适的参数。
小结: 在上面的整个流程中,我们没有进行特征筛选,特征筛选的方法也有很多,以后我也会单独出一篇博客介绍一下常见的特征筛选方法。

2、 网格搜索

网格搜索法是指定参数值的一种穷举搜索方法,通过将估计函数的参数通过交叉验证的方法进行优化来得到最优的学习算法。也就是说,将各个参数可能的取值进行排列组合,列出所有可能的组合结果生成“网格”。sklearn中用GridSearchCV类来实现。一般参数很多时可以用在随机搜索之后的精确查找。继续接着上面的随机森林算法继续:

from sklearn.model_selection import GridSearchCV
param_grid = [
        {
            'n_estimators': [1450,1475,1500,1525,1550],
            'min_samples_split':[2,3],
            'min_samples_leaf':[2,3]
        }
]

RFR_search = RandomForestRegressor(
                max_features = 'sqrt'
                ,max_depth = 90
                ,bootstrap = False
)
grid_search = GridSearchCV(RFR_search,param_grid,cv=3,scoring='r2')
grid_search.fit(train_X,train_y)
grid_search.best_params_

返回结果为:
在这里插入图片描述
至此,我们所有的参数都已经调整完毕,下面看下这些参数的效果:

RFR = RandomForestRegressor(
                n_estimators = 1550
                ,min_samples_split = 3
                ,min_samples_leaf = 2
                ,max_features = 'sqrt'
                ,max_depth = 90
                ,bootstrap = False
)
rfr = RFR.fit(train_X,train_y)
print(f"R2 for training set: {rfr.score(test_X, test_y)}")

返回结果为:
在这里插入图片描述
可以看到,在测试集上的分数由0.84提升到了0.87。

:GridSearchCV的常用方法和属性:
① grid.fit(X) :运行网格搜索。
② grid_scores_ :给出不同参数情况下的评价结果。
③ predict(X) : 使用找到的最佳参数在估计器上调用预测。
④ best_params_ :描述了已取得最佳结果的参数的组合。
⑤ best_score_ :提供优化过程期间观察到的最好的评分。
⑥ cv_results_ :具体用法模型不同参数下交叉验证的结果。

  • 6
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

steelDK

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值