AutoDL论文解读(二):基于遗传算法的典型工作

自动化机器学习(AutoML)最近变得越来越火,是机器学习下个发展方向之一。其中的神经网络结构搜索(NAS)是其中重要的技术之一。人工设计网络需要丰富的经验和专业知识,神经网络有众多的超参数,导致其搜索空间巨大。NAS即是在此巨大的搜索空间里自动地找到最优的网络结构,实现深度学习的自动化。自2017年谷歌与MIT各自在ICLR上各自发表基于强化学习的NAS以来,已产出200多篇论文,仅2019年上半年就有100多篇论文。此系列文章将解读AutoDL领域的经典论文与方法,笔者也是刚接触这个领域,有理解错误的地方还请批评指正!
此系列的文章:

本文解读两篇基于遗传算法的典型方法:谷歌的《Large-Scale Evolution of Image Classifiers》和坦佩雷理工大学的《Finding Better Topologies for Deep Convolutional Neural Network by Evolution》。过去基于遗传算法的网络结构搜索大多依赖先验知识,以残差块(residual block)、稠密块(dense block)等已被验证有效的块为基础进行组合拼接,而且要求每个个体都从头开始训练,对计算资源要求很高。这里要介绍的两篇论文要解决上面的问题,它们的核心思想都是尽可能少的使用先验知识,从node-level进行网络结构搜索。

一、遗传算法

首先,作者进化出一个神经网络模型的种群,这个种群会包含很多不同的网络模型,其中每个模型即为一个个体。这个模型被训练后在验证集上的准确率为此个体的适应度评估。在每一个进化步中,worker(即计算机)从种群中随机选择两个个体,然后计算并比较其适应度。适应度较差的个体从种群中被移除,较好的个体留下来作为亲本进行下一步的繁殖。繁殖过程中,worker复制这个亲本,然后对其进行变异,即对其进行结构上的修改,修改后的模型称为后代。这个后代被训练然后得到在验证集上的准确率,最后被放回到种群里。
用这样的策略在巨大的搜索空间里寻找最优的分类模型需要巨大的计算量,为此作者提出了一个大规模并行的方法。很多worker在不同的计算机上异步地操作,他们彼此之间不直接通信。他们使用一个共享的文件系统,这里用字典存储了种群的信息,每个字典代表一个个体。相应的操作可以通过修改字典完成,例如,移除一个个体即为字典的重命名。有时会出现这种情况,对于同一个个体,一个worker尝试对其进行修改,但另一个worker可能正在对其进行操作,此时这个worker放弃修改并重新尝试。在这篇论文里,种群的大小是1000个个体,worker的个数总是为种群大小的四分之一。为了在有限的空间内实现长时间的运行,会经常对被移除的个体的字典进行垃圾收集。

二、方法实现

1、编码和变异

个体的结构被编码为一个图,我们称之为DNA。在图中,顶点表示3阶张量或激活函数。3阶张量表示图片的长宽和通道数。激活函数可以是带ReLu的批标准化,也可以是简单的线性单元。图的边表示恒等映射或卷积,并包含定义卷积特性的变异了的数值参数。当一个顶点有多个边时,他们的长宽和通道数目可能不一致。为了解决这个问题,选择这些边中的一个作为主要边,这个主要边是非跨连接的。非主要边的激活值以主要边为基准,在长宽这个维度上进行zerothorder插值,在通道这个维度上进行填充或截断。除了图,学习率也被存在DNA里。
后代是通过对亲本的复制和变异产生的,这些变异是从预先定义的集合里随机选择的。预先定义的变异集合包括:

  • 改变学习率
  • 恒等(即“保持训练”)
  • 重置权重
  • 插入卷积(在网络主干的随机位置上插入卷积,滤波器大小为3X3,步长为1或2,通道数目和输入相同,可能应用带ReLu的批归一化)
  • 移除卷积
  • 改变步长(仅允许2的幂的数值)
  • 改变通道数目
  • 滤波器大小(只对随机卷积,在水平或垂直方向上改变,只允许奇数值)
  • 插入恒等连接
  • 添加跨连接
  • 移除跨连接

上述所有随时选取都是均匀分布的。对于数值型的变异,新的值在现有值附近选取。例如,一个变异作用于一个有10个输出通道的卷积,将会导致一个有5到20个输出通道的卷积(即是原始值的一半到两倍),在此范围内的值都是允许的。对于其他参数也是如此,从而产生一个密集的搜索空间。对于步长,都使用以2为底的log值,以便激活值的形状更容易匹配。原则上,参数没有上限,例如,模型的深度没有限制。参数的密集性和无界性会导致大量可能的网络结构。

2、初始情况

初始化的种群里包含的都是简单的个体,这些个体都是没有卷积的单层模型,学习率为0.1,这样的个体表现是非常差的。这样的初始化迫使算法自己去大量地探索。这样表现差的初始化和巨大的搜索空间最大限度地减小了人为主观因素的影响。

3、训练和验证

此论文代码使用Tensorflow实现,用momentum为0.9的SGD优化器,batch_size为50,衰减权重为0.0001,每次训练跑25600轮。在测试阶段,根据验证集准确率选择一些模型做集成。

4、计算代价

为了估计计算代价,作者确定了模型训练和验证中使用的基本Tensorflow(TF)操作,如卷积、一般矩阵乘法等。对于每个TF操作,我们估计了所需的浮点操作(FLOPs)的理论数量。在实验中的每个个体,我们在一批样本上计算由TF操作引起的总FLOPs,包括训练阶段的( F t F L O P s F_{t} {\rm FLOPs} FtFLOPs)和验证阶段的( F v F L O P s F_{v} {\rm FLOPs} FvFLOPs)。然后计算 F t N t + F v N v F_{t}N_{t}+F_{v}N_{v} FtNt+FvNv N t N_{t} Nt N v N_{v} Nv分别是训练和验证的batch数目。实验的总代价是其所有个体的代价之和。
这里的FLOPs仅作为粗略的估计。这里没有考虑输入\输出、数据预处理、TF计算图构建或内存复制的时间。

4、权重继承

25600轮数对于训练一个大型网络来说还不够,在实验中每次都需要从头训练模型,这样会非常耗时。这里作者允许后代尽可能地继承亲本的参数权重,如果一个层的形状匹配,则保留其权重。因此,有些突变保留了所有的权值(比如恒等映射或学习率突变),有些则什么也没有保留(比如重置权重突变),而大多数则保留了部分但不是全部。

三、Finding Better Topologies for Deep Convolutional Neural Network by Evolution

此篇论文方法和上一篇的比较相似,这里介绍其主要思路。

作者用一个有向图 G ( N , E ) G(N,E) G(N,E)表示CNN, N N N是节点(node)集合, E E E是边(edge)集合。源节点(source node)表示输入,汇节点(sink node)表示输出,内节点(internal node)表示对前驱节点的和、激活、池化、卷积等操作,也称为卷积节点,其输出是特征图。每个卷积节点包括如下模型参数:激活函数、通道数和池化类型,默认全部采用ReLU激活函数。池化类型可以是None或最大池化(步长为2)。

进化从简单的拓扑结构开始,包括一个源节点、汇节点和一个卷积节点。每次繁殖,个体产生变异,变异是从预先定义好的集合里随机选择,变异集合里包括:

  • 卷积节点通道数目加倍
  • 在图上增加一个新的卷积节点。卷积核大小默认为3,如果被连接的两个节点的特征图大小不同,则选择合适的步长。
  • 用新边连接两个节点。卷积核大小从1、3、5、7、9中随机选择。
  • 裁剪边。
  • 将节点插入到边。如果节点插入到了包含汇节点的边,那么在插入节点的前驱节点使用最大池化。插入节点的通道数和前驱节点的相同。

和Large-Scale Evolution的方法一样,这里采只使用了变异算子而没有使用交叉算子。之前的NEAT方法整合了有性繁殖,在父母的染色体上发生交叉。交叉是产生后代变异的重要手段,从而提高了后代在进化过程中的探索能力。然而,在自然界,有性生殖比无性生殖出现得晚得多。早期生物,特别是单细胞生物,都是无性繁殖的。这些生物的遗传特征很简单,少量的突变就足以引起变异。由于进化是从最简单的拓扑结构开始的,所以作者模仿了早期生物的进化,并应用了无性生殖。由于很难将两个不同的图合并以生成新的图,因此任何组合两个图的严格规则都会极大地限制搜索空间,而无性繁殖能够在整个拓扑空间中搜索。不过,后代可能可能和它的亲本很像,所以进化会比较缓慢。

如果一个变异产生的网络是无效的,例如源节点和汇节点没有连接或者图是循环的,则随机选择另一个变异。这个过程不断重复,直到生成一个有效的图。

在进化阶段,我们根据每个个体的验证集准确率来评估其适应度。然后使用随机排序比例选择策略,选择哪些个体留下来。个体能留下来的概率和它在整个种群的排序是成比例的,我们假设其服从玻尔兹曼分布,概率质量函数为:
p ( k ) = ( 1 − e − λ ) e − λ k 1 − e λ N p(k)=\frac{(1-e^{- \lambda}) e^{- \lambda k}}{1-e^{\lambda N}} p(k)=1eλN(1eλ)eλk
k k k是个体的排序, N N N是种群的大小, λ \lambda λ是平衡“探索”和“利用”的参数。当 λ \lambda λ比较大时, p ( k ) p(k) p(k)变的平滑,适应度低的个体变的更容易被选择,算法更倾向于“探索”。

这篇论文也采用了权重继承来加速训练。后代直接继承亲本的卷积核权重,由于变异导致的不与亲本共享的部分则随机初始化。

本论文中还使用贝叶斯方法从种群中学习超参数,如学习率、批大小、dropout、优化器等。作者这些超参数当做阶学习的知识,不把其当做需要进化的部分,而是从种群中不断学习最优参数并传给下一代。具体算法如下所示:

在这里插入图片描述

参考文献

[1] Real E, Moore S, Selle A, et al. Large-Scale Evolution of Image Classifiers[J]. 2017.
[2] Zhang H, Kiranyaz S, Gabbouj M. Finding Better Topologies for Deep Convolutional Neural Networks by Evolution[J]. 2018.
[3] 《深入理解AutoML和AutoDL》
在这里插入图片描述

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您遇到的问题是autoDL在加载模型时出现了CUDA内存不足的错误。这种错误通常是由于GPU内存不足而导致的。根据引用内容,有几种可能的解决方法可以尝试。 首先,根据的引用,如果您怀疑是因为之前的进程没有完全结束导致的错误,您可以尝试使用指令来彻底终止进程。但是需要注意的是,这种操作可能会中断所有正在运行的GPU程序,因此需要谨慎使用。 另一种解决方法是根据的引用,将权重加载到CPU,并让模型在CPU上进行加载。这将避免与GPU相关的内存错误。使用这种方法,您可以尝试将模型的权重加载到CPU上,然后再进行加载操作。 您可以尝试使用以下代码来解决这个问题: ```python import torch # 将模型加载到CPU device = torch.device('cpu') model = YourModel().to(device) # 加载权重 weights = torch.load('your_weights.pth', map_location=device) model.load_state_dict(weights) # 进行模型加载操作 output = model(input) ``` 请将"YourModel"替换为您实际使用的模型类的名称,并将"your_weights.pth"替换为实际的权重文件路径。通过将模型加载到CPU上,并在加载操作时使用CPU设备,您可以避免与GPU内存相关的错误。 希望这些信息对您有所帮助!<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [完美解決pytorch载入预训练权重时出现的CUDA error: out of memory](https://blog.csdn.net/Davidietop/article/details/126803809)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值