Создание пользовательских потерь в Керасе - PullRequest
2 голосов
/ 19 января 2020

Я пытался построить свою собственную потерю в Керасе и столкнулся с некоторой ошибкой.

Мне нужно следующее: я хочу построить классификатор на стабильном временном ряду: он должен решить, будет ли он более влажным кривая имеет восходящий или нисходящий тренд , что означает, что если производная отрицательна, скажем, для 2 или 3 временных шагов, она должна сохранять классификацию «восходящий», а не переключаться на потомок в течение небольшого промежутка времени. Входные данные - это контекстные данные, которые должны помочь NN определять, будет ли текущее изменение в направлении временного ряда продолжаться или нет.

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

Сначала я хотел использовать np.where для прогнозируемых и ссылочных тензоров, но я понял, что при просмотре форума это было невозможно, поскольку функция потерь использует тензоры-заполнители. Я должен оставаться в функциональном пространстве бэкэнда keras.

По этой причине я использовал некоторый код, который нашел на этом форуме, для создания функции следующих потерь:

import keras.backend as kb

def roll_reg(x):
    length = kb.int_shape(x)[0]
    x_tile = kb.tile(x, [2, 1])
    x_roll = x_tile[length - 1:-1]
    return kb.sum(kb.abs(x - x_roll))

def custom_loss(y_actual,y_predicted):
    posact=kb.flatten(y_actual)
    pospred=kb.flatten(y_predicted)
    na=roll_reg(posact)
    np=roll_reg(pospred)
    loss_cust=kb.mean(((y_actual-y_predicted)**2)**0.5/(kb.max(y_actual)-kb.min(y_actual)))+abs(na-np)/kb.int_shape(posact)*10
    return loss_cust

, но я все еще получаю эта ошибка:

ValueError: Shape должен иметь ранг 1, но является рангом 2 для 'loss_9 / dens_25_loss / Tile' (op: 'Tile') с входными фигурами: [?], [2].

, который я интерпретирую как невозможность моих операций над тензорами-заполнителями ... в то время как я пытался использовать выделенную функцию для таких тензоров.

Кто-нибудь знает, что Я мог бы улучшить этот код, чтобы запустить функцию потери?

Некоторые обновления по этому вопросу. В inte rnet я нашел эту страницу: https://medium.com/@j.ali.hab / on-custom-loss-functions-in-keras-3af88cf59e48 , где эта же проблема решается с помощью библиотеки tf.math.

Итак, я обновил свой код:

def custom_loss(y_actual,y_predicted):
    na=kb.tf.math.cumsum(y_actual,axis=0)
    np=kb.tf.math.cumsum(y_predicted,axis=0)

    penalty=kb.abs(kb.sum(np-na))/118319#/kb.int_shape(y_actual)[0]
    loss_nico=penalty
    return loss_nico

Теперь код компилируется, но я получаю Nan в самом конце каждой эпохи как функцию потерь. Конечно, нейронный net ничего не изучает как следствие.

Кто-нибудь знает, что я делаю неправильно?

1 Ответ

1 голос
/ 20 февраля 2020

ОК, я наконец понял!

проблема была в te kb.abs (): он не нужен, так как kb.sum () возвращает скаляр.

Итак, финал код, который работает:

def custom_loss(y_actual,y_predicted):

    na=kb.tf.math.cumsum(y_actual,axis=0)
    np=kb.tf.math.cumsum(y_predicted,axis=0)
    penalty=abs(kb.sum(na-np))
    loss_nico=kb.sum(((y_actual-y_predicted)))/1000+penalty/1000
    return loss_nico

, который компилируется и позволяет RN действительно изучать что-то. Это все еще не идеально, так как часть «без штрафа» должна быть улучшена, но она все еще работает.

...