3、深度学习模型基础回顾:神经网络原理、卷积与循环网络、激活函数与损失函数
好,咱们进入第三讲。说实话,很多做嵌入式部署的同学,一上来就急着搞量化、剪枝、转ONNX,结果模型跑起来效果稀烂,回头一看,连网络基本结构都没搞明白。我个人习惯是,先把地基打牢,再谈上层建筑。这一章,咱们就把深度学习那点老底儿翻出来晒晒。
3.1 神经网络的核心原理:从感知机到多层网络
神经网络说白了,就是一个超级大的复合函数。你给它一个输入x,它经过一堆加权求和、非线性变换,最后输出一个y。这个映射关系,就是网络学到的知识。
最基本的单元叫感知机。它干的事很简单:y = sign(w·x + b)。但单层感知机有个致命缺陷——它连异或(XOR)都学不了。我在项目中遇到过一位同事,非要用单层网络做语音唤醒词分类,结果准确率死活上不去。后来换成多层网络,问题迎刃而解。
多层网络的核心在于「层」的堆叠。每一层提取不同级别的特征。比如处理音频时,第一层可能学的是音高、音强,第二层学的是音素,第三层学的是单词。这就是深度学习的魅力——自动特征提取。
关键点:没有隐藏层的网络,表达能力有限。你想想看,如果只用一条直线去分类,能分得开复杂数据吗?
3.2 卷积神经网络(CNN):专治局部特征
CNN为什么适合做音频和图像?因为它抓住了两个核心:局部连接和权值共享。
全连接网络处理一张32x32的图片,光第一层就要上千个参数。而卷积核只有3x3或5x5,参数少得多。更重要的是,卷积核在整张图上滑动,同一个核检测同一种特征——比如边缘、纹理。这就是权值共享。
我在做智能音箱的麦克风阵列信号处理时,用1D-CNN处理时序信号。效果比传统方法好不少,但要注意卷积步长和感受野的匹配。步长太大,细节丢了;步长太小,计算量爆炸。
实战技巧:在嵌入式设备上,我建议优先使用深度可分离卷积(Depthwise Separable Convolution)。参数量是普通卷积的1/8到1/10,精度损失通常不到1%。
3.3 循环神经网络(RNN)与LSTM:处理序列数据的利器
RNN的设计思想很直观:当前时刻的输出,不仅取决于当前输入,还取决于上一时刻的隐藏状态。说白了,它是有记忆的。
但经典RNN有个大问题——梯度消失或爆炸。序列一长,前面的信息就传不过来了。我曾经调试过一个语音识别模型,训练到第50个epoch时loss突然变成NaN,查了半天,原来是梯度爆炸了。
解决方案就是LSTM(长短期记忆网络)。它引入了三个门:遗忘门、输入门、输出门。还有一个细胞状态,像传送带一样把信息一路传下去。
# 一个简单的LSTM单元(伪代码)
f_t = sigmoid(W_f · [h_{t-1}, x_t] + b_f) # 遗忘门
i_t = sigmoid(W_i · [h_{t-1}, x_t] + b_i) # 输入门
o_t = sigmoid(W_o · [h_{t-1}, x_t] + b_o) # 输出门
c_t = f_t * c_{t-1} + i_t * tanh(W_c · [h_{t-1}, x_t] + b_c) # 细胞状态更新
h_t = o_t * tanh(c_t) # 隐藏状态输出
嗯,这里要注意:LSTM虽然解决了长程依赖问题,但参数量是RNN的4倍。在资源受限的嵌入式设备上,可以考虑GRU(门控循环单元),它只有两个门,效果差不多,但参数更少。
3.4 激活函数:给网络注入非线性
没有激活函数,再多层网络也只是线性变换的堆叠,那跟单层没区别。激活函数就是那个「非线性开关」。
| 激活函数 | 公式 | 优点 | 缺点 |
|---|---|---|---|
| Sigmoid | 1/(1+e^{-x}) | 输出范围(0,1),适合概率输出 | 梯度饱和,容易消失 |
| Tanh | (e^x - e^{-x})/(e^x + e^{-x}) | 零中心,梯度比Sigmoid强 | 仍有饱和区 |
| ReLU | max(0, x) | 计算简单,缓解梯度消失 | 神经元死亡(负半轴梯度为0) |
| Leaky ReLU | max(0.01x, x) | 解决神经元死亡问题 | 超参数需要调 |
我个人在边缘部署时,首选ReLU。为什么?因为它计算量最小,没有指数运算。在Cortex-M4这类MCU上,一个ReLU就是一个比较指令,而Sigmoid要查表或近似计算,慢得多。
避坑指南:我曾经在部署一个唤醒词模型时,用了Sigmoid作为隐藏层激活函数。结果量化后精度掉了8%。换成ReLU后,精度只掉了2%。原因就是Sigmoid的饱和区对量化误差太敏感。
3.5 损失函数:告诉模型错在哪
损失函数就是模型学习的「指挥棒」。你选什么损失函数,模型就朝什么方向优化。
分类任务最常用的是交叉熵损失(Cross-Entropy Loss)。它衡量的是预测分布和真实分布的差异。公式如下:
L = -Σ y_i * log(p_i)
其中y_i是真实标签(one-hot),p_i是预测概率。为什么不用均方误差(MSE)?因为MSE对概率输出的梯度太小,收敛慢。我在做关键词识别时试过MSE,训练了100个epoch还不如交叉熵50个epoch的效果。
回归任务常用均方误差(MSE)或平均绝对误差(MAE)。MSE对大误差惩罚更重,MAE对异常值更鲁棒。比如做声源定位(回归任务),如果偶尔有离群点,用MAE更稳。
我的经验:在边缘部署场景下,损失函数的选择还要考虑量化后的表现。交叉熵在int8量化后通常表现稳定,而一些自定义的损失函数(如Focal Loss)量化后可能出问题。建议先在浮点模型上验证,再决定是否量化。
3.6 小结:从理论到部署的桥梁
这一章我们回顾了神经网络的基本构件。你可能会问:这些跟边缘部署有什么关系?关系大了去了。
- 网络结构决定了参数量和计算量——直接影响能否塞进嵌入式设备。
- 激活函数的选择影响量化精度——ReLU比Sigmoid更友好。
- 损失函数影响模型收敛和最终精度——选错了,部署后效果就是不行。
下一章,咱们就要开始动手了。我会带你从零搭建一个适合边缘部署的轻量级模型。记住,好的部署工程师,首先得是个好的模型设计师。地基打牢了,楼才盖得高。