Estoy tratando de entrenar a una CNN para clasificar el texto por tema. Cuando uso entropía cruzada binaria obtengo ~ 80% de precisión, con entropía cruzada categórica obtengo ~ 50% de precisión.
No entiendo por qué es esto. Es un problema multiclase, ¿eso no significa que tengo que usar entropía cruzada categórica y que los resultados con entropía cruzada binaria no tienen sentido?
model.add(embedding_layer)
model.add(Dropout(0.25))
# convolution layers
model.add(Conv1D(nb_filter=32,
filter_length=4,
border_mode='valid',
activation='relu'))
model.add(MaxPooling1D(pool_length=2))
# dense layers
model.add(Flatten())
model.add(Dense(256))
model.add(Dropout(0.25))
model.add(Activation('relu'))
# output layer
model.add(Dense(len(class_id_index)))
model.add(Activation('softmax'))
Luego lo compilo o bien así categorical_crossentropy
como la función de pérdida:
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
o
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
Intuitivamente tiene sentido por qué me gustaría utilizar la entropía cruzada categórica, no entiendo por qué obtengo buenos resultados con binario y malos resultados con categórico.
machine-learning
keras
neural-network
deep-learning
conv-neural-network
Daniel Messias
fuente
fuente
categorical_crossentropy
. También las etiquetas deben convertirse al formato categórico. Mirato_categorical
para hacer esto. También vea las definiciones de las crossentropías categóricas y binarias aquí .categorical_crossentropy
. Si tiene dos clases, se representarán como0, 1
en etiquetas binarias y10, 01
en formato de etiqueta categórica.Dense(1, activation='softmax')
porque la clasificación binaria es simplemente incorrecta. Recuerde que la salida de softmax es una distribución de probabilidad que se suma a uno. Si desea tener solo una neurona de salida con clasificación binaria, use sigmoide con entropía cruzada binaria.Respuestas:
La razón de esta aparente discrepancia de rendimiento entre la entropía cruzada categórica y binaria es lo que el usuario xtof54 ya ha informado en su respuesta a continuación , es decir:
Me gustaría dar más detalles sobre esto, demostrar el problema subyacente real, explicarlo y ofrecer un remedio.
Este comportamiento no es un error; La razón subyacente es un problema bastante sutil e indocumentado sobre cómo Keras realmente adivina qué precisión usar, dependiendo de la función de pérdida que haya seleccionado, cuando se incluye simplemente
metrics=['accuracy']
en la compilación de su modelo. En otras palabras, mientras tu primera opción de compilaciónes válido, tu segundo:
no producirá lo que espera, pero la razón no es el uso de entropía cruzada binaria (que, al menos en principio, es una función de pérdida absolutamente válida).
¿Porqué es eso? Si marca el código fuente de las métricas , Keras no define una sola métrica de precisión, sino varias, entre ellas
binary_accuracy
ycategorical_accuracy
. Lo que sucede debajo del capó es que, dado que seleccionó la entropía cruzada binaria como su función de pérdida y no especificó una métrica de precisión particular, Keras (erróneamente ...) infiere que le interesabinary_accuracy
, y esto es lo que devuelve: mientras que de hecho estás interesado en elcategorical_accuracy
.Verifiquemos que este sea el caso, utilizando el ejemplo MNIST CNN en Keras, con la siguiente modificación:
Para remediar esto, es decir, para utilizar la entropía cruzada binaria como su función de pérdida (como dije, no hay nada de malo en esto, al menos en principio) mientras obtiene la precisión categórica requerida por el problema en cuestión, debe solicitarlo explícitamente
categorical_accuracy
en el compilación del modelo de la siguiente manera:En el ejemplo MNIST, después de entrenar, puntuar y predecir el conjunto de pruebas como muestro arriba, las dos métricas ahora son las mismas, como deberían ser:
Configuración del sistema:
ACTUALIZACIÓN : Después de mi publicación, descubrí que este problema ya se había identificado en esta respuesta .
fuente
loss='categorical_crossentropy', metrics=['categorical_accuracy']
para la clasificación multiclase? Esta sería mi intuiciónTodo depende del tipo de problema de clasificación con el que esté lidiando. Hay tres categorías principales.
En el primer caso, se debe utilizar la entropía cruzada binaria y los objetivos deben codificarse como vectores de un solo calor.
En el segundo caso, se debe utilizar la entropía cruzada categórica y los objetivos deben codificarse como vectores de un solo calor.
En el último caso, se debe utilizar la entropía cruzada binaria y los objetivos deben codificarse como vectores de un solo calor. Cada neurona de salida (o unidad) se considera como una variable binaria aleatoria separada, y la pérdida para todo el vector de salidas es el producto de la pérdida de variables binarias individuales. Por lo tanto, es el producto de la entropía cruzada binaria para cada unidad de salida individual.
La entropía cruzada binaria se define como
y la entropía cruzada categórica se define como
donde
c
se ejecuta el índice sobre el número de clasesfuente
c
índice es redundante en la fórmula binaria de entropía cruzada, no necesita estar allí (ya que solo hay 2 clases y la probabilidad de que cada clase esté incorporaday(x)
. De lo contrario, esas fórmulas deberían ser correctas, pero cuenta esas no son las pérdidas, esas son las probabilidades Si desea que la pérdida que tiene que tomar el.log
de éstos.Encontré un problema "invertido": estaba obteniendo buenos resultados con categorical_crossentropy (con 2 clases) y pobre con binary_crossentropy. Parece que el problema fue con la función de activación incorrecta. La configuración correcta fue:
binary_crossentropy
: activación sigmoidea, objetivo escalarcategorical_crossentropy
: activación softmax, objetivo codificado en calientefuente
Es un caso realmente interesante. En realidad, en su configuración, la siguiente afirmación es verdadera:
Esto significa que hasta un factor de multiplicación constante sus pérdidas son equivalentes. El comportamiento extraño que estás observando durante una fase de entrenamiento podría ser un ejemplo de un fenómeno siguiente:
adam
, la tasa de aprendizaje tiene un valor mucho menor que al principio del entrenamiento (es debido a la naturaleza de este optimizador). Hace que el entrenamiento sea más lento y evita que su red, por ejemplo, deje un mínimo local pobre menos posible.Es por eso que este factor constante podría ayudar en caso de
binary_crossentropy
. Después de muchas épocas, el valor de la tasa de aprendizaje es mayor que en elcategorical_crossentropy
caso. Por lo general, reinicio el entrenamiento (y la fase de aprendizaje) algunas veces cuando noto tal comportamiento y / y ajusto los pesos de una clase usando el siguiente patrón:Esto hace que la pérdida de clases menos frecuentes equilibre la influencia de una pérdida de clase dominante al comienzo de un entrenamiento y en una parte adicional de un proceso de optimización.
EDITAR:
En realidad, lo comprobé aunque en el caso de las matemáticas:
debe mantenerse, en caso de
keras
que no sea cierto, porquekeras
está normalizando automáticamente todas las salidas para resumir1
. Esta es la razón real detrás de este comportamiento extraño, ya que en caso de multiclasificación, tal normalización daña un entrenamiento.fuente
Después de comentar la respuesta de @Marcin, he revisado con más cuidado el código de uno de mis estudiantes donde encontré el mismo comportamiento extraño, ¡incluso después de solo 2 épocas! (Entonces, la explicación de @ Marcin no era muy probable en mi caso).
Y descubrí que la respuesta es realmente muy simple: la precisión calculada con el método Keras
evaluate
es simplemente incorrecta cuando se usa binary_crossentropy con más de 2 etiquetas. Puede verificarlo volviendo a calcular la precisión usted mismo (primero llame al método de Keras "predecir" y luego calcule el número de respuestas correctas devueltas por predecir): obtiene la verdadera precisión, que es mucho menor que la de "evaluar" Keras.fuente
Un ejemplo simple en un entorno de varias clases para ilustrar
supongamos que tiene 4 clases (codificadas con un solo disparo) y a continuación hay solo una predicción
true_label = [0,1,0,0] predicted_label = [0,0,1,0]
cuando se utiliza categorical_crossentropy, la precisión es solo 0, solo le importa si obtiene la clase correcta.
sin embargo, cuando se usa binary_crossentropy, la precisión se calcula para todas las clases, sería del 50% para esta predicción. y el resultado final será la media de las precisiones individuales para ambos casos.
se recomienda utilizar categorical_crossentropy para el problema de varias clases (las clases se excluyen mutuamente) pero binary_crossentropy para el problema de múltiples etiquetas.
fuente
Como es un problema de varias clases, debe usar la categorical_crossentropy, la entropía cruzada binaria producirá resultados falsos, lo más probable es que solo evalúe las dos primeras clases.
El 50% para un problema de varias clases puede ser bastante bueno, dependiendo del número de clases. Si tiene n clases, entonces 100 / n es el rendimiento mínimo que puede obtener al generar una clase aleatoria.
fuente
al usar la
categorical_crossentropy
pérdida, sus objetivos deben estar en formato categórico (por ejemplo, si tiene 10 clases, el objetivo para cada muestra debe ser un vector de 10 dimensiones que es todo ceros, excepto un 1 en el índice correspondiente a la clase de muestra).fuente
Eche un vistazo a la ecuación y descubra que la entropía cruzada binaria no solo castiga a esas etiquetas = 1, predichas = 0, sino también a etiquetas = 0, predichas = 1.
Sin embargo, la entropía cruzada categórica solo castiga a esas etiquetas = 1 pero predice = 1. Es por eso que asumimos que solo hay UNA etiqueta positiva.
fuente
Está pasando una matriz de formas objetivo (x-dim, y-dim) mientras usa como pérdida
categorical_crossentropy
.categorical_crossentropy
espera que los objetivos sean matrices binarias (1s y 0s) de forma (muestras, clases). Si sus objetivos son clases enteras, puede convertirlas al formato esperado a través de:Alternativamente, puede usar la función de pérdida
sparse_categorical_crossentropy
, que espera objetivos enteros.fuente
La binary_crossentropy (y_target, y_predict) no necesita aplicarse en un problema de clasificación binaria. .
En el código fuente de binary_crossentropy () , en
nn.sigmoid_cross_entropy_with_logits(labels=target, logits=output)
realidad se utilizó la función TensorFlow. Y, en la documentación , dice que:fuente