Пользовательская метрика в модели Keras с несколькими выходами

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

Модель выглядит так:

input_shape = (256,96,3)
base_model = VGG16(weights='imagenet', include_top=False, input_shape = input_shape)
xo = base_model.output
x = base_model.input
flat = Flatten(name = 'flat')(xo)
h1 = Dense(1024, activation='relu', name = 'first_hidden_layer')(flat)
d1 = Dropout(0.5, name = 'first_hidden_dropout')(h1)
h2 = Dense(1024, activation='relu', name = 'second_hidden_layer')(d1)
d2 = Dropout(0.5, name = 'second_hidden_dropout')(h2)

o_digit1 = Dense(11, activation='softmax', name = 'digit1_classification')(d2)
o_digit2 = Dense(11, activation='softmax', name = 'digit2_classification')(d2)

model = Model(inputs = x, outputs = [o_digit1, o_digit2] )
opt = Adam(lr=0.0001)
model.compile(optimizer=opt, 
              loss='categorical_crossentropy',
              metrics={'digit1_classification': 'accuracy', 
                             'digit2_classification': 'accuracy'},
              loss_weights = {'digit1_classification': 0.5, 
                             'digit2_classification': 0.5})

Я хотел бы создать пользовательскую метрику для передачи в модель. Компиляция, которая вычисляет фактическую точность числа. Обычно, когда вы создаете свою собственную метрическую функцию, вы передаете ей y_pred и y_true. Например

def my_metric1(y_true,y_pred):    
    return calculations (y_true, y_pred)

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

def my_metric2(y_pred1, y_true1, y_pred2, y_true2):
    return calculations2(y_pred1, y_true1, y_pred2, y_true2)

Здесь y_pred1, y_true1, y_pred2, y_true2 — прогнозы и истинные значения для каждой цифры в отдельности.

Как я могу этого добиться?


person Mike Azatov    schedule 19.12.2019    source источник
comment
можно ли иметь только один выход (объединение двух предыдущих) и определить для него пользовательские метрики/потери?   -  person Zaccharie Ramzi    schedule 22.12.2019
comment
Хм.. Это возможно. Мне нужно выяснить, как сделать пользовательскую потерю, потому что я не смогу выполнить categorical_crossentropy, потому что, если я соберу свои два вывода в один вектор, он больше не будет кодироваться в горячем режиме.   -  person Mike Azatov    schedule 23.12.2019
comment
Пользовательская потеря аналогична пользовательской метрике, за исключением того, что она должна быть дифференцируемой.   -  person Zaccharie Ramzi    schedule 24.12.2019


Ответы (1)


Если вы используете 2 цифры в качестве отдельных выходов, вы можете создать пользовательскую функцию потерь примерно так:

import numpy as np

# Define custom loss
# Create a loss function that adds the MSE loss to the mean of all squared activations
def custom_loss(y_pred1, y_true1, y_pred2, y_true2):
    Loss = 0

    def loss1(y_true1,y_pred1):
        return np.square(np.subtract(y_true1,y_pred1)).mean()

    def loss2(y_true2,y_pred2):
        return np.square(np.subtract(y_true2,y_pred2)).mean()

    def finalloss(y_pred1, y_true1, y_pred2, y_true2):
        Loss = loss1(y_pred1, y_true1) + loss2(y_pred2, y_true2)
        if(y_pred1 == y_true1 and y_pred2 == y_true2):
           return(0)
        elif(y_pred1 == y_true1 and y_pred2 != y_true2):
            return(0.5 * Loss)
        elif(y_pred1 != y_true1 and y_pred2 == y_true2):
            return(0.5 * Loss)    
        else:
            return(Loss)

    return finalloss(y_pred1, y_true1, y_pred2, y_true2)

# Compile the model
model.compile(optimizer='adam',
              loss=custom_loss, # Call the loss function 
              metrics=['accuracy'])

# train
model.fit(data, labels)  

Лучше иметь только один выход в модели для обеих цифр. Что-то вроде этого Полностью связанный слой [1x1x2]. Вы можете найти статью о многозначном детекторе здесь.

person Community    schedule 14.04.2020