Вычисление F1-показателя «взвешено» на Keras - PullRequest
0 голосов
/ 02 мая 2018

Я хочу вычислить взвешенную таким образом оценку F1, чтобы штрафовать за ошибку на моем редком лейбле. К сожалению, я пока не могу получить нормальный результат Ф1. Это мои метрики

def sensitivity(y_true, y_pred):
    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
    possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
    return true_positives / (possible_positives + K.epsilon())

def specificity(y_true, y_pred):
    true_negatives = K.sum(K.round(K.clip((1-y_true) * (1-y_pred), 0, 1)))
    possible_negatives = K.sum(K.round(K.clip(1-y_true, 0, 1)))
    return true_negatives / (possible_negatives + K.epsilon())

def f1(y_true, y_pred):
    def recall(y_true, y_pred):
        true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
        possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
        recall = true_positives / (possible_positives + K.epsilon())
        return recall

    def precision(y_true, y_pred):
        true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
        predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
        precision = true_positives / (predicted_positives + K.epsilon())
        return precision
    precision = precision(y_true, y_pred)
    recall = recall(y_true, y_pred)
    return 2*((precision*recall)/(precision+recall)) 

model.compile(loss='binary_crossentropy',
              optimizer=RMSprop(0.001),
              metrics=[sensitivity, specificity, 'accuracy', f1])

и вот я тренирую модель и оцениваю:

model.fit(x_train, y_train, epochs=12, batch_size=32, verbose=1, class_weight=class_weights_dict, validation_split=0.3)
classes = model.predict(x_test)
loss_and_metrics = model.evaluate(x_test, y_test, batch_size=128, verbose=1)

Я всегда получаю nan как f1, что-то не так с кодом? Поскольку данные совпадают, я использовал со sklearn с классификатором SVM. Я еще даже не занимался взвешенными вычислениями .. Это результаты:

Epoch 1/12
5133/5133 [==============================] - 5s 976us/step - loss: 0.6955 - sensitivity: 0.0561 - specificity: 0.9377 - acc: 0.8712 - f1: nan - val_loss: 0.6884 - val_sensitivity: 0.8836 - val_specificity: 0.0000e+00 - val_acc: 0.0723 - val_f1: nan
Epoch 2/12
5133/5133 [==============================] - 5s 894us/step - loss: 0.6954 - sensitivity: 0.3865 - specificity: 0.5548 - acc: 0.5398 - f1: nan - val_loss: 0.6884 - val_sensitivity: 0.0000e+00 - val_specificity: 1.0000 - val_acc: 0.9277 - val_f1: nan
Epoch 3/12
5133/5133 [==============================] - 5s 925us/step - loss: 0.6953 - sensitivity: 0.3928 - specificity: 0.5823 - acc: 0.5696 - f1: nan - val_loss: 0.6884 - val_sensitivity: 0.0000e+00 - val_specificity: 1.0000 - val_acc: 0.9277 - val_f1: nan
Epoch 4/12
5133/5133 [==============================] - 5s 935us/step - loss: 0.6954 - sensitivity: 0.1309 - specificity: 0.8504 - acc: 0.7976 - f1: nan - val_loss: 0.6884 - val_sensitivity: 0.0000e+00 - val_specificity: 1.0000 - val_acc: 0.9277 - val_f1: nan
etc.

Final: [0,6859536773606656, 0,0, 1,0, 0,9321705426356589, нан.]

Заранее благодарим за ваши предложения

1 Ответ

0 голосов
/ 06 мая 2018

Относительно nan в вашей метрике f1:

Если вы посмотрите журнал, ваша чувствительность проверки равна 0. Это означает, что ваша точность и отзыв также равны нулю. Таким образом, в расчете f1 вы делите на ноль и получаете нан.

Добавьте K.epsilon (), как вы делали в других функциях.

На дополнительном примечании , судя по вашей потере, которая имела незначительное улучшение в наборе поездов, ваша сеть ничего не узнала. Я бы посоветовал вам начать с увеличения количества эпох, сделать сеть глубже и ничего не передавать аргументу class_weight (вы упоминаете, что пока не используете взвешенные вычисления, но ваш код устанавливает некоторый вес класса).

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