การปรับแต่งโมเดลแบบกว้างและลึกโดยใช้ Google Cloud

ดูบน TensorFlow.org ทำงานใน Google Colab ดูบน GitHub ดาวน์โหลดสมุดบันทึก โลโก้คักเกิล วิ่งใน Kaggle

ในตัวอย่างนี้ เราจะใช้ CloudTuner และ Google Cloud เพื่อปรับแต่ง โมเดล Wide และ Deep ตามโมเดลที่ปรับแต่งได้ซึ่งนำมาใช้ใน การเรียนรู้ข้อมูลที่มีโครงสร้างด้วยเครือข่าย Wide, Deep และ Cross ในตัวอย่างนี้ เราจะใช้ชุดข้อมูลจาก CAIIS Dogfood Day

นำเข้าโมดูลที่จำเป็น

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'

การกำหนดค่าโครงการ

การตั้งค่าพารามิเตอร์โครงการ สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับพารามิเตอร์เฉพาะของ Google Cloud โปรดดู คำแนะนำในการตั้งค่าโปรเจ็กต์ 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")

กำลังตรวจสอบสมุดบันทึกเพื่อใช้ Google Cloud Project ของคุณ

สำหรับ Kaggle Notebooks ให้คลิกที่ "Add-ons"->"Google Cloud SDK" ก่อนที่จะเรียกใช้เซลล์ด้านล่าง

# 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

โหลดข้อมูล

อ่านข้อมูลดิบและแยกเพื่อฝึกและทดสอบชุดข้อมูล สำหรับขั้นตอนนี้ คุณจะต้องคัดลอกชุดข้อมูลไปยังที่เก็บข้อมูล GCS เพื่อให้สามารถเข้าถึงได้ระหว่างการฝึก สำหรับตัวอย่างนี้ เราใช้ชุดข้อมูลจาก https://www.kaggle.com/c/caiis-dogfood-day-2020

ในการดำเนินการนี้ ให้เรียกใช้คำสั่งต่อไปนี้เพื่อดาวน์โหลดและคัดลอกชุดข้อมูลไปยังที่เก็บข้อมูล GCS ของคุณ หรือดาวน์โหลดชุดข้อมูลด้วยตนเองผ่าน Kaggle UI และอัปโหลดไฟล์ train.csv ไปยัง ที่เก็บข้อมูล GCS ของคุณผ่าน GCS UI

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

ประมวลผลข้อมูลล่วงหน้า

การตั้งค่าเลเยอร์การประมวลผลล่วงหน้าสำหรับข้อมูลอินพุตที่เป็นหมวดหมู่และตัวเลข สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับการประมวลผลเลเยอร์ล่วงหน้า โปรดดูที่ การทำงานกับเลเยอร์การประมวลผลล่วงหน้า

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)

กำหนดสถาปัตยกรรมโมเดลและไฮเปอร์พารามิเตอร์

ในส่วนนี้ เรากำหนดพารามิเตอร์การปรับแต่งโดยใช้ พารามิเตอร์ Keras Tuner Hyper และฟังก์ชันการสร้างแบบจำลอง ฟังก์ชันการสร้างแบบจำลองใช้อาร์กิวเมนต์ hp ซึ่งคุณสามารถสุ่มตัวอย่างไฮเปอร์พารามิเตอร์ เช่น hp.Int('units', min_value=32, max_value=512, step=32) (จำนวนเต็มจากช่วงที่กำหนด)

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

กำหนดค่า CloudTuner

ในส่วนนี้ เรากำหนดค่าเครื่องรับสัญญาณคลาวด์สำหรับการดำเนินการทั้งระยะไกลและภายในเครื่อง ความแตกต่างที่สำคัญระหว่างทั้งสองคือกลยุทธ์การกระจาย

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)

เริ่มการฝึกอบรมทางไกล

ขั้นตอนนี้จะเตรียมโค้ดของคุณจากสมุดบันทึกนี้สำหรับการดำเนินการระยะไกล และเริ่มการทำงานแบบขนาน NUM_JOBS จากระยะไกลเพื่อฝึกโมเดล เมื่อส่งงานแล้ว คุณจะไปที่ขั้นตอนถัดไปเพื่อติดตามความคืบหน้าของงานผ่าน 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
)

ผลการฝึกอบรม

เชื่อมต่ออินสแตนซ์ Colab อีกครั้ง

งานการฝึกอบรมทางไกลส่วนใหญ่จะใช้เวลานาน หากคุณใช้ Colab อาจหมดเวลาก่อนที่ผลการฝึกอบรมจะพร้อมใช้งาน ในกรณีดังกล่าว ให้เรียกใช้ส่วนต่อไปนี้อีกครั้งเพื่อเชื่อมต่อและกำหนดค่าอินสแตนซ์ Colab อีกครั้งเพื่อเข้าถึงผลการฝึก รันส่วนต่อไปนี้ตามลำดับ:

  1. นำเข้าโมดูลที่จำเป็น
  2. การกำหนดค่าโครงการ
  3. กำลังตรวจสอบสมุดบันทึกเพื่อใช้ Google Cloud Project ของคุณ

โหลดเทนเซอร์บอร์ด

ขณะที่การฝึกอบรมกำลังดำเนินอยู่ คุณสามารถใช้ Tensorboard เพื่อดูผลลัพธ์ได้ โปรดทราบว่าผลลัพธ์จะแสดงหลังจากการฝึกของคุณเริ่มต้นแล้วเท่านั้น นี้อาจใช้เวลาไม่กี่นาที.

%load_ext tensorboard
%tensorboard --logdir $TENSORBOARD_LOGS_DIR

คุณสามารถเข้าถึงเนื้อหาการฝึกอบรมได้ดังต่อไปนี้ โปรดทราบว่าผลลัพธ์จะแสดงหลังจากงานปรับแต่งของคุณเสร็จสิ้นการทดลองใช้อย่างน้อยหนึ่งครั้งเท่านั้น นี้อาจใช้เวลาไม่กี่นาที.

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)