Ottimizzazione di più obiettivi

Logo Colab Esegui questo tutorial come blocco note in Colab Logo di GitHubVisualizza il blocco note su GitHub

Questo tutorial illustra l'ottimizzazione multi-obiettivo dello strumento di ottimizzazione di AI Platform.

Scopo

L'obiettivo è minimize la metrica dell'obiettivo: y1 = r*sin(theta)

e contemporaneamente maximize la metrica obiettivo: y2 = r*cos(theta)

che valuterai sullo spazio dei parametri:

  • r in [0,1],

  • theta a [0, pi/2]

Costi

Questo tutorial utilizza i componenti fatturabili di Google Cloud:

  • AI Platform Training
  • Cloud Storage

Scopri di più sui prezzi di AI Platform Training e sui prezzi di Cloud Storage e utilizza il Calcolatore prezzi per generare una stima dei costi in base all'utilizzo previsto.

Pacchetti di installazione e dipendenze PIP

Installa le dipendenze aggiuntive non installate nell'ambiente del blocco note.

  • Utilizzare la versione GA principale più recente 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 il tuo progetto Google Cloud

I passaggi seguenti sono obbligatori, indipendentemente dall'ambiente del blocco note.

  1. Seleziona o crea un progetto Google Cloud.

  2. Assicurati che la fatturazione sia abilitata per il progetto.

  3. Abilita le API AI Platform

  4. Se l'esecuzione avviene localmente sulla tua macchina, devi installare Google Cloud SDK.

  5. Inserisci l'ID progetto nella cella seguente. Poi esegui la cella per assicurarti che Cloud SDK usi il progetto corretto per tutti i comandi in questo blocco note.

Nota: Jupyter esegue le righe con prefisso ! come comandi della shell e interpola le variabili Python con prefisso $ in questi comandi.

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

Autentica l'account Google Cloud

Se utilizzi AI Platform Notebooks, il tuo ambiente è già autenticato. Salta questi passaggi.

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 librerie

import json
import time
import datetime
from googleapiclient import errors

Tutorial

Configurazione

Questa sezione definisce alcuni parametri e metodi util per chiamare le API AI Platform Analyzer. Inserisci le seguenti informazioni per iniziare.

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

Crea il client API

La cella seguente crea il client API generato automaticamente utilizzando il servizio di rilevamento delle API di Google. Lo schema API in formato JSON è ospitato in un bucket 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 configurazione di studio

Di seguito è riportato un esempio di configurazione di studio, creato come dizionario Python gerarchico. È già compilato. Esegui la cella per configurare lo studio.

# 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 lo studio

Poi crea lo studio, che eseguirai in seguito per ottimizzare i due obiettivi.

# 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

Funzioni di valutazione delle metriche

Successivamente, definisci alcune funzioni per valutare le due metriche obiettivo.

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

Imposta i parametri di configurazione per l'esecuzione delle prove

client_id: l'identificatore del cliente che richiede il suggerimento. Se più richieste SuggestTrialsRequest hanno lo stesso client_id, il servizio restituisce la prova identica suggerita se la prova è PENDING e fornisce una nuova prova se l'ultima prova suggerita è stata completata.

suggestion_count_per_request: il numero di suggerimenti (prove) richiesti in una singola richiesta.

max_trial_id_to_stop: il numero di prove da esplorare prima di fermarsi. È impostato su 4 per ridurre il tempo di esecuzione del codice, quindi non aspettarti convergenza. Per la convergenza, sarebbe probabilmente necessario essere circa 20 (una buona regola generale è moltiplicare la dimensionalità totale per 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))

Esecuzione di prove di AI Platform ottimizzato

Esegui le prove.

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

[SPERIMENTALE] Visualizza il risultato

Questa sezione fornisce un modulo per visualizzare le prove per lo studio sopra indicato.

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

Eseguire la pulizia

Per eseguire la pulizia di tutte le risorse Google Cloud utilizzate in questo progetto, puoi eliminare il progetto Google Cloud che hai utilizzato per il tutorial.