Caricare i dati da file e altre origini

Informazioni su come caricare i dati in ML.NET per l'elaborazione e il training mediante l'API. I dati vengono inizialmente archiviati nei file o in altre origini dati, ad esempio database, JSON, XML o raccolte in memoria.

Se si usa Model Builder, vedere Caricare i dati di training in Model Builder.

Creare il modello di dati

ML.NET consente di definire modelli di dati tramite le classi. Si considerino, ad esempio, i dati di input seguenti:

Size (Sq. ft.), HistoricalPrice1 ($), HistoricalPrice2 ($), HistoricalPrice3 ($), Current Price ($)
700, 100000, 3000000, 250000, 500000
1000, 600000, 400000, 650000, 700000

Creare un modello di dati che rappresenti il frammento di codice seguente:

public class HousingData
{
    [LoadColumn(0)]
    public float Size { get; set; }

    [LoadColumn(1, 3)]
    [VectorType(3)]
    public float[] HistoricalPrices { get; set; }

    [LoadColumn(4)]
    [ColumnName("Label")]
    public float CurrentPrice { get; set; }
}

Annotare il modello di dati con gli attributi di colonna

Gli attributi comunicano a ML.NET più informazioni sul modello di data e l'origine dati.

L'attributo LoadColumn specifica gli indici colonna delle proprietà.

Importante

L'attributo LoadColumn è necessario solo per caricare dati da un file.

Caricare le colonne come:

  • Colonne singole, come Size e CurrentPrices nella classe HousingData.
  • Più colonne contemporaneamente sotto forma di vettore, come HistoricalPrices nella classe HousingData.

Se si dispone di una proprietà Vector, applicare l'attributo VectorType alla proprietà nel modello di dati. Tutti gli elementi nel vettore devono essere dello stesso tipo. Mantenere separate le colonne offre vantaggi in termini di semplicità e flessibilità di progettazione delle funzionalità, ma per un elevato numero di colonne, il funzionamento delle singole colonne influisce sulla velocità di training.

ML.NET opera attraverso i nomi di colonna. Se si desidera modificare il nome di una colonna cambiandolo rispetto al nome della proprietà, usare l'attributo ColumnName. Quando si creano oggetti in memoria, è ancora necessario usare il nome della proprietà. Tuttavia, per l'elaborazione dei dati e la creazione di modelli di Machine Learning, ML.NET esegue l'override e fa riferimento alla proprietà con il valore fornito nell'attributo ColumnName.

Caricare i dati da un unico file

Per caricare i dati da un file, usare il metodo LoadFromTextFile con il modello per i dati da caricare. Poiché il parametro separatorChar è delimitato da tabulazioni per impostazione predefinita, modificarlo per il file di dati in base alle esigenze. Se il file presenta un'intestazione, impostare il parametro hasHeader su true per ignorare la prima riga del file e iniziare a caricare i dati dalla seconda riga.

//Create MLContext
MLContext mlContext = new MLContext();

//Load Data
IDataView data = mlContext.Data.LoadFromTextFile<HousingData>("my-data-file.csv", separatorChar: ',', hasHeader: true);

Caricare i dati da più file

Nel caso in cui i dati siano archiviati in più file, e a condizione che lo schema dei dati sia lo stesso, ML.NET consente di caricare i dati da più file in una stessa directory o in directory diverse.

Caricare da file in una singola directory

Quando tutti i file di dati sono nella stessa directory, usare i caratteri jolly nel metodo LoadFromTextFile.

//Create MLContext
MLContext mlContext = new MLContext();

//Load Data File
IDataView data = mlContext.Data.LoadFromTextFile<HousingData>("Data/*", separatorChar: ',', hasHeader: true);

Caricare da file in più directory

Per caricare i dati da più directory, usare il metodo CreateTextLoader per creare un elemento TextLoader. Quindi, usare il metodo TextLoader.Load per specificare i percorsi dei singoli file. Non è possibile usare caratteri jolly.

//Create MLContext
MLContext mlContext = new MLContext();

// Create TextLoader
TextLoader textLoader = mlContext.Data.CreateTextLoader<HousingData>(separatorChar: ',', hasHeader: true);

// Load Data
IDataView data = textLoader.Load("DataFolder/SubFolder1/1.txt", "DataFolder/SubFolder2/1.txt");

Caricare dati da un database relazionale

ML.NET supporta il caricamento di dati da un'ampia gamma di database relazionali supportati da System.Data. Questi includono SQL Server, database SQL di Azure, Oracle, SQLite, PostgreSQL, Progress, IBM DB2 e molti altri.

Nota

Per usare DatabaseLoader, fare riferimento al pacchetto NuGet System.Data.SqlClient.

Dati un database con una tabella denominata House e lo schema seguente:

CREATE TABLE [House] (
    [HouseId] INT NOT NULL IDENTITY,
    [Size] INT NOT NULL,
    [NumBed] INT NOT NULL,
    [Price] REAL NOT NULL
    CONSTRAINT [PK_House] PRIMARY KEY ([HouseId])
);

I dati possono essere modellati in base a una classe come HouseData:

public class HouseData
{
    public float Size { get; set; }
    public float NumBed { get; set; }
    public float Price { get; set; }
}

All'interno dell'applicazione, creare un DatabaseLoader.

MLContext mlContext = new MLContext();

DatabaseLoader loader = mlContext.Data.CreateDatabaseLoader<HouseData>();

Definire la stringa di connessione e il comando SQL da eseguire nel database, quindi creare un'istanza DatabaseSource. Questo campione usa un database SQL Server LocalDB con un percorso file. Tuttavia, DatabaseLoader supporta qualsiasi altra stringa di connessione valida per i database locali e nel cloud.

Importante

Microsoft consiglia di usare il flusso di autenticazione più sicuro disponibile. Se ci si connette ad Azure SQL, le Identità gestite per le risorse Azure sono il metodo di autenticazione consigliato.

string connectionString = @"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=<YOUR-DB-FILEPATH>;Database=<YOUR-DB-NAME>;Integrated Security=True;Connect Timeout=30";

string sqlCommand = "SELECT CAST(Size as REAL) as Size, CAST(NumBed as REAL) as NumBed, Price FROM House";

DatabaseSource dbSource = new DatabaseSource(SqlClientFactory.Instance, connectionString, sqlCommand);

I dati numerici che non sono di tipo Real devono essere convertiti in Real. Il tipo Real è rappresentato come valore punto float a precisione singola o Single, il tipo di input previsto dagli algoritmi ML.NET. In questo campione, le colonne Size e NumBed sono numeri interi nel database. Usando la funzione predefinita CAST, viene convertita in Real. Poiché la proprietà Price è già di tipo Real, viene caricata così come è.

Usare il metodo Load per caricare i dati in un oggetto IDataView.

IDataView data = loader.Load(dbSource);

Caricare immagini

Per caricare i dati dell'immagine da una directory, creare prima di tutto un modello che includa il percorso e un'etichetta dell'immagine. ImagePath è il percorso assoluto dell'immagine nella directory dell'origine dati. Label è la classe o la categoria del file dell'immagine effettivo.

public class ImageData
{
    [LoadColumn(0)]
    public string ImagePath;

    [LoadColumn(1)]
    public string Label;
}

public static IEnumerable<ImageData> LoadImagesFromDirectory(string folder,
            bool useFolderNameAsLabel = true)
{
    string[] files = Directory.GetFiles(folder, "*", searchOption: SearchOption.AllDirectories);

    foreach (string file in files)
    {
        if (Path.GetExtension(file) != ".jpg")
            continue;

        string label = Path.GetFileName(file);

        if (useFolderNameAsLabel)
            label = Directory.GetParent(file).Name;
        else
        {
            for (int index = 0; index < label.Length; index++)
            {
                if (!char.IsLetter(label[index]))
                {
                    label = label.Substring(0, index);
                    break;
                }
            }
        }

        yield return new ImageData()
        {
            ImagePath = file,
            Label = label
        };
    }
}

Caricare quindi l'immagine:

IEnumerable<ImageData> images = LoadImagesFromDirectory(
                folder: "your-image-directory-path",
                useFolderNameAsLabel: true
                );

Per caricare immagini non elaborate nella memoria dalla directory, creare un modello per contenere la matrice di byte e l'etichetta dell'immagine non elaborata:

public class InMemoryImageData
{
    [LoadColumn(0)]
    public byte[] Image;

    [LoadColumn(1)]
    public string Label;
}

static IEnumerable<InMemoryImageData> LoadInMemoryImagesFromDirectory(
    string folder,
    bool useFolderNameAsLabel = true
    )
{
    string[] files = Directory.GetFiles(folder, "*",
        searchOption: SearchOption.AllDirectories);
    foreach (string file in files)
    {
        if (Path.GetExtension(file) != ".jpg")
            continue;

        string label = Path.GetFileName(file);
        if (useFolderNameAsLabel)
            label = Directory.GetParent(file).Name;
        else
        {
            for (int index = 0; index < label.Length; index++)
            {
                if (!char.IsLetter(label[index]))
                {
                    label = label.Substring(0, index);
                    break;
                }
            }
        }

        yield return new InMemoryImageData()
        {
            Image = File.ReadAllBytes(file),
            Label = label
        };

    }
}

Caricare i dati da altre origini

Oltre a caricare i dati archiviati nei file, ML.NET permette di caricare i dati da altre origini tra cui:

  • Raccolte in memoria
  • JSON/XML

Quando si usano origini di streaming, ML.NET prevede input in forma di raccolta in memoria. Pertanto, quando si usano origini come JSON/XML, assicurarsi di formattare i dati come una raccolta in memoria.

Considerando la raccolta in memoria seguente:

HousingData[] inMemoryCollection = new HousingData[]
{
    new HousingData
    {
        Size =700f,
        HistoricalPrices = new float[]
        {
            100000f, 3000000f, 250000f
        },
        CurrentPrice = 500000f
    },
    new HousingData
    {
        Size =1000f,
        HistoricalPrices = new float[]
        {
            600000f, 400000f, 650000f
        },
        CurrentPrice=700000f
    }
};

Caricare la raccolta in memoria in un'interfaccia IDataView con il metodo LoadFromEnumerable:

Importante

LoadFromEnumerable presuppone che l'oggetto IEnumerable da cui viene caricato sia di tipo thread-safe.

// Create MLContext
MLContext mlContext = new MLContext();

//Load Data
IDataView data = mlContext.Data.LoadFromEnumerable<HousingData>(inMemoryCollection);

Passaggi successivi