Dela via


Förbereda data för att skapa en modell

Lär dig hur du använder ML.NET för att förbereda data för ytterligare bearbetning eller för att skapa en modell.

Data är ofta orena och glesa. ML.NET maskininlärningsalgoritmer förväntar sig att indata eller funktioner ska finnas i en enda numerisk vektor. På samma sätt måste värdet för att förutsäga (etikett), särskilt när det är kategoriska data, kodas. Därför är ett av målen med dataförberedelser att få data till det format som förväntas av ML.NET algoritmer.

Dela upp data i tränings- och &-testuppsättningar

I följande avsnitt beskrivs vanliga problem när du tränar en modell som kallas överanpassning och underanpassning. Genom att dela upp dina data och validera dina modeller med hjälp av en testuppsättning kan du identifiera och åtgärda dessa problem.

Överanpassning & underanpassning

Överanpassning och underanpassning är de två vanligaste problemen du stöter på när du tränar en modell. Underanpassning innebär att den valda tränaren inte är tillräckligt kapabel för att passa träningsdatauppsättningen och resulterar vanligtvis i en hög förlust under träning och låg poäng/mått på testdatauppsättningen. För att lösa detta måste du antingen välja en kraftfullare modell eller utföra mer funktionsframställning. Överanpassning är motsatsen, vilket händer när modellen lär sig träningsdata alltför bra. Detta resulterar vanligtvis i ett lågt värde för förlustmåttet under träning men hög förlust på testdatasetet.

En bra analogi för dessa begrepp är att studera för en examen. Anta att du kände till frågorna och svaren i förväg. Efter studierna tar du testet och får en perfekt poäng. Goda nyheter! Men när du får provet igen med frågorna omorganiserade och med lite olika formuleringar får du en lägre poäng. Det tyder på att du memorerade svaren och faktiskt inte lärde dig de begrepp som du testades på. Det här är ett exempel på överanpassning. Underanpassning är motsatsen, där studiematerialet du fick inte korrekt representerar vad du utvärderas på för provet. Därför tillgriper du att gissa svaren eftersom du inte har tillräckligt med kunskap för att svara korrekt.

Dela upp data

Ta följande indata och läs in dem i en IDataView med namnet data:

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

Om du vill dela upp data i tränings-/testuppsättningar använder du metoden TrainTestSplit(IDataView, Double, String, Nullable<Int32>).

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

Parametern testFraction används för att ta 0,2 eller 20% av datauppsättningen för testning. De återstående 80% används för träning.

Resultatet är DataOperationsCatalog.TrainTestData med två IDataViews som du kan komma åt via TrainSet och TestSet.

Filtrera data

Ibland är inte alla data i en datamängd relevanta för analys. En metod för att ta bort irrelevanta data är filtrering. DataOperationsCatalog innehåller en uppsättning filteråtgärder som tar in en IDataView som innehåller alla data och returnerar en IDataView- som endast innehåller de datapunkter som är intressanta. Det är viktigt att observera att eftersom filteroperationer inte är en IEstimator eller ITransformer som de i TransformsCatalog, kan de inte inkluderas som en del av en EstimatorChain eller TransformerChain pipeline för dataförberedelse.

Ta följande indata och läs in dem i en IDataView med namnet data:

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

Om du vill filtrera data baserat på värdet för en kolumn använder du metoden FilterRowsByColumn.

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

Exemplet ovan tar rader i datamängden med ett pris mellan 200000 och 1000000. Resultatet av att tillämpa det här filtret returnerar endast de två sista raderna i data och exkluderar den första raden eftersom priset är 100000 och inte mellan det angivna intervallet.

Ersätt saknade värden

Saknade värden är en vanlig förekomst i datauppsättningar. En metod för att hantera saknade värden är att ersätta dem med standardvärdet för den specifika typen, om detta finns, eller ersätta dem med något annat meningsfullt värde, till exempel medelvärdet i dataserien.

Ta följande indata och läs in dem i en IDataView med namnet data:

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

Observera att det sista elementet i listan har ett värde som saknas för Price. Om du vill ersätta de saknade värdena i kolumnen Price använder du metoden ReplaceMissingValues för att fylla i det saknade värdet.

Viktig

ReplaceMissingValue fungerar bara med numeriska data.

// 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 stöder olika ersättningslägen. Exemplet ovan använder Mean ersättningsläge, som fyller i det saknade värdet med kolumnens genomsnittliga värde. Ersättningsresultatet fyller i egenskapen Price för det sista elementet i data med 200 000 eftersom det är genomsnittet på 100 000 och 300 000.

Använda normaliserare

Normalisering är en dataförbearbetande teknik som används för att skala funktioner så att de ligger i samma intervall, vanligtvis mellan 0 och 1, så att de kan bearbetas mer korrekt av en maskininlärningsalgoritm. Till exempel varierar intervallen för ålder och inkomst avsevärt med åldern i allmänhet i intervallet 0-100 och inkomsten är vanligtvis i intervallet noll till tusentals. Besök sidan för transformationer för en mer detaljerad lista och beskrivning av normaliseringstransformationer.

Min-max-normalisering

Ta följande indata och läs in dem i en IDataView med namnet data:

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

Normalisering kan tillämpas på kolumner med enkla numeriska värden samt vektorer. Normalisera data i kolumnen Price med min-max-normalisering med metoden NormalizeMinMax.

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

De ursprungliga prisvärdena [200000,100000] konverteras till [ 1, 0.5 ] med hjälp av den MinMax normaliseringsformeln som genererar utdatavärden i intervallet 0–1.

Indelning i grupper

Binning konverterar kontinuerliga värden till en diskret representation av indata. Anta till exempel att en av dina egenskaper är ålder. I stället för att använda det faktiska åldersvärdet skapar binning intervall för det värdet. 0-18 kan vara ett intervall, ett annat kan vara 19-35 och så vidare.

Ta följande indata och ladda det i en IDataView som heter data:

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

Normalisera data till grupper med hjälp av metod NormalizeBinning. Med parametern maximumBinCount kan du ange det antal lagerplatser som behövs för att klassificera dina data. I det här exemplet placeras data i två lagerplatser.

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

Resultatet av binning skapar intervallintervall för [0,200000,Infinity]. Därför är de resulterande intervallen [0,1,1] eftersom den första observationen är mellan 0 och 200000 och de andra är större än 200000 men mindre än oändligheten.

Arbeta med kategoriska data

En av de vanligaste typerna av data är kategoriska data. Kategoridata har ett begränsat antal kategorier. Till exempel delstaterna i USA eller en lista över de typer av djur som finns i en uppsättning bilder. Oavsett om kategoridata är funktioner eller etiketter måste de mappas till ett numeriskt värde så att de kan användas för att generera en maskininlärningsmodell. Det finns ett antal sätt att arbeta med kategoriska data i ML.NET, beroende på vilket problem du löser.

Nyckelvärdesmappning

I ML.NET är en nyckel ett heltalsvärde som representerar en kategori. Nyckelvärdesmappning används oftast för att mappa strängetiketter till unika heltalsvärden för träning och sedan tillbaka till deras strängvärden när modellen används för att göra en förutsägelse.

De transformeringar som används för att utföra nyckelvärdemappning är MapValueToKey och MapKeyToValue.

MapValueToKey lägger till en ordlista med mappningar i modellen, så att MapKeyToValue kan utföra omvänd transformering när du gör en förutsägelse.

En frekvent kodning

En frekvent kodning tar en begränsad uppsättning värden och mappar dem till heltal vars binära representation har ett enda 1 värde i unika positioner i strängen. One hot-encoding kan vara det bästa alternativet om det inte finns någon implicit ordning på kategoridata. I följande tabell visas ett exempel med postnummer som råvärden.

Råvärde Ett snabbkodat värde
98052 00...01
98100 00...10
... ...
98109 10...00

Transformationen för att omvandla kategoriska data till one-hot kodade tal är OneHotEncoding.

Hashing

Hashing är ett annat sätt att konvertera kategoriska data till tal. En hash-funktion mappar data av godtycklig storlek (till exempel en textsträng) till ett tal med ett fast intervall. Hashning kan vara ett snabbt och utrymmeseffektivt sätt att vektorisera funktioner. Ett viktigt exempel på hashning i maskininlärning är skräppostfiltrering via e-post, där varje ord i e-postmeddelandet hashas och läggs till i en stor funktionsvektor i stället för att behålla en ordlista med kända ord. Genom att använda hashning på det här sättet undviker du problemet med filtrering av skadlig skräppost genom att använda ord som inte finns i ordlistan.

ML.NET tillhandahåller Hash- transformering för att utföra hashning på text, datum och numeriska data. Precis som värdenyckelmappning är utdata från hash-transformering viktiga typer.

Arbeta med textdata

Precis som kategoriska data måste textdata omvandlas till numeriska funktioner innan de används för att skapa en maskininlärningsmodell. Gå till sidan för textomvandlingar för en mer detaljerad lista och beskrivning av textomvandlingar.

Med data som det nedan, som har laddats in i en 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 tillhandahåller FeaturizeText transformering som tar en texts strängvärde och skapar en uppsättning funktioner från texten genom att tillämpa en serie enskilda transformeringar.

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

Den resulterande transformeringen konverterar textvärdena i kolumnen Description till en numerisk vektor som ser ut ungefär som utdata nedan:

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

De transformeringar som utgör FeaturizeText kan också tillämpas individuellt för mer detaljerad kontroll över generering av funktioner.

// 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 innehåller en delmängd av åtgärder som utförs av metoden FeaturizeText. Fördelen med en mer komplex pipeline är kontroll och synlighet över de omvandlingar som tillämpas på data.

Med den första posten som exempel är följande en detaljerad beskrivning av resultaten som genereras av omvandlingsstegen som definieras av textEstimator:

originaltext: Det här är en bra produkt

Transformera Beskrivning Resultat
1. NormalizeText Konverterar automatiskt alla bokstäver till gemener som standard detta är en bra produkt
2. TokenizeWords Delar upp strängen i enskilda ord det här är en bra produkt
3. Ta bort standardstoppord Tar bort stoppord som är och en. ["bra","produkt"]
4. MapValueToKey Mappar värdena till nycklar (kategorier) baserat på indata [1,2]
5. ProduceNGrams Omvandlar text till sekvens med efterföljande ord [1,1,1,0,0]
6. NormalizeLpNorm Skala indata efter deras lp-norm [ 0.577350529, 0.577350529, 0.577350529, 0, 0 ]