0
$\begingroup$

I am trying to perform K Fold cross validation in scikit learn but I'm having a hard time understanding the results returned from it. My objective is to maximize the recall as I am using this to test a fraud detection system with a highly unbalanced dataset (approximately 98% to 2%, being the 2% the fraudulent percentage).

So my question is: how are X and y related? I know X is supposed to contain a vector {n_samples, n_features} where the samples are my data and the features are the variable(s) to predict. In my case I only have one variable so only ine feature: is it fradulent or not? The y is supposed to contain the target, i.e., the values to predict, in my case 0 or 1.

However I get strange results. For example, using this code:

X = np.array([[1], [1], [1], [1], [1], [1], [1], [1], [0], [0], [0], [0], [0], [0], [0], [0]])
y = np.array([1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0    
classifier = LogisticRegression()
scores = cross_val_score(classifier, X, y, scoring='recall', cv=10, n_jobs=1)

I was hoping to have a mean score of 0.75 since from 8 positives i only got 6 of them correctly predicted. However I got a recall average of 0.60

In another example, using this data:

X = np.array([[1], [1], [1], [1], [1], [1], [1], [1], [0], [0], [0], [0], [0], [0], [0], [0]])
y = np.array([1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

I get a recall average of 0 when I expected an average of 0.50 since only 4 of the 8 positive results were correctly predicted.

What am I doing wrong?

$\endgroup$

1 Answer 1

1
$\begingroup$

cross_val_score is a helper function that plugs your X and Y inputs into an estimator (that you specify), trains the model, and looks at the results. I suspect that what's happening here is that cross_val_score isn't calculating results directly on the X and Y that you've provided, but rather it's training the logistic regression and comparing the predicted results to your Y instead. Since your X only has a single feature, the resulting models probably aren't going to be very effective.

To get the results you're expecting given those inputs, you'll want to use something like the classification_matrix function, which simply performs precision/recall calculations on whatever data you provide rather than training a model first. Here's what that looks like:

import numpy as np
from sklearn.metrics import classification_report

#Example 1
print ('EXAMPLE 1 RESULTS:')
X1 = np.array([[1], [1], [1], [1], [1], [1], [1], [1], [0], [0], [0], [0], [0], [0], [0], [0]])
#The line below was cut off in your example, but I think this is what it was supposed to be
y1 = np.array([1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
print(classification_report(X1, y1))

print("")

#Example 2
print ('EXAMPLE 2 RESULTS:')
X2 = np.array([[1], [1], [1], [1], [1], [1], [1], [1], [0], [0], [0], [0], [0], [0], [0], [0]])
y2 = np.array([1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
print(classification_report(X2, y2))

This gives you the recall results you'd expect:

EXAMPLE 1 RESULTS:
             precision    recall  f1-score   support

          0       0.80      1.00      0.89         8
          1       1.00      0.75      0.86         8

avg / total       0.90      0.88      0.87        16


EXAMPLE 2 RESULTS:
             precision    recall  f1-score   support

          0       0.67      1.00      0.80         8
          1       1.00      0.50      0.67         8

avg / total       0.83      0.75      0.73        16
$\endgroup$
7
  • $\begingroup$ THANK YOU!! I will use this function instead! I can't thank you enough!!! $\endgroup$ Commented Oct 12, 2016 at 9:43
  • $\begingroup$ I am almost there! The only problem I have now is that, even though the metrics are correct, it does not perform 10 fold cross validation. Do you know how to apply this function directly to cross validation? Can I use this in conjunction with cross_val_score or a similar function? $\endgroup$ Commented Oct 12, 2016 at 11:26
  • $\begingroup$ I'd use the scikit-learn kfold object to create an iterable of train/test combinations. You can use that to create a loop to evaluate each combination using any criteria you want (accuracy, precision, recall, etc.). Example from sklearn docs is here $\endgroup$
    – nickhamlin
    Commented Oct 12, 2016 at 11:59
  • $\begingroup$ Just one last question (forgive my lack of understanding): I have to split the X in 10 folds and also the y in 10 folds and then run the classification_report on each of the subsets (classification_repor(X1, y1), classification_report(X2, y2), etc) correct? $\endgroup$ Commented Oct 12, 2016 at 12:02
  • $\begingroup$ Generally speaking, yes. But, there are ways to make this easier. For example, you can use the kfold object to create the splits for you so you just have to define the comparison once (see the example link in my previous comment). Alternatively, if you DO actually want to use an estimator to make a prediction (rather than just calculating the result manually based on the true and predicted vectors) cross_val_score has a scoring argument that you can use to define whatever outcome metric you want (like recall). $\endgroup$
    – nickhamlin
    Commented Oct 12, 2016 at 19:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.