You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用GridSearchCV基于准确率优化ML模型预处理的两个整数参数

用GridSearchCV优化预处理超参数pTH和pL

问题描述

我需要为机器学习模型的预处理环节找到两个最优整数值pTH和pL,这两个值用于剔除部分输入数据,优化依据是模型的准确率。我已经编写了包含完整模型流程的函数The_Function,现需基于模型准确率优化这两个预处理超参数,请问如何使用GridSearchCV实现?

原函数代码

def The_Function(pTH=0.02, pL=100 ):
    import numpy as np

    #initial values
    read_data = []
    label_data = []
    #Ues the function to get features and labels of the data
    #DS\Emirate- dataset\Train
    #DS\SAVEE , DS\EMODB
    read_data, label_data = data_collection("DS/savee", iTH = pTH, iL = pL)
    read_data = shuffle(read_data)
    read_data = shuffle(read_data)
    
    # #--------------------------------------------------------------------Read csv from a file
    #Convert to DF
    Dataset = read_data
    Dataset = pd.DataFrame(Dataset)
    
    #--------------------------------------------------------------------Normlise the Features
    X = Dataset.loc[:,0:(Dataset.shape[1] - 2)].copy()

    #X_norm = ( X - X.min() ) / ( X.max() - X.min()) * 10
    X_norm = ( X - X.min() ) / ( X.max() - X.min())
    #X_norm =(X-X.min())/(X.max()-X.min())
    #X_norm = X_norm.fillna(0)

    for i in range(X_norm.shape[1]):
        if  math.isnan(X_norm[i].mean()) :
            #print(X_norm[i])
            #print(X_norm[i].mean())
            X_norm[i] = X_norm[i].fillna(0)
            #print(X_norm[i])
        else:
            pass
            #X_norm[i] = X_norm[i].fillna(X_norm[i].mean())

    X_norm.describe()
    
    c = Dataset.shape[1]
    Y = Dataset.loc[:,[c-1]]
    Y = Y.astype(int)
    Y[:2]

    #--------------------------------------------------------------------Updated Dataset 
    Dataset2 = X_norm
    c = Dataset.shape[1]
    Y = Dataset.loc[:,[c-1]].copy()
    Y = Y.astype(int)
    Dataset2["Y"] = Y.copy()
    Dataset2.describe()
    Dataset2[:2]
    
    X = Dataset2.loc[:,:Dataset2.shape[1]-2].copy()

    Y = np.array(Y)
    X = np.array(X)

    Y[:3]
    
    #---------------------------------------------------------------------------------------------------XY Split:
    Y = Dataset2.loc[:,"Y"].copy()
    Y = Y.astype(int)
    X = Dataset2.loc[:,0:(Dataset2.shape[1] - 2)].copy()

    #X = X[selected_mrmr[:500]]

    nft = X.shape[1]
    print(X.shape)
    #---------------------------------------------------------------------------------------------------KFold Split:
    X = np.array(X)
    Y = np.array(Y)
    import numpy as np
    from sklearn.model_selection import KFold
    kf = KFold(n_splits=10,shuffle=True, random_state = 23123)
    kf.get_n_splits(X)
    print(kf)

    spt = 0
    svm_accuracy = np.array([])


    for train_index, test_index in kf.split(X):
        spt+=1

        X_train, X_test = X[train_index], X[test_index]
        Y_train, Y_test = Y[train_index], Y[test_index]

        nft = X_train.shape[1]
        #SVM
        #from sklearn.svm import SVC,SVR,LinearSVC,LinearSVR
        from sklearn.svm import SVC
        from sklearn import svm
        from sklearn.metrics import accuracy_score

        #clf_svm = svm.SVR( kernel = 'poly' )
        clf_svm = SVC( kernel = 'poly' , decision_function_shape='ovo')
        #clf_svm = svm.SVR(kernel='poly')

        clf_svm.fit(X_train, Y_train)
        print("\n\n###################################################################################")
        print("Split =",spt)
        print("SVM Train accuracy ",nft,":",accuracy_score(Y_train, clf_svm.predict(X_train)))
        print("SVM Test accuracy ",nft,':',accuracy_score(Y_test, clf_svm.predict(X_test)))
        print(clf_svm.predict(X_test)[:5])
        svm_accuracy = np.append(svm_accuracy, accuracy_score(Y_test, clf_svm.predict(X_test)))
        print(svm_accuracy)

        #################################
        print(X.shape[1])
        print("SVM:",svm_accuracy.mean())
    return(svm_accuracy.mean())

解决方案

核心思路

GridSearchCV要求待优化的流程符合sklearn估计器接口(具备__init__、fit、score方法)。因此需要将原函数重构为自定义估计器,把pTH和pL作为超参数,让GridSearchCV自动遍历参数网格并评估每个组合的交叉验证准确率。

改造后代码

1. 自定义符合sklearn接口的模型类

import numpy as np
import pandas as pd
import math
from sklearn.base import BaseEstimator, ClassifierMixin
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score
from sklearn.model_selection import KFold
from sklearn.utils import shuffle

# 确保data_collection函数已提前定义
# def data_collection(dataset_path, iTH, iL):
#     # 你的数据加载逻辑
#     return read_data, label_data

class CustomModel(BaseEstimator, ClassifierMixin):
    def __init__(self, pTH=0.02, pL=100):
        self.pTH = pTH
        self.pL = pL
        self.clf = SVC(kernel='poly', decision_function_shape='ovo')
        self.mean_accuracy = None

    def fit(self, X=None, y=None):
        # 加载并预处理数据
        read_data, label_data = data_collection("DS/savee", iTH=self.pTH, iL=self.pL)
        read_data = shuffle(read_data)
        
        Dataset = pd.DataFrame(read_data)
        # 特征归一化
        X_features = Dataset.loc[:, 0:(Dataset.shape[1]-2)].copy()
        X_norm = (X_features - X_features.min()) / (X_features.max() - X_features.min())
        
        # 处理缺失值
        for col in X_norm.columns:
            if math.isnan(X_norm[col].mean()):
                X_norm[col] = X_norm[col].fillna(0)
        
        # 提取标签
        Y_labels = Dataset.iloc[:, -1].astype(int)
        
        # 10折交叉验证训练
        kf = KFold(n_splits=10, shuffle=True, random_state=23123)
        accuracy_scores = []
        
        for train_idx, test_idx in kf.split(X_norm):
            X_train, X_test = X_norm.iloc[train_idx], X_norm.iloc[test_idx]
            Y_train, Y_test = Y_labels.iloc[train_idx], Y_labels.iloc[test_idx]
            
            self.clf.fit(X_train, Y_train)
            test_acc = accuracy_score(Y_test, self.clf.predict(X_test))
            accuracy_scores.append(test_acc)
        
        self.mean_accuracy = np.mean(accuracy_scores)
        return self

    def score(self, X=None, y=None):
        # 返回交叉验证平均准确率,供GridSearchCV评估
        return self.mean_accuracy

2. 使用GridSearchCV进行参数搜索

from sklearn.model_selection import GridSearchCV

# 定义待搜索的参数网格(根据你的需求调整整数值范围)
param_grid = {
    'pTH': [1, 2, 3, 4, 5],  # 假设pTH需要整数,替换为你实际的候选值
    'pL': [50, 100, 150, 200, 250]
}

# 初始化模型和GridSearchCV
model = CustomModel()
# 若不需要嵌套交叉验证,设置cv=1(模型内部已做10折验证);如需更稳健评估,设置cv=5/10
grid_search = GridSearchCV(estimator=model, param_grid=param_grid, cv=1, scoring='accuracy', verbose=2)

# 执行参数搜索
grid_search.fit()

# 输出结果
print("最优参数组合:", grid_search.best_params_)
print("最优交叉验证准确率:", grid_search.best_score_)

# 查看所有参数组合的评估结果
results_df = pd.DataFrame(grid_search.cv_results_)
print(results_df[['param_pTH', 'param_pL', 'mean_test_score']])

关键说明

  • 自定义模型类继承了BaseEstimator和ClassifierMixin,完全符合sklearn接口规范,让GridSearchCV可以识别并使用
  • pTH和pL作为模型的超参数,在__init__中定义,GridSearchCV会自动遍历参数网格中的所有组合
  • fit方法包含完整的数据加载、预处理和交叉验证训练逻辑,最终计算平均准确率
  • score方法返回平均准确率,作为GridSearchCV评估参数组合的依据
  • 若pTH实际是比例值而非整数,只需调整param_grid中的候选值即可(比如[0.01, 0.02, 0.03])

内容的提问来源于stack exchange,提问作者MS_22

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 05:05:01