一、神经元与感知机模型

神经网络的基础,说白了就是模仿人脑的工作方式。人脑里有大约860亿个神经元,每个神经元接收信号、处理、再传给下一个。我们做NPU设计,本质上就是在硅片上复现这个过程。

先看最简单的神经元模型——感知机。它由数学家Rosenblatt在1957年提出,结构其实很简单:

  • 输入:多个信号x₁, x₂, ..., xₙ
  • 权重:每个输入对应一个权重w₁, w₂, ..., wₙ
  • 偏置:一个常数b,相当于神经元的"阈值"
  • 激活函数:决定是否"点火"输出

数学表达式就是:y = f(w₁x₁ + w₂x₂ + ... + wₙxₙ + b)

我在做第一版NPU原型时,发现很多新人搞不清权重和偏置的物理意义。其实你可以这么理解:权重决定了输入的重要性,偏置决定了神经元激活的难易程度。权重越大,这个输入对结果的影响就越大;偏置越大,神经元越不容易被激活。

核心要点:感知机只能解决线性可分问题。比如AND、OR这类逻辑门可以,但XOR就不行。这就是为什么后来需要多层神经网络。

二、激活函数

激活函数是神经网络里最关键的组件之一。没有它,再多层网络也只是线性变换的堆叠,表达能力有限。我挑三个最常用的来讲。

2.1 Sigmoid函数

Sigmoid把输入映射到(0,1)区间,公式是:σ(x) = 1 / (1 + e⁻ˣ)

它的优点是平滑、可导,输出可以解释为概率。但有个致命问题——梯度消失。当|x|很大时,梯度趋近于0,网络几乎学不动了。

避坑指南:我曾经在做一个深度推荐模型时,用了Sigmoid做隐藏层激活,结果训练到第3层梯度就几乎为零了。后来换成ReLU,训练速度快了10倍。所以Sigmoid现在基本只用在输出层做二分类。

2.2 ReLU函数

ReLU(Rectified Linear Unit)是目前最常用的激活函数:f(x) = max(0, x)

它的好处很明显:

  • 计算简单,只需比较大小
  • 不会饱和,正区间梯度恒为1
  • 稀疏激活,很多神经元输出为0

但ReLU也有个坑——神经元死亡。如果某个神经元一直输出负值,它的梯度就是0,权重再也更新不了。我见过一个项目,因为学习率设太大,导致一半神经元都"死"了。

2.3 Tanh函数

Tanh是Sigmoid的变体,输出范围是(-1,1):tanh(x) = (eˣ - e⁻ˣ) / (eˣ + e⁻ˣ)

它比Sigmoid好的一点是零中心化,输出均值接近0,有利于下一层的学习。但梯度消失问题依然存在。

激活函数 输出范围 优点 缺点 NPU实现难度
Sigmoid (0, 1) 平滑、概率解释 梯度消失 中(需要指数运算)
ReLU [0, ∞) 简单、无饱和 神经元死亡 低(只需比较器)
Tanh (-1, 1) 零中心化 梯度消失 中(需要指数运算)

个人经验:在NPU设计中,ReLU是最容易硬件实现的,只需要一个比较器。而Sigmoid和Tanh需要查表或近似计算,会占用更多面积和功耗。所以工业界的NPU几乎都优先支持ReLU。

三、前向传播与反向传播

这两个概念是神经网络训练的"左右手"。前向传播做预测,反向传播做修正。

3.1 前向传播

前向传播就是从输入到输出的计算过程。数据从输入层开始,逐层计算,直到输出层。每一层的计算就是:

z = W · x + b    # 线性变换
a = f(z)         # 激活函数

举个例子,一个3层网络(输入层2节点,隐藏层3节点,输出层1节点)的前向传播:

# 输入层到隐藏层
z₁ = W₁ · x + b₁
a₁ = ReLU(z₁)

# 隐藏层到输出层
z₂ = W₂ · a₁ + b₂
a₂ = Sigmoid(z₂)  # 二分类问题

# 输出就是 a₂

前向传播的计算量主要来自矩阵乘法。这也是NPU最擅长的——矩阵乘累加运算。我设计的NPU里,专门有一个MAC(乘累加)阵列来加速这个操作。

3.2 反向传播

反向传播是训练的核心。它的思路是:计算输出误差,然后从输出层往回传,逐层更新权重。

具体步骤:

  1. 计算输出层的误差 δ_output
  2. 用链式法则,把误差传到隐藏层
  3. 根据误差计算梯度
  4. 用梯度更新权重

数学上,对于输出层第j个神经元:

δⱼ = ∂L/∂zⱼ = (aⱼ - yⱼ) · f'(zⱼ)

对于隐藏层第j个神经元:

δⱼ = f'(zⱼ) · Σ(Wₖⱼ · δₖ)

权重更新:

W_new = W_old - η · δ · a_input

关键理解:反向传播的本质就是链式法则。你不需要记住所有公式,但一定要理解"误差从后往前传"这个思想。在NPU设计里,反向传播需要额外的存储和计算资源,因为要保存中间层的激活值。

四、损失函数与梯度下降

4.1 损失函数

损失函数衡量模型预测和真实值的差距。不同的任务用不同的损失函数:

  • 均方误差(MSE):L = ½(y_pred - y_true)²,适合回归问题
  • 交叉熵损失:L = -[y·log(p) + (1-y)·log(1-p)],适合分类问题
  • Hinge损失:L = max(0, 1 - y·y_pred),适合SVM

我个人的习惯是:回归用MSE,分类用交叉熵。交叉熵在分类问题上收敛更快,因为它的梯度更大。

4.2 梯度下降

梯度下降就是沿着损失函数的负梯度方向更新参数,让损失越来越小。公式很简单:

θ = θ - η · ∇L(θ)

其中η是学习率,∇L(θ)是梯度。

梯度下降有三种常见变体:

方法 每次更新用的数据 优点 缺点
批量梯度下降 全部数据 稳定、方向准确 慢、内存大
随机梯度下降 1个样本 快、能跳出局部最优 震荡大
小批量梯度下降 batch个样本 折中、最常用 需要调batch size

避坑指南:我曾经因为学习率设得太大,导致损失直接发散到无穷大。后来我养成了一个习惯——先用0.001的学习率试跑几个epoch,观察损失曲线。如果下降太慢就调大,如果震荡就调小。另外,学习率衰减也是个好技巧,训练到后期减小学习率,有助于收敛到更优解。

知识体系总览

下面这张图总结了本章的核心内容,我建议你把它打印出来贴在工位上:

神经网络基础 - 知识体系 神经网络基础 神经元与感知机 输入 → 加权求和 → 激活 激活函数 Sigmoid / ReLU / Tanh 前向与反向传播 预测 → 误差 → 更新权重 损失函数与梯度下降 MSE / 交叉熵 → 梯度更新 线性分类器 多层感知机 非线性变换 梯度消失问题 链式法则 梯度计算 MSE / 交叉熵 学习率调节 NPU设计核心:矩阵乘法加速 + 激活函数硬件实现

嗯,以上就是神经网络基础的全部内容。这些概念是后续学习NPU设计的基石,尤其是前向传播和反向传播的数学原理,会直接影响NPU的架构设计。我个人建议你动手实现一个简单的全连接网络,哪怕只有几层,也能帮你把今天讲的内容串起来。

学习建议:别急着看NPU硬件设计,先把软件层面的神经网络搞明白。我见过太多人一上来就研究脉动阵列、数据流,结果连反向传播的链式法则都写不对。基础不牢,地动山摇。


专注资料整理