Он использует автоматическое дифференцирование. Где он использует правило цепочки и обратное слово в графе, назначая градиенты.
Допустим, у нас есть тензор C Этот тензор C был создан после ряда операций. Допустим, путем сложения, умножения, прохождения некоторой нелинейности и т. Д.
Так что, если этот C зависит от некоторого набора тензоров, называемых Xk, нам нужно получить градиенты
Тензор потока всегда отслеживает путь операций. Я имею в виду последовательное поведение узлов и как поток данных между ними. Что сделано графом
Если нам нужно получить производные стоимости от X входных данных, то, что сначала будет сделано, это загрузить путь от x-input к стоимости путем расширения графика.
Тогда это начнется в порядке рек. Затем распределите градиенты с помощью цепного правила. (То же, что и обратное распространение)
В любом случае, если вы читаете исходные коды, принадлежащие tf.gradients (), вы можете обнаружить, что тензор потока хорошо выполнил эту часть распределения градиента.
В то время как обратное отслеживание tf взаимодействует с графом, в проходе обратного слова TF встретит разные узлы. Внутри этих узлов есть операции, которые мы называем (ops) matmal, softmax, relu, batch_normalization и т. Д. Итак, что мы tf делаем, это автоматически загружает эти ops в график
Этот новый узел составляет частную производную операций. get_gradient ()
Давайте немного поговорим об этих недавно добавленных узлах
Внутри этих узлов мы добавляем 2 вещи: 1. Производная, которую мы вычислили раньше) 2. Также входы для сопоставления OPP в прямом проходе
Таким образом, по правилу цепи мы можем рассчитать
Так что это так же, как бэк-слово API
Так что тензор потока всегда думает о порядке графа, чтобы сделать автоматическое дифференцирование
Так как мы знаем, что нам нужны переменные прямого прохода для вычисления градиентов, то нам нужно хранить промежуточные значения также в тензорах, это может уменьшить память. Для многих операций tf знают, как вычислять градиенты и распределять их.