机器学习-一篇入门

【方法】一篇入门之-K-Fold交叉验证与参数网格搜索

作者 : 老饼 发表日期 : 2022-06-27 22:48:14 更新日期 : 2024-10-06 06:43:57
本站原创文章,转载请说明来自《老饼讲解-机器学习》www.bbbdata.com



超参数网格搜索一般与K-Fold结合使用,是机器学习中一种常用于参数调优的方法

本文讲解超参数网格搜索是什么,以及K-Fold的流程,并展示超参数网格搜索与K-Fold的使用示例

通过本文,可以快速了解超参数网格搜索与K-Fold是什么,如何使用它们来对模型进行超参数调优




    01. 超参数网格搜索与K-Fold交叉验证    



本节讲解什么是参数网格搜索,什么是K-Fold交叉验证,以及K-Fold交叉验证的流程





    超参数网格搜索与K-Fold是什么    


超参数网格搜索(Param Grid Serch)是机器学习中对模型超参数进行调优的常用一种方法
 简单来说,网格搜索就是每个超参数都设置几个要尝试的值,然后历遍所有超参数的组合 
最后,对比各组超参数的建模效果,哪组超参数的建模结果最好,就用哪组超参数来建模

 超参数网格搜索与K-fold交叉验证法
由于模型的训练往往有一定的随机性,直接使用模型效果来评估超参数效果往往不够稳定
所以,超参数网格搜索一般使用K-Fold交叉验证法来评估模型超参数的效果,它更为平稳





      K-Fold交叉验证     


K-Fold又称为K折交叉验证法,K-Fold交叉验证方法如下:
 k-fold交叉验证法是什么
每个模型以其中一份数据作为测试数据,其余作为训练数据,再计算该份数据的预测结果
最后综合K个模型就得到K份测试数据(即整体数据)的预测结果,进而评估模型的预测效果
K-Fold的算法流程 
对于要评估的超参数,K-Fold按如下方法评估超参数的建模效果
 K-Fold交叉验证算法流程图
1. 将数据划分为K份                                                          
 K根据数据量来具体设置,一般设为5或10           
2. 循环:i=1,2,3...K                                                          
        (1)将第i份数据作为测试集,其余数据作为训练集训练模型
(2)记录当前模型的测试误差                      

3. 计算K份数据的平均测试误差                                         







    02. K-Fold交叉验证法-使用示例    




本节展示如何在网格扫描超参数时,使用K-Fold交叉验证法来评估模型效果





     调用sklearn来实现K-Fold参数搜索    


在sklearn中可以调用GridSearchCV进行参数网格搜索,它同时提供了K-Fold功能
下面我们用K-Fold与参数网格搜索优化决策树模型的超参数criterion、max_depth
 具体代码示例如下:
from sklearn.datasets import load_iris
from sklearn.model_selection import GridSearchCV
from sklearn import metrics 
from sklearn import tree
import pandas as pd
 
#----------------数据准备----------------------------
iris = load_iris()                                                        # 加载数据
X = iris.data                                                             # 用iris.data作为X
y = iris.target                                                           # 用iris.target作为y

# --------使用网格搜索进行超参数调优------------------
clf = tree.DecisionTreeClassifier()                                       # 初始化模型
param_grid = {'criterion': ['gini','entropy'],'max_depth': [3,4,5,None]}  # 设置要扫描的参数
def err(y_true, y_pred):                                                  # 定义误差的计算方法
    return (y_true==y_pred).mean()
# 初始化网格扫描
grid_search = GridSearchCV(clf                                            # 模型
                           ,param_grid                                    # 参数网格
                           ,cv = 5                                        # cv=5代表用5折交叉验证法
                           ,scoring = metrics.make_scorer(err))           # 这里指定了模型的评估函数
grid_search.fit(X, y)                                                     # 进行网格扫描
rs = pd.DataFrame(grid_search.cv_results_['params'])                      # 提取扫描的参数        
rs['score'] =grid_search.cv_results_['mean_test_score']                   # 拼接参数的评估结果            
print(rs)                                                                 # 打印结果
运行结果如下:
 K-Fold代码示例运行结果 
结果中展示了criterion、max_depth不同取值时,决策树模型的评估结果
根据上表,我们可以选择出合适的criterion、max_depth作为最终建模时所使用的超参数





     自实现K-Fold法交叉验证     


下面展示如何不调用sklearn的函数包,自行实现网格搜索与K-Fold交叉验证
我们仍然以优化决策树模型参数criterion、max_depth为例,实现K-Fold与网格搜索的应用
具体代码如下:
from sklearn.datasets import load_iris
from sklearn import tree
import pandas as pd
import numpy as np
#----------------数据准备----------------------------
iris = load_iris()                                                                             # 加载数据
X = iris.data                                                                                  # 用iris.data作为X
y = iris.target                                                                                # 用iris.target作为y
k = 5                                                                                          # 数据分割的份数k
#--------------将数据分割为k份----------------------																		    
rand_idx  = np.random.choice(len(y), size=len(y), replace=False)                               # 打乱数据索引
data_len  = int(len(y)/k)                                                                      # 每份数据的大小
start_idx = [i*data_len for i in range(k)]                                                     # 每份数据的起始位置
end_idx   =  [(i+1)*data_len for i in range(k)]                                                # 每份数据的结束位置
end_idx[-1] = len(y)                                                                           # 修正最后一份数据的结束位置
																					           
#---------------超参数网络搜索----------------------                          
criterion_list = ['gini','entropy']                                                            # 超参数criterion要扫描的值
max_depth_list = [3,4,5,None]                                                                  # 超参数max_depth要扫描的值
result = pd.DataFrame(columns=['criterion','max_depth','acc'])                                 # 初始化结果表
for criterion in criterion_list:                                                               # 历遍超参数criterion
    for max_depth in max_depth_list:                                                           # 历遍超参数max_depth
        y_pred = np.array([])                                                                  # 初始化预测结果
        for i in range(k):                                                                     # 逐份数据作为预测数据
            train_idx = np.concatenate((rand_idx[0:start_idx[i]],rand_idx[end_idx[i]:]))       # 本次训练数据的索引
            test_idx  = rand_idx[start_idx[i]:end_idx[i]]                                      # 本次测试数据的索引
            clf       = tree.DecisionTreeClassifier(criterion=criterion,max_depth=max_depth)   # 用当前超参数初始化树模型
            clf       = clf.fit(X[train_idx,:], y[train_idx])                                  # 用训练数据训练决策树
            y_pred    = np.concatenate((y_pred,clf.predict(X[test_idx,:])))                    # 预测测试数据的类别
        acc    = (y_pred==y[rand_idx]).mean()                                                  # 计算准确率
        result_dict = {'criterion':criterion,'max_depth':max_depth,'acc':acc}                  # 本次的模型效果
        result = result.append(result_dict, ignore_index=True)                                 # 记录本次模型效果
print(result)                                                                                  # 打印最终的结果
        
运行结果如下:
 自实现K-Fold代码的运行结果 
结果中展示了criterion、max_depth不同取值时,模型的准确率acc
根据上表,我们可以选择出合适的criterion、max_depth作为最终建模时所使用的超参数









 End 








联系老饼