Матрица путаницы как метрика для оптимизации в задаче регрессии машинного обучения

#pytorch #loss-function

Вопрос:

Я тренирую модель для сегментации изображения, чтобы предсказать степень повреждения (в диапазоне от 0: без повреждений до 5: серьезные повреждения) для каждого пикселя изображения. Я подошел к этому так:

 def simple_loss(pred, mask):   # regression case
    pred = torch.sigmoid(pred)
    return (F.mse_loss(pred, mask, reduce='none')).mean()


def structure_loss(pred, mask):   # binary case: damaged vs undamaged
    weit = 1   5 * torch.abs(F.avg_pool2d(mask, kernel_size=31, stride=1, padding=15) - mask)
    wbce = F.binary_cross_entropy_with_logits(pred, mask, reduce='none')
    wbce = (weit * wbce).sum(dim=(2, 3)) / weit.sum(dim=(2, 3))

    pred = torch.sigmoid(pred)
    inter = ((pred * mask) * weit).sum(dim=(2, 3))
    union = ((pred   mask) * weit).sum(dim=(2, 3))
    wiou = 1 - (inter   1) / (union - inter   1)

    return (wbce   wiou).mean()
 

Двоичный случай дает долговую расписку > 0,6, но регрессионная модель неточна. Мой набор данных несбалансирован (100:1), большинство пикселей принадлежат к неповрежденному классу. Следовательно, оптимизация направлена на точное предсказание неповрежденных пикселей.
Матрица путаницы в области (1..5) не показывает корреляции между меткой и прогнозируемым значением.

Я не могу сбалансировать набор, потому что неповрежденная область рядом с поврежденной областью информативна для людей, обученных изучать повреждения.

Как я могу изменить функцию потерь, чтобы назначить более высокую стоимость ошибкам регрессии в отношении степени ущерба?

Ответ №1:

Мы можем кодировать нерелевантные пиксели с помощью -1. Затем измените функцию потерь, чтобы игнорировать нерелевантные классы таким образом:

 from keras import backend as K

def masked_mse(mask_value):
    def f(y_true, y_pred):
        mask_true = K.cast(K.not_equal(y_true, mask_value), K.floatx())
        masked_squared_error = K.square(mask_true * (y_true - y_pred))
        masked_mse = K.sum(masked_squared_error, axis=-1) / K.sum(mask_true, axis=-1)
        return masked_mse
    f.__name__ = 'Masked MSE (mask_value={})'.format(mask_value)
    return f
    

y_pred = K.constant([[ 1, 1, 1, 1], 
                     [ 1, 1, 1, 3],
                     [ 1, 1, 1, 3],
                     [ 1, 1, 1, 3],
                     [ 1, 1, 1, 3],
                     [ 1, 1, 1, 3]])
y_true = K.constant([[ 1, 1, 1, 1],
                     [ 1, 1, 1, 1],
                     [-1, 1, 1, 1],
                     [-1,-1, 1, 1],
                     [-1,-1,-1, 1],
                     [-1,-1,-1,-1]])

true = K.eval(y_true)
pred = K.eval(y_pred)
loss = K.eval(masked_mse(-1)(y_true, y_pred))

for i in range(true.shape[0]):
    print(true[3], pred[3], loss[3], sep='t')

# [-1. -1.  1.  1.]  [ 1.  1.  1.  3.]  2.0