Vorhersage mit einer benutzerdefinierten scikit-learn-Pipeline

Colab-Logo Diese Anleitung als Notebook in Colab ausführen GitHub-Logo Notebook auf GitHub ansehen

In dieser Anleitung wird gezeigt, wie Sie mit AI Platform eine scikit-learn-Pipeline mit benutzerdefinierten Transformatoren bereitstellen.

Mithilfe von scikit-learn-Pipelines können Sie mehrere Estimators zusammensetzen. Sie können zum Beispiel Transformer verwenden, um Daten vorzuverarbeiten und die transformierten Daten an einen Klassifikator zu übergeben. scikit-learn stellt viele Transformer im Paket sklearn bereit.

Sie können auch die Klasse FunctionTransformer oder TransformerMixin von scikit-learn verwenden, um einen eigenen benutzerdefinierten Transformer zu erstellen. Wenn Sie eine Pipeline mit benutzerdefinierten Transformern in AI Platform-Vorhersage bereitstellen möchten, müssen Sie diesen Code als Distributionspaket der Quellen in AI Platform bereitstellen.

In dieser Anleitung wird ein Beispielproblem mit Zensusdaten beschrieben, in dem Sie durch die folgenden Schritte geführt werden:

  • Training einer scikit-learn-Pipeline mit benutzerdefinierten Transformern in AI Platform-Training
  • Bereitstellung der trainierten Pipeline und des benutzerdefinierten Codes in AI Platform-Vorhersage
  • Bearbeitung von Vorhersageanfragen in dieser Bereitstellung

Dataset

In dieser Anleitung wird das vom UC Irvine Machine Learning Repository bereitgestellte United States Census Income Dataset (US-Dataset zur Einkommenserhebung) verwendet. Das Dataset enthält Informationen zu Personen aus einer Zensusdatenbank von 1994, einschließlich Alter, Bildungsgrad, Familienstand, Beruf und ob sie mehr als 50.000 $ pro Jahr verdienen.

Die in dieser Anleitung verwendeten Daten sind in einem öffentlichen Cloud Storage-Bucket verfügbar: gs://cloud-samples-data/ml-engine/sklearn/census_data/

Ziel

Das Ziel besteht darin, eine scikit-learn-Pipeline zu trainieren, die auf der Grundlage anderer Zensusinformationen einer Person (Merkmale) vorhersagt, ob eine Person mehr als 50.000 $ pro Jahr verdient (Ziel-Label).

Der Schwerpunkt dieser Anleitung liegt auf der Anwendung des Modells mit AI Platform statt auf dem Modelldesign. Sie sollten beim Erstellen eines Systems für maschinelles Lernen jedoch immer mögliche Probleme und unbeabsichtigte Folgen berücksichtigen. In der Übung zum Thema Fairness im Intensivkurs zum maschinellen Lernen erhalten Sie Informationen zu Verzerrungsquellen im Zensus-Dataset sowie zur allgemeinen Fairness beim maschinellen Lernen.

Kosten

In dieser Anleitung werden kostenpflichtige Komponenten der Google Cloud Platform (GCP) verwendet:

  • AI Platform
  • Cloud Storage

Informieren Sie sich über die Preise von AI Platform und die Preise von Cloud Storage. Mit dem Preisrechner können Sie die voraussichtlichen Kosten basierend auf der geplanten Nutzung kalkulieren.

Vorbereitung

Bevor Sie ein Modell in AI Platform trainieren und bereitstellen können, müssen Sie einige Schritte ausführen:

  • Lokale Entwicklungsumgebung einrichten
  • GCP-Projekt mit Abrechnung und den erforderlichen APIs einrichten
  • Cloud Storage-Bucket zum Speichern des Trainingspakets und des trainierten Modells erstellen

Lokale Entwicklungsumgebung einrichten

Für diese Anleitung benötigen Sie Folgendes:

  • Python 3
  • virtualenv
  • Cloud SDK

Der Google Cloud-Leitfaden zum Einrichten einer Python-Entwicklungsumgebung enthält detaillierte Anweisungen zur Erfüllung dieser Anforderungen. Die folgenden Schritte sind eine Zusammenfassung dieser Anweisungen:

  1. Installieren Sie Python 3.

  2. Installieren Sie virtualenv und erstellen Sie eine virtuelle Umgebung, die Python 3 verwendet.

  3. Aktivieren Sie die Umgebung.

  4. Führen Sie die Schritte im folgenden Abschnitt aus, um das Cloud SDK zu installieren.

GCP-Projekt einrichten

  1. Melden Sie sich in Ihrem Google-Konto an.

    Wenn Sie noch kein Konto haben, registrieren Sie sich hier für ein neues Konto.

  2. Wählen Sie ein Google Cloud Platform-Projekt aus oder erstellen Sie eines.

    Zur Seite "Ressourcen verwalten"

  3. Prüfen Sie, ob die Abrechnung für Ihr Google Cloud Platform-Projekt aktiviert ist.

    Informationen zum Aktivieren der Abrechnung

  4. Aktivieren Sie die AI Platform ("Cloud Machine Learning Engine") and Compute Engine erforderlichen APIs.

    Aktivieren Sie die APIs.

  5. Installieren und initialisieren Sie das Cloud SDK.

GCP-Konto authentifizieren

Sie müssen einen Dienstkontoschlüssel erstellen und eine bestimmte Umgebungsvariable für den Dateipfad zum Dienstkontoschlüssel festlegen, um die Authentifizierung einzurichten.

  1. Erstellen Sie einen Dienstkontoschlüssel für die Authentifizierung:
    1. Wechseln Sie in der GCP Console zur Seite Dienstkontoschlüssel erstellen.

      Zur Seite "Dienstkontoschlüssel erstellen"
    2. Wählen Sie aus der Drop-down-Liste Dienstkonto die Option Neues Dienstkonto aus.
    3. Geben Sie im Feld Dienstkontoname einen Namen ein.
    4. Wählen Sie aus der Drop-down-Liste Rolle die Optionen Machine Learning Engine > ML Engine-Administrator und Storage > Storage-Objekt-Administrator aus.

      Hinweis: Über das Feld Rolle wird Ihr Dienstkonto für den Zugriff auf Ressourcen autorisiert. Sie können dieses Feld später in der GCP Console ansehen und ändern. Wenn Sie eine Produktionsanwendung entwickeln, müssen Sie möglicherweise detailliertere Berechtigungen als Machine Learning Engine > ML Engine-Administrator und Storage > Storage-Objekt-Administrator angeben. Weitere Informationen finden Sie unter Zugriffssteuerung für AI Platform.
    5. Klicken Sie auf Erstellen. Eine JSON-Datei mit Ihrem Schlüssel wird auf Ihren Computer heruntergeladen.
  2. Legen Sie die Umgebungsvariable GOOGLE_APPLICATION_CREDENTIALS auf den Pfad der JSON-Datei fest, die Ihren Dienstkontoschlüssel enthält. Diese Variable gilt nur für Ihre aktuelle Shell-Sitzung. Wenn Sie eine neue Sitzung öffnen, müssen Sie die Variable noch einmal festlegen.

Cloud Storage-Bucket erstellen

In dieser Anleitung wird Cloud Storage auf verschiedene Arten verwendet:

  • Wenn Sie einen Trainingsjob mit dem Cloud SDK senden, laden Sie ein Python-Paket mit Ihrem Trainingscode in einen Cloud Storage-Bucket hoch. AI Platform führt den Code aus diesem Paket aus.

  • In dieser Anleitung speichert AI Platform das im Rahmen Ihres Jobs trainierte Modell außerdem im selben Bucket.

  • Zum Bereitstellen der scikit-learn-Pipeline, die benutzerdefinierten Code für Vorhersagen verwendet, müssen Sie die von Ihrer Pipeline verwendeten benutzerdefinierten Transformer in Cloud Storage hochladen.

Wenn Sie die AI Platform-Versionsressource erstellen, die für Vorhersagen verwendet wird, stellen Sie die trainierte scikit-learn-Pipeline und den benutzerdefinierten Code als Cloud Storage-URIs bereit.

Legen Sie den Namen Ihres Cloud Storage-Buckets als Umgebungsvariable fest. Der Name muss in allen Cloud Storage-Buckets eindeutig sein:

BUCKET_NAME="your-bucket-name"

Wählen Sie eine Region aus, in der AI Platform-Training und -Vorhersage verfügbar sind, und erstellen Sie eine weitere Umgebungsvariable. Für das Training mit AI Platform dürfen Sie keinen Multi-Regional Storage-Bucket verwenden. Beispiel:

REGION="us-central1"

Erstellen Sie einen Cloud Storage-Bucket in dieser Region und verwenden Sie später dieselbe Region für Training und Vorhersage. Führen Sie den folgenden Befehl aus, wenn noch kein Bucket vorhanden ist:

gsutil mb -l $REGION gs://$BUCKET_NAME

Trainingsanwendung und benutzerdefinierten Pipeline-Code erstellen

Erstellen Sie eine Anwendung zum Trainieren einer scikit-learn-Pipeline mit den Zensusdaten. In dieser Anleitung enthält das Trainingspaket auch den benutzerdefinierten Code, den die trainierte Pipeline während der Vorhersage verwendet. Dies ist ein nützliches Muster, da Pipelines im Allgemeinen dazu konzipiert sind, während des Trainings und der Vorhersage dieselben Transformer zu verwenden.

Führen Sie die folgenden Schritte aus, um ein Verzeichnis mit drei Dateien zu erstellen, das der folgenden Struktur entspricht:

census_package/
    __init__.py
    my_pipeline.py
    train.py

Erstellen Sie zuerst das leere Verzeichnis census_package/:

mkdir census_package

Erstellen Sie in census_package/ eine leere Datei mit dem Namen __init__.py:

touch ./census_package/__init__.py

Dies ermöglicht Ihnen, census_package/ als Paket in Python zu importieren.

Benutzerdefinierte Transformer erstellen

scikit-learn stellt viele Transformer bereit, die Sie als Teil einer Pipeline verwenden können, aber Sie können auch Ihre eigenen benutzerdefinierten Transformer definieren. Diese Transformer können während des Trainings sogar einen gespeicherten Zustand erlernen, der später während der Vorhersage verwendet wird.

Erweitern Sie sklearn.base.TransformerMixin, um drei Transformer zu definieren:

  • PositionalSelector: Bei einer Indexliste C und einer Matrix M wird eine Matrix mit einer Teilmenge der Spalten von M zurückgegeben, die mit C bezeichnet wird.

  • StripString: Bei einer Matrix von Strings werden Leerzeichen aus jedem String entfernt.

  • SimpleOneHotEncoder: Ein einfacher One-Hot-Encoder, der auf eine Matrix von Strings angewendet werden kann.

Schreiben Sie dazu den folgenden Code in eine Datei namens census_package/my_pipeline.py.

import numpy as np
from sklearn.base import BaseEstimator, TransformerMixin

class PositionalSelector(BaseEstimator, TransformerMixin):
    def __init__(self, positions):
        self.positions = positions

    def fit(self, X, y=None):
        return self

    def transform(self, X):
        return np.array(X)[:, self.positions]

class StripString(BaseEstimator, TransformerMixin):
    def fit(self, X, y=None):
        return self

    def transform(self, X):
        strip = np.vectorize(str.strip)
        return strip(np.array(X))

class SimpleOneHotEncoder(BaseEstimator, TransformerMixin):
    def fit(self, X, y=None):
        self.values = []
        for c in range(X.shape[1]):
            Y = X[:, c]
            values = {v: i for i, v in enumerate(np.unique(Y))}
            self.values.append(values)
        return self

    def transform(self, X):
        X = np.array(X)
        matrices = []
        for c in range(X.shape[1]):
            Y = X[:, c]
            matrix = np.zeros(shape=(len(Y), len(self.values[c])), dtype=np.int8)
            for i, x in enumerate(Y):
                if x in self.values[c]:
                    matrix[i][self.values[c][x]] = 1
            matrices.append(matrix)
        res = np.concatenate(matrices, axis=1)
        return res

Pipeline definieren und ein Trainingsmodul erstellen

Als Nächstes erstellen Sie ein Trainingsmodul, um Ihre scikit-learn-Pipeline mit den Zensusdaten zu trainieren. Ein Teil dieses Codes beinhaltet die Definition der Pipeline.

Dieses Trainingsmodul führt mehrere Vorgänge aus:

  • Die Trainingsdaten werden heruntergeladen und in einen Pandas-DataFrame geladen, der von scikit-learn verwendet werden kann.
  • Die zu trainierende scikit-learn-Pipeline wird definiert. In diesem Beispiel werden nur drei numerische Merkmale ('age', 'education-num' und 'hours-per-week') und drei kategoriale Merkmale ('workclass', 'marital-status' und 'relationship') aus den Eingabedaten verwendet. Die numerischen Features werden mit dem integrierten StandardScaler von scikit-learn transformiert. Die kategorialen Features werden mit dem benutzerdefinierten One-Hot-Encoder transformiert, den Sie in my_pipeline.py definiert haben. Dann werden die vorverarbeiteten Daten als Eingabe für einen Klassifikator kombiniert.
  • Abschließend wird das Modell mit joblib exportiert und in Ihrem Cloud Storage-Bucket gespeichert.

Schreiben Sie den folgenden Code in census_package/train.py:

import warnings
import argparse
from google.cloud import storage

import pandas as pd
import numpy as np
from sklearn.externals import joblib
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.pipeline import Pipeline, FeatureUnion, make_pipeline
import census_package.my_pipeline as mp
warnings.filterwarnings('ignore')

def download_data(bucket_name, gcs_path, local_path):
    bucket = storage.Client().bucket(bucket_name)
    blob = bucket.blob(gcs_path)
    blob.download_to_filename(local_path)

def upload_data(bucket_name, gcs_path, local_path):
    bucket = storage.Client().bucket(bucket_name)
    blob = bucket.blob(gcs_path)
    blob.upload_from_filename(local_path)

def get_features_target(local_path):
    strip = np.vectorize(str.strip)
    raw_df = pd.read_csv(local_path, header=None)
    target_index = len(raw_df.columns) - 1  # Last columns, 'income-level', is the target

    features_df = raw_df.drop(target_index, axis=1)
    features = features_df.as_matrix()
    target = strip(raw_df[target_index].values)
    return features, target

def create_pipeline():
    # We want to use 3 categorical and 3 numerical features in this sample.
    # Categorical features: age, education-num, and hours-per-week
    # Numerical features: workclass, marital-status, and relationship
    numerical_indices = [0, 4, 12]  # age, education-num, and hours-per-week
    categorical_indices = [1, 5, 7]  # workclass, marital-status, and relationship

    p1 = make_pipeline(mp.PositionalSelector(categorical_indices), mp.StripString(), mp.SimpleOneHotEncoder())
    p2 = make_pipeline(mp.PositionalSelector(numerical_indices), StandardScaler())

    feats = FeatureUnion([
        ('numericals', p1),
        ('categoricals', p2),
    ])

    pipeline = Pipeline([
        ('pre', feats),
        ('estimator', GradientBoostingClassifier(max_depth=4, n_estimators=100))
    ])
    return pipeline

def get_bucket_path(gcs_uri):
    if not gcs_uri.startswith('gs://'):
        raise Exception('{} does not start with gs://'.format(gcs_uri))
    no_gs_uri = gcs_uri[len('gs://'):]
    first_slash_index = no_gs_uri.find('/')
    bucket_name = no_gs_uri[:first_slash_index]
    gcs_path = no_gs_uri[first_slash_index + 1:]
    return bucket_name, gcs_path

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--gcs_data_path', action="store", required=True)
    parser.add_argument('--gcs_model_path', action="store", required=True)

    arguments, others = parser.parse_known_args()

    local_path = '/tmp/adul.data'
    data_bucket, data_path = get_bucket_path(arguments.gcs_data_path)
    print('Downloading the data...')
    download_data(data_bucket, data_path, local_path)
    features, target = get_features_target(local_path)
    pipeline = create_pipeline()

    print('Training the model...')
    pipeline.fit(features, target)

    joblib.dump(pipeline, './model.joblib')

    model_bucket, model_path = get_bucket_path(arguments.gcs_model_path)
    upload_data(model_bucket, model_path, './model.joblib')
    print('Model was successfully uploaded.')

Pipeline in AI Platform trainieren

Verwenden Sie gcloud, um einen Trainingsjob an AI Platform zu senden. Mit dem folgenden Befehl wird Ihre Trainingsanwendung verpackt, in Cloud Storage hochgeladen und AI Platform wird angewiesen, Ihr Trainingsmodul auszuführen.

Das Argument -- ist ein Trennzeichen: Der AI Platform-Dienst verwendet keine Argumente, die auf das Trennzeichen folgen, aber das Trainingsmodul kann trotzdem darauf zugreifen.

gcloud ai-platform jobs submit training census_training_$(date +"%Y%m%d_%H%M%S") \
  --job-dir gs://$BUCKET_NAME/custom_pipeline_tutorial/job \
  --package-path ./census_package \
  --module-name census_package.train \
  --region $REGION \
  --runtime-version 1.13 \
  --python-version 3.5 \
  --scale-tier BASIC \
  --stream-logs \
  -- \
  --gcs_data_path gs://cloud-samples-data/ml-engine/census/data/adult.data.csv \
  --gcs_model_path gs://$BUCKET_NAME/custom_pipeline_tutorial/model/model.joblib

Pipeline bereitstellen und Vorhersagen erstellen

Wenn Sie in AI Platform Vorhersagen erstellen möchten, müssen Sie eine Modellressource und eine Versionsressource bereitstellen. Das Modell unterstützt Sie beim Organisieren mehrerer Bereitstellungen, wenn Sie die Pipeline mehrmals ändern und trainieren. Die Versionsressource verwendet das trainierte Modell und den benutzerdefinierten Code für Vorhersagen.

Zur Bereitstellung dieser Ressourcen müssen Sie zwei Artefakte bereitstellen:

  • Ein Cloud Storage-Verzeichnis, das die trainierte Pipeline enthält. Diese Datei wurde durch den Trainingsjob im vorherigen Schritt erstellt, als model.joblib in Ihren Bucket exportiert wurde.
  • Ein .tar.gz-Distributionspaket der Quellen in Cloud Storage, das alle benutzerdefinierten Transformer enthält, die von der Pipeline verwendet werden. Dieses erstellen Sie im nächsten Schritt.

Paket der benutzerdefinierten Transformer erstellen

Wenn Sie eine Version ohne den Code aus my_pipeline.py bereitstellen, kann AI Platform Prediction die benutzerdefinierten Transformer (z. B. mp.SimpleOneHotEncoder) nicht importieren und keine Vorhersagen bereitstellen.

Erstellen Sie die folgende setup.py-Datei, um ein Distributionspaket der Quellen für Ihren Code zu definieren:

import setuptools
setuptools.setup(name='census_package',
      packages=['census_package'],
      version="1.0",
      )

Dann führen Sie den folgenden Befehl aus, um dist/census_package-1.0.tar.gz zu erstellen:

python setup.py sdist --formats=gztar

Abschließend laden Sie dieses Tarball-Paket in Ihren Cloud Storage-Bucket hoch:

gsutil cp ./dist/census_package-1.0.tar.gz gs://$BUCKET_NAME/custom_pipeline_tutorial/code/census_package-1.0.tar.gz

Modell- und Versionsressourcen erstellen

Zuerst definieren Sie die Modell- und Versionsnamen:

MODEL_NAME='CensusPredictor'
VERSION_NAME='v1'

Anschließend erstellen Sie die Modellressource mit dem folgenden Befehl:

gcloud ai-platform models create $MODEL_NAME \
  --regions $REGION

Zum abschließenden Erstellen der Versionsressource geben Sie Cloud Storage-Pfade zu Ihrem Modellverzeichnis (in dem sich model.joblib befindet) und Ihrem benutzerdefinierten Code (census_package-1.0.tar.gz) an:

gcloud components install beta

gcloud beta ai-platform versions create $VERSION_NAME --model $MODEL_NAME \
  --origin gs://$BUCKET_NAME/custom_pipeline_tutorial/model/ \
  --runtime-version 1.13 \
  --python-version 3.5 \
  --framework SCIKIT_LEARN \
  --package-uris gs://$BUCKET_NAME/custom_pipeline_tutorial/code/census_package-1.0.tar.gz

Onlinevorhersagen bereitstellen

Senden Sie eine Anfrage für eine Onlinevorhersage, um die Bereitstellung zu testen. Installieren Sie zuerst die Google APIs-Clientbibliothek für Python:

pip install --upgrade google-api-python-client

Dann senden Sie zwei Instanzen von Zensusdaten an die bereitgestellte Version:

import googleapiclient.discovery

instances = [
  [39, 'State-gov', 77516, ' Bachelors .  ', 13, 'Never-married', 'Adm-clerical', 'Not-in-family',
   'White', 'Male', 2174, 0, 40, 'United-States', '<=50K'],
  [50, 'Self-emp-not-inc', 83311, 'Bachelors', 13, 'Married-civ-spouse', 'Exec-managerial', 'Husband',
   'White', 'Male', 0, 0, 13, 'United-States', '<=50K']
]

service = googleapiclient.discovery.build('ml', 'v1')
name = 'projects/{}/models/{}/versions/{}'.format(PROJECT_ID, MODEL_NAME, VERSION_NAME)

response = service.projects().predict(
    name=name,
    body={'instances': instances}
).execute()

if 'error' in response:
    raise RuntimeError(response['error'])
else:
  print(response['predictions'])

Die Version übergibt die Eingabedaten durch die trainierte Pipeline und gibt die Ergebnisse des Klassifikators zurück: entweder <=50K oder >50K für jede Instanz, abhängig von der jeweiligen Vorhersage für die Einkommensklasse der Person.

Bereinigen

Zum Bereinigen aller in diesem Projekt verwendeten GCP-Ressourcen können Sie das GCP-Projekt löschen, das Sie für die Anleitung verwendet haben.

Alternativ können Sie mit den folgenden Befehlen einzelne Ressourcen bereinigen:

# Delete version resource
gcloud ai-platform versions delete $VERSION_NAME --quiet --model $MODEL_NAME

# Delete model resource
gcloud ai-platform models delete $MODEL_NAME --quiet

# Delete Cloud Storage objects that were created
gsutil -m rm -r gs://$BUCKET_NAME/custom_pipeline_tutorial

Weitere Informationen

Hat Ihnen diese Seite weitergeholfen? Teilen Sie uns Ihr Feedback mit:

Feedback geben zu...