ML-2 : Préparation des données et ingénierie des features

Navigation : Index | << ML-1 | Suivant >>

Objectifs d’apprentissage

A la fin de ce notebook, vous saurez : 1. Charger des données depuis un fichier CSV avec TextLoader 2. Explorer et manipuler un IDataView 3. Appliquer des transformations : encoding, normalisation, concaténation 4. Construire un pipeline de feature engineering complet

Prérequis

  • ML-1-Introduction complété
  • Fichier taxi-fare.csv disponible

Durée estimée : 40-50 minutes


Préparation des Données et Ingénierie des Caractéristiques

Les données sont cruciales pour entraîner et préparer un modèle. Dans ce notebook, nous allons couvrir comment charger des données dans ML.NET et s’assurer qu’elles sont dans le bon format pour que ML.NET puisse les utiliser.

Chargement des données dans ML.NET

Qu’est-ce qu’un IDataView?

Le IDataView est le format de données que ML.NET charge pour l’entraînement. Il s’agit d’un ensemble d’interfaces et de composants qui fournissent un traitement efficace et compositionnel des données schématisées pour les applications de machine learning et d’analytique avancée. Il est conçu pour gérer de manière efficace les données de haute dimension et les grands ensembles de données.

Comment créer un IDataView

Vous pouvez créer un IDataView en utilisant l’une des méthodes de chargement des données suivantes :

  • TextLoader
  • LoadFromEnumerable
  • DatabaseLoader
  • LoadFromTextFile

Pour plus de documentation et d’exemples, consultez Charger les données à partir de fichiers et d’autres sources.

#r "nuget: Microsoft.ML, 5.0.0"

using Microsoft.ML;
using Microsoft.ML.Data;
using Microsoft.ML.Transforms;

MLContext mlContext = new MLContext();
Installing Packages
  • Microsoft.ML

Télécharger ou localiser les données

Le code suivant essaie de localiser le fichier de données dans quelques emplacements connus ou le téléchargera à partir de l’emplacement GitHub connu.

using System;
using System.IO;
using System.Net;

string EnsureDataSetDownloaded(string fileName)
{
    // Ce chemin est utilisé si le dépôt a été cloné.
    var filePath = Path.Combine(Directory.GetCurrentDirectory(),"data", fileName);

    if (!File.Exists(filePath))
    {
        // Ce chemin est utilisé si le fichier a déjà été téléchargé.
        filePath = Path.Combine(Directory.GetCurrentDirectory(), fileName);
    }

    if (!File.Exists(filePath))
    {
        using (var client = new WebClient())
        {
            client.DownloadFile($"https://raw.githubusercontent.com/dotnet/csharp-notebooks/main/machine-learning/data/{fileName}", filePath);
        }
        Console.WriteLine($"Téléchargé {fileName} dans le dossier du notebook");
    }
    else
    {
        Console.WriteLine($"{fileName} présent dans le dossier du notebook");
    }

    return filePath;
}

Chargement depuis un fichier

Un TextLoader peut charger un fichier structuré dans un IDataView. Les informations structurées sont représentées comme des colonnes et des lignes de données.

public class ModelInput
{
    [LoadColumn(0)]
    [ColumnName(@"vendor_id")]
    public string Vendor_id { get; set; }

    [LoadColumn(1)]
    [ColumnName(@"rate_code")]
    public float Rate_code { get; set; }

    [LoadColumn(2)]
    [ColumnName(@"passenger_count")]
    public float Passenger_count { get; set; }

    [LoadColumn(3)]
    [ColumnName(@"trip_time_in_secs")]
    public float Trip_time_in_secs { get; set; }

    [LoadColumn(4)]
    [ColumnName(@"trip_distance")]
    public float Trip_distance { get; set; }

    [LoadColumn(5)]
    [ColumnName(@"payment_type")]
    public string Payment_type { get; set; }

    [LoadColumn(6)]
    [ColumnName(@"fare_amount")]
    public float Fare_amount { get; set; }
}

MLContext mlContext = new MLContext();

var trainDataPath = EnsureDataSetDownloaded("taxi-fare.csv");

// Créer un TextLoader basé sur le type ModelInput.
TextLoader textLoader = mlContext.Data.CreateTextLoader<ModelInput>(separatorChar: ',', hasHeader: true);

// Charger les données dans un IDataView. La méthode Load() peut prendre en charge plusieurs fichiers.
// Les fichiers doivent avoir le même caractère séparateur, en-tête, noms de colonnes, etc.
IDataView data = textLoader.Load(trainDataPath);

data.Preview(1)
taxi-fare.csv présent dans le dossier du notebook
7 columns, 1 rows
Schema
[ vendor_id: String, rate_code: Single, passenger_count: Single, trip_time_in_secs: Single, trip_distance: Single, payment_type: String, fare_amount: Single ]
Count
7
(values)
index value
0
vendor_id: String
Name
vendor_id
Index
0
IsHidden
False
Type
String
Annotations
Schema
[ ]
Count
0
(values) (empty)
1
rate_code: Single
Name
rate_code
Index
1
IsHidden
False
Type
Single
RawType System.Single
Annotations
Schema
[ ]
Count
0
(values) (empty)
2
passenger_count: Single
Name
passenger_count
Index
2
IsHidden
False
Type
Single
RawType System.Single
Annotations
Schema
[ ]
Count
0
(values) (empty)
3
trip_time_in_secs: Single
Name
trip_time_in_secs
Index
3
IsHidden
False
Type
Single
RawType System.Single
Annotations
Schema
[ ]
Count
0
(values) (empty)
4
trip_distance: Single
Name
trip_distance
Index
4
IsHidden
False
Type
Single
RawType System.Single
Annotations
Schema
[ ]
Count
0
(values) (empty)
5
payment_type: String
Name
payment_type
Index
5
IsHidden
False
Type
String
Annotations
Schema
[ ]
Count
0
(values) (empty)
6
fare_amount: Single
Name
fare_amount
Index
6
IsHidden
False
Type
Single
RawType System.Single
Annotations
Schema
[ ]
Count
0
(values) (empty)
ColumnView
index value
0
vendor_id: String
Column
vendor_id: String
Name
vendor_id
Index
0
IsHidden
False
Type
String
Annotations
Schema
[ ]
Count 0
(values) (empty)
Values
index value
0 CMT
1
rate_code: Single
Column
rate_code: Single
Name
rate_code
Index
1
IsHidden
False
Type
Single
RawType System.Single
Annotations
Schema
[ ]
Count 0
(values) (empty)
Values
index value
0
1
2
passenger_count: Single
Column
passenger_count: Single
Name
passenger_count
Index
2
IsHidden
False
Type
Single
RawType System.Single
Annotations
Schema
[ ]
Count 0
(values) (empty)
Values
index value
0
1
3
trip_time_in_secs: Single
Column
trip_time_in_secs: Single
Name
trip_time_in_secs
Index
3
IsHidden
False
Type
Single
RawType System.Single
Annotations
Schema
[ ]
Count 0
(values) (empty)
Values
index value
0
1271
4
trip_distance: Single
Column
trip_distance: Single
Name
trip_distance
Index
4
IsHidden
False
Type
Single
RawType System.Single
Annotations
Schema
[ ]
Count 0
(values) (empty)
Values
index value
0
3.8
5
payment_type: String
Column
payment_type: String
Name
payment_type
Index
5
IsHidden
False
Type
String
Annotations
Schema
[ ]
Count 0
(values) (empty)
Values
index value
0 CRD
6
fare_amount: Single
Column
fare_amount: Single
Name
fare_amount
Index
6
IsHidden
False
Type
Single
RawType System.Single
Annotations
Schema
[ ]
Count 0
(values) (empty)
Values
index value
0
17.5
RowView
index value
0
7 columns
Values
index value
0
[vendor_id, CMT]
Key
vendor_id
Value CMT
1
[rate_code, 1]
Key
rate_code
Value
1
2
[passenger_count, 1]
Key
passenger_count
Value
1
3
[trip_time_in_secs, 1271]
Key
trip_time_in_secs
Value
1271
4
[trip_distance, 3,8]
Key
trip_distance
Value
3.8
5
[payment_type, CRD]
Key
payment_type
Value CRD
6
[fare_amount, 17,5]
Key
fare_amount
Value
17.5

Chargement d’une collection en mémoire

ML.NET prend en charge le chargement des données à partir d’une collection en mémoire. Cela facilite le chargement à partir d’un fichier JSON ou XML en utilisant C#. Apprenez comment désérialiser JSON avec C# ou utilisez XML serializer pour obtenir ces fichiers en mémoire.

Une fois que vous avez la collection de données en mémoire, vous pouvez la charger dans ML.NET avec la méthode LoadFromEnumerable.

ModelInput[] inMemoryCollection = new ModelInput[]
{
    new ModelInput
    {
        Vendor_id = "CMT",
        Rate_code = 1,
        Passenger_count = 1,
        Trip_time_in_secs = 1271,
        Trip_distance = 3.8f,
        Payment_type = "CRD",
        Fare_amount = 17.5f,
    },
    new ModelInput
    {
        Vendor_id = "VST",
        // Rate_code manquant : pour un Single, l'absence se marque NaN (le defaut C# 0.0f serait une valeur presente)
        Rate_code = float.NaN,
        Passenger_count = 1,
        Trip_time_in_secs = 474,
        Trip_distance = 1.5f,
        Payment_type = "CSH",
        Fare_amount = 8,
    }
};

// Créer un MLContext
MLContext mlContext = new MLContext();

// Charger les données
IDataView data = mlContext.Data.LoadFromEnumerable<ModelInput>(inMemoryCollection);

// Afficher les données chargées
var preview = data.Preview();
display(preview);
7 columns, 2 rows
Schema
[ vendor_id: String, rate_code: Single, passenger_count: Single, trip_time_in_secs: Single, trip_distance: Single, payment_type: String, fare_amount: Single ]
Count
7
(values)
index value
0
vendor_id: String
Name
vendor_id
Index
0
IsHidden
False
Type
String
Annotations
Schema
[ ]
Count
0
(values) (empty)
1
rate_code: Single
Name
rate_code
Index
1
IsHidden
False
Type
Single
RawType System.Single
Annotations
Schema
[ ]
Count
0
(values) (empty)
2
passenger_count: Single
Name
passenger_count
Index
2
IsHidden
False
Type
Single
RawType System.Single
Annotations
Schema
[ ]
Count
0
(values) (empty)
3
trip_time_in_secs: Single
Name
trip_time_in_secs
Index
3
IsHidden
False
Type
Single
RawType System.Single
Annotations
Schema
[ ]
Count
0
(values) (empty)
4
trip_distance: Single
Name
trip_distance
Index
4
IsHidden
False
Type
Single
RawType System.Single
Annotations
Schema
[ ]
Count
0
(values) (empty)
5
payment_type: String
Name
payment_type
Index
5
IsHidden
False
Type
String
Annotations
Schema
[ ]
Count
0
(values) (empty)
6
fare_amount: Single
Name
fare_amount
Index
6
IsHidden
False
Type
Single
RawType System.Single
Annotations
Schema
[ ]
Count
0
(values) (empty)
ColumnView
index value
0
vendor_id: String
Column
vendor_id: String
Name
vendor_id
Index
0
IsHidden
False
Type
String
Annotations
Schema
[ ]
Count 0
(values) (empty)
Values
index value
0 CMT
1 VST
1
rate_code: Single
Column
rate_code: Single
Name
rate_code
Index
1
IsHidden
False
Type
Single
RawType System.Single
Annotations
Schema
[ ]
Count 0
(values) (empty)
Values
index value
0
1
1
NaN
2
passenger_count: Single
Column
passenger_count: Single
Name
passenger_count
Index
2
IsHidden
False
Type
Single
RawType System.Single
Annotations
Schema
[ ]
Count 0
(values) (empty)
Values
index value
0
1
1
1
3
trip_time_in_secs: Single
Column
trip_time_in_secs: Single
Name
trip_time_in_secs
Index
3
IsHidden
False
Type
Single
RawType System.Single
Annotations
Schema
[ ]
Count 0
(values) (empty)
Values
index value
0
1271
1
474
4
trip_distance: Single
Column
trip_distance: Single
Name
trip_distance
Index
4
IsHidden
False
Type
Single
RawType System.Single
Annotations
Schema
[ ]
Count 0
(values) (empty)
Values
index value
0
3.8
1
1.5
5
payment_type: String
Column
payment_type: String
Name
payment_type
Index
5
IsHidden
False
Type
String
Annotations
Schema
[ ]
Count 0
(values) (empty)
Values
index value
0 CRD
1 CSH
6
fare_amount: Single
Column
fare_amount: Single
Name
fare_amount
Index
6
IsHidden
False
Type
Single
RawType System.Single
Annotations
Schema
[ ]
Count 0
(values) (empty)
Values
index value
0
17.5
1
8
RowView
index value
0
7 columns
Values
index value
0
[vendor_id, CMT]
Key
vendor_id
Value CMT
1
[rate_code, 1]
Key
rate_code
Value
1
2
[passenger_count, 1]
Key
passenger_count
Value
1
3
[trip_time_in_secs, 1271]
Key
trip_time_in_secs
Value
1271
4
[trip_distance, 3,8]
Key
trip_distance
Value
3.8
5
[payment_type, CRD]
Key
payment_type
Value CRD
6
[fare_amount, 17,5]
Key
fare_amount
Value
17.5
1
7 columns
Values
index value
0
[vendor_id, VST]
Key
vendor_id
Value VST
1
[rate_code, NaN]
Key
rate_code
Value
NaN
2
[passenger_count, 1]
Key
passenger_count
Value
1
3
[trip_time_in_secs, 474]
Key
trip_time_in_secs
Value
474
4
[trip_distance, 1,5]
Key
trip_distance
Value
1.5
5
[payment_type, CSH]
Key
payment_type
Value CSH
6
[fare_amount, 8]
Key
fare_amount
Value
8

Différence entre DataFrame et IDataView

Vous avez peut-être entendu parler du type DataFrame. C’est un autre outil pour charger, visualiser et manipuler des données, courant dans les notebooks. Il implémente un IDataView, il peut donc être facilement passé à ML.NET.

DataFrame et IDataView sont très similaires en ce sens qu’ils sont tous deux des moyens de représenter des données sous forme tabulaire et d’appliquer des transformations. Voici quelques différences clés :

  • DataFrame ne prend en charge que le chargement de fichiers délimités.
  • DataFrame fonctionne en mémoire, vous êtes donc limité par la quantité de mémoire de votre PC.

Le DataFrame est recommandé pour effectuer des tâches telles que l’analyse exploratoire des données sur un échantillon de vos données. Consultez le notebook de référence REF-Data Processing pour un exemple d’utilisation des DataFrames pour manipuler un fichier de données pour l’entraînement.

IDataView est recommandé pour l’entraînement sur des ensembles de données plus grands, et ce qui est utilisé pour les exemples dans ce notebook. Les ensembles de données plus grands dans ce cas sont définis comme des ensembles de données qui ne peuvent pas tenir en mémoire.

Transformations des données

ML.NET prend en charge une variété de transformations de données qui convertiront les données dans le format requis et vous aideront à apporter des corrections à vos données. Parmi les opérations courantes, citons la manipulation des colonnes, la normalisation des valeurs, le remplacement des valeurs manquantes, la conversion des valeurs, etc.

Pour plus d’informations, consultez Transformations des données.

Données catégorielles

L’encodage one-hot (Hastie, Tibshirani & Friedman, 2009) est une transformation importante pour les données contenant des catégories. Les algorithmes ML nécessitent des données numériques, ils ne savent pas comment traiter les chaînes représentant des catégories. Les colonnes vendor_id et payment_type sont catégoriques, le fournisseur peut être “CMD” ou “VST” et le paiement peut être “CReDit” ou “CaSH”. L’encodage one-hot prend les valeurs de chaîne passées et les convertit en données numériques.

IEstimator<ITransformer> pipeline = mlContext.Transforms.Categorical.OneHotEncoding(
    new[] 
    { new InputOutputColumnPair(@"vendor_id"), 
    new InputOutputColumnPair(@"payment_type")},
    OneHotEncodingEstimator.OutputKind.Binary);
Console.WriteLine("Pipeline OneHotEncoding configure.");
Pipeline OneHotEncoding configure.

Testons la transformation ci-dessus sur les colonnes vendor_id et payment_type. Le résultat devrait être une valeur vectorielle pour chaque catégorie. Dans le cas de Vendor_Id, CMT devient 000 et VST devient 001. Nous allons créer une nouvelle classe ModelInputTransformed pour les nouveaux types convertis.

using System.Numerics;

public class ModelInputTransformed
{
    [LoadColumn(0)]
    [ColumnName(@"vendor_id")]
    public VBuffer<Single> Vendor_id { get; set; }

    [LoadColumn(1)]
    [ColumnName(@"rate_code")]
    public float Rate_code { get; set

; }

    [LoadColumn(2)]
    [ColumnName(@"passenger_count")]
    public float Passenger_count { get; set; }

    [LoadColumn(3)]
    [ColumnName(@"trip_time_in_secs")]
    public float Trip_time_in_secs { get; set; }

    [LoadColumn(4)]
    [ColumnName(@"trip_distance")]
    public float Trip_distance { get; set; }

    [LoadColumn(5)]
    [ColumnName(@"payment_type")]
    public VBuffer<Single> Payment_type { get; set; }

    [LoadColumn(6)]
    [ColumnName(@"fare_amount")]
    public float Fare_amount { get; set; }
}

// Exécuter la transformation
IDataView transformedData = pipeline.Fit(data).Transform(data);
var convertedData = mlContext.Data.CreateEnumerable<ModelInputTransformed>(transformedData, true);

// Encodage one-hot de deux colonnes 'vendor_id' et 'payment_type'.
Console.WriteLine("Vendor_Id" +"\t" + "Payment_Type"); 
foreach (ModelInputTransformed item in convertedData.Take(10))
{    
    Console.WriteLine("{0}\t\t{1}", string.Join(" ", item.Vendor_id.DenseValues()),
                    string.Join(" ", item.Payment_type.DenseValues()));
}
Vendor_Id   Payment_Type
0 0 0       0 0 0
0 0 1       0 0 1

Remplacer les valeurs manquantes

Une autre opération courante est de remplacer les valeurs manquantes. Ici, nous utilisons le mode de remplacement par défaut, qui remplace la valeur par la valeur par défaut de son type.

pipeline = pipeline.Append(mlContext.Transforms.ReplaceMissingValues(
    new[] { new InputOutputColumnPair(@"rate_code", @"rate_code"), 
    new InputOutputColumnPair(@"passenger_count", @"passenger_count"), 
    new InputOutputColumnPair(@"trip_time_in_secs", @"trip_time_in_secs"), 
    new InputOutputColumnPair(@"trip_distance", @"trip_distance") }));
Console.WriteLine("Transforms ReplaceMissingValues ajoutes au pipeline.");
Transforms ReplaceMissingValues ajoutes au pipeline.

Encore une fois, exécutons la transformation et jetons un coup d’œil à la valeur remplie. Il nous manquait le rate_code pour le deuxième objet factice : la cellule ci-dessous imprime la valeur brute (NaN) puis la valeur transformée, pour que la substitution soit constatée plutôt que supposée.

// Valeur brute, avant toute transformation : le NaN pose dans les donnees
var brut = mlContext.Data.CreateEnumerable<ModelInput>(data, true);

IDataView  transformedData = pipeline.Fit(data).Transform(data);
var convertedData = mlContext.Data.CreateEnumerable<ModelInputTransformed>(transformedData, true);

Console.WriteLine("Rate_code brut      : " + brut.ElementAt(1).Rate_code);
Console.WriteLine("Rate_code transforme: " + convertedData.ElementAt(1).Rate_code);

"Rate_code: " + convertedData.ElementAt(1).Rate_code
Rate_code brut      : NaN
Rate_code transforme: 0
Rate_code: 0

Concaténer les colonnes de caractéristiques

Concaténons maintenant toutes nos colonnes de caractéristiques en une seule colonne vectorielle. De nombreux formateurs ML s’attendent à ce que les caractéristiques soient de type vecteur, car l’application d’opérations sur un vecteur est plus efficace.

pipeline = pipeline.Append(mlContext.Transforms.Concatenate(
    @"Features", new[] { @"vendor_id", @"payment_type", @"rate_code", @"passenger_count", @"trip_time_in_secs", @"trip_distance" }));
Console.WriteLine("Concatenation des features configuree.");

// Verifier que la colonne Features est bien presente dans le schema transforme
var colonnes = pipeline.Fit(data).Transform(data).Schema.Select(c => c.Name);
Console.WriteLine("Schema apres transformations : " + string.Join(", ", colonnes));
"Colonne Features dans le pipeline : " + colonnes.Contains("Features")
Concatenation des features configuree.
Schema apres transformations : vendor_id, vendor_id, vendor_id, rate_code, rate_code, passenger_count, passenger_count, trip_time_in_secs, trip_time_in_secs, trip_distance, trip_distance, payment_type, payment_type, payment_type, fare_amount, Features
Colonne Features dans le pipeline : True

Nous avons maintenant un IDataView chargé et un pipeline prêt pour l’entraînement.

Point de vigilance : Append renvoie une nouvelle chaîne d’estimateurs, il ne modifie pas celle sur laquelle il est appelé. Écrire pipeline.Append(...) sans réaffecter laisse donc le pipeline inchangé ; c’est pourquoi les deux cellules ci-dessus écrivent pipeline = pipeline.Append(...), et le schéma affiché est la preuve que les transformations ont été retenues.

Exercices supplémentaires

Les exercices suivants approfondissent les transformations de données et le feature engineering avec ML.NET.

Exercice 1 : Featurisation de texte personnalisée

Créez un pipeline utilisant FeaturizeText (vectorisation par n-grams et hachage, Manning, Raghavan & Schütze, 2008 ; Weinberger et al., 2009) avec des options personnalisees (n-grams de mots, n-grams de caractères) et comparez les performances avec les paramètres par defaut.

Objectifs : 1. Preparer un jeu de données contenant du texte (avis clients, commentaires, etc.) 2. Construire un pipeline avec FeaturizeText par defaut et entrainer un modèle 3. Construire un second pipeline avec FeaturizeTextOptions personnalise (n-grams, char n-grams) 4. Comparer l’accuracy des deux modèles et analyser l’impact de la featurisation

Indice : Utilisez new FeaturizeTextOptions { WordFeatureExtractor = new WordBagEstimator.Options { NgramLength = 2 }, CharFeatureExtractor = new WordBagEstimator.Options { NgramLength = 3 } }. Observez comment les n-grams capturent des sequences de mots que les unigrams ignorent.

// Exercice 1 : Featurisation de texte personnalisee
// TODO etudiant : Creez un pipeline avec FeaturizeText et comparez avec les parametres par defaut
// Indice : utilisez FeaturizeTextOptions pour configurer word n-grams, char n-grams
// Etape 1 : chargez un jeu de donnees avec du texte (par ex. des avis produits)
// Etape 2 : creez un pipeline avec FeaturizeText par defaut et entrainez un modele
// Etape 3 : creez un second pipeline avec FeaturizeTextOptions personnalises
// Etape 4 : comparez l'accuracy des deux modeles

Console.WriteLine("Exercice a completer : featurisation de texte personnalisee");
Exercice a completer : featurisation de texte personnalisee

Exercice 2 : Feature cross - combinaison de features catégorielles

Combinez deux variables categorielles en une seule feature croisee pour capturer leurs interactions, puis comparez les performances du modèle avec et sans cette transformation.

Objectifs : 1. Ajouter une colonne categorielle supplementaire (ex : saison) aux données taxi 2. Concatener vendor_id et la nouvelle colonne en un seul feature croise via mlContext.Transforms.Expression ou CustomMapping 3. Entrainer un modèle avec le cross-feature et un modèle sans 4. Comparer les metriques de regression (R2, RMSE) entre les deux approches

Indice : Un cross-feature capture les interactions entre variables. Par exemple, vendor “CMT” en ete peut avoir un comportement différent de vendor “VST” en hiver. Concatenez les deux colonnes string puis appliquez un OneHotEncoding sur le résultat.

// Exercice 2 : Feature cross - combinaison de features categorielles
// TODO etudiant : Combinez deux features categorielles en une seule feature croisee
// Indice : concatenez deux colonnes string avant le OneHotEncoding
// Etape 1 : ajoutez une colonne "season" (ete, hiver, printemps, automne) aux donnees taxis
// Etape 2 : combinez vendor_id et season en une seule colonne via une expression custom
// Etape 3 : entrainez un modele avec et sans le cross-feature
// Etape 4 : comparez les metriques (R2, RMSE) dans les deux cas

Console.WriteLine("Exercice a completer : feature cross");
Exercice a completer : feature cross

Exercice : Feature engineering pour la prédiction de prix immobiliers

En vous basant sur l’exemple des taxis, créez un pipeline de préparation de données pour prédire le prix de vente de maisons.

Objectifs

  1. Définir la classe HouseInput avec les colonnes : quartier (catégoriel), surface (numérique), nb_chambres (numérique), prix (label)
  2. Appliquer l’encodage one-hot sur la colonne catégorielle quartier
  3. Remplacer les valeurs manquantes pour les colonnes numériques
  4. Concaténer toutes les features en une seule colonne Features

Indices - Utilisez [LoadColumn] pour mapper les colonnes CSV - OneHotEncoding pour les catégories (quartier) - ReplaceMissingValues pour les valeurs numériques manquantes - Concatenate pour créer le vecteur de features final

// Exercice : Feature engineering pour maisons
// Complétez les parties TODO pour créer un pipeline de préparation

// TODO: Définir la classe HouseInput avec les attributs LoadColumn
public class HouseInput
{
    // Colonne 0: quartier (string, catégoriel)
    // Colonne 1: surface en m² (float)
    // Colonne 2: nb_chambres (float)
    // Colonne 3: prix (float, label)
}

// TODO: Créer un MLContext
MLContext houseContext = null;

// TODO: Définir les données d'exemple (3-4 maisons)
HouseInput[] houses = 
{
    // Exemple: { Quartier = "Centre", Surface = 120, NbChambres = 4, Prix = 350000 },
    // Ajoutez d'autres exemples avec différents quartiers
};

// TODO: Charger les données en IDataView
IDataView houseData = null;

// TODO: Créer le pipeline avec OneHotEncoding pour le quartier
IEstimator<ITransformer> housePipeline = null;

// TODO: Ajouter ReplaceMissingValues pour les colonnes numériques
// housePipeline = housePipeline.Append(...)

// TODO: Ajouter Concatenate pour créer la colonne Features
// housePipeline = housePipeline.Append(...)

// TODO: Appliquer les transformations et afficher le résultat
IDataView transformedHouses = null;

if (transformedHouses != null)
{
    var preview = transformedHouses.Preview();
    display(preview);
}
else
{
    Console.WriteLine("Exercice a completer : implementez les TODO ci-dessus");
}
Exercice a completer : implementez les TODO ci-dessus

Résumé

Ce notebook a couvert la préparation des données et l’ingénierie des features avec ML.NET :

Concept Description
TextLoader Chargement structuré depuis un fichier CSV
LoadFromEnumerable Chargement depuis une collection en mémoire
OneHotEncoding Conversion des variables catégorielles en vecteurs binaires
ReplaceMissingValues Remplacement des valeurs manquantes
Concatenate Fusion de colonnes en un vecteur de features

Points clés : - IDataView est le format central pour toutes les données ML.NET - Les transformations sont définies dans un pipeline et appliquées avec Fit().Transform() - L’encodage one-hot est indispensable pour les colonnes catégorielles - La concaténation des features prépare les données pour l’entraînement

Navigation : Index | << ML-1 Introduction | Suivant >> ML-3 Entrainement&AutoML

Références

Transformations de features - Hastie, T., Tibshirani, R., & Friedman, J. (2009). The Elements of Statistical Learning: Data Mining, Inference, and Prediction (2nd ed.). Springer. — variables catégorielles et encodage one-hot (section 3.6), termes d’interaction (feature cross). - Manning, C. D., Raghavan, P., & Schütze, H. (2008). Introduction to Information Retrieval. Cambridge University Press. — modélisation par n-grams de mots et de caractères (featurisation de texte). - Weinberger, K., Dasgupta, A., Langford, J., Smola, A., & Attenberg, J. (2009). Feature Hashing for Large Scale Multitask Learning. ICML. — « hashing trick », sous-jacent à la vectorisation FeaturizeText de ML.NET.

Framework (ML.NET) - Ahmed, Z., Amizadeh, S., Bilenko, M., et al. (2019). DOI: 10.1145/3292500.3330667 — Machine Learning at Microsoft with ML.NET. ACM SIGKDD (KDD).

Retour au sommet