web-dev-qa-db-fra.com

Scikit-learn renvoie les valeurs de coefficient de détermination (R ^ 2) inférieurs à -1

Je fais un modèle linéaire simple. j'ai

fire = load_data()
regr = linear_model.LinearRegression()
scores = cross_validation.cross_val_score(regr, fire.data, fire.target, cv=10, scoring='r2')
print scores

qui donne

[  0.00000000e+00   0.00000000e+00  -8.27299054e+02  -5.80431382e+00
  -1.04444147e-01  -1.19367785e+00  -1.24843536e+00  -3.39950443e-01
   1.95018287e-02  -9.73940970e-02]

Comment est-ce possible? Lorsque je fais la même chose avec les données de diabète intégrées, cela fonctionne parfaitement, mais pour mes données, ces résultats apparemment absurdes sont renvoyés. Ai-je fait quelque chose de mal?

12
rhombidodecahedron

Il n'y a pas de raison que r^2 ne soit pas négatif (malgré le ^2 dans son nom). Ceci est également indiqué dans doc . Vous pouvez voir r^2 comme une comparaison de l'ajustement de votre modèle (dans le contexte de la régression linéaire, par exemple un modèle d'ordre 1 (affine)) à un modèle d'ordre 0 (ajustant simplement une constante), les deux en minimisant une perte au carré. La constante minimisant l'erreur au carré est la moyenne. Étant donné que vous effectuez une validation croisée avec des données omises, il peut arriver que la moyenne de votre ensemble de tests soit très différente de la moyenne de votre ensemble d’entraînement. Cela seul peut induire une erreur au carré beaucoup plus élevée dans votre prédiction par rapport à une simple prédiction de la moyenne des données de test, ce qui donne un score r^2 négatif.

Dans le pire des cas, si vos données n'expliquent pas du tout votre cible, ces scores peuvent devenir très fortement négatifs. Essayer

import numpy as np
rng = np.random.RandomState(42)
X = rng.randn(100, 80)
y = rng.randn(100)  # y has nothing to do with X whatsoever
from sklearn.linear_model import LinearRegression
from sklearn.cross_validation import cross_val_score
scores = cross_val_score(LinearRegression(), X, y, cv=5, scoring='r2')

Cela devrait entraîner des valeurs r^2 négatives.

In [23]: scores
Out[23]: 
array([-240.17927358,   -5.51819556,  -14.06815196,  -67.87003867,
    -64.14367035])

La question importante à présent est de savoir si cela est dû au fait que les modèles linéaires ne trouvent tout simplement rien dans vos données, ou à quelque chose d'autre qui pourrait être corrigé lors du prétraitement de vos données. Avez-vous essayé de redimensionner vos colonnes pour avoir la moyenne 0 et la variance 1? Vous pouvez le faire en utilisant sklearn.preprocessing.StandardScaler. En fait, vous devez créer un nouvel estimateur en concaténant une StandardScaler et la LinearRegression dans un pipeline à l'aide de sklearn.pipeline.Pipeline. Ensuite, vous voudrez peut-être essayer la régression Ridge.

19
eickenberg

R² = 1 - RSS/TSS, où RSS est la somme des carrés ∑ (y - f (x)) ² et TSS est la somme des carrés ∑ (y - moyenne (y)) ². Maintenant pour R² ≥ -1, il est nécessaire que RSS/TSS ≤ 2, mais il est facile de construire un modèle et un jeu de données pour lesquels ce n'est pas vrai:

>>> x = np.arange(50, dtype=float)
>>> y = x
>>> def f(x): return -100
...
>>> rss = np.sum((y - f(x)) ** 2)
>>> tss = np.sum((y - y.mean()) ** 2)
>>> 1 - rss / tss
-74.430972388955581
7
Fred Foo

Ce n'est pas parce que R^2 peut être négatif que cela devrait l'être.

Possibilité 1: un bug dans votre code.

Un bug courant que vous devriez vérifier est que vous passez correctement les paramètres:

r2_score(y_true, y_pred) # Correct!
r2_score(y_pred, y_true) # Incorrect!!!!

Possibilité 2: petits jeux de données

Si vous obtenez un R ^ 2 négatif, vous pouvez également vérifier le sur-ajustement. N'oubliez pas que cross_validation.cross_val_score() ne mélange pas vos entrées de manière aléatoire. Par conséquent, si votre échantillon est trié par inadvertance (par date, par exemple), vous pouvez créer des modèles sur chaque pli non prédictifs.

Essayez de réduire le nombre de fonctionnalités, d’augmenter le nombre d’échantillons et de réduire le nombre de plis (si vous utilisez cross_validation). Bien qu'il n'y ait pas de règle officielle ici, votre ensemble de données m x n (où m est le nombre d'échantillons et n est le nombre d'entités) devrait être de forme où

m > n^2

et lorsque vous utilisez la validation croisée avec f comme nombre de plis, vous devez viser

m/f > n^2
5
mgoldwasser

Si vous obtenez des r ^ 2 scores de régression négatifs, veillez à supprimer tout identificateur unique (par exemple, "id" ou "rownum") de votre jeu de données avant d'ajuster/évaluer le modèle. Contrôle simple, mais cela vous fera gagner un peu de temps.

0
Alexus Wong