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.
-
¿Hay algún tutorial / ejemplo sobre el uso de la capa
INFOGAIN_LOSS
? -
¿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).
-
¿Cómo puedo convertir mi
numpy.array
en un archivobinproto
que se puede proporcionar como uninfogain_loss_param { source }
para el modelo? -
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" esH
? 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
SÍ
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.