Příprava dat pro vytvoření modelu

Naučte se používat ML.NET k přípravě dat na další zpracování nebo sestavení modelu.

Data jsou často nečistá a řídká. ML.NET algoritmy strojového učení očekávají, že vstup nebo funkce budou v jednom číselném vektoru. Podobně musí být hodnota predikce (popisek), zejména pokud jde o kategorická data, zakódovaná. Jedním z cílů přípravy dat je tedy získání dat do formátu očekávaného algoritmy ML.NET.

Rozdělení dat do trénovacích a testovacích sad

Následující část popisuje běžné problémy při trénování modelu označovaného jako přeurčení a nedoučení. S identifikací a zmírněním těchtoproblémůch

Přeurčení a podurčení

Přeurčení a nedoučení jsou dvěma nejběžnějšími problémy, se kterými se setkáte při trénování modelu. Nedoučení znamená, že vybraný trenér není schopen dostatečně přizpůsobit trénovací datovou sadu a obvykle vést k vysoké ztrátě během trénování a nízkého skóre nebo metriky testovací datové sady. Pokud chcete tento problém vyřešit, musíte buď vybrat výkonnější model, nebo provést více přípravy funkcí. Přeurčení je opak, což se stane, když se model učí trénovací data příliš dobře. To obvykle vede k nízké ztrátě metriky během trénování, ale k vysoké ztrátě testovací datové sady.

Dobrou analogií pro tyto koncepty je studium zkoušky. Řekněme, že znáte otázky a odpovědi předem. Po studiu si test vezmete a dostanete perfektní skóre. Skvělé zprávy! Když ale znovu dostanete zkoušku s přeuspořádanými otázkami a mírně odlišnými formulacemi, dostanete nižší skóre. To naznačuje, že jste si odpovědi zapamatovali a ve skutečnosti jste se nenaučili koncepty, na které jste byli testováni. Toto je příklad přeurčení. Nedoučení je opakem, kde studijní materiály, které jste dostali, přesně nepředstavují to, na co jste se na zkoušku vyhodnotili. V důsledku toho se uchýlíte k odhadu odpovědí, protože nemáte dostatek znalostí, abyste mohli správně odpovědět.

Rozdělení dat

Vezměte následující vstupní data a načtěte je do volané IDataViewdatapoložky:

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
    }
};

K rozdělení dat do trénovacích a testovacích sad použijte metodu TrainTestSplit(IDataView, Double, String, Nullable<Int32>) .

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

Parametr testFraction se používá k 0,2 nebo 20 % datové sady pro testování. Zbývající 80 % se používá k trénování.

Výsledek je DataOperationsCatalog.TrainTestData se dvěma IDataViews, ke kterým můžete přistupovat prostřednictvím TrainSet a TestSet.

Filtrování dat

Někdy nejsou všechna data v datové sadě relevantní pro analýzu. Filtruje se přístup k odebrání irelevantních dat. Obsahuje DataOperationsCatalog sadu operací filtru, které přebírají IDataView obsahující všechna data a vrací IDataView obsahující pouze datové body zájmu. Je důležité si uvědomit, že vzhledem k tomu, že operace filtrování nejsou nebo IEstimatorITransformer se podobají operacím v nástroji TransformsCatalog, není možné je zahrnout jako součást EstimatorChain kanálu přípravy dat.TransformerChain

Vezměte následující vstupní data a načtěte je do volané IDataViewdatapoložky:

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

K filtrování dat na základě hodnoty sloupce použijte metodu FilterRowsByColumn .

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

Výše uvedený vzorek přebírá řádky v datové sadě s cenou mezi 200000 a 1 000000. Výsledek použití tohoto filtru by vrátil pouze poslední dva řádky v datech a vyloučil první řádek, protože jeho cena je 1 00000, a ne mezi zadaným rozsahem.

Nahrazení chybějících hodnot

Chybějící hodnoty jsou běžným výskytem v datových sadách. Jedním z přístupů k řešení chybějících hodnot je nahradit výchozí hodnotou pro daný typ, pokud existuje nějaká nebo jiná smysluplná hodnota, například střední hodnota v datech.

Vezměte následující vstupní data a načtěte je do volané IDataViewdatapoložky:

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

Všimněte si, že poslední prvek v našem seznamu obsahuje chybějící hodnotu pro Price. Chcete-li nahradit chybějící hodnoty ve Price sloupci, použijte metodu ReplaceMissingValues k vyplnění této chybějící hodnoty.

Důležité

ReplaceMissingValue funguje pouze s číselnými daty.

// 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 podporuje různé režimy nahrazení. Výše uvedený vzorek používá Mean režim nahrazení, který vyplní chybějící hodnotu průměrnou hodnotou daného sloupce. Výsledek nahrazení vyplní Price vlastnost posledního prvku v našich datech 200 000, protože je to průměr 100 000 a 300 000.

Použití normalizátorů

Normalizace je technika předběžného zpracování dat, která slouží ke škálování funkcí tak, aby byly ve stejném rozsahu, obvykle mezi 0 a 1, aby bylo možné je přesněji zpracovat algoritmem strojového učení. Například rozsahy pro věk a příjmy se výrazně liší s věkem obecně v rozsahu od 0 do 100 a příjmů obecně v rozsahu od nuly do tisíců. Podrobnější seznam a popis transformací normalizace najdete na stránce transformací.

Min-Max normalizace

Vezměte následující vstupní data a načtěte je do volané IDataViewdatapoložky:

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

Normalizaci lze použít u sloupců s jednoduchými číselnými hodnotami a vektory. Normalizovat data ve Price sloupci pomocí min-max normalizace pomocí NormalizeMinMax metody.

// 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);

Původní hodnoty [200000,100000] cen se převedou na [ 1, 0.5 ] použití MinMax vzorce normalizace, který generuje výstupní hodnoty v rozsahu od 0 do 1.

Binning

Binning převede souvislé hodnoty na diskrétní reprezentaci vstupu. Předpokládejme například, že jedna z vašich funkcí je věk. Místo použití skutečné věkové hodnoty vytvoří binning rozsahy pro danou hodnotu. 0-18 může být jedna přihrádka, druhá by mohla být 19-35 atd.

Vezměte následující vstupní data a načtěte je do volané IDataViewdatapoložky:

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

Normalizuje data do intervalů pomocí NormalizeBinning metody. Parametr maximumBinCount umožňuje zadat počet intervalů potřebných ke klasifikaci dat. V tomto příkladu budou data vložena do dvou intervalů.

// 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);

Výsledek binningu vytvoří hranice intervalu [0,200000,Infinity]. Výsledné intervaly jsou [0,1,1] proto, že první pozorování je mezi 0–200000 a ostatními jsou větší než 2 00000, ale menší než nekonečno.

Práce s kategorickými daty

Jedním z nejběžnějších typů dat je kategorická data. Kategorická data mají konečný počet kategorií. Například státy USA nebo seznam typů zvířat nalezených v sadě obrázků. Ať už jsou kategorická data funkce nebo popisky, musí se namapovat na číselnou hodnotu, aby bylo možné je použít k vygenerování modelu strojového učení. Existuje řada způsobů práce s kategorickými daty v ML.NET v závislosti na problému, který řešíte.

Mapování hodnot klíče

V ML.NET je klíč celočíselnou hodnotou, která představuje kategorii. Mapování hodnot klíče se nejčastěji používá k mapování popisků řetězců na jedinečné celočíselné hodnoty pro trénování a pak zpět k řetězcovým hodnotám, když se model použije k vytvoření předpovědi.

Transformace použité k mapování hodnot klíče jsou MapValueToKey a MapKeyToValue.

MapValueToKey přidá slovník mapování v modelu, aby MapKeyToValue při vytváření předpovědi mohl provést zpětnou transformaci.

Jedno kódování za tepla

Jedno horké kódování přebírá konečnou sadu hodnot a mapuje je na celá čísla, jejichž binární reprezentace má jednu 1 hodnotu v jedinečných pozicích v řetězci. Jedno kódování za tepla může být nejlepší volbou, pokud neexistuje žádné implicitní řazení kategorických dat. Následující tabulka ukazuje příklad se PSČ jako nezpracovanými hodnotami.

Surová hodnota Jedna horká zakódovaná hodnota
98052 00...01
98100 00...10
... ...
98109 10...00

Transformace pro převod kategorických dat na čísla zakódovaná za 1 horkou hodnotu je OneHotEncoding.

Hash

Hashování je další způsob, jak převést kategorická data na čísla. Funkce hash mapuje data libovolné velikosti (například řetězce textu) na číslo s pevným rozsahem. Hashování může být rychlý a prostorově efektivní způsob vektorizace funkcí. Jedním z znaménných příkladů hashování ve strojovém učení je filtrování spamu e-mailů, kde místo zachování slovníku známých slov se každé slovo v e-mailu zatřiďuje a přidá do velkého vektoru funkce. Použití hash tímto způsobem zabraňuje problému se škodlivým filtrováním spamu obcházením použití slov, která nejsou ve slovníku.

ML.NET poskytuje transformaci hodnoty hash pro provádění hash u textu, kalendářních dat a číselných dat. Stejně jako mapování hodnotových klíčů jsou výstupy transformace hash typy klíčů.

Práce s textovými daty

Podobně jako kategorická data je potřeba textová data před vytvořením modelu strojového učení transformovat na číselné funkce. Podrobnější seznam a popis transformací textu najdete na stránce transformací.

Použití dat, jako jsou data níže, která byla načtena do 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 poskytuje FeaturizeText transformaci, která přebírá řetězcovou hodnotu textu a vytvoří sadu funkcí z textu použitím řady jednotlivých transformací.

// 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);

Výsledná transformace převede textové hodnoty ve Description sloupci na číselný vektor, který vypadá podobně jako následující výstup:

[ 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 ]

Transformace, které tvoří FeaturizeText , lze také použít jednotlivě, aby bylo možné jemně řídit generování funkcí.

// 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 obsahuje podmnožinu operací provedených metodou FeaturizeText . Výhodou složitějšího kanálu je řízení a přehled o transformacích použitých u dat.

Při použití první položky jako příkladu je následující podrobný popis výsledků vytvořených postupem transformace definovaným textEstimator:

Původní text: Jedná se o dobrý produkt

Transformace Popis Výsledek
1. NormalizeText Ve výchozím nastavení převede všechna písmena na malá písmena. to je dobrý produkt.
2. TokenizeWords Rozdělí řetězec na jednotlivá slova. ["this","is","a","good","product"]
3. OdebratDefaultStopWords Odebere slova stop jako je a a. ["good","product"]
4. MapValueToKey Mapy hodnoty klíčů (kategorií) na základě vstupních dat [1,2]
5. ProduceNGrams Převede text na posloupnost po sobě jdoucích slov. [1,1,1,0,0]
6. NormalizeLpNorm Škálování vstupů podle jejich lp-norm [ 0.577350529, 0.577350529, 0.577350529, 0, 0 ]