Abordar el desequilibrio de clase: escalando la contribución a la pérdida y sgd


(Se ha añadido una actualización a esta pregunta.)

Soy un estudiante graduado en la universidad de Gante, Bélgica; mi investigación es sobre el reconocimiento de emociones con redes neuronales convolucionales profundas. Estoy usando el framework Caffe para implementar el CNNs.

Recientemente me he encontrado con un problema relacionado con el desequilibrio de clase. Estoy usando muestras de entrenamiento 9216, aprox. el 5% se etiquetan positivamente (1), las muestras restantes se etiquetan negativamente (0).

Estoy usando la capa SigmoidCrossEntropyLoss para calcular la pérdida. Durante el entrenamiento, 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 ambos cero, respaldando esta afirmación)

Para resolver este problema, me gustaría escalar la contribución a la pérdida dependiendo de la combinación predicción-verdad (castigar severamente los falsos negativos). Mi mentor / coach también me ha aconsejado queuse un factor de escala cuando backpropagating a través del descenso de gradiente estocástico (sgd): el factor estaría correlacionado con el desequilibrio en el lote. Un lote que contenga solo muestras negativas no actualizaría los pesos en absoluto.

Solo he agregado una capa personalizada a Caffe: para reportar otras métricas como precisión y recuperación. Mi experiencia con el código Caffe es limitada, pero tengo mucha experiencia escribiendo C++ codificar.


¿Podría alguien ayudarme o señalarme en la dirección correcta sobre cómo ajustar las capas SigmoidCrossEntropyLoss y Sigmoid para acomodar los siguientes cambios:

  1. ajuste la contribución de una muestra a la pérdida total dependiendo de la combinación predicción-verdad (verdadero positivo, falso positivo, verdadero negativo, falso negativo).
  2. escala la actualización de peso realizada por descenso de gradiente estocástico dependiendo de la desequilibrio en el lote (negativos vs positivos).

Gracias de antemano!


Actualización

He incorporado el InfogainLossLayer como sugiere Shai. También he agregado otra capa personalizada que construye la matriz infogain H basada en el 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 en un desequilibrio 10:1. Los resultados han demostrado que la red está aprendiendo cosas útiles ahora: (resultados después de 30 épocas)

  • La precisión es de aprox. ~70% (por debajo de ~97%);
  • La precisión es de aprox. ~20% (desde 0%);
  • La recuperación es de aprox. ~60% (desde 0%).

Estos números se alcanzaron alrededor de 20 épocas y no cambiaron significativamente después de eso.

!! Los resultados indicados anteriormente son simplemente una prueba de concepto, se obtuvieron mediante el entrenamiento de una red simple en un conjunto de datos desequilibrados 10: 1. !!

Author: Community, 2015-05-27

2 answers

¿Por qué no usas el InfogainLoss capa para compensar el desequilibrio en su conjunto de entrenamiento?

La pérdida de Infogain se define utilizando una matriz de peso H (en su caso 2 por 2) El significado de sus entradas son

[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 en la predicción 0 o 1.

Puedes encontrar cómo definir matrix H para caffe en este hilo.

Con respecto a los pesos de la muestra, usted puede encuentra este post interesante: muestra cómo modificar la capa SoftmaxWithLoss para tener en cuenta los pesos de la muestra.


Recientemente, una modificación a la pérdida de entropía cruzada fue propuesta por Tsung-Yi Lin, Priya Goyal, Ross Girshick, Kaiming He, Piotr Dollár Pérdida Focal para la Detección de Objetos Densos, (ICCV 2017).
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 basado en el tamaño de la clase, etc.). Desde el breve tiempo que tuve que experimentar con esta pérdida, se siente superior a "InfogainLoss" con pesos de tamaño de clase.

 20
Author: Shai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-04 06:36:48

También me he encontrado con este problema de desequilibrio de clase en mi tarea de clasificación. Ahora mismo estoy usando CrossEntropyLoss con weight (documentación aquí) y funciona bien. La idea es dar más pérdida a las muestras en clases con menor número de imágenes.

Calculando el 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 toda la clase 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
 0
Author: jdhao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-04 03:55:01