Пользовательская функция потерь с min(y, p) и max(y, p)

Вопрос или проблема

Я создаю нейронную сеть в tensorflow и мне нужно минимизировать следующую функцию потерь:
$\frac{max(y,p)}{min(y,p)}$ где $y$ обозначает истинное значение, а $p$ предсказанное значение. Поскольку функция потерь недифференцируема, это становится проблемой при использовании градиентного спуска.

Обновление, теперь я пытаюсь реализовать:
$p > y \rightarrow loss = log(p)-log(y)$
$p < y \rightarrow loss = log(y)-log(p)$
$p = y \rightarrow loss = log(y)-log(y) = log(p)-log(p)$

Вот мой код:

def custom_loss(y_true, pred):
    if pred > y_true:
        custom_loss = K.log(pred) - K.log(y_true)
    elif pred < y_true:
        custom_loss = K.log(y_true) - K.log(pred)
    else:
        custom_loss = K.log(pred)-K.log(pred)

    return custom_loss


if __name__ == '__main__':
    run = 1

    X = np.load("vectors_normal_2way.npy")

    with open("target2.pickle", "rb") as file:
        target_dict = pickle.load(file)

    target_strings = [*target_dict]

    Y = np.array([])

    for target_value in target_strings:
        Y = np.append(Y, target_dict.get(target_value))

    for i in range(run):
        X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size = 0.2)
        model = get_model()
        start = time.time()
        model.fit(X_train, Y_train, verbose = 1, epochs = 1, batch_size = 32)
        end_time = time.time()-start
        pred = model.predict(X_test)[:, 0]

Но я получаю следующую ошибку:

tensorflow.python.framework.errors_impl.InvalidArgumentError:  Второй ввод должен быть скаляром, но имеет форму [32]
     [[{{node gradient_tape/custom_loss/cond/StatelessIf/gradient_tape/custom_loss/weighted_loss/Mul/_17}}]] [Op:__inference_train_function_1040]
 

Код может выполняться, когда я ставлю batch_size = 1

Функция потерь вычисляет ошибку на всех данных, которые она получает. Для нейронных сетей это среднее значение по мини-пакету. Ваш код может обрабатывать только скаляры (поэтому работает при batch=1), он должен обрабатывать векторы.

K похоже, что вы используете tf.Keras. Документация дает примеры пользовательских функций потерь. Полезно наследоваться от tf.keras.losses.Loss, который ожидает метод call(), содержащий логику для вычисления потерь с использованием y_true, y_pred.

class CustomLoss(Loss):

  def call(self, y_true, y_pred):
    pass

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

.

Ответ или решение

Создание настраиваемой функции потерь для нейронной сети, особенно такой, которая включает в себя как min(y, p), так и max(y, p), требует внимательного подхода в связи с особенностями, характеристиками и ограничениями методов оптимизации, часто используемых в глубоких сетях, например, градиентного спуска. В рассматриваемом случае, цель – минимизировать выражение $\frac{max(y,p)}{min(y,p)}$, что, по сути, представляет собой отношение максимального и минимального значений между истинным значением y и прогнозируемым значением p.

Теория

Ключевым инструментом в машинном обучении является функция потерь, которая определяет, насколько хорошо, или наоборот, плохо модель выполняет свою задачу прогнозирования. Она, в конечном счете, является тем компасом, который направляет процесс обучения в правильное русло. В общем случае она должна быть:

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

  2. Континуальной: Континуальность позволяет избежать резких скачков в значениях функции потерь, что может привести к неустойчивому обучению.

Пример

Представленная функция: $\frac{max(y,p)}{min(y,p)}$ не является дифференцируемой во всех точках, особенно в местах разрывов, что требует осторожного подхода к её оптимизации. В первоначальной попытке, отмеченной в вопросе пользователя, используется логарифмическое выражение для дифференциации условий p > y, p < y и p = y. Однако, текущая реализация была представлена с ошибкой из-за использования недифференцируемой функции в векторном контексте.

Применение

Для корректного вычисления предлагаем следующие шаги:

  1. Реализация настраиваемой функции потерь: Используйте класс tf.keras.losses.Loss для создания настраиваемой функции. Это позволяет инкапсулировать необходимую логику в пределах метода call(), который будет вызван во время обучения модели.
import tensorflow as tf
from tensorflow.keras.losses import Loss

class CustomLoss(Loss):
    def call(self, y_true, y_pred):
        difference = y_pred - y_true
        log_difference = tf.math.log(tf.abs(difference) + 1e-10)  # добавляем небольшую величину для стабильности
        condition = tf.greater(y_pred, y_true)
        loss = tf.where(condition, log_difference, -log_difference)
        return tf.reduce_mean(loss)
  1. Обработка батчей: Вместо обработки скаляров необходимо обеспечить работу с векторами значений, что обеспечит возможность параллельной обработки данных в батче. В приведённом примере используется векторизация операций с применением функций библиотеки TensorFlow.

  2. Синтетическое тестирование: Подобная функция потерь может привести к сложным ландшафтам оптимизации, которые могут вызвать проблемы с сходимостью. Проведение тестов моделей с такими функциями потерь на синтетических данных позволяет выявить проблемы на ранних стадиях и скорректировать подход, до того как модель будет задействована на более сложных реальных данных.

Заключение

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

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

Оцените материал
Добавить комментарий

Капча загружается...