Tengo un problema de clasificación con datos altamente desequilibrados. He leído que sobremuestrear y submuestrear, así como cambiar el costo de resultados categóricos subrepresentados, conducirá a una mejor adaptación. Antes de que esto se hiciera, tensorflow clasificaría cada entrada como el grupo mayoritario (y obtendría más del 90% de precisión, por insignificante que sea).
He notado que el registro del porcentaje inverso de cada grupo ha hecho el mejor multiplicador que he probado. ¿Existe una manipulación más estándar para la función de costo? ¿Se implementa esto correctamente?
from collections import Counter
counts = Counter(category_train)
weightsArray =[]
for i in range(n_classes):
weightsArray.append(math.log(category_train.shape[0]/max(counts[i],1))+1)
class_weight = tf.constant(weightsArray)
weighted_logits = tf.mul(pred, class_weight)
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(weighted_logits, y))
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
Respuestas:
Esto parece una buena solución para la función de pérdida. He tenido éxito con un enfoque similar recientemente, pero creo que querrías reordenar donde multiplicas en
class_weight
.Pensando en ello lógicamente,
class_weight
será una constante wrt la salida, por lo que se llevará a lo largo y se aplicará al gradiente de la misma manera que se aplica a la función de costo. Sin embargo, hay un problema.De la forma en que lo tenga,
class_weight
afectaría el valor de predicción. Pero desea que afecte la escala del gradiente. Si no me equivoco, creo que querría invertir el orden de las operaciones:Me interesaría saber cómo funciona esto en comparación con simplemente sobremuestrear la clase subrepresentada, lo cual es más típico. Entonces, si obtienes alguna idea, ¡publica al respecto! :)
Curiosamente, utilicé con éxito una técnica muy similar en un dominio de problemas diferente recientemente (lo que me trajo a esta publicación):
Aprendizaje de tareas múltiples, encontrar una función de pérdida que "ignora" ciertas muestras
fuente
Pago
tf.nn.weighted_cross_entropy_with_logits()
:Esto debería permitirte hacer lo que quieras.
fuente
Tengo 2 implementaciones diferentes:
Donde class_weight es un marcador de posición, lo relleno en la iteración por lotes de everey.
Donde uso la función de tensorflow implementada pero necesito calcular los pesos para el lote. Los documentos son un poco confusos al respecto. Hay 2 formas de hacerlo con tf.gather o de esta manera:
aquí hay una buena discusión al respecto
Y, finalmente, como no quería casarme con ninguna de las implementaciones de manera permanente, agregué un poco de tf.case y pasé el tiempo de entrenamiento a la estrategia que quiero usar.
fuente