Livello InfogainLoss

Desidero utilizzare uno strato di perdita di tipo InfogainLoss nel mio modello. Ma ho difficoltà a definirlo correttamente.

  1. Esiste un tutorial / esempio sull’uso del layer INFOGAIN_LOSS ?

  2. L’input di questo livello, le probabilità di class, dovrebbe essere l’output di un livello SOFTMAX , o è sufficiente inserire la “parte superiore” di un livello completamente connesso?

INFOGAIN_LOSS richiede tre input: probabilità di class, etichette e matrice H La matrice H può essere fornita come parametro di livello infogain_loss_param { source: "fiename" } .
Supponiamo di avere uno script python che calcola H come un numpy.array di forma (L,L) con dtype='f4' (dove L è il numero di etichette nel mio modello).

  1. Come posso convertire il mio numpy.array in un file binproto che può essere fornito come infogain_loss_param { source } al modello?

  2. Supponiamo di volere che H sia fornito come terzo input (in basso) allo strato di perdita (piuttosto che come parametro di modello). Come posso fare questo?
    Definisco un nuovo livello dati che “top” è H ? In tal caso, i dati di questo livello non dovrebbero essere incrementati ogni iterazione di addestramento come i dati di addestramento vengono incrementati? Come posso definire più strati di “dati” di input non collegati, e come fa il caffè a leggere dal batch di “formazione” dei dati di addestramento / test dopo il batch, mentre dal livello di “dati” H sa leggere solo una volta per tutto l’allenamento processi?

Non ho ancora una risposta completa alla mia domanda. Questa risposta copre solo la mia terza e quarta parte:
3. Come posso convertire un file numpy.array in un file di binproto :

In pitone

 H = np.eye( L, dtype = 'f4' ) import caffe blob = caffe.io.array_to_blobproto( H.reshape( (1,1,L,L) ) ) with open( 'infogainH.binaryproto', 'wb' ) as f : f.write( blob.SerializeToString() ) 

Ora puoi aggiungere al prototesto del modello il layer INFOGAIN_LOSS con H come parametro:

 layer { bottom: "topOfPrevLayer" bottom: "label" top: "infoGainLoss" name: "infoGainLoss" type: "InfogainLoss" infogain_loss_param { source: "infogainH.binaryproto" } } 

4. Come caricare H come parte di un livello DATI

Citando il post di Evan Shelhamer :

Al momento non è ansible effettuare il caricamento di strati di dati a velocità diverse. Ogni passaggio in avanti tutti i livelli di dati avanzeranno. Tuttavia, l’input H costante può essere fatto creando un file lmdb / leveldb / hdf5 di input che è solo H poiché il livello dati si interrompe e continua a caricare lo stesso H. Questo ovviamente spreca l’IO del disco.


Per quanto riguarda le prime due parti della mia domanda:
1. Esiste un tutorial / esempio sull’uso del livello InfogainLoss ? :
Un bell’esempio può essere trovato qui : usando InfogainLoss per affrontare lo squilibrio di class.

2. L’input di questo layer, le probabilità di class, dovrebbe essere l’output di un layer di Softmax ?
Secondo la risposta di Yair la risposta è SI dovrebbe essere l’output del livello Softmax (o qualsiasi altro livello che assicura che i valori di input siano nel range [0..1]).


Recentemente, ho notato che l’uso di "InfogainLoss" sopra al livello "Softmax" può portare all’instabilità numerica. Quindi suggerisco di combinare questi due strati in uno solo (molto simile al livello "SoftmaxWithLoss" ). Qui viene fornita la matematica di questo livello combinato. In questa richiesta di pull è ansible trovare un’implementazione di questo “combinato” infogainLoss + Softmax.

Il livello sta riassumendo

 -log(p_i) 

e quindi il p_i deve essere in (0, 1) per avere un senso come una funzione di perdita (altrimenti punteggi di fiducia più alti produrranno una perdita maggiore) .Vedi la curva sottostante per i valori di log (p).

inserisci la descrizione dell'immagine qui

Non penso che debbano riassumere fino a 1, ma passandoli attraverso uno strato di Softmax otterremo entrambe le proprietà.

Dal momento che ho dovuto cercare tra molti siti web per risolvere il codice completo, ho pensato di condividere la mia implementazione:

Layer Python per il calcolo della matrice H con pesi per ogni class:

 import numpy as np import caffe class ComputeH(caffe.Layer): def __init__(self, p_object, *args, **kwargs): super(ComputeH, self).__init__(p_object, *args, **kwargs) self.n_classs = -1 def setup(self, bottom, top): if len(bottom) != 1: raise Exception("Need (only) one input to compute H matrix.") params = eval(self.param_str) if 'n_classs' in params: self.n_classs = int(params['n_classs']) else: raise Exception('The number of classs (n_classs) must be specified.') def reshape(self, bottom, top): top[0].reshape(1, 1, self.n_classs, self.n_classs) def forward(self, bottom, top): classs, cls_num = np.unique(bottom[0].data, return_counts=True) if np.size(classs) != self.n_classs or self.n_classs == -1: raise Exception("Invalid number of classs") cls_num = cls_num.astype(float) cls_num = cls_num.max() / cls_num weights = cls_num / np.sum(cls_num) top[0].data[...] = np.diag(weights) def backward(self, top, propagate_down, bottom): pass 

e la parte relativa da train_val.prototxt:

 layer { name: "computeH" bottom: "label" top: "H" type: "Python" python_param { module: "digits_python_layers" layer: "ComputeH" param_str: '{"n_classs": 7}' } exclude { stage: "deploy" } } layer { name: "loss" type: "InfogainLoss" bottom: "score" bottom: "label" bottom: "H" top: "loss" infogain_loss_param { axis: 1 # compute loss and probability along axis } loss_param { normalization: 0 } exclude { stage: "deploy" } }