ML.net AutoML ile En Uygun Modeli Bulalım

ML.net ilgili yazılara biraz ara vermiştim çünkü her yeni versiyonda o kadar fazla değişiklik oldu ki yazıları sürekli güncellemek gerekiyor. Fakat ML.net hem major bir sürüme ulaştı hem de ekosistemi giderek genişliyor. Bu da artık geliştiricilerin radikal değişikler yapmasını engeller diye düşünüyorum ve yazılara yavaştan tekrar başlıyorum.

👉 AutoML şeklinde arattığınızda AzureML'in içinde de benzer isimde bir şeyler olduğunu bulabilirsiniz. Bu yazıda ben ML.net'in bir eklentisi olanından bahsediyor olacağım.

Genellikle makine öğrenmesi işlerimizde veri ön işleme adımlarını tamamladıktan sonra farklı algoritmaları denemeye koyuluruz. Bir algoritmada karar kılsak bile o algoritmayı farklı parametreler ile deneriz. İşte AutoML kütüphanesi buradaki farklı denemelerden bizi kurtarıyor.

Örneklemeyi bir regresyon problemi üzerinden yapacağım. Problem en bilindik verisetlerinden olan "Kaliforniya ev fiyatları" üzerine olacak. Veri setine ulaşmak için şu adresi kullanabilirsiniz: https://www.kaggle.com/camnugent/california-housing-prices

Bir .net core 3.0 projesi açarak işe başlıyoruz. Projeyi açtıktan sonra ilk olarak gerekli paketleri yüklüyoruz. AutoML ML.net'in üzerine geliştirildiği için AutoML'i yüklediğinizde gerekli ML.net paketi de yüklenmiş oluyor. Fakat ben önce ML.net i yüklemeyi tercih ediyorum. Böylece ikisinin de sürümlerini takip edebilmem daha kolay oluyor. Neticede paket ekranımız şöyle oluyor:
file

🪀 Gördüğünüz gibi uslanmadım ve yazıyı 0.16 sürümü için hazırlıyorum. Bu da demek oluyor ki AutoML'in daha yüksek sürümlerini kullanıyorsanız bu yazıdaki örneklerde problem yaşayabilirsiniz. Şayet bu durum yaşanırsa yazıya yorum atmaktan çekinmeyin ben de mevcut sürüme göre yazıyı güncelleyim.

Modeli Oluşturalım

Elimizdeki CSV dosyasının C# tarafındaki sınıf karşılığını oluşturmakla başlıyoruz. Bu işi ister elle ister araç kullanarak yapabilirsiniz. Ben https://toolslick.com/generation/code/class-from-csv adresindeki aracı kullanarak öncelikle basit bir sınıf oluşturuyorum, bunu yaptığımız sonuç aşağıdaki gibi olacaktır.

   public class InputModel
    {
    public double Longitude { get; set; }
    public double Latitude { get; set; }
    public double HousingMedianAge { get; set; }
    public double TotalRooms { get; set; }
    public double TotalBedrooms { get; set; }
    public double Population { get; set; }
    public double Households { get; set; }
    public double MedianIncome { get; set; }
    public double MedianHouseValue { get; set; }
    public string OceanProximity { get; set; }
    }

Bildiğiniz gibi ML.net eşleştirme işlemini indisler üzerinden yapıyor. Bu sebeple her bir property'nin üzerinde ilgili indisi belirten bir attribute ekliyoruz. Ek olarak ML.net double türünü sevmiyor, bunları float olarak değiştiriyoruz.

   public class InputModel
    {
        [LoadColumn(0)]
        public float Longitude { get; set; }
        [LoadColumn(1)]
        public float Latitude { get; set; }
        [LoadColumn(2)]
        public float HousingMedianAge { get; set; }
        [LoadColumn(3)]
        public float TotalRooms { get; set; }
        [LoadColumn(4)]
        public float TotalBedrooms { get; set; }
        [LoadColumn(5)]
        public float Population { get; set; }
        [LoadColumn(6)]
        public float Households { get; set; }
        [LoadColumn(7)]
        public float MedianIncome { get; set; }
        [LoadColumn(8)]
        public float MedianHouseValue { get; set; }
        [LoadColumn(9)]
        public string OceanProximity { get; set; }
    }

Bir de çıktı için model oluşturmamız lazım. Bunun için fiyatı temsil eden tek bir property işimi görecektir.

  public class OutputModel
    {
        public double Score { get; set; }
    }

Artık eğitim işine başlayabiliriz. Gerekli using satırlarını ekleyerek işe başlıyoruz:

using Microsoft.ML;
using Microsoft.ML.AutoML;
using Microsoft.ML.Data;

Buradan sonrası ise son derece hızlı gerçekleşecek. Kodu inceleyin:

var context = new MLContext();

var trainData = context.Data
                       .LoadFromTextFile<InputModel>(path: "housing.csv",
                                                     hasHeader: true,
                                                     separatorChar: ',');

var experiment = context.Auto()
                        .CreateRegressionExperiment(maxExperimentTimeInSeconds: 30);

var results = experiment.Execute(trainData: trainData,
                                 labelColumnName: nameof(InputModel.MedianHouseValue));

Console.WriteLine($"Algoritma:  { results.BestRun.TrainerName}");
Console.WriteLine($"R^2:  { results.BestRun.ValidationMetrics.RSquared}");

Gerçekten hızlı oldu değil mi? İlk satırda klasik context oluşturarak başladık ve peşinden üzerinde çalışacağımız veriyi bu bağlama yükledik.

Ardında Auto() metodu ile deney nesnesini oluşturduk ve kendisiden bir regresyon denemesi yapmasını ve en iyi sonucu bulana kadar 30sn uğraşmasını istedik.

Sonra bu isteğimizi yapmasını üzerinde çalışacağı veriyi ve bulacağı hedef niteliği vererek istedik. Artık yaslanıp 30sn bekleyeceğiz.

Süre sona erdiğinde AutoML en iyi sonucu BestRun property'si içine koyacak. Bu property üzerinden seçilen model hakkında bilgiler alabiliriz. Biz ince ayar yapmadığımız için $$R^2$$ değeri en iyi hale getirilmeye çalışıldı. İnce ayar kısmına preview sürümleri bitip her şey netleşince tekrar değinmeyi planlıyorum.

Burada oluşan modeli kaydetmek için şu adımları izleyebilirsiniz:

var model = results.BestRun.Model;
context.Model.Save(model, trainData.Schema, "model.zip");

Başka bir projenizde bu modelden bir tahminleyici metot üretmek için ise şu adımları izleyebilirsiniz:

var context2 = new MLContext();
var model2 = context2.Model.Load("model.zip", out var schema);
var ml = context2.Model.CreatePredictionEngine<InputModel, OutputModel>(model2);
var tahmin = ml.Predict(new InputModel
{
    Households = 127F,
    HousingMedianAge = 21F,
    Latitude = -122F,
    Longitude = 37.1F,
    TotalRooms = 888F,
    TotalBedrooms = 123F,
    Population = 322F,
    MedianIncome = 8.352F,
    OceanProximity = "NEAR BAY"
});
Console.WriteLine($"Tahmin : {tahmin.Score}");
Console.ReadLine();

Yeni yazılarda görüşmek üzere.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.