如何用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
相关产品推荐
相关产品推荐

