Przygotowywanie danych do tworzenia modelu

Dowiedz się, jak używać ML.NET do przygotowywania danych do dodatkowego przetwarzania lub tworzenia modelu.

Dane są często nieczyste i rozrzedzone. ML.NET algorytmy uczenia maszynowego oczekują, że dane wejściowe lub funkcje będą znajdować się w jednym wektorze liczbowym. Podobnie wartość do przewidywania (etykiety), zwłaszcza gdy są to dane podzielone na kategorie, musi być zakodowana. Dlatego jednym z celów przygotowywania danych jest pobranie danych do formatu oczekiwanego przez algorytmy ML.NET.

Dzielenie danych na zestawy treningowe i testowe

W poniższej sekcji opisano typowe problemy występujące podczas trenowania modelu znanego jako nadmierne dopasowanie i niedopasowanie. Podzielenie danych i walidacji modeli przy użyciu zestawu przechowywanego może pomóc w zidentyfikowaniu i wyeliminowaniu tych problemów.

Nadmierne dopasowanie i niedopasowanie

Nadmierne dopasowanie i niedopasowanie to dwa najczęstsze problemy występujące podczas trenowania modelu. Niedopasowanie oznacza, że wybrany trener nie jest wystarczająco zdolny do dopasowania zestawu danych treningowych i zwykle powoduje wysoką utratę podczas trenowania i niskiej oceny/metryki w zestawie danych testowych. Aby rozwiązać ten problem, należy wybrać bardziej zaawansowany model lub wykonać więcej inżynierii cech. Nadmierne dopasowanie jest odwrotne, co dzieje się, gdy model zbyt dobrze uczy się danych treningowych. Zwykle skutkuje to niską utratą metryki podczas trenowania, ale wysoką stratą w zestawie danych testowych.

Dobrą analogią dla tych pojęć jest badanie egzaminu. Załóżmy, że znasz pytania i odpowiedzi z wyprzedzeniem. Po studiach przejmiesz test i uzyskasz doskonały wynik. Dobra wiadomość! Jednak po ponownym otrzymaniu egzaminu z pytaniami rozmieszanymi i nieco innym sformułowaniem uzyskasz niższy wynik. Sugeruje to, że zapamiętałeś odpowiedzi i w rzeczywistości nie dowiedziałeś się, na których pojęcia były testowane. Jest to przykład nadmiernego dopasowania. Niedopasowanie jest przeciwieństwem, w którym podane materiały badawcze nie reprezentują dokładnie tego, co oceniasz na egzaminie. W rezultacie uciekasz się do odgadnięcia odpowiedzi, ponieważ nie masz wystarczającej wiedzy, aby odpowiedzieć poprawnie.

Dzielenie danych

Pobierz następujące dane wejściowe i załaduj je do wywołania IDataViewdata:

var homeDataList = new HomeData[]
{
    new()
    {
        NumberOfBedrooms = 1f,
        Price = 100_000f
    },
    new()
    {
        NumberOfBedrooms = 2f,
        Price = 300_000f
    },
    new()
    {
        NumberOfBedrooms = 6f,
        Price = 600_000f
    },
    new()
    {
        NumberOfBedrooms = 3f,
        Price = 300_000f
    },
    new()
    {
        NumberOfBedrooms = 2f,
        Price = 200_000f
    }
};

Aby podzielić dane na zestawy trenowania/testowania TrainTestSplit(IDataView, Double, String, Nullable<Int32>) , użyj metody .

// Apply filter
TrainTestData dataSplit = mlContext.Data.TrainTestSplit(data, testFraction: 0.2);

Parametr testFraction służy do 0,2 lub 20% zestawu danych do testowania. Pozostałe 80% jest używane do trenowania.

Wynik jest DataOperationsCatalog.TrainTestData z dwoma widokami IDataView, do których można uzyskać dostęp za pośrednictwem i TrainSetTestSet.

Filtrowanie danych

Czasami nie wszystkie dane w zestawie danych są istotne dla analizy. Podejście do usuwania nieistotnych danych polega na filtrowaniu. Zawiera DataOperationsCatalog zestaw operacji filtrowania, które przyjmują IDataView wszystkie dane i zwracają widok IDataView zawierający tylko punkty danych. Należy pamiętać, że ponieważ operacje filtrowania nie IEstimator są lub ITransformer podobne do tych w elemecie TransformsCatalog, nie mogą być uwzględniane jako część EstimatorChain potoku przygotowywania danych ani TransformerChain .

Pobierz następujące dane wejściowe i załaduj je do wywołania IDataViewdata:

HomeData[] homeDataList = new HomeData[]
{
    new ()
    {
        NumberOfBedrooms=1f,
        Price=100000f
    },
    new ()
    {
        NumberOfBedrooms=2f,
        Price=300000f
    },
    new ()
    {
        NumberOfBedrooms=6f,
        Price=600000f
    }
};

Aby filtrować dane na podstawie wartości kolumny, użyj FilterRowsByColumn metody .

// Apply filter
IDataView filteredData = mlContext.Data.FilterRowsByColumn(data, "Price", lowerBound: 200000, upperBound: 1000000);

Powyższy przykład pobiera wiersze w zestawie danych z ceną z zakresu od 200000 do 1000000. Wynik zastosowania tego filtru zwróci tylko dwa ostatnie wiersze w danych i wykluczy pierwszy wiersz, ponieważ jego cena wynosi 100000, a nie między określonym zakresem.

Zastępowanie brakujących wartości

Brakujące wartości są typowym wystąpieniem w zestawach danych. Jednym z podejść do radzenia sobie z brakującymi wartościami jest zastąpienie ich wartością domyślną dla danego typu, jeśli jakakolwiek lub inna znacząca wartość, taka jak średnia wartość w danych.

Pobierz następujące dane wejściowe i załaduj je do wywołania IDataViewdata:

HomeData[] homeDataList = new HomeData[]
{
    new ()
    {
        NumberOfBedrooms=1f,
        Price=100000f
    },
    new ()
    {
        NumberOfBedrooms=2f,
        Price=300000f
    },
    new ()
    {
        NumberOfBedrooms=6f,
        Price=float.NaN
    }
};

Zwróć uwagę, że ostatni element na naszej liście ma brakującą wartość .Price Aby zastąpić brakujące wartości w kolumnie Price , użyj ReplaceMissingValues metody , aby wypełnić tę brakującą wartość.

Ważne

ReplaceMissingValue działa tylko z danymi liczbowymi.

// Define replacement estimator
var replacementEstimator = mlContext.Transforms.ReplaceMissingValues("Price", replacementMode: MissingValueReplacingEstimator.ReplacementMode.Mean);

// Fit data to estimator
// Fitting generates a transformer that applies the operations of defined by estimator
ITransformer replacementTransformer = replacementEstimator.Fit(data);

// Transform data
IDataView transformedData = replacementTransformer.Transform(data);

ML.NET obsługuje różne tryby wymiany. W powyższym przykładzie użyto trybu zastępczego Mean , który wypełnia brakującą wartość średnią tej kolumny. Wynik zamiany wypełnia Price właściwość dla ostatniego elementu w danych z 200 000, ponieważ jest to średnia 100 000 i 300 000.

Korzystanie z normalizacji

Normalizacja to technika przetwarzania wstępnego danych używana do skalowania funkcji w tym samym zakresie, zwykle z zakresu od 0 do 1, dzięki czemu mogą być dokładniej przetwarzane przez algorytm uczenia maszynowego. Na przykład zakresy wieku i dochodu różnią się znacznie w zależności od wieku, w zakresie od 0 do 100, a dochód zazwyczaj mieści się w przedziale od zera do tysięcy. Odwiedź stronę przekształcenia, aby uzyskać bardziej szczegółową listę i opis przekształceń normalizacji.

Minimalna maksymalna normalizacja

Pobierz następujące dane wejściowe i załaduj je do wywołania IDataViewdata:

HomeData[] homeDataList = new HomeData[]
{
    new ()
    {
        NumberOfBedrooms = 2f,
        Price = 200000f
    },
    new ()
    {
        NumberOfBedrooms = 1f,
        Price = 100000f
    }
};

Normalizację można zastosować do kolumn z pojedynczymi wartościami liczbowymi, a także wektorami. Normalizuj dane w Price kolumnie przy użyciu normalizacji min-max z NormalizeMinMax metodą .

// Define min-max estimator
var minMaxEstimator = mlContext.Transforms.NormalizeMinMax("Price");

// Fit data to estimator
// Fitting generates a transformer that applies the operations of defined by estimator
ITransformer minMaxTransformer = minMaxEstimator.Fit(data);

// Transform data
IDataView transformedData = minMaxTransformer.Transform(data);

Oryginalne wartości [200000,100000] cen są konwertowane na [ 1, 0.5 ] przy użyciu MinMax formuły normalizacji, która generuje wartości wyjściowe w zakresie od 0 do 1.

Binning

Kwantowanie konwertuje wartości ciągłe na dyskretną reprezentację danych wejściowych. Załóżmy na przykład, że jedną z Twoich funkcji jest wiek. Zamiast używać rzeczywistej wartości wieku, kwantowanie tworzy zakresy dla tej wartości. 0-18 może być jednym pojemnikem, inny może być 19-35 i tak dalej.

Pobierz następujące dane wejściowe i załaduj je do wywołania IDataViewdata:

HomeData[] homeDataList = new HomeData[]
{
    new ()
    {
        NumberOfBedrooms=1f,
        Price=100000f
    },
    new ()
    {
        NumberOfBedrooms=2f,
        Price=300000f
    },
    new ()
    {
        NumberOfBedrooms=6f,
        Price=600000f
    }
};

Normalizuj dane w pojemnikach przy użyciu NormalizeBinning metody . Parametr maximumBinCount umożliwia określenie liczby pojemników potrzebnych do klasyfikowania danych. W tym przykładzie dane zostaną umieszczone w dwóch pojemnikach.

// Define binning estimator
var binningEstimator = mlContext.Transforms.NormalizeBinning("Price", maximumBinCount: 2);

// Fit data to estimator
// Fitting generates a transformer that applies the operations of defined by estimator
var binningTransformer = binningEstimator.Fit(data);

// Transform Data
IDataView transformedData = binningTransformer.Transform(data);

Wynik kwantowania tworzy granice pojemnika [0,200000,Infinity]. Dlatego wynikowe pojemniki są [0,1,1] spowodowane tym, że pierwsza obserwacja wynosi od 0 do 200000, a pozostałe są większe niż 200000, ale mniejsze niż nieskończoność.

Praca z danymi kategorialnymi

Jednym z najpopularniejszych typów danych są dane podzielone na kategorie. Dane podzielone na kategorie mają skończona liczbę kategorii. Na przykład stany USA lub lista typów zwierząt znalezionych w zestawie obrazów. Niezależnie od tego, czy dane podzielone na kategorie są funkcjami, czy etykietami, muszą być mapowane na wartość liczbową, aby można było użyć ich do wygenerowania modelu uczenia maszynowego. Istnieje wiele sposobów pracy z danymi kategorialnymi w ML.NET, w zależności od rozwiązywanego problemu.

Mapowanie wartości klucza

W ML.NET klucz jest wartością całkowitą reprezentującą kategorię. Mapowanie wartości klucza jest najczęściej używane do mapowania etykiet ciągów na unikatowe wartości całkowite na potrzeby trenowania, a następnie z powrotem do ich wartości ciągów, gdy model jest używany do przewidywania.

Przekształcenia używane do wykonywania mapowania wartości klucza to MapValueToKey i MapKeyToValue.

MapValueToKey Dodaje słownik mapowań w modelu, dzięki czemu MapKeyToValue może wykonać transformację odwrotną podczas przewidywania.

Jedno kodowanie gorąca

Jedno kodowanie gorące przyjmuje skończony zestaw wartości i mapuje je na liczby całkowite, których reprezentacja binarna ma pojedynczą 1 wartość w unikatowych pozycjach w ciągu. Jedno kodowanie gorące może być najlepszym wyborem, jeśli nie ma niejawnej kolejności danych kategorii. W poniższej tabeli przedstawiono przykład z kodami pocztowymi jako nieprzetworzone wartości.

Wartość nieprzetworzona Jedna wartość zakodowana w formacie gorąca
98052 00...01
98100 00...10
... ...
98109 10...00

Przekształcenie w celu przekonwertowania danych kategorii na liczby zakodowane jednym gorącą to OneHotEncoding.

Mieszania

Tworzenie skrótów to inny sposób konwertowania danych kategorii na liczby. Funkcja skrótu mapuje dane dowolnego rozmiaru (na przykład ciąg tekstu) na liczbę ze stałym zakresem. Tworzenie skrótów może być szybkim i wydajnym sposobem wektoryzacji funkcji. Jednym z istotnych przykładów tworzenia skrótów w uczeniu maszynowym jest filtrowanie spamu w wiadomościach e-mail, w którym zamiast utrzymywać słownik znanych słów, każde słowo w wiadomości e-mail jest skrótem i dodawane do dużego wektora funkcji. Użycie skrótu w ten sposób pozwala uniknąć problemu złośliwego filtrowania spamu przez użycie słów, które nie znajdują się w słowniku.

ML.NET zapewnia przekształcenie skrótu w celu wykonywania skrótów w tekście, datach i danych liczbowych. Podobnie jak mapowanie klucza wartości, dane wyjściowe przekształcenia skrótu są typami kluczy.

Praca z danymi tekstowymi

Podobnie jak dane podzielone na kategorie, dane tekstowe muszą zostać przekształcone w funkcje liczbowe przed użyciem ich do utworzenia modelu uczenia maszynowego. Odwiedź stronę przekształcenia, aby uzyskać bardziej szczegółową listę i opis przekształceń tekstu.

Korzystając z danych takich jak poniższe dane, które zostały załadowane do elementu IDataView:

ReviewData[] reviews = new ReviewData[]
{
    new ReviewData
    {
        Description="This is a good product",
        Rating=4.7f
    },
    new ReviewData
    {
        Description="This is a bad product",
        Rating=2.3f
    }
};

ML.NET zapewnia FeaturizeText przekształcenie, które przyjmuje wartość ciągu tekstu i tworzy zestaw funkcji z tekstu, stosując serię pojedynczych przekształceń.

// Define text transform estimator
var textEstimator  = mlContext.Transforms.Text.FeaturizeText("Description");

// Fit data to estimator
// Fitting generates a transformer that applies the operations of defined by estimator
ITransformer textTransformer = textEstimator.Fit(data);

// Transform data
IDataView transformedData = textTransformer.Transform(data);

Wynikowa transformacja konwertuje wartości tekstowe w Description kolumnie na wektor liczbowy, który wygląda podobnie do poniższych danych wyjściowych:

[ 0.2041241, 0.2041241, 0.2041241, 0.4082483, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0, 0, 0, 0, 0.4472136, 0.4472136, 0.4472136, 0.4472136, 0.4472136, 0 ]

Przekształcenia, które tworzą FeaturizeText , można również stosować indywidualnie w celu bardziej precyzyjnej kontroli nad generowaniem funkcji.

// Define text transform estimator
var textEstimator = mlContext.Transforms.Text.NormalizeText("Description")
    .Append(mlContext.Transforms.Text.TokenizeIntoWords("Description"))
    .Append(mlContext.Transforms.Text.RemoveDefaultStopWords("Description"))
    .Append(mlContext.Transforms.Conversion.MapValueToKey("Description"))
    .Append(mlContext.Transforms.Text.ProduceNgrams("Description"))
    .Append(mlContext.Transforms.NormalizeLpNorm("Description"));

textEstimator zawiera podzbiór operacji wykonywanych przez metodę FeaturizeText . Zaletą bardziej złożonego potoku jest kontrola i widoczność przekształceń zastosowanych do danych.

Korzystając z pierwszego wpisu jako przykładu, poniżej przedstawiono szczegółowy opis wyników generowanych przez kroki przekształcania zdefiniowane przez textEstimatorprogram :

Oryginalny tekst: jest to dobry produkt

Przekształcanie opis Wynik
1. NormalizeText Konwertuje wszystkie litery na małe litery domyślnie jest to dobry produkt
2. TokenizeWords Dzieli ciąg na pojedyncze wyrazy ["this","is","a","good","product"]
3. RemoveDefaultStopWords Usuwa słowa zatrzymane, takie jak is i a. ["good","product"]
4. MapValueToKey Mapy wartości kluczy (kategorii) na podstawie danych wejściowych [1,2]
5. ProduceNGramy Przekształca tekst w sekwencję kolejnych wyrazów [1,1,1,0,0]
6. NormalizeLpNorm Skalowanie danych wejściowych według ich lp-norm [ 0.577350529, 0.577350529, 0.577350529, 0, 0 ]