计算神经网络中梯度的核心机制 - 反向传播(backpropagation)算法(1)

flyfish

2024-06-29
2024-07-02 修复图
链式法则在深度学习中的主要应用是在反向传播(backpropagation)算法中。
从简单的开始 ,文本说的就是链式法则

R\mathbb{R}R

  • 英文:The set of real numbers
  • 解释:符号 R\mathbb{R}R 表示所有实数的集合,包括所有正数、负数和零。在英语中,这个符号称为 “the set of real numbers” 或简称 “the reals”。
  • 读作:实数集
  • 含义:符号 R\mathbb{R}R 表示所有实数的集合。在数学中,这个符号用来指代从负无穷到正无穷的所有实数。

f∘gf \circ gfg

  • 读作fff 复合 ggg
  • 含义:符号 ∘\circ 表示函数的复合。复合函数 f∘gf \circ gfg 表示先应用函数 ggg,然后将 ggg 的输出作为函数 fff 的输入。形式上,这可以写作:
    (f∘g)(x)=f(g(x))(f \circ g)(x) = f(g(x))(fg)(x)=f(g(x))

例子

假设我们有两个函数 g(x)=2x+3g(x) = 2x + 3g(x)=2x+3f(u)=u3f(u) = u^3f(u)=u3,复合函数 f∘gf \circ gfg 表示为:
(f∘g)(x)=f(g(x))=f(2x+3)=(2x+3)3(f \circ g)(x) = f(g(x)) = f(2x + 3) = (2x + 3)^3(fg)(x)=f(g(x))=f(2x+3)=(2x+3)3

箭头符号的意义

  • f:A→Bf: A \to Bf:AB 表示函数 fff 将集合 AAA 中的每个元素映射到集合 BBB 中的一个元素。
  • x↦f(x)x \mapsto f(x)xf(x) 表示 xxx 经过函数 fff 的映射得到 f(x)f(x)f(x)

例子

  1. 简单映射
    f:R→Rf: \mathbb{R} \to \mathbb{R}f:RR 表示一个从实数集合到实数集合的函数。具体的映射可以是:
    f(x)=x2f(x) = x^2f(x)=x2
    这里,fff 将每个实数 xxx 映射到它的平方 x2x^2x2
  2. 复合函数的映射
    如果有两个函数 gggfff
  • g:R→Rg: \mathbb{R} \to \mathbb{R}g:RR
  • f:R→Rf: \mathbb{R} \to \mathbb{R}f:RR并且 g(x)=2x+3g(x) = 2x + 3g(x)=2x+3f(u)=u3f(u) = u^3f(u)=u3,那么复合函数 f∘gf \circ gfg 可以表示为:
    (f∘g)(x)=f(g(x))(f \circ g)(x) = f(g(x))(fg)(x)=f(g(x))
    具体的映射是:
    g:x↦2x+3g: x \mapsto 2x + 3g:x2x+3
    f:u↦u3f: u \mapsto u^3f:uu3
    结合起来:
    (f∘g):x↦(2x+3)3(f \circ g): x \mapsto (2x + 3)^3(fg):x(2x+3)3

函数的映射关系

在数学中,函数的定义和使用广泛应用于各种映射关系中。箭头符号帮助我们清晰地描述这些关系。更具体地:

  • 箭头 →\to 用于描述集合之间的映射关系。
  • 箭头 ↦\mapsto 用于描述具体的元素如何被映射。

复合函数的表示

复合函数的映射关系可以通过箭头符号更直观地表示:

  1. g:A→Bg: A \to Bg:AB
  2. f:B→Cf: B \to Cf:BC
  3. 复合函数 f∘gf \circ gfg 的映射关系为 f∘g:A→Cf \circ g: A \to Cfg:AC
    假设 gggxxx 映射到 uuu,即 g:x↦ug: x \mapsto ug:xu,并且 fffuuu 映射到 yyy,即 f:u↦yf: u \mapsto yf:uy。那么复合函数 f∘gf \circ gfgxxx 直接映射到 yyy,即:
    (f∘g):x↦f(g(x))(f \circ g): x \mapsto f(g(x))(fg):xf(g(x))

复合函数的概念

如果我们有两个函数:

  • g:A→Bg: A \to Bg:AB
  • f:B→Cf: B \to Cf:BC
    其中,函数 ggg 将集合 AAA 中的元素映射到集合 BBB,而函数 fff 将集合 BBB 中的元素映射到集合 CCC。那么,复合函数 f∘gf \circ gfg 将集合 AAA 中的元素直接映射到集合 CCC,即:
    (f∘g)(x)=f(g(x))(f \circ g)(x) = f(g(x))(fg)(x)=f(g(x))

例子

  1. 简单的复合函数
    g(x)=x2g(x) = x^2g(x)=x2f(u)=sin⁡(u)f(u) = \sin(u)f(u)=sin(u)。复合函数 (f∘g)(x)(f \circ g)(x)(fg)(x) 表示为:
    (f∘g)(x)=f(g(x))=sin⁡(x2)(f \circ g)(x) = f(g(x)) = \sin(x^2)(fg)(x)=f(g(x))=sin(x2)
    在这个例子中,先计算内部函数 g(x)=x2g(x) = x^2g(x)=x2,然后将结果代入到外部函数 f(u)=sin⁡(u)f(u) = \sin(u)f(u)=sin(u)
  2. 其他例子
    g(x)=2x+3g(x) = 2x + 3g(x)=2x+3f(u)=u3f(u) = u^3f(u)=u3。复合函数 (f∘g)(x)(f \circ g)(x)(fg)(x) 表示为:
    (f∘g)(x)=f(g(x))=(2x+3)3(f \circ g)(x) = f(g(x)) = (2x + 3)^3(fg)(x)=f(g(x))=(2x+3)3

假设我们有两个函数 g(x)g(x)g(x)f(u)f(u)f(u)
3. 先绘制 g(x)g(x)g(x) 的图形。例如,g(x)=x2g(x) = x^2g(x)=x2 是一个抛物线。
4. 然后将 g(x)g(x)g(x) 的输出代入 f(u)f(u)f(u),绘制 f(g(x))f(g(x))f(g(x)) 的图形。例如,f(u)=sin⁡(u)f(u) = \sin(u)f(u)=sin(u),将 u=x2u = x^2u=x2 代入,得到 sin⁡(x2)\sin(x^2)sin(x2) 的图形。
在这里插入图片描述

import numpy as np
import matplotlib.pyplot as plt

# 定义两个函数
def g(x):
    return x**2

def f(u):
    return np.sin(u)

# 生成x的值
x = np.linspace(-2, 2, 400)
y_g = g(x)
y_f = f(y_g)

# 初始化图形
fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(8, 12))

# 绘制函数 g(x)
ax1.plot(x, y_g, label=r'$g(x) = x^2$', color='blue')
ax1.set_title('Function $g(x)$')
ax1.set_xlabel('$x$')
ax1.set_ylabel('$g(x)$')
ax1.legend()

# 绘制函数 f(u)
u = np.linspace(0, 4, 400)
ax2.plot(u, f(u), label=r'$f(u) = \sin(u)$', color='green')
ax2.set_title('Function $f(u)$')
ax2.set_xlabel('$u$')
ax2.set_ylabel('$f(u)$')
ax2.legend()

# 绘制复合函数 h(x) = f(g(x))
ax3.plot(x, y_f, label=r'$h(x) = \sin(x^2)$', color='red')
ax3.set_title('Composite Function $h(x) = f(g(x))$')
ax3.set_xlabel('$x$')
ax3.set_ylabel('$h(x)$')
ax3.legend()

# 调整子图之间的间距
plt.subplots_adjust(hspace=0.5)

# 显示图形
plt.show()

链式法则(Chain Rule)是微积分中一个重要的求导法则,它用于求复合函数的导数。复合函数是指一个函数的输入是另一个函数的输出,形式上可以写作 y=f(g(x))y = f(g(x))y=f(g(x))。链式法则告诉我们如何求这种复合函数的导数。

如果我们有两个函数 fffggg,其中 y=f(u)y = f(u)y=f(u)u=g(x)u = g(x)u=g(x),那么根据链式法则,复合函数 y=f(g(x))y = f(g(x))y=f(g(x))xxx 的导数可以表示为:
dydx=dydu⋅dudx\frac{dy}{dx} = \frac{dy}{du} \cdot \frac{du}{dx}dxdy=dudydxdu

用更直观的方式理解,链式法则表明:

  1. 首先求出内部函数 u=g(x)u = g(x)u=g(x)xxx 的导数,即 dudx\frac{du}{dx}dxdu
  2. 然后求出外部函数 y=f(u)y = f(u)y=f(u)uuu 的导数,即 dydu\frac{dy}{du}dudy
  3. 最后将这两个导数相乘,得到复合函数 y=f(g(x))y = f(g(x))y=f(g(x))xxx 的导数。

例子

假设有函数 y=sin⁡(x2)y = \sin(x^2)y=sin(x2),我们希望求 yyyxxx 的导数。

  1. 首先,我们将 y=sin⁡(x2)y = \sin(x^2)y=sin(x2) 看作两个函数的复合,即 y=sin⁡(u)y = \sin(u)y=sin(u)u=x2u = x^2u=x2
  2. 对内部函数 u=x2u = x^2u=x2 求导:dudx=2x\frac{du}{dx} = 2xdxdu=2x
  3. 对外部函数 y=sin⁡(u)y = \sin(u)y=sin(u) 求导:dydu=cos⁡(u)\frac{dy}{du} = \cos(u)dudy=cos(u)
  4. 将这两个结果相乘:dydx=dydu⋅dudx=cos⁡(x2)⋅2x\frac{dy}{dx} = \frac{dy}{du} \cdot \frac{du}{dx} = \cos(x^2) \cdot 2xdxdy=dudydxdu=cos(x2)2x
    所以,y=sin⁡(x2)y = \sin(x^2)y=sin(x2)xxx 的导数为:
    dydx=2xcos⁡(x2)\frac{dy}{dx} = 2x \cos(x^2)dxdy=2xcos(x2)

微分符号 ddd 的含义

  1. 导数的定义
    导数表示函数在某一点的变化率。对于函数 y=f(x)y = f(x)y=f(x),它在 xxx 处的导数定义为:dydx=lim⁡Δx→0ΔyΔx\frac{dy}{dx} = \lim_{\Delta x \to 0} \frac{\Delta y}{\Delta x}dxdy=limΔx0ΔxΔy这里,Δy\Delta yΔyΔx\Delta xΔx 分别表示 yyyxxx 的增量。当这些增量趋近于零时,我们用 dydydydxdxdx 来表示这些非常小的变化量。
  2. 微分表示法
    微分符号 ddd 用于表示一个函数的微小变化。例如,dxdxdx 表示变量 xxx 的一个非常小的变化量。同样地,dydydy 表示函数 yyy 的一个非常小的变化量。如果 y=f(x)y = f(x)y=f(x),那么 dydydy 表示 yyyxxx 的微小变化,可以表示为:dy=f′(x)⋅dxdy = f'(x) \cdot dxdy=f(x)dx这里,f′(x)f'(x)f(x) 是函数 f(x)f(x)f(x) 的导数,表示 xxx 处的变化率。

链式法则中的 ddd

在链式法则中,ddd 表示不同变量的微小变化。例如:

  • dududu 表示变量 uuu 的微小变化量。

  • dxdxdx 表示变量 xxx 的微小变化量。

  • dydydy 表示函数 yyy 的微小变化量。
    链式法则告诉我们,当我们有复合函数 y=f(g(x))y = f(g(x))y=f(g(x)) 时,yyyxxx 的变化可以分解为 yyyuuu 的变化以及 uuuxxx 的变化:
    dydx=dydu⋅dudx\frac{dy}{dx} = \frac{dy}{du} \cdot \frac{du}{dx}dxdy=dudydxdu
    这里,每个 ddd 都表示相应变量的微小变化。例如:

  • dydx\frac{dy}{dx}dxdy 表示 yyyxxx 的变化率。

  • dydu\frac{dy}{du}dudy 表示 yyyuuu 的变化率。

  • dudx\frac{du}{dx}dxdu 表示 uuuxxx 的变化率。
    通过这样分解,我们可以更容易地计算复合函数的导数。

基于极限和增量来理解链式法则

  1. 定义复合函数和导数
  • y=f(u)y = f(u)y=f(u),其中 u=g(x)u = g(x)u=g(x)
  • 我们需要求 y=f(g(x))y = f(g(x))y=f(g(x))xxx 的导数。
  1. 增量表示
  • Δx\Delta xΔxxxx 的一个非常小的增量。
  • 相应的, uuu 有一个非常小的增量 Δu\Delta uΔu,其中 Δu=g(x+Δx)−g(x)\Delta u = g(x + \Delta x) - g(x)Δu=g(x+Δx)g(x)
  • yyy 的增量表示为 Δy=f(g(x+Δx))−f(g(x))\Delta y = f(g(x + \Delta x)) - f(g(x))Δy=f(g(x+Δx))f(g(x))
  1. 导数的定义dydx=lim⁡Δx→0ΔyΔx\frac{dy}{dx} = \lim_{\Delta x \to 0} \frac{\Delta y}{\Delta x}dxdy=limΔx0ΔxΔy
  2. 应用链式法则的思想Δy=f(g(x+Δx))−f(g(x))\Delta y = f(g(x + \Delta x)) - f(g(x))Δy=f(g(x+Δx))f(g(x))可以表示为:ΔyΔx=f(g(x+Δx))−f(g(x))Δx\frac{\Delta y}{\Delta x} = \frac{f(g(x + \Delta x)) - f(g(x))}{\Delta x}ΔxΔy=Δxf(g(x+Δx))f(g(x))
  3. 拆分增量
    由于 u=g(x)u = g(x)u=g(x),我们可以引入 Δu\Delta uΔuΔyΔx=f(g(x+Δx))−f(g(x))g(x+Δx)−g(x)⋅g(x+Δx)−g(x)Δx\frac{\Delta y}{\Delta x} = \frac{f(g(x + \Delta x)) - f(g(x))}{g(x + \Delta x) - g(x)} \cdot \frac{g(x + \Delta x) - g(x)}{\Delta x}ΔxΔy=g(x+Δx)g(x)f(g(x+Δx))f(g(x))Δxg(x+Δx)g(x)
  4. 极限过程
    Δx→0\Delta x \to 0Δx0,我们有 Δu→0\Delta u \to 0Δu0,因此:dydx=lim⁡Δx→0(f(g(x+Δx))−f(g(x))g(x+Δx)−g(x)⋅g(x+Δx)−g(x)Δx)\frac{dy}{dx} = \lim_{\Delta x \to 0} \left( \frac{f(g(x + \Delta x)) - f(g(x))}{g(x + \Delta x) - g(x)} \cdot \frac{g(x + \Delta x) - g(x)}{\Delta x} \right)dxdy=Δx0lim(g(x+Δx)g(x)f(g(x+Δx))f(g(x))Δxg(x+Δx)g(x))根据导数的定义,我们有:dydx=(lim⁡Δu→0ΔyΔu)⋅(lim⁡Δx→0ΔuΔx)\frac{dy}{dx} = \left( \lim_{\Delta u \to 0} \frac{\Delta y}{\Delta u} \right) \cdot \left( \lim_{\Delta x \to 0} \frac{\Delta u}{\Delta x} \right)dxdy=(Δu0limΔuΔy)(Δx0limΔxΔu)
  5. 导数表示dydx=dydu⋅dudx\frac{dy}{dx} = \frac{dy}{du} \cdot \frac{du}{dx}dxdy=dudydxdu其中,dydu=lim⁡Δu→0ΔyΔu\frac{dy}{du} = \lim_{\Delta u \to 0} \frac{\Delta y}{\Delta u}dudy=Δu0limΔuΔydudx=lim⁡Δx→0ΔuΔx\frac{du}{dx} = \lim_{\Delta x \to 0} \frac{\Delta u}{\Delta x}dxdu=Δx0limΔxΔu
    因此复合函数的导数可以表示为外层函数的导数乘以内层函数的导数。

可视化

  • g(x):定义了内层函数 sin⁡(x)\sin(x)sin(x)
  • f(u):定义了外层函数 exp⁡(u)\exp(u)exp(u)
  • g_prime(x) 和 f_prime(u):定义了对应的导数。
  • h(x):复合函数 esin⁡(x)e^{\sin(x)}esin(x)
  • h_prime(x):复合函数的导数,使用链式法则 f′(g(x))⋅g′(x)f'(g(x)) \cdot g'(x)f(g(x))g(x)

在这里插入图片描述

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

# 定义两个函数及其导数
def g(x):
    return np.sin(x)

def f(u):
    return np.exp(u)

def g_prime(x):
    return np.cos(x)

def f_prime(u):
    return np.exp(u)

# 复合函数及其导数
def h(x):
    return f(g(x))

def h_prime(x):
    return f_prime(g(x)) * g_prime(x)

# 生成x的值
x = np.linspace(0, 2 * np.pi, 400)
y_g = g(x)
y_f = f(y_g)
y_h = h(x)

# 初始化图形
fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(8, 12))

# 绘制函数 g(x)
ax1.plot(x, y_g, label=r'$g(x) = \sin(x)$', color='blue')
ax1.set_title('Function $g(x)$')
ax1.set_xlabel('$x$')
ax1.set_ylabel('$g(x)$')
ax1.legend()

# 绘制函数 f(u)
u = np.linspace(-1, 1, 400)
ax2.plot(u, f(u), label=r'$f(u) = e^{u}$', color='green')
ax2.set_title('Function $f(u)$')
ax2.set_xlabel('$u$')
ax2.set_ylabel('$f(u)$')
ax2.legend()

# 绘制复合函数 h(x) = f(g(x))
ax3.plot(x, y_h, label=r'$h(x) = e^{\sin(x)}$', color='red')
ax3.set_title('Composite Function $h(x) = f(g(x))$')
ax3.set_xlabel('$x$')
ax3.set_ylabel('$h(x)$')
ax3.legend()

plt.subplots_adjust(hspace=0.5)

# 初始化点和切线
point1, = ax1.plot([], [], 'ro')  # 点
tangent_line1, = ax1.plot([], [], 'r--')  # 切线

point2, = ax2.plot([], [], 'ro')  # 点
tangent_line2, = ax2.plot([], [], 'r--')  # 切线

point3, = ax3.plot([], [], 'ro')  # 点
tangent_line3, = ax3.plot([], [], 'r--')  # 切线

def init():
    point1.set_data([], [])
    tangent_line1.set_data([], [])
    point2.set_data([], [])
    tangent_line2.set_data([], [])
    point3.set_data([], [])
    tangent_line3.set_data([], [])
    return point1, tangent_line1, point2, tangent_line2, point3, tangent_line3

def animate(i):
    x0 = i * 2 * np.pi / 100  # 从 0 开始,步长为 2π / 100
    y0_g = g(x0)
    y0_h = h(x0)
    
    # 绘制 g(x) 的点和切线
    slope_g = g_prime(x0)
    point1.set_data([x0], [y0_g])
    tangent_x1 = np.array([x0 - 0.5, x0 + 0.5])
    tangent_y1 = y0_g + slope_g * (tangent_x1 - x0)
    tangent_line1.set_data(tangent_x1, tangent_y1)
    
    # 绘制 f(g(x)) 的点和切线
    u0 = y0_g
    y0_f = f(u0)
    slope_f = f_prime(u0)
    point2.set_data([u0], [y0_f])
    tangent_x2 = np.array([u0 - 0.5, u0 + 0.5])
    tangent_y2 = y0_f + slope_f * (tangent_x2 - u0)
    tangent_line2.set_data(tangent_x2, tangent_y2)
    
    # 绘制 h(x) = f(g(x)) 的点和切线
    slope_h = h_prime(x0)
    point3.set_data([x0], [y0_h])
    tangent_x3 = np.array([x0 - 0.5, x0 + 0.5])
    tangent_y3 = y0_h + slope_h * (tangent_x3 - x0)
    tangent_line3.set_data(tangent_x3, tangent_y3)
    
    return point1, tangent_line1, point2, tangent_line2, point3, tangent_line3

ani = animation.FuncAnimation(fig, animate, frames=100, init_func=init, blit=True)

# 保存为gif
ani.save('chain_rule_animation.gif', writer='imagemagick')

# 显示动画
plt.show()
Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐