Пользовательские функции потерь

В Keras.js пользовательские функции потерь позволяют задавать собственные критерии оценки ошибок модели при обучении, выходя за пределы стандартного набора mean_squared_error, categorical_crossentropy и других встроенных функций. Это особенно важно при работе с нестандартными задачами, где стандартные метрики не отражают специфику ошибки, или при экспериментах с новыми подходами к оптимизации.


Формат определения функции потерь

В Keras.js функции потерь задаются как функции JavaScript с двумя обязательными аргументами:

function customLoss(yTrue, yPred) {
    // yTrue — ожидаемые значения (targets)
    // yPred — предсказанные значения (predictions)
    return lossValue; // число или тензор, представляющий ошибку
}
  • yTrue — массив или тензор с правильными метками.
  • yPred — массив или тензор с предсказанными моделью значениями.
  • Возвращаемое значение должно быть скалярной величиной, отражающей степень ошибки на текущем батче данных.

Функция может включать сложные математические операции, комбинации стандартных метрик или условия для обработки выбросов и специальных случаев.


Использование встроенных математических функций

Для операций с тензорами в Keras.js используются встроенные методы объекта K (аналог Keras backend в Python):

  • K.mean(tensor) — среднее значение элементов тензора.
  • K.sum(tensor) — сумма элементов.
  • K.square(tensor) — возведение элементов в квадрат.
  • K.abs(tensor) — модуль элементов.
  • K.maximum(a, b) — поэлементный максимум.

Пример реализации функции потерь на основе MSE с порогом:

function thresholdedMSE(yTrue, yPred) {
    const diff = K.sub(yPred, yTrue);
    const squaredDiff = K.square(diff);
    const mask = K.greater(squaredDiff, 0.01); // игнорируем ошибки меньше порога
    const filteredDiff = K.mul(squaredDiff, mask);
    return K.mean(filteredDiff);
}

В этом примере мелкие ошибки не учитываются, что может быть полезно при шумных данных.


Работа с асимметричными функциями потерь

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

function asymmetricLoss(yTrue, yPred) {
    const diff = K.sub(yPred, yTrue);
    const loss = K.where(
        K.greater(diff, 0),
        K.mul(diff, 2), // переоценка
        K.mul(K.abs(diff), 5) // недооценка
    );
    return K.mean(loss);
}

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


Внедрение регуляризации в потери

Регуляризация часто включается непосредственно в функцию потерь для контроля переобучения. В Keras.js это может быть сделано через L1 и L2 нормы весов:

function lossWithL2(yTrue, yPred, model) {
    const mse = K.mean(K.square(K.sub(yPred, yTrue)));
    let l2Penalty = K.scalar(0);
    model.layers.forEach(layer => {
        if (layer.weights) {
            layer.weights.forEach(w => {
                l2Penalty = K.add(l2Penalty, K.sum(K.square(w))));
            });
        }
    });
    return K.add(mse, K.mul(K.scalar(0.01), l2Penalty));
}

В этом примере 0.01 — коэффициент регуляризации, регулирующий влияние штрафа на веса.


Особенности работы с батчами

Keras.js обрабатывает данные батчами. Функции потерь должны корректно работать с тензорами любого размера. Рекомендуется использовать агрегирующие операции (K.mean, K.sum) для перевода тензора ошибок в скалярное значение, чтобы оптимизатор мог корректно обновлять веса.


Советы по написанию эффективных функций потерь

  1. Использовать операции Keras.js, а не нативный JavaScript, для совместимости с тензорами и GPU-ускорением.
  2. Минимизировать создание новых объектов внутри функции для снижения нагрузки на сборщик мусора.
  3. Тестировать на небольших примерах перед использованием на всей модели, чтобы убедиться в правильности вычислений.
  4. Комбинировать несколько потерь для мультикритериальных задач через взвешенное сложение.
function combinedLoss(yTrue, yPred) {
    const mse = K.mean(K.square(K.sub(yPred, yTrue)));
    const mae = K.mean(K.abs(K.sub(yPred, yTrue)));
    return K.add(K.mul(mse, K.scalar(0.7)), K.mul(mae, K.scalar(0.3)));
}

Ограничения и особенности Keras.js

  • Полная совместимость с Python-версией Keras невозможна, поэтому функции, использующие нестандартные бэкенды или сложные графы вычислений, могут не работать.
  • Поддерживаются только функции, возвращающие скаляры, не массивы.
  • Для сложных пользовательских операций стоит проверять поведение на GPU и CPU, так как некоторые операции могут иметь разную производительность.

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