GeneticNas代码理解

总体结构:神经网络-Cell(每个NN含有3个Cell)-DAG(每个Cell含有一个DAG)-block(每个DAG含有5个block)

Individual:储存一个DAG中的5个np.asarray([input1index,input2index,op1index,op2index])组成的list和5个(input1,input2,input1index,input2index,op1,op2)tuple组成的list;主要作用存储一个神经网络的一个cell中的DAG的配置
MultipleBlockIndividual:3个Individual组成,代表一个具体的神经网络

ConvNodeModule:存储一个CnnNodeConfig,以及其len(input_list)*5个op(一个CnnNodeConfig存储着一个block中的input_list和CNN_OP=[‘Dw3x3’,‘Identity’,‘Dw5x5’,‘Avg3x3’,‘Max3x3’],而ConvNodeModule把这些input_list中的每个元素的所有可能的op都添加到nn.Module,以便之后使用requires_grad来激活某些input和op组合来实现一个特定的神经网络)

搜索空间单个神经网络的实现:set_individual
(NN)Net.set_individual:
输入为MultipleBlockIndividual
(-RepeatBlock.set_individuall(输入为MultipleBlockIndividual))
-(Cell)CnnSearchModule.set_individuall:
输入为MultipleBlockIndividual
-(DAG)SubGraphModule.set_individual:
输入为MultipleBlockIndividual,但这里仅取其中的一个Individual来做运算,更新ConvNodeModule存储的变量,并计算出哪些node_id作为一个DAG的输出
-(block)ConvNodeModule.set_current_node_config:
把一组(input1,input2,input1index,input2index,op1,op2)更新ConvNodeModule存储的对应的变量,并使用requires_grad来激活某些input和op组合;
(Net.set_individual实质上是ConvNodeModule.set_current_node_config)

大致过程:
1-创建一个搜索空间ss对象

用于存储[node_config_list_a,node_config_list_b,node_config_list_c],这些元素均为5个CnnNodeConfig组成的list,每个CnnNodeConfig又存储着在该节点所有可能的input组成的input_list和该节点所有可能的op的名称,从而形成一个搜索空间对象

2-根据搜索空间ss创建一个神经网络nn.Module容器net
Net-Cell-DAG-block
用于存储搜索空间内所有神经网络的参数,即最底层至每个block中所有节点的所有input的所有op参数,之后在ga中使用ConvNodeModule中的requires_grad来激活block中的某组input,op组合来实现权重共享

3-根据net中所有的参数和学习率策略构造optimizer

4-根据搜索空间ss创建遗传算法搜索器ga
创建一个ga对象后,则初始化并储存generation_size个被初始化过后的神经网络,即generation_size个MultipleBlockIndividual作为现在的generation,储存至ga.generation中

5-首先使用trainloader的数据训练由requires_grad来激活一组参数的一个神经网络一次
该神经网络最初由net.set_individual(ga.sample_child())配置, ga.sample_child()返回一个MultipleBlockIndividual代表着一个随机神经网络的基因序列,训练后得到一组搜索空间参数(第一个epoch时为随机的一个MultipleBlockIndividual,之后为在ga.max_dict里取两个MultipleBlockIndividual进行crossover再对返回的第一个MultipleBlockIndividual进行mutation操作后作为最终返回的神经网络)

6-预测当前ga.generation中所有MultipleBlockIndividual对应的神经网络的测试集准确率
evaluate_individual_list

ga.current_dict=dict()添加最新的由generation_size个MultipleBlockIndividual对应的神经网络
测试得到的{individual:individual_fitness};

7-ga根据当前的ga.generation的准确率在当前的ga.generation(MultipleBlockIndividual)上进行选择,crossover,变异生成新的ga.generation
generation_size个取population_size个准确率最好的{MultipleBlockIndividual:individual_fitness}组成的PopulationDict(),得出PopulationDict()与之前的self.max_dict中的MultipleBlockIndividual有多少个不同的个数,然后更新self.max_dict为该PopulationDict(),清零self.current_dict以便于上面预测步骤更新新的self.current_dict;
根据拟合程度选取n个之前的神经网络(MultipleBlockIndividual)(可能会重复),再进行cross_over,mutation,若有重复,则再使用self.population_initializer()(随机产生新的神经网络),返回含MultipleBlockIndividual()的数组更新ga.generation

8-上面两步基于上面第三步固定训练好的搜索空间参数后,重复预测当前ga.generation并更新ga.generation两次(‘generation_per_epoch’)
相当于再固定的搜索空间参数,多次产生ga.generation配置,再取在测试集上准确率最好的,如果目前最好的准确率高于之前最好的准确率,则保存整个搜索空间的参数

注意点:步骤5-8为一个epoch,一个epoch更新一次搜索空间,只在整个训练集上训练一遍搜索空间中的一个神经网络

与Deep Neural Network Evolution遗传算法的实现的比较(更新):DEvol通过事先固定多个染色体序列list得到多个神经网络训练一定epoch得到多个验证集准确率,根据准确率改变list从而不断更新改变神经网络,所以每次更新后的population中的所有神经网络都需要训练一遍;GeneticNas的话是只训练一定的epoch,每个epoch只训练整个搜索空间参数中的一个神经网络参数至训练集结束(即只在训练集上训练一次),训练后更新了一小部分整个搜索空间的参数(即训练的神经网络对应的参数),然后更新2次population里所存储的神经网络的配置(更新基于之前的population和其中神经网络对应的测试准确率),如果更新后的population中存在比之前最好的神经网络准确率更好的网络,则存储该神经网络的配置和对应的准确率。所以说population是一直在更新的。(其中也有一定的问题,根据上一个epoch的训练后固定的整个搜索空间参数所更新后的population,来作为这个epoch训练完更新完整个搜索空间部分参数后更新population前的基础输入population,前后的整个搜索空间参数不同,不能一定保证之前epoch更新得到的population在现在的搜索空间里和上个epoch更新前的population在现在的搜索空间参数下经过上一个epoch的相同更新population的操作是一样的,但由于每次epoch训练改变的整个搜索空间的参数仅为一个神经网络,变化的部分相对较少,所以综上上一个epoch更新后的population大致可以作为现在epoch的population输入)
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章