大家好,我是小寒。
我们都知道在训练机器学习模型时,都需要人工指定一组超参数。
最好的超参数是「主观的」,并且对于每个数据集都不同。
有两种流行的技术用于执行超参数优化——「网格搜索和随机搜索」
网格搜索
然后选择具有「最佳性能的模型」
随机搜索
该技术从超参数网格中「随机采样」,而不是进行详尽的搜索。
我们可以指定随机搜索在返回最佳模型之前应该「尝试的总运行次数」
使用网格搜索和随机搜索优化随机森林分类器
1、加载数据集
import pandas as pd
df = pd.read_csv("../../data/wine/winequalityN.csv")
df.head()

2、数据预处理
目标变量 quality 包含 1 到 10 之间的值。
import numpy as np
df['target'] = np.where(df['quality']>5, 1, 0)
删除缺失值
df.dropna(inplace=True)
df.isnull().sum()
type 0
fixed acidity 0
volatile acidity 0
citric acid 0
residual sugar 0
chlorides 0
free sulfur dioxide 0
total sulfur dioxide 0
density 0
pH 0
sulphates 0
alcohol 0
quality 0
target 0
dtype: int64
让我们拆分此数据集中的因变量和自变量:
df2 = df.drop(['quality','type'],axis=1)
X = df2.drop(['target'],axis=1)
y = df2[['target']]
df2.head()

3、构建模型
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier()
4、使用 Scikit-Learn 实现网格搜索
「定义超参数空间」
我们现在将尝试调整该模型的「以下一组超参数:」
“Max_depth”:这个超参数表示随机森林模型中每棵树的最大深度。更深的树表现良好,并捕获有关训练数据的大量信息,但不能很好的泛化到测试数据。「默认情况下,该值在 Scikit-Learn 库中设置为 “None”,这意味着树完全展开。」
“Max_features”:随机森林模型允许在每次拆分时尝试的最大特征数。默认情况下,在 Scikit-Learn 中,此值设置为数据集中变量总数的平方根。
“N_estimators”:随机森林中决策树的数量。Scikit-Learn 中的默认估计器数量为 10。
“Min_samples_leaf”:每棵树的叶节点所需的最小样本数。Scikit-Learn 中的默认值为 1。
“Min_samples_split”:拆分每棵树的内部节点所需的最小样本数。Scikit-Learn 中的默认值为 2。
grid_space={ 'max_depth':[3,5,10,None],
'n_estimators':[10,100,200],
'max_features':[3,5,7],
'min_samples_leaf':[1,2,3],
'min_samples_split':[2,3]
}
「运行网格搜索」
现在,我们需要执行搜索,以找到模型的最佳超参数组合:
from sklearn.model_selection import GridSearchCV
grid = GridSearchCV(rf,param_grid=grid_space,cv=3,scoring='accuracy')
model_grid = grid.fit(X,y)
「评估模型结果」
最后,让我们打印出最佳模型精度,以及产生这个分数的一组超参数:
print('Best hyperparameters are: '+str(model_grid.best_params_))
print('Best score is: '+str(model_grid.best_score_))
Best hyperparameters are: {'max_depth': 3, 'max_features': 7, 'min_samples_leaf': 3, 'min_samples_split': 2, 'n_estimators': 10}
Best score is: 0.726290769309208
最佳模型的准确度得分约为 0.73。
5:使用 Scikit-Learn 实现随机搜索
「定义超参数空间」
现在,让我们「定义超参数空间来实现随机搜索。」
这个参数空间可以有比我们为网格搜索构建的更大范围的值,因为随机搜索「不会尝试超参数的每一个组合。」
from scipy.stats import randint
rs_space={'max_depth':list(np.arange(10, 100, step=10)) + [None],
'n_estimators':np.arange(10, 500, step=50),
'max_features':randint(1,7),
'criterion':['gini','entropy'],
'min_samples_leaf':randint(1,4),
'min_samples_split':np.arange(2, 10, step=2)
}
「运行随机搜索」
你可以尝试不同的迭代次数以看看「哪一个能给你最佳结果。」
请记住,大量迭代会带来更好的性能,但很耗时。
from sklearn.model_selection import RandomizedSearchCV
rf = RandomForestClassifier()
rf_random = RandomizedSearchCV(rf, rs_space, n_iter=500, scoring='accuracy', n_jobs=-1, cv=3)
model_random = rf_random.fit(X,y)
「评估模型结果」
print('最佳超参数是:'+str(model_random.best_params_))
print('最好成绩是:'+str(model_random.best_score_))
最佳超参数是:{'criterion': 'entropy', 'max_depth': 20, 'max_features': 5, 'min_samples_leaf': 3, 'min_samples_split': 4, 'n_estimators': 60}
最好成绩是:0.718243078759207
构建的所有模型的最高精度为 0.72。
「观察网格搜索和随机搜索在数据集上的表现都相当好。」
网格搜索与随机搜索如何选择?
如果你已经拥有可以很好地执行的「已知超参数值的大致范围,请使用网格搜索。」确保你的参数空间很小,因为网格搜索可能非常耗时。 如果你还不知道在模型上表现良好的参数,请对广泛的值使用随机搜索。随机搜索比网格搜索要快,并且在参数空间较大时应始终使用。 同时使用随机搜索和网格搜索以获得最佳结果也是一个好主意。
最后
「如果需要完整代码和数据集,可以加我微信: algo_code」
「进群方式:加我微信,备注 “python”」

往期回顾







如果对本文有疑问可以加作者微信直接交流。进技术交流群的可以拉你进群。





