Aller au contenu principal

Module 8 — Prédiction par lots

Toutes les transactions de la plateforme ne demandent pas une réponse à 30 ms. Les virements SEPA à traitement différé, les remboursements en attente, les rapports quotidiens des équipes conformité — tout cela peut attendre le lendemain matin. Servir ces cas par l'endpoint du module 7 serait un gâchis. La prédiction par lots de Vertex répond exactement à cet usage.

Lot contre en ligne : deux régimes

CritèrePoint de terminaison (module 7)Prédiction par lots
Latence par prédiction20 à 100 msSans objet (batch de plusieurs millions)
Latence de bout en boutMillisecondesMinutes à heures
RéplicasToujours allumésÉphémères, provisionnés à la tâche
Coût par million de prédictionsÉlevé (100 % de disponibilité facturée)Bas (payé au temps de calcul réel)
InterfaceHTTP / gRPCFichiers GCS ou table BigQuery

Notre plateforme fraude utilise les deux, pour des populations différentes : l'endpoint en ligne pour les transactions carte présente en magasin (réponse sous 30 ms), la prédiction par lots nocturne pour les virements SEPA et un scan de contrôle sur tout le trafic de la veille.

Le BatchPredictionJob

En Python, une seule fonction :

from google.cloud import aiplatform

modele = aiplatform.Model("projects/paiement-fraude-prod/locations/europe-west1/models/1234567890@default")

job = modele.batch_predict(
job_display_name="fraude-lot-nocturne-2026-09-06",
bigquery_source="bq://paiement-fraude-prod.transactions.a_scorer_2026_09_05",
bigquery_destination_prefix="bq://paiement-fraude-prod.transactions.scores",
machine_type="n1-standard-8",
starting_replica_count=4,
max_replica_count=16,
sync=False,
service_account="vertex-fraude-runner@paiement-fraude-prod.iam.gserviceaccount.com",
labels={"equipe": "fraude", "type": "nocturne"},
)

Trois éléments à noter. La source et la destination peuvent être BigQuery (bigquery_source) ou Cloud Storage (gcs_source en JSONL, CSV ou TFRecord) — les deux sont supportés, on choisit selon le format le plus économique pour le pipeline aval. Le nombre de réplicas est un intervalle : Vertex démarre à starting_replica_count et monte jusqu'à max_replica_count selon la file d'attente. Enfin, sync=False rend la main immédiatement — un lot de plusieurs millions de lignes dure typiquement une à trois heures.

Format d'entrée et de sortie

Pour un bigquery_source, la table doit contenir exactement les colonnes que le modèle attend, dans le même ordre — mêmes types, mêmes noms. Une variable renommée, une colonne en plus, et le job échoue à la première ligne. La bonne discipline est de matérialiser une vue :

CREATE OR REPLACE VIEW `paiement-fraude-prod.transactions.a_scorer_2026_09_05` AS
SELECT
id_transaction,
montant, pays_carte, pays_marchand, canal, age_compte_jours, nb_transactions_24h
-- ... les 36 autres, dans l'ordre attendu
FROM `paiement-fraude-prod.transactions.a_scorer_bruts`
WHERE DATE(horodatage) = '2026-09-05'

En sortie, Vertex crée une table scores_predictions_<horodatage> dans le préfixe donné, avec les colonnes d'entrée dupliquées, une colonne prediction (la sortie du modèle) et une colonne error renseignée seulement en cas d'échec sur la ligne.

Planifier avec Cloud Scheduler

Un job de prédiction ne s'exécute pas de lui-même. Deux options : Cloud Scheduler + Cloud Function, ou intégrer le job dans un pipeline Vertex (module 9). Le premier est plus simple :

gcloud scheduler jobs create http fraude-lot-nocturne \
--location=europe-west1 \
--schedule="0 2 * * *" \
--time-zone="Europe/Paris" \
--uri="https://europe-west1-paiement-fraude-prod.cloudfunctions.net/lancer-lot-fraude" \
--http-method=POST \
--oidc-service-account-email=vertex-fraude-runner@paiement-fraude-prod.iam.gserviceaccount.com

Le Cloud Scheduler déclenche chaque nuit à 2 h une petite Cloud Function qui appelle modele.batch_predict(). Vingt lignes de code, la journalisation dans les logs GCP, et un rejet automatique si le lot précédent tourne encore.

Comparer les coûts

C'est souvent l'argument décisif. Prenons dix millions de prédictions par jour.

En ligne avec l'endpoint du module 7 : deux réplicas n1-standard-4 en permanence + jusqu'à huit en pointe. Coût moyen 3 réplicas × 24 h × 0,19 $ = 13,68 $/jour.

En lots avec le job ci-dessus : quatre réplicas n1-standard-8 pendant 2 heures = 3,04 $/jour. Quatre fois moins.

L'écart se creuse avec le volume : à cent millions par jour, l'endpoint coûterait 40 $ (plus de réplicas en permanence), le lot 22 $ (deux fois plus long, mêmes réplicas). Le lot passe à l'échelle mieux parce que l'utilisation des machines est proche de 100 %, alors que l'endpoint doit rester provisionné pour la pointe.

Jointure des résultats

Le lot écrit une table de scores. Comment la relier au métier ? Une jointure BigQuery, indexée sur id_transaction :

CREATE OR REPLACE TABLE `paiement-fraude-prod.transactions.a_alerter_2026_09_05`
PARTITION BY DATE(horodatage) AS
SELECT
t.id_transaction,
t.horodatage,
t.montant,
s.prediction AS score_fraude
FROM `paiement-fraude-prod.transactions.a_scorer_bruts` t
JOIN `paiement-fraude-prod.transactions.scores.scores_predictions_2026_09_06_02_15` s
USING (id_transaction)
WHERE DATE(t.horodatage) = '2026-09-05'
AND CAST(JSON_VALUE(s.prediction, '$.probabilite') AS FLOAT64) > 0.85

Le seuil 0.85 est le seuil opérationnel décidé par l'équipe conformité : les 12 000 transactions au-dessus partent dans la file d'analyse humaine du lendemain matin. Les autres sont marquées RAS.

Superviser un lot en cours

Un lot qui échoue en silence coûte deux fois : la facture du calcul et l'absence de résultats. Deux signaux à surveiller :

job = aiplatform.BatchPredictionJob("projects/.../batchPredictionJobs/12345")

print(job.state) # JOB_STATE_RUNNING, JOB_STATE_SUCCEEDED, JOB_STATE_FAILED
print(job.error) # None ou message d'erreur
print(job.output_info) # emplacement des resultats

# Compter les erreurs par ligne
requete = """
SELECT COUNT(*) AS lignes_en_erreur
FROM `paiement-fraude-prod.transactions.scores.scores_predictions_2026_09_06_02_15`
WHERE error IS NOT NULL
"""

Une alerte Cloud Monitoring déclenchée sur state = JOB_STATE_FAILED prévient l'astreinte. Une seconde, plus subtile, se déclenche si lignes_en_erreur > 1 % : le lot a « réussi » du point de vue Vertex, mais avec des dizaines de milliers de lignes non scorées, ce qui est aussi grave.

La prédiction par lots n'utilise pas votre endpoint

Le BatchPredictionJob ne passe pas par l'endpoint du module 7. Il provisionne ses propres réplicas, tire l'image de service directement depuis le modèle, et les éteint à la fin. Conséquence : la répartition de trafic 90/10 configurée sur l'endpoint ne s'applique pas aux lots. Si l'équipe veut tester v2 en lot avant de la promouvoir, il faut lancer le lot explicitement avec modele_v2, pas modele@default.

En résumé

  • Le lot convient dès que la latence par prédiction n'importe pas : SEPA, rapports, scan de contrôle.
  • Source et destination peuvent être BigQuery ou Cloud Storage ; les colonnes doivent correspondre exactement au modèle.
  • Cloud Scheduler + Cloud Function est la voie la plus simple pour un lot nocturne récurrent.
  • Le lot coûte typiquement 3 à 5 fois moins cher qu'un endpoint pour le même volume, grâce à l'utilisation proche de 100 %.
  • Surveiller state et error par ligne : un lot peut réussir avec 30 % de lignes en erreur.

Module suivant : nous cessons de piloter à la main entraînement, upload, déploiement et lot ; nous les orchestrons dans un pipeline Vertex.