Diese Anleitung als Notebook in Colab ausführen | Notebook auf GitHub ansehen |
In dieser Anleitung erfahren Sie, wie Sie mit AI Platform eine scikit-learn-Pipeline mit benutzerdefinierten Transformern 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 Prediction bereitstellen möchten, müssen Sie diesen Code als Distributionspaket der Quellen in AI Platform Prediction 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 Prediction
- 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/ai-platform/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 (Ziellabel).
Der Schwerpunkt dieser Anleitung liegt mehr auf der Verwendung des Modells mit AI Platform Prediction als auf dem eigentlichen 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 zum allgemeinen Thema Fairness beim maschinellen Lernen.
Kosten
In dieser Anleitung werden kostenpflichtige Komponenten von Google Cloud verwendet.
- AI Platform Training
- AI Platform Prediction
- Cloud Storage
Informieren Sie sich über die Preise für AI Platform Training, die Preise für AI Platform Prediction und die Cloud Storage-Preise und verwenden Sie den Preisrechner, um eine Kostenschätzung anhand Ihrer prognostizierten Nutzung zu erstellen.
Hinweise
Bevor Sie ein Modell in AI Platform Prediction trainieren und bereitstellen können, müssen Sie einige Schritte ausführen:
- Lokale Entwicklungsumgebung einrichten
- Google Cloud-Projekt einrichten, für das die Abrechnungsfunktion und die erforderlichen APIs aktiviert sind
- 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
- Das Google 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:
Installieren Sie virtualenv und erstellen Sie eine virtuelle Umgebung, die Python 3 verwendet.
Aktivieren Sie die Umgebung.
Führen Sie die Schritte im folgenden Abschnitt aus, um das Google Cloud SDK zu installieren.
Google Cloud-Projekt einrichten
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the AI Platform Training & Prediction and Compute Engine APIs.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the AI Platform Training & Prediction and Compute Engine APIs.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
GCP-Konto authentifizieren
Für die Einrichtung der Authentifizierung müssen Sie einen Dienstkontoschlüssel erstellen und eine Umgebungsvariable für den Dateipfad zum Dienstkontoschlüssel festlegen.
-
Erstellen Sie ein Dienstkonto:
-
Wechseln Sie in der Google Cloud Console zur Seite Dienstkonto erstellen.
- Geben Sie im Feld Dienstkontoname einen Namen ein.
- Optional: Geben Sie im Feld Dienstkontobeschreibung eine Beschreibung ein.
- Klicken Sie auf Erstellen.
- Klicken Sie auf das Feld Rolle auswählen. Wählen Sie unter Alle Rollen die Option AI Platform > AI Platform-Administrator aus.
- Klicken Sie auf Weitere Rolle hinzufügen.
-
Klicken Sie auf das Feld Rolle auswählen. Wählen Sie unter Alle Rollen die Option Storage > Storage-Objekt-Administrator.
-
Klicken Sie auf Fertig, um das Dienstkonto zu erstellen.
Schließen Sie das Browserfenster nicht. Sie verwenden es in der nächsten Aufgabe.
-
-
Erstellen Sie einen Dienstkontoschlüssel für die Authentifizierung:
- Klicken Sie in der Google Cloud Console auf die E-Mail-Adresse des von Ihnen erstellten Dienstkontos.
- Klicken Sie auf Schlüssel.
- Klicken Sie auf Schlüssel hinzufügen > Neuen Schlüssel erstellen.
- Klicken Sie auf Erstellen. Daraufhin wird eine JSON-Schlüsseldatei auf Ihren Computer heruntergeladen.
- Klicken Sie auf Schließen.
-
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 Training führt den Code aus diesem Paket aus.
In dieser Anleitung speichert AI Platform Training das im Rahmen des Jobs trainierte Modell auch im selben Bucket.
Wenn Sie Ihre scikit-learn-Pipeline mit benutzerdefiniertem Code in AI Platform Prediction bereitstellen möchten, müssen Sie die von der Pipeline verwendeten benutzerdefinierten Transformer in Cloud Storage hochladen.
Wenn Sie eine AI Platform Prediction-Versionsressource erstellen, die Vorhersagen bereitstellt, 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 AI Platform Prediction verfügbar sind, und erstellen Sie eine weitere Umgebungsvariable. Beispiel:
REGION="us-central1"
Erstellen Sie in dieser Region einen Cloud Storage-Bucket 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:
gcloud storage buckets create gs://$BUCKET_NAME --location=$REGION
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. Das ist praktisch, weil Pipelines im Allgemeinen während des Trainings und der Vorhersage dieselben Transformer 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 es 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
: Akzeptiert eine Indexliste C und eine Matrix M und gibt eine Matrix zurück, die die in C angegebenen Spalten von M enthält.StripString
: Akzeptiert eine Matrix mit Strings und entfernt die Leerzeichen aus ihnen.SimpleOneHotEncoder
: Ein einfacher One-Hot-Encoder, der auf eine Matrix mit Strings angewendet werden kann.
Schreiben Sie dazu den folgenden Code in eine Datei mit dem Namen 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 Trainingsmodul erstellen
Als Nächstes erstellen Sie ein Trainingsmodul, um Ihre scikit-learn-Pipeline mit den Zensusdaten zu trainieren. Ein Teil dieses Codes definiert die 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 drei numerische Merkmale (
'age'
,'education-num'
,'hours-per-week'
) und drei kategoriale Merkmale ('workclass'
,'marital-status'
,'relationship'
) der Eingabedaten verwendet. Die numerischen Merkmale werden mit dem integriertenStandardScaler
von scikit-learn transformiert. Die kategorialen Merkmale werden mit dem benutzerdefinierten One-Hot-Encoder transformiert, den Sie inmy_pipeline.py
definiert haben. Dann werden die vorverarbeiteten Daten als Eingabe für einen Klassifikator kombiniert. - Schließlich wird das Modell mit der in scikit-learn enthaltenen Version von
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 Training trainieren
Verwenden Sie gcloud
, um einen Trainingsjob an AI Platform Training zu senden. Der folgende Befehl erstellt ein Paket aus Ihrer Trainingsanwendung, lädt sie in Cloud Storage hoch und weist AI Platform Training an, Ihr Trainingsmodul auszuführen.
Das Argument --
ist ein Trennzeichen: Der AI Platform Training-Dienst verwendet keine Argumente, die auf das Trennzeichen folgen. Das Trainingsmodul kann jedoch 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/ai-platform/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 Prediction 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 Version 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
-Quelldistributionspaket 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
erstellen, 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 Quelldistributionspaket für Ihren Code zu definieren:
import setuptools
setuptools.setup(name='census_package',
packages=['census_package'],
version="1.0",
)
Führen Sie dann 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:
gcloud storage 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 Namen für das Modell und die Version:
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
Für das 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
Testen Sie Ihre Bereitstellung mit einer Anfrage für eine Onlinevorhersage. Dafür installieren Sie zuerst die Google API-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 verarbeitet die Eingabedaten in der trainierten Pipeline und gibt die Ergebnisse des Klassifikators zurück, also für jede Instanz entweder <=50K
oder >50K
. Dies ist die Vorhersage der Einkommensklasse der Person.
Bereinigen
Wenn Sie alle für dieses Projekt verwendeten Google Cloud-Ressourcen bereinigen möchten, können Sie das Google Cloud-Projekt löschen, das Sie für diese 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
gcloud storage rm gs://$BUCKET_NAME/custom_pipeline_tutorial --recursive
Nächste Schritte
- Weitere Informationen zum Verwenden benutzerdefinierter scikit-learn-Pipelines mit AI Platform Prediction
- Benutzerdefinierte Vorhersageroutinen (Beta) erstellen, um noch mehr Kontrolle über die Bereitstellung von Vorhersagen in AI Platform Prediction zu haben