python - machine - scikit-learn vs tensorflow
Scikit-learn predict_proba da respuestas incorrectas (3)
Existe cierta confusión sobre qué es lo que predict_proba realmente hace. No predice probabilidades como sugiere el título, sino que produce distancias. En el ejemplo de apple vs orange 0.39097541, 0.60902459, la distancia más corta 0.39097541 es la clase de manzana. que es contra intuitivo. usted está buscando la probabilidad más alta, pero no es el caso.
Otra fuente de confusión proviene de que predic_proba hace coincidir las etiquetas duras, simplemente no en el orden de las clases, desde 0..n secuencialmente. Scikit parece barajar las clases, pero es posible mapearlas.
Así es como funciona.
say we have 5 classes with labels:
classifier.classes_ = [0 1 2 3 4]
target names = [''1'', ''2'', ''3'', ''6'', ''8'']
etiquetas predichas [2 0 1 0 4]
classifier.predict_proba
[[ 0.20734121 0.20451986 0.17262553 0.20768649 0.20782692]
[ 0.19099348 0.2018391 0.20222314 0.20136784 0.20357644]
[ 0.19982284 0.19497121 0.20399376 0.19824784 0.20296435]
[ 0.19884577 0.1999416 0.19998889 0.20092702 0.20029672]
[ 0.20328893 0.2025956 0.20500402 0.20383255 0.1852789 ]]
Confusion matrix:
[[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[1 0 0 0 0]
[0 0 0 0 1]]
y_test [2 0 1 3 4]
pred [2 0 1 0 4]
classifier.classes_ = [0 1 2 3 4]
cualquier cosa menos la tercera clase es un partido. de acuerdo con las etiquetas predichas en cm, se predice la clase 0 y la clase real es 0 argmax (pred_prob). Pero, está asignado a
y_test [2 0 1 3 4]
así que encuentra la segunda clase
0 1 2 3 4
[ 0.20734121 0.20451986 0.17262553 0.20768649 0.20782692]
and the winner is **0.17262553**
hagámoslo de nuevo. mira el resultado número 4 de clasificación errónea donde el lebel real 4, predicho 1 según cm.
BUT y_test [2 0 1 3 4] pred [2 0 1 0 4]
which translates to actual label 3 predicted label 0
0 1 2 3 4
]0.19884577 0.1999416 0.19998889 0.20092702 0.20029672]
look at label number 0, and the winner is **0.19884577**
Estos son mis 0.02.
Esta es una pregunta de seguimiento de Cómo saber qué clases se representan en la matriz de retorno de predicción en Scikit-learn
En esa pregunta, cité el siguiente código:
>>> import sklearn
>>> sklearn.__version__
''0.13.1''
>>> from sklearn import svm
>>> model = svm.SVC(probability=True)
>>> X = [[1,2,3], [2,3,4]] # feature vectors
>>> Y = [''apple'', ''orange''] # classes
>>> model.fit(X, Y)
>>> model.predict_proba([1,2,3])
array([[ 0.39097541, 0.60902459]])
Descubrí en esa pregunta que este resultado representa la probabilidad del punto que pertenece a cada clase, en el orden dado por model.classes_
>>> zip(model.classes_, model.predict_proba([1,2,3])[0])
[(''apple'', 0.39097541289393828), (''orange'', 0.60902458710606167)]
Entonces ... esta respuesta, si se interpreta correctamente, dice que el punto es probablemente un ''naranja'' (con una confianza bastante baja, debido a la poca cantidad de datos). Pero intuitivamente, este resultado es obviamente incorrecto, ya que el punto dado fue idéntico a los datos de entrenamiento para ''apple''. Solo para estar seguro, probé lo contrario también:
>>> zip(model.classes_, model.predict_proba([2,3,4])[0])
[(''apple'', 0.60705475211840931), (''orange'', 0.39294524788159074)]
De nuevo, obviamente incorrecto, pero en la otra dirección.
Finalmente, lo intenté con puntos que estaban mucho más lejos.
>>> X = [[1,1,1], [20,20,20]] # feature vectors
>>> model.fit(X, Y)
>>> zip(model.classes_, model.predict_proba([1,1,1])[0])
[(''apple'', 0.33333332048410247), (''orange'', 0.66666667951589786)]
De nuevo, el modelo predice las probabilidades incorrectas. PERO, la función model.predict lo hace bien!
>>> model.predict([1,1,1])[0]
''apple''
Ahora, recuerdo haber leído algo en los documentos sobre predictionproba ser inexacto para pequeños conjuntos de datos, aunque parece que no puedo encontrarlo de nuevo. ¿Es este el comportamiento esperado, o estoy haciendo algo mal? Si este ES el comportamiento esperado, entonces ¿por qué la función predicción y predicción_proba no están de acuerdo con la salida? Y lo que es más importante, ¿qué tan grande debe ser el conjunto de datos antes de poder confiar en los resultados de predic_proba?
-------- ACTUALIZACIÓN --------
Ok, entonces hice algunos más ''experimentos'' en esto: el comportamiento de predic_proba depende en gran medida de ''n'', ¡pero no de una manera predecible!
>>> def train_test(n):
... X = [[1,2,3], [2,3,4]] * n
... Y = [''apple'', ''orange''] * n
... model.fit(X, Y)
... print "n =", n, zip(model.classes_, model.predict_proba([1,2,3])[0])
...
>>> train_test(1)
n = 1 [(''apple'', 0.39097541289393828), (''orange'', 0.60902458710606167)]
>>> for n in range(1,10):
... train_test(n)
...
n = 1 [(''apple'', 0.39097541289393828), (''orange'', 0.60902458710606167)]
n = 2 [(''apple'', 0.98437355278112448), (''orange'', 0.015626447218875527)]
n = 3 [(''apple'', 0.90235408180319321), (''orange'', 0.097645918196806694)]
n = 4 [(''apple'', 0.83333299908143665), (''orange'', 0.16666700091856332)]
n = 5 [(''apple'', 0.85714254878984497), (''orange'', 0.14285745121015511)]
n = 6 [(''apple'', 0.87499969631893626), (''orange'', 0.1250003036810636)]
n = 7 [(''apple'', 0.88888844127886335), (''orange'', 0.11111155872113669)]
n = 8 [(''apple'', 0.89999988018127364), (''orange'', 0.10000011981872642)]
n = 9 [(''apple'', 0.90909082368682159), (''orange'', 0.090909176313178491)]
¿Cómo debo usar esta función de forma segura en mi código? Por lo menos, ¿hay algún valor de n para el que se garantice que está de acuerdo con el resultado del modelo.predict?
si usa svm.LinearSVC()
como estimador, y .decision_function()
(que es como svm.SVC''s .predict_proba ()) para clasificar los resultados de la clase más probable a la menos probable. esto concuerda con la función .predict()
. Además, este estimador es más rápido y da casi los mismos resultados con svm.SVC()
el único inconveniente para usted podría ser que .decision_function()
da un valor con signo sth como entre -1 y 3 en lugar de un valor de probabilidad. pero está de acuerdo con la predicción.
predict_probas
está utilizando la función de escalado de Platt de libsvm para calibrar probabilidades, ver:
De hecho, las predicciones de hiperplano y la calibración probada pueden estar en desacuerdo, especialmente si solo tiene 2 muestras en su conjunto de datos. Es extraño que la validación cruzada interna realizada por libsvm para escalar las probabilidades no falle (explícitamente) en este caso. Tal vez esto es un error. Uno tendría que sumergirse en el código de escala de Platt de libsvm para entender lo que está sucediendo.