c++ - neural - Abordar el desequilibrio de clase: contribución de escala a la pérdida y sgd
google neural network (2)
¿Por qué no usas la capa de InfogainLoss para compensar el desequilibrio en tu conjunto de entrenamiento?
La pérdida de Infogain se define utilizando una matriz de ponderación H
(en su caso 2 por 2). El significado de sus entradas es
[cost of predicting 1 when gt is 0, cost of predicting 0 when gt is 0
cost of predicting 1 when gt is 1, cost of predicting 0 when gt is 1]
Por lo tanto, puede establecer las entradas de H
para reflejar la diferencia entre los errores al predecir 0 o 1.
Puede encontrar cómo definir la matriz H
para caffe en este hilo .
En cuanto a los pesos de muestra, puede encontrar here interesante: muestra cómo modificar la capa de SoftmaxWithLoss para tener en cuenta los pesos de muestra.
Recientemente, Tsung-Yi Lin, Priya Goyal, Ross Girshick, Kaiming He y Piotr Dollár Focal Loss for Dense Object Detection (ICCV 2017) propusieron una modificación a la pérdida de entropía cruzada.
La idea detrás de la pérdida focal es asignar un peso diferente para cada ejemplo basado en la dificultad relativa de predecir este ejemplo (más bien en función del tamaño de la clase, etc.). A partir del breve tiempo en que pude experimentar con esta pérdida, se siente superior a "InfogainLoss"
con pesos de clase.
(Se ha agregado una actualización a esta pregunta).
Soy un estudiante graduado en la universidad de Ghent, Bélgica; mi investigación trata del reconocimiento de emociones con redes neuronales convolucionales profundas. Estoy usando el marco de Caffe para implementar las CNN.
Recientemente me encontré con un problema relacionado con el desequilibrio de clase. Estoy usando 9216 muestras de entrenamiento, aprox. 5% están etiquetados positivamente (1), las muestras restantes están etiquetadas negativamente (0).
Estoy usando la capa SigmoidCrossEntropyLoss para calcular la pérdida. Al entrenar, la pérdida disminuye y la precisión es extremadamente alta incluso después de algunas épocas. Esto se debe al desequilibrio: la red simplemente siempre predice negativo (0). (La precisión y el recuerdo son cero, respaldando esta afirmación)
Para resolver este problema, me gustaría escalar la contribución a la pérdida en función de la combinación predicción-verdad (castigar severamente los falsos negativos). Mi mentor / coach también me ha aconsejado que use un factor de escala cuando se retropropague a través del descenso de gradiente estocástico (sgd): el factor se correlacionaría con el desequilibrio en el lote. Un lote que contenga solo muestras negativas no actualizaría los pesos.
Solo agregué una capa hecha a medida a Caffe: para informar otras métricas, como precisión y recuperación. Mi experiencia con el código Caffe es limitada, pero tengo mucha experiencia escribiendo código C ++.
¿Alguien podría ayudarme o SigmoidCrossEntropyLoss en la dirección correcta sobre cómo ajustar las capas SigmoidCrossEntropyLoss y SigmoidCrossEntropyLoss para acomodar los siguientes cambios:
- ajustar la contribución de una muestra a la pérdida total según la combinación predicción-verdad (verdadero positivo, falso positivo, verdadero negativo, falso negativo).
- escala la actualización de peso realizada por descenso de gradiente estocástico dependiendo del desequilibrio en el lote (negativos vs. positivos).
¡Gracias por adelantado!
Actualizar
He incorporado el InfogainLossLayer como lo sugirió Shai . También agregué otra capa personalizada que construye la matriz de infogain sobre la base del desequilibrio en el lote actual.
Actualmente, la matriz está configurada de la siguiente manera:
H(i, j) = 0 if i != j
H(i, j) = 1 - f(i) if i == j (with f(i) = the frequency of class i in the batch)
Estoy planeando experimentar con diferentes configuraciones para la matriz en el futuro.
He probado esto con un desequilibrio de 10: 1. Los resultados han demostrado que la red está aprendiendo cosas útiles ahora: (resultados después de 30 épocas)
- La precisión es aprox. ~ 70% (por debajo de ~ 97%);
- La precisión es aprox. ~ 20% (por encima del 0%);
- Recordar es aprox. ~ 60% (por encima del 0%).
Estos números se alcanzaron en alrededor de 20 épocas y no cambiaron significativamente después de eso.
!! Los resultados indicados anteriormente son meramente una prueba de concepto, se obtuvieron al entrenar una red simple en un conjunto de datos desequilibrado 10: 1. !!
También he encontrado este problema de desequilibrio de clase en mi tarea de clasificación. En este momento estoy usando CrossEntropyLoss con peso (documentación here ) y funciona bien. La idea es dar más pérdidas a las muestras en las clases con menor cantidad de imágenes.
Cálculo del peso
peso para cada clase en inversamente proporcional al número de imagen en esta clase. Aquí hay un fragmento para calcular el peso de todas las clases usando numpy,
cls_num = []
# train_labels is a list of class labels for all training samples
# the labels are in range [0, n-1] (n classes in total)
train_labels = np.asarray(train_labels)
num_cls = np.unique(train_labels).size
for i in range(num_cls):
cls_num.append(len(np.where(train_labels==i)[0]))
cls_num = np.array(cls_num)
cls_num = cls_num.max()/cls_num
x = 1.0/np.sum(cls_num)
# the weight is an array which contains weight to use in CrossEntropyLoss
# for each class.
weight = x*cls_num