binary_crossentropy와 categorical_crossentropy가 동일한 문제에 대해 다른 성능을 제공하는 이유는 무엇입니까?


160

주제별로 텍스트를 분류하도록 CNN을 훈련하려고합니다. 이진 교차 엔트로피를 사용하면 ~ 80 % 정확도를 얻을 수 있으며 범주 형 교차 엔트로피를 사용하면 ~ 50 % 정확도를 얻을 수 있습니다.

왜 그런지 이해할 수 없습니다. 그것은 다중 클래스 문제입니다. 즉, 범주 교차 엔트로피를 사용해야하며 이진 교차 엔트로피 결과가 의미가 없다는 것을 의미하지 않습니까?

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'))

그런 다음 categorical_crossentropy손실 함수로 사용하여 다음과 같이 컴파일합니다 .

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

또는

model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

직관적으로 범주 형 교차 엔트로피를 사용하려는 이유는 이해가되며, 왜 바이너리로 좋은 결과를 얻었는지, 범주 적으로 나쁜 결과를 얻는 이유를 이해하지 못합니다.


10
다중 클래스 문제인 경우을 사용해야 categorical_crossentropy합니다. 또한 레이블을 범주 형식으로 변환해야합니다. 이 작업을 참조하십시오 to_categorical. 또한 categorical 및 binary crossentropies의 정의를 참조 하십시오 .
자치

내 레이블은 범주 형이며 to_categorical (각 클래스에 대해 하나의 핫 벡터)을 사용하여 생성됩니다. 이것은 이진 교차 엔트로피의 ~ 80 % 정확도가 가짜 숫자라는 것을 의미합니까?
Daniel Messias

나도 그렇게 생각해. 범주 형 레이블, 즉 하나의 핫 벡터를 사용하는 경우 원하는 것 categorical_crossentropy입니다. 클래스가 두 개인 경우 0, 1이진 레이블 및 10, 01범주 레이블 형식으로 표시됩니다.
자치

1
나는 그가 벡터의 첫 번째 숫자와 비교하고 나머지는 무시한다고 생각합니다.
Thomas Pinetz 2012

2
@NilavBaranGhosh 두 클래스를 포함하는 범주 적 분류 ([[0, 0], [0, 1]] 아님)에 대한 표현은 [[1, 0], [0, 1]]입니다. Dense(1, activation='softmax')이진 분류의 경우 단순히 잘못되었습니다. softmax 출력은 1에 합산 된 확률 분포를 기억하십시오. 이진 분류를 사용하여 하나의 출력 뉴런 만 가지려면 이진 교차 엔트로피와 함께 시그 모이 드를 사용하십시오.
자치

답변:


204

범주 형 및 이진 교차 엔트로피 간의 이러한 명백한 성능 불일치의 이유는 xtof54 사용자가 아래의 답변 에서 이미보고 한 것입니다 .

evaluate2 개 이상의 레이블이있는 binary_crossentropy를 사용할 때 Keras 방법으로 계산 된 정확도 가 잘못되었습니다.

이에 대해 자세히 설명하고 실제 근본적인 문제를 설명하고 설명하며 해결책을 제시하고 싶습니다.

이 동작은 버그가 아닙니다. 근본적인 이유는 단순히 모델 컴파일에 포함시킬 때 선택한 손실 함수에 따라 Keras가 실제로 어느 정확도를 사용 할지 추측 하는 방법에있어 미묘하고 문서화되지 않은 문제 metrics=['accuracy']입니다. 즉, 첫 번째 컴파일 옵션 동안

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

두 번째 것은 유효합니다.

model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

당신이 기대하는 것을 생산하지는 않지만 그 이유는 이진 교차 엔트로피 (적어도 원칙적으로는 절대적으로 유효한 손실 함수입니다)를 사용하지 않기 때문입니다.

왜 그런 겁니까? 당신이 선택하면 측정 소스 코드를 , Keras는 하나의 정확도 측정하지만, 그 중 몇 가지 것들, 정의하지 않습니다 binary_accuracycategorical_accuracy. 후드 아래에서 발생 하는 것은 손실 함수로 이진 교차 엔트로피를 선택하고 특정 정확도 메트릭을 지정하지 않았기 때문에 Keras (잘못 ...)는에 관심이 있다고 추측하고 binary_accuracy이것이 반환되는 것입니다. 실제로 당신은에 관심이 categorical_accuracy있습니다.

KerasMNIST CNN 예제 를 사용하여 다음과 같이 수정 된 경우인지 확인하십시오.

model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])  # WRONG way

model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=2,  # only 2 epochs, for demonstration purposes
          verbose=1,
          validation_data=(x_test, y_test))

# Keras reported accuracy:
score = model.evaluate(x_test, y_test, verbose=0) 
score[1]
# 0.9975801164627075

# Actual accuracy calculated manually:
import numpy as np
y_pred = model.predict(x_test)
acc = sum([np.argmax(y_test[i])==np.argmax(y_pred[i]) for i in range(10000)])/10000
acc
# 0.98780000000000001

score[1]==acc
# False    

이 문제를 해결하려면, 즉 실제로 이진 크로스 엔트로피를 손실 함수로 사용하려면 (적어도 원칙적으로는 아무 문제가 없습니다) 문제에 필요한 범주 정확도를 얻으려면 명시 적으로 요청해야 categorical_accuracy합니다. 다음과 같이 모델 컴파일 :

from keras.metrics import categorical_accuracy
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=[categorical_accuracy])

MNIST 예제에서 위에서 보여준 것처럼 테스트 세트를 훈련, 스코어링 및 예측 한 후에는 두 메트릭이 동일해야합니다.

# Keras reported accuracy:
score = model.evaluate(x_test, y_test, verbose=0) 
score[1]
# 0.98580000000000001

# Actual accuracy calculated manually:
y_pred = model.predict(x_test)
acc = sum([np.argmax(y_test[i])==np.argmax(y_pred[i]) for i in range(10000)])/10000
acc
# 0.98580000000000001

score[1]==acc
# True    

시스템 설치:

Python version 3.5.3
Tensorflow version 1.2.1
Keras version 2.0.4

업데이트 : 내 게시물을 보낸 후이 답변 에서이 문제가 이미 확인되었습니다 .


1
loss='categorical_crossentropy', metrics=['categorical_accuracy']멀티 클래스 분류에 사용 하는 데 문제가 있습니까? 이것은 내 직감 일 것입니다
NeStack

2
@NeStack 아무 문제가 없을뿐만 아니라 이것은 명목상의 조합입니다.
desertnaut

1
당신이 말한 것에 따르면, 내가 loss = 'binary_crossentropy'를 사용하는 한, metrics = 'binary_accuracy'또는 metrics = 'accuracy'를 사용하는 동일한 결과를 얻지 못할 것입니다.
BioCoder

2
@BioCoder 정확하게
desertnaut

54

그것은 모두 당신이 다루고있는 분류 문제의 유형에 달려 있습니다. 세 가지 주요 범주가 있습니다

  • 이진 분류 (2 개의 대상 클래스)
  • 멀티 클래스 분류 (2 개 이상의 독점 대상)
  • 여러 개의 대상 클래스가 동시에 존재할 수있는 다중 레이블 분류 ( 독점적이지 않은 두 개 이상의 대상).

첫 번째 경우에는 이진 교차 엔트로피를 사용해야하며 대상은 one-hot 벡터로 인코딩되어야합니다.

두 번째 경우에는 범주 형 교차 엔트로피를 사용해야하며 대상은 one-hot 벡터로 인코딩되어야합니다.

마지막 경우에는 이진 교차 엔트로피를 사용해야하며 대상은 one-hot 벡터로 인코딩되어야합니다. 각 출력 뉴런 (또는 단위)은 별도의 임의 이진 변수로 간주되며 전체 출력 벡터의 손실은 단일 이진 변수의 손실의 곱입니다. 따라서 각 단일 출력 단위에 대한 이진 교차 엔트로피의 곱입니다.

이진 교차 엔트로피는 다음과 같이 정의됩니다.

여기에 이미지 설명을 입력하십시오

범주 형 교차 엔트로피는 다음과 같이 정의됩니다.

여기에 이미지 설명을 입력하십시오

c클래스 수에 대해 인덱스가 실행 되는 위치 는 어디 입니까?


귀하의 답변은 매우 사실이지만, ... @desertnaut 답변을 따르려고 시도하고 테스트를 수행했습니다. binary_crossentropy loss function 및 metrcis to categorical_accurency 나는 categorical_crossentropy loss function 및 accurency metrics를 사용하는 것이 더 정확합니다.
Metal3d

@ Metal3d : 문제의 공식은 무엇입니까 : 다중 레이블 또는 단일 레이블?
Whynote

단일 레이블, 그리고 나는 왜 그것이 더 잘 작동하는지 알고 있습니다 :)
Metal3d

이항 및 카테고리 간 엔트로피가이 답변의 수식에서 정의 된 것입니까?
nbro

@nbro, 실제로는 c인덱스가 이진 교차 엔트로피 수식에 중복되어있을 필요가 없습니다 (2 개의 클래스 만 있고 각 클래스의 확률이에 포함되어 있기 때문에) y(x). 그렇지 않으면 수식이 정확해야하지만 그들이다없는 손실을 발견, 사람들은 우도는 당신이 손실을 원한다면 당신이 가지고해야합니다. log이런.
Whynote

40

"반전 된"문제가 발생했습니다. categorical_crossentropy (2 개 클래스 포함)에서는 좋은 결과를 얻었고 binary_crossentropy에서는 좋지 않았습니다. 문제가 잘못된 활성화 기능인 것 같습니다. 올바른 설정은 다음과 같습니다.

  • 대한 binary_crossentropy: 시그 모이 드 활성화, 스칼라 대상
  • categorical_crossentropy: softmax를 활성화 한 핫 부호화 대상

4
binary_crossentropy의 스칼라 대상이 확실합니까? "many-hot"인코딩 대상을 사용해야하는 것 같습니다 (예 : [0 1 0 0 1 1]).
Dmitry

5
확실한. keras.io/losses/#usage-of-loss-functions를 참조하십시오 . "categorical_crossentropy loss를 사용하는 경우 대상은 범주 형식이어야합니다 (예 : 10 개의 클래스가있는 경우 각 샘플의 대상은 10이어야합니다) 모두 0 인 차원 벡터는 샘플의 클래스에 해당하는 인덱스에서 1을 기대합니다) "
Alexander Svetkin

1
그러나 우리는 categorical_crossentropy가 아니라 binary_crossentropy에 대해 이야기하고 있습니다.
Dmitry

이 답변은 stackoverflow.com/a/49175655/3924118 과 일치하지 않는 것 같습니다 . 여기서 대상은 원 핫 인코딩해야하며 답변에서는 스칼라 여야한다고 제안합니다. 이것을 명확히해야합니다.
nbro

@AlexanderSvetkin, 범주 형 교차 엔트로피를 사용할 때뿐만 아니라 대상을 모든 곳에서 핫 인코딩해야합니다
Whynote

28

정말 흥미로운 사건입니다. 실제로 설정에서 다음 내용은 적용됩니다.

binary_crossentropy = len(class_id_index) * categorical_crossentropy

이것은 일정한 곱셈 계수까지 손실이 동등하다는 것을 의미합니다. 훈련 단계에서 관찰되는 이상한 행동은 다음 현상의 예일 수 있습니다.

  1. 처음에는 가장 빈번한 클래스가 손실을 지배하고 있으므로 네트워크는 모든 예제에 대해 대부분이 클래스를 예측하는 것을 배우고 있습니다.
  2. 가장 빈번한 패턴을 알게되면 덜 빈번한 클래스를 구별하기 시작합니다. 그러나 당신이 사용할 때 adam-학습 속도는 훈련을 시작할 때보 다 훨씬 적습니다 (이 옵티마이 저의 특성 때문입니다). 그것은 훈련 속도를 늦추고 당신의 네트워크가 예를 들어 빈약 한 지역 최소값을 남겨 두는 것을 방지합니다.

이것이이 상수 요소가의 경우에 도움이되는 이유입니다 binary_crossentropy. 많은 시대 이후-학습 속도 값은 categorical_crossentropy경우 보다 큽니다 . 나는 일반적으로 다음과 같은 패턴을 사용하여 그러한 행동을 보거나 수업 가중치를 조정하면 훈련 (및 학습 단계)을 몇 번 다시 시작합니다.

class_weight = 1 / class_frequency

이것은 훈련이 시작될 때와 최적화 과정의 추가 부분에서 지배적 인 클래스 손실의 영향을 균형 잡히는 덜 빈번한 클래스의 손실을 만듭니다.

편집하다:

실제로-수학의 경우에도 확인했습니다.

binary_crossentropy = len(class_id_index) * categorical_crossentropy

모든 출력을 합산하여 자동으로 정규화 keras하기 때문에 true가 아닌 경우 보류해야 keras합니다 1. 이것이 다중 분류의 경우 이러한 정규화가 훈련에 해를 끼치기 때문에이 이상한 행동의 배후에있는 실제 이유입니다.


내 대답이 도움이 되었습니까?
Marcin Możejko

1
이것은 매우 그럴듯한 설명입니다. 그러나 그것이 주된 이유인지 확실하지 않습니다. 또한 여러 학생들이 cat-X-ent 대신 binary-X-ent를 적용 할 때이 이상한 행동을하는 것을 관찰했기 때문에 (실수입니다). 그리고 이것은 단지 2 시대를 훈련 할 때도 마찬가지입니다! 역 클래스 우선 순위와 함께 class_weight를 사용하면 도움이되지 않았습니다. 학습 속도를 엄격하게 조정하면 도움이 될 수 있지만 기본값은 bin-X-ent를 선호하는 것으로 보입니다. 이 질문에 더 많은 조사가 필요하다고 생각합니다.
xtof54

1
기다리십시오, 죄송합니다, 귀하의 업데이트를받지 못했습니다 : softmax는 항상 출력을 1로 만듭니다. 그래서 우리는 그것에 대해 신경 쓰지 않습니까? 그리고 우리가 예에 맞는 단 하나의 금 종류 만 가지고 있다면 왜이 훈련에 해를 끼치겠습니까?
xtof54 2016 년

20

@Marcin 답변을 언급 한 후, 나는 2 번의 획기 이후에도 동일한 이상한 행동을 발견 한 학생 코드 중 하나를 더 신중하게 확인했습니다! (따라서 @Marcin의 설명은 제 경우에는별로 가능성이 없었습니다).

그리고 대답은 실제로 매우 간단하다는 것을 evaluate알았습니다. Keras 방법으로 계산 된 정확도 는 2 개 이상의 레이블이있는 binary_crossentropy를 사용할 때 잘못되었습니다. 정확성을 직접 재 계산하여 확인할 수 있습니다 (먼저 Keras 메소드를 "predict"로 호출 한 다음 예측으로 리턴 된 정답 수를 계산하십시오). Keras "evaluate"보다 훨씬 낮은 실제 정확도를 얻습니다.


1
첫 번째 반복에서도 비슷한 동작을 보았습니다.
dolbi

10

설명하기 위해 다중 클래스 설정에서 간단한 예

4 개의 클래스 (onehot encoding)가 있고 아래는 하나의 예측이라고 가정하십시오.

true_label = [0,1,0,0] predicted_label = [0,0,1,0]

categorical_crossentropy를 사용할 때 정확도는 0이며 관련 클래스를 올바르게 얻는 지 여부 만 신경 쓰입니다.

그러나 binary_crossentropy를 사용하는 경우 모든 클래스에 대해 정확도가 계산되며이 예측의 경우 50 %입니다. 최종 결과는 두 경우 모두 개별 정확도의 평균이됩니다.

다중 클래스 문제는 categorical_crossentropy를 사용하고 다중 레이블 문제는 binary_crossentropy를 사용하는 것이 좋습니다.


8

다중 클래스 문제이므로 categorical_crossentropy를 사용해야합니다. 이진 교차 엔트로피는 가짜 결과를 생성하며 대부분 첫 두 클래스 만 평가합니다.

클래스 수에 따라 멀티 클래스 문제의 50 %가 상당히 우수 할 수 있습니다. n 개의 클래스가있는 경우 임의 클래스를 출력하여 얻을 수있는 최소 성능은 100 / n입니다.


2

categorical_crossentropy손실을 사용할 때 목표는 범주 형식이어야합니다 (예 : 10 개의 클래스가있는 경우 각 샘플의 목표는 10의 벡터로, 0의 클래스는 해당 클래스의 인덱스에 해당하는 인덱스의 1을 제외하고 모두 0이어야 함) 견본).


3
이것이 정확히 질문에 어떻게 대답합니까?
desertnaut

2

이진 교차 엔트로피 가 해당 레이블 = 1을 예측할뿐만 아니라 = 0을 예측할뿐만 아니라 레이블 = 0, 예측 = 1 을 나타내는 방정식을 살펴보십시오 .

그러나 범주 형 교차 엔트로피 는 해당 레이블 = 1 만 처벌하지만 예측 된 = 1입니다. 따라서 레이블이 하나만 있다고 가정합니다.


1

loss로 사용하는 동안 모양 (x-dim, y-dim)의 대상 배열을 전달합니다 categorical_crossentropy. categorical_crossentropy목표는 모양 (샘플, 클래스)의 이진 행렬 (1과 0)이 될 것으로 예상합니다. 대상이 정수 클래스 인 경우 다음을 통해 예상 형식으로 변환 할 수 있습니다.

from keras.utils import to_categorical
y_binary = to_categorical(y_int)

또는 sparse_categorical_crossentropy정수 목표를 예상 하는 loss 함수를 대신 사용할 수 있습니다 .

model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

0

binary_crossentropy (y_target, y_predict)는 이진 분류 문제에 적용 할 필요가 없습니다. .

소스 코드에서 binary_crossentropy ()nn.sigmoid_cross_entropy_with_logits(labels=target, logits=output)TensorFlow 함수는 실제로 사용되었다. 그리고 설명서 에서 다음과 같이 말합니다.

각 클래스가 독립적이며 상호 배타적이지 않은 불연속 분류 작업에서 확률 오류를 측정합니다. 예를 들어, 그림이 코끼리와 개를 동시에 포함 할 수있는 다중 레이블 분류를 수행 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.