Diseño de tareas del proxy

Antes de ejecutar un trabajo de búsqueda de arquitectura neuronal para buscar un modelo óptimo, define tu tarea de proxy. La búsqueda de etapa 1 usa una representación mucho más pequeña de un entrenamiento de modelos completo, que suele terminar en dos horas. Esta representación se denomina tarea de proxy y reduce el costo de búsqueda de manera significativa. Cada prueba durante la búsqueda entrena un modelo con la configuración de la tarea de proxy.

En las siguientes secciones, se describe lo que implica aplicar el diseño de tareas de proxy:

  • Enfoques para crear una tarea de proxy.
  • Requisitos de una buena tarea de proxy.
  • Cómo usar las tres herramientas de diseño de tareas de proxy para encontrar la tarea óptima, lo que reduce el costo de búsqueda y mantiene la calidad de esta.

Enfoques para crear una tarea de proxy

Existen tres enfoques comunes para crear una tarea del proxy, que incluyen los siguientes:

  • Usar menos pasos de entrenamiento.
  • Usar un conjunto de datos de entrenamiento con submuestras.
  • Usar un modelo reducido.

Usa menos pasos de entrenamiento

La forma más sencilla de crear una tarea de proxy es reducir la cantidad de pasos de entrenamiento para tu entrenador y, luego, informar una puntuación al controlador en función de este entrenamiento parcial.

Usa un conjunto de datos de entrenamiento con submuestras

En esta sección, se describe el uso de un conjunto de datos de entrenamiento con submuestras para una búsqueda de arquitectura y una búsqueda de políticas de magnificación.

Se puede crear una tarea de proxy mediante un conjunto de datos de entrenamiento con submuestras durante la búsqueda de arquitectura. Sin embargo, cuando se realice un submuestreo, sigue estos lineamientos:

  • Distribuye los datos de forma aleatoria entre fragmentos.
  • Si los datos de entrenamiento están desequilibrados, realiza una muestra secundaria para equilibrarlos.

Omite esta sección si no realizas una búsqueda solo de magnificación y solo ejecutas la búsqueda normal de arquitectura. Usa la magnificación automática para buscar una política de magnificación. Es conveniente realizar una submuestra de los datos de entrenamiento y ejecutar un entrenamiento completo que reducir la cantidad de pasos de entrenamiento. Ejecutar el entrenamiento completo con una magnificación grande mantiene las puntuaciones más estables. Además, usa los datos de entrenamiento reducidos para que el costo de búsqueda sea más bajo.

Tarea de proxy basada en un modelo reducido

También puedes reducir la escala del modelo en relación con el modelo de referencia para crear una tarea de proxy. Esto también puede ser útil cuando deseas separar la búsqueda de diseño de bloque de la búsqueda de escala.

Sin embargo, si reduces la escala del modelo y quieres usar una restricción de latencia, usa una restricción de latencia más estricta para el modelo reducido. Sugerencia: Puedes reducir la escala del modelo de referencia y medir su latencia para establecer esta restricción de latencia más estricta.

Para el modelo de reducción de escala, también puedes reducir la cantidad de magnificación y regularización en comparación con el modelo de referencia original.

Ejemplos de un modelo reducido

Para las tareas de visión artificial en las que entrenas en imágenes, existen tres maneras comunes de reducir la escala de un modelo:

  • Reducir el ancho del modelo: una cantidad de canales.
  • Reducir la profundidad del modelo: una cantidad de capas y bloques que se repiten.
  • Reducir ligeramente el tamaño de la imagen de entrenamiento (para que no elimine atributos) o recortar las imágenes de entrenamiento si tu tarea lo permite.

Lectura sugerida: El informe de EfficientNet proporciona excelentes estadísticas sobre el escalamiento de modelos para las tareas de visión artificial. También explica cómo se relacionan las tres formas de escalamiento.

La búsqueda de Spinnaker es otro ejemplo de escalamiento de modelos que se usa con Neural Architecture Search. Para la búsqueda de la etapa 1, reduce la cantidad de canales y el tamaño de la imagen.

Tarea de proxy basada en una combinación

Los enfoques funcionan de forma independiente y se pueden combinar en diferentes grados para crear una tarea de proxy.

Requisitos para una buena tarea de proxy

Una tarea de proxy debe cumplir con ciertos requisitos antes de que pueda otorgar una recompensa estable al controlador y mantener la calidad de la búsqueda.

Correlación de rangos entre la búsqueda de la etapa 1 y el entrenamiento completo de la etapa 2

Cuando se usa una tarea de proxy para la búsqueda de Neural Architecture Search, una suposición clave de una búsqueda exitosa es que, si el modelo A funciona mejor que el modelo B durante entrenamiento de la tarea de proxy de la etapa 1, el modelo A también tendrá un mejor rendimiento que el modelo B en el entrenamiento completo de la etapa 2. Para validar esta suposición, debes evaluar la correlación de rangos entre las recompensas de las búsquedas de la etapa 1 y el entrenamiento completo de la etapa 2 en alrededor de 10-20 modelos en tu espacio de búsqueda. Estos modelos se denominan modelos de candidato de correlación.

En la figura a continuación, se muestra un ejemplo de una correlación deficiente (puntuación de correlación = -0.03), lo que hace que esta tarea de proxy sea una mala opción para una búsqueda:

Correlación deficiente.

Cada punto en el trazado representa un modelo de correlación y candidatos. El eje x representa las puntuaciones de entrenamiento completo de la etapa 2 para los modelos y el eje y representa las puntuaciones de la tarea del proxy de la etapa 1 para los mismos modelos. Observa el punto más alto. Este modelo otorgó la puntuación de tarea de proxy más alta (eje y), pero tiene un rendimiento bajo durante el entrenamiento completo de etapa 2 (eje x) en comparación con otros modelos. En cambio, en la figura a continuación, se muestra un ejemplo de una buena correlación (puntuación de puntuación = 0.67) que hace que esta tarea de proxy sea una buena candidata para una búsqueda:

Corrige la correlación.

Si tu búsqueda implica una restricción de latencia, verifica también una buena correlación para los valores de latencia.

Ten en cuenta que las recompensas de modelo de candidato de correlación tienen un buen rango y un muestreo aceptable del rango de recompensas. De lo contrario, no puedes evaluar la correlación de rangos. Por ejemplo, si todas las recompensas de etapa 1 de los modelos candidatos para la correlación se centran en solo dos valores, 0.9 y 0.1, entonces esto no proporciona suficiente variación de muestreo.

Verificación de varianza

Otro requisito de una tarea de proxy es que no debe tener una gran variación en la precisión ni su puntuación de latencia cuando se repite varias veces para el mismo modelo sin ningún cambio. Si esto sucede, le da una señal de ruido al controlador. Se proporciona una herramienta para medir esta varianza.

Se proporcionan ejemplos para mitigar una gran varianza durante el entrenamiento. Una forma es usar cosine decay como el programa de tasa de aprendizaje. En el siguiente gráfico, se comparan tres estrategias de tasa de aprendizaje:

Puntuación con diferentes tasas de aprendizaje.

El trazado más bajo corresponde a una tasa de aprendizaje constante. Cuando la puntuación se modifica al final del entrenamiento, un pequeño cambio en la cantidad reducida de pasos de entrenamiento puede causar un gran cambio en la recompensa de la tarea de proxy final. Para que la recompensa de la tarea de proxy sea más estable, es mejor usar una disminución de coseno de la tasa de aprendizaje, como lo muestran las puntuaciones de validación correspondientes en el diagrama superior. Observa cómo el diagrama superior se vuelve más fluido al final del entrenamiento. En el diagrama del medio, se muestra la puntuación correspondiente a la disminución gradual de la tasa de aprendizaje. Es mejor que la tasa constante, pero aún no es tan uniforme como la disminución del coseno y también requiere un ajuste manual.

Los programas de tasa de aprendizaje se muestran a continuación:

Tasas de aprendizaje.

Fluidez adicional

Si usas una magnificación importante, es posible que la curva de validación aún no sea lo suficientemente uniforme con la disminución del coseno. El uso de una magnificación importante indica la falta de datos de entrenamiento. En este caso, no se recomienda el uso de la búsqueda de arquitectura neuronal, por lo que te sugerimos que uses la búsqueda de aumento.

Si el aumento grande no es la causa y ya probaste la disminución del coseno, pero aún deseas lograr más suavidad, usa la media móvil exponencial para TensorFlow-2 o media ponderada estocásica para PyTorch. Consulta este punto de código para ver un ejemplo en el que se usa un optimizador de media móvil exponencial con TensorFlow 2 y este ejemplo de promediación con ponderación estocástica para PyTorch.

Si los grafos de precisión/ciclo de entrenamiento para las pruebas se ven así:

Grafo de exactitud/ciclo de entrenamiento sin alisamiento aplicado

Luego, puedes aplicar las técnicas de suavizamiento mencionadas antes (como el promedio ponderado estocástico o el uso de la media móvil exponencial) para obtener un grafo más coherente como el siguiente:

Grafo de exactitud/ciclo de entrenamiento con alisamiento aplicado

Errores de memoria insuficiente (OOM) y tasa de aprendizaje

La arquitectura del espacio de búsqueda puede generar modelos mucho más grandes que el modelo de referencia. Es posible que hayas ajustado el tamaño del lote para tu modelo de referencia, pero esta configuración puede fallar cuando los modelos más grandes se muestrean durante la búsqueda, lo que genera errores de OOM. En este caso, debes reducir el tamaño del lote.

El otro tipo de error que aparece es el error NaN (no un número). Debes reducir la tasa de aprendizaje inicial o agregar recorte de gradientes.

Como se mencionó en instructivo-2, si más del 20% de tus modelos de espacio de búsqueda muestran puntuaciones no válidas, no ejecutarás la búsqueda completa. Nuestras herramientas de diseño de tareas de proxy proporcionan una forma de evaluar la tasa de fallas.

Herramientas de diseño de tareas de proxy

En las secciones anteriores, se analizan los principios del diseño de tareas de proxy. En esta sección, se proporcionan tres herramientas de diseño de tarea de proxy para encontrar de forma automática la tarea de proxy óptima en función de los diferentes enfoques de diseño y cuál reúnetodos los requisitos.

Cambios de código obligatorios

Primero debes modificar el código del entrenador para que pueda interactuar con las herramientas de diseño de tareas de proxy durante un proceso iterativo. En tf_vision/train_lib.py, se muestra un ejemplo. Primero debes importar nuestra biblioteca:

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

Antes de que comience un ciclo de entrenamiento en tu bucle de entrenamiento, verifica si necesitas detener el entrenamiento antes de tiempo, ya que la herramienta de diseño de tareas de proxy quiere que uses nuestra biblioteca:

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

Una vez que se completa cada ciclo de entrenamiento en el bucle de entrenamiento, actualiza la puntuación de precisión nueva, el paso de inicio y finalización del ciclo de entrenamiento, el tiempo del ciclo de entrenamiento en segundos y los pasos de entrenamiento totales.

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>)

Ten en cuenta que el tiempo del ciclo de entrenamiento no debe incluir el tiempo para la evaluación de la puntuación de validación. Asegúrate de que el entrenador calcule las puntuaciones de validación con frecuencia (frecuencia de evaluación) para que tengas suficientes muestras de la curva de validación. Si usas la restricción de latencia, actualiza la métrica de latencia después de latencia de procesamiento:

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

La herramienta de selección de modelos requiere que se cargue el punto de control anterior para una iteración sucesiva. Para habilitar la reutilización de un punto de control anterior, agrega una marca a tu entrenador, como se muestra en 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."
  )

Carga este punto de control antes de entrenar el modelo:

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'.

También necesitas el metric-id correspondiente a los valores de precisión y latencia que informa tu entrenador. Si tu recompensa de entrenador (que a veces es una combinación de exactitud y latencia) es diferente de la exactitud, asegúrate de informar también la métrica de solo precisión mediante other_metrics de tu entrenador. Por ejemplo, en el siguiente ejemplo, se muestran las métricas de solo precisión y latencia que informa nuestro entrenador compilado previamente:

Métricas de selección de modelos

Medición de la varianza

Después de modificar tu código de entrenador, el primer paso es medir la varianza para tu entrenador. Para la medición de la varianza, modifica la configuración del entrenamiento de referencia de lo siguiente:

  • Reducir los pasos de entrenamiento para que se ejecuten durante aproximadamente una hora con solo una o dos GPUs. Necesitamos una pequeña muestra del entrenamiento completo.
  • Use la tasa de aprendizaje de disminución de coseno y establece sus pasos de la misma manera que estos pasos reducidos, de modo que la tasa de aprendizaje sea casi cero hacia el final.

La herramienta de medición de la varianza toma una muestra de un modelo del espacio de búsqueda y se asegura de que este modelo pueda comenzar a entrenar sin generar errores OOM o NAN, ejecuta cinco copias de este modelo con tu configuración durante aproximadamente una hora, e informa la varianza y la fluidez de la puntuación de entrenamiento. El costo total de ejecutar esta herramienta es aproximadamente el mismo que el de ejecutar cinco modelos con tu configuración durante aproximadamente una hora.

Inicia el trabajo de medición de la varianza con la ejecución del siguiente comando (necesitas una cuenta de servicio):

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"

Una vez que inicies este trabajo de medición de la varianza, obtendrás un vínculo de trabajo. El nombre del trabajo debe comenzar con el prefijo Variance_Measurement. A continuación, se muestra un ejemplo de una IU de trabajo:

Trabajo de medición de la varianza

variance_measurement_dir contendrá todos los resultados y puedes verificar los registros si haces clic en el vínculo Ver registros. Este trabajo usa una CPU en la nube de forma predeterminada para ejecutarse en segundo plano como un trabajo personalizado y, luego, inicia y administra los trabajos NAS secundarios.

Trabajos personalizados frente a NAS

En trabajos de NAS, verás un trabajo llamado Find_workable_model_<your job name>. Este trabajo muestreará tu espacio de búsqueda para encontrar un modelo, que no genera ningún error. Una vez que se encuentra este modelo, el trabajo de medición de la varianza inicia otro trabajo NAS <your job name>, que ejecuta cinco copias de este modelo para la cantidad de pasos de entrenamiento que configuraste antes. Una vez que finaliza el entrenamiento de estos modelos, el trabajo de medición de la varianza mide su varianza y fluidez en las puntuaciones, y las informa en sus registros:

Registros de medición de la varianza

Si la varianza es alta, puedes explorar las técnicas que se enumeran aquí.

Selección del modelo

Una vez que hayas verificado que tu entrenador no tiene una varianza alta, los siguientes pasos son los siguientes:

  • encontrar alrededor de 10 modelos-candidatos-correlación
  • calcular sus puntuaciones de entrenamiento completo que actuarán como referencia cuando calcules las puntuaciones de correlación de tareas de proxy para diferentes opciones de tareas de proxy más adelante.

Nuestra herramienta de forma automática y eficiente encuentra estos modelos candidatos para la correlación y garantiza que tengan una buena distribución de puntuación tanto para la exactitud como para la latencia a fin de que el cálculo de la correlación futura tenga una buena base. Para ello, la herramienta hace lo siguiente:

  • Muestra de forma aleatoria modelos N_begin de tu espacio de búsqueda. Para este ejemplo, supongamos que se trata N_begin = 30. La herramienta los entrena durante un 1/30 de tiempo completo de entrenamiento.
  • Rechazar cinco de 30 modelos, que no suman más a la distribución de precisión y latencia. En la siguiente figura, se muestra este ejemplo. Los modelos rechazados se muestran como puntos rojos:

Ejemplo de selección de modelos

  • Entrena los 25 modelos seleccionados para 1/25 de tiempo completo de entrenamiento y, luego, rechaza cinco modelos más según las puntuaciones hasta ahora. Ten en cuenta que el entrenamiento de los 25 modelos se continúa desde su punto de control anterior.
  • Repite este proceso hasta que solo queden N modelos con una buena distribución.
  • Entrena estos últimos modelos N hasta su finalización.

La configuración predeterminada para N_begin es 30 y se puede encontrar como START_NUM_MODELS en el archivo proxy_task/proxy_task_model_selection_lib_constants.py. La configuración predeterminada para N es 10 y se puede encontrar como FINAL_NUM_MODELS en el archivo proxy_task/proxy_task_model_selection_lib_constants.py.

El costo adicional de este proceso de selección de modelos se calcula de la siguiente manera:

= (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

Sin embargo, permanece por encima de la configuración N=10. La herramienta de búsqueda de tareas del proxy ejecuta estos modelos N en paralelo. Por lo tanto, asegúrate de tener suficiente cuota de GPU para esto. Por ejemplo, si tu tarea de proxy usa dos GPU para un modelo, debes tener una cuota de al menos 2*N GPU.

En el trabajo de selección de modelos, usa la misma partición de conjunto de datos que el trabajo de entrenamiento completo de etapa 2 y la misma configuración de entrenador para el entrenamiento completo de referencia.

Ahora estás listo para iniciar el trabajo de selección de modelos mediante la ejecución del siguiente comando (necesitas una cuenta de servicio):

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"

Una vez que inicies este trabajo de controlador de selección de modelos, se recibirá un vínculo de trabajo. El nombre del trabajo comienza con el prefijo Model_Selection_. A continuación, se muestra un ejemplo de una IU de trabajo:

Trabajo de selección de modelos

model_selection_dir contiene todos los resultados. Haz clic en el vínculo View logs para verificar los registros. Este trabajo del controlador de selección de modelos usa de forma predeterminada una CPU en Google Cloud para ejecutarse en segundo plano como un trabajo personalizado y, luego, inicia y administra los trabajos NAS secundarios para cada iteración de la selección del modelo.

Trabajos personalizados frente a NAS

Cada trabajo NAS secundario tiene un nombre como <your_job_name>_iter_3 (excepto la iteración 0). Solo una iteración se ejecuta a la vez. En cada iteración, la cantidad de modelos (cantidad de pruebas) se reduce y la duración del entrenamiento aumenta. Al final de cada iteración, cada trabajo de NAS guarda el archivo gs://<job-output-dir>/search/filtered_trial_scores.png que muestra de forma visual qué modelos se rechazaron en esta iteración. También puedes ejecutar el siguiente comando:

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

que muestra un resumen de las iteraciones y el estado actual del trabajo del controlador de selección de modelos, el nombre del trabajo y los vínculos para cada iteración:

{
  "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
    }
  ]
}

La última iteración tiene la cantidad final de modelos de referencia con una buena distribución de la puntuación. Estos modelos y sus puntuaciones se usan para la búsqueda de tareas de proxy en el siguiente paso. Si el rango de puntuación de latencia y precisión final para los modelos de referencia parece mejor o cercano a tu modelo de referencia existente, lo que proporciona una buena indicación temprana sobre tu espacio de búsqueda. Si el rango de puntuación final de precisión y latencia es mucho peor que el modelo de referencia, vuelve a revisar el espacio de búsqueda.

Ten en cuenta que si más del 20% de tus pruebas en la primera iteración fallan, cancela tu trabajo de selección de modelos e identifica la causa raíz de las fallas. Puede tratarse de un problema con tu espacio de búsqueda o la configuración del tamaño del lote y la tasa de aprendizaje.

Usa el dispositivo de latencia local para seleccionar el modelo

Si deseas usar el dispositivo de latencia local para la selección de modelos, ejecuta el comando select_proxy_task_models sin el Docker de latencia y las marcas de latencia de Docker, ya que no deseas iniciar el Docker de latencia en Google Cloud. A continuación, usa el comando run_latency_calculator_local que se describe en el Instructivo 4 para iniciar el trabajo de calculadora de latencia local. En lugar de pasar la marca --search_job_id, pasa la marca --controller_job_id con el ID de trabajo numérico de selección de modelos que obtienes después de ejecutar el comando select_proxy_task_models.

Reanuda el trabajo del controlador de selección de modelos

En las siguientes situaciones, se requiere que reanudes el trabajo del controlador de selección de modelos:

  • El trabajo del controlador de selección del modelo superior no funciona (casos poco frecuentes).
  • Cancelas por accidente el trabajo del controlador de selección de modelos.

Primero, no canceles el trabajo de iteración NAS secundario (pestaña NAS) si ya se está ejecutando. Luego, para reanudar el trabajo del controlador de selección de modelos superiores, ejecuta el comando select_proxy_task_models como antes, pero esta vez pasa la marca --previous_model_selection_dir y establécela en el directorio de salida para el trabajo de controlador de selección de modelo anterior. El trabajo del controlador de selección de modelos reanudado carga su estado anterior desde el directorio y continúa funcionando como antes.

Después de encontrar los modelos candidatos y sus puntuaciones de entrenamiento completo, el siguiente paso es usarlos para evaluar las puntuaciones de correlación en las diferentes opciones de tarea de proxy y elegir la tarea de proxy óptima. Nuestra herramienta de búsqueda de tareas de proxy puede encontrar automáticamente una tarea de proxy, que ofrece lo siguiente:

  • El costo de búsqueda de NAS más bajo.
  • Cumple con un umbral mínimo de requisito de correlación después de proporcionarle una definición de espacio de búsqueda de tarea de proxy.

Recuerda que hay tres dimensiones comunes para buscar una tarea óptima de proxy, que incluyen las siguientes:

  • Se redujo la cantidad de pasos de entrenamiento.
  • Menor cantidad de datos de entrenamiento.
  • Escalamiento de modelos reducida

Puedes crear un espacio de búsqueda de tarea de proxy discreto si muestras estas dimensiones, como se muestra a continuación:

Cuadrícula de espacio de búsqueda de tareas del proxy

Los números porcentuales anteriores solo se establecen como una sugerencia aproximada y un ejemplo. En la práctica, puedes elegir cualquier opción discreta. Ten en cuenta que no incluimos la dimensión de pasos de entrenamiento en el espacio de búsqueda anterior. Esto se debe a que la herramienta de búsqueda de tarea de proxy determina el paso de entrenamiento óptimo con una opción de tarea de proxy. Considera una elección de tarea de proxy de [50% training data, 25% model scale]. Establece la cantidad de pasos de entrenamiento en la misma cantidad que para el entrenamiento de modelo de referencia completo. Cuando se evalúa esta tarea de proxy, la herramienta de búsqueda de tareas del proxy inicia el entrenamiento de los modelos de correlación de candidatos, supervisa sus puntuaciones de precisión actuales y calcula de forma continua la puntuación de correlación de clasificación (usando las puntuaciones de entrenamiento completas pasadas para los modelos de referencia):

Correlación frente a pasos de entrenamiento

Por lo tanto, la herramienta de búsqueda de tarea de proxy puede detener el entrenamiento de tarea de proxy una vez que se obtiene la correlación deseada (como 0.65), o también se puede detener de forma anticipada si se supera la cuota de costo de búsqueda (como el límite de 3 horas por tarea de proxy). Por lo tanto, no necesitas buscar de forma explícita durante los pasos de entrenamiento. La herramienta de búsqueda de tareas del proxy evalúa cada tarea de proxy desde tu espacio de búsqueda discreto como una búsqueda de cuadrícula y te brinda la mejor opción.

Lo que se muestra a continuación es un MnasNet de ejemplo de definición de espacio de búsqueda de tarea de proxy mnasnet_proxy_task_config_generator, definido en el archivo proxy_task/proxy_task_search_spaces.py, para demostrar cómo puedes definir tu propio espacio de búsqueda:

# 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

En este ejemplo, creamos un espacio de búsqueda simple sobre el porcentaje de datos de entrenamiento 25, 50, 75 y 95 (ten en cuenta que el 100% de los datos de entrenamiento sonno se usa para la búsqueda de etapa 1). La función mnasnet_proxy_task_config_generator toma una plantilla de referencia común de argumentos de Docker de entrenamiento y, luego, los modifica para cada tamaño de datos de entrenamiento de tarea de proxy deseado. Luego, muestra una lista de configuración de tarea de proxy que la herramienta de búsqueda de tarea de proxy procesa más tarde una por una en el mismo orden. Cada archivo de configuración de tarea de proxy tiene name y docker_args_map, que es un mapa clave-valor para los argumentos de Docker de tarea de proxy.

Puedes implementar tu propia definición de espacio de búsqueda según tus propios requisitos y diseñar tus propios espacios de búsqueda de tareas de proxy, incluso para más de las dos dimensiones de datos de entrenamiento reducidos o escala de modelo reducida. Sin embargo, no se recomienda buscar de forma explícita en los pasos de entrenamiento, ya que implica un procesamiento repetido desperdiciado. Permite que la herramienta de búsqueda de tareas del proxy controle esta dimensión por ti.

Para tu primera búsqueda de tareas de proxy, puedes intentar reducir solo los datos de entrenamiento (al igual que el ejemplo MnasNet) y omite la reducción de escala del modelo porque el escalamiento del modelo puede incluir varios parámetros en lugar de image-size, num-filters onum-blocks. En la mayoría de los casos, los datos de entrenamiento reducidos (y la búsqueda implícita en los pasos de entrenamiento reducidos) son suficientes para encontrar una buena tarea de proxy.

Establece la cantidad de pasos de entrenamiento en la cantidad que se usa en el entrenamiento de referencia completo. Existen diferencias entre las configuraciones de entrenamiento completo de etapa 2 y de entrenamiento de tarea de proxy de etapa 1. Para la tarea del proxy, debes reducir el batch-size en comparación con la configuración de entrenamiento del modelo de referencia completo para usar solo 2 GPUs o 4 GPUs. Por lo general, el entrenamiento completo usa 4 GPUs, 8 GPUs o más, pero la tarea de proxy solo usa 2 GPUs o 4 GPUs. Otra diferencia es la división del entrenamiento y la validación. Este es un ejemplo de los cambios de la configuración de MnasNet que van de 4 GPUs para el entrenamiento completo de etapa 2 a 2 GPUs y una división de validación diferente para la búsqueda de tareas de proxy:

Configuración de tareas del proxy

Inicia el trabajo del controlador de búsqueda de la tarea de proxy mediante la ejecución del siguiente comando (necesitas una cuenta de servicio):

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"

Después de iniciar este trabajo del controlador de búsqueda de tarea de proxy, se recibe un vínculo del trabajo. El nombre del trabajo comienza con el prefijo Search_controller_. A continuación, se muestra un ejemplo de una IU de trabajo:

Trabajo de búsqueda de tarea del proxy

search_controller_dir contendrá todos los resultados y puedes verificar los registros si haces clic en el vínculo View logs. Este trabajo usa una CPU de forma predeterminada en la nube para ejecutarse en segundo plano como un trabajo personalizado y, luego, inicia y administra los trabajos NAS secundarios para cada proxy: evaluación de tareas.

Trabajos personalizados frente a NAS

Cada trabajo de NAS de tarea de proxy tiene un nombre como ProxyTask_<your-job-name>_<proxy-task-name>, en el que <proxy-task-name> es lo que proporciona el módulo del generador de configuración de tarea de proxy para cada tarea de proxy. Solo se ejecuta una evaluación de tarea de proxy a la vez. También puedes ejecutar el siguiente comando:

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

Este comando muestra un resumen de todas las evaluaciones de tarea de proxy y el estado actual del trabajo de controlador de búsqueda, el nombre del trabajo y los vínculos para cada evaluación:

{
  "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 almacena el resultado de cada evaluación de tarea de proxy y best_proxy_task_name registra la mejor tarea de proxy para la búsqueda. Cada entrada de tarea de proxy tiene datos adicionales, como proxy_task_stats, que registra el progreso de la correlación de precisión, sus valores de p, la precisión de la mediana y el tiempo de entrenamiento medio en los pasos de entrenamiento. También registra la correlación relacionada con la latencia, si corresponde, y registra el motivo por el que se detiene este trabajo (como el límite de tiempo de entrenamiento excedido) y el paso de entrenamiento en el que se detiene. También puedes ver estas estadísticas como trazados si copias el contenido de search_controller_dir en tu carpeta local mediante la ejecución del siguiente comando:

gsutil -m cp gs://<path to 'search_controller_dir'>/* /your/local/dir

e inspeccionar las imágenes de trazado. Por ejemplo, en el siguiente gráfico, se muestra la correlación de precisión con el tiempo de entrenamiento para la mejor tarea de proxy:

Correlación de precisión-tiempo del entrenamiento

Tu búsqueda se completó y encontraste la mejor configuración de tarea de proxy. Debes hacer lo siguiente:

  • Establece la cantidad de pasos de entrenamiento en el final_training_steps de la tarea del proxy ganador.
  • Configura los pasos de disminución de coseno con el mismo valor que final_training_steps para que la tasa de aprendizaje casi se reduzca a cero en el final.
  • Realiza una evaluación de puntuación de validación al final del entrenamiento, lo que ahorra varios costos de evaluación (opcional).

Si quieres usar un dispositivo de latencia local para la búsqueda de tareas de proxy, ejecuta el comando search_proxy_task sin el Docker de latencia y las marcas de latencia de Docker, ya que no quieres iniciar el Docker de latencia en Google Cloud. A continuación, usa el comando run_latency_calculator_local que se describe en el Instructivo 4 para iniciar el trabajo de calculadora de latencia local. En lugar de pasar la marca --search_job_id, pasa la marca --controller_job_id con el ID numérico del trabajo de búsqueda de tarea de proxy que obtienes después de ejecutar el comando search_proxy_task.

Las siguientes situaciones requieren que reanudes el trabajo del controlador de búsqueda de la tarea de proxy:

  • El trabajo del controlador de búsqueda del proxy y de la tarea principal se apaga (casos poco frecuentes).
  • Cancelas por accidente el trabajo del controlador de búsqueda de la tarea de proxy.
  • Deseas extender el espacio de búsqueda de la tarea de proxy más tarde (incluso después de muchos días).

Primero, no canceles el trabajo de iteración NAS secundario (pestaña NAS) si ya se está ejecutando. Luego, para reanudar el trabajo del controlador de búsqueda de la tarea de proxy superior, ejecuta el comando search_proxy_task como antes, pero esta vez pasa la marca --previous_proxy_task_search_dir y configúrala en el directorio de salida para el trabajo anterior del controlador de búsqueda de tarea de proxy. El trabajo del controlador de búsqueda de la tarea de proxy reanudada carga su estado anterior desde el directorio y continúa funcionando como antes.

Comprobaciones finales

Dos verificaciones finales para la tarea de proxy incluyen un rango de recompensas y guardar datos para el análisis posterior a la búsqueda.

Rango de recompensas

La recompensa que se informa al controlador debe estar dentro del rango [1e-3, 10]. Si este no es el caso, puedes escalar artificialmente la recompensa para lograr este objetivo.

Guarda los datos para realizar análisis posteriores a la búsqueda

El código de la tarea de proxy debe guardar las métricas y los datos adicionales en la ubicación de almacenamiento en la nube, lo que podría ser útil para analizar el espacio de búsqueda más adelante. Nuestra plataforma de búsqueda de arquitectura neuronal solo admite el registro de un máximo de cinco other_metrics de punto flotante. Cualquier métrica adicional debe guardarse en la ubicación de almacenamiento en la nube para realizar análisis posteriores.