Comment créer/personnaliser votre propre fonction de marqueur dans scikit-learn?

j'utilise Régression À Vecteurs De Support comme un estimateur GridSearchCV. Mais je veux changer la fonction d'erreur: au lieu d'utiliser la valeur par défaut (R-squared: coefficient de détermination), je tiens à définir ma propre fonction d'erreur.

j'ai essayé de faire un make_scorer, mais il ne fonctionne pas.

j'ai lu la documentation et a trouvé qu'il est possible de créer estimateurs sur mesure, mais je n'ai pas besoin de refaire le estimateur entier - seulement la fonction d'erreur / de notation.

je pense que je peux le faire par la définition d'un callable en tant que correcteur, comme il est dit dans le docs.

mais je ne sais pas comment utiliser un estimateur: dans mon cas SVR. Devrais-je passer à un classificateur (comme 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 null/zero. Je viens de mettre à zéro pour simplicité.

Quelqu'un pourrait-il montrer un exemple d'application de cette fonction de notation personnalisée? Merci pour votre aide!

19
demandé sur alichaudry 2015-09-04 18:20:08

2 réponses

comme vous l'avez vu, ceci est fait en utilisant make_scorer ( docs).

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:])
16
répondu Jamie Bull 2016-04-12 11:33:36

Jamie a un exemple étoffé, Mais voici un exemple utilisant make_scorer directement de 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 retourner une valeur pour maximiser. Et pour les buteurs se terminant par _loss ou _error, une valeur est retournée pour être minimisée. Vous pouvez utiliser cette fonctionnalité en définissant le greater_is_better paramètre à l'intérieur de make_scorer. C'est, ce paramètre devrait être True pour les marqueurs où des valeurs plus élevées sont meilleures, et False pour les marqueurs où les valeurs inférieures sont meilleures. GridSearchCV peut alors optimiser dans la bonne direction.

vous pouvez alors 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)

puis passer custom_scorer en GridSearchCV comme vous le feriez avec toute autre fonction de notation: clf = GridSearchCV(scoring=custom_scorer).

18
répondu alichaudry 2016-04-14 22:46:45