Cloud AI Platform पर PyTorch मॉडल को ट्यून करने वाली ट्रेनिंग और हाइपर पैरामीटर

1. खास जानकारी

इस लैब में, आपको Google Cloud पर एमएल ट्रेनिंग के पूरे वर्कफ़्लो के बारे में बताया जाएगा. साथ ही, PyTorch का इस्तेमाल करके अपना मॉडल बनाने का तरीका भी बताया जाएगा. Cloud AI Platform Notebooks एनवायरमेंट में, आपको ट्रेनिंग जॉब को पैकेज करने का तरीका बताया जाएगा. इससे, हाइपरपैरामीटर ट्यूनिंग के साथ AI Platform Training पर ट्रेनिंग जॉब को चलाया जा सकेगा.

आपको क्या सीखने को मिलेगा

आपको, इनके बारे में जानकारी मिलेगी:

  • AI Platform Notebooks का इंस्टेंस बनाना
  • PyTorch मॉडल बनाना
  • AI Platform Training पर हाइपरपैरामीटर ट्यूनिंग की मदद से अपने मॉडल को ट्रेन करना

इस लैब को Google Cloud पर चलाने की कुल लागत करीब 1 डॉलर है.

2. अपना एनवायरमेंट सेट अप करना

इस कोडलैब को चलाने के लिए, आपके पास बिलिंग की सुविधा वाला Google Cloud Platform प्रोजेक्ट होना चाहिए. प्रोजेक्ट बनाने के लिए, यहां दिए गए निर्देशों का पालन करें.

पहला चरण: Cloud AI Platform Models API को चालू करना

Cloud Console में AI Platform Models सेक्शन पर जाएं. अगर यह सुविधा पहले से चालू नहीं है, तो 'चालू करें' पर क्लिक करें.

d0d38662851c6af3.png

दूसरा चरण: Compute Engine API चालू करना

Compute Engine पर जाएं. अगर यह पहले से चालू नहीं है, तो चालू करें को चुनें. आपको नोटबुक इंस्टेंस बनाने के लिए इसकी ज़रूरत होगी.

तीसरा चरण: AI Platform Notebooks का इंस्टेंस बनाना

Cloud Console के AI Platform Notebooks सेक्शन पर जाएं और नया इंस्टेंस पर क्लिक करें. इसके बाद, PyTorch का नया इंस्टेंस टाइप चुनें (बिना जीपीयू के):

892b7588f940d145.png

डिफ़ॉल्ट विकल्पों का इस्तेमाल करें या अपनी पसंद का कोई नाम डालें. इसके बाद, बनाएं पर क्लिक करें. इंस्टेंस बन जाने के बाद, JupyterLab खोलें को चुनें:

63d2cf44801c2df5.png

इसके बाद, लॉन्चर से Python 3 Notebook इंस्टेंस खोलें:

de4c86c6c7f9438f.png

अब आप इसका इस्तेमाल शुरू कर सकते हैं!

पांचवां चरण: Python पैकेज इंपोर्ट करना

अपनी नोटबुक की पहली सेल में, यहां दिए गए इंपोर्ट जोड़ें और सेल को चलाएं. इसे चलाने के लिए, सबसे ऊपर मौजूद मेन्यू में जाकर राइट ऐरो बटन दबाएं या command-enter दबाएं:

import datetime
import numpy as np
import os
import pandas as pd
import time

आपको दिखेगा कि हम यहां PyTorch को इंपोर्ट नहीं कर रहे हैं. ऐसा इसलिए है, क्योंकि हम ट्रेनिंग के काम को AI Platform Training पर चला रहे हैं, न कि अपने Notebook इंस्टेंस से.

3. ट्रेनिंग जॉब के लिए पैकेज बनाना

AI Platform Training पर ट्रेनिंग का काम करने के लिए, हमें अपने ट्रेनिंग कोड को Notebooks इंस्टेंस में स्थानीय तौर पर पैकेज करना होगा. साथ ही, हमें Cloud Storage बकेट की ज़रूरत होगी, ताकि हम अपने काम के लिए ऐसेट सेव कर सकें. सबसे पहले, हम एक स्टोरेज बकेट बनाएंगे. अगर आपके पास पहले से ही कोई खाता है, तो इस चरण को छोड़ा जा सकता है.

पहला चरण: हमारे मॉडल के लिए Cloud Storage बकेट बनाना

सबसे पहले, कुछ एनवायरमेंट वैरिएबल तय करते हैं. इनका इस्तेमाल हम बाकी कोडलैब में करेंगे. यहां दी गई वैल्यू में, अपने Google Cloud प्रोजेक्ट का नाम और उस क्लाउड स्टोरेज बकेट का नाम डालें जिसे आपको बनाना है. यह नाम सबसे अलग (ग्लोबली यूनीक) होना चाहिए:

# Update these to your own GCP project, model, and version names
GCP_PROJECT = 'your-gcp-project'
BOCKET_URL = 'gs://storage_bucket_name'

अब हम स्टोरेज बकेट बनाने के लिए तैयार हैं. ट्रेनिंग का काम शुरू करते समय, हम इसी बकेट का इस्तेमाल करेंगे.

बकेट बनाने के लिए, अपनी नोटबुक में यह gsutil कमांड चलाएं:

!gsutil mb $BUCKET_URL

दूसरा चरण: Python पैकेज के लिए शुरुआती फ़ाइलें बनाना

AI Platform पर ट्रेनिंग जॉब चलाने के लिए, हमें अपने कोड को Python पैकेज के तौर पर कॉन्फ़िगर करना होगा. इसमें हमारी रूट डायरेक्ट्री में मौजूद एक setup.py फ़ाइल होती है. यह फ़ाइल, बाहरी पैकेज की किसी भी डिपेंडेंसी के बारे में बताती है. इसमें हमारे पैकेज के नाम वाली एक सबडायरेक्ट्री होती है. यहां हम इसे trainer/ कहेंगे. साथ ही, इस सबडायरेक्ट्री में एक खाली __init__.py फ़ाइल होती है.

सबसे पहले, setup.py फ़ाइल लिखते हैं. हम फ़ाइल को अपने इंस्टेंस में सेव करने के लिए, iPython %%writefile मैजिक का इस्तेमाल कर रहे हैं. यहां हमने तीन बाहरी लाइब्रेरी के बारे में बताया है. इनका इस्तेमाल हम ट्रेनिंग कोड में करेंगे: PyTorch, Scikit-learn, और Pandas:

%%writefile setup.py
from setuptools import find_packages
from setuptools import setup

REQUIRED_PACKAGES = ['torch>=1.5', 'scikit-learn>=0.20', 'pandas>=1.0']

setup(
    name='trainer',
    version='0.1',
    install_requires=REQUIRED_PACKAGES,
    packages=find_packages(),
    include_package_data=True,
    description='My training application package.'
)

इसके बाद, हम trainer/ डायरेक्ट्री और इसके अंदर खाली init.py फ़ाइल बनाएंगे. Python इस फ़ाइल का इस्तेमाल यह पहचानने के लिए करता है कि यह एक पैकेज है:

!mkdir trainer
!touch trainer/__init__.py

अब हम ट्रेनिंग जॉब बनाना शुरू कर सकते हैं.

4. डेटासेट की झलक देखना

इस लैब का फ़ोकस, मॉडल को ट्रेनिंग देने के लिए इस्तेमाल होने वाले टूल पर है. हालांकि, आइए हम उस डेटासेट पर एक नज़र डालें जिसका इस्तेमाल हम अपने मॉडल को ट्रेनिंग देने के लिए करेंगे, ताकि हम उसे समझ सकें. हम BigQuery में उपलब्ध जन्मदर डेटासेट का इस्तेमाल करेंगे. इसमें अमेरिका में कई दशकों का जन्म से जुड़ा डेटा शामिल है. हम बच्चे के जन्म के समय के वज़न का अनुमान लगाने के लिए, डेटासेट के कुछ कॉलम का इस्तेमाल करेंगे. ओरिजनल डेटासेट काफ़ी बड़ा है. हम इसके सबसेट का इस्तेमाल करेंगे. हमने इसे Cloud Storage बकेट में आपके लिए उपलब्ध कराया है.

पहला चरण: BigQuery का जन्मदर डेटासेट डाउनलोड करना

आइए, Cloud Storage में आपके लिए उपलब्ध कराए गए डेटासेट के वर्शन को Pandas DataFrame में डाउनलोड करें और उसका पूर्वावलोकन करें.

natality = pd.read_csv('https://storage.googleapis.com/ml-design-patterns/natality.csv')
natality.head()

इस डेटासेट में 1,000,000 से कुछ कम लाइनें हैं. हम बच्चे के जन्म के समय के वज़न का अनुमान लगाने के लिए, पांच सुविधाओं का इस्तेमाल करेंगे: मां और पिता की उम्र, गर्भधारण के हफ़्ते, मां का वज़न पाउंड में बढ़ना, और बच्चे का लिंग, जिसे बूलियन के तौर पर दिखाया गया है.

5. हाइपरपैरामीटर ट्यूनिंग के साथ ट्रेनिंग जॉब तय करना

हम अपनी ट्रेनिंग स्क्रिप्ट को trainer/ सबडायरेक्ट्री में मौजूद model.py नाम की फ़ाइल में लिखेंगे. इस सबडायरेक्ट्री को हमने पहले बनाया था. हमारी ट्रेनिंग जॉब, AI Platform Training पर चलेगी. साथ ही, यह AI Platform की हाइपरपैरामीटर ट्यूनिंग सेवा का इस्तेमाल करेगी, ताकि हमारे मॉडल के लिए सबसे सही हाइपरपैरामीटर मिल सकें. इसके लिए, यह बायेज़ियन ऑप्टिमाइज़ेशन का इस्तेमाल करेगी.

पहला चरण: ट्रेनिंग स्क्रिप्ट बनाना

सबसे पहले, ट्रेनिंग स्क्रिप्ट वाली Python फ़ाइल बनाते हैं. इसके बाद, हम यह देखेंगे कि इसमें क्या हो रहा है. %%writefile कमांड चलाने पर, मॉडल कोड को लोकल Python फ़ाइल में लिखा जाएगा:

%%writefile trainer/model.py
import argparse
import hypertune
import numpy as np
import pandas as pd
import torch
import torch.nn as nn
import torch.optim as optim

from sklearn.utils import shuffle
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import normalize

def get_args():
    """Argument parser.
    Returns:
        Dictionary of arguments.
    """
    parser = argparse.ArgumentParser(description='PyTorch MNIST')
    parser.add_argument('--job-dir',  # handled automatically by AI Platform
                        help='GCS location to write checkpoints and export ' \
                             'models')
    parser.add_argument('--lr',  # Specified in the config file
                        type=float,
                        default=0.01,
                        help='learning rate (default: 0.01)')
    parser.add_argument('--momentum',  # Specified in the config file
                        type=float,
                        default=0.5,
                        help='SGD momentum (default: 0.5)')
    parser.add_argument('--hidden-layer-size',  # Specified in the config file
                        type=int,
                        default=8,
                        help='hidden layer size')
    args = parser.parse_args()
    return args

def train_model(args):
    # Get the data
    natality = pd.read_csv('https://storage.googleapis.com/ml-design-patterns/natality.csv')
    natality = natality.dropna()
    natality = shuffle(natality, random_state = 2)
    natality.head()

    natality_labels = natality['weight_pounds']
    natality = natality.drop(columns=['weight_pounds'])


    train_size = int(len(natality) * 0.8)
    traindata_natality = natality[:train_size]
    trainlabels_natality = natality_labels[:train_size]

    testdata_natality = natality[train_size:]
    testlabels_natality = natality_labels[train_size:]

    # Normalize and convert to PT tensors
    normalized_train = normalize(np.array(traindata_natality.values), axis=0)
    normalized_test = normalize(np.array(testdata_natality.values), axis=0)

    train_x = torch.Tensor(normalized_train)
    train_y = torch.Tensor(np.array(trainlabels_natality))

    test_x = torch.Tensor(normalized_test)
    test_y = torch.Tensor(np.array(testlabels_natality))

    # Define our data loaders
    train_dataset = torch.utils.data.TensorDataset(train_x, train_y)
    train_dataloader = torch.utils.data.DataLoader(train_dataset, batch_size=128, shuffle=True)

    test_dataset = torch.utils.data.TensorDataset(test_x, test_y)
    test_dataloader = torch.utils.data.DataLoader(test_dataset, batch_size=128, shuffle=False)

    # Define the model, while tuning the size of our hidden layer
    model = nn.Sequential(nn.Linear(len(train_x[0]), args.hidden_layer_size),
                          nn.ReLU(),
                          nn.Linear(args.hidden_layer_size, 1))
    criterion = nn.MSELoss()

    # Tune hyperparameters in our optimizer
    optimizer = optim.SGD(model.parameters(), lr=args.lr, momentum=args.momentum)
    epochs = 20
    for e in range(epochs):
        for batch_id, (data, label) in enumerate(train_dataloader):
            optimizer.zero_grad()
            y_pred = model(data)
            label = label.view(-1,1)
            loss = criterion(y_pred, label)
            
            loss.backward()
            optimizer.step()


    val_mse = 0
    num_batches = 0
    # Evaluate accuracy on our test set
    with torch.no_grad():
        for i, (data, label) in enumerate(test_dataloader):
            num_batches += 1
            y_pred = model(data)
            mse = criterion(y_pred, label.view(-1,1))
            val_mse += mse.item()


    avg_val_mse = (val_mse / num_batches)

    # Report the metric we're optimizing for to AI Platform's HyperTune service
    # In this example, we're mimizing error on our test set
    hpt = hypertune.HyperTune()
    hpt.report_hyperparameter_tuning_metric(
        hyperparameter_metric_tag='val_mse',
        metric_value=avg_val_mse,
        global_step=epochs        
    )

def main():
    args = get_args()
    print('in main', args)
    train_model(args)

if __name__ == '__main__':
    main()

ट्रेनिंग जॉब में दो फ़ंक्शन होते हैं, जिनमें ज़्यादातर काम होता है.

  • get_args(): यह कमांड लाइन के उन आर्ग्युमेंट को पार्स करता है जिन्हें हम ट्रेनिंग जॉब बनाते समय पास करेंगे. साथ ही, यह उन हाइपरपैरामीटर को भी पार्स करता है जिन्हें हमें AI Platform से ऑप्टिमाइज़ कराना है. इस उदाहरण में, हमारे आर्ग्युमेंट की सूची में सिर्फ़ वे हाइपरपैरामीटर शामिल हैं जिन्हें हम ऑप्टिमाइज़ करेंगे. जैसे, हमारे मॉडल की लर्निंग रेट, मोमेंटम, और हिडन लेयर में न्यूरॉन की संख्या.
  • train_model(): यहां हम डेटा को Pandas DataFrame में डाउनलोड करते हैं, उसे सामान्य बनाते हैं, उसे PyTorch Tensor में बदलते हैं, और फिर अपने मॉडल को तय करते हैं. हमारा मॉडल बनाने के लिए, हम PyTorch nn.Sequential एपीआई का इस्तेमाल कर रहे हैं. इससे हम अपने मॉडल को लेयर के स्टैक के तौर पर तय कर सकते हैं:
model = nn.Sequential(nn.Linear(len(train_x[0]), args.hidden_layer_size),
                      nn.ReLU(),
                      nn.Linear(args.hidden_layer_size, 1))

ध्यान दें कि हम अपने मॉडल की हिडन लेयर के साइज़ को हार्डकोड करने के बजाय, इसे एक हाइपरपैरामीटर बना रहे हैं. इसे AI Platform हमारे लिए ट्यून करेगा. इसके बारे में अगले सेक्शन में ज़्यादा जानकारी दी गई है.

दूसरा चरण: AI Platform की हाइपरपैरामीटर ट्यूनिंग सेवा का इस्तेमाल करना

हम मैन्युअल तरीके से अलग-अलग हाइपरपैरामीटर वैल्यू आज़माने और हर बार अपने मॉडल को फिर से ट्रेन करने के बजाय, Cloud AI Platform की हाइपरपैरामीटर ऑप्टिमाइज़ेशन सेवा का इस्तेमाल करेंगे. अगर हम हाइपरपैरामीटर आर्ग्युमेंट के साथ ट्रेनिंग जॉब सेट अप करते हैं, तो AI Platform, बेज़ियन ऑप्टिमाइज़ेशन का इस्तेमाल करके, हमारे बताए गए हाइपरपैरामीटर के लिए सबसे सही वैल्यू ढूंढता है.

हाइपरपैरामीटर ट्यूनिंग में, एक ट्रायल में हाइपरपैरामीटर वैल्यू के किसी खास कॉम्बिनेशन के साथ, हमारे मॉडल की एक ट्रेनिंग रन शामिल होती है. हम जितने भी ट्रायल चलाते हैं, उनके आधार पर AI Platform, पूरे हो चुके ट्रायल के नतीजों का इस्तेमाल करेगा. इससे, वह आने वाले समय में होने वाले ट्रायल के लिए, चुने गए हाइपरपैरामीटर को ऑप्टिमाइज़ कर पाएगा. हाइपरपैरामीटर ट्यूनिंग को कॉन्फ़िगर करने के लिए, हमें कॉन्फ़िगरेशन फ़ाइल पास करनी होगी. ऐसा तब किया जाता है, जब हम ट्रेनिंग जॉब शुरू करते हैं. इस फ़ाइल में, उन सभी हाइपरपैरामीटर का कुछ डेटा होता है जिन्हें हम ऑप्टिमाइज़ कर रहे हैं.

इसके बाद, उस कॉन्फ़िगरेशन फ़ाइल को स्थानीय तौर पर बनाएं:

%%writefile config.yaml
trainingInput:
  hyperparameters:
    goal: MINIMIZE
    maxTrials: 10
    maxParallelTrials: 5
    hyperparameterMetricTag: val_mse
    enableTrialEarlyStopping: TRUE
    params:
    - parameterName: lr
      type: DOUBLE
      minValue: 0.0001
      maxValue: 0.1
      scaleType: UNIT_LINEAR_SCALE
    - parameterName: momentum
      type: DOUBLE
      minValue: 0.0
      maxValue: 1.0
      scaleType: UNIT_LINEAR_SCALE
    - parameterName: hidden-layer-size
      type: INTEGER
      minValue: 8
      maxValue: 32
      scaleType: UNIT_LINEAR_SCALE

हम हर हाइपरपैरामीटर के लिए, टाइप, वैल्यू की वह रेंज बताते हैं जिसे हमें खोजना है. साथ ही, वह स्केल बताते हैं जिस पर अलग-अलग ट्रायल के दौरान वैल्यू को बढ़ाना है.

हम काम की शुरुआत में ही उस मेट्रिक के बारे में बता देते हैं जिसे हमें ऑप्टिमाइज़ करना है. ध्यान दें कि ऊपर दिए गए train_model() फ़ंक्शन के आखिर में, हम इस मेट्रिक को AI Platform पर रिपोर्ट करते हैं. ऐसा हर बार तब किया जाता है, जब कोई ट्रायल पूरा होता है. यहां हम अपने मॉडल की औसत वर्ग त्रुटि को कम कर रहे हैं. इसलिए, हमें उन हाइपरपैरामीटर का इस्तेमाल करना है जिनसे हमारे मॉडल की औसत वर्ग त्रुटि सबसे कम हो. इस मेट्रिक (val_mse) का नाम, उस नाम से मेल खाता है जिसका इस्तेमाल हम ट्रायल के खत्म होने पर report_hyperparameter_tuning_metric() को कॉल करते समय करते हैं.

6. AI Platform पर ट्रेनिंग जॉब चलाना

इस सेक्शन में, हम AI Platform पर हाइपरपैरामीटर ट्यूनिंग के साथ मॉडल ट्रेनिंग का काम शुरू करेंगे.

पहला चरण: कुछ एनवायरमेंट वैरिएबल तय करना

सबसे पहले, कुछ एनवायरमेंट वैरिएबल तय करते हैं. इनका इस्तेमाल हम ट्रेनिंग जॉब शुरू करने के लिए करेंगे. अगर आपको किसी दूसरे क्षेत्र में अपनी नौकरी ढूंढनी है, तो यहां दिए गए REGION वैरिएबल को अपडेट करें:

MAIN_TRAINER_MODULE = "trainer.model"
TRAIN_DIR = os.getcwd() + '/trainer'
JOB_DIR = BUCKET_URL + '/output'
REGION = "us-central1"

AI Platform पर हर ट्रेनिंग जॉब का नाम यूनीक होना चाहिए. टाइमस्टैंप का इस्तेमाल करके, अपनी नौकरी के नाम के लिए वैरिएबल तय करने के लिए, यह कमांड चलाएं:

timestamp = str(datetime.datetime.now().time())
JOB_NAME = 'caip_training_' + str(int(time.time()))

दूसरा चरण: ट्रेनिंग का काम शुरू करना

हम Google Cloud CLI, gcloud का इस्तेमाल करके ट्रेनिंग जॉब बनाएंगे. हम इस कमांड को सीधे अपनी नोटबुक में चला सकते हैं. इसके लिए, हमें ऊपर बताए गए वैरिएबल का रेफ़रंस देना होगा:

!gcloud ai-platform jobs submit training $JOB_NAME \
        --scale-tier basic \
        --package-path $TRAIN_DIR \
        --module-name $MAIN_TRAINER_MODULE \
        --job-dir $JOB_DIR \
        --region $REGION \
        --runtime-version 2.1 \
        --python-version 3.7 \
        --config config.yaml

अगर आपका काम सही तरीके से बनाया गया है, तो लॉग की निगरानी करने के लिए, AI Platform कंसोल के जॉब सेक्शन पर जाएं.

तीसरा चरण: अपने काम को मॉनिटर करना

Console के Jobs सेक्शन में जाकर, उस नौकरी पर क्लिक करें जिसके लिए आपने अभी-अभी आवेदन किया है. इससे आपको नौकरी की जानकारी दिखेगी:

c184167641bb7ed7.png

पहले राउंड के ट्रायल शुरू होने पर, आपको हर ट्रायल के लिए चुनी गई हाइपरपैरामीटर वैल्यू दिखेंगी:

787c053ef9110e6b.png

ट्रायल पूरे होने पर, ऑप्टिमाइज़ेशन मेट्रिक (इस मामले में val_mse) की वैल्यू यहां लॉग की जाएगी. जॉब को पूरा होने में 15 से 20 मिनट लगेंगे. जॉब पूरा होने के बाद, डैशबोर्ड कुछ ऐसा दिखेगा (वैल्यू अलग-अलग होंगी):

47ef6b9b4ecb532c.png

संभावित समस्याओं को ठीक करने और अपने काम को ज़्यादा बारीकी से मॉनिटर करने के लिए, नौकरी की जानकारी वाले पेज पर जाकर व्यू लॉग पर क्लिक करें:

18c32dcd36351930.png

आपके मॉडल ट्रेनिंग कोड में मौजूद हर print() स्टेटमेंट यहां दिखेगा. अगर आपको समस्याएं आ रही हैं, तो ज़्यादा प्रिंट स्टेटमेंट जोड़ें और ट्रेनिंग का नया जॉब शुरू करें.

ट्रेनिंग का काम पूरा होने के बाद, उन हाइपरपैरामीटर का पता लगाएं जिनसे val_mse सबसे कम मिला है. इनका इस्तेमाल, अपने मॉडल को ट्रेन करने और उसके फ़ाइनल वर्शन को एक्सपोर्ट करने के लिए किया जा सकता है. इसके अलावा, इनका इस्तेमाल दिशा-निर्देश के तौर पर करके, हाइपरपैरामीटर ट्यूनिंग के अतिरिक्त ट्रायल के साथ ट्रेनिंग का दूसरा काम शुरू किया जा सकता है.

7. साफ़-सफ़ाई सेवा

अगर आपको इस नोटबुक का इस्तेमाल जारी रखना है, तो हमारा सुझाव है कि इस्तेमाल न करने पर इसे बंद कर दें. Cloud Console में Notebooks के यूज़र इंटरफ़ेस (यूआई) में जाकर, नोटबुक चुनें. इसके बाद, बंद करें को चुनें:

879147427150b6c7.png

अगर आपको इस लैब में बनाए गए सभी संसाधन मिटाने हैं, तो नोटबुक इंस्टेंस को बंद करने के बजाय मिटा दें.

Cloud Console में नेविगेशन मेन्यू का इस्तेमाल करके, Storage पर जाएं. इसके बाद, मॉडल ऐसेट सेव करने के लिए बनाए गए दोनों बकेट मिटाएं.