주제별로 텍스트를 분류하도록 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'])
직관적으로 범주 형 교차 엔트로피를 사용하려는 이유는 이해가되며, 왜 바이너리로 좋은 결과를 얻었는지, 범주 적으로 나쁜 결과를 얻는 이유를 이해하지 못합니다.
답변
범주 형 및 이진 교차 엔트로피 간의 이러한 명백한 성능 불일치의 이유는 xtof54 사용자가 아래의 답변 에서 이미보고 한 것입니다 .
evaluate
2 개 이상의 레이블이있는 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_accuracy
와 categorical_accuracy
. 후드 아래에서 발생 하는 것은 손실 함수로 이진 교차 엔트로피를 선택하고 특정 정확도 메트릭을 지정하지 않았기 때문에 Keras (잘못 …)는에 관심이 있다고 추측하고 binary_accuracy
이것이 반환되는 것입니다. 실제로 당신은에 관심이 categorical_accuracy
있습니다.
Keras 의 MNIST 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
업데이트 : 내 게시물을 보낸 후이 답변 에서이 문제가 이미 확인되었습니다 .
답변
그것은 모두 당신이 다루고있는 분류 문제의 유형에 달려 있습니다. 세 가지 주요 범주가 있습니다
- 이진 분류 (2 개의 대상 클래스)
- 멀티 클래스 분류 (2 개 이상의 독점 대상)
- 여러 개의 대상 클래스가 동시에 존재할 수있는 다중 레이블 분류 ( 독점적이지 않은 두 개 이상의 대상).
첫 번째 경우에는 이진 교차 엔트로피를 사용해야하며 대상은 one-hot 벡터로 인코딩되어야합니다.
두 번째 경우에는 범주 형 교차 엔트로피를 사용해야하며 대상은 one-hot 벡터로 인코딩되어야합니다.
마지막 경우에는 이진 교차 엔트로피를 사용해야하며 대상은 one-hot 벡터로 인코딩되어야합니다. 각 출력 뉴런 (또는 단위)은 별도의 임의 이진 변수로 간주되며 전체 출력 벡터의 손실은 단일 이진 변수의 손실의 곱입니다. 따라서 각 단일 출력 단위에 대한 이진 교차 엔트로피의 곱입니다.
이진 교차 엔트로피는 다음과 같이 정의됩니다.
범주 형 교차 엔트로피는 다음과 같이 정의됩니다.
c
클래스 수에 대해 인덱스가 실행 되는 위치 는 어디 입니까?
답변
“반전 된”문제가 발생했습니다. categorical_crossentropy (2 개 클래스 포함)에서는 좋은 결과를 얻었고 binary_crossentropy에서는 좋지 않았습니다. 문제가 잘못된 활성화 기능인 것 같습니다. 올바른 설정은 다음과 같습니다.
- 대한
binary_crossentropy
: 시그 모이 드 활성화, 스칼라 대상 - 대
categorical_crossentropy
: softmax를 활성화 한 핫 부호화 대상
답변
정말 흥미로운 사건입니다. 실제로 설정에서 다음 내용은 적용됩니다.
binary_crossentropy = len(class_id_index) * categorical_crossentropy
이것은 일정한 곱셈 계수까지 손실이 동등하다는 것을 의미합니다. 훈련 단계에서 관찰되는 이상한 행동은 다음 현상의 예일 수 있습니다.
- 처음에는 가장 빈번한 클래스가 손실을 지배하고 있으므로 네트워크는 모든 예제에 대해 대부분이 클래스를 예측하는 것을 배우고 있습니다.
- 가장 빈번한 패턴을 알게되면 덜 빈번한 클래스를 구별하기 시작합니다. 그러나 당신이 사용할 때
adam
-학습 속도는 훈련을 시작할 때보 다 훨씬 적습니다 (이 옵티마이 저의 특성 때문입니다). 그것은 훈련 속도를 늦추고 당신의 네트워크가 예를 들어 빈약 한 지역 최소값을 남겨 두는 것을 방지합니다.
이것이이 상수 요소가의 경우에 도움이되는 이유입니다 binary_crossentropy
. 많은 시대 이후-학습 속도 값은 categorical_crossentropy
경우 보다 큽니다 . 나는 일반적으로 다음과 같은 패턴을 사용하여 그러한 행동을 보거나 수업 가중치를 조정하면 훈련 (및 학습 단계)을 몇 번 다시 시작합니다.
class_weight = 1 / class_frequency
이것은 훈련이 시작될 때와 최적화 과정의 추가 부분에서 지배적 인 클래스 손실의 영향을 균형 잡히는 덜 빈번한 클래스의 손실을 만듭니다.
편집하다:
실제로-수학의 경우에도 확인했습니다.
binary_crossentropy = len(class_id_index) * categorical_crossentropy
모든 출력을 합산하여 자동으로 정규화 keras
하기 때문에 true가 아닌 경우 보류해야 keras
합니다 1
. 이것이 다중 분류의 경우 이러한 정규화가 훈련에 해를 끼치기 때문에이 이상한 행동의 배후에있는 실제 이유입니다.
답변
@Marcin 답변을 언급 한 후, 나는 2 번의 획기 이후에도 동일한 이상한 행동을 발견 한 학생 코드 중 하나를 더 신중하게 확인했습니다! (따라서 @Marcin의 설명은 제 경우에는별로 가능성이 없었습니다).
그리고 대답은 실제로 매우 간단하다는 것을 evaluate
알았습니다. Keras 방법으로 계산 된 정확도 는 2 개 이상의 레이블이있는 binary_crossentropy를 사용할 때 잘못되었습니다. 정확성을 직접 재 계산하여 확인할 수 있습니다 (먼저 Keras 메소드를 “predict”로 호출 한 다음 예측으로 리턴 된 정답 수를 계산하십시오). Keras “evaluate”보다 훨씬 낮은 실제 정확도를 얻습니다.
답변
설명하기 위해 다중 클래스 설정에서 간단한 예
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를 사용하는 것이 좋습니다.
답변
다중 클래스 문제이므로 categorical_crossentropy를 사용해야합니다. 이진 교차 엔트로피는 가짜 결과를 생성하며 대부분 첫 두 클래스 만 평가합니다.
클래스 수에 따라 멀티 클래스 문제의 50 %가 상당히 우수 할 수 있습니다. n 개의 클래스가있는 경우 임의 클래스를 출력하여 얻을 수있는 최소 성능은 100 / n입니다.