Aracılığıyla paylaş


Öğretici: Zaman serisi analizi ve ML.NET ile bisiklet kiralama hizmeti talebini tahmin edin

ML.NET içeren bir SQL Server veritabanında depolanan veriler üzerinde tek değişkenli zaman serisi analizi kullanarak bisiklet kiralama hizmetine yönelik talebi tahmin etmeyi öğrenin.

Bu eğitimde şunları öğreniyorsunuz:

  • Sorunu anlama
  • Veritabanından veri yükleme
  • Tahmin modeli oluşturma
  • Tahmin modelini değerlendirme
  • Tahmin modelini kaydetme
  • Tahmin modeli kullanma

Önkoşullar

Zaman serisi tahmin örneğine genel bakış

Bu örnek, Tekil Spektrum Analizi olarak bilinen tek değişkenli bir zaman serisi analiz algoritması kullanarak bisiklet kiralama talebini tahmin eden bir C# konsol uygulamasıdır . Bu örneğin kodu GitHub'daki dotnet/machinelearning-samples deposunda bulunabilir.

Sorunu anlama

Verimli bir işlem çalıştırmak için envanter yönetimi önemli bir rol oynar. Stokta çok fazla ürün olması, raflarda duran satılmamış ürünlerin gelir elde etmemesi anlamına gelir. Çok az ürüne sahip olmak, satışların kaybolmasına ve rakiplerden satın alınan müşterilere yol açar. Bu nedenle, sabit soru şudur: Elde tutulacak en uygun stok miktarı nedir? Zaman serisi analizi, geçmiş verilere bakarak, desenleri tanımlayarak ve gelecekte bir süre değerleri tahmin etmek için bu bilgileri kullanarak bu sorulara yanıt sağlamaya yardımcı olur.

Bu öğreticide kullanılan verileri analiz etme tekniği tek değişkenli zaman serisi analizidir. Tek değişkenli zaman serisi analizi, aylık satışlar gibi belirli aralıklarda belirli bir süre boyunca tek bir sayısal gözleme göz atar.

Bu öğreticide kullanılan algoritma Tekil Spektrum Analizi(SSA)'dır. SSA, bir zaman serisini bir dizi asıl bileşene ayırarak çalışır. Bu bileşenler bir sinyalin eğilimlere, gürültüye, mevsimselliğe ve diğer birçok faktöre karşılık gelen parçaları olarak yorumlanabilir. Ardından bu bileşenler yeniden oluşturulur ve gelecekte bir süre değerleri tahmin etmek için kullanılır.

Konsol uygulaması oluşturma

  1. "BikeDemandForecasting" adlı bir C# Konsol Uygulaması oluşturun. İleri düğmesine tıklayın.

  2. Kullanılacak çerçeve olarak .NET 8'i seçin. Oluştur düğmesine tıklayın.

  3. Microsoft.ML sürüm NuGet paketini yükleme

    Uyarı

    Bu örnek, aksi belirtilmedikçe bahsedilen NuGet paketlerinin en son kararlı sürümünü kullanır.

    1. Çözüm Gezgini'nde projenize sağ tıklayın ve NuGet Paketlerini Yönet'i seçin.
    2. Paket kaynağı olarak "nuget.org" öğesini seçin, Gözat sekmesini seçin, Microsoft.ML arayın.
    3. Ön sürümü dahil et onay kutusunu işaretleyin.
    4. Yükle düğmesini seçin.
    5. Listelenen paketlerin lisans koşullarını kabul ediyorsanız, Değişiklikleri Önizle iletişim kutusunda Tamam düğmesini ve ardından Lisans Kabulü iletişim kutusunda Kabul Ediyorum düğmesini seçin.
    6. System.Data.SqlClient ve Microsoft.ML.TimeSeries için bu adımları yineleyin.

Verileri hazırlama ve anlama

  1. Data adlı bir dizin oluşturun.
  2. DailyDemand.mdf veritabanı dosyasını indirin ve Veri dizinine kaydedin.

Uyarı

Bu öğreticide kullanılan veriler UCI Bisiklet Paylaşım Veri Kümesi'nden gelir. Hadi Fanaee-T ve João Gama, 'Topluluk dedektörlerini ve arka plan bilgilerini birleştiren olay etiketleme', Yapay Zekada İlerleme (2013): pp. 1-15, Springer Berlin Heidelberg, Web Link.

Özgün veri kümesi mevsimsellik ve hava durumuna karşılık gelen birkaç sütun içerir. Kısa ve kısa olması için ve bu öğreticide kullanılan algoritma yalnızca tek bir sayısal sütundaki değerleri gerektirdiğinden, özgün veri kümesi yalnızca aşağıdaki sütunları içerecek şekilde daraltılmıştır:

  • dteday: Gözlem tarihi.
  • year: Gözlemin kodlanmış yılı (0=2011, 1=2012).
  • cnt: O gün için toplam bisiklet kiralama sayısı.

Özgün veri kümesi, SQL Server veritabanında aşağıdaki şemaya sahip bir veritabanı tablosuna eşlenir.

CREATE TABLE [Rentals] (
    [RentalDate] DATE NOT NULL,
    [Year] INT NOT NULL,
    [TotalRentals] INT NOT NULL
);

Aşağıda verilerin bir örneği verilmiştir:

RentalDate Yıl TotalRentals
1/1/2011 0 985
1/2/2011 0 801
1/3/2011 0 1349

Giriş ve çıkış sınıfları oluşturma

  1. Program.cs dosyasını açın ve mevcut using yönergeleri aşağıdakilerle değiştirin:

    using Microsoft.ML;
    using Microsoft.ML.Data;
    using Microsoft.ML.Transforms.TimeSeries;
    using System.Data.SqlClient;
    
  2. Sınıf oluşturma ModelInput . sınıfının altına Program aşağıdaki kodu ekleyin.

    public class ModelInput
    {
        public DateTime RentalDate { get; set; }
    
        public float Year { get; set; }
    
        public float TotalRentals { get; set; }
    }
    

    ModelInput sınıfı aşağıdaki sütunları içerir:

    • RentalDate: Gözlem tarihi.
    • Yıl: Gözlemin kodlanmış yılı (0=2011, 1=2012).
    • TotalRentals: O güne ait toplam bisiklet kiralama sayısı.
  3. Yeni oluşturulan ModelOutput sınıfın altında sınıf oluşturunModelInput.

    public class ModelOutput
    {
        public float[] ForecastedRentals { get; set; }
    
        public float[] LowerBoundRentals { get; set; }
    
        public float[] UpperBoundRentals { get; set; }
    }
    

    ModelOutput sınıfı aşağıdaki sütunları içerir:

    • ForecastedRentals: Tahmin edilen dönem için tahmin edilen değerler.
    • LowerBoundRentals: Tahmin edilen dönem için tahmin edilen minimum değerler.
    • UpperBoundRentals: Tahmin edilen dönem için tahmin edilen maksimum değerler.

Yolları tanımlama ve değişkenleri başlatma

  1. Yönergelerin using altında verilerinizin konumunu, bağlantı dizesini ve eğitilen modelin kaydedileceği konumu depolamak için değişkenler tanımlayın.

    string rootDir = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "../../../"));
    string dbFilePath = Path.Combine(rootDir, "Data", "DailyDemand.mdf");
    string modelPath = Path.Combine(rootDir, "MLModel.zip");
    var connectionString = $"Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename={dbFilePath};Integrated Security=True;Connect Timeout=30;";
    
  2. mlContext Yolları tanımladıktan sonra aşağıdaki satırı ekleyerek değişkenini yeni bir örneğiyle MLContext başlatın.

    MLContext mlContext = new MLContext();
    

    MLContext sınıfı tüm ML.NET işlemleri için bir başlangıç noktasıdır ve mlContext'i başlatmak, model oluşturma iş akışı nesneleri arasında paylaşılabilen yeni bir ML.NET ortamı oluşturur. Entity Framework'tekine DBContext benzer, kavramsal olarak.

Verileri yükleme

  1. türünde DatabaseLoaderkayıtları yükleyen bir oluşturunModelInput.

    DatabaseLoader loader = mlContext.Data.CreateDatabaseLoader<ModelInput>();
    
  2. Veritabanından verileri yüklemek için sorguyu tanımlayın.

    string query = "SELECT RentalDate, CAST(Year as REAL) as Year, CAST(TotalRentals as REAL) as TotalRentals FROM Rentals";
    

    ML.NET algoritmaları verilerin türünde Singleolmasını bekler. Bu nedenle, veritabanından gelen ve türünde Realolmayan sayısal değerlerin tek duyarlıklı kayan nokta değerine dönüştürülmesi Realgerekir.

    Year ve TotalRental sütunlarının her ikisi de veritabanındaki tamsayı türleridir. CAST Yerleşik işlevi kullanılarak her ikisi de öğesine Realatılır.

  3. Veritabanına bağlanmak ve sorguyu yürütmek için bir DatabaseSource oluşturun.

    DatabaseSource dbSource = new DatabaseSource(SqlClientFactory.Instance,
                                    connectionString,
                                    query);
    
  4. Verileri içine IDataViewyükleyin.

    IDataView dataView = loader.Load(dbSource);
    
  5. Veri kümesi iki yıllık veriler içerir. Eğitim için yalnızca ilk yıla ait veriler kullanılır, ikinci yıl ise gerçek değerleri model tarafından üretilen tahminle karşılaştırmak için tutulur. Dönüştürmeyi kullanarak verileri filtreleyin FilterRowsByColumn .

    IDataView firstYearData = mlContext.Data.FilterRowsByColumn(dataView, "Year", upperBound: 1);
    IDataView secondYearData = mlContext.Data.FilterRowsByColumn(dataView, "Year", lowerBound: 1);
    

    İlk yıl için parametre 1 olarak ayarlanarak yalnızca 1'den küçük sütundaki YearupperBound değerler seçilir. Buna karşılık, ikinci yıl için parametre 1 olarak ayarlanarak lowerBound 1'den büyük veya 1'e eşit değerler seçilir.

Zaman serisi çözümleme işlem hattını tanımlama

  1. Zaman serisi veri kümesindeki değerleri tahmin etmek için SsaForecastingEstimator kullanan bir işlem hattı tanımlayın.

    var forecastingPipeline = mlContext.Forecasting.ForecastBySsa(
        outputColumnName: "ForecastedRentals",
        inputColumnName: "TotalRentals",
        windowSize: 7,
        seriesLength: 30,
        trainSize: 365,
        horizon: 7,
        confidenceLevel: 0.95f,
        confidenceLowerBoundColumn: "LowerBoundRentals",
        confidenceUpperBoundColumn: "UpperBoundRentals");
    

    forecastingPipeline ilk yıl için 365 veri noktası alır ve seriesLength parametresi tarafından belirtilen şekilde zaman serisi veri kümesini 30 günlük (aylık) aralıklara ayırır veya örnekler alır. Bu örneklerin her biri haftalık veya 7 günlük bir süre boyunca analiz edilir. Sonraki dönemler için tahmin edilen değerin ne olduğunu belirlerken, tahminde bulunmak için önceki yedi güne ait değerler kullanılır. Model, parametresi tarafından horizon tanımlanan yedi dönemi geleceğe tahmin etmek için ayarlanır. Tahmin, bilinçli bir tahmin olduğundan her zaman 100% doğru değildir. Bu nedenle, üst ve alt sınırlar tarafından tanımlanan en iyi ve en kötü durum senaryolarındaki değer aralığını bilmek iyidir. Bu durumda, alt ve üst sınırların güvenilirlik düzeyi 95%olarak ayarlanır. Güvenilirlik düzeyi buna göre artırılabilir veya azaltılabilir. Değer ne kadar yüksek olursa, istenen güvenilirlik düzeyini elde etmek için aralık üst ve alt sınırlar arasında o kadar geniştir.

  2. Fit Modeli eğitmek ve verileri önceden tanımlanmış forecastingPipelineolan öğesine sığdırmak için yöntemini kullanın.

    SsaForecastingTransformer forecaster = forecastingPipeline.Fit(firstYearData);
    

Modeli değerlendirme

Gelecek yılın verilerini tahmin ederek ve gerçek değerlerle karşılaştırarak modelin performansını değerlendirin.

  1. Evaluate dosyasının en altında adlı yeni bir yardımcı program yöntemi oluşturun.

    Evaluate(IDataView testData, ITransformer model, MLContext mlContext)
    {
    
    }
    
  2. yönteminin Evaluate içinde, eğitilen modelle yöntemini kullanarak Transform ikinci yılın verilerini tahmin edin.

    IDataView predictions = model.Transform(testData);
    
  3. yöntemini kullanarak CreateEnumerable verilerden gerçek değerleri alın.

    IEnumerable<float> actual =
        mlContext.Data.CreateEnumerable<ModelInput>(testData, true)
            .Select(observed => observed.TotalRentals);
    
  4. yöntemini kullanarak CreateEnumerable tahmin değerlerini alın.

    IEnumerable<float> forecast =
        mlContext.Data.CreateEnumerable<ModelOutput>(predictions, true)
            .Select(prediction => prediction.ForecastedRentals[0]);
    
  5. Gerçek ve tahmin değerleri arasındaki farkı (genellikle hata olarak adlandırılır) hesaplayın.

    var metrics = actual.Zip(forecast, (actualValue, forecastValue) => actualValue - forecastValue);
    
  6. Ortalama Mutlak Hata ve Kök Ortalama Kare Hatası değerlerini hesaplayarak performansı ölçün.

    var MAE = metrics.Average(error => Math.Abs(error)); // Mean Absolute Error
    var RMSE = Math.Sqrt(metrics.Average(error => Math.Pow(error, 2))); // Root Mean Squared Error
    

    Performansı değerlendirmek için aşağıdaki ölçümler kullanılır:

    • Ortalama Mutlak Hata: Tahminlerin gerçek değere ne kadar yakın olduğunu ölçer. Bu değer 0 ile sonsuz arasında değişir. 0'a ne kadar yakın olursa, modelin kalitesi o kadar iyi olur.
    • Kök Ortalama Kare Hatası: Modeldeki hatayı özetler. Bu değer 0 ile sonsuz arasında değişir. 0'a ne kadar yakın olursa, modelin kalitesi o kadar iyi olur.
  7. Ölçümleri konsola çıktılayın.

    Console.WriteLine("Evaluation Metrics");
    Console.WriteLine("---------------------");
    Console.WriteLine($"Mean Absolute Error: {MAE:F3}");
    Console.WriteLine($"Root Mean Squared Error: {RMSE:F3}\n");
    
  8. Evaluate Aşağıdaki yöntemi çağırarak yöntemini çağırınFit().

    Evaluate(secondYearData, forecaster, mlContext);
    

Modeli kaydetme

Modelinizden memnunsanız, daha sonra diğer uygulamalarda kullanmak üzere kaydedin.

  1. yönteminin altında Evaluate() bir TimeSeriesPredictionEngineoluşturun. TimeSeriesPredictionEngine tek tahminler yapmak için kullanışlı bir yöntemdir.

    var forecastEngine = forecaster.CreateTimeSeriesEngine<ModelInput, ModelOutput>(mlContext);
    
  2. Modeli, önceden tanımlanmış MLModel.zip değişken tarafından belirtilen adlı modelPath bir dosyaya kaydedin. Checkpoint Modeli kaydetmek için yöntemini kullanın.

    forecastEngine.CheckPoint(mlContext, modelPath);
    

Talebi tahmin etmek için modeli kullanma

  1. yönteminin altında Evaluate adlı Forecastyeni bir yardımcı program yöntemi oluşturun.

    void Forecast(IDataView testData, int horizon, TimeSeriesPredictionEngine<ModelInput, ModelOutput> forecaster, MLContext mlContext)
    {
    
    }
    
  2. yönteminin Forecast içinde, sonraki yedi gün için kiralama tahmin etmek için yöntemini kullanın Predict .

    ModelOutput forecast = forecaster.Predict();
    
  3. Yedi dönem için gerçek ve tahmin değerlerini hizalayın.

    IEnumerable<string> forecastOutput =
        mlContext.Data.CreateEnumerable<ModelInput>(testData, reuseRowObject: false)
            .Take(horizon)
            .Select((ModelInput rental, int index) =>
            {
                string rentalDate = rental.RentalDate.ToShortDateString();
                float actualRentals = rental.TotalRentals;
                float lowerEstimate = Math.Max(0, forecast.LowerBoundRentals[index]);
                float estimate = forecast.ForecastedRentals[index];
                float upperEstimate = forecast.UpperBoundRentals[index];
                return $"Date: {rentalDate}\n" +
                $"Actual Rentals: {actualRentals}\n" +
                $"Lower Estimate: {lowerEstimate}\n" +
                $"Forecast: {estimate}\n" +
                $"Upper Estimate: {upperEstimate}\n";
            });
    
  4. Tahmin çıktısını yineleyip konsolda görüntüleyin.

    Console.WriteLine("Rental Forecast");
    Console.WriteLine("---------------------");
    foreach (var prediction in forecastOutput)
    {
        Console.WriteLine(prediction);
    }
    

Uygulamayı çalıştırma

  1. Aşağıda yöntemini çağırarak Checkpoint() yöntemini çağırın Forecast .

    Forecast(secondYearData, 7, forecastEngine, mlContext);
    
  2. Uygulamayı çalıştırın. Konsolda aşağıdakine benzer bir çıktı görünmelidir. Kısalık adına çıktı kısaltıldı.

    Evaluation Metrics
    ---------------------
    Mean Absolute Error: 726.416
    Root Mean Squared Error: 987.658
    
    Rental Forecast
    ---------------------
    Date: 1/1/2012
    Actual Rentals: 2294
    Lower Estimate: 1197.842
    Forecast: 2334.443
    Upper Estimate: 3471.044
    
    Date: 1/2/2012
    Actual Rentals: 1951
    Lower Estimate: 1148.412
    Forecast: 2360.861
    Upper Estimate: 3573.309
    

Gerçek ve tahmin edilen değerlerin incelenmesi aşağıdaki ilişkileri gösterir:

Gerçek ve Tahmin Karşılaştırması

Tahmin edilen değerler tam kiralama sayısını tahmin etmese de, bir işlemin kaynak kullanımını iyileştirmesine olanak tanıyan daha dar bir değer aralığı sağlar.

Tebrikler! Bisiklet kiralama talebini tahmin etmek için bir zaman serisi makine öğrenmesi modelini başarıyla oluşturdunuz.

Bu öğreticinin kaynak kodunu dotnet/machinelearning-samples deposunda bulabilirsiniz.

Sonraki Adımlar