2013-06-10 12 views
26

Questa è una domanda di follow-up da How to know what classes are represented in return array from predict_proba in Scikit-learnscikit-learn predict_proba fornisce risposte sbagliate

In questa domanda, ho citato il seguente codice:

>>> 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]]) 

ho scoperto in che domanda a questo risultato rappresenta la probabilità del punto appartenenti a ciascuna classe, nell'ordine dato dal model.classes_

>>> zip(model.classes_, model.predict_proba([1,2,3])[0]) 
[('apple', 0.39097541289393828), ('orange', 0.60902458710606167)] 

Quindi ... questa risposta, se correttamente interpretato, dice che il punto è probabilmente un 'arancione' (con una fiducia abbastanza bassa, a causa della piccola quantità di dati). Ma intuitivamente, questo risultato è ovviamente errato, poiché il punto indicato era identico ai dati di allenamento per "mela". Per sicurezza, ho provato anche il retro:

>>> zip(model.classes_, model.predict_proba([2,3,4])[0]) 
[('apple', 0.60705475211840931), ('orange', 0.39294524788159074)] 

Di nuovo, ovviamente errato, ma nella direzione opposta.

Infine, l'ho provato con punti che erano molto più lontani.

>>> 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)] 

Ancora, il modello prevede le probabilità errate. MA, la funzione model.predict ha ragione!

>>> model.predict([1,1,1])[0] 
'apple' 

Ora, mi ricordo di aver letto qualcosa nella documentazione su predict_proba essere impreciso per piccoli insiemi di dati, anche se non riesco a trovare di nuovo. È questo il comportamento previsto o sto facendo qualcosa di sbagliato? Se questo è il comportamento previsto, allora perché la funzione predice e predict_proba non concorda con l'output? E, soprattutto, quanto deve essere grande il set di dati prima di potermi fidare dei risultati di predict_proba?

-------- -------- UPDATE

Ok, così ho fatto un altro po 'esperimenti' in questo: il comportamento di predict_proba è fortemente dipendente 'n ', ma non in alcun modo prevedibile!

>>> 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)] 

Come si utilizza questa funzione in modo sicuro nel mio codice? Per lo meno, c'è qualche valore di n per il quale sarà garantito il consenso sul risultato di model.predict?

risposta

12

se si utilizza svm.LinearSVC() come stimatore e .decision_function() (che è come svm.SVC .predict_proba()) per ordinare i risultati dalla classe più probabile a quella meno probabile. questo è d'accordo con la funzione .predict().Inoltre, questo stimatore è più veloce e dà quasi gli stessi risultati con svm.SVC()

l'unico inconveniente per voi potrebbe essere che .decision_function() fornisce un valore con segno sth come tra -1 e 3 invece di un valore di probabilità. ma è d'accordo con la previsione.

+0

Questo è interessante Bilal ... Non ho davvero bisogno delle probabilità per il mio scopo, solo l'ordine. Penso che questa sia la risposta che sto cercando. – Alex

+0

Sì interessante. Ho avuto lo stesso problema e ho usato questo metodo per ordinare. Mi ha dato risultati migliori di predict_proba() –

+1

Si noti che 'LinearSVC()' produrrà previsioni simili a 'SVC (kernel =' linear ') 'ma non' SVC (kernel =' rbf ') 'che è il kernel predefinito per 'SVC'. – ogrisel

15

predict_probas sta usando la funzione Scala Platt di libsvm a callibrate probabilità, vedi:

Così in effetti le previsioni iperpiani e la calibrazione Proba può non essere d'accordo, soprattutto se si hanno solo 2 campioni nel set di dati. È strano che la convalida incrociata interna effettuata da libsvm per ridimensionare le probabilità non fallisca (esplicitamente) in questo caso. Forse questo è un bug. Uno dovrebbe tuffarsi nel codice di scala di Platt di libsvm per capire cosa sta succedendo.

+0

Solo aggiungendo a questo: In linea di principio la convalida incrociata deve essere d'accordo con il limite di decisione per il grande n. –

-1

C'è un po 'di confusione su ciò che in realtà fa predict_proba. Non predice le probabilità come suggerisce il titolo, ma emette le distanze. Nella mela vs arancione esempio 0,39097541, 0,60902459 la distanza più breve 0,39097541 è la classe di mele. che è contro intuitivo. stai guardando la più alta probabilità, ma non è il caso.

Un'altra fonte di confusione deriva dal fatto che predict_proba fa corrispondere le etichette rigide, solo non nell'ordine delle classi, da 0..n in sequenza. Scikit sembra mischiare le classi, ma è possibile mapparle.

ecco come funziona.

say we have 5 classes with labels: 
    classifier.classes_ = [0 1 2 3 4] 
    target names = ['1', '2', '3', '6', '8'] 

predetto etichette [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] 

nulla, ma la terza classe è una partita. in base alle etichette previste in cm, la classe 0 è prevista e la classe effettiva è 0 argmax (pred_prob). Ma, la sua mappato

 y_test [2 0 1 3 4] 

in modo da trovare la seconda classe

0    1    2   3   4 
    [ 0.20734121 0.20451986 0.17262553 0.20768649 0.20782692] 
    and the winner is **0.17262553** 

facciamolo di nuovo. guarda il risultato di classificazioni errate numero 4 dove lebel effettivo 4, previsto 1 secondo 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** 

Questi sono i miei 0,02.

Problemi correlati