numpy neural-network protocol-buffers deep-learning caffe

numpy - Capa de pérdida de información



neural-network protocol-buffers (3)

Deseo utilizar una capa de pérdida del tipo InfogainLoss en mi modelo. Pero estoy teniendo dificultades para definirlo correctamente.

  1. ¿Hay algún tutorial / ejemplo sobre el uso de la capa INFOGAIN_LOSS ?

  2. ¿Debería la entrada a esta capa, las probabilidades de clase, ser la salida de una capa SOFTMAX , o es suficiente para ingresar la "parte superior" de una capa totalmente conectada?

INFOGAIN_LOSS requiere tres entradas: probabilidades de clase, etiquetas y la matriz H La matriz H se puede proporcionar como parámetros de capa infogain_loss_param { source: "fiename" } .
Supongamos que tengo un script de Python que calcula H como una numpy.array de formas (L,L) con dtype=''f4'' (donde L es el número de etiquetas en mi modelo).

  1. ¿Cómo puedo convertir mi numpy.array en un archivo binproto que se puede proporcionar como un infogain_loss_param { source } para el modelo?

  2. Supongamos que quiero que se proporcione H como la tercera entrada (inferior) a la capa de pérdida (en lugar de como un parámetro de modelo). ¿Cómo puedo hacer esto?
    ¿Defino una nueva capa de datos que "arriba" es H ? Si es así, ¿no se aumentarían los datos de esta capa en cada iteración de entrenamiento como se incrementan los datos de entrenamiento? ¿Cómo puedo definir múltiples capas de "datos" de entrada no relacionadas, y cómo sabe Caffe leer de la capa de "datos" de entrenamiento / prueba lote tras lote, mientras que de la capa de "datos" H sabe leer solo una vez durante todo el entrenamiento ¿proceso?


Como tuve que buscar en muchos sitios web para descifrar el código completo, pensé en compartir mi implementación:

Capa de Python para calcular la matriz H con pesos para cada clase:

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_classes = -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_classes'' in params: self.n_classes = int(params[''n_classes'']) else: raise Exception(''The number of classes (n_classes) must be specified.'') def reshape(self, bottom, top): top[0].reshape(1, 1, self.n_classes, self.n_classes) def forward(self, bottom, top): classes, cls_num = np.unique(bottom[0].data, return_counts=True) if np.size(classes) != self.n_classes or self.n_classes == -1: raise Exception("Invalid number of classes") 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

y la parte relevante del train_val.prototxt:

layer { name: "computeH" bottom: "label" top: "H" type: "Python" python_param { module: "digits_python_layers" layer: "ComputeH" param_str: ''{"n_classes": 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" } }


La capa se resume

-log(p_i)

y entonces el p_i necesita estar en (0, 1] para tener sentido como una función de pérdida (de lo contrario, puntuaciones de confianza más altas producirán una pérdida más alta). Vea la curva a continuación para conocer los valores de log (p).

No creo que tengan que sumar 1, pero pasarlos a través de una capa Softmax logrará ambas propiedades.


1. ¿Hay algún tutorial / ejemplo sobre el uso de la capa InfogainLoss ? :
Un buen ejemplo se puede encontrar here : usar InfogainLoss para abordar el desequilibrio de clase.

2. ¿Debería la entrada a esta capa, las probabilidades de clase, ser la salida de una capa Softmax ?
Históricamente, la respuesta solía ser según la respuesta de Yair . La antigua implementación de "InfogainLoss" necesitaba ser la salida de la capa "Softmax" o cualquier otra capa que asegure que los valores de entrada estén en el rango [0..1].

El notó que usar "InfogainLoss" encima de la capa "Softmax" puede provocar inestabilidad numérica. Su solicitud de extracción , que combina estas dos capas en una sola (al igual que la capa "SoftmaxWithLoss" ), fue aceptada y fusionada en los repositorios oficiales de Caffe el 14/04/2017. here se dan las matemáticas de esta capa combinada.

La "apariencia" de la capa mejorada es exactamente igual a la anterior, aparte del hecho de que ya no es necesario pasar explícitamente la entrada a través de una capa "Softmax" .

3. ¿Cómo puedo convertir un numpy.array en un archivo binproto ?

En pitón

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

Ahora puede agregar al INFOGAIN_LOSS modelo la capa INFOGAIN_LOSS con H como parámetro:

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

4. Cómo cargar H como parte de una capa DATA

Citando la publicación de Evan Shelhamer :

Actualmente no hay forma de hacer que las capas de datos carguen entradas a diferentes velocidades. Cada paso hacia adelante todas las capas de datos avanzarán. Sin embargo, la entrada constante de H podría hacerse haciendo un archivo de entrada lmdb / leveldb / hdf5 que sea solo H ya que la capa de datos se repetirá y seguirá cargando la misma H. ​​Esto obviamente desperdicia el disco IO.