Maschinelles Lernen CI/CD mit CircleCI und AWS Sagemaker | von Timothy Cheung | Juli 2023

0
65


Die Integration von CI/CD in Ihre ML-Pipeline bietet viele Vorteile, beispielsweise die Automatisierung der Bereitstellung von ML-Modellen für die Produktion im großen Maßstab.

Der Schwerpunkt dieses Artikels liegt auf der Veranschaulichung, wie die Schulung und Bereitstellung des AWS Sagemaker-Modells in CircleCI CI/CD-Pipelines integriert werden kann. In diesem Tutorial wird davon ausgegangen, dass Sie bereits über ein AWS-Konto mit Zugriff auf Sagemaker verfügen. Wenn Sie neu auf der CircleCI-Plattform sind, können Sie sich für ein kostenloses Konto anmelden und den Anweisungen folgen Schnellstartanleitung einzurichten.

Die Struktur dieses Projekts ist ein Monorepo, das mehrere Modelle enthält. Der Monorepo-Ansatz kann gegenüber dem Polyrepo-Ansatz Vorteile haben, einschließlich einer vereinfachten Versionierung von Abhängigkeiten und der Verwaltung von Sicherheitslücken.

Den Code für dieses Tutorial finden Sie hier Github-Repository.

Der erste Schritt besteht darin, AWS-Anmeldeinformationen in Ihrem Projekt auf CircleCI einzurichten. Sie können dies in CircleCI tun, indem Sie zu den Einstellungen Ihres Projekts gehen, auf Umgebungsvariablen klicken und dann auf die Schaltfläche „Variable hinzufügen“ klicken, um einen Namen und einen Wert der neuen Umgebungsvariablen einzugeben. Sobald Sie sie festgelegt haben, können Sie diese Umgebungsvariablen mithilfe von in Ihr Python-Skript übernehmen os.environ. Weitere Möglichkeiten zum Festlegen von Umgebungsvariablen in Ihrem Projekt finden Sie unter Schauen Sie sich diese Dokumentation an. Wenn Sie außerdem eine Verbindung zu Ihrem Cloud-Anbieter herstellen möchten, ohne dass langlebige Anmeldeinformationen in CircleCI gespeichert werden, können Sie dies über tun OIDC-Token.

In diesem Beispielprojekt haben wir insbesondere AWS-Zugriffsschlüssel und einen Sagemaker-Ausführungsrollen-ARN in unseren Umgebungsvariablen gespeichert. Es ist zu beachten, dass boto3 die genannten Umgebungsvariablen automatisch abruft AWS_ACCESS_KEY_ID Und AWS_SECRET_ACCESS_KEY Wenn wir eine Boto3-Sitzung erstellen, sollten wir sie daher nicht in etwas anderes umbenennen.

Auf CircleCI gespeicherte Geheimnisse

Darüber hinaus speichern wir Umgebungsvariablen, die für einen CI/CD-Job spezifisch sind, indem wir sie mit deklarieren atmosphere Geben Sie den Schlüssel in der Konfigurationsdatei ein. Dies ist in unserem Fall nicht unbedingt erforderlich, wir tun dies jedoch zur Demonstration.

atmosphere:
MODEL_NAME: abalone-model
MODEL_DESC: abalone mannequin description textual content

In unseren Python-Skripten rufen wir diese Umgebungsvariablen wie folgt ab:

model_name = os.environ["MODEL_NAME"]
model_description = os.environ["MODEL_DESC"]
role_arn = os.environ["SAGEMAKER_EXECUTION_ROLE_ARN"]

Zur Veranschaulichung haben wir zwei Modelle verwendet, die häufig in der AWS-Dokumentation zu finden sind: Abalone und Churn. Bei beiden handelt es sich um einfache XGBoost-Modelle, wobei Abalone ein linearer Regressor und Churn ein binärer Klassifikator ist. Jedes Modell ist in einem eigenen Ordner enthalten und jeder Ordner enthält die folgenden Dateien:

sammeln_data.py

Diese Datei lädt die Daten für ihr Modell herunter, verarbeitet sie vor und lädt sie dann in S3 hoch. Wir laden die Trainings- und Validierungsdatensätze in separaten Ordnern hoch, wie es von Sagemaker gefordert wird.

# Add coaching and validation knowledge to S3
csv_buffer = io.BytesIO()
train_data.to_csv(csv_buffer, index=False)
s3_client.put_object(Bucket=bucket, Physique=csv_buffer.getvalue(), Key=f"{model_name}/prepare/prepare.csv")

csv_buffer = io.BytesIO()
validation_data.to_csv(csv_buffer, index=False)
s3_client.put_object(Bucket=bucket, Physique=csv_buffer.getvalue(), Key=f"{model_name}/validation/validation.csv")

train_register.py

Diese Datei trainiert unser Modell und registriert es dann in der Modellregistrierung. Sie ist die erste Stelle in unserem CI/CD, an der wir Sagemaker tatsächlich verwenden.

Bei der Konfiguration des Sagemaker XGBoost Estimator können wir den S3-Pfad angeben, über den die Modellartefakte ausgegeben werden sollen output_path. Wir müssen ihm die Sagemaker-Sitzung und einen Sagemaker-Ausführungsrollen-ARN bereitstellen, da wir diesen Code außerhalb von Sagemaker-Notizbüchern ausführen und er diese Informationen daher nicht automatisch korrekt abruft.

# Configure coaching estimator
xgb_estimator = Estimator(
base_job_name = model_name,
image_uri = image_uri,
instance_type = "ml.m5.massive",
instance_count = 1,
output_path = model_location,
sagemaker_session = sagemaker_session,
position = role_arn,
hyperparameters = {
"goal": "reg:linear",
"max_depth": 5,
"eta": 0.2,
"gamma": 4,
"min_child_weight": 6,
"subsample": 0.7,
"verbosity": 2,
"num_round": 50,
}
)

Nach dem Coaching des Modells übertragen wir das Modellpaket in die Sagemaker-Modellregistrierung. Sagemaker unterscheidet zwischen einem Modell und einem Modellpaket. Ein Modell ist lediglich das Objekt, das wir an einem Endpunkt bereitstellen und Inferenz ausführen würden, während das Modellpaket alle mit diesem Modell verbundenen Artefakte enthält, wie z. B. Modellgewichtungen, Bewertungsergebnisse und Konfigurationsdateien. Wir pushen Modellpakete in die Modellregistrierung, keine Modelle.

Wir möchten eine Modellregistrierung verwenden, damit wir in nachfolgenden Schritten, z. B. bei der Bereitstellung oder wenn wir Modelle auf frühere Versionen zurücksetzen möchten, problemlos auf trainierte Modelle verweisen können. Beachten Sie, dass wir das Modellpaket vorab genehmigen, da wir CircleCI-Genehmigungsjobs verwenden, um die Modellgenehmigung zu verwalten.

# Retrieve mannequin artifacts from coaching job
model_artifacts = xgb_estimator.model_data

# Create pre-approved cross-account mannequin package deal
create_model_package_input_dict = {
"ModelPackageGroupName": model_name,
"ModelPackageDescription": "",
"ModelApprovalStatus": "Accepted",
"InferenceSpecification": {
"Containers": [
{
"Image": image_uri,
"ModelDataUrl": model_artifacts
}
],
"SupportedContentTypes": [ "text/csv" ],
"SupportedResponseMIMETypes": [ "text/csv" ]
}
}

create_model_package_response = sagemaker_client.create_model_package(**create_model_package_input_dict)

Deploy.py

Diese Datei stellt das neueste genehmigte Modellpaket auf dem Modellendpunkt bereit, indem entweder der Endpunkt erstellt wird, falls er noch nicht vorhanden ist, oder ein vorhandener Endpunkt aktualisiert wird.

Um das neueste genehmigte Modellpaket zu erhalten, verwenden wir eine Sagemaker-Funktion, um vorhandene Modellpakete nach absteigender Erstellungszeit aufzulisten und den Modellpaket-ARN abzurufen:

# Get the newest accepted mannequin package deal of the mannequin group in query
model_package_arn = sagemaker_client.list_model_packages(
ModelPackageGroupName = model_name,
ModelApprovalStatus = "Accepted",
SortBy = "CreationTime",
SortOrder = "Descending"
)['ModelPackageSummaryList'][0]['ModelPackageArn']

Dann erstellen wir ein Modell aus dem Modellpaket:

# Create the mannequin
timed_model_name = f"{model_name}-{current_time}"
container_list = [{"ModelPackageName": model_package_arn}]

create_model_response = sagemaker_client.create_model(
ModelName = timed_model_name,
ExecutionRoleArn = role_arn,
Containers = container_list
)

Und erstellen Sie eine Endpunktkonfiguration mit diesem Modell:

# Create endpoint config
create_endpoint_config_response = sagemaker_client.create_endpoint_config(
EndpointConfigName = timed_model_name,
ProductionVariants = [
{
"InstanceType": endpoint_instance_type,
"InitialVariantWeight": 1,
"InitialInstanceCount": endpoint_instance_count,
"ModelName": timed_model_name,
"VariantName": "AllTraffic",
}
]
)

Abschließend aktualisieren wir den Endpunkt mit der neuen Konfiguration:

create_update_endpoint_response = sagemaker_client.update_endpoint(
EndpointName = model_name,
EndpointConfigName = timed_model_name
)

Da wir einen Monorepo-Ansatz gewählt haben, benötigen wir eine Möglichkeit, unser CI/CD nur für das geänderte Modell auszuführen. Andernfalls wird beim Zusammenführen von Änderungen am Abalone-Modell auch das Churn-Modell neu trainiert und neu bereitgestellt! Hier kommen die dynamischen Konfigurationen von CircleCI zum Einsatz. Mit dieser Funktion können wir erkennen, ob Änderungen an einem bestimmten Ordner vorgenommen wurden, und wenn ja, den Wert eines Pipeline-Parameters festlegen. Der Pipeline-Parameter wiederum bestimmt, welche Workflows in unserer CI/CD-Pipeline ausgeführt werden.

Sie müssen mehrere Schritte ausführen, um die Verwendung dynamischer Konfigurationen zu aktivieren, z. B. die Aktivierung in Ihren CircleCI-Projekteinstellungen. Wir werden jedoch nicht näher darauf eingehen, da es eine gibt Schritt-für-Schritt-Anleitung verfügbar. Stattdessen konzentrieren wir uns auf die Abschnitte, die für unsere CI/CD-Architektur für maschinelles Lernen am wichtigsten sind. Lass uns eintauchen.

Setup-Konfiguration

Der erste Schritt bei der Nutzung dynamischer Konfigurationen ist die Setup-Konfiguration. In unserem Beispiel-Repository heißt es config.yml. Wir beschäftigen die path-filtering orb, um zu identifizieren, welche Ordner Codeänderungen enthalten.

Beachten Sie, dass wir Dateien mit denen im Hauptzweig vergleichen. Darüber hinaus ordnen wir Änderungen in bestimmten Ordnern Parameterwerten zu. Wenn beispielsweise Änderungen im Ordner abalone_model erkannt werden, gilt der Pipeline-Parameter deploy-abalone wird auf true gesetzt. Darüber hinaus geben wir den Pfad der Konfigurationsdatei an, die ausgelöst werden soll, sobald die Pfadfilterung und die Aktualisierung der Pipeline-Parameterwerte abgeschlossen sind.

base-revision: important
mapping: |
abalone_model/.* deploy-abalone true
churn_model/.* deploy-churn true
config-path: ".circleci/dynamic_config.yml"

Konfiguration fortsetzen

Nachdem die Pipeline-Parameterwerte aus der Setup-Konfiguration aktualisiert wurden, führen wir nun die Proceed-Konfiguration aus, die in unserem Beispiel-Repository den Namen „dynamic_config.yml“ trägt. Um das Verständnis der Konfigurationsdatei zu erleichtern, konzentrieren wir uns auf die abalone-model Arbeitsablauf.

workflows:
abalone-model:
when: << pipeline.parameters.deploy-abalone >>
jobs:
- abalone-model-train:
filters:
branches:
ignore:
- important
- request-deployment:
kind: approval
filters:
branches:
ignore:
- important
requires:
- abalone-model-train
- abalone-model-deploy:
filters:
branches:
solely:
- important

Erstens wird der Workflow nur ausgeführt, wenn der Pipeline-Parameter deploy-abalone ist wahr. Als nächstes führen wir den Job aus abalone-model-train, das die Datei train_register.py ausführt. Dann lösen wir das aus request-deployment Job, bei dem es sich um einen Genehmigungsjob handelt, der eine manuelle Genehmigung des Benutzers auf CircleCI erfordert, damit der Workflow fortgesetzt werden kann. Dies wäre ein Punkt, an dem ein Prüfer die Modellbewertungsmetriken auf Sagemaker überprüfen würde, bevor er die Bereitstellung des Modells auf dem Endpunkt zulässt. Wenn schließlich die Genehmigung erteilt wird, wird die abalone-model-deploy Der Job führt „deploy.py“ aus.

Beachten Sie, dass die Schulungs- und Genehmigungsjobs den Hauptzweig ignorieren, während der Bereitstellungsjob nur im Hauptzweig ausgeführt wird. Dadurch können neue Modellversionen trainiert werden, wenn der Entwickler in einem Entwicklerzweig an Aktualisierungen des Modells arbeitet, ohne dass irgendeine Artwork von Bereitstellung ausgelöst wird. Sobald die Codeänderungen dann akzeptiert und in important zusammengeführt wurden, wird der Bereitstellungsjob ausgelöst, ohne dass eine weitere Neuschulung des Modells ausgelöst wird.

Folgendes sehen wir auf CircleCI, wenn Codeänderungen in einem Entwicklerzweig an das Abalone-Modell übertragen werden. Die dynamische Konfiguration hat selektiv nur die Abalone-Trainingspipeline ausgeführt. Der request-deployment Das Gate des Genehmigungsjobs verhindert, dass die Codeänderungen in die Hauptdatei eingefügt werden. Sobald es genehmigt ist, kann die PR auf Github zusammengeführt werden.

In einem Entwicklerzweig wird nur die Trainingspipeline ausgeführt

Folgendes sehen wir, wenn Codeänderungen im Hauptzweig zusammengeführt werden. Da sich die Codeänderungen dieses Mal auf important beziehen, führt die dynamische Konfiguration selektiv nur die Abalone-Bereitstellungspipeline aus.

Im Hauptzweig wird nur die Bereitstellungspipeline ausgeführt

Wir haben die Verwendung von CircleCI zusammen mit AWS Sagemaker demonstriert, um eine Finish-to-Finish-ML-Pipeline zu erstellen. Es automatisiert den Prozess des Trainierens eines Modells und dessen Bereitstellung auf einem Endpunkt für Echtzeit-Inferenzen.

Es verwendet ein Monorepo-Setup, bei dem jedes Modell in einem eigenen Ordner enthalten ist. Darüber hinaus werden die dynamischen Konfigurationen von CircleCI verwendet, um jede Pipeline an das Modell anzupassen, bei dem Codeänderungen aufgetreten sind.

Nehmen Sie gerne Kontakt mit mir auf Linkedin.



Source link

HINTERLASSEN SIE EINE ANTWORT

Please enter your comment!
Please enter your name here