目录

GridSearch网格搜索调参

GridSearch(网格搜索)调参

GridSearch(网格搜索)调参

Author: Xin Pan

Date: 2020.01.01


GridSearch

是模型调参的一个常用方法。使用穷举的思路,将需要调整的参数的所有组合罗列出来,每个参数组合训练一个模型得到一个精度。将参数组合的数量(如产生10种参数组合)作为X轴,将需要调整的参数和精度(如调整学习率=(1,2,3),隐层神经元数量=(128,256,512))作为Y轴。利用这些信息可以画一个表格,正好组成了一个个的网格,因此叫做网格搜索。

看了网上一位朋友写的博客(见文末链接)感觉收获不少,清晰地理解了这个方法的实践过程。但是可能实践比较久远的原因,原始博客里的程序和数据都出现了问题。我重新更改了,方便需要的朋友。

GridSearch实践

数据集来自 ,但是本文使用的数据集自己更改过。我发现原始的数据集不能用因为缺少字段。

使用的编程语言是Python3.5

from sklearn.naive_bayes import GaussianNB
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import AdaBoostClassifier
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import make_scorer, fbeta_score, accuracy_score
from sklearn.model_selection import GridSearchCV, KFold
from matplotlib import pyplot as plt

data = pd.read_csv("adult.data")
# print(data.head(n=1))
income_raw = data['income']
features_raw = data.drop('income', axis=1)
plt.xlabel("X")
plt.ylabel("Y")
len = len(features_raw)
x = np.linspace(0, len, len)
pcg = plt.plot(x, features_raw["capital-gain"])
pcl = plt.plot(x, features_raw["capital-loss"])
l1 = plt.legend([pcg, pcl], ["capital-gain", "capital-loss"], loc='upper left')
plt.gca().add_artist(l1)
plt.show()

# 因为原始数据中的,capital-gain 和 capital-loss的倾斜度非常高,所以要是用对数转换。
skewed = ['capital-gain', 'capital-loss']
features_raw[skewed] = data[skewed].apply(lambda x: np.log(x + 1))

pcgl = plt.plot(x, features_raw["capital-gain"])
pcll = plt.plot(x, features_raw["capital-loss"])
l2 = plt.legend(
    [pcgl, pcll], ["capital-gain", "capital-loss"], loc='upper left')
plt.gca().add_artist(l2)
plt.show()

scaler = MinMaxScaler()
numerical = [
    'age', 'education-num', 'capital-gain', 'capital-loss', 'hours-per-week'
]
features_raw[numerical] = scaler.fit_transform(data[numerical])
pcgs = plt.plot(x, features_raw["capital-gain"])
pcls = plt.plot(x, features_raw["capital-loss"])
l3 = plt.legend(
    [pcgs, pcls], ["capital-gain", "capital-loss"], loc='upper left')
plt.gca().add_artist(l3)
plt.show()

features = pd.get_dummies(features_raw)
income = income_raw.replace(['>50K', ['<=50K']], [1, 0])
X_train, X_test, y_train, y_test = train_test_split(
    features, income, test_size=0.2, random_state=0)

# Adaboost
clf_Ada = AdaBoostClassifier(random_state=0)

# 决策树
clf_Tree = DecisionTreeClassifier(random_state=0)

# KNN
clf_KNN = KNeighborsClassifier()

# SVM
clf_svm = SVC(random_state=0)

# Logistic
clf_log = LogisticRegression(random_state=0)

# 随机森林
clf_forest = RandomForestClassifier(random_state=0)

# GBDT
clf_gbdt = GradientBoostingClassifier(random_state=0)

# GaussianNB
clf_NB = GaussianNB()

scorer = make_scorer(accuracy_score)

# 参数调优

kfold = KFold(n_splits=10)
# 决策树
parameter_tree = {'max_depth': range(1, 10)}
grid = GridSearchCV(clf_Tree, parameter_tree, scorer, cv=kfold)
grid = grid.fit(X_train, y_train)

print("best score: {}".format(grid.best_score_))
print(pd.DataFrame(grid.cv_results_).T)

在使用的时候请将程序文件和数据(adult.data)放在同一目录中。像这样

https://i-blog.csdnimg.cn/blog_migrate/771643f5c7d515e8592e89023639bd6f.png

额外内容

代码的32行对 capital-gain , capital-loss 施加了一个log变换,一开始我不明白是为什么。我当时觉得是要削弱这两个值或者说这两个变量对应values取值范围差异大对于模型的影响,可到底这么做了之后会有什么效果我自己并不清楚。于是我用图给了自己解释。

https://i-blog.csdnimg.cn/blog_migrate/24a879b936a807f56d9db8e919556ec7.png

上图是capital-gain(lanse)和capital-loss(黄色)直接作为直方图显式的结果,可以看到它们的取值范围相差非常大,这对于模型训练影响是很大的。那么对于它们进行了log计算之后得到的结果如下图:

https://i-blog.csdnimg.cn/blog_migrate/7f1c731655bd15abf7d026c02f49a17f.png

从图里看到它们之间的数值范围差异被明显缩短了,但是不同的特征之间还是有取值范围差异。为了更好的进行模型的训练,原文作者在此基础之上施加了一个归一化处理,这时capital-gain和capital-loss之间的差异,以及它们和别的参数之间的差异就都限制在了0-1之间了。

https://i-blog.csdnimg.cn/blog_migrate/9c9caf7b8a6b73dd971d669d29fb4054.png

Reference