1.TinyML-TVM是如何驯服Tiny的(上)
2.通过Pytorch实现ResNet18
3.深入解读VGGish
4.使用Cleanlab、PCA和Procrustes可视化ViT微调
5.SWA (Stochastic Weight Average)
6.如何评价斯坦福大学提出SGD动量自调节器YellowFin?
TinyML-TVM是如何驯服Tiny的(上)
低成本、人工智能驱动的消费类设备的激增,激发了研究者对“裸智能”(低功耗、通常无操作系统)设备的兴趣。传统上,dydx源码开发专家能在这些设备上运行某些模型,但为不同设备优化模型是个挑战,往往需要针对设备的手动优化。尤其是针对没有Linux支持的平台,没有可扩展的模型部署解决方案。因此,开发者通常需要创建一次性的定制软件堆栈,以管理资源和调度模型执行。
尽管机器学习软件的优化并不是裸机领域特有的难题,它与GPU和FPGA等硬件后端的开发人员共同面对。TVM展现出了适应新硬件目标的能力,但在微控制器独特配置的挑战下,它之前还未能提供足够的支持。为解决这一问题,TVM扩展了微控制器后端,即µTVM(发音为“MicroTVM”),以在裸机设备上执行张量程序,并通过TVM内置的张量程序优化器AutoTVM自动优化这些程序。上图展示了µTVM+AutoTVM基础设施的概览。
µTVM+AutoTVM的实际应用
在讨论TVM/MicroTVM及其工作原理之前,我们先看一个实际应用示例。假设我们使用STMFZG板,它配备了一个强大的ARM Cortex-M7处理器,非常适合边缘人工智能应用。通过USB-JTAG端口将板连接至桌面,使用OpenOCD打开与设备的JTAG连接,从而通过µTVM使用设备无关的TCP套接字控制M7处理器。在桌面上运行TVM代码,执行CIFAR-分类器,如完整脚本所示:
在这个设置中,性能表现可能不佳,但AutoTVM提供了一线生机。通过为设备编写调度模板并进行一轮自动调整,可以显著提升性能。具体来说,opensift源码只需替换原始构建行:
然后替换为:
这样,结果将显著提升,性能大约提升2倍,与CMSIS-NN版本5.7.0(commit ab7c9a)相比,后者是一个手工优化的ML内核库。
µTVM的性能表现与CMSIS-NN模型相比较具竞争力,但工作才刚刚开始,利用TVM的优化特性还有更多空间。通过加速密集/全连接运算(如密集/全连接操作)并利用TVM的模型特定量化和运算符融合功能,可以进一步优化性能。µTVM与TVM能够协同工作,发挥最佳性能。
µTVM的设计理念
µTVM旨在满足设备最低公分母的要求,只需提供设备的C交叉编译器工具链、读/写设备内存的方法、设备内存布局和体系结构特征的规范以及为设备准备函数执行的代码段。大多数裸机设备都支持C和JTAG,因此(1)和(2)通常是免费的。此外,(3)和(4)要求通常较小。例如,STMF系列板的(3)和(4)示例如下:
µTVM基础设施和设备runtime的构建是为了满足这些需求,正努力通过支持常见的开源runtime平台(如mBED OS)来简化编译和链接过程。
µTVM的设备会话
考虑到微控制器的网络特性,引入了微会话的概念,它稍微偏离了标准的TVM代码。µTVM中的每一项功能都依赖于与目标设备的开放会话。在第一个代码片段中,一行代码偏离了规范,即这一行:
通过这个with块内的每一行,都可以调用µTVM中的函数,上下文是device_config指定的设备。这条线背后做了很多工作,让其拆分如下:
首先,它初始化与设备的连接,使用指定的任何通信方法(通常是OpenOCD)。然后使用指定的交叉编译器交叉编译µTVM设备runtime。最后,主机为编译后的二进制文件分配空间,并使用打开的fastjason源码连接将二进制文件加载到设备上。
由于runtime现在位于设备上,自然需要一些函数来运行它。
模块加载
TVM的核心抽象之一是模块。模块为特定设备/ runtime目标存储一组相关函数。考虑到微控制器通常没有操作系统,µTVM需要额外的工作来维护这种高级抽象。跟踪创建和加载µTVM兼容模块的过程:
假设有一个微型会议打开设备,并实现二维卷积的TVM调度。如果想把它加载到微控制器上,需要将C代码发出。为了实现这一点,只需要设定目标tvm.build或relay.build,例如:
然后,通过µTVM基础设施中的核心功能运行它:create_micro_mod:
这样,交叉编译模块中的C源代码,为生成的二进制文件分配空间,然后将二进制文件的每个部分发送到设备上分配的插槽中。一旦模块二进制文件在设备内存中处于合适的位置,二进制文件中的函数指针将被修补,使模块能够在设备runtime访问帮助函数(例如,分配草稿行)。
加载内核后,可以获取卷积函数的远程句柄,如下所示:
张量加载
如果要调用运算符,首先需要一些张量作为参数:
然后,根据其数据类型(例如int8、float等)和形状,计算每个张量的字节大小,主机在设备堆上分配内存区域。接着将张量的数据加载到分配的区域中。
函数调用
运算符执行可能是系统中最复杂的部分。为了简化表示,我们首先讨论严格执行(运算符一被调用就立即执行),然后是延迟执行(只有在需要运算符的结果时才执行运算符),这是系统的实际工作方式。
严格执行
调用函数时,输入和输出张量都作为参数传递,这就是目标传递样式:
考虑到这些张量已经在设备上分配,只需要向设备发送元数据(设备地址、形状和数据类型),kdevelop 源码设备就能知道使用哪个驻留张量。下面显示了一个名为“runtime”的函数调用。在构造这个表示之前,需要将元数据序列化到设备上专门为此目的而存在的arguments部分中。
µTVM会有一个全局UTVMTask实例,从主机端写入该实例。一旦写入任务,runtime就拥有了执行函数所需的一切,可以在runtime的入口点开始执行。runtime执行一些轻量级初始化,运行运算符,然后将控制权返回给主机。
通过Pytorch实现ResNet
深入学习深度学习时,新手常常面临在掌握工具与理论应用之间的挑战。作为入门者,找到合适的项目进行实践尤为重要。ResNet作为深度学习领域的基石之一,以其独特的残差学习机制受到广泛关注。ResNet作为其中的经典模型,不仅结构简洁,而且适合初学者实践。
开发环境设定为Python环境,需具备PyTorch库。首先,明确ResNet的网络架构是关键。对于初学者,理解ResNet中“短路连接”机制的实现至关重要,这一步骤理解到位后,后续实现过程将更为顺畅。
ResNet的架构设计遵循了层层嵌套的残差块结构,通过添加shortcut路径,允许网络在多层间进行有效的信息传递。实际操作中,ResNet可以细分为6个关键部分进行实现。
实现过程分为两步:一是构建残差块,这是网络的基础单元;二是构建整个ResNet模型,将多个残差块串联起来。
至此,一个完整的ResNet网络架构搭建完成。但实践才是助学 源码检验真理的唯一标准,选择CIFAR数据集进行模型训练,是检验模型效果的常见方法。利用Jupyter Notebook,进行模型训练,操作流畅,结果令人满意。
代码实现过程已在GitHub上开源,欢迎访问查看源码。如果本文对你有所启发,不妨给代码库添加star,支持作者。
深入解读VGGish
深度学习技术近年来取得了飞速发展,这一进步与开源数据集的普及密切相关。在图像识别领域,CIFAR-、PASCAL、MSCOCO以及Imagenet等数据集的出现推动了算法的革新。其中,Imagenet数据集规模庞大,包含万张和万个类别,为图像识别研究提供了丰富资源。然而,声音识别领域的发展却因缺乏同等规模的数据集而相对滞后,这一情况在年3月被改变,Google发布了由万张个人标记的秒YouTube视频音轨组成的数据集Audioset,数据集包含多个音频事件标签。
基于Audioset数据集,Google训练出了VGGish模型,这是本文关注的重点。VGGish模型使用了Audioset的大量音频数据进行预训练,其源代码基于TensorFlow框架实现。官方文档指出,VGGish模型在多种音频任务上表现出色,优于传统手工设计的特征如mel、cqt、mfcc等。
VGGish模型的构建和特征选择遵循了传统方法,即采用mel特征和四层卷积作为特征提取器。区别在于,VGGish模型是通过Audioset大量音频数据训练获得的,并提供了预训练参数,这使得用户可以直接使用预训练的VGGish模型作为特征提取器,以获得较好的表现。然而,如果仅使用VGGish模型而未利用预训练参数,其效果可能不如直接使用更先进的模型网络如MobileNet或Shufflenet等,并且在使用[nums,]输出特征做为深层网络输入时,由于信息量有限,效果可能不理想。相反,直接在[nums,]之后进行全连接分类,可能获得更满意的结果。
VGGish模型的实现使用了TensorFlow 1.x框架,而多数研究工作更倾向于使用PyTorch框架。为解决这一问题,GitHub上提供了将TensorFlow模型转换为PyTorch模型的代码,包括定义相同网络结构、权重迁移和验证结果等步骤,有兴趣的读者可以自行下载并调试。
VGGish模型的源代码包含8个文件,其中预训练参数文件两个。作者在复现代码时使用的相关库版本非官方,但经过复现研究发现,VGGish模型在模型构建和特征选择方面并无显著创新,但在基于大规模数据集训练和提供预训练参数方面展现出独特优势。
为了方便用户,作者使用PyTorch生成了预训练模型参数,并上传至云盘,供用户下载使用。总体而言,VGGish模型通过利用大规模音频数据集进行预训练,提供了一种有效的音频特征提取方法,尤其适用于音频识别和分类任务,但其效果的发挥还需结合适当的网络架构和优化策略。
使用Cleanlab、PCA和Procrustes可视化ViT微调
在图像处理领域,与传统的CNN不同,基于Transformers架构的ViT模型因其在自然语言处理任务中的成功而被引入。微调这些模型以获得理想性能的过程往往涉及精细的操作。下面,我们将通过一步步的示例,展示如何通过Cleanlab、PCA和Procrustes技术可视化ViT模型在CIFAR-数据集上的微调过程。
首先,微调从预训练的ViT模型开始,使用CIFAR-的6万张和类标签。微调过程中,通过设置save_strategy和save_step来频繁保存检查点,确保动画有足够的数据点。然后,利用Transformers库的AutoFeatureExtractor和automodel获取不同阶段模型的嵌入,每个嵌入都是维的。
嵌入分析中,Cleanlab的离群值检测功能识别出分类错误的特征。接着,通过scikit-learn的PCA将维向量降维到2维,以便可视化。然而,PCA可能导致动画帧间出现不必要的轴翻转或旋转。为解决这个问题,我们应用了Procrustes Analysis进行几何变换,确保动画过渡平滑。
在最终的动画制作中,我们使用make_pca和get_ood函数创建图表,展示嵌入的二维分布和前8个异常值。此外,还会加载训练损失数据,以线形图的形式呈现。整个过程在Spotlight中进行最后检查,确保所有数据准确无误。
这个可视化过程不仅有助于理解微调ViT模型的步骤,还是一个有效的教学工具,能够直观地展示模型调整的过程和结果。源代码可在GitHub上查看,作者为Markus Stoll。
SWA (Stochastic Weight Average)
SWA(Stochastic Weight Averaging),一种调参技巧,其实质是通过连续更新后的权重计算平均值,而非保存历史权重。PyTorch.contrib提供了相应的源码实现,让我们通过一个简单的测试代码来了解如何使用:
代码中前两个参数的作用在于设置更新的规则,例如,s和f分别代表滑动窗口大小和步长。内部机制是(optimizer的state字典)为每个权重维护一个字典,记录swa_buff(用于计算均值的tensor)和相关计数。
举个例子,当s=3,f=3时,只有在第1、2、3步之后,权重才会被包含在均值计算中。下面进行实验,以CIFAR-为例,首先不使用SWA,记录训练过程:
加入SWA后,模型性能显著提升,如无BN更新,提升%;当加入BN更新,性能进一步提升至%。这表明尽管在某些情况下BN更新可能带来影响,但SWA确能有效提升性能。
那么,为何平均权重就能产生效果呢?可以直观地通过以下图形解释:图形展示了SWA和SGD解的差异。SWA解位于loss曲线的平坦区域,使得模型在训练过程中损失变化平稳,有利于泛化性能的提高。
图形的绘制方法虽然未在文中详细说明,但推测是将SWA和SGD解表示为x1和x2,通过变量w进行加权平均,当w=0时代表SWA,w=时代表SGD。这展示了SWA的稳定性在对抗训练扰动和优化泛化方面的重要性。
如何评价斯坦福大学提出SGD动量自调节器YellowFin?
Ranger优化器将两个非常新的开发(radam+lookahead)合并到一个单独的优化器中。为了证明它的有效性,我们的团队最近使用Ranger optimizer在fastai全球排名中获得了个排名记录。Lookahead是Ranger优化器的一半。它是由著名深度学习研究员杰弗里·辛顿(Geoffrey Hinton)在年7月的一篇新论文《前瞻优化:K步进,1步后退》中介绍的。Lookahead受最近神经网络损失面研究的启发,提出了一种新的方法来稳定深度学习的训练和收敛速度。基于radam(corrected Adam)在深度学习方差管理方面的突破,发现将radam+lookahead组合在一起(Ranger)可以产生一个梦想团队,并且可以得到比单个radam更好的优化器。
Ranger optimizer是一个易于使用和高效的单一代码库(在一个循环中加载/保存和更新所有参数)。它被集成到fastai中。Ranger源代码可以直接使用:/lessw/Ranger-Deep-Learning-Optimizer。
Adam、SGD和前瞻+Adam/SGD在LSTM上的比较
为什么radam和lookahead是互补的
可以说,RADAM为优化器开始训练提供了最好的基础。雷达采用动态整流器根据变化调整Adam的自适应动量。对于当前的数据集,它有效地提供了自动热身,以确保坚实的训练开始。
最近对神经网络的深入探索和深入了解,为今后神经网络的深入研究提供了一个灵感。
“快速调整”以减少“团队在实现快速收敛时所需的大量计算开销。”。
因此,两者都在深度学习优化的不同方面提供了突破,两者的结合具有很高的协同性,可以为您的深度学习效果提供两种改进的最佳效果。因此,寻求更稳定和更稳健的优化方法将继续下去。通过结合两个最新突破(radam+lookahead),Ranger集成有望为深度学习提供另一个进步。
Hinton等人。-“我们通过实验证明,即使在Imagenet、cifar-/、神经机器翻译和Penn treebank上设置了默认的超参数设置,lookahead也可以显著提高SGD和Adam的性能。”
因为lookahead具有双向探测设置,所以lookahead可以优化到比SGD更接近最小值的位置。
因此,本文在介绍雷达的基础上,阐述了什么是超前雷达,以及如何将雷达和超前雷达组合成一个单一的优化测距仪,以达到新的高精度。在我测试的前个时代,我获得了一个新的高准确率,比目前的fastai排名高出1%。
我们可以摆脱SGD和Adam,以及新的深度学习优化器Ranger:radam+lookahead
流浪者的第一次测试是%
法塔伊,个时代,%
更重要的是,任何人都可以使用Ranger,看看它是否提高了你的深度学习结果的稳定性和准确性!
因此,让我们仔细看看驱动Ranger的两个组件:radam和lookahead
1什么是拉丹(亚当纠正)
小结:开发radam的研究人员调查了为什么自适应动量优化器(Adam、rmsprop等)都需要预热,否则在训练开始前它们会陷入一个糟糕/可疑的局部最优状态。
我们可以摆脱SGD和Adam,以及新的深度学习优化器Ranger:radam+lookahead
原因是当优化器在训练开始时没有看到足够的数据来做出准确的自适应动量决策,那么数据的方差将非常大。因此,热身可以在训练开始时减小方差,但即使要确定热身的程度,也需要根据数据集的变化进行手动调整。
因此,修正后的Adam通过使用一个修正函数来确定一个“启发式预热”,该函数基于实际遇到的方差。整流器动态地关闭和打开自适应动量,以便在数据方差稳定之前不会全速跳跃。
这样,就避免了手动热身的需要,训练也自动稳定下来。
一旦方差稳定下来,拉丹就变成了亚当,甚至是新元。因此,拉丹的贡献是在训练的开始。
读者注意到