Quale funzione di perdita per compiti di classificazione multi-classe e multi-etichetta nelle reti neurali?


64

Sto addestrando una rete neurale per classificare un insieme di oggetti in n-classi. Ogni oggetto può appartenere a più classi contemporaneamente (multi-classe, multi-etichetta).

Ho letto che per problemi multi-classe è generalmente raccomandato l'uso di softmax e entropia incrociata categorica come funzione di perdita invece di mse e capisco più o meno perché.

Per il mio problema con l'etichetta multipla non avrebbe senso usare il softmax ovviamente poiché ogni probabilità di classe dovrebbe essere indipendente dall'altra. Quindi il mio livello finale sono solo unità sigmoidi che schiacciano i loro input in un intervallo di probabilità 0..1 per ogni classe.

Ora non sono sicuro di quale funzione di perdita dovrei usare per questo. Osservando la definizione di crossentropia categorica, credo che non si applicherebbe bene a questo problema in quanto prenderà in considerazione solo l'output di neuroni che dovrebbero essere 1 e ignora gli altri.

L'entropia incrociata binaria sembra che si adatterebbe meglio, ma la vedo solo menzionata per problemi di classificazione binaria con un singolo neurone in uscita.

Sto usando Python e Keras per allenarmi nel caso in cui sia importante.


1
Credo che softmax sia "unità sigmoidi che schiacciano i loro input in un intervallo di probabilità 0..1 per ogni classe".
Hong Ooi,

Puoi utilizzare softmax come funzione di perdita e quindi utilizzare le probabilità per rendere multietichetti i tuoi dati.
balboa

Risposte:


30

Se stai usando keras, metti semplicemente sigmoidi sul tuo livello di output e binary_crossentropy sulla tua funzione di costo.

Se stai usando tensorflow, puoi usare sigmoid_cross_entropy_with_logits . Ma nel mio caso questa funzione di perdita diretta non stava convergendo. Così ho finito per usare la perdita esplicita di entropia incrociata sigmoide . Puoi crearne uno tuo in questo esempio(yln(sigmoid(logits))+(1y)ln(1sigmoid(logits)))

Sigmoid, a differenza di softmax, non fornisce distribuzione di probabilità intorno a come output, ma probabilità indipendenti.nclasses

Se in media a una riga vengono assegnate meno etichette, è possibile utilizzare softmax_cross_entropy_with_logits perché con questa perdita mentre le classi si escludono a vicenda, le loro probabilità non devono esserlo. Tutto ciò che serve è che ogni riga di etichette sia una distribuzione di probabilità valida. In caso contrario, il calcolo del gradiente non sarà corretto.


Caro Alok, puoi spiegare all'OP come farebbero per usare questa funzione e perché ha senso? Come vedrai nel tour , sul sito non sono incoraggiate solo le risposte ai link.
Antoine Vernet,

Una bella breve spiegazione può essere vista in keras github: github.com/fchollet/keras/issues/741
Dror Hilman

1
Non è consigliabile scrivere la propria funzione di costo quando si utilizza l'entropia incrociata: può essere soggetto a problemi di stabilità numerica. Vedi github.com/tensorflow/tensorflow/issues/2462 per una discussione.
kbrose,

Una cosa è multilabel, un'altra cosa è multilabel multiclasse. Sigmoid schiaccia il tuo output tra 0 e 1, ma l'OP ha più classi, quindi gli output dovrebbero essere per esempio 0 - 10. Quindi gli output dovrebbero apparire: [0,5,2,3,1] <--- questo non è ciò che sigmoid lo fa.
mimoralea,

dovrei tf.round (logit) prima di usarlo nella funzione di costo o posso usare direttamente i log dal layer nascosto a tf.nn.sigmoid ....?
Monaco

9

AGGIORNAMENTO (18/04/18): la vecchia risposta si è dimostrata utile sul mio modello. Il trucco è modellare la funzione di partizione e la distribuzione separatamente, sfruttando così la potenza di softmax.

Considera il tuo vettore di osservazione per contenere etichette. (1 se il campione i contiene l'etichetta m, 0 altrimenti). Quindi l'obiettivo sarebbe quello di modellare la matrice in un modo per campione. Quindi il modello valuta . espandere per ottenere due proprietà:ymyim=δimF(yi,xi)=logP(yi|xi)yim=ZP(ym)

  1. Funzione di distribuzione:mP(ym)=1
  2. Funzione di partizione: stima il numero di etichetteZ

Quindi si tratta di modellare i due separatamente. La funzione di distribuzione è modellata al meglio con un layer softmax e la funzione di partizione può essere modellata con un'unità lineare (in pratica l'ho ritagliata come . Una modellazione più sofisticata come l'unità Poisson probabilmente funzionerebbe meglio). Quindi puoi scegliere di applicare la perdita distribuita (KL sulla distribuzione e MSE sulla partizione) oppure puoi provare la seguente perdita sul loro prodotto.max(0.01,output)

In pratica, anche la scelta dell'ottimizzatore fa una grande differenza. La mia esperienza con l'approccio alla fattorizzazione è che funziona meglio con Adadelta (Adagrad non funziona per me, non ho ancora provato RMSprop, le prestazioni di SGD sono soggette a parametro).

Commento laterale su sigmoid : ho sicuramente provato sigmoid + crossentropy e non ha funzionato. Il modello tendeva a prevedere solo la e non riusciva a catturare la variazione nella funzione di distribuzione. (aka, è in qualche modo abbastanza utile per modellare la partizione e potrebbe esserci una ragione matematica dietro di essa)Z

AGGIORNAMENTO : (Pensiero casuale) Sembra che l'utilizzo del processo Dirichlet consentirebbe l'incorporazione di alcuni precedenti sul numero di etichette?

AGGIORNAMENTO : Per esperimento, la divergenza KL modificata è ancora incline a fornire output multi-classe anziché output multi-etichetta.


(Vecchia risposta)

La mia esperienza con l'entropia sigmoidea non è stata molto piacevole. Al momento sto usando una divergenza di KL modificata. Prende la forma

Loss(P,Q)=x|P(x)Q(x)||logP(x)Q(x)|=x|(P(x)Q(x))logP(x)Q(x)|
Dove è la pseudo-distribuzione target e è la pseudo-distribuzione prevista (ma la funzione è in realtà simmetrica, quindi non ha importanza)P(x)Q(x)

Sono chiamati pseudo-distribuzioni per non essere normalizzati. Quindi puoi avere se hai 2 etichette per un particolare campione.xP(x)=2

Impelmentazione di Keras

def abs_KL_div(y_true, y_pred):
    y_true = K.clip(y_true, K.epsilon(), None)
    y_pred = K.clip(y_pred, K.epsilon(), None)
    return K.sum( K.abs( (y_true- y_pred) * (K.log(y_true / y_pred))), axis=-1)

nel mio particolare set di dati, adamera molto meglio dirmsprop
shadi

Se usi tale perdita per l'allenamento, come farlo in fase di test? Utilizzare anche softmax per la previsione, ma come selezionare la soglia per determinare le classi multi-etichetta?
karl_TUM,


0

In realtà in tensorsflow è ancora possibile utilizzare la sigmoid_cross_entropy_meanfunzione di calcolo delle perdite in multi-etichetta, lo confermo molto


Dacci un link alla documentazione
Ivelin,

0

Sono un principiante qui, ma proverò a provarlo con questa domanda. Stavo cercando la tua stessa cosa e alla fine ho trovato un ottimo tutorial di classificazione multi-classe di keras @ http://machinelearningmastery.com/multi-class-classification-tutorial-keras-deep-learning-library/ .

L'autore di quel tutorial usa la categorica funzione di perdita di entropia incrociata, e ci sono altri thread che possono aiutarti a trovare la soluzione @ qui .


3
Non è solo multi classe, ma anche multi etichette.
Monaco
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.