cómo ajustar los parámetros de la función del kernel personalizada con canalización en scikit-learn

Actualmente, he definido con éxito una función de kernel personalizada (pre-computando la matriz del kernel) usando la función def, y ahora estoy usando la función GridSearchCV para obtener los mejores parámetros.

por lo tanto, en la función de kernel personalizada, hay un total de 2 parámetros que se ajustarán (a saber, gamm y sea_gamma en el siguiente ejemplo), y también, para el modelo SVR, el parámetro costo c también debe ajustarse. Pero hasta ahora, solo puedo ajustar el parámetro de costo c usando GridSearchCV -> consulte la Parte I: ejemplo a continuación.

He buscado algunas soluciones similares, tales como:

¿Es posible ajustar los parámetros con la búsqueda de cuadrícula para núcleos personalizados en scikit-learn?

dice que ” Una forma de hacerlo es utilizando Pipeline, SVC (kernel = ‘precomputed’) y envolviendo su función de kernel personalizada como un estimador sklearn (una subclase de BaseEstimator y TransformerMixin)) .” Pero que aún es diferente de mi caso y la pregunta, sin embargo, traté de resolver el problema basado en esta solución, pero hasta ahora no imprimió ningún resultado, ni siquiera ningún error. -> Consulte la Parte II: soluciones con tubería.

Parte I: Ejemplo-> mi kernel personalizado original y el método de puntuación en la búsqueda de cuadrícula es:

import numpy as np import pandas as pd import sklearn.svm as svm from sklearn import preprocessing,svm, datasets from sklearn.preprocessing import StandardScaler, MaxAbsScaler from sklearn.metrics.pairwise import rbf_kernel from sklearn.grid_search import GridSearchCV from sklearn.svm import SVR from sklearn.pipeline import Pipeline from sklearn.metrics.scorer import make_scorer # weighting the vectors def distance_scale(X,Y): K = np.zeros((X.shape[0],Y.shape[0])) gamma_sea =192 for i in range(X.shape[0]): for j in range(Y.shape[0]): dis = min(np.abs(X[i]-Y[j]),1-np.abs(X[i]-Y[j])) K[i,j] = np.exp(-gamma_sea*dis**2) return K # custom RBF kernel : kernel matrix calculation def sea_rbf(X,Y): gam=1 t1 = X[:, 5:6] t2 = Y[:, 5:6] X = X[:, 0:5] Y = Y[:, 0:5] d = distance_scale(t1,t2) return rbf_kernel(X,Y,gamma=gam)*d def my_custom_loss_func(y_true, y_pred): error=np.abs((y_true - y_pred)/y_true) return np.mean(error)*100 my_scorer = make_scorer(my_custom_loss_func,greater_is_better=False) # Generate sample data X_train=np.random.random((100,6)) y_train=np.random.random((100,1)) X_test=np.random.random((40,6)) y_test=np.random.random((40,1)) y_train=np.ravel(y_train) y_test=np.ravel(y_test) # scale the input and output in training data set, also scale the input #in testing data set max_scale = preprocessing.MaxAbsScaler().fit(X_train) X_train_max = max_scale.transform(X_train) X_test_max = max_scale.transform(X_test) max_scale_y = preprocessing.MaxAbsScaler().fit(y_train) y_train_max = max_scale_y.transform(y_train) #precompute the kernel matrix gam=sea_rbf(X_train_max,X_train_max) #grid search for the model with the custom scoring method, but can only tune the *cost c* parameter in this case. clf= GridSearchCV(SVR(kernel='precomputed'), scoring=my_scorer, cv=5, param_grid={"C": [0.1,1,2,3,4,5] }) clf.fit(gam, y_train_max) print(clf.best_params_) print(clf.best_score_) print(clf.grid_scores_) 

Parte II: Solución con tubería

 from __future__ import print_function from __future__ import division import sys import sklearn from sklearn.base import BaseEstimator, TransformerMixin from sklearn.pipeline import Pipeline # Wrapper class for the custom kernel RBF_kernel class RBF2Kernel(BaseEstimator,TransformerMixin): def __init__(self, gamma=1,sea_gamma=20): super(RBF2Kernel,self).__init__() self.gamma = gamma self.sea_gamma = sea_gamma def fit(self, X, y=None, **fit_params): return self #calculate the kernel matrix def transform(self, X): self.a_train_ = X[:, 0:5] self.b_train_ = X[:, 0:5] self.t1_train_ = X[:, 5:6] self.t2_train_ = X[:, 5:6] sea=16 K = np.zeros((t1.shape[0],t2.shape[0])) for i in range(self.t1_train_.shape[0]): for j in range(self.t2_train_.shape[0]): dis = min(np.abs(self.t1_train_[i]*sea- self.t2_train_[j]*sea),sea-np.abs(self.t1_train_[i]*sea-self.t2_train_[j]*sea)) K[i,j] = np.exp(-self.gamma_sea *dis**2) return K return rbf_kernel(self.a_train_ , self.b_train_, gamma=self.gamma)*K def main(): print('python: {}'.format(sys.version)) print('numpy: {}'.format(np.__version__)) print('sklearn: {}'.format(sklearn.__version__)) # Generate sample data X_train=np.random.random((100,6)) y_train=np.random.random((100,1)) X_test=np.random.random((40,6)) y_test=np.random.random((40,1)) y_train=np.ravel(y_train) y_test=np.ravel(y_test) # Create a pipeline where our custom predefined kernel RBF2Kernel # is run before SVR. pipe = Pipeline([ ('sc', MaxAbsScaler()), ('rbf2', RBF2Kernel()), ('svm', SVR()), ]) # Set the parameter 'gamma' of our custom kernel by # using the 'estimator__param' syntax. cv_params = dict([ ('rbf2__gamma', 10.0**np.arange(-2,2)), ('rbf2__sea_gamma', 10.0**np.arange(-2,2)), ('svm__kernel', ['precomputed']), ('svm__C', 10.0**np.arange(-2,2)), ]) # Do grid search to get the best parameter value of 'gamma'. # here i am also trying to tune the parameters of the custom kernel model = GridSearchCV(pipe, cv_params, verbose=1, n_jobs=-1,scoring=my_scorer) model.fit(X_train, y_train) y_pred = model.predict(X_test) acc_test = mean_absolute_error(y_test, y_pred) mape_100 = my_custom_loss_func (y_test, y_pred) print("Test accuracy: {}".format(acc_test)) print("mape_100: {}".format(mape_100)) print("Best params:") print(model.best_params_) print(model.grid_scores_) if __name__ == '__main__': main() 

así, en resumen:

  1. el ejemplo funciona bien, pero solo puede ajustar el parámetro predeterminado (parater de costo en este caso)
  2. Quiero ajustar los parámetros adicionales del kernel personalizado que lo he definido como una función en la Parte I.
  3. scikit-learn o python todavía es realmente nuevo para mí, si la explicación no está clara, hágame saber si tiene alguna pregunta para los detalles.

Muchas gracias por su lectura, espero que la descripción larga le haga un poco más claro, todas las sugerencias son bienvenidas 🙂

Envuelve el modelo usando una función:

 def GBC(self): model = GradientBoostingRegressor() p = [{'learning_rate':[[0.0005,0.01,0.02,0.03]],'n_estimators':[[for i in range(1,100)]],'max_depth':[[4]]}] return model,p 

Luego, pruébalo con un kernel mediante la cuadrícula de parámetros:

 def kernel(self,model,p): parameter = ParameterGrid(p) clf = GridSearchCV(model, parameter, cv=5, scoring='neg_mean_squared_error',n_jobs=2) clf.fit(X,Y) 

Utilice este enfoque para administrar el tipo de función y su conjunto de hiperparámetros sobre una función distinta, llame la función directamente en main

 a = the_class() a.kernel(a.GBC()) 

Atacando el problema desde un ángulo ligeramente diferente: ¿qué tal si se usa un ajuste automático de parámetros con auto-sklearn ? Es un reemplazo directo de sklearn y con frecuencia hace un mejor trabajo que los parámetros ajustados manualmente.