深度学习基础回顾:神经网络基础、卷积层、全连接层、激活函数、量化概念
各位同学,欢迎来到《FINN编译流程从零到部署实战》的第二讲。
说实话,很多做FPGA加速的朋友,一上来就盯着Vivado、HLS、RTL代码猛啃。但我个人的经验是——不懂深度学习基础,做AI加速就像闭着眼睛开车。你调了半天流水线,结果发现模型结构本身就不适合硬件,那真是白费功夫。
所以这一章,咱们把深度学习里最核心的几个概念捋一遍。别担心,我不讲那些花里胡哨的数学推导,咱们就聊点实在的。
2.1 神经网络基础:从感知机到多层网络
神经网络这东西,说白了就是模仿人脑的神经元结构。一个神经元接收多个输入,加权求和后,再经过一个激活函数,输出结果。
我刚开始学的时候,总觉得这东西很玄乎。后来做项目多了才发现,它本质上就是一个复杂的函数逼近器。你给它一堆数据,它自己学出一套映射关系。
核心公式(单个神经元):
y = f( w1*x1 + w2*x2 + ... + wn*xn + b )
其中 w 是权重,b 是偏置,f 是激活函数。
多层神经网络,就是把这样的神经元一层层堆起来。每一层的输出,作为下一层的输入。层数越多,模型能表达的特征就越复杂。
嗯,这里要注意:层数不是越多越好。我在项目中遇到过,有人为了追求精度,堆了上百层网络,结果在FPGA上根本跑不动。硬件资源是有限的,你得学会做减法。
2.2 卷积层:图像特征提取的利器
卷积层是CNN(卷积神经网络)的核心。它用一个小窗口(卷积核)在输入图像上滑动,每次做一次点积运算。
你想想看,为什么卷积层这么重要?因为它能捕捉局部特征。比如一张猫的图片,卷积核可以检测出边缘、纹理、眼睛、耳朵这些局部模式。
我个人习惯:在设计FPGA加速器时,会把卷积层拆成两个阶段——数据加载和计算。数据加载用DMA,计算用PE阵列。这样流水线效率最高。
卷积层有几个关键参数,我列个表,大家记一下:
| 参数 | 含义 | 对硬件的影响 |
|---|---|---|
| 输入通道数 (C_in) | 输入特征图的深度 | 决定输入缓冲区的宽度 |
| 输出通道数 (C_out) | 卷积核的数量 | 决定PE阵列的规模 |
| 卷积核大小 (K) | 窗口的尺寸,如3x3 | 影响计算量和缓存需求 |
| 步长 (Stride) | 窗口每次移动的像素数 | 影响输出特征图尺寸 |
| 填充 (Padding) | 输入边缘补零的圈数 | 影响数据对齐方式 |
我曾经踩过一个坑:步长大于1时,数据读取的地址不连续。如果直接用突发传输,效率会很低。后来我改用行缓冲(Line Buffer)的方式,才把性能提上来。这个经验后面讲FINN编译时会详细说。
2.3 全连接层:特征整合与分类
全连接层,也叫密集层(Dense Layer)。它的每个神经元都和上一层的所有神经元相连。
说白了,卷积层负责提取特征,全连接层负责把这些特征整合起来做决策。比如前面卷积层检测到了「尖耳朵」、「胡须」、「圆眼睛」,全连接层就判断:嗯,这是一只猫。
注意:全连接层的参数量非常大!一个输入1024、输出512的全连接层,就有 1024*512 + 512 ≈ 52万个参数。在FPGA上,这通常意味着巨大的存储开销。
我建议:能用卷积层替代的,就别用全连接层。比如用1x1卷积来做通道间的融合,效果类似,但参数量小得多。
全连接层的计算公式很简单:
y = W * x + b
其中 W 是权重矩阵,x 是输入向量,b 是偏置向量。
在硬件实现上,全连接层其实就是矩阵向量乘法。这个操作在FPGA上可以用脉动阵列(Systolic Array)来加速,效率很高。
2.4 激活函数:引入非线性
如果没有激活函数,神经网络就只是个线性模型,表达能力非常有限。激活函数的作用,就是引入非线性。
常用的激活函数有几种:
- ReLU:f(x) = max(0, x)。简单粗暴,计算量几乎为零。FPGA上实现就是判断符号位,正数直接输出,负数输出0。
- Sigmoid:f(x) = 1 / (1 + e^(-x))。输出范围0~1,适合二分类。但计算复杂,硬件实现需要查表或近似计算。
- Tanh:f(x) = (e^x - e^(-x)) / (e^x + e^(-x))。输出范围-1~1,计算同样复杂。
- SiLU / Swish:f(x) = x * sigmoid(x)。最近很流行,但硬件实现成本高。
我的建议:做FPGA加速,优先选ReLU。它不需要乘法器,只需要一个比较器。如果模型必须用Sigmoid或Tanh,可以考虑用分段线性近似(PWL)来替代,精度损失很小,但硬件资源节省很多。
我记得有一次,客户要求部署一个用了Swish激活函数的模型。我一看,这玩意在FPGA上实现太费资源了。后来我跟算法团队沟通,把Swish换成了ReLU,精度只掉了0.3%,但硬件资源节省了40%。这就是软硬件协同设计的价值。
2.5 量化概念:从浮点到定点
量化,是深度学习部署到FPGA上最关键的一步。没有之一。
为什么需要量化?因为神经网络训练时用的是32位浮点数(FP32),但FPGA上做浮点运算太慢了,资源消耗也大。我们希望能用更少的比特数来表示权重和激活值。
常见的量化方式:
- INT8量化:用8位整数表示。精度损失很小,但速度提升4倍,资源节省4倍。
- INT4量化:用4位整数表示。精度损失较大,但速度更快。
- 二值量化:只用+1和-1。精度损失大,但硬件实现极其简单。
- 混合精度量化:不同层用不同精度。敏感层用INT8,不敏感层用INT4。
量化原理(以INT8为例):
float_value = int_value * scale + zero_point
其中 scale 是缩放因子,zero_point 是零点偏移。量化就是把浮点数映射到整数范围 [-128, 127] 或 [0, 255]。
FINN框架的核心能力之一,就是自动量化。它会分析你的模型,找到最优的量化参数,然后生成对应的硬件代码。
我曾经接手过一个项目,模型是FP32的,在FPGA上跑一次推理要200ms。量化到INT8后,直接降到25ms。客户都惊呆了。但要注意,量化不是万能的。有些模型对量化非常敏感,精度会掉很多。这时候就需要做量化感知训练(QAT),让模型在训练时就适应低精度。
避坑指南:量化后的模型,一定要做端到端验证。我遇到过,量化后单层精度没问题,但多层叠加后误差累积,最终结果完全不对。所以,每量化一层,就要跑一次完整推理,对比浮点结果。
小结
这一章我们回顾了深度学习的几个核心概念:
- 神经网络的基础结构
- 卷积层如何提取特征
- 全连接层如何做决策
- 激活函数引入非线性
- 量化如何让模型适应硬件
这些知识,是后面学习FINN编译流程的基础。下一章,我们会正式进入FINN的世界,看看它到底是怎么把神经网络模型变成FPGA上可运行的硬件的。
嗯,今天就到这里。有什么问题,咱们课后交流。