Как создать взвешенную перекрестную энтропийную потерю?

Мне приходится иметь дело с сильно несбалансированными данными. Насколько я понимаю, мне нужно использовать взвешенную кросс-энтропийную потерю.

Я пробовал это:

import tensorflow as tf

weights = np.array([<values>])
def loss(y_true, y_pred):
    # weights.shape = (63,)
    # y_true.shape = (64, 63)
    # y_pred.shape = (64, 63)
    return tf.reduce_mean(tf.nn.weighted_cross_entropy_with_logits(y_true, y_pred, weights))

model.compile('adam', loss=loss, metrics=['acc'])

Но есть ошибка:

ValueError: Creating variables on a non-first call to a function decorated with tf.function

Как я могу создать такую ​​потерю?


person Ivan Adanenko    schedule 20.10.2020    source источник


Ответы (3)


Я предлагаю в первую очередь прибегнуть к использованию class_weight от Keras.

class_weight

это словарь с {label:weight}

Например, если у вас в 20 раз больше примеров на метке 1, чем на метке 0, вы можете написать

# Assign 20 times more weight to label 0
model.fit(..., class_weight = {0:20, 1:0})

Таким образом, вам не нужно беспокоиться о самостоятельном внедрении взвешенного CCE.

Дополнительное примечание: в model.compile() не забудьте использовать weighted_metrics=['accuracy'], чтобы иметь соответствующее отражение вашей точности.

model.fit(..., class_weight = {0:1, 1:20}, weighted_metrics = ['accuracy'])
person Timbus Calin    schedule 20.10.2020
comment
Я думаю, если класс 1 появляется в 20 раз чаще, вы должны использовать {0: 20, 1: 1} - person Yoskutik; 22.10.2020
comment
Да, опечатка на моей стороне - person Timbus Calin; 22.10.2020
comment
Спасибо за наблюдение - person Timbus Calin; 22.10.2020

веса классов — это словарь, который компенсирует дисбаланс в наборе данных. Например, если у вас есть набор данных из 1000 изображений собак и 100 изображений кошек, ваш классификатор будет смещен в сторону класса собак. Если бы он предсказывал собаку каждый раз, он был бы верным в 90 процентах случаев. Чтобы компенсировать дисбаланс, словарь class_weights позволяет вам взвешивать выборки кошек в 10 раз выше, чем собак, при расчете потерь. Один из способов — использовать метод class_weight из sklearn, как показано ниже.

from sklearn.utils import class_weight
import numpy as np

class_weights = class_weight.compute_class_weight(
               'balanced',
                np.unique(train_generator.classes), 
                train_generator.classes) 
person Gerry P    schedule 20.10.2020

Если вы работаете с классами дисбаланса, вам следует использовать веса классов. Например, если у вас есть два класса, в которых класс 0 содержит в два раза больше данных, чем класс 1:

class_weight = {0 :1, 1: 2}

При компиляции используйте weighted_metrics вместо одних только метрик, иначе модель не будет учитывать веса классов при расчете точности, и она будет нереально высокой.

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

hist = model.fit_generator(train,validation_split=0.2,epochs=20,class_weight=class_weight)
person bebbieyin    schedule 21.10.2020