Article
· Oct 27 7m de lecture

Amusons-nous avec les séries chronologiques d'IntegratedML

Récemment, @Anastasia Dyubaylo a publié un article (celui-ci) sur une nouvelle fonctionnalité d'IntegratedML pour les prédictions de séries chronologiques présentée par @Thomas Dyar lors du Global Summit 2023, organisons donc un petit atelier pour la tester !

Introduction

Nous avons choisi comme sujet de cet atelier la prédiction des utilisateurs du métro de Valence, mois par mois, ligne par ligne. Pour ce faire, nous disposons de données mensuelles ventilées par ligne depuis 2022 ainsi que de données annuelles ventilées par ligne depuis 2017 que nous extrapolerons mensuellement.

Une fois compilé le nombre mensuel de passagers, nous pourrons créer un fichier CSV qui ressemblera à celui-ci :

Year,Month,Passengers,Line
2017,1,549007,1
2017,1,515947,2
2017,1,770564,3
2017,1,621256,5
2017,1,429640,7
2017,1,520692,9
2017,1,322392,4
2017,1,95473,6
2017,1,18188,8
2017,1,0,10

Nous avons inclus dans notre fichier csv une ligne finale ",,,," qui nous permettra de savoir quand le fichier est terminé.

Mappage des fichiers CSV

Bien que le mappage soit déjà effectué dans le projet inclus dans cet article, nous allons le détailler pour les utilisateurs qui ne sont pas familiers avec Record Mapper.

Comme vous pouvez le voir dans l'image précédente, la première ligne sera l'en-tête du fichier et nous avons les données pour l'année, le mois, le flux de passagers et la ligne. Pour enregistrer le CSV dans notre base de données IRIS, nous utiliserons la fonctionnalité Record Mapper, à laquelle nous accéderons via le portail de gestion à partir des options de menu Interopérabilité -> Construire -> Assistant d'enregistrement CSV Record Wizard. Une fois l'accès obtenu, nous remplirons les champs de la manière indiquée :

N'oubliez pas que notre fichier CSV comporte des en-têtes, c'est pourquoi nous avons coché l'option L'échantillon comporte une ligne d'en-tête. À partir de ces informations, IRIS génère automatiquement le mappage CSV, en affichant l'écran suivant :

Nous n'aurons pas besoin de changer quoi que ce soit et en cliquant sur Générer (Generate), le système créera automatiquement toutes les classes nécessaires pour le mappage CSV à partir de nos productions.

Configuration de la production

Jetons un coup d'œil à la production configurée qui fonctionne dans notre projet :

Comme nous le voyons, notre production est composée de 3 Composants Métier. Voyons un peu plus en détail le rôle de chacun d'entre eux :

CSVIn

Ce service d'affaires est de la classe EnsLib.RecordMap.Service.FileService, il nous permettra de capturer les fichiers CSV qui se trouvent dans un chemin indiqué dans sa configuration. Pour chaque ligne du fichier CSV capturée, il créera un objet du type MLTEST.PassengersMap.Record défini par le RecordMap configuré, dans notre cas PassengersMap, et l'enverra au composant métier indiqué dans TargetConfigNames.

PredictionModelGeneration

Ce Processus Métier est défini par la BPL MLTEST.BP.PopulateTable à partir de laquelle nous allons transformer les données brutes reçues dans le format le plus intéressant pour l'entraînement de notre modèle. Jetons un coup d'œil à la BPL :

Voyons cela en détail dans le diagramme :

Tout d'abord, nous vérifierons si l'objet reçu correspond à une donnée réelle ou s'il s'agit de l'indicateur de fin de fichier défini précédemment par nous.

L'objet N'EST PAS la fin du fichier :

Si ce n'est pas la fin du fichier, nous allons transformer les données brutes reçues en un élément plus utilisable par notre modèle et pour cela nous avons défini une petite DTL : MLTEST.DT.ParseDate.

Cette DTL va seulement générer un objet de type MLTEST.Data.PassengersInfo avec une date de type DateTime formée avec les données du CSV. Lorsque la transformation sera terminée, la BPL aura juste à sauvegarder l'objet (dans la variable contextuelle PassengersInfo) dans notre base de données.

 set sc = context.PassengersInfo.%Save()
 if ($$$ISERR(sc))
 {
   set context.Result = "Error"
   set context.ErrorMessage = sc
 }
 else
 {
   set context.Result = "Success"
 }

L'objet se trouve à la fin du fichier :

Lorsque nous avons fini de lire le fichier, nous devons procéder au formatage des données pour que le modèle de Time Series (séries chronologiques) les comprenne. ATTENTION! Il faut prendre en considération les deux points suivants (et que je n'ai pas pris en compte 🙄) :

  1. Il est nécessaire d'avoir un champ de type DateTime qui sera utilisé pour continuer la série chronologique, un type Date ne sera pas suffisant..
  2. Les enregistrements doivent être ordonnés de l'enregistrement le plus ancien au plus récent pour que l'entraînement fonctionne correctement.

Si le modèle a déjà été généré, nous le supprimerons, ainsi que les données du tableau d'apprentissage. Le processus se poursuit comme suit :

 

Voyons chaque étape en détail :

  1. Nous effectuons une insertion massive avec les données transformées.
INSERT INTO MLTEST_Data.PassengersLine (DateOfData, Line1, Line2, Line3, Line4, Line5, Line6, Line7, Line8, Line9, Line10) 
SELECT DateOfData, 
(SELECT MAX(s1.Passengers) FROM MLTEST_Data.PassengersInfo s1 WHERE s1.Line = 1 AND s1.DateOfData = s.DateOfData) as Line1, 
(SELECT MAX(s2.Passengers) FROM MLTEST_Data.PassengersInfo s2 WHERE s2.Line = 2 AND s2.DateOfData = s.DateOfData) as Line2, 
(SELECT MAX(s3.Passengers) FROM MLTEST_Data.PassengersInfo s3 WHERE s3.Line = 3 AND s3.DateOfData = s.DateOfData) as Line3, 
(SELECT MAX(s4.Passengers) FROM MLTEST_Data.PassengersInfo s4 WHERE s4.Line = 4 AND s4.DateOfData = s.DateOfData) as Line4, 
(SELECT MAX(s5.Passengers) FROM MLTEST_Data.PassengersInfo s5 WHERE s5.Line = 5 AND s5.DateOfData = s.DateOfData) as Line5,
(SELECT MAX(s6.Passengers) FROM MLTEST_Data.PassengersInfo s6 WHERE s6.Line = 6 AND s6.DateOfData = s.DateOfData) as Line6, 
(SELECT MAX(s7.Passengers) FROM MLTEST_Data.PassengersInfo s7 WHERE s7.Line = 7 AND s7.DateOfData = s.DateOfData) as Line7, 
(SELECT MAX(s8.Passengers) FROM MLTEST_Data.PassengersInfo s8 WHERE s8.Line = 8 AND s8.DateOfData = s.DateOfData) as Line8, 
(SELECT MAX(s9.Passengers) FROM MLTEST_Data.PassengersInfo s9 WHERE s9.Line = 9 AND s9.DateOfData = s.DateOfData) as Line9, 
(SELECT MAX(s10.Passengers) FROM MLTEST_Data.PassengersInfo s10 WHERE s10.Line = 10 AND s10.DateOfData = s.DateOfData) as Line10 
FROM MLTEST_Data.PassengersInfo s GROUP BY DateOfData
  1. Nous créons notre modèle de type TIME SERIES (séries chronologiques), en définissant les valeurs à prédire et la colonne contenant les séries chronologiques de type DateTime (DateOfData) :
CREATE TIME SERIES MODEL PassengersPrediction 
PREDICTING (Line1,Line2,Line3,Line4,Line5,Line6,Line7,Line8,Line9,Line10) 
BY (DateOfData) 
FROM MLTEST_Data.PassengersLine USING {"Forward":3}
  1. Nous formons notre modèle :
TRAIN MODEL PassengersPrediction
  1. Enfin, nous appelons l'opération métier PredictionToCSV qui générera la prédiction et l'enregistrera dans un fichier CSV.

PredictionToCSV

Cette opération métier est extrêmement simple et tout cela grâce au projet @Evgeny Shvarov csvgen qui nous permet d'exporter directement les résultats d'une requête SQL vers un fichier CSV de manière directe. Le code de cette BO se trouve ici :

Class MLTEST.BO.PredictionToCSV Extends Ens.BusinessOperation
{

Parameter INVOCATION = "Queue";
Method ExportPrediction(pRequest As Ens.Request, pResponse As Ens.Response) As %Status
{
    set query="SELECT WITH PREDICTIONS (PassengersPrediction) * FROM MLTEST_Data.PassengersLine"
    w ##class(community.csvgen).SQLToCSV(",",1,"/shared/prediction.csv",query)

    Quit $$$OK
}

XData MessageMap
{
<MapItems>
  <MapItem MessageType="Ens.Request">
    <Method>ExportPrediction</Method>
  </MapItem>
</MapItems>
}

}

Comme vous pouvez le constater, la requête permettant d'obtenir la prédiction est très simple.

SELECT WITH PREDICTIONS (PassengersPrediction) * FROM MLTEST_Data.PassengersLine

Voyons le résultat généré dans le fichier /shared/prediction.csv.

Conclusions

Comme vous pouvez le constater, la création de modèles de prédiction de séries temporelles est relativement simple, vous devez juste vous assurer que la colonne de type DateTime est correctement ordonnée afin que l'entraînement fonctionne sans problème.

Si vous avez des remarques ou des suggestions, n'hésitez pas à les laisser dans la section des commentaires. Merci beaucoup pour le temps accordé !

Discussion (0)1
Connectez-vous ou inscrivez-vous pour continuer