Эта статья была написана ** Луо Чжоуянstupidme.me.lzy@gmail.com**Оригинал, при перепечатке указывать источник. Эта статья была опубликована в оригинальном блоге автораblog.stupid?/2018/08/25/…
Обратное распространение — краеугольный камень глубокого обучения.
Производная
Сначала рассмотрим производные:
Производная функции по каждой переменной является частной производной.
для функции,,в то же время
Градиент — это вектор частных производных. В приведенном выше примере
Правило цепи
Для простых функций мы можем напрямую вычислить их производные по формуле. Но для сложных функций не так просто записать производные напрямую. но у нас естьПравило цепи.
Об определении особо нечего сказать, давайте возьмем пример и почувствуем прелесть цепного правила.
Мы знакомы с сигмовидной функцией, если вы не можете вспомнить его производную, как мы ее решим?
Шаги решения следующие:
- Разделите функцию на несколько основных частей, каждая из которых может быть получена с использованием простого правила вывода.
- Используя цепное правило, соедините эти производные вместе, чтобы вычислить окончательную производную.
детали следующим образом:
сделать,но
сделать,но
сделать,но
сделать,но
сделать,но
Приведенное выше e на самом деле является нашим ?\sigma(x)?, тогда согласно цепному правилу мы имеем:
Производная сигмовидной функции может быть непосредственно представлена сама по себе, что также является замечательным свойством. Является ли этот процесс вывода простым?
Реализация кода обратного распространения
Я знаю и вывод, и цепное правило, так что же такое конкретный код прямого и обратного распространения?
На этот раз мы используем немного более сложный пример:
Давайте сначала посмотрим на его код прямого доступа:
import math
x = 3
y = -4
sigy = 1.0 / (1 + math.exp(-y)) # sigmoid function
num = x + sigy # 分子
sigx = 1.0 / (1 + math.exp(-x))
xpy = x + y
xpy_sqr = xpy**2
den = sigx + xpy_sqr # 分母
invden = 1.0 / den
f = num * invden # 函数
Описанный выше процесс очень прост, не так ли?Это разложение сложных функций на простые функции.
Давайте посмотрим на следующий процесс обратного распространения:
dnum = invden
так как
Так что есть
это
dinvden = num # 同理
dden = (-1.0 / (den**2)) * dinvden # 链式法则
Расширять:
снова
так
Итак, по тому же принципу мы можем записать все производные:
dsigx = (1) * dden
dxpy_sqr = (1) * dden
dxpy = (2 * xpy) * dxpy_sqr
# backprob xpy = x + y
dx = (1) * dxpy
dy = (1) * dxpy
# 这里开始,请注意使用的是"+=",而不是"=”
dx += ((1 - sigx) * sigx) * dsigx # dsigma(x) = (1 - sigma(x))*sigma(x)
dx += (1) * dnum
# backprob num = x + sigy
dsigy = (1) * dnum
# 注意“+=”
dy += ((1 - sigy) * sigy) * dsigy
проблема:
- В приведенном выше процессе расчета зачем использовать «+=» вместо «=»?
Если переменные x, y появляются несколько раз в выражении прямого распространения, будьте очень осторожны при выполнении обратного распространения, используйте += вместо = для накопления градиентов этих переменных (иначе это вызовет перезапись). Это следует правилу многомерной цепочки в исчислении, которое гласит, что если переменные разветвляются в разные части схемы, то градиенты должны накапливаться по мере их возвращения.
свяжитесь со мной
-
Email: stupidme.me.lzy@gmail.com
-
WeChat: luozhouyang0528
-
Личный публичный аккаунт, возможно вас заинтересует: