欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

理解深度学习基石:前向传播与反向传播详解

最编程 2024-07-24 22:43:11
...

深度学习基础 - 前向传播和反向传播

flyfish

有一个故事:
一位外地人闯进小镇,到镇里的旅店,取出100元钱准备住店,然后便随服务员去看房。旅店老板拿着这100元钱到街对面的肉铺还赊账买肉的钱;肉铺老板赶紧跑去一公里外的养猪场还了买猪钱;养猪场场主开开心心地将还没捂热的100元钱又还给前来催债的邻镇饲料厂厂长;厂长正惦记着前几天住旅店欠下的100元钱,飞奔到旅店将钱还上。外地人向旅店老板反映房间环境不好,要退掉100元房钱,老板便将饲料厂厂长付给自己的钱给了这个外地人。这下子,小镇上的人债务都解除了,大家都很开心。

从一个简单的数学表达式开始
1 + 2 = 3 1+2=3 1+2=3
把常量换成变量,如下
x + y = z x+y=z x+y=z
这是数学表达式的方式

我们再换种计算图的方式,如下

前向传播
在这里插入图片描述

反向传播
这是加法,左边是前向传播,右边是反向传播
在这里插入图片描述
这是乘法,左边是前向传播,右边是反向传播
在这里插入图片描述
在这里插入图片描述

从左向右进行计算是一种正方向上的传播,简称为正向传播 (forward propagation)。从右向左的传播称为反向传播 (backward propagation)。
计算图的反向传播
计算图的反向传播:沿着与正方向相反的方向,乘上局部导数。
反向传播的计算顺序是:
将信号 E 乘以节点的局部导数( ∂ y ∂ x \frac{\partial y}{\partial x} xy),然后将结果传递给下一个节点。这里所说的局部导数是指正向传播中 y = f ( x ) y = f (x) y=f(x) 的导数,也就是 y 关于 x 的导数( ∂ y ∂ x \frac{\partial y}{\partial x} xy )。比如,假设 y = f ( x ) = x 2 y = f(x) = x 2 y=f(x)=x2 ,则局部导数为 ∂ y ∂ x \frac{\partial y}{\partial x} xy = 2x。把这个局部导数乘以 E,然后传递给前面的节点。这就是反向传播的计算顺序。通过这样的计算,可以高效地求出导数的值,这是反向传播的要点。
在这里插入图片描述

z = f ( x , y ) z=f(x,y) z=f(x,y) 求偏导数
加法的偏导数
f ( x , y ) = x + y ∂ f ∂ x = 1 , ∂ f ∂ y = 1 \begin{array}{l} f(x, y)=x+y \\\\ \frac{\partial f}{\partial x}=1, \\\\ \frac{\partial f}{\partial y}=1 \end{array} f(x,y)=x+yxf=1,yf=1
乘法的偏导数

f ( x , y ) = x y ∂ f ∂ x = y , ∂ f ∂ y = x \begin{array}{l} f(x, y)=x y \\\\ \frac{\partial f}{\partial x}=y, \\\\ \frac{\partial f}{\partial y}=x \end{array} f(x,y)=xyxf=y,yf=x

我们把加法和乘法联合起来,以应用题的方式说明正向传播和反向传播
完整代码
物品a的单价是3,数量是7
物品b的单价是4,数量是8
物品的总价是多少?
3×7 + 4×8 = 53
代码实现

class multiplication_layer:
    def __init__(self):
        self.x = None
        self.y = None

    def forward(self, x, y):
        self.x = x
        self.y = y
        out = x * y
        return out

    def backward(self, d_out):
        d_x = d_out * self.y
        d_y = d_out * self.x
        return d_x, d_y


class addition_layer:
    def __init__(self):
        pass

    def forward(self, x, y):
        out = x + y
        return out

    def backward(self, d_out):
        d_x = d_out * 1
        d_y = d_out * 1
        return d_x, d_y

a_price = 3
a_num = 7
b_price = 4
b_num = 8


# layer
a_layer = multiplication_layer()
b_layer = multiplication_layer()
c_layer = addition_layer()

# forward
a_price = a_layer.forward(a_price, a_num)  # (1)
b_price = b_layer.forward(b_price, b_num)  # (2)
totoal_price = c_layer.forward(a_price, b_price)  # (3)

# backward
d_price = 1
d_a_price, d_b_price = c_layer.backward(d_price)  # (3)
d_b, d_b_num = b_layer.backward(d_b_price)  # (2)
d_a, d_a_num = a_layer.backward(d_a_price)  # (1)

print("totoal_price:", (totoal_price))
print("d_a:", d_a)
print("d_a_num:", (d_a_num))
print("d_b:", d_b)
print("d_b_num:", (d_b_num))

# totoal_price: 53
# d_a: 7
# d_a_num: 3
# d_b: 8
# d_b_num: 4

局部计算 - 各人自扫门前雪,莫管他人瓦上霜
计算图的特征是可以通过传递“局部计算”获得最终结果。通过一个乘号看局部计算是指,无论全局发生了什么,这个乘号只根据与自己相关两个连接的信息计算与其他点和线无关。
在计算图中表示链式法则

z = ( x + y ) 2 z = {(x + y)}^2 z=(x+y)2是由两个式子构成的。
1 、 z = t 2 2 、 t = x + y 1、z = t^2 2、t = x + y 1z=t22t=x+y
在这里插入图片描述

简单实现一个全连接层的前向传播和反向传播
全连接层是fully connected layer,类似的名词是affine或者linear

Y = W X + B Y=WX+B Y=WX+B

import numpy as np
N=1
X= np.random.random((N,2))
W= np.random.random((2,3))
B= np.random.random((3,))
Y = np.dot(X, W) + B
print(Y)

以矩阵为对象的反向传播
∂ L ∂ X = ∂ L ∂ Y ⋅ W T ∂ L ∂ W = X T ⋅ ∂ L ∂ Y \begin{array}{l} \frac{\partial L}{\partial \boldsymbol{X}}=\frac{\partial L}{\partial \boldsymbol{Y}} \cdot \boldsymbol{W}^{\mathrm{T}} \\ \\ \frac{\partial L}{\partial \boldsymbol{W}}=\boldsymbol{X}^{\mathrm{T}} \cdot \frac{\partial L}{\partial \boldsymbol{Y}} \end{array} XL=YLWTWL=XTYL
X 和 ∂ L ∂ X \frac{\partial L}{\partial X} XL形状相同,W 和 ∂ L ∂ W \frac{\partial L}{\partial W} WL形状相同
X = ( x 0 , x 1 , ⋯   , x n ) ∂ L ∂ X = ( ∂ L ∂ x 0 , ∂ L ∂ x 1 , ⋯   , ∂ L ∂ x n ) \begin{array}{l} \boldsymbol{X}=\left(x_{0}, x_{1}, \cdots, x_{n}\right) \\ \frac{\partial L}{\partial \boldsymbol{X}}=\left(\frac{\partial L}{\partial x_{0}}, \frac{\partial L}{\partial x_{1}}, \cdots, \frac{\partial L}{\partial x_{n}}\right) \end{array} X=(x0,x1,,xn)XL=(x0L,x

上一篇: 理解深度学习基础:从神经网络构造到实践 - 1.评分函数介绍 2.SVM损失函数解析 3.正规化惩罚项说明 4.Softmax与交叉熵损失函数详解 5.前向传播中的最优化挑战 6.批量大小(batch_size)实操指南...

下一篇: 用一个实例深入理解神经网络的前向传播与反向传播机制