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

  1. В тензорном потоке, можете ли вы использовать негладкую функцию в качестве функции потерь, например, кусочную (или с if-else)? Если вы не можете, почему вы можете использовать ReLU?

  2. В этой ссылке SLIM, это говорит

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

Означает ли это вообще "не дифференцируемо", например, проблемы с множеством? Потому что для ReLU в точке 0 он не дифференцируем.

  1. Если вы используете такую настраиваемую функцию потерь, вам нужно реализовать градиент самостоятельно? Или tenorflow может сделать это автоматически? Я проверил некоторые настраиваемые функции потерь, они не реализовали градиент для своей функции потерь.

Ответ 1

Проблема заключается не в том, что потеря является кусочной или негладкой. Проблема в том, что нам нужна функция потерь, которая может отправить обратно ненулевой градиент в параметры сети (dloss/dparameter), когда есть ошибка между выходом и ожидаемым выходом. Это касается практически любой функции, используемой внутри модели (например, функции потерь, функции активации, функции внимания).

Например, Perceptron использует шаг устройства H (x) в качестве функции активации (H (x) = 1, если x > 0 else 0). так как производная от H (x) всегда равна нулю (undefined при x = 0). Градиент, исходящий из потери, не будет проходить через него обратно к весам (правило цепи), поэтому никакие веса до этой функции в сети не могут обновляться с использованием градиентного спуска. Исходя из этого, градиентный спуск не может использоваться для персептронов, но может использоваться для обычных нейронов, который использует функцию активации sigmoid (поскольку градиент не равен нулю для всех x).

Для Relu производная равна 1 при x > 0 и 0 в противном случае. тогда как производная undefined при x = 0, мы по-прежнему можем пропустить градиент потерь через нее при x > 0. Вот почему он может быть использован.

Вот почему нам нужна функция потерь, которая имеет ненулевой градиент. Функции, такие как точность и F1, везде имеют нулевые градиенты (или undefined при некоторых значениях x), поэтому они не могут использоваться, тогда как функции, такие как кросс-энтропия, L2 и L1 имеют ненулевые градиенты, поэтому их можно использовать. (заметим, что "абсолютная разница" L1 является кусочной и негладкой при x = 0, но все еще может быть использована)

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

Ответ 2

Что касается вопроса № 3 OP, вам фактически не нужно выполнять вычисления градиента самостоятельно. Tensorflow сделает это для вас, что является одной из вещей, которые мне нравятся!

Ответ 3

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

  2. При этом можно только аппроксимировать кусочно дифференцируемые функции, чтобы реализовать, например, кусочно-постоянные/ступенчатые функции. Следующее - моя реализация согласно такой идее в MATLAB. Можно легко распространить его на случаи с большим количеством порогов (узлов) и желательных граничных условий.

function [s, ds] = QPWC_Neuron(z, sharp)
% A special case of (quadraple) piece-wise constant neuron composing of three Sigmoid functions
% There are three thresholds (junctures), 0.25, 0.5, and 0.75, respectively
% sharp determines how steep steps are between two junctures.
% The closer a point to one of junctures, the smaller its gradient will become. Gradients at junctures are zero.
% It deals with 1D signal only are present, and it must be preceded by another activation function, the output from which falls within [0, 1]
% Example:
% z = 0:0.001:1;
% sharp = 100;

LZ = length(z);
s = zeros(size(z));
ds = s;
for l = 1:LZ
    if z(l) <= 0
        s(l) = 0;
        ds(l) = 0;
    elseif (zl > 0) && (z(l) <= 0.25)
        s(l) = 0.25 ./ (1+exp(-sharp*((z(l)-0.125)./0.25)));
        ds(l) = sharp/0.25 * (s(l)-0) * (1-(s(l)-0)/0.25);
    elseif (z(l) > 0.25) && (z(l) <= 0.5)
        s(l) = 0.25 ./ (1+exp(-sharp*((z(l)-0.375)./0.25))) + 0.25;
        ds(l) = sharp/0.25 * (s(l)-0.25) * (1-(s(l)-0.25)/0.25);
    elseif (z(l) > 0.5) && (z(l) <= 0.75)
        s(l) = 0.25 ./ (1+exp(-sharp*((z(l)-0.625)./0.25))) + 0.5;
        ds(l) = sharp/0.25 * (s(l)-0.5) * (1-(s(l)-0.5)/0.25);
    elseif (z(l) > 0.75) && (z(l) < 1)
        % If z is larger than 0.75, the gradient shall be descended to it faster than other cases
        s(l) = 0.5 ./ (1+exp(-sharp*((z(l)-1)./0.5))) + 0.75;
        ds(l) = sharp/0.5 * (s(l)-0.75) * (1-(s(l)-0.75)/0.5);
    else
        s(l) = 1;
        ds(l) = 0;
    end
end
figure;
subplot 121, plot(z, s); xlim([0, 1]);grid on;
subplot 122, plot(z, ds); xlim([0, 1]);grid on;

end

enter image description here enter image description here enter image description here

  1. Что касается реализаций в Python и tf, отсюда можно обратиться к превосходным пошаговым инструкциям @papaouf_ai. Как сделать пользовательскую функцию активации только с Python в Tensorflow?