机器学习、深度学习与人工智能

机器学习系列(八)——超参数GridSearch调节与模型优化

2019-06-10  本文已影响32人  Ice_spring

超参数

超参数与模型参数

超参数是运行算法之前需要指定的参数;
模型参数是算法运行过程中学习的参数,往往需要不断随算法运行更新

knn算法比较特殊,它没有模型参数,只有超参数,k即是超参数。
机器学习算法工程师调参需要调的是超参数,超参数影响最终的模型参数进而影响模型效果。

如何寻找好的超参数

调节参数首先要有一定的领域专业知识,其次是根据经验得来的经验数值(sklearn中算法的很多默认数值都是经验数值),最后是通过实验搜索最优超参数。

'''手写数字knn实现'''
import numpy as np
from sklearn import datasets
digits = datasets.load_digits()
x = digits.data
y = digits.target

from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.2)

from sklearn.neighbors import KNeighborsClassifier
'''超参数设定'''
knn_clf = KNeighborsClassifier(n_neighbors=3,random_state=666)
knn_clf.fit(x_train,y_train)
knn_clf.score(x_test,y_test)
out:0.966

上面是用sklearn中knn算法默认超参数进行的模型fit,下小节将通过网格搜索来寻找最优参数:

knn算法中最优的n_neighbors

寻找最优的k思想很简单,就是针对不同的k都建立一个knn分类器,看哪个k的分类准确率高,循环即可解决:

'''最优k搜索'''
best_score=0
best_k=-1
for k in range(1,11):
    
    knn_clf = KNeighborsClassifier(n_neighbors=k)
    knn_clf.fit(x_train,y_train)
    score = knn_clf.score(x_test,y_test)
    if score > best_score:
        best_k = k
        best_score = score
        
print("best_k = ",best_k)
print("best_score = ",best_score)

结果如下:


best_k

如果搜索得到的最优值在搜索范围的边界,最好进行拓展搜索,因为往往准确率是连续变化的,最优值出现在边界,则很可能在你规定的范围外面。

knn中的其它超参数

best_method = ""
best_score=0
best_k=-1
for method in ("uniform","distance"):
    for k in range(1,11):
        '''加入weight参数'''
        knn_clf = KNeighborsClassifier(n_neighbors=k,weights = method)
        knn_clf.fit(x_train,y_train)
        score = knn_clf.score(x_test,y_test)
        if score > best_score:
            best_k = k
            best_score = score
            best_method = method
print("best_method is",best_method)            
print("best_k = ",best_k)
print("best_score = ",best_score)

结果如下:


method
'''最优的明氏距离参数p搜索'''
%%time#计算运行时间
best_p = -1
best_score=0
best_k=-1
for k in range(1,11):
    for p in range(1,6):
        knn_clf = KNeighborsClassifier(n_neighbors=k,weights = "distance",p=p)
        knn_clf.fit(x_train,y_train)
        score = knn_clf.score(x_test,y_test)
        if score > best_score:
            best_k = k
            best_score = score
            best_p = p
print("best_p = ",best_p)
print("best_k = ",best_k)
print("best_score = ",best_score)

结果如下:


m_p

网格搜索GridSearch

上面我们看到,超参数之间可能出现依赖关系,如何进行一次命令就完成网格搜索呢,sklearn中可以这样实现。

GridSearch

首先定义搜索的参数列表:

'''定义搜索参数网格'''
param_grid=[
    {
        'weights':['uniform'],
        'n_neighbors':[i for i in range(1,11)]
        
    },
    {
        'weights':['distance'],
        'n_neighbors':[i for i in range(1,11)],
        'p':[i for i in range(1,6)]
    }
]

然后实例化GridSearch搜索对象并执行搜索:

'''搜索'''
knn_clf = KNeighborsClassifier()

from sklearn.model_selection import GridSearchCV
grid_search = GridSearchCV(knn_clf,param_grid)#实例化一个网格搜索对象,1指定对哪个分类器进行网格搜索,2搜索参数是什么

grid_search.fit(x_train,y_train)

搜索结果:

search_result
可以用命令给出最优分类器参数:
grid_search.best_estimator_
best_estimator
最佳准确率和对应的参数值:
accuaracy_param
可以发现即使指定了random_state,这里找到的最优参数和上面自行搜索找到的仍然不一样,这是因为网格搜索中,CV用的评价标准是一种更加复杂的方式,即交叉验证
注:不是用户传入的参数,而是根据用户传入的参数,由类计算出来的参数,名字后跟下划线,这是一种编码规范。
于是将当前分类器设置为最优分类器:
re_apply

GridSearch中的其它参数

GridSearch工作原理其实是创建多个分类器进行搜索,实际这个工作可以并行处理以加快速度,n_jobs默认为1相当于串行。如果你的计算机双核,可以传2(我的虚拟机2核),传参数-1则表示计算机所有核都用于网格并行搜索,可以用%%time测试时间,参数verbose可以在搜索过程输出一些信息,默认为2最好。

'''gridsearch中其它参数'''
grid_search = GridSearchCV(knn_clf,param_grid,n_jobs=2,verbose=2)
'''gridsearch工作原理其实是创建多个分类器进行搜索,实际这个工作可以并行处理,n_jobs默认为1是串行
   如果你的计算机双核,可以传2(我的虚拟机2核),传-1表示计算机所有核都用于网格搜索
   可以用%%time测试时间
   verbose可以在搜索过程输出一些信息
'''
grid_search.fit(x_train,y_train)

更多距离度量

不同距离度量有不同的最佳应用场景
度量metrics默认是明氏,可以根据应用场景修改为其它距离,如jaccard,pearson等。

上一篇 下一篇

猜你喜欢

热点阅读