Proxy 工作設計

執行 Agent Platform Neural Architecture Search 工作來搜尋最佳模型前,請先定義代理工作Stage1-search 會使用完整模型訓練的較小表示法,通常會在兩小時內完成。這個表示法稱為代理工作,可大幅降低搜尋成本。搜尋期間的每次試驗都會使用代理工作設定訓練模型。

以下各節說明應用程式代理工作設計的相關事項:

  • 建立 Proxy 工作的方法。
  • 優質 Proxy 工作的要求。
  • 如何使用三種代理工作設計工具找出最佳代理工作,降低搜尋成本,同時維持搜尋品質。

建立 Proxy 工作的方法

建立 Proxy 工作有三種常見方法,包括:

  • 減少訓練步驟。
  • 使用經過子取樣的訓練資料集。
  • 使用縮減的模型。

減少訓練步驟

建立 Proxy 工作最簡單的方式,就是減少訓練師的訓練步驟數量,並根據這項部分訓練向控制器回報分數。

使用經過子取樣的訓練資料集

本節說明如何使用子取樣訓練資料集進行架構搜尋和擴增政策搜尋。

您可以在架構搜尋期間,使用子取樣訓練資料集建立 Proxy 工作。不過,子取樣時請遵守下列規範:

  • 在分片之間隨機取用資料。
  • 如果訓練資料不平衡,請進行子取樣來平衡資料。

如果您並非只執行擴增搜尋,而是執行一般架構搜尋,請略過本節。使用 auto-augment 搜尋擴增政策。建議您對訓練資料進行子取樣並執行完整訓練,而不是減少訓練步驟。使用大量擴增執行完整訓練可讓分數更穩定。此外,使用減少的訓練資料可降低搜尋成本。

以縮減模型為基礎的 Proxy 工作

您也可以相對於基準模型縮減模型,藉此建立 Proxy 工作。如果您想將區塊設計搜尋與縮放搜尋分開,這項功能也很有用。

不過,如果縮減模型規模,並想使用延遲時間限制,請為縮減規模的模型設定更嚴格的延遲時間限制。提示:您可以縮減基準模型,並測量其延遲時間,藉此設定更嚴格的延遲時間限制。

對於縮減的模型,您也可以減少擴增和正規化量,與原始基準模型相比。

縮減模型範例

如要執行電腦視覺工作 (訓練圖片),有三種常見的模型縮減方式:

  • 縮減模型寬度:聲道數。
  • 減少模型深度:層數和區塊重複次數。
  • 稍微縮減訓練圖片大小 (以免消除特徵),或在工作允許的情況下裁剪訓練圖片。

建議閱讀EfficientNet 論文深入探討電腦視覺工作適用的模型資源調度方式, 並說明三種資源調度方式之間的關聯。

Spinenet 搜尋是另一個模型縮放的例子,用於 Agent Platform Neural Architecture Search。在第 1 階段搜尋中,它會縮減管道數量和圖片大小。

根據組合建立 Proxy 工作

這些方法各自獨立,但可以不同程度地結合,建立 Proxy 工作。

優質 Proxy 工作的要求

代理工作必須符合特定條件,才能將穩定獎勵回傳給控制器,並維持搜尋品質。

第 1 階段搜尋和第 2 階段完整訓練之間的排名關聯性

使用代理工作進行 Agent Platform 神經架構搜尋時,成功搜尋的關鍵假設是:如果模型 A 在第 1 階段代理工作訓練中的表現優於模型 B,則模型 A 在第 2 階段完整訓練中的表現也會優於模型 B。如要驗證這項假設,您必須評估搜尋空間中約 10 到 20 個模型,在第 1 階段搜尋和第 2 階段完整訓練獎勵之間的排名關聯性。這些模型稱為相關候選模型

下圖顯示關聯性不佳的範例 (關聯性分數 = -0.03),因此這項 Proxy 工作不適合用於搜尋:

關聯性不佳。

圖中的每個點都代表一個相關候選模型。x 軸代表模型的第 2 階段完整訓練分數,y 軸則代表相同模型的第 1 階段代理工作分數。請觀察最高點。這個模型提供最高的代理工作分數 (y 軸),但與其他模型相比,在第 2 階段完整訓練 (x 軸) 的表現不佳。相反地,下圖顯示相關性良好的範例 (相關分數 = 0.67),因此這個代理工作很適合用於搜尋:

相關性良好。

如果搜尋條件包含延遲時間限制,請一併確認延遲時間值是否具有良好關聯性。

請注意,相關候選模型的獎勵範圍良好,且獎勵範圍的取樣適當。否則無法評估排名關聯性。舉例來說,如果所有候選模型的第 1 階段獎勵都集中在 0.9 和 0.1 這兩個值,就無法提供足夠的取樣變異。

差異檢查

代理工作還有另一項要求,就是針對同一模型重複執行多次時,準確度或延遲分數不應有大幅變化,且模型不得有任何變更。如果發生這種情況,控制器就會收到雜訊訊號。我們提供測量這項差異的工具。

提供範例,以減少訓練期間的大幅變異。其中一種方法是使用 cosine decay 做為學習率時間表。下圖比較了三種學習率策略:

不同學習率的分數。

最底下的圖對應於恆定的學習率。如果分數在訓練結束時大幅變動,則訓練步驟減少的幅度稍有變化,就可能導致最終的替代工作獎勵大幅變動。為使代理工作獎勵更穩定,最好使用餘弦學習率衰減,如最高繪圖中的相應驗證分數所示。請注意,最高繪圖在訓練結束時會變得較平滑。中間的圖表顯示與逐步學習率衰減對應的分數。這比固定速率好,但仍不如餘弦衰減平滑,且需要手動調整。

學習率時間表如下所示:

學習率。

額外平滑處理

如果您使用大量擴增,驗證曲線可能無法透過餘弦衰減變得夠平滑。使用大量擴增資料表示訓練資料不足。在這種情況下,不建議使用 Agent Platform Neural Architecture Search,建議改用擴增搜尋

如果不是大量擴增所致,且您已嘗試餘弦衰減,但仍想獲得更平滑的結果,請使用 TensorFlow-2 的指數移動平均,或 PyTorch 的隨機加權平均。如需使用 TensorFlow 2 的指數移動平均最佳化工具範例,請參閱這個程式碼指標;如需 PyTorch 範例,請參閱這個隨機加權平均範例

如果試驗的準確度/週期圖表如下所示:

未套用平滑處理的準確率/週期圖表

然後套用上述平滑化技術 (例如隨機加權平均或使用指數移動平均),即可取得更一致的圖表,如下所示:

套用平滑處理的準確率/訓練週期圖表

記憶體不足 (OOM) 和學習率相關錯誤

架構搜尋空間產生的模型可能比基準模型大得多。您可能已調整基準模型的批次大小,但如果搜尋期間取樣到較大的模型,這項設定可能會失敗,導致 OOM 錯誤。在這種情況下,您需要縮減批次大小。

另一種顯示的錯誤是 NaN (非數字) 錯誤。 您應降低初始學習率或新增梯度裁剪。

tutorial-2 所述,如果超過 20% 的搜尋空間模型傳回無效分數,您就不會執行完整搜尋。我們的代理工作設計工具提供評估失敗率的方法

Proxy 工作設計工具

前幾節介紹了代理工作設計原則。本節提供三種代理工作設計工具,可根據不同的設計方法自動找出最佳代理工作,並符合所有需求

必要程式碼變更

您需要先稍微修改訓練師程式碼,才能在反覆運算過程中與 Proxy 工作設計工具互動。tf_vision/train_lib.py 顯示範例。您需要先匯入我們的程式庫:

from google.cloud.visionsolutions.nas.proxy_task import proxy_task_utils

訓練迴圈開始訓練週期前,請檢查是否需要提早停止訓練,因為 Proxy 工作設計工具希望您使用我們的程式庫:

if proxy_task_utils.get_stop_training(
    model_dir,
    end_training_cycle_step=<last-training-step-idx done so far>,
    total_training_steps=<total-training-steps>):
  break

訓練迴圈中的每個訓練週期完成後,請更新新的準確率分數、訓練週期的開始和結束步驟、訓練週期時間 (以秒為單位),以及訓練步驟總數。

proxy_task_utils.update_trial_training_accuracy_metric(
      model_dir=model_dir,
      accuracy=<latest accuracy value>,
      begin_training_cycle_step=<beginning training step for this cycle>,
      end_training_cycle_step=<end training step for this cycle>,
      training_cycle_time_in_secs=<training cycle time (excluding validation)>,
      total_training_steps=<total-training-steps>)

請注意,訓練週期時間不應包含驗證分數評估時間。請確保訓練師經常計算驗證分數 (評估頻率),這樣您才能充分取樣驗證曲線。如果您使用延遲時間限制,請在計算延遲時間後更新延遲時間指標:

proxy_task_utils.update_trial_training_latency_metric(
          model_dir=model_dir,
          latency=<measured_latency>)

模型選取工具需要載入先前的檢查點,才能進行後續疊代。如要啟用先前的檢查點重複使用功能,請在訓練器中新增旗標,如 tf_vision/cloud_search_main.py 所示:

parser.add_argument(
      "--retrain_use_search_job_checkpoint",
      type=cloud_nas_utils.str_2_bool,
      default=False,
      help="True to use previous NAS search job checkpoint."
  )

訓練模型前,請先載入這個檢查點:

if FLAGS.retrain_use_search_job_checkpoint:
    prev_checkpoint_dir = cloud_nas_utils.get_retrain_search_job_model_dir(
        retrain_search_job_trials=FLAGS.retrain_search_job_trials,
        retrain_search_job_dir=FLAGS.retrain_search_job_dir)
    logging.info("Setting checkpoint to %s.", prev_checkpoint_dir)
    # Now set your checkpoint using 'prev_checkpoint_dir'.

您也需要與訓練師回報的準確度和延遲值相應的 metric-id。如果訓練師的獎勵 (有時是準確度和延遲時間的組合) 與準確度不同,請務必也使用訓練師的 other_metrics 回報僅限準確度的指標。舉例來說,以下範例顯示預先建構的訓練工具回報的準確度和延遲時間指標:

模型選擇指標

差異評估

修改訓練師程式碼後,第一步是評估訓練師的變異數。如要評估變異數,請修改下列項目的基準訓練設定:

  • 降低訓練步驟,只需一或兩個 GPU,即可在約一小時內完成訓練。我們需要一小部分完整訓練。
  • 使用餘弦衰減學習率,並將步數設為與這些減少的步數相同,這樣學習率在接近尾聲時就會幾乎為零。

變異數評估工具會從搜尋空間取樣一個模型,確保這個模型可以開始訓練,不會發生 OOM 或 NAN 錯誤,然後使用您的設定執行這個模型的五個副本約一小時,最後回報訓練分數變異數和平滑度。執行這項工具的總成本,大約等同於使用您的設定執行五個模型約一小時。

執行下列指令,啟動差異測量工作 (您需要服務帳戶):

DATE="$(date '+%Y%m%d_%H%M%S')"
project_id=<your project-id>
# You can choose any unique docker id below.
trainer_docker_id=${USER}_trainer_${DATE}
trainer_docker_file=<path to your trainer dockerfile>
region=<your job region such as 'us-central1'>
search_space_module=<path to your search space module>
accelerator_type="NVIDIA_TESLA_V100"
num_gpus=2
# Your bucket should be for your project and in the same region as the job.
root_output_dir=<gs://your-bucket>

####### Variance measurement related parameters ######
proxy_task_variance_measurement_docker_id=${USER}_variance_measurement_${DATE}
# Use the service account that you set-up for your project.
service_account=<your service account>
job_name=<your job name>
############################################################

python3 vertex_nas_cli.py build \
--project_id=${project_id} \
--region=${region} \
--trainer_docker_id=${trainer_docker_id} \
--trainer_docker_file=${trainer_docker_file} \
--proxy_task_variance_measurement_docker_id=${proxy_task_variance_measurement_docker_id}

# The command below passes 'dummy' arguments for the training docker.
# You need to modify them for your own docker.
python3 vertex_nas_cli.py measure_proxy_task_variance \
--proxy_task_variance_measurement_docker_id=${proxy_task_variance_measurement_docker_id} \
--project_id=${project_id} \
--service_account=${service_account} \
--region=${region} \
--trainer_docker_id=${trainer_docker_id} \
--job_name=${job_name} \
--search_space_module=${search_space_module} \
--accelerator_type=${accelerator_type} \
--num_gpus=${num_gpus} \
--root_output_dir=${root_output_dir} \
--search_docker_flags \
dummy_trainer_flag1="dummy_trainer_val"

啟動這項差異測量工作後,您會取得工作連結。工作名稱應以 Variance_Measurement 前置字串開頭。以下顯示工作使用者介面範例:

變異數評估工作

variance_measurement_dir會包含所有輸出內容,您可以按一下「查看記錄」連結來查看記錄。根據預設,這項工作會使用雲端上的一個 CPU 在背景以自訂工作的形式執行,然後啟動及管理子項 NAS 工作。

自訂工作與 NAS 工作

在「NAS」工作下方,您會看到名為 Find_workable_model_<your job name> 的工作。這項工作會對搜尋空間取樣,找出不會產生任何錯誤的模型。找到這類模型後,變異數測量工作會啟動另一項「NAS」工作 <your job name>,針對您先前設定的訓練步驟數量,執行這個模型的五個副本。這些模型訓練完成後,變異數測量工作會測量其分數變異數和平滑度,並在記錄檔中回報:

變異數評估記錄

如果差異很大,您可以探索這裡列出的技巧

多種模型供您選擇

確認訓練師沒有高變異數後,請按照下列步驟操作:

  • 找出約 10 個關聯候選模型
  • 計算完整訓練分數,做為之後計算不同替代工作選項的替代工作關聯分數時的參考。

我們的工具會自動且有效率地找出這些關聯候選模型,並確保這些模型在準確度和延遲時間方面都有良好的分數分布,以便日後進行關聯計算時有良好的基礎。為此,這項工具會執行下列操作:

  • 從搜尋空間隨機取樣 N_begin 模型。 以這個範例來說,假設 N_begin = 30。 這項工具會以完整訓練時間的 1/30 訓練模型。
  • 從 30 個模型中拒絕 5 個,因為這些模型不會為準確度和延遲時間的分配情形帶來更多價值。下圖顯示這項操作的範例。遭拒絕的模型會以紅點表示:

模型選取範例

  • 以完整訓練時間的 1/25 訓練所選的 25 個模型,然後根據目前的分數再拒絕五個模型。請注意,這 25 個模型的訓練會從先前的檢查點繼續。
  • 重複這個程序,直到只剩下分配良好的 N 模型為止。
  • 訓練最後 N 個模型,直到完成為止。

N_begin 的預設設定為 30,您可以在 proxy_task/proxy_task_model_selection_lib_constants.py 檔案中找到 START_NUM_MODELSN 的預設設定為 10,可在 proxy_task/proxy_task_model_selection_lib_constants.py 檔案中找到 FINAL_NUM_MODELS

選取模型時產生的額外費用計算方式如下:

= (30*1/30 + 25*1/25 + 20*1/20 + 15*1/15 + 10*(remaining-training-time-fraction)) * full-training-time
= (4 + 10*(0.81)) * full-training-time
~= 12 * full-training-time

不過,請高於 N=10 設定。代理工作搜尋工具稍後會平行執行這些 N 模型。因此,請確保您有足夠的 GPU 配額。舉例來說,如果代理工作使用兩個 GPU 執行一個模型,則您應至少有 2*N 個 GPU 的配額。

對於模型選取工作,請使用與第 2 階段完整訓練工作相同的資料集分割區,並為基準完整訓練使用相同的訓練工具設定。

現在您已準備好執行下列指令,啟動模型選取工作 (您需要服務帳戶):

DATE="$(date '+%Y%m%d_%H%M%S')"
project_id=<your project-id>
# You can choose any unique docker id below.
trainer_docker_id=${USER}_trainer_${DATE}
trainer_docker_file=<path to your trainer dockerfile>
latency_calculator_docker_id=${USER}_model_selection_${DATE}
latency_calculator_docker_file=${USER}_latency_${DATE}
region=<your job region such as 'us-central1'>
search_space_module=<path to your search space module>
accelerator_type="NVIDIA_TESLA_V100"
num_gpus=2
# Your bucket should be for your project and in the same region as the job.
root_output_dir=<gs://your-bucket>
# Your latency computation device.
target_device_type="CPU"

####### Proxy task model-selection related parameters ######
proxy_task_model_selection_docker_id=${USER}_model_selection_${DATE}
# Use the service account that you set-up for your project.
service_account=<your service account>
job_name=<your job name>
# The value below depends on your accelerator quota. By default
# the model-selection job runs 30 trials. However, depending on
# your quota, you can choose to only run 10 trials in parallel at a time.
# However, lowering this number can increase the overall runtime for the job.
max_parallel_nas_trial=<num parallel trials>
# The value below is the 'metric-id' corresponding to the accuracy ONLY
# metric reported by your trainer. Note that this metric may
# be different from the 'reward'.
accuracy_metric_id=<set accuracy metric id used by your trainer>
latency_metric_id=<set latency metric id used by your trainer>
############################################################

python3 vertex_nas_cli.py build \
--project_id=${project_id} \
--region=${region} \
--trainer_docker_id=${trainer_docker_id} \
--trainer_docker_file=${trainer_docker_file} \
--latency_calculator_docker_id=${latency_calculator_docker_id} \
--latency_calculator_docker_file=${latency_calculator_docker_file} \
--proxy_task_model_selection_docker_id=${proxy_task_model_selection_docker_id}

# The command below passes 'dummy' arguments for trainer-docker
# and latency-docker. You need to modify them for your own docker.
python3 vertex_nas_cli.py select_proxy_task_models \
--service_account=${service_account} \
--proxy_task_model_selection_docker_id=${proxy_task_model_selection_docker_id} \
--project_id=${project_id} \
--region=${region} \
--trainer_docker_id=${trainer_docker_id} \
--job_name=${job_name} \
--max_parallel_nas_trial=${max_parallel_nas_trial} \
--accuracy_metric_id=${accuracy_metric_id} \
--latency_metric_id=${latency_metric_id} \
--search_space_module=${search_space_module} \
--accelerator_type=${accelerator_type} \
--num_gpus=${num_gpus} \
--root_output_dir=${root_output_dir} \
--latency_calculator_docker_id=${latency_calculator_docker_id} \
--latency_docker_flags \
dummy_latency_flag1="dummy_latency_val" \
--target_device_type=${target_device_type} \
--search_docker_flags \
dummy_trainer_flag1="dummy_trainer_val"

啟動這項模型選取控制器工作後,您會收到工作連結。工作名稱會以 Model_Selection_ 前置字串開頭。工作 UI 範例如下:

模型選取工作

model_selection_dir 包含所有輸出內容。按一下 View logs 連結即可查看記錄。根據預設,這個模型選取控制器工作會在 Google Cloud 上使用一個 CPU,以自訂工作的形式在背景執行,然後為模型選取的每次疊代啟動及管理子 NAS 工作。

自訂工作與 NAS 工作

每個子項 NAS 工作都有名稱,例如 <your_job_name>_iter_3 (疊代 0 除外)。一次只能執行一個疊代。每次疊代時,模型數量 (試驗次數) 會減少,訓練時間會增加。每次疊代結束時,每個 NAS 工作都會儲存 gs://<job-output-dir>/search/filtered_trial_scores.png 檔案,以視覺化方式顯示本次疊代中遭拒的模型。您也可以執行下列指令:

gcloud storage cat gs://<path to 'model_selection_dir'>/MODEL_SELECTION_STATE.json

這會顯示模型選取控制器工作的疊代和目前狀態摘要、工作名稱,以及每次疊代的連結:

{
  "start_num_models": 30,
  "final_num_models": 10,
  "num_models_to_remove_per_iter": 5,
  "accuracy_metric_id": "top_1_accuracy_without_latency",
  "latency_metric_id": "latency_milli_seconds",
  "iterations": [
    {
      "num_trials": 30,
      "trials_to_retrain": [
        "27",
        "16",
        ...,
        "14"
      ],
      "search_job_name": "projects/123456/locations/europe-west4/nasJobs/2111217356469436416",
      "search_job_link": "https://console.cloud.google.com/vertex-ai/locations/europe-west4/training/2111217356469436416/cpu?project=my-project",
      "latency_calculator_job_name": "projects/123456/locations/europe-west4/customJobs/6909239809479278592",
      "latency_calculator_job_link": "https://console.cloud.google.com/vertex-ai/locations/europe-west4/training/6909239809479278592/cpu?project=my-project",
      "desired_training_step_pct": 2.0
    },
    ...,
    {
      "num_trials": 15,
      "trials_to_retrain": [
        "14",
        ...,
        "5"
      ],
      "search_job_name": "projects/123456/locations/europe-west4/nasJobs/7045544066951413760",
      "search_job_link": "https://console.cloud.google.com/vertex-ai/locations/europe-west4/training/7045544066951413760/cpu?project=my-project",
      "latency_calculator_job_name": "projects/123456/locations/europe-west4/customJobs/2790768318993137664",
      "latency_calculator_job_link": "https://console.cloud.google.com/vertex-ai/locations/europe-west4/training/2790768318993137664/cpu?project=my-project",
      "desired_training_step_pct": 28.57936507936508
    },
    {
      "num_trials": 10,
      "trials_to_retrain": [],
      "search_job_name": "projects/123456/locations/europe-west4/nasJobs/2742864796394192896",
      "search_job_link": "https://console.cloud.google.com/vertex-ai/locations/europe-west4/training/2742864796394192896/cpu?project=my-project",
      "latency_calculator_job_name": "projects/123456/locations/europe-west4/customJobs/1490864099985195008",
      "latency_calculator_job_link": "https://console.cloud.google.com/vertex-ai/locations/europe-west4/training/1490864099985195008/cpu?project=my-project",
      "desired_training_step_pct": 101.0
    }
  ]
}

最後一次疊代會產生最終的參考模型數量,且分數分布良好。這些模型和分數會用於下一個步驟的 Proxy 工作搜尋。如果參考模型的最終準確度和延遲分數範圍優於或接近現有基準模型,這表示搜尋空間良好。如果最終準確度和延遲分數範圍明顯低於基準模型,請重新檢視搜尋空間。

請注意,如果第一次疊代中超過 20% 的試驗失敗,請取消模型選取工作,並找出失敗的根本原因。這可能是搜尋空間的問題,或是批量和學習率設定有誤

使用地端部署延遲裝置選取模型

如要使用地端部署延遲裝置選取模型,請執行 select_proxy_task_models 指令,但不要使用延遲 Docker 和延遲 Docker 旗標,因為您不想在 Google Cloud上啟動延遲 Docker。接著,請使用教學課程 4 中說明的 run_latency_calculator_local 指令,啟動地端部署延遲計算機工作。請傳遞 --controller_job_id 標記,而非 --search_job_id 標記,並搭配使用您在執行 select_proxy_task_models 指令後取得的數字模型選取工作 ID。

繼續執行模型選取控制器工作

在下列情況下,您需要繼續執行模型選取控制器工作:

  • 父項模型選取控制器工作終止 (罕見情況)。
  • 不小心取消了模型選取控制器工作。

首先,如果子項 NAS 疊代工作 (「NAS」分頁) 正在執行,請勿取消。接著,如要繼續執行父項模型選取控制器工作,請照常執行 select_proxy_task_models 指令,但這次要傳遞 --previous_model_selection_dir 旗標,並將其設為先前模型選取控制器工作的輸出目錄。繼續執行的模型選取控制器工作會從目錄載入先前的狀態,並照常運作。

找出相關候選模型及其完整訓練分數後,下一步是使用這些模型評估不同替代工作的相關分數,並選擇最佳替代工作。我們的替代工作搜尋工具可自動找出替代工作,並提供下列功能:

  • 最低的 NAS 搜尋成本。
  • 提供代理工作搜尋空間定義後,達到最低關聯性需求門檻。

請回想一下,搜尋最佳替代工作時,有三種常見的維度,包括:

  • 減少訓練步驟數。
  • 減少訓練資料量。
  • 縮小模型比例。

您可以透過取樣這些維度,建立離散的 Proxy 工作搜尋空間,如下所示:

Proxy 工作搜尋空間格線

上述百分比僅為建議和範例,實際情況中,您可以選擇任何離散值。請注意,上述搜尋空間未納入訓練步驟維度,這是因為代理工作搜尋工具會根據代理工作選項找出最佳訓練步驟。以 [50% training data, 25% model scale] 為例,請將訓練步驟數量設為與完整基準訓練相同。評估這項代理工作時,代理工作搜尋工具會啟動相關候選模型的訓練、監控目前的準確度分數,並持續計算等級相關分數 (使用參考模型過去的完整訓練分數):

關聯與訓練批次

因此,一旦達到所需關聯性 (例如 0.65),或超過搜尋費用配額 (例如每個 Proxy 工作 3 小時的限制),Proxy 工作搜尋工具就會停止 Proxy 工作訓練。因此,您不需要在訓練步驟中明確搜尋。Proxy 工作搜尋工具會以網格搜尋方式評估離散搜尋空間中的每個 Proxy 工作,並提供最佳選項。

以下是 MnasNet 檔案中定義的 MnasNet 代理工作搜尋空間定義範例 mnasnet_proxy_task_config_generator,可說明如何定義自己的搜尋空間:proxy_task/proxy_task_search_spaces.py

# MNasnet training-data size choices.
MNASNET_TRAINING_DATA_PCT_LIST = [25, 50, 75, 95]

# Training data path regex pattern.
_TRAINING_DATA_PATH_REGEX = r"gs://.*/.*"


def update_mnasnet_proxy_training_data(
    baseline_docker_args_map: Dict[str, Any],
    training_data_pct: int) -> Optional[Dict[str, Any]]:
  """Updates MNasnet baseline docker to use a certain training_data_pct."""
  proxy_task_docker_args_map = copy.deepcopy(baseline_docker_args_map)
  # Imagenet training data path looks like:
  # gs://<path to imagenet data>/train-00[0-7]??-of-01024.
  if not re.match(_TRAINING_DATA_PATH_REGEX,
                  baseline_docker_args_map["training_data_path"]):
    raise ValueError(
        "Training data path %s does not match the desired pattern." %
        baseline_docker_args_map["training_data_path"])

  root_path, _ = baseline_docker_args_map["training_data_path"].rsplit("/", 1)
  if training_data_% == 25:
    proxy_task_docker_args_map["training_data_path"] = os.path.join(
        root_path, "train-00[0-1][0-4]?-of-01024*")
  elif training_data_% == 50:
    proxy_task_docker_args_map["training_data_path"] = os.path.join(
        root_path, "train-00[0-4]??-of-01024*")
  elif training_data_% == 75:
    proxy_task_docker_args_map["training_data_path"] = os.path.join(
        root_path, "train-00[0-6][0-4]?-of-01024*")
  elif training_data_% == 95:
    proxy_task_docker_args_map["training_data_path"] = os.path.join(
        root_path, "train-00[0-8][0-4]?-of-01024*")
  else:
    logging.warning("Mnasnet training_data_% %d is not supported.",
                    training_data_pct)
    return None
  proxy_task_docker_args_map["validation_data_path"] = os.path.join(
      root_path, "train-009[0-4]?-of-01024")
  return proxy_task_docker_args_map


def mnasnet_proxy_task_config_generator(
    baseline_docker_args_map: Dict[str, Any]
) -> List[proxy_task_utils.ProxyTaskConfig]:
  """Returns a list of proxy-task configs to be evaluated for MNasnet.

  Args:
    baseline_docker_args_map: A set of baseline training-docker arguments in
      the form of a dictionary of {'key', val}. The different proxy-task
      configs to try can be built by modifying this baseline.

  Returns:
    A list of proxy-task configs to be evaluated for this
    proxy-task search space.
  """
  proxy_task_config_list = []
  # NOTE: Will not search over model-scale for MNasnet.
  for training_data_% in MNASNET_TRAINING_DATA_PCT_LIST:
    proxy_task_docker_args_map = update_mnasnet_proxy_training_data(
        baseline_docker_args_map=baseline_docker_args_map,
        training_data_pct=training_data_pct)
    if not proxy_task_docker_args_map:
      continue
    proxy_task_name = "mnasnet_proxy_training_data_pct_{}".format(
        training_data_pct)
    proxy_task_config_list.append(
        proxy_task_utils.ProxyTaskConfig(
            name=proxy_task_name, docker_args_map=proxy_task_docker_args_map))
  return proxy_task_config_list

在本範例中,我們會在訓練資料百分比 25、50、75 和 95 上建立簡單的搜尋空間 (請注意,階段 1 搜尋不會使用 100% 的訓練資料)。mnasnet_proxy_task_config_generator 函式會採用訓練 Docker 引數的常見基準範本,然後針對每個所需的 Proxy 工作訓練資料大小修改這些引數。接著,函式會傳回 proxy-task-config 清單,Proxy 工作搜尋工具稍後會依相同順序逐一處理這些設定。每個 Proxy 工作設定都有 namedocker_args_map,這是 Proxy 工作 Docker 引數的鍵值對應。

您可以根據自身需求,自由實作自己的搜尋空間定義,並設計自己的 Proxy 工作搜尋空間,即使是減少訓練資料或減少模型規模這兩個維度以外的空間也沒問題。不過,不建議明確搜尋訓練步驟,因為這會涉及重複運算,造成浪費。請讓 Proxy 工作搜尋工具為您處理這個維度。

第一次搜尋 Proxy 工作時,您可以嘗試只減少訓練資料 (就像 MnasNet 範例),並略過縮減模型規模,因為模型縮放可能涉及 image-sizenum-filtersnum-blocks 的多個參數。在大多數情況下,減少訓練資料 (以及減少訓練步驟的隱含搜尋) 就足以找到合適的 Proxy 工作。

將訓練步驟數設為完整基準訓練中使用的數量。第 2 階段完整訓練和第 1 階段代理工作訓練設定有所不同。與完整基準訓練設定相比,代理工作應減少 batch-size,只使用 2 個或 4 個 GPU。一般來說,完整訓練會使用 4 個、8 個或更多 GPU,但代理工作只會使用 2 個或 4 個 GPU。另一個差異是訓練和驗證分割。以下是 MnasNet 設定的變更範例,從第 2 階段完整訓練的 4 個 GPU,變更為代理工作搜尋的 2 個 GPU 和不同的驗證分割:

Proxy 工作設定

執行下列指令,啟動 Proxy 工作搜尋控制器工作 (您需要服務帳戶):

DATE="$(date '+%Y%m%d_%H%M%S')"
project_id=<your project-id>
# You can choose any unique docker id below.
trainer_docker_id=${USER}_trainer_${DATE}
trainer_docker_file=<path to your trainer dockerfile>
latency_calculator_docker_id=${USER}_model_selection_${DATE}
latency_calculator_docker_file=${USER}_latency_${DATE}
region=<your job region such as 'us-central1'>
search_space_module=<path to your NAS job search space module>
accelerator_type="NVIDIA_TESLA_V100"
num_gpus=2
# Your bucket should be for your project and in the same region as the job.
root_output_dir=<gs://your-bucket>
# Your latency computation device.
target_device_type="CPU"

####### Proxy task search related parameters ######
proxy_task_search_controller_docker_id=${USER}_proxy_task_search_${DATE}
job_name=<your job name>
# Path to your proxy task search space definition. For ex:
# 'proxy_task.proxy_task_search_spaces.mnasnet_proxy_task_config_generator'
proxy_task_config_generator_module=<path to your proxy task config generator module>
# The previous model-slection job provides the candidate-correlation-models
# and their scores.
proxy_task_model_selection_job_id=<Numeric job id of your previous model-selection>
# During proxy-task search, the proxy-task training is stopped
# when the following correlation score is achieved.
desired_accuracy_correlation=0.65
# During proxy-task search, the proxy-task training is stopped
# if the runtime exceeds this limit: 4 hrs.
training_time_hrs_limit=4
# The proxy-task is marked a good candidate only if the latency
# correlation is also above the required threshold.
# Note: This won't be used if you do not have a latency job.
desired_latency_correlation=0.65
# Early stop a proxy-task evaluation if you already have a better candidate.
# If False, evaluate all proxy-taask candidates.
early_stop_proxy_task_if_not_best=False
# Use the service account that you set-up for your project.
service_account=<your service account>
###################################################


python3 vertex_nas_cli.py build \
--project_id=${project_id} \
--region=${region} \
--trainer_docker_id=${trainer_docker_id} \
--trainer_docker_file=${trainer_docker_file} \
--latency_calculator_docker_id=${latency_calculator_docker_id} \
--latency_calculator_docker_file=${latency_calculator_docker_file} \
--proxy_task_search_controller_docker_id=${proxy_task_search_controller_docker_id}

# The command below passes 'dummy' arguments for trainer-docker
# and latency-docker. You need to modify them for your own docker.
python3 vertex_nas_cli.py search_proxy_task \
--service_account=${service_account} \
--proxy_task_search_controller_docker_id=${proxy_task_search_controller_docker_id} \
--proxy_task_config_generator_module=${proxy_task_config_generator_module} \
--proxy_task_model_selection_job_id=${proxy_task_model_selection_job_id} \
--proxy_task_model_selection_job_region=${region} \
--desired_accuracy_correlation={$desired_accuracy_correlation}\
--training_time_hrs_limit=${training_time_hrs_limit} \
--desired_latency_correlation=${desired_latency_correlation} \
--early_stop_proxy_task_if_not_best=${early_stop_proxy_task_if_not_best} \
--project_id=${project_id} \
--region=${region} \
--trainer_docker_id=${trainer_docker_id} \
--job_name=${job_name} \
--search_space_module=${search_space_module} \
--accelerator_type=${accelerator_type} \
--num_gpus=${num_gpus} \
--root_output_dir=${root_output_dir} \
--latency_calculator_docker_id=${latency_calculator_docker_id} \
--latency_docker_flags \
dummy_latency_flag1="dummy_latency_val" \
--target_device_type=${target_device_type} \
--search_docker_flags \
dummy_trainer_flag1="dummy_trainer_val"

啟動這項 Proxy 工作搜尋控制器工作後,您會收到工作連結。工作名稱開頭為前置字串 Search_controller_。工作使用者介面範例如下:

Proxy 工作搜尋工作

search_controller_dir 會包含所有輸出內容,點選 View logs 連結即可查看記錄。這項工作預設會使用雲端上的單一 CPU,以自訂工作的形式在背景執行,然後為每個 Proxy 工作評估啟動及管理子項 NAS 工作。

自訂工作與 NAS 工作

每個 Proxy 工作 NAS 工作都有名稱,例如 ProxyTask_<your-job-name>_<proxy-task-name>,其中 <proxy-task-name> 是 Proxy 工作設定產生器模組為每個 Proxy 工作提供的內容。一次只能執行一項 Proxy 工作評估。您也可以執行下列指令:

gcloud storage cat gs://<path to 'search_controller_dir'>/SEARCH_CONTROLLER_STATE.json

這項指令會顯示所有 Proxy 工作評估的摘要,以及搜尋控制器工作、工作名稱和每個評估的連結目前狀態:

{
  "proxy_tasks_map": {
    "mnasnet_proxy_training_data_pct_25": {
      "proxy_task_stats": {
        "training_steps": [
          1249,
          2499,
          ...,
          18749
        ],
        "accuracy_correlation_over_step": [
          -0.06666666666666667,
          -0.6,
          ...,
          0.7857142857142856
        ],
        "accuracy_correlation_p_value_over_step": [
          0.8618005952380953,
          0.016666115520282188,
          ...,
          0.005505952380952381
        ],
        "median_accuracy_over_step": [
          0.011478611268103123,
          0.04956454783678055,
          ...,
          0.32932570576667786
        ],
        "median_training_time_hrs_over_step": [
          0.11611097933475001,
          0.22913257125276987,
          ...,
          1.6682701704073444
        ],
        "latency_correlation": 0.9555555555555554,
        "latency_correlation_p_value": 5.5114638447971785e-06,
        "stopping_state": "Met desired correlation",
        "posted_stop_trials_message": true,
        "final_training_time_in_hours": 1.6675102778428197,
        "final_training_steps": 18512
      },
      "proxy_task_name": "mnasnet_proxy_training_data_pct_25",
      "search_job_name": "projects/123456/locations/europe-west4/nasJobs/4173661476642357248",
      "search_job_link": "https://console.cloud.google.com/vertex-ai/locations/europe-west4/training/4173661476642357248/cpu?project=my-project",
      "latency_calculator_job_name": "projects/123456/locations/europe-west4/customJobs/8785347495069745152",
      "latency_calculator_job_link": "https://console.cloud.google.com/vertex-ai/locations/europe-west4/training/8785347495069745152/cpu?project=my-project"
    },
    ...,
    "mnasnet_proxy_training_data_pct_95": {
      "proxy_task_stats": {
        "training_steps": [
          1249,
          ...,
          18749
        ],
        "accuracy_correlation_over_step": [
          -0.3333333333333333,
          ...,
          0.7857142857142856,
          -5.0
        ],
        "accuracy_correlation_p_value_over_step": [
          0.21637345679012346,
          ...,
          0.005505952380952381,
          -5.0
        ],
        "median_accuracy_over_step": [
          0.01120645459741354,
          ...,
          0.38238024711608887,
          -1.0
        ],
        "median_training_time_hrs_over_step": [
          0.11385884770307843,
          ...,
          1.5466042930547819,
          -1.0
        ],
        "latency_correlation": 0.9555555555555554,
        "latency_correlation_p_value": 5.5114638447971785e-06,
        "stopping_state": "Met desired correlation",
        "posted_stop_trials_message": true,
        "final_training_time_in_hours": 1.533235285929564,
        "final_training_steps": 17108
      },
      "proxy_task_name": "mnasnet_proxy_training_data_pct_95",
      "search_job_name": "projects/123456/locations/europe-west4/nasJobs/2341822328209408000",
      "search_job_link": "https://console.cloud.google.com/vertex-ai/locations/europe-west4/training/2341822328209408000/cpu?project=my-project",
      "latency_calculator_job_name": "projects/123456/locations/europe-west4/customJobs/7575005095213924352",
      "latency_calculator_job_link": "https://console.cloud.google.com/vertex-ai/locations/europe-west4/training/7575005095213924352/cpu?project=my-project"
    }
  },
  "best_proxy_task_name": "mnasnet_proxy_training_data_pct_75"
}

proxy_tasks_map 會儲存每個 Proxy 工作評估的輸出內容,並best_proxy_task_name記錄搜尋的最佳 Proxy 工作。每個 Proxy 工作項目都有額外資料,例如 proxy_task_stats,可記錄準確度關聯性的進度、p 值、準確度中位數,以及訓練步驟的訓練時間中位數。此外,系統也會記錄延遲相關的關聯性 (如適用),以及停止這項工作的原因 (例如超過訓練時間限制) 和停止時的訓練步驟。您也可以執行下列指令,將 search_controller_dir 的內容複製到本機資料夾,以繪圖形式查看這些統計資料:

gcloud storage cp gs://<path to 'search_controller_dir'>/* /your/local/dir

並檢查繪圖圖片。舉例來說,下圖顯示最佳替代工作的準確度與訓練時間的相關性:

準確度與訓練時間的相關性

搜尋完成後,您已找到最佳的 Proxy 工作設定,請務必執行下列操作:

  • 將訓練步數設為勝出者 Proxy 工作的 final_training_steps
  • 將餘弦衰減步驟設為與 final_training_steps 相同,這樣學習率在接近尾聲時幾乎會變成零。
  • [選用] 在訓練結束時進行一次驗證分數評估,可節省多次評估的費用。

如要使用地端部署延遲裝置進行 Proxy 工作搜尋,請執行 search_proxy_task 指令,但不要使用延遲 Docker 和 latency-docker 旗標,因為您不想在 Google Cloud上啟動延遲 Docker。接著,請使用教學課程 4 中說明的 run_latency_calculator_local 指令,啟動地端部署延遲計算機工作。請傳遞 --controller_job_id 旗標,並在執行 search_proxy_task 指令後取得數值型 proxy-task-search 工作 ID,而不是傳遞 --search_job_id 旗標。

在下列情況下,您需要繼續執行 Proxy 工作搜尋控制器工作:

  • 父項 Proxy 工作搜尋控制器工作終止 (罕見情況)。
  • 不小心取消了 Proxy 工作搜尋控制器工作。
  • 您想在稍後 (即使是多天後) 擴展 Proxy 工作搜尋空間。

首先,如果子項 NAS 疊代作業 (NAS 分頁) 正在執行,請勿取消。接著,如要繼續執行父項 Proxy 工作搜尋控制器作業,請照常執行 search_proxy_task 指令,但這次要傳遞 --previous_proxy_task_search_dir 旗標,並將其設為先前 Proxy 工作搜尋控制器作業的輸出目錄。繼續執行的 Proxy 工作搜尋控制器作業會從目錄載入先前的狀態,並照常運作。

最終檢查

代理工作最後的兩項檢查包括獎勵範圍,以及儲存資料以供搜尋後分析。

獎勵範圍

回報給控制器的獎勵應介於 [1e-3, 10] 範圍內。 如果不是,您可以人為調整獎勵,以達到這個目標。

儲存資料以供搜尋後分析

您的 Proxy 工作程式碼應將任何其他指標和資料儲存至 Cloud Storage 位置,這可能有助於稍後分析搜尋空間。我們的 Agent Platform Neural Architecture Search 最多只支援記錄五個浮點數 other_metrics任何其他指標都應儲存至 Cloud Storage 位置,以供後續分析。