AI-ANNE: 将神经网络迁移到微控制器的深度探索——论文阅读

举报
DuHz 发表于 2025/09/24 18:17:27 2025/09/24
【摘要】 AI-ANNE: 将神经网络迁移到微控制器的深度探索Klinkhammer D. AI-ANNE:(A)(N) eural (N) et for (E) xploration: Transferring Deep Learning Models onto Microcontrollers and Embedded Systems[J]. arXiv preprint arXiv:2501....

AI-ANNE: 将神经网络迁移到微控制器的深度探索

Klinkhammer D. AI-ANNE:(A)(N) eural (N) et for (E) xploration: Transferring Deep Learning Models onto Microcontrollers and Embedded Systems[J]. arXiv preprint arXiv:2501.03256, 2025.

引言:嵌入式系统中的人工智能革命

机器学习和深度学习正在推动各个领域的创新发展,从计算机视觉到自然语言处理,从医疗诊断到工业自动化。近年来,这种创新浪潮正逐渐扩展到嵌入式系统领域,将智能计算能力直接带到数据源头。这种被称为TinyML的趋势,特别在微控制器和物联网(IoT)设备中展现出巨大潜力。

TinyML相比传统的基于云的人工智能解决方案,具有诸多独特优势。首先,数据隐私得到更好保护,因为敏感数据无需传输到云端即可在本地处理。其次,处理延迟大幅降低,从云端往返的网络延迟被消除,实现真正的实时响应。第三,能源效率显著提升,避免了数据传输的能耗开销。最后,系统对网络连接的依赖性降低,即使在网络不稳定或完全离线的环境中也能正常工作。

本研究提出的AI-ANNE(A Neural Net for Exploration)框架,旨在解决将预训练神经网络模型迁移到资源受限微控制器的挑战。通过在MicroPython中重新实现神经网络的核心组件,包括神经元、层、密度和激活函数,使得在TensorFlow和Keras等高性能框架上训练的模型能够在Raspberry Pi Pico等微控制器上运行,同时保持相同的推理能力。

硬件平台与开发环境

Raspberry Pi Pico系列微控制器

Raspberry Pi Pico采用RP2040微控制器,配备双核ARM Cortex-M0+处理器,运行频率133 MHz,具有264 KB片上SRAM和2 MB板载闪存。这款微控制器提供了丰富的连接选项:USB接口用于供电和数据传输,最多两个I2C、SPI和UART接口用于通信,16个PWM通道用于精确控制外部设备。板载还包括三个12位ADC通道用于模拟输入,支持实时时钟(RTC)、定时器和通过嵌套向量中断控制器(NVIC)进行中断处理等外设。

2024年推出的升级版Raspberry Pi Pico 2搭载RP2350微控制器,配备双核ARM Cortex-M33处理器,运行频率提升至150 MHz,片上SRAM增加到520 KB,板载闪存扩展到4 MB。性能的提升使Pico 2能够处理更大的数据集和更复杂的神经网络。对于实际应用,建议使用Raspberry Pi Pico 2;而对于教育目的,原版Raspberry Pi Pico已经足够。

MicroPython编程语言

MicroPython是Python编程语言的精简高效实现,专门设计用于在资源受限的微控制器和嵌入式系统上运行。与完整的Python环境不同,MicroPython经过优化,能够在小型设备典型的内存和处理限制内运行,提供精简的解释器和Python标准库的子集。

MicroPython保留了Python的大部分高级语法和易用性,使熟悉Python的开发者能够快速上手。在神经网络应用的背景下,MicroPython特别适合边缘计算场景,其中深度学习模型需要直接部署到基于微控制器的系统上进行实时、本地化推理。虽然MicroPython不原生支持完整Python中的大量数值库(如TensorFlow和Keras),但通过AI-ANNE框架,可以从零开始在MicroPython中重现神经网络的基本架构。

神经网络架构的数学基础

神经元:计算的基本单元

神经网络中的神经元是一个计算单元,其数学模型可以描述为接收多个输入信号,对每个输入应用特定权重,将加权输入求和,加上偏置项,最后通过激活函数产生输出。这个过程的数学表达式为:

y=f(i=1nwixi+b)y = f\left(\sum_{i=1}^{n} w_i x_i + b\right)

其中,yy是神经元的输出,ff是激活函数,xix_i是第ii个输入,wiw_i是对应的权重,bb是偏置项,nn是输入的数量。

在MicroPython实现中,这个计算过程分解为几个步骤。首先初始化一个零向量来存储累加结果,然后遍历所有输入,计算每个输入与其权重的乘积并累加。最后,加上偏置项并应用激活函数。这种实现方式虽然在大规模网络中可能不如矩阵运算高效,但在微控制器的资源限制下是可行的。

层的组织结构

神经网络通过层的方式组织神经元,形成信息处理的层次结构。每一层包含多个神经元,这些神经元并行处理来自前一层的输入。网络的深度(层数)和每层的宽度(神经元数)共同决定了网络的表达能力。

输入层是网络的第一层,直接接收原始数据。在AI-ANNE的实现中,输入层的每个神经元对应输入数据的一个特征。例如,在处理传感器数据时,每个传感器读数对应输入层的一个神经元。

隐藏层位于输入层和输出层之间,负责提取和学习数据的抽象特征。隐藏层的数量和每层神经元的数量是网络架构设计的关键参数。深度网络(多个隐藏层)能够学习更复杂的特征层次,但也需要更多的计算资源。

输出层产生最终的预测结果。对于二分类问题,输出层通常只有一个神经元,输出一个介于0和1之间的概率值。对于多分类问题,输出层的神经元数量等于类别数,每个神经元输出对应类别的概率。

全连接层的密度概念

在全连接(密集)层中,当前层的每个神经元都与前一层的所有神经元相连接。这种连接模式的数学表示可以用矩阵乘法来高效实现:

y=f(Wx+b)\mathbf{y} = f(\mathbf{W} \mathbf{x} + \mathbf{b})

其中,x\mathbf{x}是输入向量,W\mathbf{W}是权重矩阵,b\mathbf{b}是偏置向量,ff是逐元素应用的激活函数,y\mathbf{y}是输出向量。

权重矩阵W\mathbf{W}的维度为m×nm \times n,其中nn是输入层的神经元数量,mm是当前层的神经元数量。这意味着一个密集层需要存储m×nm \times n个权重参数加上mm个偏置参数。

激活函数的深入分析

激活函数是神经网络中引入非线性的关键组件,使网络能够学习和表示复杂的非线性关系。不同的激活函数具有不同的数学特性和应用场景。

Sigmoid函数

Sigmoid函数将任意实数映射到(0,1)(0, 1)区间:

σ(x)=11+ex\sigma(x) = \frac{1}{1 + e^{-x}}

Sigmoid函数的导数具有优美的形式:

σ(x)=σ(x)(1σ(x))\sigma'(x) = \sigma(x)(1 - \sigma(x))

这个特性在反向传播算法中非常有用。然而,Sigmoid函数存在梯度消失问题:当输入值很大或很小时,梯度接近于零,导致深层网络训练困难。

ReLU函数族

标准ReLU(Rectified Linear Unit)

ReLU(x)=max(0,x)={xif x>00if x0\text{ReLU}(x) = \max(0, x) = \begin{cases} x & \text{if } x > 0 \\ 0 & \text{if } x \leq 0 \end{cases}

ReLU的导数:

ReLU(x)={1if x>00if x0\text{ReLU}'(x) = \begin{cases} 1 & \text{if } x > 0 \\ 0 & \text{if } x \leq 0 \end{cases}

Leaky ReLU解决了ReLU的"死亡神经元"问题:

LeakyReLU(x)={xif x>0αxif x0\text{LeakyReLU}(x) = \begin{cases} x & \text{if } x > 0 \\ \alpha x & \text{if } x \leq 0 \end{cases}

其中α\alpha是一个小的正数(通常为0.01或0.1)。Leaky ReLU的导数:

LeakyReLU(x)={1if x>0αif x0\text{LeakyReLU}'(x) = \begin{cases} 1 & \text{if } x > 0 \\ \alpha & \text{if } x \leq 0 \end{cases}

Tanh函数

双曲正切函数输出范围为(1,1)(-1, 1)

tanh(x)=exexex+ex=e2x1e2x+1\tanh(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}} = \frac{e^{2x} - 1}{e^{2x} + 1}

Tanh函数的导数:

tanh(x)=1tanh2(x)\tanh'(x) = 1 - \tanh^2(x)

Softmax函数

Softmax函数用于多分类问题的输出层,将实数向量转换为概率分布:

Softmax(xi)=exij=1Kexj\text{Softmax}(x_i) = \frac{e^{x_i}}{\sum_{j=1}^{K} e^{x_j}}

为了数值稳定性,实际实现中通常使用:

Softmax(xi)=eximax(x)j=1Kexjmax(x)\text{Softmax}(x_i) = \frac{e^{x_i - \max(\mathbf{x})}}{\sum_{j=1}^{K} e^{x_j - \max(\mathbf{x})}}

IRIS数据集上的实验验证

数据集描述与问题定义

IRIS数据集包含150个鸢尾花样本,每个样本具有四个连续型特征:萼片长度(sepal length)、萼片宽度(sepal width)、花瓣长度(petal length)和花瓣宽度(petal width),所有测量单位为厘米。数据集包含三个类别,每类50个样本:Iris-setosa、Iris-versicolor和Iris-virginica。

在本研究中,我们专注于区分Versicolor和Virginica两个类别的二分类问题。这两个类别在特征空间中有部分重叠,使得分类任务具有一定挑战性,适合用于验证神经网络的性能。

实验一:8神经元网络架构

第一个实验网络包含8个神经元,分布在4层中:

  • 输入层:2个神经元
  • 第一隐藏层:3个神经元
  • 第二隐藏层:2个神经元
  • 输出层:1个神经元

网络的前向传播过程可以表示为:

h1=ReLU(W1x+b1)\mathbf{h}_1 = \text{ReLU}(\mathbf{W}_1 \mathbf{x} + \mathbf{b}_1)

h2=tanh(W2h1+b2)\mathbf{h}_2 = \tanh(\mathbf{W}_2 \mathbf{h}_1 + \mathbf{b}_2)

h3=Softmax(W3h2+b3)\mathbf{h}_3 = \text{Softmax}(\mathbf{W}_3 \mathbf{h}_2 + \mathbf{b}_3)

y=σ(W4h3+b4)y = \sigma(\mathbf{W}_4 \mathbf{h}_3 + b_4)

其中,W1R2×4\mathbf{W}_1 \in \mathbb{R}^{2 \times 4}W2R3×2\mathbf{W}_2 \in \mathbb{R}^{3 \times 2}W3R2×3\mathbf{W}_3 \in \mathbb{R}^{2 \times 3}W4R1×2\mathbf{W}_4 \in \mathbb{R}^{1 \times 2}

这个网络达到了90%的准确率,混淆矩阵显示模型在某些边界案例上存在分类困难。

实验二:6神经元网络架构

第二个实验采用更简单的网络结构,包含6个神经元,分布在3层中:

  • 输入层:3个神经元
  • 隐藏层:2个神经元
  • 输出层:1个神经元

前向传播过程:

h1=ReLU(W1x+b1)\mathbf{h}_1 = \text{ReLU}(\mathbf{W}_1 \mathbf{x} + \mathbf{b}_1)

h2=σ(W2h1+b2)\mathbf{h}_2 = \sigma(\mathbf{W}_2 \mathbf{h}_1 + \mathbf{b}_2)

y=σ(W3h2+b3)y = \sigma(\mathbf{W}_3 \mathbf{h}_2 + b_3)

令人意外的是,这个更简单的网络达到了95%的准确率。混淆矩阵显示:

  • 真阳性(TP):9个样本
  • 真阴性(TN):10个样本
  • 假阳性(FP):0个样本
  • 假阴性(FN):1个样本

这表明对于这个特定问题,简单的网络架构可能更适合,避免了过拟合。

性能评估指标

混淆矩阵分析

混淆矩阵提供了分类性能的详细视图。对于二分类问题,混淆矩阵是一个2×22 \times 2的表格:

[TPFNFPTN]\begin{bmatrix} \text{TP} & \text{FN} \\ \text{FP} & \text{TN} \end{bmatrix}

基于混淆矩阵,可以计算多个性能指标:

准确率(Accuracy)

Accuracy=TP+TNTP+TN+FP+FN\text{Accuracy} = \frac{\text{TP} + \text{TN}}{\text{TP} + \text{TN} + \text{FP} + \text{FN}}

精确率(Precision)

Precision=TPTP+FP\text{Precision} = \frac{\text{TP}}{\text{TP} + \text{FP}}

召回率(Recall)

Recall=TPTP+FN\text{Recall} = \frac{\text{TP}}{\text{TP} + \text{FN}}

F1分数

F1=2PrecisionRecallPrecision+Recall\text{F1} = 2 \cdot \frac{\text{Precision} \cdot \text{Recall}}{\text{Precision} + \text{Recall}}

MicroPython实现细节

矩阵运算的底层实现

由于MicroPython没有NumPy等科学计算库,需要从零实现基本的矩阵运算。矩阵转置函数的实现展示了这种方法:

def transpose(M):
    if not isinstance(M[0], list):
        M = [M]
    rows = len(M)
    cols = len(M[0])
    MT = zeros(cols, rows)
    for i in range(rows):
        for j in range(cols):
            MT[j][i] = M[i][j]
    return MT

这种逐元素的操作虽然不如优化的BLAS库高效,但在微控制器的小规模网络中是可行的。

神经元的完整实现

单个神经元的计算涉及多个步骤:加权求和、添加偏置和应用激活函数。MicroPython实现必须处理不同的激活函数类型:

def neuron(x, w, b, activation):
    tmp = zero_dim(x[0])
    for i in range(len(x)):
        tmp = add_dim(tmp, [(float(w[i]) * float(x[i][j]))
                            for j in range(len(x[0]))])
    
    if activation == "sigmoid":
        yp = sigmoid([tmp[i] + b for i in range(len(tmp))])
    elif activation == "relu":
        yp = relu([tmp[i] + b for i in range(len(tmp))])
    # ... 其他激活函数
    
    return yp

与现有方法的比较

AIfES框架

Fraunhofer开发的AIfES(Artificial Intelligence for Embedded Systems)是一个灵活的软件框架,专门设计用于在微控制器等小型低功耗设备上运行深度学习模型。AIfES可以直接在设备上构建、训练和运行模型,无需强大的外部系统。用户可以通过选择不同的模型组件(如层类型或数据处理方式)来定制框架。

AI-ANNE的独特优势

相比AIfES,AI-ANNE具有以下特点:

  1. 教育透明性:完全开放的MicroPython源代码,便于理解神经网络的内部工作原理
  2. 灵活性:可以轻松修改激活函数、调整网络架构,甚至在微控制器上进行微调
  3. 轻量级:最小化的依赖和内存占用,适合资源极度受限的环境
  4. 可扩展性:用户可以根据需要添加新的激活函数或网络组件

实际应用场景

状态监测与预测性维护

在工业环境中,AI-ANNE可以部署在传感器节点上,实时监测设备状态。通过分析振动、温度、压力等传感器数据,神经网络可以检测异常模式,预测潜在故障,实现预测性维护。

医疗诊断辅助

在医疗设备中,特别是便携式诊断设备,AI-ANNE可以实现实时的信号处理和模式识别。例如,在心电图(ECG)监测中,神经网络可以识别异常心律模式。

智能农业

在精准农业应用中,部署在田间的微控制器可以分析土壤湿度、温度、光照等数据,通过神经网络模型预测作物生长状态和灌溉需求。

未来发展方向

AI-ANNE框架的未来发展可以从多个方向展开:

  1. 模型压缩技术:研究量化、剪枝等技术,进一步减少模型大小和计算需求
  2. 在线学习能力:开发增量学习算法,使模型能够在部署后继续适应新数据
  3. 硬件加速:利用微控制器的特殊硬件功能,如DSP指令,加速神经网络计算
  4. 自动化工具:开发自动将TensorFlow/Keras模型转换为AI-ANNE格式的工具

结论

本研究成功展示了如何将神经网络迁移到资源受限的微控制器上。通过AI-ANNE框架,我们证明了即使在Raspberry Pi Pico这样的低成本微控制器上,也能运行有效的神经网络模型。实验结果表明,经过精心设计的小型网络可以达到与大型网络相当的性能,同时显著降低资源消耗。


附录:数学推导

附录A:反向传播算法

虽然AI-ANNE主要用于推理而非训练,理解反向传播算法对于理解预训练权重的来源至关重要。

损失函数

对于二分类问题,使用二元交叉熵损失函数:

L=1Ni=1N[yilog(y^i)+(1yi)log(1y^i)]L = -\frac{1}{N}\sum_{i=1}^{N}[y_i \log(\hat{y}_i) + (1-y_i)\log(1-\hat{y}_i)]

其中NN是样本数量,yiy_i是真实标签,y^i\hat{y}_i是预测概率。

梯度计算

对于输出层权重wjk(L)w_{jk}^{(L)}的梯度:

Lwjk(L)=Laj(L)aj(L)zj(L)zj(L)wjk(L)\frac{\partial L}{\partial w_{jk}^{(L)}} = \frac{\partial L}{\partial a_j^{(L)}} \cdot \frac{\partial a_j^{(L)}}{\partial z_j^{(L)}} \cdot \frac{\partial z_j^{(L)}}{\partial w_{jk}^{(L)}}

定义误差项δj(L)=Lzj(L)\delta_j^{(L)} = \frac{\partial L}{\partial z_j^{(L)}},则:

δj(L)=Laj(L)f(zj(L))\delta_j^{(L)} = \frac{\partial L}{\partial a_j^{(L)}} \cdot f'(z_j^{(L)})

对于隐藏层的误差项,使用链式法则:

δj(l)=(kwkj(l+1)δk(l+1))f(zj(l))\delta_j^{(l)} = \left(\sum_{k} w_{kj}^{(l+1)} \delta_k^{(l+1)}\right) \cdot f'(z_j^{(l)})

权重更新规则

使用梯度下降法更新权重:

wjk(l)wjk(l)ηLwjk(l)w_{jk}^{(l)} \leftarrow w_{jk}^{(l)} - \eta \frac{\partial L}{\partial w_{jk}^{(l)}}

其中η\eta是学习率。

附录B:激活函数的数值稳定性分析

Sigmoid函数的数值问题

x|x|很大时,exe^{-x}可能导致数值溢出或下溢。改进的实现:

σ(x)={11+exif x0ex1+exif x<0\sigma(x) = \begin{cases} \frac{1}{1 + e^{-x}} & \text{if } x \geq 0 \\ \frac{e^x}{1 + e^x} & \text{if } x < 0 \end{cases}

Softmax的数值稳定实现

标准Softmax在输入值很大时会溢出。稳定版本:

Softmax(xi)=exiCjexjC\text{Softmax}(x_i) = \frac{e^{x_i - C}}{\sum_{j} e^{x_j - C}}

其中C=max(x)C = \max(\mathbf{x})。证明这与原始定义等价:

exiCjexjC=exieCjexjeC=exijexj\frac{e^{x_i - C}}{\sum_{j} e^{x_j - C}} = \frac{e^{x_i} \cdot e^{-C}}{\sum_{j} e^{x_j} \cdot e^{-C}} = \frac{e^{x_i}}{\sum_{j} e^{x_j}}

附录C:矩阵运算的计算复杂度分析

前向传播的复杂度

对于一个全连接层,输入维度为nn,输出维度为mm

  • 矩阵乘法:O(mn)O(mn)次乘法和O(mn)O(mn)次加法
  • 偏置加法:O(m)O(m)次加法
  • 激活函数:O(m)O(m)次函数调用

总复杂度:O(mn)O(mn)

内存需求分析

对于LL层网络,第ll层有nln_l个神经元:

  • 权重存储:l=1L1nl×nl+1\sum_{l=1}^{L-1} n_l \times n_{l+1}个浮点数
  • 偏置存储:l=1L1nl+1\sum_{l=1}^{L-1} n_{l+1}个浮点数
  • 激活值缓存:maxlnl\max_l n_l个浮点数(可以重用)

对于8神经元网络:

  • 权重:4×2+2×3+3×2+2×1=224 \times 2 + 2 \times 3 + 3 \times 2 + 2 \times 1 = 22个参数
  • 偏置:2+3+2+1=82 + 3 + 2 + 1 = 8个参数
  • 总计:30个参数

附录D:梯度消失和梯度爆炸问题

Sigmoid函数的梯度消失

Sigmoid函数的导数最大值为0.25(当x=0x=0时):

σ(0)=σ(0)(1σ(0))=0.5×0.5=0.25\sigma'(0) = \sigma(0)(1-\sigma(0)) = 0.5 \times 0.5 = 0.25

在深层网络中,梯度通过多层反向传播时会连续相乘:

l=1Lσ(z(l))0.25L\prod_{l=1}^{L} \sigma'(z^{(l)}) \leq 0.25^L

LL很大时,梯度趋近于零。

ReLU的优势

ReLU的导数在正区间恒为1:

ReLU(x)={1if x>00if x0\text{ReLU}'(x) = \begin{cases} 1 & \text{if } x > 0 \\ 0 & \text{if } x \leq 0 \end{cases}

这避免了梯度消失问题,但可能导致"死亡ReLU"现象。

附录E:信息论视角下的激活函数

熵与信息增益

Sigmoid函数输出的熵:

H(p)=plog(p)(1p)log(1p)H(p) = -p\log(p) - (1-p)\log(1-p)

其中p=σ(x)p = \sigma(x)。熵最大值出现在p=0.5p=0.5(即x=0x=0)时。

Softmax与最大熵原理

Softmax函数是在约束条件ipi=1\sum_i p_i = 1pi0p_i \geq 0下,最大化熵H=ipilogpiH = -\sum_i p_i \log p_i的解。

使用拉格朗日乘数法:

L=ipilogpi+λ(ipi1)\mathcal{L} = -\sum_i p_i \log p_i + \lambda(\sum_i p_i - 1)

求导并令其为零:

Lpi=logpi1+λ=0\frac{\partial \mathcal{L}}{\partial p_i} = -\log p_i - 1 + \lambda = 0

解得pi=eλ1p_i = e^{\lambda - 1},归一化后即得Softmax形式。

附录F:微控制器上的定点数实现

虽然本文使用浮点数,但在某些微控制器上,定点数运算可能更高效。

定点数表示

使用Q格式,例如Q15.16表示16位整数部分和16位小数部分:

xfixed=xfloat×216x_{fixed} = x_{float} \times 2^{16}

定点数乘法

两个Q15.16数相乘:

z=xfixed×yfixed216z = \frac{x_{fixed} \times y_{fixed}}{2^{16}}

定点数激活函数

Sigmoid函数的查找表实现:

  1. 预计算[8,8][-8, 8]区间内的Sigmoid值
  2. 量化到256个值
  3. 使用线性插值提高精度

这种方法可以将Sigmoid计算时间从几百个时钟周期减少到几十个。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。