web-dev-qa-db-fra.com

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

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!

26
daniel2014

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:])
26
Jamie Bull

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).

24
alichaudry