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輸入)
在這裏插入圖片描述

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