Je voudrais vérifier l'erreur de prédiction d'une nouvelle méthode à travers la validation croisée. Je voudrais savoir si je peux passer ma méthode à la fonction de validation croisée de sklearn et au cas où comment.
Je voudrais quelque chose comme sklearn.cross_validation(cv=10).mymethod
.
J'ai aussi besoin de savoir comment définir mymethod
si c'est une fonction et quel élément d'entrée et quelle sortie
Par exemple, nous pouvons considérer comme mymethod
une implémentation de l'estimateur des moindres carrés (bien sûr pas ceux de sklearn).
J'ai trouvé ce tutoriel link mais ce n'est pas très clair pour moi.
Dans le documentation ils utilisent
>>> import numpy as np
>>> from sklearn import cross_validation
>>> from sklearn import datasets
>>> from sklearn import svm
>>> iris = datasets.load_iris()
>>> iris.data.shape, iris.target.shape
((150, 4), (150,))
>>> clf = svm.SVC(kernel='linear', C=1)
>>> scores = cross_validation.cross_val_score(
... clf, iris.data, iris.target, cv=5)
...
>>> scores
Mais le problème est qu'ils utilisent comme estimateur clf
qui est obtenu par une fonction construite en sklearn. Comment dois-je définir mon propre estimateur pour pouvoir le passer au cross_validation.cross_val_score
fonction?
Supposons par exemple un estimateur simple qui utilise un modèle linéaire $ y = x\beta $ où beta est estimé comme X [1,:] + alpha où alpha est un paramètre. Comment dois-je compléter le code?
class my_estimator():
def fit(X,y):
beta=X[1,:]+alpha #where can I pass alpha to the function?
return beta
def scorer(estimator, X, y) #what should the scorer function compute?
return ?????
Avec le code suivant, j'ai reçu une erreur:
class my_estimator():
def fit(X, y, **kwargs):
#alpha = kwargs['alpha']
beta=X[1,:]#+alpha
return beta
>>> cv=cross_validation.cross_val_score(my_estimator,x,y,scoring="mean_squared_error")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python27\lib\site-packages\scikit_learn-0.14.1-py2.7-win32.Egg\sklearn\cross_validation.py", line 1152, in cross_val_score
for train, test in cv)
File "C:\Python27\lib\site-packages\scikit_learn-0.14.1-py2.7-win32.Egg\sklearn\externals\joblib\parallel.py", line 516, in __call__
for function, args, kwargs in iterable:
File "C:\Python27\lib\site-packages\scikit_learn-0.14.1-py2.7-win32.Egg\sklearn\cross_validation.py", line 1152, in <genexpr>
for train, test in cv)
File "C:\Python27\lib\site-packages\scikit_learn-0.14.1-py2.7-win32.Egg\sklearn\base.py", line 43, in clone
% (repr(estimator), type(estimator)))
TypeError: Cannot clone object '<class __main__.my_estimator at 0x05ACACA8>' (type <type 'classobj'>): it does not seem to be a scikit-learn estimator a it does not implement a 'get_params' methods.
>>>
La réponse réside également dans sklearn documentation .
Vous devez définir deux choses:
un estimateur qui implémente la fonction fit(X, y)
, X
étant la matrice avec les entrées et y
étant le vecteur des sorties
une fonction scorer, ou un objet appelable qui peut être utilisé avec: scorer(estimator, X, y)
et renvoie le score du modèle donné
En vous référant à votre exemple: tout d'abord, scorer
ne devrait pas être une méthode de l'estimateur, c'est une notion différente. Créez simplement un appelable:
def scorer(estimator, X, y)
return ????? # compute whatever you want, it's up to you to define
# what does it mean that the given estimator is "good" or "bad"
Ou encore une solution plus simple: vous pouvez passer une chaîne 'mean_squared_error'
ou 'accuracy'
(liste complète disponible dans cette partie de la documentation ) à cross_val_score
fonction pour utiliser un marqueur prédéfini.
Une autre possibilité consiste à utiliser make_scorer
fonction d'usine.
Quant à la deuxième chose, vous pouvez passer des paramètres à votre modèle via le fit_params
dict
paramètre du cross_val_score
fonction (comme mentionné dans la documentation). Ces paramètres seront passés à la fonction fit
.
class my_estimator():
def fit(X, y, **kwargs):
alpha = kwargs['alpha']
beta=X[1,:]+alpha
return beta
Après avoir lu tous les messages d'erreur, qui donnent une idée assez claire de ce qui manque, voici un exemple simple:
import numpy as np
from sklearn.cross_validation import cross_val_score
class RegularizedRegressor:
def __init__(self, l = 0.01):
self.l = l
def combine(self, inputs):
return sum([i*w for (i,w) in Zip([1] + inputs, self.weights)])
def predict(self, X):
return [self.combine(x) for x in X]
def classify(self, inputs):
return sign(self.predict(inputs))
def fit(self, X, y, **kwargs):
self.l = kwargs['l']
X = np.matrix(X)
y = np.matrix(y)
W = (X.transpose() * X).getI() * X.transpose() * y
self.weights = [w[0] for w in W.tolist()]
def get_params(self, deep = False):
return {'l':self.l}
X = np.matrix([[0, 0], [1, 0], [0, 1], [1, 1]])
y = np.matrix([0, 1, 1, 0]).transpose()
print cross_val_score(RegularizedRegressor(),
X,
y,
fit_params={'l':0.1},
scoring = 'mean_squared_error')