ML.NET Series: Membuat Rekomendasi Restaurant (Matrix Factorization)

Hi rekan-rekan Makers,

Bertemu lagi di seri ML.NET, kali ini kita akan mencoba menggunakan ML.NET untuk memberikan rekomendasi berdasarkan data history. Untuk rekan-rekan yang belum mengikuti seri ini dari awal silakan baca dari artikel ini. Adapun beberapa hal yang sebelumnya dibahas antara lain regression, binary classification, multiclass classification, clustering, dan time-series.

Jika rekan-rekan membuka situs jual beli online terkadang muncul saran produk-produk lainnya yang suka dibeli bersama barang yang kita pilih. Tapi untuk kasus kali ini kita akan memberikan rekomendasi berdasarkan nilai rating yang diberikan terhadap restoran tertentu. Logika sederhananya jika kita suka makanan pedas maka kita memberikan score tinggi pada restoran-restoran yang menyajikan makanan pedas, dan jika teman kita juga suka pedas tentunya akan memiliki preferensi sama dalam memilih restoran. Nah dataset yang akan kita gunakan memiliki attribut antara lain:

  1. Reviewer, ini akan menjadi features
  2. Restauran, nama restoran akan menjadi features
  3. Score, nilai rating 1-10 yang diberikan reviewer, ini menjadi label

selanjutnya, rekan-rekan memastikan sudah menginstall .NET Core / .NET Framework versi terakhir, dalam artikel ini saya menggunakan .NET Core versi 2.2. Jika belum silakan download disini. Jika belum memiliki IDE silakan download visual studio and vs code.

Langkah pertama silakan buat project baru dengan tipe console application. Kalau dengan dengan .Net Core bisa menggunakan CLI, silakan buka terminal atau command line (cmd.exe). Lalu ketik:

mkdir RestauranRecommenderApp

Lalu masuk ke folder yang baru dibuat dengan mengetik:

cd RestauranRecommenderApp

Selanjutnya buat aplikasi console dengan mengetik:

dotnet new console

Kita perlu menambahkan nuget package ML.NET dan algoritma Recommendation dengan mengetik:

dotnet add package Microsoft.ML
dotnet add package Microsoft.ML.Recommender

Kemudian buatlah folder dengan nama “Data” dengan mengetik:

mkdir Data

Lalu download file tsv dari link ini, dan masukan ke folder “Data” tersebut.

Kemudian buka dengan visual studio code folder “RestauranRecommenderApp”

pada Program.cs masukan namespace ML.NET dengan mengetik pada bagian atas:

using Microsoft.ML;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

Selanjutnya buatlah class dengan nama “RestaurantData.cs” isikan kode berikut:

using Microsoft.ML.Data;
using System;
using System.Collections.Generic;
using System.Text;

namespace RestauranRecommenderApp
{
    class RestaurantData
    {
        [ColumnName("Reviewer"), LoadColumn(0)]
        public string Reviewer { get; set; }
        [ColumnName("RestaurantName"), LoadColumn(1)]
        public string RestaurantName { get; set; }
        [ColumnName("Score"), LoadColumn(2)]
        public float Score { get; set; }
    }
}

Class diatas merepresentasikan struktur data training yang kita gunakan. Lalu buatlah class dengan nama “RestaurantPrediction.cs” isikan kode berikut:

using System;
using System.Collections.Generic;
using System.Text;

namespace RestauranRecommenderApp
{
public class RestaurantPrediction
{
public float Label;
public float Score;
}
}

Class ini digunakan untuk melakukan prediksi nilai rating restoran. Lalu kembali ke file “Program.cs” lalu masukan kode berikut dalam void main:

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

var filePath = GetAbsolutePath("../../../Data/IENS_USER_ITEM.csv");
//Load Data File
IDataView trainData = mlContext.Data.LoadFromTextFile<RestaurantData>(filePath, separatorChar: ',', hasHeader: true);

Kode diatas memuat data training dari csv, lalu memasukannya pada objek IDataView. Rekan-rekan bisa melihat preview datanya dengan method Preview(). Selanjut kita lakukan transformasi data dengan kode berikut:

var dataPrepTransform = mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: "RestaurantNameEncoded", inputColumnName: nameof(RestaurantData.RestaurantName))
.Append(mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: "ReviewerEncoded", inputColumnName: nameof(RestaurantData.Reviewer)))
.Append(mlContext.Transforms.CopyColumns("Label", nameof(RestaurantData.Score)))
.AppendCacheCheckpoint(mlContext);

// Create data transformer
ITransformer dataPrepTransformer = dataPrepTransform.Fit(trainData);

IDataView transformedTrainingData = dataPrepTransformer.Transform(trainData);

Kita ubah restauran dan reviewer menjadi key (dalam bentuk number) agar dapat ditraining dengan algoritma rekomendasi. Selanjutnya kita pilih algoritma rekomendasinya:

// Choose learner
var Estimator = mlContext.Recommendation().Trainers.MatrixFactorization(
labelColumnName: "Label",
matrixColumnIndexColumnName: "RestaurantNameEncoded",
matrixRowIndexColumnName: "ReviewerEncoded");

// Build machine learning model
var trainedModel = dataPrepTransformer.Append(Estimator.Fit(transformedTrainingData));

Kita gunakan MatrixFactorization karena kita memiliki cuma 2 features dan nilai label berupa rating. Algoritma ini umum banyak digunakan. Selanjutnya kita panggil method Fit untuk mentraining model. Lalu kita ukur seberapa akurat model kita dengan kode berikut:

// Measure trained model performance
var testData = trainedModel.Transform(transformedTrainingData);
var metrics = mlContext.Regression.Evaluate(testData, labelColumnName: "Label", scoreColumnName: "Score");

Console.WriteLine();
Console.WriteLine("Model quality metrics evaluation");
Console.WriteLine("Root Mean Squared Error : " + metrics.RootMeanSquaredError.ToString());
Console.WriteLine("RSquared: " + metrics.RSquared.ToString());
Console.WriteLine("=============== End of model evaluation ===============");

Kita gunakan evaluator yang sama dengan algoritma regresi. Sehingga beberapa metriknya bisa disimpulkan, RMS semakin rendah semakin baik, karena menunjukan perbedaan hasil prediksi model dan nilai yang sebenernya dari test data. Sedangkan nilai RSquared semakin mendekati 1 semakin baik, karena artinya 0 adalah tebakan random, dan 1 tepat dalam memprediksi nilai. Selanjutnya model kita simpan dalam format binary dengan kode berikut:

var modelRelativePath = GetAbsolutePath("MLModel.zip");
mlContext.Model.Save(trainedModel, trainData.Schema, GetAbsolutePath(modelRelativePath));
Console.WriteLine("The model is saved to {0}", GetAbsolutePath(modelRelativePath));

Kemudian kita ujicoba untuk memuat model dari file, dan lakukan prediksi tunggal dengan data contoh:

ITransformer mlModel = mlContext.Model.Load(GetAbsolutePath(modelRelativePath), out DataViewSchema inputSchema);
var predEngine = mlContext.Model.CreatePredictionEngine<RestaurantData, RestaurantPrediction>(mlModel);

// Create sample data to do a single prediction with it 
var sampleDatas = mlContext.Data.CreateEnumerable<RestaurantData>(trainData, false).Take(10);

foreach (var sampleData in sampleDatas)
{
// Try a single prediction
RestaurantPrediction predictionResult = predEngine.Predict(sampleData);
if (Math.Round(predictionResult.Score, 1) > 7.5)
{
Console.WriteLine("Restaurant " + sampleData.RestaurantName + " is recommended for reviewer " + sampleData.Reviewer);
}
else
{
Console.WriteLine("Restaurant " + sampleData.RestaurantName + " is not recommended for reviewer " + sampleData.Reviewer);
}
}

Nah seperti rekan-rekan lihat kita asumsikan semakin tinggi nilai prediksi rating sebuah restoran (diatas threshold yaitu 7.5) maka semakin direkomendasikan restauran tersebut untuk reviewer tertentu.

Nah jika saat dirunning ada error tenang saja, rekan-rekan bisa unduh source codenya dari sini. Agar akurasi semakin baik coba tambahkan jumlah dataset dan tuning hyper parameter dari model yang digunakan.

Nah, ada pertanyaan nih… bagaimana jika kita memiliki lebih dari 2 features untuk memberi rekomendasi, sebagai contoh ada restoran, lokasi, kebersihan, pelayanan, harga, dsb.. Tentunya kita membutuhkan algoritma rekomendasi yang berbeda. Tunggu artikel selanjutnya, kita akan membahas bagaimana menggunakan algoritma Field-Aware Factorization Machine untuk memberikan rekomendasi.

Semoga manfaat dan berkah.

Salam Makers

Loading

You May Also Like