这是一篇来自于旧站的重置文章。

前言

其实这个很早之前就想做了,很久之前做过一个《[人工智能] 反向传播BP算法+用Excel写一个二层神经网络怎么破》,但是,由于当时学术造诣不深,也只做了一个不完全的Regression(回归),这里想要把整篇文章完善一下。

而且当时也没有用到Markdown自带的公式,类似:$$MSE = \frac{1}{2}(y - y_{true})^{2}$$

所以,这次打算更加完善的做完这一篇文章。

现在已经转入了 更高级的系统。

这次,终于可以更加完善中的完善做完这一篇文章了。

正文

1. Regression(回归)

1.1 基本要素

flowchart LR subgraph Input[输入] X1[x_1] X2[x_2] end subgraph Hidden[隐藏层: 线性] H1[h1 = x_1 * w_11 + x_2 * w_21] H2[h2 = x_1 * w_12 + x_2 * w_22] end subgraph Output[输出层: 线性] Y[y = w_3 * h_1 + w_4 * h_2] end X1 -->|w_11| H1 X2 -->|w_21| H1 X1 -->|w_12| H2 X2 -->|w_22| H2 H1 -->|w_3| Y H2 -->|w_4| Y

我们这里先介绍一下回归的NN流程,我们的基础元素如下:

  • 输入层: x_{1}, x_{2}

  • 隐藏层:h1 = x_{1}w_{1,1} + x_{2}w_{2,1}, h2=x_{1}w_{1,2} + x_{2}w_{2,2}

  • 输出层: y = w_{3}h_{1} + w_{4}h_{2}

  • Loss(回归问题我们使用MSE):
    对于单个样本:

    loss = \frac{1}{2}(y-y_{true})^2

    (这里的 \frac{1}{2}是为了梯度好看,不影响最终的结果)

1.2 前向传递

我们通过单个样本 [x_{1}, x_{2}] 传入得到 h1 = x_{1}w_{1,1} + x_{2}w_{2,1}, h2=x_{1}w_{1,2} + x_{2}w_{2,2},最终得到 y = w_{3}h_{1} + w_{4}h_{2},然后通过MSE计算得到 loss = \frac{1}{2}(y-y_{true})^2

1.3 反向传递

1.3.1 梯度更新方向

我们现在需要做的是,通过 loss 去计算需要对 w_{i,j} 进行多少的更新,但是我们该如何去设计这样一个更新呢?

最直接的一个方法就是:对loss 求偏导,然后按反方向更新w_{i,j}

但是为什么这样能够让预测更接近真实呢?

直觉解释(“下山找谷底”)

loss是一个函数:

L(w)=神经网络输出与真实的差

它是一个关于 wx 的函数,因为不同的 wx 会导致不同的输出, 从而导致不同的 loss。求导 \frac{dloss}{dw}, \frac{\partial{loss}}{\partial{w}} 具有一个很重要的数学性质

梯度方向是函数值增长最快的方向

所以,对求导出来的\frac{dloss}{dw}, \frac{\partial{loss}}{\partial{w}} 取负数,那么就是函数值减少的最快方向。这种直觉解释可以理解为所谓的“下山找谷底”、“摸黑下山”,我们顺着loss减少的方向,迟早能找到一个(局部loss)最小值的点,这个点的意思就是“在这个点,神经网络输出与真实的差最小”,也就是我们想要找到的点。

数学解释(泰勒展开)

其实这个也能通过泰勒展开来解释。

假设loss在某个 w 附近可以近似为(如果 \eta足够小,仅考虑一阶泰勒展开):

L(w + \Delta w) \approx L(w) + \frac{\partial{L}}{\partial{w}} \Delta w

如果我们选择:

\Delta w = - \eta \frac{\partial{L}}{\partial{w}}

那么:

L(w + \Delta w) \approx L(w) - \eta (\frac{\partial{L}}{\partial{w}})^2

那么平方永远非负,这保证了如果学习率\eta足够小,那么loss就能够保证永远往减小的方向进行。

1.3.2 梯度更新计算

在证明了我们的梯度更新方向之后,我们就可以知道我们该怎么做了:我们需要往 -\frac{\partial{loss}}{\partial{w}} 方向更新:

w \leftarrow w - \eta \frac{\partial{loss}}{\partial{w}}

其中 \eta为学习率。

那么我们要怎么计算 \frac{\partial{loss}}{\partial{w}}呢?我们需要用到一些数学的方法:

\frac{\partial{loss}}{\partial{w}} = \frac{\partial{loss}}{\partial{y}} \cdot \frac{\partial{y}}{\partial{w}}

上面的 \frac{\partial{loss}}{\partial{y}}\frac{\partial{y}}{\partial{w}} 我们是都可以计算的,那么这样,我们就可以反向更新了。

1.3.3 更新 w_{3}, w_{4}

我们根据以下公式:

\begin{aligned} &\frac{\partial{loss}}{\partial{w_3}} = \frac{\partial{loss}}{\partial{y}} \cdot \frac{\partial{y}}{\partial{w_3}} \\ &\frac{\partial{loss}}{\partial{w_4}} = \frac{\partial{loss}}{\partial{y}} \cdot \frac{\partial{y}}{\partial{w_4}} \end{aligned}

由于:

\begin{aligned} &loss = \frac{1}{2}(y-y_{true})^2 \\ &y = w_3h_1 + w_4h_2 \\ &h_1 = x_1w_{1,1} + x_2w_{2,1} \\ &h_2 = x_1w_{1,2} + x_2w_{2,2} \end{aligned}

我们可以得到

\begin{aligned} &\frac{\partial{loss}}{\partial{y}} = y - y_{true} \\ &\frac{\partial{y}}{\partial{w_3}} = h_1 \\ &\frac{\partial{y}}{\partial{w_4}} = h_2 \end{aligned}

最终,我们可以得到:

\begin{aligned} &\frac{\partial{loss}}{\partial{w_3}} = (y - y_{true}) \cdot h_1 = (y - y_{true}) \cdot (x_1w_{1,1} + x_2w_{2,1}) \\ &\frac{\partial{loss}}{\partial{w_4}} = (y - y_{true}) \cdot h_2 = (y - y_{true}) \cdot (x_1w_{1,2} + x_2w_{2,2}) \end{aligned}

其中,所有的变量我们都有值,我们可以计算出来 \frac{\partial{loss}}{\partial{w_3}}, \frac{\partial{loss}}{\partial{w_4}}

\begin{aligned} &w_3' = w_3 - \eta \cdot (y - y_{true}) \cdot (x_1w_{1,1} + x_2w_{2,1}) \\ &w_4' = w_4 - \eta \cdot (y - y_{true}) \cdot (x_1w_{1,2} + x_2w_{2,2}) \end{aligned}

现在,我们更新了这一层的,可以返回更新上一层的了(这也是为什么称之为反向传递更新的原因。)

1.3.4 更新 w_{1,1}, w_{1,2}, w_{2,1}, w_{2,2}

flowchart LR %% ==== 节点定义 ==== X1["x1"] X2["x2"] W11["w11"] W21["w21"] W12["w12"] W22["w22"] W3["w3"] W4["w4"] H1["h1 = x1·w11 + x2·w21"] H2["h2 = x1·w12 + x2·w22"] Y["y = w3·h1 + w4·h2"] Ytrue["y_true"] L["loss = 0.5·(y − y_true)²"] %% ==== 前向 ==== X1 --> H1 X2 --> H1 X1 --> H2 X2 --> H2 W11 --> H1 W21 --> H1 W12 --> H2 W22 --> H2 H1 --> Y H2 --> Y W3 --> Y W4 --> Y Y --> L Ytrue --> L %% ==== 反向(虚线 + 标签) ==== L -.->|∂L/∂y = y − y_true| Y Y -.->|"∂L/∂w3 = (y − y_true)·h1"| W3 Y -.->|"∂L/∂w4 = (y − y_true)·h2"| W4 Y -.->|"∂L/∂h1 = (y − y_true)·w3"| H1 Y -.->|"∂L/∂h2 = (y − y_true)·w4"| H2 H1 -.->|"∂L/∂w11 = (y − y_true)·w3·x1"| W11 H1 -.->|"∂L/∂w21 = (y − y_true)·w3·x2"| W21 H2 -.->|"∂L/∂w12 = (y − y_true)·w4·x1"| W12 H2 -.->|"∂L/∂w22 = (y − y_true)·w4·x2"| W22

2. Classification(分类)

总结

参考

[1] 自己
[2] ChatGPT
[3] [人工智能] 反向传播BP算法+用Excel写一个二层神经网络怎么破

立志做一个有趣的碳水化合物。