華爲諾亞AutoML框架-Vega:(2) 代碼結構

Vega已更新到1.2版本,所以本教程以1.2版本爲準進行介紹。
Vega框架鏈接:
Vega論文:VEGA: Towards an End-to-End Configurable AutoML Pipeline[1]
Vega QQ討論羣: 833345709
Vega是基於Pipeline的設計思路,這和我們實驗室寫的AutoML綜述思路不謀而合,感興趣的也可以看看我們的論文:AutoML: A Survey of the State-of-the-art[2]

整體代碼架構

之前的華爲諾亞實驗室AutoML框架-Vega:(1) 介紹 已經介紹了相比於其他的AutoML框架, Vega框架的優點和特性。本文將從代碼結構的角度來介紹Vega,幫助大家對Vega有一個全局的瞭解,主要起到一個幫助索引查找的作用。

普通開發者用戶需要特別關注上圖圈出的4個目錄:

  • docs: 該目錄下包含豐富的中英文文檔說明,不同算法的設置和用法可以通過查閱文檔就能輕鬆解決
  • examples:該目錄下包含所有內置的開箱即用的算法,你可以進入該目錄來選擇運行指定的算法,後面會介紹運行方法
  • vega:很顯然,這是Vega的核心部件。
  • zeus:這是一個涵蓋數據集、訓練、評估等階段的全Pipeline通用組件,將Pytorch、TensorFlow和MindSpore三個框架做了整合,用戶在寫好代碼之後可以一鍵切換不同框架。因此如果你想測試不同框架的性能,Zeus一定能助你一臂之力。

看到這你可能會想爲什麼要叫 Vega呢? Vega名字官方的解釋[3]如下:

“ Zhinü (織女, the weaver girl, symbolizing the star Vega) is a fairy in ancient Chinese myths and legends. She's responsible for providing the fairy's clothes and clouds. We hope that Vega will provide AI research and application infrastructure like a weaver girl.
織女是中國古代神話傳說中的仙女,織女類比織女星。她負責提供仙女的衣服和雲彩。我們希望織女星能像織女一樣提供人工智能研究和應用基礎設施。

那Zeus也很好理解了,因爲Zeus是古希臘神話中的衆神之王,這裏Zeus將三個流行深度學習框架做了深度整合,提供了基礎的深度學習訓練Pipeline。

Docs提供了什麼?

Docs目錄下提供了中英雙語版本的文檔方便用戶查閱,這裏以中文文檔進行介紹。

由上圖可以看到docs目錄主要分成四個部分:

  • user: 該目錄下的內容主要介紹了Vega初學者需要注意的問題,介紹了Vega中引入的新的概念
    • README.md: 對user目錄的總結說明
    • config_reference.md: Vega的所有任務都是由yaml文件配置的,該文件主要介紹瞭如何在yaml文件中配置不同組件(數據集、算法等)。
    • deployment.md:介紹如何部署集羣
    • evaluate_service.md: 介紹如何部署服務器的評估服務
    • examples.md: 介紹內置算法的在不同階段的輸入(如配置文件和預訓練模型)和輸出(如保存日誌和checkpoints)
    • faq.md:常見問題和解決辦法
    • install.md:Vega安裝教程

 

  • developer:該目錄下的內容主要介紹開發者應當如何實現自定義的功能,如自定義數據集、模型、NAS算法等。
    • developer_guide.md:介紹了Vega的搜索空間、搜索算法和參數配置等基本概念和使用方法
    • datasets.md: 介紹如何自定義數據集
    • fine_grained_search_space: 介紹Vega框架的細粒度搜索空間概念和自定義方式
    • new_algorithm.md:介紹如何自定義算法

 

  • algorithms: 該目錄下包含了所有Vega框架下內置的算法介紹。
  • tasks:該目錄對幾個常見的CV任務進行介紹不同場景下的使用。

Zeus代碼架構

前面已經提到過了,Zeus是一個提供基礎組件的框架,所有組件採樣註冊機制,因此我們可以通過修改yaml文件設置即可調用不同的組件(如數據集、模型等)。

Zeus的代碼結構如上圖所示,每個模塊的作用其實可以看名字也能大概知道,下面對各個模塊做一個簡單的介紹,後續的教程會做進一步的分析。

common

該目錄下主要提供了各種參數配置組件和註冊工廠。

  • config.py: 新建了Config類,該類繼承自dict,能夠靈活處理yamljsonpy等不同格式的配置文件,同樣也可以直接傳入一個字典。其代碼大致示例如下:
 1 class Config(dict):
 2     def __init__(self, *args, **kwargs):
 3         """Init config class with multiple config files or dictionary."""
 4         super(Config, self).__init__()
 5         for arg in args:
 6             if isinstance(arg, str): # 可以傳入多個配置文件的路徑
 7                 if arg.endswith('.yaml') or arg.endswith('.yml'):
 8      ...
 9                 elif arg.endswith('.py'):
10      ...
11                 elif arg.endswith(".json"):
12      ...
13   if kwargs: # 也可以傳入一個字典進行處理
14    ...

 

  • config_serializable.py: 該文件提供了ConfigSerializable類,該類的作用是提供將類序列化爲Config的作用,比如我們定義如下類
class MyDatasetConf(ConfigSerializable):
  data_dir = './data/cifar10'
  batch_size = 32
  ...

 

之後我們可以只需要執行如下命令即可把MyDatasetConf這個類轉化成Config類。

MyDatasetConf.to_json()
  • user_config.py:該文件中定義了一個UserConfig類,該類是單例模式,可以簡單理解成是一個全局信息,因此在整個pipeline過程中都由這個類管理所有配置信息。
  • general.py: 該文件定義了通用的配置信息,如 日誌信息、集羣配置、任務ID、Backend (可以是Pytorch、TensorFlow或者Mindspore)等。
  • file_ops.py 主要是對常用的文件操作做了封裝,提供了更加便捷的操作
  • task_ops.py 主要管理每次task的ID、日誌路徑、checkpoint路徑等信息
  • class_factory.py:該文件內定義了兩個非常重要的類,即ClassTypeClassFactory,Vega的註冊機制就是靠這兩個類來管理和實現的。
    • ClassType:該類預先定義好了可以註冊的組件類別,部分代碼示例如下:
class ClassType(object):
    """Const class saved defined class type."""

    DATASET = 'dataset'               # 數據集
    NETWORK = "network"               # 模型
    TRAINER = 'trainer'               # 訓練器
    METRIC = 'trainer.metric'           # 指標(如accuracy)
    OPTIMIZER = 'trainer.optimizer'       # 優化器
    LR_SCHEDULER = 'trainer.lr_scheduler'   # 學習率scheduler
    LOSS = 'trainer.loss'              # 損失函數
    EVALUATOR = 'evaluator'             # 評估器基類,會自動根據設置調用下面不同類別的評估器 
    GPU_EVALUATOR = 'evaluator.gpu_evaluator' # GPU評估器,即在GPU上對模型等設置進行評估
    HAVA_D_EVALUATOR = 'evaluator.hava_d_evaluator' # 華爲自研達芬奇芯片評估器
    DAVINCI_MOBILE_EVALUATOR = 'evaluator.davinci_mobile_evaluator' # 達芬奇移動端評估器
    SEARCH_ALGORITHM = 'search_algorithm'    # 搜索算法
    PIPE_STEP = 'pipe_step'             # 
    GENERAL = 'general'                # 通用參數配置
    TRANSFORM = 'dataset.transforms'       # 數據增強
    CALLBACK = 'trainer.callback'         # Callback (後面教程會介紹)
    CONFIG = 'CONFIG'                 # 
    CODEC = 'search_algorithm.codec'       # 編碼解碼 (比如進化算法會把模型編碼成01序列,之後也需要解碼)
    QUOTA = 'quota'                   # 配額(比如搜索會對時間和flops有要求,可以起到過濾篩選的作用) 

 

    • ClassFactory可以通過裝飾器的方式來註冊你想要複用的模塊。如下面的代碼示例,你自定義了一個數據集MyDataset和模型MyModel,你只需要在上面加上一行ClassFactory.register(<class type>)即可完成註冊。
@ClassFactory.register(ClassType.NETWORK)
class MyModel(...):
    ...

@ClassFactory.register(ClassType.DATASET)
class MyDataset(...):
    ...

 



註冊之後,你只需要在yaml文件中將模型和數據集的名字改成MyModelMyDataset,之後會根據名字自動調用對應的類。

modules、 networks、model_zoo

這三個模塊提供的都是模型結構,看名字可能會覺得有點搞不清楚,區別在於

  • modules提供的是一些基礎模塊,Conv2D、MaxPool2d、ResBlock、StemBlock等等
  • networks提供的通常是一個Zeus內置的完整的網絡結構,比如MobileNetV3FasterRCNN
  • model_zoo主要有兩個作用
    • torchvision的模型進行了註冊,也就是說你可以很方便地調用torchvision.models內置的模型,方法是在你想調用的模型名字前面加上torchvision_前綴即可。假如你想調用ResNet18,你只需要在yaml文件裏把模型名稱改爲torchvision_resnet18
    • 提供了ModelZoo類,你可以通過調用該類的ModelZoo.get_model(model_descpretrained_model_file)方法來得到指定模型, 其中model_desc是模型的描述字典信息,比如{'type':'torchvision_resnet18', 'num_classes':10},這樣會自動生成一個ResNet18類,其輸出類別是10;pretrained_model_file是預訓練模型權重的路徑。

trainer

trainer模塊下主要有如下兩部分組件:

  • 一個是callbacks,目前Zeus內置了豐富的Callback,如lr_scheduler,model_checkpoint,progress_logger(負責管理打印日誌信息),model_statistics(計算模型參數量,FLOPS ,latency)等。這些Callback也支持註冊機制,因此你可以靈活選擇你需要的Callback。

 

  • 另一個是modules,如下圖示主要包含了losses,lr_scheduler,optimizer等。

 

Zeus分別爲Pytorch、TensorFlow、MindSpore三個框架實現了trainer組件,他們都繼承自trainer_base.py裏的TrainerBase類,該類實現了通用的參數初始化設置等操作。

trainer_api.py則是將三個框架的trainer做了整合,會自動根據設置的Backend選擇合適的trainer,代碼示例如下:

# trainer_api.py
@ClassFactory.register(ClassType.TRAINER)
class Trainer(TrainerBase):
    """Trainer class."""

    def __new__(cls, model=None, id=None, hps=None, load_ckpt_flag=False,
                model_desc=None, lazy_build=True, **kwargs):
        """Create Trainer clss."""
        if zeus.is_torch_backend():
            from zeus.trainer_torch import TrainerTorch
            trainer_cls = TrainerTorch
        elif zeus.is_tf_backend():
            from zeus.trainer_tf import TrainerTf
            trainer_cls = TrainerTf
        else:
            from zeus.trainer_ms import TrainerMs
            trainer_cls = TrainerMs

        return trainer_cls(model=model, id=id, hps=hps, load_ckpt_flag=load_ckpt_flag,
                           model_desc=model_desc, lazy_build=lazy_build, **kwargs)

 

Vega

下圖是vega目錄下的整體代碼架構,可以看到很簡單隻有3個部分組成,下面開始介紹Vega的代碼架構設計邏輯。

tools

  • 提供了一系列的運行腳本,如run_pipeline.py,full_train.py,benchmark.py,inference.py
  • 提供依賴包安裝腳本,install_pkgs.py

core

下圖是core目錄下的代碼結構

Pipeline

Vega是基於Pipeline的設計思路,這和我們實驗室寫的AutoML綜述思路不謀而合。下圖是我們的綜述論文中Pipeline示意圖,Vega的實現方法則是把每個階段視爲一個PipeStep,通過講這些階段串聯起來就可以很方便且靈活跑完所有階段,而不再需要每個階段跑完後,再手動運行下一個階段代碼。

具體而言,整個pipeline由Vega的Pipeline類管理執行,另外Vega中的PipeStep類有三個子類:BenchmarkPipeStepNasPipeStepFullyTrainPipeStep,這些定義在vega/core/pipeline中。

爲了方便理解,我把Pipeline代碼做了簡化如下進行介紹

class Pipeline:
    def run(self):
     for step_name in PipelineConfig.steps: # 遍歷['nas', 'fully_train']
            step_cfg = UserConfig().data.get(step_name) # 拿到對應step的參數設置
            ...
            PipeStep().do() # 運行對應Step

 

可以看到會有一個for循環來遍歷PipelineConfig.steps內存儲的所有step名稱,這個是由yaml文件中的pipeline定義的(如下圖示)。

每次遍歷會讀取出對應名稱的step參數,比如首先會把名稱爲nas的參數讀取出來,其實你也可以設置爲其他名字,這個名字主要是爲了方便人理解,主要用於判斷step類型的是上圖中藍色框的部分,因爲不同類型的step會有不同的運行方法。

拿到參數後會運行PipeStep().do(),這裏面的PipeStep()會通過設計好的__new__函數調用對應的step,例如NasPipeStep,之後會運行NasPipeStep內設置的do函數開始運行,這些細節會在後面的教程中做詳細介紹。

search_algs和search_space

search_algssearch_space目錄分別定義了搜索算法和搜索空間的基類,爲避免文章累贅,這部分內容也會在後面的教程中做詳細介紹。

backend_register.py

前面已經介紹過了Zeus將三個通用深度學習框架做了整合,vega下的backend_register.py作用就是設置指定的Backend和設備(如GPU、NPU等)。

在運行代碼前必須設置好Backend,否則會報錯。因爲只有這樣才能,才能知道應該調用哪個框架的模型結構。

run.py

這是Vega框架的運行入口,代碼如下所示。可以看到在對參數進行驗證處理後就會通過_run_pipeline()函數開始運行指定的Pipeline。

# vega/run.py
def run(cfg_path):
    """Run vega automl.

    :param cfg_path: config path.
    """
    if sys.version_info < (3, 6):
        sys.exit('Sorry, Python < 3.6 is not supported.')
    _init_env(cfg_path)
    _backup_cfg(cfg_path)
    _adjust_config()
    _run_pipeline()
 

 

微信公衆號:AutoML機器學習

MARSGGBO♥原創
如有意合作或學術討論歡迎私戳聯繫~
郵箱:[email protected]
2020-11-21 10:44:27

參考資料

[1] VEGA: Towards an End-to-End Configurable AutoML Pipeline: 

[2] AutoML: A Survey of the State-of-the-art: 

[3] Vega名字官方的解釋: 

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