J'utilise Support Vector Regression comme estimateur dans GridSearchCV . Mais je veux changer la fonction d'erreur: au lieu d'utiliser la valeur par défaut (R au carré: coefficient de détermination), je voudrais définir ma propre fonction d'erreur personnalisée.
J'ai essayé d'en faire un avec make_scorer
, mais cela n'a pas fonctionné.
J'ai lu la documentation et j'ai découvert qu'il était possible de créer estimateurs personnalisés , mais je n'ai pas besoin de refaire l'intégralité de l'estimateur - uniquement la fonction erreur/score.
Je pense que je peux le faire en définissant un callable comme un marqueur, comme il est dit dans le docs .
Mais je ne sais pas comment utiliser un estimateur: dans mon cas SVR. Dois-je passer à un classificateur (tel que SVC)? Et comment pourrais-je l'utiliser?
Ma fonction d'erreur personnalisée est la suivante:
def my_custom_loss_func(X_train_scaled, Y_train_scaled):
error, M = 0, 0
for i in range(0, len(Y_train_scaled)):
z = (Y_train_scaled[i] - M)
if X_train_scaled[i] > M and Y_train_scaled[i] > M and (X_train_scaled[i] - Y_train_scaled[i]) > 0:
error_i = (abs(Y_train_scaled[i] - X_train_scaled[i]))**(2*np.exp(z))
if X_train_scaled[i] > M and Y_train_scaled[i] > M and (X_train_scaled[i] - Y_train_scaled[i]) < 0:
error_i = -(abs((Y_train_scaled[i] - X_train_scaled[i]))**(2*np.exp(z)))
if X_train_scaled[i] > M and Y_train_scaled[i] < M:
error_i = -(abs(Y_train_scaled[i] - X_train_scaled[i]))**(2*np.exp(-z))
error += error_i
return error
La variable M
n'est pas nulle/nulle. Je viens de le mettre à zéro pour plus de simplicité.
Quelqu'un pourrait-il montrer un exemple d'application de cette fonction de notation personnalisée? Merci de votre aide!
Comme vous l'avez vu, cela se fait en utilisant make_scorer
( documents ).
from sklearn.grid_search import GridSearchCV
from sklearn.metrics.scorer import make_scorer
from sklearn.svm import SVR
import numpy as np
rng = np.random.RandomState(1)
def my_custom_loss_func(X_train_scaled, Y_train_scaled):
error, M = 0, 0
for i in range(0, len(Y_train_scaled)):
z = (Y_train_scaled[i] - M)
if X_train_scaled[i] > M and Y_train_scaled[i] > M and (X_train_scaled[i] - Y_train_scaled[i]) > 0:
error_i = (abs(Y_train_scaled[i] - X_train_scaled[i]))**(2*np.exp(z))
if X_train_scaled[i] > M and Y_train_scaled[i] > M and (X_train_scaled[i] - Y_train_scaled[i]) < 0:
error_i = -(abs((Y_train_scaled[i] - X_train_scaled[i]))**(2*np.exp(z)))
if X_train_scaled[i] > M and Y_train_scaled[i] < M:
error_i = -(abs(Y_train_scaled[i] - X_train_scaled[i]))**(2*np.exp(-z))
error += error_i
return error
# Generate sample data
X = 5 * rng.Rand(10000, 1)
y = np.sin(X).ravel()
# Add noise to targets
y[::5] += 3 * (0.5 - rng.Rand(X.shape[0]/5))
train_size = 100
my_scorer = make_scorer(my_custom_loss_func, greater_is_better=True)
svr = GridSearchCV(SVR(kernel='rbf', gamma=0.1),
scoring=my_scorer,
cv=5,
param_grid={"C": [1e0, 1e1, 1e2, 1e3],
"gamma": np.logspace(-2, 2, 5)})
svr.fit(X[:train_size], y[:train_size])
print svr.best_params_
print svr.score(X[train_size:], y[train_size:])
Jamie a un exemple étoffé, mais voici un exemple utilisant make_scorer directement depuis scikit-learn documentation :
import numpy as np
def my_custom_loss_func(ground_truth, predictions):
diff = np.abs(ground_truth - predictions).max()
return np.log(1 + diff)
# loss_func will negate the return value of my_custom_loss_func,
# which will be np.log(2), 0.693, given the values for ground_truth
# and predictions defined below.
loss = make_scorer(my_custom_loss_func, greater_is_better=False)
score = make_scorer(my_custom_loss_func, greater_is_better=True)
ground_truth = [[1, 1]]
predictions = [0, 1]
from sklearn.dummy import DummyClassifier
clf = DummyClassifier(strategy='most_frequent', random_state=0)
clf = clf.fit(ground_truth, predictions)
loss(clf,ground_truth, predictions)
score(clf,ground_truth, predictions)
Lors de la définition d'un marqueur personnalisé via sklearn.metrics.make_scorer
, la convention est que les fonctions personnalisées se terminant par _score
Renvoient une valeur à maximiser. Et pour les buteurs se terminant par _loss
Ou _error
, Une valeur est renvoyée pour être minimisée. Vous pouvez utiliser cette fonctionnalité en définissant le paramètre greater_is_better
À l'intérieur make_scorer
. Autrement dit, ce paramètre serait True
pour les correcteurs où les valeurs élevées sont meilleures, et False
pour les correcteurs où les valeurs inférieures sont meilleures. GridSearchCV
peut alors optimiser dans la direction appropriée.
Vous pouvez ensuite convertir votre fonction de marqueur comme suit:
from sklearn.metrics.scorer import make_scorer
def custom_loss_func(X_train_scaled, Y_train_scaled):
error, M = 0, 0
for i in range(0, len(Y_train_scaled)):
z = (Y_train_scaled[i] - M)
if X_train_scaled[i] > M and Y_train_scaled[i] > M and (X_train_scaled[i] - Y_train_scaled[i]) > 0:
error_i = (abs(Y_train_scaled[i] - X_train_scaled[i]))**(2*np.exp(z))
if X_train_scaled[i] > M and Y_train_scaled[i] > M and (X_train_scaled[i] - Y_train_scaled[i]) < 0:
error_i = -(abs((Y_train_scaled[i] - X_train_scaled[i]))**(2*np.exp(z)))
if X_train_scaled[i] > M and Y_train_scaled[i] < M:
error_i = -(abs(Y_train_scaled[i] - X_train_scaled[i]))**(2*np.exp(-z))
error += error_i
return error
custom_scorer = make_scorer(custom_loss_func, greater_is_better=True)
Et puis passez custom_scorer
Dans GridSearchCV
comme vous le feriez pour n'importe quelle autre fonction de notation: clf = GridSearchCV(scoring=custom_scorer)
.