Strojenie szerokiego i głębokiego modelu za pomocą Google Cloud

Zobacz na TensorFlow.org Uruchom w Google Colab Zobacz na GitHubie Pobierz notatnik Logo Kaggle'aBiegaj w Kaggle

W tym przykładzie użyjemy CloudTuner i Google Cloud do dostrojenia szerokiego i głębokiego modelu w oparciu o przestrajalny model wprowadzony w uczeniu się danych strukturalnych w sieciach szerokich, głębokich i krzyżowych . W tym przykładzie użyjemy zestawu danych z CAIIS Dogfood Day

Zaimportuj wymagane moduły

import datetime
import uuid

import numpy as np
import pandas as pd
import tensorflow as tf
import os
import sys
import subprocess

from tensorflow.keras import datasets, layers, models
from sklearn.model_selection import train_test_split

# Install the latest version of tensorflow_cloud and other required packages.
if os.environ.get("TF_KERAS_RUNNING_REMOTELY", True):
    subprocess.run(
        ['python3', '-m', 'pip', 'install', 'tensorflow-cloud', '-q'])
    subprocess.run(
        ['python3', '-m', 'pip', 'install', 'google-cloud-storage', '-q'])
    subprocess.run(
        ['python3', '-m', 'pip', 'install', 'fsspec', '-q'])
    subprocess.run(
        ['python3', '-m', 'pip', 'install', 'gcsfs', '-q'])

import tensorflow_cloud as tfc
print(tfc.__version__)
0.1.15
tf.version.VERSION
'2.6.0'

Konfiguracje projektu

Ustawianie parametrów projektu. Aby uzyskać więcej informacji na temat parametrów specyficznych dla Google Cloud, zapoznaj się z instrukcjami konfiguracji projektu Google Cloud .

# Set Google Cloud Specific parameters

# TODO: Please set GCP_PROJECT_ID to your own Google Cloud project ID.
GCP_PROJECT_ID = 'YOUR_PROJECT_ID' 

# TODO: Change the Service Account Name to your own Service Account
SERVICE_ACCOUNT_NAME = 'YOUR_SERVICE_ACCOUNT_NAME'
SERVICE_ACCOUNT = f'{SERVICE_ACCOUNT_NAME}@{GCP_PROJECT_ID}.iam.gserviceaccount.com'

# TODO: set GCS_BUCKET to your own Google Cloud Storage (GCS) bucket.
GCS_BUCKET = 'YOUR_GCS_BUCKET_NAME'

# DO NOT CHANGE: Currently only the 'us-central1' region is supported.
REGION = 'us-central1'
# Set Tuning Specific parameters

# OPTIONAL: You can change the job name to any string.
JOB_NAME = 'wide_and_deep'

# OPTIONAL: Set Number of concurrent tuning jobs that you would like to run.
NUM_JOBS = 5

# TODO: Set the study ID for this run. Study_ID can be any unique string.
# Reusing the same Study_ID will cause the Tuner to continue tuning the
# Same Study parameters. This can be used to continue on a terminated job,
# or load stats from a previous study.
STUDY_NUMBER = '00001'
STUDY_ID = f'{GCP_PROJECT_ID}_{JOB_NAME}_{STUDY_NUMBER}'

# Setting location were training logs and checkpoints will be stored
GCS_BASE_PATH = f'gs://{GCS_BUCKET}/{JOB_NAME}/{STUDY_ID}'
TENSORBOARD_LOGS_DIR = os.path.join(GCS_BASE_PATH,"logs")

Uwierzytelnianie notatnika w celu korzystania z projektu Google Cloud

W przypadku notesów Kaggle kliknij „Dodatki” -> „Google Cloud SDK” przed uruchomieniem poniższej komórki.

# Using tfc.remote() to ensure this code only runs in notebook
if not tfc.remote():

    # Authentication for Kaggle Notebooks
    if "kaggle_secrets" in sys.modules:
        from kaggle_secrets import UserSecretsClient
        UserSecretsClient().set_gcloud_credentials(project=GCP_PROJECT_ID)

    # Authentication for Colab Notebooks
    if "google.colab" in sys.modules:
        from google.colab import auth
        auth.authenticate_user()
        os.environ["GOOGLE_CLOUD_PROJECT"] = GCP_PROJECT_ID

Załaduj dane

Odczytuj surowe dane i dziel je, aby trenować i testować zestawy danych. Na tym etapie musisz skopiować zbiór danych do zasobnika GCS, aby można było uzyskać do niego dostęp podczas szkolenia. W tym przykładzie używamy zbioru danych z https://www.kaggle.com/c/caiis-dogfood-day-2020

Aby to zrobić, możesz uruchomić następujące polecenia, aby pobrać i skopiować zbiór danych do zasobnika GCS lub ręcznie pobrać zbiór danych za pomocą interfejsu użytkownika Kaggle i przesłać plik train.csv do zasobnika GCS za pomocą interfejsu użytkownika GCS .

# Download the dataset
kaggle competitions download -c caiis-dogfood-day-2020

# Copy the training file to your bucket
gsutil cp ./caiis-dogfood-day-2020/train.csv $GCS_BASE_PATH/caiis-dogfood-day-2020/train.csv
train_URL = f'{GCS_BASE_PATH}/caiis-dogfood-day-2020/train.csv'
data = pd.read_csv(train_URL)
train, test = train_test_split(data, test_size=0.1)
# A utility method to create a tf.data dataset from a Pandas Dataframe
def df_to_dataset(df, shuffle=True, batch_size=32):
  df = df.copy()
  labels = df.pop('target')
  ds = tf.data.Dataset.from_tensor_slices((dict(df), labels))
  if shuffle:
    ds = ds.shuffle(buffer_size=len(df))
  ds = ds.batch(batch_size)
  return ds
sm_batch_size = 1000  # A small batch size is used for demonstration purposes
train_ds = df_to_dataset(train, batch_size=sm_batch_size)
test_ds = df_to_dataset(test, shuffle=False, batch_size=sm_batch_size)

Wstępnie przetwórz dane

Konfigurowanie warstw wstępnego przetwarzania danych wejściowych kategorycznych i liczbowych. Więcej szczegółów na temat warstw przetwarzania wstępnego można znaleźć w artykule Praca z warstwami przetwarzania wstępnego .

from tensorflow.keras.layers.experimental import preprocessing

def create_model_inputs():
    inputs ={}
    for name, column in data.items():
        if name in ('id','target'):
            continue
        dtype = column.dtype
        if dtype == object:
            dtype = tf.string
        else:
            dtype = tf.float32

        inputs[name] = tf.keras.Input(shape=(1,), name=name, dtype=dtype)

    return inputs
#Preprocessing the numeric inputs, and running them through a normalization layer.
def preprocess_numeric_inputs(inputs):

    numeric_inputs = {name:input for name,input in inputs.items()
                      if input.dtype==tf.float32}

    x = layers.Concatenate()(list(numeric_inputs.values()))
    norm = preprocessing.Normalization()
    norm.adapt(np.array(data[numeric_inputs.keys()]))
    numeric_inputs = norm(x)
    return numeric_inputs
# Preprocessing the categorical inputs.
def preprocess_categorical_inputs(inputs):
    categorical_inputs = []
    for name, input in inputs.items():
        if input.dtype == tf.float32:
            continue

        lookup = preprocessing.StringLookup(vocabulary=np.unique(data[name]))
        one_hot = preprocessing.CategoryEncoding(max_tokens=lookup.vocab_size())

        x = lookup(input)
        x = one_hot(x)
        categorical_inputs.append(x)

    return layers.concatenate(categorical_inputs)

Zdefiniuj architekturę modelu i hiperparametry

W tej sekcji definiujemy nasze parametry strojenia za pomocą Keras Tuner Hyper Parameters i funkcji budowania modelu. Funkcja budowania modelu przyjmuje argument hp, z którego można próbkować hiperparametry, takie jak hp.Int('units', min_value=32, max_value=512, step=32) (liczba całkowita z określonego zakresu).

import kerastuner

# Configure the search space
HPS = kerastuner.engine.hyperparameters.HyperParameters()
HPS.Float('learning_rate', min_value=1e-4, max_value=1e-2, sampling='log')

HPS.Int('num_layers', min_value=2, max_value=5)
for i in range(5):
    HPS.Float('dropout_rate_' + str(i), min_value=0.0, max_value=0.3, step=0.1)
    HPS.Choice('num_units_' + str(i), [32, 64, 128, 256])
from tensorflow.keras import layers
from tensorflow.keras.optimizers import Adam


def create_wide_and_deep_model(hp):

    inputs = create_model_inputs()
    wide = preprocess_categorical_inputs(inputs)
    wide = layers.BatchNormalization()(wide)

    deep = preprocess_numeric_inputs(inputs)
    for i in range(hp.get('num_layers')):
        deep = layers.Dense(hp.get('num_units_' + str(i)))(deep)
        deep = layers.BatchNormalization()(deep)
        deep = layers.ReLU()(deep)
        deep = layers.Dropout(hp.get('dropout_rate_' + str(i)))(deep)

    both = layers.concatenate([wide, deep])
    outputs = layers.Dense(1, activation='sigmoid')(both)
    model = tf.keras.Model(inputs=inputs, outputs=outputs)
    metrics = [
        tf.keras.metrics.Precision(name='precision'),
        tf.keras.metrics.Recall(name='recall'),
        'accuracy',
        'mse'
    ]

    model.compile(
        optimizer=Adam(lr=hp.get('learning_rate')),
        loss='binary_crossentropy',
        metrics=metrics)
    return model

Skonfiguruj CloudTuner

W tej sekcji konfigurujemy tuner chmurowy zarówno do wykonywania zdalnego, jak i lokalnego. Główną różnicą między nimi jest strategia dystrybucji.

from tensorflow_cloud import CloudTuner

distribution_strategy = None
if not tfc.remote():
    # Using MirroredStrategy to use a single instance with multiple GPUs
    # during remote execution while using no strategy for local.
    distribution_strategy = tf.distribute.MirroredStrategy()

tuner = CloudTuner(
    create_wide_and_deep_model,
    project_id=GCP_PROJECT_ID,
    project_name=JOB_NAME,
    region=REGION,
    objective='accuracy',
    hyperparameters=HPS,
    max_trials=100,
    directory=GCS_BASE_PATH,
    study_id=STUDY_ID,
    overwrite=True,
    distribution_strategy=distribution_strategy)
# Configure Tensorboard logs
callbacks=[
    tf.keras.callbacks.TensorBoard(log_dir=TENSORBOARD_LOGS_DIR)]

# Setting to run tuning remotely, you can run tuner locally to validate it works first.
if tfc.remote():
    tuner.search(train_ds, epochs=20, validation_data=test_ds, callbacks=callbacks)

# You can uncomment the code below to run the tuner.search() locally to validate
# everything works before submitting the job to Cloud. Stop the job manually
# after one epoch.

# else:
#     tuner.search(train_ds, epochs=1, validation_data=test_ds, callbacks=callbacks)

Rozpocznij zdalne szkolenie

Ten krok spowoduje przygotowanie kodu z tego notatnika do zdalnego wykonania i zdalne uruchomienie równoległych uruchomień NUM_JOBS w celu uczenia modelu. Po przesłaniu zadań możesz przejść do następnego kroku i monitorować postęp zadań za pośrednictwem Tensorboard.

tfc.run_cloudtuner(
    distribution_strategy='auto',
    docker_config=tfc.DockerConfig(
        image_build_bucket=GCS_BUCKET
        ),
    chief_config=tfc.MachineConfig(
        cpu_cores=16,
        memory=60,
    ),
    job_labels={'job': JOB_NAME},
    service_account=SERVICE_ACCOUNT,
    num_jobs=NUM_JOBS
)

Wyniki szkolenia

Podłącz ponownie instancję Colab

Większość zdalnych zadań szkoleniowych trwa długo. Jeśli korzystasz z Colab, może upłynąć limit czasu, zanim wyniki szkolenia będą dostępne. W takim przypadku uruchom ponownie poniższe sekcje, aby ponownie połączyć się i skonfigurować instancję Colab w celu uzyskania dostępu do wyników uczenia. Uruchom następujące sekcje w kolejności:

  1. Zaimportuj wymagane moduły
  2. Konfiguracje projektu
  3. Uwierzytelnianie notatnika w celu korzystania z projektu Google Cloud

Załaduj Tensorboard

W trakcie szkolenia możesz przeglądać wyniki za pomocą Tensorboardu. Pamiętaj, że wyniki pojawią się dopiero po rozpoczęciu treningu. Może to potrwać kilka minut.

%load_ext tensorboard
%tensorboard --logdir $TENSORBOARD_LOGS_DIR

Dostęp do zasobów szkoleniowych można uzyskać w następujący sposób. Pamiętaj, że wyniki zostaną wyświetlone dopiero po zakończeniu zadania strojenia przynajmniej raz w trybie próbnym. Może to potrwać kilka minut.

if not tfc.remote():
    tuner.results_summary(1)
    best_model = tuner.get_best_models(1)[0]
    best_hyperparameters = tuner.get_best_hyperparameters(1)[0]

    # References to best trial assets
    best_trial_id = tuner.oracle.get_best_trials(1)[0].trial_id
    best_trial_dir = tuner.get_trial_dir(best_trial_id)