Hi rekan-rekan Makers,
Bertemu lagi di seri ML.NET, kali ini kita akan mencoba menggunakan ML.NET untuk melakukan klasifikasi data ke dalam beberapa kategori. Untuk rekan-rekan yang belum mengikuti seri ini dari awal silakan baca dari artikel ini. Adapun beberapa hal yang sebelumnya dibahas antara lain regression dan binary classification.
Dataset yang akan kita gunakan adalah data struktur biji gandum. Silakan melihat informasi mengenai dataset ini di link ini. Biji gandum ini diklasifikasi menjadi 3 varietas yaitu : Kama, Rosa dan Canadian. Masing-masing varietas memiliki 70 unsur diacak untuk percobaan. Struktur biji ini dideteksi menggunakan Soft X-Ray. Studi ini dilakukan dari hasil panen di bidang eksperimental Institute of Agrophysics dari Akademi Ilmu Pengetahuan Polandia di Lublin.
Beberapa attribut dari dataset ini adalah:
- Area (A), attribut ini adalah features
- Perimeter (P), attribut ini adalah features
- Compactness (C) = 4*pi*A/P^2, attribut ini adalah features
- Length of kernel, attribut ini adalah features
- Width of kernel, attribut ini adalah features
- Asymmetry coefficient, attribut ini adalah features
- Length of kernel groove, attribut ini adalah features
- Category, attribut ini adalah 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 SeedsApp
Lalu masuk ke folder yang baru dibuat dengan mengetik:
cd SeedsApp
Selanjutnya buat aplikasi console dengan mengetik:
dotnet new console
Kita perlu menambahkan nuget package ML.NET dengan mengetik:
dotnet add package Microsoft.ML
Kemudian buatlah folder dengan nama “Data” dengan mengetik:
mkdir Data
Lalu download file csv dari link ini, dan masukan ke folder “Data” tersebut.
Kemudian buka dengan visual studio code folder “SeedsApp”
pada Program.cs masukan namespace ML.NET dengan mengetik pada bagian atas:
using Microsoft.ML; using Microsoft.ML.Data; using System.Collections.Generic; using System.IO; using System.Linq;
Selanjutnya buatlah class dengan nama “SeedData.cs” isikan kode berikut:
using Microsoft.ML.Data; using System; using System.Collections.Generic; using System.Text; namespace SeedsApp { public class SeedData { [ColumnName("Area"), LoadColumn(0)] public float Area { get; set; } [ColumnName("Perimeter"), LoadColumn(1)] public float Perimeter { get; set; } [ColumnName("Compactness"), LoadColumn(2)] public float Compactness { get; set; } [ColumnName("Length"), LoadColumn(3)] public float Length { get; set; } [ColumnName("Width"), LoadColumn(4)] public float Width { get; set; } [ColumnName("AsymmetryCoefficient"), LoadColumn(5)] public float AsymmetryCoefficient { get; set; } [ColumnName("LengthOfKernel"), LoadColumn(6)] public float LengthOfKernel { get; set; } [ColumnName("Category"), LoadColumn(7)] public int Category { get; set; } } }
Kode diatas merepresentasikan struktur csv yang kita gunakan untuk data training, selanjutnya buat class untuk prediksi dengan nama “SeedPrediction.cs”, isi dengan kode berikut:
using System; using System.Collections.Generic; using System.Text; namespace SeedsApp { public class SeedPrediction { public float[] Score { get; set; } } }
Score akan berisi nilai-nilai dari kategori yang ada, semakin tinggi semakin mendekati prediksi. Lalu buka “Program.cs” dan masukan kode berikut ke dalam void main:
//Create MLContext MLContext mlContext = new MLContext(); //Load Data File IDataView trainData = mlContext.Data.LoadFromTextFile<SeedData>(GetAbsolutePath("../../../Data/seeds_dataset.txt"), separatorChar: '\t', hasHeader: false);
Kode diatas akan meload data training dari file, lalu menyimpannya ke objek IDataView. Jika ingin melihat data saat debugging gunakan method Preview(), selanjutnya kita akan melakukan transformasi data dengan kode berikut:
//Data process configuration with pipeline data transformations var dataPrepTransform = mlContext.Transforms.Conversion.MapValueToKey("Label", "Category") .Append(mlContext.Transforms.Concatenate("Features", new[] { "Area", "Perimeter", "Compactness", "Length", "Width", "AsymmetryCoefficient", "LengthOfKernel"})) .Append(mlContext.Transforms.NormalizeMinMax("Features", "Features")) .AppendCacheCheckpoint(mlContext); // Create data prep transformer ITransformer dataPrepTransformer = dataPrepTransform.Fit(trainData); IDataView transformedTrainingData = dataPrepTransformer.Transform(trainData);
Kode diatas digunakan untuk memilih beberapa kolom menjadi features dan menentukan kolom yang menjadi label, kita juga memapping value dari category menjadi key. Selanjutnya kita pilih algoritma ML dan lakukan training dengan kode berikut:
// Choose learner var SdcaEstimator = mlContext.MulticlassClassification.Trainers.SdcaMaximumEntropy(labelColumnName: "Label", featureColumnName: "Features"); // Build machine learning model var trainedModel = dataPrepTransformer.Append(SdcaEstimator.Fit(transformedTrainingData));
Setelah dijalankan beberapa saat maka model kita sudah dapat digunakan, lalu berikut adalah cara mengevaluasi akurasi model kita:
/ Measure trained model performance var testData = trainedModel.Transform(transformedTrainingData); var testMetrics = mlContext.MulticlassClassification.Evaluate(testData); Console.WriteLine($"*************************************************************************************************************"); Console.WriteLine($"* Metrics for Multi-class Classification model - Test Data "); Console.WriteLine($"*------------------------------------------------------------------------------------------------------------"); Console.WriteLine($"* MicroAccuracy: {testMetrics.MicroAccuracy:0.###}"); Console.WriteLine($"* MacroAccuracy: {testMetrics.MacroAccuracy:0.###}"); Console.WriteLine($"* LogLoss: {testMetrics.LogLoss:#.###}"); Console.WriteLine($"* LogLossReduction: {testMetrics.LogLossReduction:#.###}"); Console.WriteLine($"*************************************************************************************************************");
Metrik MicroAccuracy menjelaskan tentang setiap pasangan class contoh memberikan kontribusi yang sama pada metrik akurasi, semakin mendekati 1 semakin baik, MacroAccuracy menjelaskan tentang bahwa setiap kelas memberikan kontribusi yang sama pada metrik akurasi. Class minoritas akan dianggap sama dengan class yang lebih besar, semakin mendekati 1 semakin baik. LogLoss menjelaskan tentang akurasi classifier, semakin mendekati 0 nilainya semakin baik, LogLossReduction, nilai 100 adalah prediksi sempurna, sedangkan 0 mengindikasikan rata-rata dari prediksi. Nilai ini semakin mendekati 0 semakin baik.
Selanjutnya masukan kode berikut untuk menyimpan model ke dalam file binary:
var modelRelativePath = GetAbsolutePath("MLModel.zip"); mlContext.Model.Save(trainedModel, trainData.Schema, GetAbsolutePath(modelRelativePath)); Console.WriteLine("The model is saved to {0}", GetAbsolutePath(modelRelativePath));
Setelah model disimpan kita coba muat ke dalam objek ITransformer, lalu kita lakukan prediksi tunggal dengan contoh data. Berikut adalah kodenya:
ITransformer mlModel = mlContext.Model.Load(GetAbsolutePath(modelRelativePath), out DataViewSchema inputSchema); var predEngine = mlContext.Model.CreatePredictionEngine<SeedData, SeedPrediction>(mlModel); VBuffer<int> keys = default; predEngine.OutputSchema["PredictedLabel"].GetKeyValues(ref keys); var labelsArray = keys.DenseValues().ToArray(); Dictionary<int, string> CancerTypes = new Dictionary<int, string>(); CancerTypes.Add(1, "Kama"); CancerTypes.Add(2, "Rosa"); CancerTypes.Add(3, "Canadian"); // Create sample data to do a single prediction with it var sampleData = mlContext.Data.CreateEnumerable<SeedData>(trainData, false).First(); // Try a single prediction SeedPrediction predictionResult = predEngine.Predict(sampleData); var Maks = Array.IndexOf(predictionResult.Score, predictionResult.Score.Max()); Console.WriteLine($"Single Prediction --> Predicted label and score: {CancerTypes[labelsArray[Maks]]}: {predictionResult.Score[Maks]:0.####}");
Pada kode diatas rekan-rekan bisa lihat, bahwa output dari prediksi berbentuk key-value yang harus dimapping ke data label rekan-rekan. Nah, silakan bereksperimen dengan data-data lainnya, misalnya kategori pujaan hati idaman berdasarkan data-data behaviour dan penampakannya.. ;D
Source code lengkap dapat diunduh dari link ini. Sampai jumpa di artikel selanjutnya pada seri yang sama.
Salam Makers