Optimización de varios objetivos

Logotipo de ColabEjecuta este instructivo como un notebook en Colab Logotipo de GitHubVisualiza el notebook en GitHub

En este instructivo, se muestra la optimización de múltiples objetivos de AI Platform Optimizer.

Objetivo

Lo ideal es poder minimize la métrica objetivo: y1 = r*sin(theta)

y, al mismo tiempo, lograr maximize la métrica objetivo: y2 = r*cos(theta)

que evaluarás en el espacio de parámetros:

  • r en [0,1],

  • theta en [0, pi/2]

Costos

En este instructivo, se usan los siguientes componentes facturables de Google Cloud:

  • AI Platform Training
  • Cloud Storage

Obtén información sobre los precios de AI Platform Training y los precios de Cloud Storage. Usa la calculadora de precios para generar una estimación de los costos según el uso previsto.

Dependencias y paquetes de instalación de PIP

Instala dependencias adicionales no instaladas en el entorno del notebook.

  • Usa la versión con disponibilidad general más reciente del framework.
! pip install -U google-api-python-client
! pip install -U google-cloud
! pip install -U google-cloud-storage
! pip install -U requests
! pip install -U matplotlib

# Restart the kernel after pip installs
import IPython
app = IPython.Application.instance()
app.kernel.do_shutdown(True)

Configura el proyecto de Google Cloud

Los siguientes pasos son obligatorios, sin importar el entorno del notebook.

  1. Selecciona o crea un proyecto de Google Cloud.

  2. Asegúrate de tener habilitada la facturación para tu proyecto.

  3. Habilita las API de AI Platform.

  4. Si lo ejecutas de forma local en tu máquina, deberás instalar el SDK de Google Cloud.

  5. Ingresa el ID del proyecto en la celda a continuación. Luego, ejecuta la celda a fin de asegurarte de que el SDK de Cloud use el proyecto correcto para todos los comandos de este notebook.

Nota: Jupyter ejecuta líneas con el prefijo ! como comandos de shell y, luego, interpola las variables de Python con el prefijo $ en estos comandos.

PROJECT_ID = "[project-id]" #@param {type:"string"}
! gcloud config set project $PROJECT_ID

Autentica la cuenta de Google Cloud

Si usas AI Platform Notebooks, tu entorno ya está autenticado. Omite estos pasos.

import sys

# If you are running this notebook in Colab, run this cell and follow the
# instructions to authenticate your Google Cloud account. This provides access
# to your Cloud Storage bucket and lets you submit training jobs and prediction
# requests.

if 'google.colab' in sys.modules:
    from google.colab import auth as google_auth
    google_auth.authenticate_user()

# If you are running this tutorial in a notebook locally, replace the string
# below with the path to your service account key and run this cell to
# authenticate your Google Cloud account.
else:
    %env GOOGLE_APPLICATION_CREDENTIALS your_path_to_credentials.json

# Log in to your account on Google Cloud
!gcloud auth login

Importa las bibliotecas

import json
import time
import datetime
from googleapiclient import errors

Instructivo

Configuración

En esta sección, se definen algunos parámetros y métodos de utilidades para llamar a las API de AI Platform Optimizer. Completa la siguiente información para comenzar.

# Update to your username
USER = '[user-id]' #@param {type: 'string'}

# These will be automatically filled in.
STUDY_ID = '{}_study_{}'.format(USER, datetime.datetime.now().strftime('%Y%m%d_%H%M%S')) #@param {type: 'string'}
REGION = 'us-central1'
def study_parent():
  return 'projects/{}/locations/{}'.format(PROJECT_ID, REGION)

def study_name(study_id):
  return 'projects/{}/locations/{}/studies/{}'.format(PROJECT_ID, REGION, study_id)

def trial_parent(study_id):
  return study_name(study_id)

def trial_name(study_id, trial_id):
  return 'projects/{}/locations/{}/studies/{}/trials/{}'.format(PROJECT_ID, REGION,
                                                                study_id, trial_id)

def operation_name(operation_id):
  return 'projects/{}/locations/{}/operations/{}'.format(PROJECT_ID, REGION, operation_id)

print('USER: {}'.format(USER))
print('PROJECT_ID: {}'.format(PROJECT_ID))
print('REGION: {}'.format(REGION))
print('STUDY_ID: {}'.format(STUDY_ID))

Compila el cliente de la API

Mediante la siguiente celda, se compila el cliente de la API generado de manera automática con el servicio de descubrimiento de API de Google. El esquema de la API con formato JSON se aloja en un bucket de Cloud Storage.

from google.cloud import storage
from googleapiclient import discovery

_OPTIMIZER_API_DOCUMENT_BUCKET = 'caip-optimizer-public'
_OPTIMIZER_API_DOCUMENT_FILE = 'api/ml_public_google_rest_v1.json'

def read_api_document():
  client = storage.Client(PROJECT_ID)
  bucket = client.get_bucket(_OPTIMIZER_API_DOCUMENT_BUCKET)
  blob = bucket.get_blob(_OPTIMIZER_API_DOCUMENT_FILE)
  return blob.download_as_string()

ml = discovery.build_from_document(service=read_api_document())
print('Successfully built the client.')

Crea la configuración del estudio

La siguiente es una configuración de estudio de muestra creada como un diccionario de Python jerárquico. Ya se completó. Ejecuta la celda para configurar el estudio.

# Parameter Configuration
param_r = {
    'parameter': 'r',
    'type' : 'DOUBLE',
    'double_value_spec' : {
        'min_value' : 0,
        'max_value' : 1
    }
}

param_theta = {
    'parameter': 'theta',
    'type' : 'DOUBLE',
    'double_value_spec' : {
        'min_value' : 0,
        'max_value' : 1.57
    }
}

# Objective Metrics
metric_y1 = {
    'metric' : 'y1',
    'goal' : 'MINIMIZE'
}

metric_y2 = {
    'metric' : 'y2',
    'goal' : 'MAXIMIZE'
}

# Put it all together in a study configuration
study_config = {
    'algorithm' : 'ALGORITHM_UNSPECIFIED',  # Let the service choose the `default` algorithm.
    'parameters' : [param_r, param_theta,],
    'metrics' : [metric_y1, metric_y2,],
}

study = {'study_config': study_config}
print(json.dumps(study, indent=2, sort_keys=True))

Crea el estudio

A continuación, crea el estudio que luego ejecutarás para optimizar los dos objetivos.

# Creates a study
req = ml.projects().locations().studies().create(
    parent=study_parent(), studyId=STUDY_ID, body=study)
try :
  print(req.execute())
except errors.HttpError as e:
  if e.resp.status == 409:
    print('Study already existed.')
  else:
    raise e

Funciones de evaluación de métricas

Luego, definirás algunas funciones para evaluar las dos métricas objetivo.

import math

# r * sin(theta)
def Metric1Evaluation(r, theta):
  """Evaluate the first metric on the trial."""
  return r * math.sin(theta)

# r * cose(theta)
def Metric2Evaluation(r, theta):
  """Evaluate the second metric on the trial."""
  return r * math.cos(theta)

def CreateMeasurement(trial_id, r, theta):
  print(("=========== Start Trial: [{0}] =============").format(trial_id))

  # Evaluate both objective metrics for this trial
  y1 = Metric1Evaluation(r, theta)
  y2 = Metric2Evaluation(r, theta)
  print('[r = {0}, theta = {1}] => y1 = r*sin(theta) = {2}, y2 = r*cos(theta) = {3}'.format(r, theta, y1, y2))
  metric1 = {'metric': 'y1', 'value': y1}
  metric2 = {'metric': 'y2', 'value': y2}

  # Return the results for this trial
  measurement = {'step_count': 1, 'metrics': [metric1, metric2,]}
  return measurement

Establece parámetros de configuración para ejecutar pruebas

client_id: El identificador del cliente que solicita la sugerencia. Si varias SuggestTrialsRequests tienen el mismo client_id, el servicio mostrará la prueba sugerida idéntica si esta está PENDING y proporcionará una prueba nueva si se completó la última sugerida.

suggestion_count_per_request: La cantidad de sugerencias (pruebas) solicitadas en una sola solicitud.

max_trial_id_to_stop: La cantidad de pruebas que se deben explorar antes de detenerse. Se estableció en 4 para acortar el tiempo de ejecución del código, por lo que no se espera que haya convergencia. Para que haya convergencia, es más probable que se necesite un valor de alrededor de 20 (una buena regla general es multiplicar la dimensionalidad total por 10).

client_id = 'client1' #@param {type: 'string'}
suggestion_count_per_request =  5 #@param {type: 'integer'}
max_trial_id_to_stop =  50 #@param {type: 'integer'}

print('client_id: {}'.format(client_id))
print('suggestion_count_per_request: {}'.format(suggestion_count_per_request))
print('max_trial_id_to_stop: {}'.format(max_trial_id_to_stop))

Ejecuta pruebas de AI Platform Optimizer

Ejecuta las pruebas.

trial_id = 0
while trial_id < max_trial_id_to_stop:
  # Requests trials.
  resp = ml.projects().locations().studies().trials().suggest(
    parent=trial_parent(STUDY_ID),
    body={'client_id': client_id, 'suggestion_count': suggestion_count_per_request}).execute()
  op_id = resp['name'].split('/')[-1]

  # Polls the suggestion long-running operations.
  get_op = ml.projects().locations().operations().get(name=operation_name(op_id))
  while True:
      operation = get_op.execute()
      if 'done' in operation and operation['done']:
        break
      time.sleep(1)

  for suggested_trial in get_op.execute()['response']['trials']:
    trial_id = int(suggested_trial['name'].split('/')[-1])
    # Featches the suggested trials.
    trial = ml.projects().locations().studies().trials().get(name=trial_name(STUDY_ID, trial_id)).execute()
    if trial['state'] in ['COMPLETED', 'INFEASIBLE']:
      continue

    # Parses the suggested parameters.
    params = {}
    for param in trial['parameters']:
      if param['parameter'] == 'r':
        r = param['floatValue']
      elif param['parameter'] == 'theta':
        theta = param['floatValue']

    # Evaluates trials and reports measurement.
    ml.projects().locations().studies().trials().addMeasurement(
        name=trial_name(STUDY_ID, trial_id),
        body={'measurement': CreateMeasurement(trial_id, r, theta)}).execute()
    # Completes the trial.
    ml.projects().locations().studies().trials().complete(
        name=trial_name(STUDY_ID, trial_id)).execute()

Visualiza el resultado (experimental)

En esta sección, se proporciona un módulo para visualizar las pruebas del estudio anterior.

max_trials_to_annotate = 20

import matplotlib.pyplot as plt
trial_ids = []
y1 = []
y2 = []
resp = ml.projects().locations().studies().trials().list(parent=trial_parent(STUDY_ID)).execute()
for trial in resp['trials']:
  if 'finalMeasurement' in trial:
    trial_ids.append(int(trial['name'].split('/')[-1]))
    metrics = trial['finalMeasurement']['metrics']
    try:
        y1.append([m for m in metrics if m['metric'] == "y1"][0]['value'])
        y2.append([m for m in metrics if m['metric'] == "y2"][0]['value'])
    except:
        pass

fig, ax = plt.subplots()
ax.scatter(y1, y2)
plt.xlabel("y1=r*sin(theta)")
plt.ylabel("y2=r*cos(theta)");
for i, trial_id in enumerate(trial_ids):
  # Only annotates the last `max_trials_to_annotate` trials
  if i > len(trial_ids) - max_trials_to_annotate:
    try:
        ax.annotate(trial_id, (y1[i], y2[i]))
    except:
        pass
plt.gcf().set_size_inches((16, 16))

Realice una limpieza

Para limpiar todos los recursos de Google Cloud que se usaron en este proyecto, puedes borrar el proyecto de Google Cloud que usaste para el instructivo.