Tại sao binary_crossentropy và c sortical_crossentropy cung cấp các hiệu suất khác nhau cho cùng một vấn đề?


159

Tôi đang cố gắng đào tạo một CNN để phân loại văn bản theo chủ đề. Khi tôi sử dụng entropy chéo nhị phân, tôi có độ chính xác ~ 80%, với entropy chéo phân loại tôi có độ chính xác ~ 50%.

Tôi không hiểu tại sao lại như vậy. Đó là một vấn đề đa kính, không có nghĩa là tôi phải sử dụng entropy chéo phân loại và kết quả với entropy chéo nhị phân là vô nghĩa?

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

Sau đó, tôi biên dịch nó hoặc nó như thế này bằng cách sử dụng categorical_crossentropyhàm mất:

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

hoặc là

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

Theo trực giác, nó có ý nghĩa tại sao tôi muốn sử dụng entropy chéo phân loại, tôi không hiểu tại sao tôi nhận được kết quả tốt với nhị phân và kết quả kém với phân loại.


10
Nếu đó là một vấn đề đa kính, bạn phải sử dụng categorical_crossentropy. Ngoài ra các nhãn cần phải chuyển đổi sang định dạng phân loại. Xem to_categoricalđể làm điều này. Cũng xem định nghĩa của crossentropies phân loại và nhị phân ở đây .
Tự trị

Nhãn của tôi là phân loại, được tạo bằng cách sử dụng to_c sortical (một vectơ nóng cho mỗi lớp). Điều đó có nghĩa là độ chính xác ~ 80% từ crossentropy nhị phân chỉ là một con số không có thật?
Daniel Messias

Tôi nghĩ vậy. Nếu bạn sử dụng nhãn phân loại tức là một vectơ nóng, thì bạn muốn categorical_crossentropy. Nếu bạn có hai lớp, chúng sẽ được thể hiện dưới dạng 0, 1nhãn nhị phân và 10, 01ở định dạng nhãn phân loại.
Tự trị

1
Tôi nghĩ rằng anh ta chỉ so sánh với số đầu tiên trong vector và bỏ qua phần còn lại.
Thomas Pinetz

2
@NilavBaranGhosh Đại diện sẽ là [[1, 0], [0, 1]] cho một phân loại phân loại liên quan đến hai lớp (không phải [[0, 0], [0, 1]] như bạn đề cập). Dense(1, activation='softmax')để phân loại nhị phân đơn giản là sai. Hãy nhớ đầu ra softmax là phân phối xác suất tính tổng thành một. Nếu bạn muốn chỉ có một nơ ron đầu ra với phân loại nhị phân, hãy sử dụng sigmoid với entropy chéo nhị phân.
Tự trị

Câu trả lời:


204

Lý do cho sự khác biệt hiệu suất rõ ràng này giữa entropy chéo phân loại & nhị phân là những gì người dùng xtof54 đã báo cáo trong câu trả lời của mình dưới đây , nghĩa là:

độ chính xác được tính toán bằng phương pháp Keras evaluatehoàn toàn sai khi sử dụng binary_crossentropy với hơn 2 nhãn

Tôi muốn giải thích thêm về vấn đề này, chứng minh vấn đề thực tế tiềm ẩn, giải thích nó và đưa ra một biện pháp khắc phục.

Hành vi này không phải là một lỗi; lý do cơ bản là một vấn đề khá tinh tế & không có giấy tờ về cách Keras thực sự đoán độ chính xác sẽ sử dụng, tùy thuộc vào chức năng mất mà bạn đã chọn, khi bạn đưa đơn giản metrics=['accuracy']vào trình biên dịch mô hình của mình. Nói cách khác, trong khi tùy chọn biên dịch đầu tiên của bạn

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

là hợp lệ, cái thứ hai của bạn:

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

sẽ không tạo ra những gì bạn mong đợi, nhưng lý do không phải là việc sử dụng entropy chéo nhị phân (mà, ít nhất là về nguyên tắc, là một hàm mất hoàn toàn hợp lệ).

Tại sao vậy? Nếu bạn kiểm tra mã nguồn số liệu , Keras không xác định một số liệu chính xác duy nhất, nhưng một số chỉ số khác nhau, trong số đó binary_accuracycategorical_accuracy. Điều xảy ra dưới mui xe là vì bạn đã chọn entropy chéo nhị phân làm hàm mất mát của mình và chưa chỉ định một số liệu chính xác cụ thể, Keras (sai ...) cho rằng bạn quan tâm đến binary_accuracy, và đây là những gì nó trả về - trong khi trên thực tế bạn đang quan tâm đến categorical_accuracy.

Hãy xác minh rằng đây là trường hợp, sử dụng ví dụ MNIST CNN trong Keras, với sửa đổi sau:

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    

Để khắc phục điều này, tức là sử dụng entropy thực nhị phân chéo như chức năng mất mát của bạn (như tôi đã nói, không có gì sai với điều này, ít nhất là về nguyên tắc) trong khi vẫn nhận được phân loại chính xác theo yêu cầu của vấn đề trong tầm tay, bạn nên yêu cầu một cách rõ ràng cho categorical_accuracytrong tổng hợp mô hình như sau:

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

Trong ví dụ của MNIST, sau khi đào tạo, ghi điểm và dự đoán bộ kiểm tra như tôi trình bày ở trên, hai số liệu bây giờ giống nhau, như chúng phải là:

# 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    

Thiết lập hệ thống:

Python version 3.5.3
Tensorflow version 1.2.1
Keras version 2.0.4

CẬP NHẬT : Sau bài viết của tôi, tôi phát hiện ra rằng vấn đề này đã được xác định trong câu trả lời này .


1
Có điều gì sai với việc sử dụng loss='categorical_crossentropy', metrics=['categorical_accuracy']để phân loại đa lớp? Đây sẽ là trực giác của tôi
NeStack

2
@NeStack Không chỉ không có gì sai, mà đây là sự kết hợp danh nghĩa.
sa mạc

1
Theo những gì bạn nói, miễn là tôi sử dụng loss = 'binary_crossentropy', tôi sẽ nhận được lợi nhuận tương tự mà tôi không sử dụng metrics = 'binary_accuracy' hoặc metrics = 'precision'?
BioCoder

2
@BioCoder chính xác
Sahnaut

54

Tất cả phụ thuộc vào loại vấn đề phân loại bạn đang giải quyết. Có ba loại chính

  • phân loại nhị phân (hai lớp mục tiêu),
  • phân loại nhiều lớp (nhiều hơn hai mục tiêu độc quyền ),
  • phân loại nhiều nhãn (nhiều hơn hai mục tiêu không độc quyền ), trong đó nhiều lớp mục tiêu có thể được bật cùng một lúc.

Trong trường hợp đầu tiên, nên sử dụng entropy chéo nhị phân và các mục tiêu phải được mã hóa dưới dạng các vectơ nóng.

Trong trường hợp thứ hai, nên sử dụng entropy chéo phân loại và các mục tiêu nên được mã hóa dưới dạng các vectơ nóng.

Trong trường hợp cuối cùng, nên sử dụng entropy chéo nhị phân và các mục tiêu phải được mã hóa dưới dạng các vectơ nóng. Mỗi nơ ron đầu ra (hoặc đơn vị) được coi là một biến nhị phân ngẫu nhiên riêng biệt và tổn thất cho toàn bộ vectơ đầu ra là sản phẩm của việc mất các biến nhị phân đơn. Do đó, nó là sản phẩm của entropy chéo nhị phân cho mỗi đơn vị đầu ra duy nhất.

Entropy chéo nhị phân được định nghĩa là

nhập mô tả hình ảnh ở đây

và entropy chéo phân loại được định nghĩa là

nhập mô tả hình ảnh ở đây

nơi cđược chỉ số chạy qua số lượng các lớp học


Câu trả lời của bạn có vẻ rất đúng với tôi, nhưng ... Tôi đã cố gắng làm theo câu trả lời @desertnaut và đã thực hiện bài kiểm tra đó: Với hàm mất binary_crossentropy và metrcis để phân loại_accurency Tôi có độ chính xác tốt hơn khi sử dụng hàm mất phân loại và độ chính xác - và tôi không thể giải thích rằng ...
Metal3d

@ Metal3d: công thức của vấn đề của bạn là gì: đa nhãn hay đơn nhãn?
Whynote

nhãn đơn, và bây giờ tôi nhận ra lý do tại sao nó hoạt động tốt hơn :)
Metal3d

Bạn có chắc chắn rằng các entropies chéo nhị phân và phân loại được định nghĩa như trong các công thức trong câu trả lời này?
nbro

@nbro, thực ra, cchỉ mục là dự phòng trong công thức entropy nhị phân, nó không cần ở đó (vì chỉ có 2 lớp và xác suất của mỗi lớp được nhúng vào y(x). Nếu không, các công thức đó phải chính xác, nhưng Lưu ý rằng đó không phải là những mất mát, đó là những khả năng. Nếu bạn muốn mất mát, bạn phải thực hiện lognhững điều này.
Whynote

40

Tôi đã gặp một vấn đề "đảo ngược" - Tôi đã nhận được kết quả tốt với c sortical_crossentropy (với 2 lớp) và kém với binary_crossentropy. Có vẻ như vấn đề là với chức năng kích hoạt sai. Các cài đặt chính xác là:

  • cho binary_crossentropy: kích hoạt sigmoid, mục tiêu vô hướng
  • cho categorical_crossentropy: kích hoạt softmax, mục tiêu được mã hóa một lần nóng

4
Bạn có chắc chắn về mục tiêu vô hướng cho binary_crossentropy. Có vẻ như bạn nên sử dụng mục tiêu được mã hóa "nhiều nóng" (ví dụ: [0 1 0 0 1 1]).
Dmitry

5
Chắc chắn rồi. Xem keras.io/losses/#usage-of-loss-fifts , nó nói: "khi sử dụng tổn thất phân loại, các mục tiêu của bạn phải ở định dạng phân loại (ví dụ: nếu bạn có 10 lớp, mục tiêu cho mỗi mẫu sẽ là 10 vectơ hai chiều là tất cả các số không mong đợi cho 1 tại chỉ số tương ứng với lớp của mẫu) "
Alexander Svetkin

1
Nhưng chúng tôi đang nói về binary_crossentropy - không phải phân loại_crossentropy.
Dmitry

Câu trả lời này dường như không nhất quán với stackoverflow.com/a/49175655/3924118 , trong đó tác giả nói rằng các mục tiêu nên được mã hóa một lần, trong khi, trong câu trả lời của bạn, bạn đề nghị chúng nên là vô hướng. Bạn nên làm rõ điều này.
nbro

@AlexanderSvetkin, mục tiêu phải được mã hóa một lần ở khắp mọi nơi, không chỉ khi sử dụng entropy chéo phân loại
Whynote

28

Đó là trường hợp thực sự thú vị. Trên thực tế trong thiết lập của bạn, tuyên bố sau đây là đúng:

binary_crossentropy = len(class_id_index) * categorical_crossentropy

Điều này có nghĩa là lên đến một hệ số nhân không đổi, tổn thất của bạn là tương đương. Hành vi kỳ lạ mà bạn đang quan sát trong giai đoạn huấn luyện có thể là một ví dụ về hiện tượng sau:

  1. Lúc đầu, lớp thường xuyên nhất đang chi phối sự mất mát - vì vậy mạng đang học cách dự đoán phần lớn lớp này cho mọi ví dụ.
  2. Sau khi nó học được mô hình thường xuyên nhất, nó bắt đầu phân biệt giữa các lớp ít thường xuyên hơn. Nhưng khi bạn đang sử dụng adam- tỷ lệ học tập có giá trị nhỏ hơn nhiều so với lúc bắt đầu đào tạo (đó là do bản chất của trình tối ưu hóa này). Nó làm cho việc đào tạo chậm hơn và ngăn chặn mạng của bạn, ví dụ như để lại mức tối thiểu tại địa phương kém.

Đó là lý do tại sao yếu tố không đổi này có thể giúp đỡ trong trường hợp binary_crossentropy. Sau nhiều kỷ nguyên - giá trị tỷ lệ học tập lớn hơn trong categorical_crossentropytrường hợp. Tôi thường khởi động lại đào tạo (và giai đoạn học tập) một vài lần khi tôi nhận thấy hành vi đó hoặc / và điều chỉnh trọng số lớp bằng cách sử dụng mẫu sau:

class_weight = 1 / class_frequency

Điều này làm cho tổn thất từ ​​một lớp ít thường xuyên hơn cân bằng ảnh hưởng của mất lớp chiếm ưu thế khi bắt đầu đào tạo và trong một phần tiếp theo của quá trình tối ưu hóa.

BIÊN TẬP:

Trên thực tế - tôi đã kiểm tra rằng mặc dù trong trường hợp toán học:

binary_crossentropy = len(class_id_index) * categorical_crossentropy

nên giữ - trong trường hợp keraskhông đúng, vì kerastự động bình thường hóa tất cả các kết quả đầu ra để tổng hợp 1. Đây là lý do thực sự đằng sau hành vi kỳ lạ này như trong trường hợp đa lớp hóa việc bình thường hóa như vậy gây hại cho đào tạo.


Có câu trả lời của tôi đã giúp bạn?
Marcin Możejko

1
Đây là một lời giải thích rất hợp lý. Nhưng tôi không chắc đó thực sự là lý do chính. Bởi vì tôi cũng đã quan sát thấy ở một số học sinh của mình thực hiện hành vi kỳ lạ này khi áp dụng nhị phân X-ent thay vì cat-X-ent (đó là một sai lầm). Và điều này đúng ngay cả khi đào tạo chỉ 2 epoch! Sử dụng class_ weight với các thầy tu lớp nghịch đảo không giúp được gì. Có thể điều chỉnh nghiêm ngặt tỷ lệ học tập sẽ giúp ích, nhưng các giá trị mặc định dường như thiên về bin-X-ent. Tôi nghĩ rằng câu hỏi này xứng đáng được điều tra nhiều hơn ...
xtof54

1
Đợi đã, xin lỗi, tôi không nhận được cập nhật của bạn: softmax luôn làm cho kết quả đầu ra là 1, vì vậy chúng tôi không quan tâm đến điều đó? Và tại sao điều này lại gây hại cho đào tạo, miễn là chúng ta chỉ có một lớp vàng duy nhất đúng với mỗi ví dụ?
xtof54

20

Sau khi nhận xét câu trả lời @Marcin, tôi đã kiểm tra kỹ hơn một trong những mã sinh viên của mình, nơi tôi tìm thấy hành vi kỳ lạ tương tự, thậm chí chỉ sau 2 epoch! (Vì vậy, lời giải thích của @ Marcin không có khả năng trong trường hợp của tôi).

Và tôi thấy rằng câu trả lời thực sự rất đơn giản: độ chính xác được tính toán bằng phương pháp Keras evaluatehoàn toàn sai khi sử dụng binary_crossentropy với hơn 2 nhãn. Bạn có thể kiểm tra xem bằng cách tự tính lại độ chính xác (trước tiên hãy gọi phương thức Keras là "dự đoán" và sau đó tính số câu trả lời đúng được dự đoán): bạn có được độ chính xác thực sự, thấp hơn nhiều so với phương pháp "đánh giá" của Keras.


1
Tôi đã thấy hành vi tương tự trên lần lặp đầu tiên là tốt.
cá heo

10

một ví dụ đơn giản dưới một thiết lập nhiều lớp để minh họa

giả sử bạn có 4 lớp (được mã hóa một lần) và bên dưới chỉ là một dự đoán

true_label = [0,1,0,0] dự đoán_label = [0,0,1,0]

khi sử dụng c sortical_crossentropy, độ chính xác chỉ là 0, nó chỉ quan tâm nếu bạn có được lớp liên quan đúng.

tuy nhiên khi sử dụng binary_crossentropy, độ chính xác được tính cho tất cả các lớp, nó sẽ là 50% cho dự đoán này. và kết quả cuối cùng sẽ là giá trị trung bình của độ chính xác riêng cho cả hai trường hợp.

nên sử dụng c sortical_crossentropy cho bài toán nhiều lớp (các lớp loại trừ lẫn nhau) nhưng binary_crossentropy cho bài toán nhiều nhãn.


8

Vì đây là một vấn đề đa lớp, bạn phải sử dụng phân loại_crossentropy, entropy chéo nhị phân sẽ tạo ra kết quả không có thật, rất có thể sẽ chỉ đánh giá hai lớp đầu tiên.

50% cho một vấn đề đa lớp có thể khá tốt, tùy thuộc vào số lượng lớp. Nếu bạn có n lớp, thì 100 / n là hiệu suất tối thiểu bạn có thể nhận được bằng cách xuất ra một lớp ngẫu nhiên.


2

khi sử dụng categorical_crossentropytổn thất, các mục tiêu của bạn phải ở định dạng phân loại (ví dụ: nếu bạn có 10 lớp, mục tiêu cho mỗi mẫu phải là một vectơ 10 chiều là tất cả các số 0 ngoại trừ 1 tại chỉ số tương ứng với lớp của mẫu vật).


3
Làm thế nào chính xác điều này trả lời câu hỏi?
Sahnaut

2

Hãy nhìn vào phương trình mà bạn có thể thấy rằng entropy chéo nhị phân không chỉ trừng phạt những nhãn đó = 1, dự đoán = 0, mà còn nhãn = 0, dự đoán = 1.

Tuy nhiên, entropy chéo phân loại chỉ trừng phạt những nhãn đó = 1 nhưng dự đoán = 1. Đó là lý do tại sao chúng tôi đưa ra giả định rằng chỉ có MỘT nhãn tích cực.


1

Bạn đang truyền một mảng mục tiêu có hình dạng (x-dim, y-dim) trong khi sử dụng làm mất categorical_crossentropy. categorical_crossentropydự kiến ​​các mục tiêu sẽ là ma trận nhị phân (1s và 0) hình dạng (mẫu, lớp). Nếu mục tiêu của bạn là các lớp nguyên, bạn có thể chuyển đổi chúng sang định dạng mong đợi thông qua:

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

Ngoài ra, bạn có thể sử dụng hàm mất sparse_categorical_crossentropythay thế, điều này không mong đợi các mục tiêu nguyên.

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

0

Binary_crossentropy (y_target, y_predict) không cần phải áp dụng trong bài toán phân loại nhị phân. .

Trong mã nguồn của binary_crossentropy () , nn.sigmoid_cross_entropy_with_logits(labels=target, logits=output)hàm TensorFlow đã thực sự được sử dụng. Và, trong tài liệu , nó nói rằng:

Đo lường lỗi xác suất trong các nhiệm vụ phân loại riêng biệt trong đó mỗi lớp là độc lập và không loại trừ lẫn nhau. Chẳng hạn, người ta có thể thực hiện phân loại đa nhãn trong đó một bức ảnh có thể chứa cả voi và chó cùng một lúc.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.