硬核拆解!跟着公式“走”一遍,你也能彻底看懂神经网络

引言:从概率视角看AI的本质

在探索神经网络奥秘的旅程中,我们不得不先审视一个深刻的认知:无论是当下令人瞩目的生成式 AI,还是朝着通用人工智能(AGI)迈进的探索,本质上都与“概率模型”紧密相连。从单纯的概率框架出发,现实世界复杂事件的联合分布可被统一表征,而神经网络的非线性拟合能力,又依托通用逼近定理、柯尔莫哥洛夫理论等数学基石。信息论中“压缩即智能”的理念,更是为我们理解 AI 如何从海量数据中提炼规律、模拟智能提供了独特视角。

值得深思的是,我们所处的现实世界本身就充满不确定性,是天然的概率模型,可人们往往追求确定性。这种思维转变,对深入理解 AI 本质与大模型运行逻辑,有着至关重要的意义。为了具体地理解这一过程,就让我们一同拆解一个简单的神经网络,探寻其与概率模型、现实世界的交织脉络。

神经网络如下图所示:

在这里插入图片描述

一、 网络结构与初始化

1. 网络结构

  • 输入层 (Layer 1): 3 个输入神经元,接收初始数据。
  • 隐含层 (Layer 2): 2 个神经元,负责非线性变换。
    • 权重矩阵 W ( 1 ) \mathbf{W}^{(1)} W(1) 维度为 2×3。
    • 偏置向量 b ( 1 ) \mathbf{b}^{(1)} b(1) 维度为 2×1。
    • 激活函数:Sigmoid (为了简单示例,当然也可用 ReLU、Tanh 等)。
  • 输出层 (Layer 3): 3 个神经元,对应最终 3 个类别的分类。
    • 权重矩阵 W ( 2 ) \mathbf{W}^{(2)} W(2) 维度为 3×2。
    • 偏置向量 b ( 2 ) \mathbf{b}^{(2)} b(2)维度为 3×1。
    • 输出处理:不使用 Sigmoid,而是直接输出 logits,然后通过 Softmax 函数计算概率分布,最后使用 交叉熵 (Cross-Entropy) 作为损失。

关于权重矩阵维度的说明
例如, W ( 1 ) \mathbf{W}^{(1)} W(1) 连接第1层(3个神经元)和第2层(2个神经元),其维度为 2x3。这保证了 W ( 1 ) a ( 1 ) + b ( 1 ) \mathbf{W}^{(1)} \mathbf{a}^{(1)} + \mathbf{b}^{(1)} W(1)a(1)+b(1) 的矩阵乘法能够顺利进行。

2. 参数初始化

在训练初始,我们可随机初始化参数。为方便演示和复现,这里我们直接给出一组固定的示例数值。

  • 输入
    a ( 1 ) = [ 1.0 1.0 1.0 ] \mathbf{a}^{(1)} = \begin{bmatrix}1.0 \\ 1.0 \\ 1.0\end{bmatrix} a(1)= 1.01.01.0

  • 隐含层参数:
    W ( 1 ) = [ 0.10 0.20 0.30 0.40 0.50 0.60 ] , b ( 1 ) = [ 0.10 0.10 ] \mathbf{W}^{(1)} = \begin{bmatrix} 0.10 & 0.20 & 0.30\\ 0.40 & 0.50 & 0.60 \end{bmatrix}, \quad \mathbf{b}^{(1)} = \begin{bmatrix} 0.10 \\ 0.10 \end{bmatrix} W(1)=[0.100.400.200.500.300.60],b(1)=[0.100.10]

  • 输出层参数 :
    W ( 2 ) = [ 0.70 0.80 0.90 1.00 1.10 1.20 ] , b ( 2 ) = [ 0.20 0.20 0.20 ] \mathbf{W}^{(2)} = \begin{bmatrix} 0.70 & 0.80\\ 0.90 & 1.00\\ 1.10 & 1.20 \end{bmatrix}, \quad \mathbf{b}^{(2)} = \begin{bmatrix} 0.20 \\ 0.20 \\ 0.20 \end{bmatrix} W(2)= 0.700.901.100.801.001.20 ,b(2)= 0.200.200.20

二、 前向传播:一步步计算网络输出

前向传播(Forward Propagation)是指数据从输入层流向输出层的过程。

1. 隐含层 (Layer 2) 的计算

首先,计算进入隐含层激活函数前的线性组合 z ( 2 ) \mathbf{z}^{(2)} z(2)
z ( 2 ) = W ( 1 ) a ( 1 ) + b ( 1 ) \mathbf{z}^{(2)} = \mathbf{W}^{(1)} \mathbf{a}^{(1)} + \mathbf{b}^{(1)} z(2)=W(1)a(1)+b(1)

由于 W ( 1 ) \mathbf{W}^{(1)} W(1) 2 × 3 2 \times 3 2×3 a ( 1 ) \mathbf{a}^{(1)} a(1) 3 × 1 3 \times 1 3×1 b ( 1 ) \mathbf{b}^{(1)} b(1) 2 × 1 2 \times 1 2×1,所以
z ( 2 ) = [ 0.10 0.20 0.30 0.40 0.50 0.60 ] [ 1.0 1.0 1.0 ] + [ 0.10 0.10 ] = [ ( 0.10 + 0.20 + 0.30 ) + 0.10 ( 0.40 + 0.50 + 0.60 ) + 0.10 ] = [ 0.70 1.60 ] \begin{align} &\mathbf{z}^{(2)} = \begin{bmatrix} 0.10 & 0.20 & 0.30\\ 0.40 & 0.50 & 0.60 \end{bmatrix} \begin{bmatrix} 1.0 \\ 1.0 \\ 1.0 \end{bmatrix} + \begin{bmatrix} 0.10 \\ 0.10 \end{bmatrix} = \\ &\begin{bmatrix} (0.10 + 0.20 + 0.30) + 0.10 \\ (0.40 + 0.50 + 0.60) + 0.10 \end{bmatrix}= \begin{bmatrix} 0.70 \\ 1.60 \end{bmatrix} \end{align} z(2)=[0.100.400.200.500.300.60] 1.01.01.0 +[0.100.10]=[(0.10+0.20+0.30)+0.10(0.40+0.50+0.60)+0.10]=[0.701.60]

然后,将 z ( 2 ) \mathbf{z}^{(2)} z(2) 通过 Sigmoid 激活函数,得到隐含层的输出 a ( 2 ) \mathbf{a}^{(2)} a(2)
a ( 2 ) = σ ( z ( 2 ) ) , σ ( x ) = 1 1 + e − x \mathbf{a}^{(2)} = \sigma\bigl(\mathbf{z}^{(2)}\bigr), \quad \sigma(x) = \frac{1}{1 + e^{-x}} a(2)=σ(z(2)),σ(x)=1+ex1
对应分量:
a 1 ( 2 ) = 1 1 + e − 0.70 ≈ 0.66818777 , a 2 ( 2 ) = 1 1 + e − 1.60 ≈ 0.83201839 \begin{align} &a_1^{(2)} = \frac{1}{1 + e^{-0.70}} \approx 0.66818777,\quad \\ &a_2^{(2)} = \frac{1}{1 + e^{-1.60}} \approx 0.83201839 \end{align} a1(2)=1+e0.7010.66818777,a2(2)=1+e1.6010.83201839
故:
a ( 2 ) ≈ [ 0.66818777 0.83201839 ] \mathbf{a}^{(2)} \approx \begin{bmatrix} 0.66818777 \\ 0.83201839 \end{bmatrix} a(2)[0.668187770.83201839]

核心概念:

  • z通常表示某一层线性计算(权重乘法和偏置加法)的结果。
  • a通常表示 z经过激活函数后的输出,它将作为下一层的输入。

2. 输出层 (Layer 3) 的计算

接下来,用隐含层的输出 a ( 2 ) \mathbf{a}^{(2)} a(2) 计算输出层的线性组合 z ( 3 ) \mathbf{z}^{(3)} z(3),也称为 logits
z ( 3 ) = W ( 2 )   a ( 2 ) + b ( 2 ) \mathbf{z}^{(3)} = \mathbf{W}^{(2)}\, \mathbf{a}^{(2)} + \mathbf{b}^{(2)} z(3)=W(2)a(2)+b(2)

然后,对 logits z ( 3 ) \mathbf{z}^{(3)} z(3) 应用 Softmax 函数,得到最终的概率分布输出 a ( 3 ) \mathbf{a}^{(3)} a(3)。其中 W ( 2 ) \mathbf{W}^{(2)} W(2) 3 × 2 3 \times 2 3×2 a ( 2 ) \mathbf{a}^{(2)} a(2) 2 × 1 2 \times 1 2×1 b ( 2 ) \mathbf{b}^{(2)} b(2) 3 × 1 3 \times 1 3×1。数值计算如下:
z ( 3 ) = [ 0.70 0.80 0.90 1.00 1.10 1.20 ] [ 0.66818777 0.83201839 ] + [ 0.20 0.20 0.20 ] = [ 0.70 × 0.66818777 + 0.80 × 0.83201839 0.90 × 0.66818777 + 1.00 × 0.83201839 1.10 × 0.66818777 + 1.20 × 0.83201839 ] + [ 0.20 0.20 0.20 ] ≈ [ 1.33334615 1.63338738 1.93240000 ] \begin{aligned} \mathbf{z}^{(3)} &= \begin{bmatrix} 0.70 & 0.80\\ 0.90 & 1.00\\ 1.10 & 1.20 \end{bmatrix} \begin{bmatrix} 0.66818777 \\ 0.83201839 \end{bmatrix} + \begin{bmatrix} 0.20 \\ 0.20 \\ 0.20 \end{bmatrix}\\ &= \begin{bmatrix} 0.70 \times 0.66818777 + 0.80 \times 0.83201839\\ 0.90 \times 0.66818777 + 1.00 \times 0.83201839\\ 1.10 \times 0.66818777 + 1.20 \times 0.83201839 \end{bmatrix} + \begin{bmatrix} 0.20\\ 0.20\\ 0.20 \end{bmatrix}\\ &\approx \begin{bmatrix} 1.33334615 \\ 1.63338738 \\ 1.93240000 \end{bmatrix} \end{aligned} z(3)= 0.700.901.100.801.001.20 [0.668187770.83201839]+ 0.200.200.20 = 0.70×0.66818777+0.80×0.832018390.90×0.66818777+1.00×0.832018391.10×0.66818777+1.20×0.83201839 + 0.200.200.20 1.333346151.633387381.93240000

然后对 logits 做 Softmax 得到输出层的激活 a ( 3 ) \mathbf{a}^{(3)} a(3):
a i ( 3 ) = e z i ( 3 ) ∑ j e z j ( 3 ) a_i^{(3)} = \frac{e^{z_i^{(3)}}}{\sum_j e^{z_j^{(3)}}} ai(3)=jezj(3)ezi(3)
分母是 e 1.3333 + e 1.6334 + e 1.9324 e^{1.3333} + e^{1.6334} + e^{1.9324} e1.3333+e1.6334+e1.9324。我们分别计算 (取近似):

  • e 1.3333 ≈ 3.793 e^{1.3333} \approx 3.793 e1.33333.793
  • e 1.6334 ≈ 5.120 e^{1.6334} \approx 5.120 e1.63345.120
  • e 1.9324 ≈ 6.909 e^{1.9324} \approx 6.909 e1.93246.909
    因此分母 ≈ 3.793 + 5.120 + 6.909 = 15.822 \approx 3.793 + 5.120 + 6.909 = 15.822 3.793+5.120+6.909=15.822
    各分量:
  • a 1 ( 3 ) ≈ 3.793 / 15.822 ≈ 0.2397 a_1^{(3)} \approx 3.793 / 15.822 \approx 0.2397 a1(3)3.793/15.8220.2397
  • a 2 ( 3 ) ≈ 5.120 / 15.822 ≈ 0.3236 a_2^{(3)} \approx 5.120 / 15.822 \approx 0.3236 a2(3)5.120/15.8220.3236
  • a 3 ( 3 ) ≈ 6.909 / 15.822 ≈ 0.4367 a_3^{(3)} \approx 6.909 / 15.822 \approx 0.4367 a3(3)6.909/15.8220.4367
    故输出层最终得到的概率分布 (Softmax) 为:
    a ( 3 ) ≈ [ 0.2397 0.3236 0.4367 ] \mathbf{a}^{(3)} \approx \begin{bmatrix} 0.2397 \\ 0.3236 \\ 0.4367 \end{bmatrix} a(3) 0.23970.32360.4367
    至此,一次完整的前向传播完成。我们得到了模型对输入样本的预测概率分布。

三、 损失函数:衡量预测与现实的差距

我们使用交叉熵损失 (Cross-Entropy Loss) 来衡量模型预测 a ( 3 ) \mathbf{a}^{(3)} a(3)与真实标签 t 之间的差距。

为什么选择交叉熵?
在像大语言模型这样的现代分类任务中,交叉熵是首选损失函数。当预测概率偏离真实标签(概率为1)时,它会产生一个非常大的损失值(梯度很陡),这能更高效地指导模型参数更新,从而加快收敛速度。相比之下,均方差(MSE)在分类问题中容易出现梯度消失,导致训练缓慢。

假设我们的真实标签是类别 1,其 one-hot 编码为 t = [ 1 ,   0 ,   0 ] T \mathbf{t} = [1,\, 0,\, 0]^T t=[1,0,0]T
交叉熵损失 (Cross-Entropy) 定义为:
L = − ∑ i t i ln ⁡ ( a i ( 3 ) ) L = -\sum_{i} t_i \ln(a_i^{(3)}) L=itiln(ai(3))
在本例中,只有 t 1 = 1 t_1=1 t1=1,其余为 0,因此
a ( 3 ) ≈ [ 0.2397 0.3236 0.4367 ] L = − ( t 1 ∗ l n ( a 1 ( 3 ) ) + t 2 ∗ l n ( a 2 ( 3 ) ) + t 3 ∗ l n ( a 3 ( 3 ) ) ) L = − ( 1 ∗ l n ( 0.2397 ) + 0 ∗ l n ( 0.3236 ) + 0 ∗ l n ( 0.4367 ) ) L = − ln ⁡ ( a 1 ( 3 ) ) = − ln ⁡ ( 0.2397 ) ≈ 1.434 \begin{align} &\mathbf{a}^{(3)} \approx \begin{bmatrix} 0.2397 \\ 0.3236 \\ 0.4367 \end{bmatrix} \\ & L = - (t_1 * ln(a^{(3)}_1) + t_2 * ln(a^{(3)}_2) + t_3 * ln(a^{(3)}_3)) \\ &L = - (1 * ln(0.2397) + 0 * ln(0.3236) + 0 * ln(0.4367)) \\ &L = - \ln(a_1^{(3)}) = - \ln(0.2397) \approx 1.434 \\ \end{align} a(3) 0.23970.32360.4367 L=(t1ln(a1(3))+t2ln(a2(3))+t3ln(a3(3)))L=(1ln(0.2397)+0ln(0.3236)+0ln(0.4367))L=ln(a1(3))=ln(0.2397)1.434

计算得到的损失 L ≈ 1.434。这个值表示当前模型预测的“错误程度”,我们的目标就是通过调整权重和偏置来让这个值变得尽可能小。

注意:以上是单个样本的损失。在实际训练中,通常会计算一个批次(mini-batch)中所有样本的平均损失,然后根据这个平均损失进行一次反向传播。

四、 反向传播:误差的逐层归因

反向传播(Backpropagation)是训练神经网络的核心。它通过链式法则,将输出层的总损失(误差)逐层向后传递,并计算出每一层参数(权重和偏置)对总损失应负的“责任”,即梯度

1. 输出层的梯度

首先计算损失 L 对输出层线性组合 z ( 3 ) \mathbf{z}^{(3)} z(3) 的梯度,我们称之为误差 δ ( 3 ) δ^{(3)} δ(3)。对于 Softmax + 交叉熵的组合,这个梯度有一个非常简洁的“黄金公式”:
δ ( 3 ) = ∂ L ∂ z 3 = a ( 3 ) − t \delta^{(3)} = \frac{∂L}{∂z_{3}}=\mathbf{a}^{(3)} - \mathbf{t} δ(3)=z3L=a(3)t

这个公式的美妙之处在于它直接将模型的预测 a ( 3 ) \mathbf{a}^{(3)} a(3)和真实标签 t联系起来,其差值即为输出层的误差。我们给出这个公式简单的推导过程:推导公式
下面我们根据给出的数值做出计算如下:
δ ( 3 ) = a ( 3 ) − t = [ 0.2397 − 1 0.3236 − 0 0.4367 − 0 ] = [ − 0.7603 0.3236 0.4367 ] \delta^{(3)} = \mathbf{a}^{(3)} - \mathbf{t}= \begin{bmatrix} 0.2397 - 1 \\ 0.3236 - 0 \\ 0.4367 - 0 \end{bmatrix}= \begin{bmatrix} -0.7603 \\ 0.3236 \\ 0.4367 \end{bmatrix} δ(3)=a(3)t= 0.239710.323600.43670 = 0.76030.32360.4367

接下来,我们利用这个误差 δ ( 3 ) δ^{(3)} δ(3) 计算输出层参数 w ( 2 ) w^{(2)} w(2) b ( 2 ) b^{(2)} b(2) 的梯度。

1.1 权重梯度

∇ W ( 2 ) L = δ ( 3 ) ⋅ ( a ( 2 ) ) T \nabla_{\mathbf{W}^{(2)}} L = \delta^{(3)} \cdot (\mathbf{a}^{(2)})^T W(2)L=δ(3)(a(2))T
权重梯度公式推导:推导公式

根据给定的数值计算如下:

δ ( 3 ) = [ − 0.7603 0.3236 0.4367 ] , a ( 2 ) = [ 0.66818777 0.83201839 ] \delta^{(3)} = \begin{bmatrix} -0.7603\\ 0.3236\\ 0.4367 \end{bmatrix}, \quad \mathbf{a}^{(2)} = \begin{bmatrix} 0.66818777\\ 0.83201839 \end{bmatrix} δ(3)= 0.76030.32360.4367 ,a(2)=[0.668187770.83201839]
( a ( 2 ) ) T = [ 0.66818777 , 0.83201839 ] (a^{(2)})^T=[0.66818777,0.83201839] (a(2))T=[0.66818777,0.83201839]
所以:

∇ W ( 2 ) L = [ − 0.7603 × 0.66818777 − 0.7603 × 0.83201839   0.3236 × 0.66818777   0.3236 × 0.83201839   0.4367 × 0.66818777   0.4367 × 0.83201839 ] ≈ [ − 0.508 ,   − 0.633 0.216 ,   0.269 0.292 ,   0.364 ] \begin{align} \nabla_{\mathbf{W}^{(2)}} L &= \begin{bmatrix} -0.7603 \times 0.66818777 & -0.7603 \times 0.83201839\\ \ 0.3236 \times 0.66818777 & \ 0.3236 \times 0.83201839\\ \ 0.4367 \times 0.66818777 & \ 0.4367 \times 0.83201839 \end{bmatrix} \\ &\approx \begin{bmatrix} -0.508,\, -0.633 \\ 0.216,\, 0.269 \\ 0.292,\, 0.364 \end{bmatrix} \end{align} W(2)L= 0.7603×0.66818777 0.3236×0.66818777 0.4367×0.668187770.7603×0.83201839 0.3236×0.83201839 0.4367×0.83201839 0.508,0.6330.216,0.2690.292,0.364

1.2 偏置梯度

偏置 b ( 2 ) \mathbf{b}^{(2)} b(2) 的梯度计算公式如下:
∂ L ∂ b i ( 2 ) = δ i ( 3 ) \frac{\partial L}{\partial b_i^{(2)}} = \delta_i^{(3)} bi(2)L=δi(3)
即偏置的梯度就是 δ ( 3 ) \delta^{(3)} δ(3) 的各分量。

∇ b ( 2 ) L = [ − 0.7603 0.3236 0.4367 ] \nabla_{\mathbf{b}^{(2)}} L = \begin{bmatrix} -0.7603 \\ 0.3236 \\ 0.4367 \end{bmatrix} b(2)L= 0.76030.32360.4367
这就是输出层偏置的梯度矩阵。

2. 隐含层的梯度

误差需要从输出层传播回隐含层。隐含层的误差 δ ( 2 ) δ^{(2)} δ(2)计算如下:
隐含层的误差梯度 δ ( 2 ) = ∂ L ∂ z ( 2 ) \delta^{(2)} = \frac{\partial L}{\partial z^{(2)}} δ(2)=z(2)L 根据链式法则
δ ( 2 ) = ∂ L ∂ z ( 3 ) ⋅ ∂ z ( 3 ) ∂ a ( 2 ) ⋅ ∂ a ( 2 ) ∂ z ( 2 ) \delta^{(2)} = \frac{\partial L}{\partial z^{(3)}} \cdot \frac{\partial z^{(3)}}{\partial a^{(2)}} \cdot \frac{\partial a^{(2)}}{\partial z^{(2)}} δ(2)=z(3)La(2)z(3)z(2)a(2)
根据
z ( 3 ) = W ( 2 ) . a ( 2 ) + b ( 2 ) z^{(3)}=W^{(2)}.a^{(2)}+b^{(2)} z(3)=W(2).a(2)+b(2) => ∂ z ( 3 ) ∂ a ( 2 ) = ( W ( 2 ) ) T \frac{\partial z^{(3)}}{\partial a^{(2)}}=(W^{(2)})^T a(2)z(3)=(W(2))T
(这个推导略可参考权重梯度-偏导构成的雅可比矩阵)

a ( 2 ) = σ ( z ( 2 ) ) a^{(2)}=\sigma( \mathbf{z}^{(2)} ) a(2)=σ(z(2)) => ∂ a ( 2 ) ∂ z ( 2 ) = σ ′ ( z ( 2 ) ) \frac{\partial a^{(2)}}{\partial z^{(2)}}=\sigma'( \mathbf{z}^{(2)} ) z(2)a(2)=σ(z(2))
δ ( 3 ) = ∂ L ∂ z ( 3 ) \delta^{(3)} = \frac{\partial L}{\partial z^{(3)}} δ(3)=z(3)L

此神经网络隐含层误差梯度公式变为:

δ ( 2 ) = ( W ( 2 ) ) T δ ( 3 )   ⊙   σ ′ ( z ( 2 ) ) \delta^{(2)} = \Bigl(\mathbf{W}^{(2)}\Bigr)^T \delta^{(3)} \,\odot\, \sigma'( \mathbf{z}^{(2)} ) δ(2)=(W(2))Tδ(3)σ(z(2))

公式解读:

  • ( W ( 2 ) ) T δ ( 3 ) \Bigl(\mathbf{W}^{(2)}\Bigr)^T \delta^{(3)} (W(2))Tδ(3): 将输出层的误差 δ ( 3 ) δ^{(3)} δ(3)通过转置后的权重矩阵 W ( 2 ) W^{(2)} W(2) 反向传播回来,实现了误差的“责任分配”。
  • σ ′ ( z ( 2 ) ) \sigma'( \mathbf{z}^{(2)} ) σ(z(2)): 乘以隐含层激活函数(Sigmoid)的导数。这衡量了隐含层自身输出对误差的敏感度。
  • : 表示 Hadamard 积,即矩阵对应元素逐个相乘。

这说明要计算隐含层的误差 δ ( 2 ) δ^{(2)} δ(2),需要将输出层的误差 δ ( 3 ) δ^{(3)} δ(3) 沿着连接权重 W ( 2 ) W^{(2)} W(2) 反向传播回来,并考虑隐含层激活函数的导数。这里 ⊙ \odot 表示按元素逐项相乘 (Hadamard product), σ ′ ( z ) = σ ( z ) ( 1 − σ ( z ) ) \sigma'(z) = \sigma(z)(1 - \sigma(z)) σ(z)=σ(z)(1σ(z)) 对应 sigmoid 的导数。这里有一个重要的逻辑就是链式法则反向传播中,梯度需从输出层传递到隐含层,需要符合链式法则的"反向传递”特性,其本质是链式法则中"偏导连乘"在矩阵运算中的维度匹配要求,实现了反向加权,也是标量偏导连乘在高维空间满足维度一致性的必然结果,按元素逐项相乘。还有一点就是当梯度用行向量表示时,矩阵乘法顺序与链式法则书写顺序一致;用列向量时则相反。而深度学习框架中通常默认使用列向量梯度,因此反向传播公式里会出现 “转置矩阵在前” 的现象

先计算 ( W ( 2 ) ) T δ ( 3 ) (\mathbf{W}^{(2)})^T \delta^{(3)} (W(2))Tδ(3) W ( 2 ) \mathbf{W}^{(2)} W(2) 3 × 2 3 \times 2 3×2,所以其转置是 2 × 3 2 \times 3 2×3
( W ( 2 ) ) T = [ 0.70 0.90 1.10 0.80 1.00 1.20 ] (\mathbf{W}^{(2)})^T = \begin{bmatrix} 0.70 & 0.90 & 1.10\\ 0.80 & 1.00 & 1.20 \end{bmatrix} (W(2))T=[0.700.800.901.001.101.20]
δ ( 3 ) \delta^{(3)} δ(3) (大小 3 × 1 3\times1 3×1) 相乘:
( W ( 2 ) ) T δ ( 3 ) = [ 0.70 0.90 1.10 0.80 1.00 1.20 ] [ − 0.7603 0.3236 0.4367 ] (\mathbf{W}^{(2)})^T \delta^{(3)}= \begin{bmatrix} 0.70 & 0.90 & 1.10\\ 0.80 & 1.00 & 1.20 \end{bmatrix} \begin{bmatrix} -0.7603\\ 0.3236\\ 0.4367 \end{bmatrix} (W(2))Tδ(3)=[0.700.800.901.001.101.20] 0.76030.32360.4367

计算:

  • 第一行: 0.70 × − 0.7603 + 0.90 × 0.3236 + 1.10 × 0.4367 0.70 \times -0.7603 + 0.90 \times 0.3236 + 1.10 \times 0.4367 0.70×0.7603+0.90×0.3236+1.10×0.4367
  • 第二行: 0.80 × − 0.7603 + 1.00 × 0.3236 + 1.20 × 0.4367 0.80 \times -0.7603 + 1.00 \times 0.3236 + 1.20 \times 0.4367 0.80×0.7603+1.00×0.3236+1.20×0.4367
    故可近似得到:

( W ( 2 ) ) T δ ( 3 ) ≈ [ 0.2394 0.2394 ] (\mathbf{W}^{(2)})^T \delta^{(3)} \approx \begin{bmatrix} 0.2394\\ 0.2394 \end{bmatrix} (W(2))Tδ(3)[0.23940.2394]
再计算 σ ′ ( z ( 2 ) ) \sigma'(\mathbf{z}^{(2)}) σ(z(2)) ,对于 sigmoid:
σ ′ ( z ) = σ ( z ) ( 1 − σ ( z ) ) \sigma'(z) = \sigma(z)\bigl(1 - \sigma(z)\bigr) σ(z)=σ(z)(1σ(z))
前面我们算过:

z ( 2 ) ≈ [ 0.70 1.60 ] , a ( 2 ) = σ ( z ( 2 ) ) ≈ [ 0.6682 0.8320 ] \mathbf{z}^{(2)} \approx \begin{bmatrix} 0.70\\ 1.60 \end{bmatrix}, \quad \mathbf{a}^{(2)} = \sigma(\mathbf{z}^{(2)}) \approx \begin{bmatrix} 0.6682\\ 0.8320 \end{bmatrix} z(2)[0.701.60],a(2)=σ(z(2))[0.66820.8320]

因此

σ ′ ( z 1 ( 2 ) ) = 0.6682 × ( 1 − 0.6682 ) ≈ 0.6682 × 0.3318 ≈ 0.2218 \sigma'(z_1^{(2)}) = 0.6682 \times (1 - 0.6682) \approx 0.6682 \times 0.3318 \approx 0.2218 σ(z1(2))=0.6682×(10.6682)0.6682×0.33180.2218

σ ′ ( z 2 ( 2 ) ) = 0.8320 × ( 1 − 0.8320 ) ≈ 0.8320 × 0.1680 ≈ 0.139776 \sigma'(z_2^{(2)}) = 0.8320 \times (1 - 0.8320) \approx 0.8320 \times 0.1680 \approx 0.139776 σ(z2(2))=0.8320×(10.8320)0.8320×0.16800.139776
故:
σ ′ ( z ( 2 ) ) ≈ [ 0.2218 0.1398 ] . \sigma'(\mathbf{z}^{(2)}) \approx \begin{bmatrix} 0.2218\\ 0.1398 \end{bmatrix}. σ(z(2))[0.22180.1398].

δ ( 2 ) = [ 0.2394 0.2394 ] ⊙ [ 0.2218 0.1398 ] = [ 0.2394 × 0.2218 0.2394 × 0.1398 ] ≈ [ 0.0531 0.0334 ] . \delta^{(2)} = \begin{bmatrix} 0.2394\\ 0.2394 \end{bmatrix} \odot \begin{bmatrix} 0.2218\\ 0.1398 \end{bmatrix}= \begin{bmatrix} 0.2394 \times 0.2218\\ 0.2394 \times 0.1398 \end{bmatrix} \approx \begin{bmatrix} 0.0531\\ 0.0334 \end{bmatrix}. δ(2)=[0.23940.2394][0.22180.1398]=[0.2394×0.22180.2394×0.1398][0.05310.0334].

得到隐含层误差 δ ( 2 ) \delta^{(2)} δ(2) 后,我们用同样的方法计算隐含层参数 W ( 1 ) W^{(1)} W(1) b ( 1 ) b^{(1)} b(1) 的梯度。

2.1 权重梯度

与输出层类似,这里也是:
∂ L ∂ W i j ( 1 ) = δ i ( 2 ) ⋅ a j ( 1 ) , \frac{\partial L}{\partial W_{ij}^{(1)}} = \delta_i^{(2)} \cdot a_j^{(1)}, Wij(1)L=δi(2)aj(1),

其中 i = 1 , 2 i=1,2 i=1,2 表示隐含层第 i i i 个神经元, j = 1 , 2 , 3 j=1,2,3 j=1,2,3 表示输入层第 j j j 个神经元。因为 a ( 1 ) = [ 1 , 1 , 1 ] T \mathbf{a}^{(1)} = [1,1,1]^T a(1)=[1,1,1]T,所以
∇ W ( 1 ) L = δ ( 2 ) ⋅ ( a ( 1 ) ) T = [ 0.0531 0.0334 ] [ 1 1 1 ] = [ 0.0531 0.0531 0.0531 0.0334 0.0334 0.0334 ] \begin{align} \\ \nabla_{\mathbf{W}^{(1)}} L &= \delta^{(2)} \cdot (\mathbf{a}^{(1)})^T= \begin{bmatrix} 0.0531\\ 0.0334 \end{bmatrix} \begin{bmatrix} 1 & 1 & 1 \end{bmatrix} \\ &= \begin{bmatrix} 0.0531 & 0.0531 & 0.0531\\ 0.0334 & 0.0334 & 0.0334 \end{bmatrix} \end{align} \\ W(1)L=δ(2)(a(1))T=[0.05310.0334][111]=[0.05310.03340.05310.03340.05310.0334]

2.2 偏置梯度

偏置的梯度:
∇ b ( 1 ) L = δ ( 2 ) = [ 0.0531 0.0334 ] . \nabla_{\mathbf{b}^{(1)}} L = \delta^{(2)}= \begin{bmatrix} 0.0531\\ 0.0334 \end{bmatrix}. b(1)L=δ(2)=[0.05310.0334].

五、 参数更新:向正确的方向迈出一步

计算出所有参数的梯度后,我们使用**梯度下降(Gradient Descent)**来更新参数。梯度指明了损失函数上升最快的方向,因此我们沿着梯度的反方向更新参数,就能让损失下降。

更新规则如下,学习率设为 η \eta η,则更新规则为:

W ( l ) ← W ( l ) − η   ∇ W ( l ) L , b ( l ) ← b ( l ) − η   ∇ b ( l ) L . W^{(l)} \leftarrow W^{(l)} - \eta \,\nabla_{W^{(l)}} L, \quad b^{(l)} \leftarrow b^{(l)} - \eta \,\nabla_{b^{(l)}} L. W(l)W(l)ηW(l)L,b(l)b(l)ηb(l)L.

假设学习率 η = 0.1 \eta = 0.1 η=0.1,则每个参数都减去 η \eta η 乘以对应梯度。
例如,更新输出层权重 W ( 2 ) \mathbf{W}^{(2)} W(2):
W i j ( 2 ) ← W i j ( 2 ) − 0.1 × ( ∇ W ( 2 ) L ) i j . W_{ij}^{(2)} \leftarrow W_{ij}^{(2)} - 0.1 \times \bigl(\nabla_{\mathbf{W}^{(2)}} L\bigr)_{ij}. Wij(2)Wij(2)0.1×(W(2)L)ij.
以第一行(对应输出层第1个神经元)为例:

  • W 1 , 1 ( 2 ) W_{1,1}^{(2)} W1,1(2) 原先是 0.70,更新后约 0.70 − 0.1 × ( − 0.508 ) = 0.70 + 0.0508 = 0.7508 0.70 - 0.1 \times (-0.508) = 0.70 + 0.0508 = 0.7508 0.700.1×(0.508)=0.70+0.0508=0.7508
  • W 1 , 2 ( 2 ) W_{1,2}^{(2)} W1,2(2) 原先是 0.80,更新后约 0.80 − 0.1 × ( − 0.633 ) = 0.80 + 0.0633 = 0.8633 0.80 - 0.1 \times (-0.633) = 0.80 + 0.0633 = 0.8633 0.800.1×(0.633)=0.80+0.0633=0.8633

其他同理。所有 b ( 2 ) \mathbf{b}^{(2)} b(2) W ( 1 ) \mathbf{W}^{(1)} W(1) b ( 1 ) \mathbf{b}^{(1)} b(1) 也依此更新。

六、 训练迭代与代码实现

上述“前向传播 → 计算损失 → 反向传播 → 更新参数”的完整流程构成了一次迭代。在实际训练中,我们会重复这个过程成千上万次(称为 Epochs),直到损失 L 下降到一个足够小的阈值(如 0.01),或者达到预设的最大迭代次数。

Python 代码实现

下面是整个过程的 Python 实现,它完美复现了我们手动计算的每一步。

import numpy as np

# ------- 1. 初始化参数 -------
np.random.seed(123)  # 可固定随机种子
# 这里直接用我们示例中给的固定初始化:
W1 = np.array([[0.10, 0.20, 0.30],
               [0.40, 0.50, 0.60]], dtype=float)
b1 = np.array([[0.10],
               [0.10]], dtype=float)

W2 = np.array([[0.70, 0.80],
               [0.90, 1.00],
               [1.10, 1.20]], dtype=float)
b2 = np.array([[0.20],
               [0.20],
               [0.20]], dtype=float)

# 学习率
eta = 0.1

# 训练目标
x = np.array([[1.0],
              [1.0],
              [1.0]])   # 输入 a^(1)
t = np.array([[1.0],
              [0.0],
              [0.0]])   # one-hot 标签

def sigmoid(z):
    return 1.0 / (1.0 + np.exp(-z))

def sigmoid_prime(a):
    # a = sigmoid(z), so sigma'(z) = a * (1 - a)
    return a * (1.0 - a)

def softmax(z):
    exp_z = np.exp(z - np.max(z))  # 防止溢出
    return exp_z / np.sum(exp_z, axis=0, keepdims=True)

def cross_entropy(y, t):
    # y, t shape: (3,1)
    return -np.sum(t * np.log(y + 1e-12))  # 加一点防止 log(0)

# ------- 2. 迭代训练 -------
threshold = 0.01
epoch = 0
max_epoch = 10000  # 防止死循环, 只是示例

while True:
    epoch += 1
    # ----- Forward -----
    # Layer 2
    z2 = np.dot(W1, x) + b1       # (2,1)
    a2 = sigmoid(z2)             # (2,1)
    # Layer 3 (output)
    z3 = np.dot(W2, a2) + b2      # (3,1)
    a3 = softmax(z3)             # (3,1)

    # 计算损失
    loss = cross_entropy(a3, t)

    # 检查是否达到阈值
    if loss < threshold or epoch > max_epoch:
        print(f"Epoch={epoch}, Loss={loss:.6f}")
        break

    # ----- Backward -----
    # 输出层梯度 delta^(3)
    delta3 = a3 - t   # (3,1)

    # 输出层参数梯度
    dW2 = np.dot(delta3, a2.T)    # (3,2)
    db2 = delta3                  # (3,1)

    # 传播到隐层
    delta2 = np.dot(W2.T, delta3) * sigmoid_prime(a2)  # (2,1)

    # 隐层参数梯度
    dW1 = np.dot(delta2, x.T)  # (2,3)
    db1 = delta2               # (2,1)

    # ----- Update -----
    W2 -= eta * dW2
    b2 -= eta * db2
    W1 -= eta * dW1
    b1 -= eta * db1

    # 可输出观察
    if epoch % 500 == 0:
        print(f"Epoch={epoch}, Loss={loss:.6f}")

print("Training finished!")
print("Final parameters:")
print("W1 =\n", W1)
print("b1 =\n", b1)
print("W2 =\n", W2)
print("b2 =\n", b2)

七、 总结与要点

以上,我们完整地手动推演并实现了一个神经网络的训练过程。其核心步骤可以总结为:

  1. 前向传播:

    • 按层计算 z ( l ) = W ( l − 1 ) a ( l − 1 ) + b ( l − 1 ) z^{(l)} = W^{(l-1)} a^{(l-1)} + b^{(l-1)} z(l)=W(l1)a(l1)+b(l1)
    • 激活函数 a ( l ) = σ ( z ( l ) ) a^{(l)} = \sigma(z^{(l)}) a(l)=σ(z(l)) (本示例隐层用 Sigmoid,输出层用 Softmax)
  2. 损失计算:

    • 本文示例使用 Softmax + Cross Entropy
    • 单个样本 t \mathbf{t} t 的交叉熵损失 L = − ∑ i t i ln ⁡ ( a i ) L = -\sum_i t_i \ln(a_i) L=itiln(ai)
  3. 反向传播:

    • 对于 Softmax + Cross Entropy,有简洁公式 δ ( 3 ) = a ( 3 ) − t \delta^{(3)} = a^{(3)} - t δ(3)=a(3)t
    • 隐层梯度 δ ( 2 ) = ( W ( 2 ) ) T δ ( 3 ) ⊙ σ ′ ( z ( 2 ) ) \delta^{(2)} = (W^{(2)})^T \delta^{(3)} \odot \sigma'(z^{(2)}) δ(2)=(W(2))Tδ(3)σ(z(2))
    • 梯度求导 ∇ W ( l ) L = δ ( l ) ⋅ ( a ( l − 1 ) ) T \nabla_{W^{(l)}} L = \delta^{(l)} \cdot (a^{(l-1)})^T W(l)L=δ(l)(a(l1))T ∇ b ( l ) L = δ ( l ) \nabla_{b^{(l)}} L = \delta^{(l)} b(l)L=δ(l)
  4. 更新参数:

    • W ( l ) ← W ( l ) − η ∇ W ( l ) L W^{(l)} \leftarrow W^{(l)} - \eta \nabla_{W^{(l)}} L W(l)W(l)ηW(l)L
    • b ( l ) ← b ( l ) − η ∇ b ( l ) L b^{(l)} \leftarrow b^{(l)} - \eta \nabla_{b^{(l)}} L b(l)b(l)ηb(l)L
  5. 迭代: 不断重复以上步骤,直至模型收敛。

我们之所以如此枯燥地从头到尾手搓一个神经网络,是希望大家能看到它与概率模型的深度绑定。从现实世界概率本质的映照,到通用逼近定理等理论支撑下的非线性拟合,再到信息论视角下智能与压缩的关联,神经网络一步步揭开了 AI 运行的神秘面纱。

当我们从“追求确定性”的思维转向“拥抱概率不确定性”,不仅是理解 AI 本质的关键,更是未来与大模型协同创新的思想基石。当我们意识到 AI 模型与现实世界皆以概率为底色,便能以更包容、更契合本质的视角,继续探索人工智能的无限可能,让技术在理解不确定性、模拟智能的道路上,走得更远、更深入。

上一篇文章 从线性到万能近似定理

由于没有具体关于小米硬件笔试的详细内容,下面从一般角度对小米硬件笔试进行拆解分析。 ### 笔试目的 小米作为知名科技企业,硬件笔试主要是为了筛选出具备扎实硬件相关知识、技能和潜力的人才,以满足其在硬件研发、设计、测试等岗位的需求。通过笔试可以初步评估应聘者对硬件基础知识的掌握程度、解决实际问题的能力以及逻辑思维能力等。 ### 可能涉及的知识领域 - **电路原理**:包括基本电路元件(电阻、电容、电感等)的特性、电路定律(基尔霍夫定律等)、电路分析方法(如节点电压法、网孔电流法)等。例如,可能会有题目要求分析一个复杂电路的电流、电压分布。 ```python # 简单示例:计算串联电阻的总阻值 R1 = 10 R2 = 20 total_resistance = R1 + R2 print(f"串联电阻的总阻值为: {total_resistance} 欧姆") ``` - **模拟电子技术**:如二极管、三极管、场效应管等半导体器件的工作原理、放大电路的设计与分析、反馈电路等。可能会出题目让应聘者设计一个简单的放大电路并计算其性能参数。 - **数字电子技术**:涵盖数字逻辑电路(与门、或门、非门等基本逻辑门电路)、组合逻辑电路和时序逻辑电路的设计与分析、可编程逻辑器件(FPGA、CPLD)的基础知识等。例如,设计一个计数器电路。 ```python # 简单示例:实现一个4位二进制计数器 class Counter: def __init__(self): self.count = 0 def increment(self): self.count = (self.count + 1) % 16 return bin(self.count)[2:].zfill(4) counter = Counter() print(counter.increment()) ``` - **单片机原理与应用**:了解单片机的体系结构、指令系统、中断系统、定时器/计数器等,能够进行单片机程序的设计与开发。可能会要求用汇编语言或C语言编写一个控制LED闪烁的程序。 ```c // 简单示例:51单片机控制LED闪烁 #include <reg51.h> sbit LED = P1^0; void delay(unsigned int time) { unsigned int i, j; for(i = 0; i < time; i++) for(j = 0; j < 1275; j++); } void main() { while(1) { LED = 0; delay(500); LED = 1; delay(500); } } ``` - **信号与系统**:包括信号的分类、时域和频域分析、系统的响应分析等。可能会有题目要求对一个给定信号进行频谱分析。 ### 题型分析 - **选择题**:主要考查应聘者对基础知识的掌握程度,题目可能涉及概念的理解、公式的应用等。 - **填空题**:通常是对一些关键知识点的填空,检验应聘者对重要概念和公式的记忆。 - **简答题**:要求应聘者对某个知识点或问题进行较为详细的阐述,考查其对知识的理解和表达能力。例如,简述某一种电路的工作原理。 - **计算题**:需要运用所学的知识进行计算,如计算电路的参数、信号的特征值等。 - **设计题**:根据给定的要求设计硬件电路或编写程序,考查应聘者的综合应用能力和创新思维。 ### 难度层次 一般会有基础题、中等难度题和难题。基础题主要是对基础知识的直接考查,中等难度题需要应聘者对知识有一定的理解和运用能力,难题则可能需要综合多个知识点进行分析和解决。 ### 应对策略 - 对于基础知识,要进行系统的复习,确保对概念和公式有清晰的理解和记忆。 - 多做练习题和真题,熟悉各种题型和解题思路。 - 注重实践能力的培养,通过实际项目或实验加深对知识的理解和应用。 - 在考试时,合理安排时间,先易后难,确保会做的题目都能得分。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值