#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