J'aime utiliser le LOGO de scikit (laisser un groupe) comme méthode de validation croisée, en combinaison avec des courbes d'apprentissage. Cela fonctionne très bien dans la plupart des cas que je traite, mais je ne peux (efficacement) utiliser que les deux paramètres qui sont (je crois) les plus critiques dans ces cas (d'expérience): caractéristiques maximales et nombre d'estimateurs. Exemple de mon code ci-dessous:Combinaison de RandomizedSearchCV (ou GridSearcCV) avec la validation croisée LeaveOneGroupOut dans scikit-learn
Fscorer = make_scorer(f1_score, average = 'micro')
gp = training_data["GP"].values
logo = LeaveOneGroupOut()
from sklearn.ensemble import RandomForestClassifier
RF_clf100 = RandomForestClassifier (n_estimators=100, n_jobs=-1, random_state = 49)
RF_clf200 = RandomForestClassifier (n_estimators=200, n_jobs=-1, random_state = 49)
RF_clf300 = RandomForestClassifier (n_estimators=300, n_jobs=-1, random_state = 49)
RF_clf400 = RandomForestClassifier (n_estimators=400, n_jobs=-1, random_state = 49)
RF_clf500 = RandomForestClassifier (n_estimators=500, n_jobs=-1, random_state = 49)
RF_clf600 = RandomForestClassifier (n_estimators=600, n_jobs=-1, random_state = 49)
param_name = "max_features"
param_range = param_range = [5, 10, 15, 20, 25, 30]
plt.figure()
plt.suptitle('n_estimators = 100', fontsize=14, fontweight='bold')
_, test_scores = validation_curve(RF_clf100, X, y, cv=logo.split(X, y, groups=gp),
param_name=param_name, param_range=param_range,
scoring=Fscorer, n_jobs=-1)
test_scores_mean = np.mean(test_scores, axis=1)
plt.plot(param_range, test_scores_mean)
plt.xlabel(param_name)
plt.xlim(min(param_range), max(param_range))
plt.ylabel("F1")
plt.ylim(0.47, 0.57)
plt.legend(loc="best")
plt.show()
plt.figure()
plt.suptitle('n_estimators = 200', fontsize=14, fontweight='bold')
_, test_scores = validation_curve(RF_clf200, X, y, cv=logo.split(X, y, groups=gp),
param_name=param_name, param_range=param_range,
scoring=Fscorer, n_jobs=-1)
test_scores_mean = np.mean(test_scores, axis=1)
plt.plot(param_range, test_scores_mean)
plt.xlabel(param_name)
plt.xlim(min(param_range), max(param_range))
plt.ylabel("F1")
plt.ylim(0.47, 0.57)
plt.legend(loc="best")
plt.show()
...
...
Ce que je voudrais vraiment bien est de combiner le logo avec la recherche de la grille ou la recherche aléatoire, pour une recherche d'espace des paramètres plus approfondie.
A partir de maintenant mon code ressemble à ceci:
param_dist = {"n_estimators": [100, 200, 300, 400, 500, 600],
"max_features": sp_randint(5, 30),
"max_depth": sp_randint(2, 18),
"criterion": ['entropy', 'gini'],
"min_samples_leaf": sp_randint(2, 17)}
clf = RandomForestClassifier(random_state = 49)
n_iter_search = 45
random_search = RandomizedSearchCV(clf, param_distributions=param_dist,
n_iter=n_iter_search,
scoring=Fscorer, cv=8,
n_jobs=-1)
random_search.fit(X, y)
Quand je remplace cv = 8
avec cv=logo.split(X, y, groups=gp)
, je reçois ce message d'erreur:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-10-0092e11ffbf4> in <module>()
---> 35 random_search.fit(X, y)
/Applications/anaconda/lib/python2.7/site-packages/sklearn/model_selection/_search.pyc in fit(self, X, y, groups)
1183 self.n_iter,
1184 random_state=self.random_state)
-> 1185 return self._fit(X, y, groups, sampled_params)
/Applications/anaconda/lib/python2.7/site-packages/sklearn/model_selection/_search.pyc in _fit(self, X, y, groups, parameter_iterable)
540
541 X, y, groups = indexable(X, y, groups)
--> 542 n_splits = cv.get_n_splits(X, y, groups)
543 if self.verbose > 0 and isinstance(parameter_iterable, Sized):
544 n_candidates = len(parameter_iterable)
/Applications/anaconda/lib/python2.7/site-packages/sklearn/model_selection/_split.pyc in get_n_splits(self, X, y, groups)
1489 Returns the number of splitting iterations in the cross-validator.
1490 """
-> 1491 return len(self.cv) # Both iterables and old-cv objects support len
1492
1493 def split(self, X=None, y=None, groups=None):
TypeError: object of type 'generator' has no len()
Toutes les suggestions à (1) ce qui se passe et, plus important encore, (2) comment je peux le faire fonctionner (combinant RandomizedSearchCV avec LeaveOneGroupOut)?
* Mise à jour février 08 2017 *
Il a travaillé à l'aide cv=logo
avec suggestion « @Vivek Kumar de random_search.fit(X, y, wells)
Je ne suis pas sûr de comprendre. Où dois-je passer 'cv.get_n_splits'? – MyCarta
@MyCarta Désolé, je parlais de 'logo.split()', pas 'cv.get_n_splits'. J'ai édité ma réponse pour enlever la confusion. –
@ Vivek Kumar ok c'est un peu plus clair. Êtes-vous également en train de dire qu'il n'y a pas de solution de contournement? – MyCarta