Я нахожусь под впечатлением, что последнее измерение Y_TRUE и Y_PRED отбрасывается, когда модель вызывает функцию потерь - PullRequest
1 голос
/ 16 марта 2020

Я строю модель глубокого обучения для классификации и локализации объектов, используя подход "yolo" для Keras и тензорного потока. Мой вывод для одного входного изображения - матрица 52 * 52 * 10. Итак, когда я запускаю model.summary (), я получаю следующее выходное измерение:

...
...

leaky_103 (LeakyReLU)           (None, 52, 52, 128)  0           bnorm_103[0][0]                  
__________________________________________________________________________________________________
conv_104 (Conv2D)               (None, 52, 52, 256)  294912      leaky_103[0][0]                  
__________________________________________________________________________________________________
bnorm_104 (BatchNormalization)  (None, 52, 52, 256)  1024        conv_104[0][0]                   
__________________________________________________________________________________________________
leaky_104 (LeakyReLU)           (None, 52, 52, 256)  0           bnorm_104[0][0]                  
__________________________________________________________________________________________________
conv_105 (Conv2D)               (None, 52, 52, 10)   2570        leaky_104[0][0]                  
__________________________________________________________________________________________________
activation_2 (Activation)       (None, 52, 52, 10)   0           conv_105[0][0]                   
==================================================================================================
Total params: 55,642,218
Trainable params: 55,592,682
Non-trainable params: 49,536
______________________________________________________________

, т. Е. Выходное значение [Нет, 52, 52, 10]

Итак, поскольку я должен создать собственную функцию потерь для своего вывода (как я должен применить перекрестную энтропию к срезу [:,:,0:2] и еще одну потерю к срезу [:,:,2:6]). Ниже приведена выдержка из функции потерь

epsilon = 0.000001
def loss(y_true, y_pred):
    loss1 = K.mean(K.sum(K.categorical_crossentropy(y_true[:,:,:,0:2], y_pred[:,:,:,0:2]), 
                         axis = (1,2,3)), 
                   axis = 0)
    loss2 = K.mean(K.sum(-K.log(K.abs(tf.math.subtract(y_true[:,:,:,2:6],
                                                       y_pred[:,:,:,2:6])) 
                                + epsilon), 
                         axis = (1,2, 3)), 
                   axis = 0)
    return loss1+loss2

, но при запуске model.compile() я получаю следующую ошибку:

ValueError: Неверный размер сокращения 3 для ввода с 3 Габаритные размеры. для 'loss_6 / активации_2_loss / Sum_2' (op: 'Sum') с формами ввода: [?, 52,52], [3] и с вычисленными тензорами ввода: input [1] = <1 2 3>.

Я интерпретировал, что в действительности, при вызове функции потерь, потеря рассчитывается по частям по частям вдоль последнего измерения и уменьшаются размеры оси в функции потерь, «модифицированная функция потерь» равна:

epsilon = 0.000001

def loss(y_true, y_pred):
    loss1 = K.mean(K.sum(K.categorical_crossentropy(y_true[:,:,:,0:2], y_pred[:,:,:,0:2]), 
                         axis = (1,2)), 
                   axis = 0)
    loss2 = K.mean(K.sum(-K.log(K.abs(tf.math.subtract(y_true[:,:,:,2:6],y_pred[:,:,:,2:6])) + epsilon), axis = (1,2)), axis = 0)
    return loss1+loss2

, после этого модель успешно скомпилирована. Кто-нибудь может сказать мне погоду, я прав или не прав насчет моей гипотезы.

1 Ответ

0 голосов
/ 16 марта 2020

Вы правы: categorical_crossentropy, уменьшит последнюю ось (размерность 3). У вас есть «одна» потеря для 3 классов, а не одна потеря для каждого класса.

Таким образом, вы вводите (batch, 52, 52, 3), и он возвращает (batch, 52, 52). Таким образом, ваш sum может работать только с измерениями 1 и 2, измерение 3 отсутствует.

Вы исправили loss1 соответственно.


О loss2, вы забыли добавить размеры к сумме. Так что это будет в другом порядке величины, потому что loss1 имеет mean по оси 0, а loss2 имеет sum по оси 0.

Вам нужно loss2, как это было до:

loss2 = K.mean(K.sum(-K.log(K.abs(tf.math.subtract(y_true[:,:,:,2:6],
                                                   y_pred[:,:,:,2:6])) 
                            + epsilon), 
                     axis = (1,2, 3)), 
               axis = 0)

Я не специализируюсь на этой задаче, но, возможно, у вас все еще есть другой порядок величины, потому что categorical_crossentropy выполняет среднее по оси 3, так что ваш loss2 может также необходимо это значение:

loss2 = K.mean(K.sum(-K.log(K.abs(y_true[:,:,:,2:6] - y_pred[:,:,:,2:6]) + epsilon),
                     axis=(1,2))) #let axis 3 to the mean. 

Подсказка: mean на оси 0 является необязательным. Керас сделает это за вас позже. Преимущество, если оставить размер 0 нетронутым, заключается в возможности позже использовать веса образцов.

Подсказка 2: tf.math.subtract(a, b) равно записи a-b.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...