web-dev-qa-db-fra.com

TypeError: l'objet 'KFold' n'est pas itérable

Je suis l'un des noyaux sur Kaggle , principalement, je suis n noyau pour la détection de fraude par carte de crédit .

J'ai atteint l'étape où j'ai besoin d'effectuer KFold afin de trouver les meilleurs paramètres pour la régression logistique.

Le code suivant est affiché dans le noyau lui-même, mais pour une raison quelconque (probablement une version plus ancienne de scikit-learn, donnez-moi des erreurs).

def printing_Kfold_scores(x_train_data,y_train_data):
    fold = KFold(len(y_train_data),5,shuffle=False) 

    # Different C parameters
    c_param_range = [0.01,0.1,1,10,100]

    results_table = pd.DataFrame(index = range(len(c_param_range),2), columns = ['C_parameter','Mean recall score'])
    results_table['C_parameter'] = c_param_range

    # the k-fold will give 2 lists: train_indices = indices[0], test_indices = indices[1]
    j = 0
    for c_param in c_param_range:
        print('-------------------------------------------')
        print('C parameter: ', c_param)
        print('-------------------------------------------')
        print('')

        recall_accs = []
        for iteration, indices in enumerate(fold,start=1):

            # Call the logistic regression model with a certain C parameter
            lr = LogisticRegression(C = c_param, penalty = 'l1')

            # Use the training data to fit the model. In this case, we use the portion of the fold to train the model
            # with indices[0]. We then predict on the portion assigned as the 'test cross validation' with indices[1]
            lr.fit(x_train_data.iloc[indices[0],:],y_train_data.iloc[indices[0],:].values.ravel())

            # Predict values using the test indices in the training data
            y_pred_undersample = lr.predict(x_train_data.iloc[indices[1],:].values)

            # Calculate the recall score and append it to a list for recall scores representing the current c_parameter
            recall_acc = recall_score(y_train_data.iloc[indices[1],:].values,y_pred_undersample)
            recall_accs.append(recall_acc)
            print('Iteration ', iteration,': recall score = ', recall_acc)

            # The mean value of those recall scores is the metric we want to save and get hold of.
        results_table.ix[j,'Mean recall score'] = np.mean(recall_accs)
        j += 1
        print('')
        print('Mean recall score ', np.mean(recall_accs))
        print('')

    best_c = results_table.loc[results_table['Mean recall score'].idxmax()]['C_parameter']

    # Finally, we can check which C parameter is the best amongst the chosen.
    print('*********************************************************************************')
    print('Best model to choose from cross validation is with C parameter = ', best_c)
    print('*********************************************************************************')

    return best_c

Les erreurs que j'obtiens sont les suivantes: pour cette ligne: fold = KFold(len(y_train_data),5,shuffle=False) Erreur:

TypeError: init () a obtenu plusieurs valeurs pour l'argument 'shuffle'

si je supprime le shuffle=False de cette ligne, j'obtiens l'erreur suivante:

TypeError: shuffle doit être True ou False; obtenu 5

Si je supprime le 5 Et que je conserve le shuffle=False, J'obtiens l'erreur suivante;

TypeError: l'objet 'KFold' n'est pas itérable qui vient de cette ligne: for iteration, indices in enumerate(fold,start=1):

Si quelqu'un peut m'aider à résoudre ce problème et suggérer comment cela peut être fait avec la dernière version de scikit-learn, ce sera très apprécié.

Merci.

8
kevinH

KFold est un séparateur, vous devez donc donner quelque chose à diviser.

exemple de code:

X = np.array([1,1,1,1], [2,2,2,2], [3,3,3,3], [4,4,4,4]])
y = np.array([1, 2, 3, 4])
# Now you create your Kfolds by the way you just have to pass number of splits and if you want to shuffle.
fold = KFold(2,shuffle=False)
# For iterate over the folds just use split
for train_index, test_index in fold.split(X):
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]
    # Follow fitting the classifier

Si vous voulez obtenir l'index de la boucle train/test, ajoutez simplement énumérer

for i, train_index, test_index in enumerate(fold.split(X)):
    print('Iteration:', i)
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]

J'espère que ça marche

13
Tzomas

Cela dépend de la façon dont vous avez importé le KFold.

Si vous l'avez fait:

from sklearn.cross_validation import KFold

Ensuite, votre code devrait fonctionner. Parce qu'il nécessite 3 paramètres: - longueur du tableau, nombre de divisions et mélange

Mais si vous faites cela:

from sklearn.model_selection import KFold

alors cela ne fonctionnera pas et il vous suffit de passer le nombre de divisions et de mélanger. Pas besoin de passer la longueur du tableau avec des modifications dans enumerate().

Soit dit en passant, le model_selection est le nouveau module et recommandé d'utiliser. Essayez de l'utiliser comme ceci:

fold = KFold(5,shuffle=False)

for train_index, test_index in fold.split(X):

    # Call the logistic regression model with a certain C parameter
    lr = LogisticRegression(C = c_param, penalty = 'l1')
    # Use the training data to fit the model. In this case, we use the portion of the fold to train the model
    lr.fit(x_train_data.iloc[train_index,:], y_train_data.iloc[train_index,:].values.ravel())

    # Predict values using the test indices in the training data
    y_pred_undersample = lr.predict(x_train_data.iloc[test_index,:].values)

    # Calculate the recall score and append it to a list for recall scores representing the current c_parameter
    recall_acc = recall_score(y_train_data.iloc[test_index,:].values,y_pred_undersample)
    recall_accs.append(recall_acc)
14
Vivek Kumar