Självstudie: Skapa en filmrekommendator med hjälp av matrisfaktorisering med ML.NET

Den här självstudien visar hur du skapar en filmrekommendator med ML.NET i ett .NET Core-konsolprogram. Stegen använder C# och Visual Studio 2019.

I den här guiden får du lära dig att:

  • Välj en maskininlärningsalgoritm
  • Förbereda och läsa in dina data
  • Skapa och träna en modell
  • Utvärdera en modell
  • Distribuera och använda en modell

Du hittar källkoden för den här självstudien på lagringsplatsen dotnet/samples .

Arbetsflöde för maskininlärning

Du kommer att använda följande steg för att utföra din uppgift, liksom andra ML.NET uppgift:

  1. Läs in dina data
  2. Skapa och träna din modell
  3. Utvärdera din modell
  4. Använd din modell

Förutsättningar

Välj lämplig maskininlärningsuppgift

Det finns flera sätt att hantera rekommendationsproblem, till exempel att rekommendera en lista över filmer eller rekommendera en lista över relaterade produkter, men i det här fallet kommer du att förutsäga vilket omdöme (1–5) en användare kommer att ge till en viss film och rekommendera filmen om den är högre än ett definierat tröskelvärde (ju högre omdöme, desto högre är sannolikheten för att en användare gillar en viss film).

Skapa ett konsolprogram

Skapa ett projekt

  1. Skapa ett C# -konsolprogram med namnet "MovieRecommender". Klicka på knappen Nästa.

  2. Välj .NET 6 som ramverk att använda. Klicka på knappen Skapa.

  3. Skapa en katalog med namnet Data i projektet för att lagra datauppsättningen:

    Högerklicka på projektet i Solution Explorer och välj Lägg till>ny mapp. Skriv "Data" och tryck på Retur.

  4. Installera nuget-paketen Microsoft.ML och Microsoft.ML.Recommender :

    Anteckning

    Det här exemplet använder den senaste stabila versionen av De NuGet-paket som nämns om inget annat anges.

    Högerklicka på projektet i Solution Explorer och välj Hantera NuGet-paket. Välj "nuget.org" som paketkälla, välj fliken Bläddra , sök efter Microsoft.ML, välj paketet i listan och välj knappen Installera . Välj knappen OK i dialogrutan Förhandsgranska ändringar och välj sedan knappen Jag accepterar i dialogrutan Licensgodkännande om du godkänner licensvillkoren för de paket som anges. Upprepa de här stegen för Microsoft.ML.Recommender.

  5. Lägg till följande using instruktioner överst i filen Program.cs :

    using Microsoft.ML;
    using Microsoft.ML.Trainers;
    using MovieRecommendation;
    

Ladda ned dina data

  1. Ladda ned de två datauppsättningarna och spara dem i mappen Data som du skapade tidigare:

    • Högerklicka på recommendation-ratings-train.csv och välj "Spara länk (eller Mål) som..."

    • Högerklicka på recommendation-ratings-test.csv och välj "Spara länk (eller Mål) som..."

      Se till att du antingen sparar *.csv-filerna i datamappen eller när du har sparat den någon annanstans flyttar du *.csv-filerna till mappen Data .

  2. Högerklicka på var och en av filerna *.csv i Solution Explorer och välj Egenskaper. Under Avancerat ändrar du värdet för Kopiera till utdatakatalog till Kopiera om nyare.

    GIF för en användare som väljer kopiera om det är nyare i VS.

Läs in dina data

Det första steget i ML.NET processen är att förbereda och läsa in dina modelltränings- och testdata.

Rekommendationsklassificeringsdata delas upp i Train och Test datauppsättningar. Data Train används för att passa din modell. Data Test används för att göra förutsägelser med din tränade modell och utvärdera modellens prestanda. Det är vanligt att dela en 80/20 med Train och Test data.

Nedan visas en förhandsgranskning av data från dina *.csv-filer:

Skärmbild av förhandsversionen av CVS-datauppsättningen.

I filerna *.csv finns det fyra kolumner:

  • userId
  • movieId
  • rating
  • timestamp

I maskininlärning kallas kolumnerna som används för att göra en förutsägelse funktioner, och kolumnen med den returnerade förutsägelsen kallas etikett.

Du vill förutsäga filmklassificeringar, så klassificeringskolumnen Labelär . De andra tre kolumnerna, userId, movieIdoch timestamp används alla Features för att förutsäga Label.

Funktioner Etikett
userId rating
movieId
timestamp

Det är upp till dig att bestämma vilka som Features används för att förutsäga Label. Du kan också använda metoder som funktionsvikt för permutation för att hjälpa dig att välja de bästa Features.

I det här fallet bör du eliminera timestamp kolumnen som en Feature eftersom tidsstämpeln inte påverkar hur en användare betygsätter en viss film och därför inte skulle bidra till att göra en mer exakt förutsägelse:

Funktioner Etikett
userId rating
movieId

Därefter måste du definiera datastrukturen för indataklassen.

Lägg till en ny klass i projektet:

  1. Högerklicka på projektet i Solution Explorer och välj sedan Lägg till > nytt objekt.

  2. I dialogrutan Lägg till nytt objekt väljer du Klass och ändrar fältet Namn till MovieRatingData.cs. Välj sedan knappen Lägg till .

Filen MovieRatingData.cs öppnas i kodredigeraren. Lägg till följande using instruktion överst i MovieRatingData.cs:

using Microsoft.ML.Data;

Skapa en klass med namnet MovieRating genom att ta bort den befintliga klassdefinitionen och lägga till följande kod i MovieRatingData.cs:

public class MovieRating
{
    [LoadColumn(0)]
    public float userId;
    [LoadColumn(1)]
    public float movieId;
    [LoadColumn(2)]
    public float Label;
}

MovieRating anger en indataklass. Attributet LoadColumn anger vilka kolumner (efter kolumnindex) i datauppsättningen som ska läsas in. Kolumnerna userId och är dina Features (indata som du ger modellen för att förutsäga Label), och klassificeringskolumnen Label är den som du kommer att förutsäga (modellens movieId utdata).

Skapa en annan klass, MovieRatingPrediction, för att representera förutsagda resultat genom att lägga till följande kod efter MovieRating klassen i MovieRatingData.cs:

public class MovieRatingPrediction
{
    public float Label;
    public float Score;
}

I Program.cs ersätter du Console.WriteLine("Hello World!") med följande kod:

MLContext mlContext = new MLContext();

MLContext-klassen är en startpunkt för alla ML.NET åtgärder, och initiering mlContext skapar en ny ML.NET miljö som kan delas mellan arbetsflödesobjekten för modellskapande. Det är ungefär som konceptuellt DBContext i Entity Framework.

Längst ned i filen skapar du en metod med namnet LoadData():

(IDataView training, IDataView test) LoadData(MLContext mlContext)
{

}

Anteckning

Den här metoden ger dig ett fel tills du lägger till en retursats i följande steg.

Initiera dina datasökvägsvariabler, läs in data från *.csv-filerna och returnera TrainTest data och som IDataView objekt genom att lägga till följande som nästa kodrad i LoadData():

var trainingDataPath = Path.Combine(Environment.CurrentDirectory, "Data", "recommendation-ratings-train.csv");
var testDataPath = Path.Combine(Environment.CurrentDirectory, "Data", "recommendation-ratings-test.csv");

IDataView trainingDataView = mlContext.Data.LoadFromTextFile<MovieRating>(trainingDataPath, hasHeader: true, separatorChar: ',');
IDataView testDataView = mlContext.Data.LoadFromTextFile<MovieRating>(testDataPath, hasHeader: true, separatorChar: ',');

return (trainingDataView, testDataView);

Data i ML.NET representeras som ett IDataView-gränssnitt. IDataView är ett flexibelt och effektivt sätt att beskriva tabelldata (numeriska och text). Data kan läsas in från en textfil eller i realtid (till exempel SQL-databas eller loggfiler) till ett IDataView objekt.

LoadFromTextFile() definierar dataschemat och läser i filen. Den tar in datasökvägsvariablerna och returnerar en IDataView. I det här fallet anger du sökvägen för dina Test filer och Train filer och anger både textfilrubriken (så att den kan använda kolumnnamnen korrekt) och kommateckendataavgränsaren (standardavgränsaren är en flik).

Lägg till följande kod för att anropa din LoadData() metod och returnera data och TrainTest :

(IDataView trainingDataView, IDataView testDataView) = LoadData(mlContext);

Skapa och träna din modell

BuildAndTrainModel() Skapa metoden, precis efter LoadData() -metoden, med hjälp av följande kod:

ITransformer BuildAndTrainModel(MLContext mlContext, IDataView trainingDataView)
{

}

Anteckning

Den här metoden ger dig ett fel tills du lägger till en retursats i följande steg.

Definiera datatransformeringarna genom att lägga till följande kod i BuildAndTrainModel():

IEstimator<ITransformer> estimator = mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: "userIdEncoded", inputColumnName: "userId")
    .Append(mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: "movieIdEncoded", inputColumnName: "movieId"));

Eftersom userId och movieId representerar användare och filmtitlar, inte verkliga värden, använder du metoden MapValueToKey() för att omvandla var userId och movieId en till en kolumn av numerisk nyckeltyp Feature (ett format som godkänns av rekommendationsalgoritmer) och lägger till dem som nya datauppsättningskolumner:

userId movieId Etikett userIdEncoded movieIdEncoded
1 1 4 userKey1 movieKey1
1 3 4 userKey1 movieKey2
1 6 4 userKey1 movieKey3

Välj maskininlärningsalgoritmen och lägg till den i definitionerna för datatransformering genom att lägga till följande som nästa kodrad i BuildAndTrainModel():

var options = new MatrixFactorizationTrainer.Options
{
    MatrixColumnIndexColumnName = "userIdEncoded",
    MatrixRowIndexColumnName = "movieIdEncoded",
    LabelColumnName = "Label",
    NumberOfIterations = 20,
    ApproximationRank = 100
};

var trainerEstimator = estimator.Append(mlContext.Recommendation().Trainers.MatrixFactorization(options));

MatrixFactorizationTrainer är din rekommendationsträningsalgoritm. Matrisfaktorisering är en vanlig metod för rekommendation när du har data om hur användare har klassificerat produkter tidigare, vilket är fallet för datauppsättningarna i den här självstudien. Det finns andra rekommendationsalgoritmer för när du har olika tillgängliga data (se avsnittet Andra rekommendationsalgoritmer nedan om du vill veta mer).

I det här fallet använder algoritmen Matrix Factorization en metod som kallas "samarbetsfiltrering", som förutsätter att om användare 1 har samma åsikt som användare 2 i ett visst problem, är det mer troligt att användare 1 känner på samma sätt som användare 2 om ett annat problem.

Till exempel, om användare 1 och användare 2 betygsätter filmer på samma sätt, så är användare 2 mer benägna att njuta av en film som användare 1 har tittat på och betygsatt högt:

Incredibles 2 (2018) The Avengers (2012) Guardians of the Galaxy (2014)
Användare 1 Såg och gillade film Såg och gillade film Såg och gillade film
Användare 2 Såg och gillade film Såg och gillade film Har inte sett -- REKOMMENDERA film

Utbildaren Matrix Factorization har flera alternativ, som du kan läsa mer om i avsnittet Algoritm hyperparametrar nedan.

Anpassa modellen till data och returnera den tränade modellen genom att Train lägga till följande som nästa kodrad i BuildAndTrainModel() metoden:

Console.WriteLine("=============== Training the model ===============");
ITransformer model = trainerEstimator.Fit(trainingDataView);

return model;

Metoden Fit() tränar din modell med den angivna träningsdatauppsättningen. Tekniskt sett kör den Estimator definitionerna genom att transformera data och tillämpa träningen, och den returnerar den tränade modellen, som är en Transformer.

Mer information om arbetsflödet för modellträning i ML.NET finns i Vad är ML.NET och hur fungerar det?.

Lägg till följande som nästa kodrad under anropet LoadData() till metoden för att anropa din BuildAndTrainModel() metod och returnera den tränade modellen:

ITransformer model = BuildAndTrainModel(mlContext, trainingDataView);

Utvärdera din modell

När du har tränat din modell använder du dina testdata för att utvärdera hur modellen presterar.

EvaluateModel() Skapa metoden, precis efter BuildAndTrainModel() -metoden, med hjälp av följande kod:

void EvaluateModel(MLContext mlContext, IDataView testDataView, ITransformer model)
{

}

Transformera Test data genom att lägga till följande kod i EvaluateModel():

Console.WriteLine("=============== Evaluating the model ===============");
var prediction = model.Transform(testDataView);

Metoden Transform() gör förutsägelser för flera angivna indatarader i en testdatauppsättning.

Utvärdera modellen genom att lägga till följande som nästa kodrad i EvaluateModel() metoden:

var metrics = mlContext.Regression.Evaluate(prediction, labelColumnName: "Label", scoreColumnName: "Score");

När du har angett förutsägelsen utvärderar metoden Evaluate() modellen, som jämför de förutsagda värdena med det faktiska Labels i testdatauppsättningen och returnerar mått på hur modellen presterar.

Skriv ut dina utvärderingsmått till konsolen genom att lägga till följande som nästa kodrad i EvaluateModel() -metoden:

Console.WriteLine("Root Mean Squared Error : " + metrics.RootMeanSquaredError.ToString());
Console.WriteLine("RSquared: " + metrics.RSquared.ToString());

Lägg till följande som nästa kodrad under anropet BuildAndTrainModel() till metoden för att anropa din EvaluateModel() metod:

EvaluateModel(mlContext, testDataView, model);

Utdata hittills bör se ut ungefär så här:

=============== Training the model ===============
iter      tr_rmse          obj
   0       1.5403   3.1262e+05
   1       0.9221   1.6030e+05
   2       0.8687   1.5046e+05
   3       0.8416   1.4584e+05
   4       0.8142   1.4209e+05
   5       0.7849   1.3907e+05
   6       0.7544   1.3594e+05
   7       0.7266   1.3361e+05
   8       0.6987   1.3110e+05
   9       0.6751   1.2948e+05
  10       0.6530   1.2766e+05
  11       0.6350   1.2644e+05
  12       0.6197   1.2541e+05
  13       0.6067   1.2470e+05
  14       0.5953   1.2382e+05
  15       0.5871   1.2342e+05
  16       0.5781   1.2279e+05
  17       0.5713   1.2240e+05
  18       0.5660   1.2230e+05
  19       0.5592   1.2179e+05
=============== Evaluating the model ===============
Rms: 0.994051469730769
RSquared: 0.412556298844873

I dessa utdata finns det 20 iterationer. I varje iteration minskar och konvergerar måttet fel närmare och närmare 0.

root of mean squared error (RMS eller RMSE) används för att mäta skillnaderna mellan modellens förutsagda värden och testdatauppsättningens observerade värden. Tekniskt sett är det kvadratroten för medelvärdet av kvadraterna för felen. Ju lägre den är, desto bättre är modellen.

R Squared anger hur väl data passar en modell. Sträcker sig från 0 till 1. Värdet 0 innebär att data är slumpmässiga eller inte kan passa modellen. Värdet 1 innebär att modellen exakt matchar data. Du vill att poängen R Squared ska vara så nära 1 som möjligt.

Att skapa framgångsrika modeller är en iterativ process. Den här modellen har inledande lägre kvalitet eftersom självstudien använder små datauppsättningar för att tillhandahålla snabb modellträning. Om du inte är nöjd med modellkvaliteten kan du försöka förbättra den genom att tillhandahålla större träningsdatauppsättningar eller genom att välja olika träningsalgoritmer med olika hyperparametrar för varje algoritm. Mer information finns i avsnittet Förbättra din modell nedan.

Använd din modell

Nu kan du använda din tränade modell för att göra förutsägelser om nya data.

UseModelForSinglePrediction() Skapa metoden, precis efter EvaluateModel() -metoden, med hjälp av följande kod:

void UseModelForSinglePrediction(MLContext mlContext, ITransformer model)
{

}

PredictionEngine Använd för att förutsäga klassificeringen genom att lägga till följande kod i UseModelForSinglePrediction():

Console.WriteLine("=============== Making a prediction ===============");
var predictionEngine = mlContext.Model.CreatePredictionEngine<MovieRating, MovieRatingPrediction>(model);

PredictionEngine är ett bekvämlighets-API som gör att du kan utföra en förutsägelse på en enda instans av data. PredictionEngine är inte trådsäkert. Det är acceptabelt att använda i entrådade miljöer eller prototypmiljöer. För bättre prestanda och trådsäkerhet i produktionsmiljöer använder du PredictionEnginePool tjänsten, som skapar ett ObjectPool objekt PredictionEngine för användning i hela programmet. Se den här guiden om hur du använder PredictionEnginePool i ett ASP.NET Core webb-API.

Anteckning

PredictionEnginePool tjänsttillägget är för närvarande i förhandsversion.

Skapa en instans av MovieRating anropad testInput och skicka den till förutsägelsemotorn genom att lägga till följande som nästa kodrader i UseModelForSinglePrediction() metoden:

var testInput = new MovieRating { userId = 6, movieId = 10 };

var movieRatingPrediction = predictionEngine.Predict(testInput);

Funktionen Predict() gör en förutsägelse för en enda datakolumn.

Du kan sedan använda Score, eller det förutsagda omdömet, för att avgöra om du vill rekommendera filmen med movieId 10 till användare 6. Desto högre Scoreär , desto högre är sannolikheten för att en användare gillar en viss film. I det här fallet kan vi säga att du rekommenderar filmer med ett förutsagt omdöme på > 3,5.

Om du vill skriva ut resultatet lägger du till följande som nästa kodrader i UseModelForSinglePrediction() -metoden:

if (Math.Round(movieRatingPrediction.Score, 1) > 3.5)
{
    Console.WriteLine("Movie " + testInput.movieId + " is recommended for user " + testInput.userId);
}
else
{
    Console.WriteLine("Movie " + testInput.movieId + " is not recommended for user " + testInput.userId);
}

Lägg till följande som nästa kodrad efter anropet EvaluateModel() till metoden för att anropa din UseModelForSinglePrediction() metod:

UseModelForSinglePrediction(mlContext, model);

Utdata för den här metoden bör se ut ungefär så här:

=============== Making a prediction ===============
Movie 10 is recommended for user 6

Spara din modell

Om du vill använda din modell för att göra förutsägelser i slutanvändarprogram måste du först spara modellen.

SaveModel() Skapa metoden, precis efter UseModelForSinglePrediction() -metoden, med hjälp av följande kod:

void SaveModel(MLContext mlContext, DataViewSchema trainingDataViewSchema, ITransformer model)
{

}

Spara din tränade modell genom att lägga till följande kod i SaveModel() metoden:

var modelPath = Path.Combine(Environment.CurrentDirectory, "Data", "MovieRecommenderModel.zip");

Console.WriteLine("=============== Saving the model to a file ===============");
mlContext.Model.Save(model, trainingDataViewSchema, modelPath);

Den här metoden sparar din tränade modell i en .zip fil (i mappen Data), som sedan kan användas i andra .NET-program för att göra förutsägelser.

Lägg till följande som nästa kodrad efter anropet UseModelForSinglePrediction() till metoden för att anropa din SaveModel() metod:

SaveModel(mlContext, trainingDataView.Schema, model);

Använda din sparade modell

När du har sparat din tränade modell kan du använda modellen i olika miljöer. Se Spara och läsa in tränade modeller för att lära dig hur du operationaliserar en tränad maskininlärningsmodell i appar.

Resultat

När du har följt stegen ovan kör du konsolappen (Ctrl + F5). Dina resultat från den enda förutsägelsen ovan bör likna följande. Du kan se varningar eller bearbeta meddelanden, men dessa meddelanden har tagits bort från följande resultat för tydlighetens skull.

=============== Training the model ===============
iter      tr_rmse          obj
   0       1.5382   3.1213e+05
   1       0.9223   1.6051e+05
   2       0.8691   1.5050e+05
   3       0.8413   1.4576e+05
   4       0.8145   1.4208e+05
   5       0.7848   1.3895e+05
   6       0.7552   1.3613e+05
   7       0.7259   1.3357e+05
   8       0.6987   1.3121e+05
   9       0.6747   1.2949e+05
  10       0.6533   1.2766e+05
  11       0.6353   1.2636e+05
  12       0.6209   1.2561e+05
  13       0.6072   1.2462e+05
  14       0.5965   1.2394e+05
  15       0.5868   1.2352e+05
  16       0.5782   1.2279e+05
  17       0.5713   1.2227e+05
  18       0.5637   1.2190e+05
  19       0.5604   1.2178e+05
=============== Evaluating the model ===============
Rms: 0.977175077487166
RSquared: 0.43233349213192
=============== Making a prediction ===============
Movie 10 is recommended for user 6
=============== Saving the model to a file ===============

Grattis! Nu har du skapat en maskininlärningsmodell för att rekommendera filmer. Du hittar källkoden för den här självstudien på lagringsplatsen dotnet/samples .

Förbättra din modell

Det finns flera sätt att förbättra modellens prestanda så att du kan få mer exakta förutsägelser.

Data

Genom att lägga till fler träningsdata som har tillräckligt med exempel för varje användare och film-ID kan du förbättra kvaliteten på rekommendationsmodellen.

Korsvalidering är en teknik för att utvärdera modeller som slumpmässigt delar upp data i delmängder (i stället för att extrahera testdata från datauppsättningen som du gjorde i den här självstudien) och som tar några av grupperna som träningsdata och några av grupperna som testdata. Den här metoden överträffar att göra en träningstestsplit när det gäller modellkvalitet.

Funktioner

I den här självstudien använder du bara de tre Features (user id, movie id, och rating) som tillhandahålls av datauppsättningen.

Även om det här är en bra början kanske du i själva verket vill lägga till andra attribut eller Features (till exempel ålder, kön, geoplats osv.) om de ingår i datauppsättningen. Om du lägger till mer relevanta Features kan du förbättra prestandan för din rekommendationsmodell.

Om du är osäker på vad som Features kan vara mest relevant för din maskininlärningsuppgift kan du också använda beräkning av funktionsbidrag (FCC) och permutationsfunktionsvikt, som ML.NET ger för att upptäcka de mest inflytelserika Features.

Hyperparametrar för algoritmer

Även om ML.NET tillhandahåller bra standardträningsalgoritmer kan du finjustera prestanda ytterligare genom att ändra algoritmens hyperparametrar.

För Matrix Factorizationkan du experimentera med hyperparametrar som NumberOfIterations och ApproximationRank för att se om det ger bättre resultat.

I den här självstudien är till exempel algoritmalternativen:

var options = new MatrixFactorizationTrainer.Options
{
    MatrixColumnIndexColumnName = "userIdEncoded",
    MatrixRowIndexColumnName = "movieIdEncoded",
    LabelColumnName = "Label",
    NumberOfIterations = 20,
    ApproximationRank = 100
};

Andra rekommendationsalgoritmer

Matrisfaktoriseringsalgoritmen med samarbetsfiltrering är bara en metod för att utföra filmrekommendationer. I många fall kanske du inte har klassificeringsdata tillgängliga och bara har filmhistorik tillgänglig från användare. I andra fall kan du ha mer än bara användarens klassificeringsdata.

Algoritm Scenario Exempel
En klassmatrisfaktorisering Använd detta när du bara har userId och movieId. Den här rekommendationsstilen baseras på samköpsscenariot eller produkter som ofta köps tillsammans, vilket innebär att kunderna får en uppsättning produkter baserat på deras egen inköpsorderhistorik. >Prova
Fältmedvetna factoriseringsdatorer Använd detta för att ge rekommendationer när du har fler funktioner utöver userId, productId och omdöme (till exempel produktbeskrivning eller produktpris). Den här metoden använder också en metod för samarbetsfiltrering. >Prova

Nytt användarscenario

Ett vanligt problem vid samarbetsfiltrering är kallstartsproblemet, vilket är när du har en ny användare utan tidigare data att dra slutsatser från. Det här problemet löses ofta genom att be nya användare att skapa en profil och till exempel betygsätta filmer som de har sett tidigare. Även om den här metoden lägger viss börda på användaren, ger den viss startdata för nya användare utan klassificeringshistorik.

Resurser

De data som används i den här självstudien härleds från MovieLens Dataset.

Nästa steg

I den här självstudiekursen lärde du dig att:

  • Välj en maskininlärningsalgoritm
  • Förbereda och läsa in dina data
  • Skapa och träna en modell
  • Utvärdera en modell
  • Distribuera och använda en modell

Gå vidare till nästa självstudie om du vill veta mer