öğretici: zaman serisi analizi ve .net ML bisiklet kiralama hizmeti talebini tahmin etme

ML .net ile SQL Server veritabanında depolanan veriler üzerinde bağımsız zamanlı bir zaman serisi analizi kullanarak bir bisiklet kiralama hizmeti için talebi tahmin etme hakkında bilgi edinin.

Bu öğreticide şunların nasıl yapıldığını öğreneceksiniz:

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

Önkoşullar

Zaman serisi tahmin örneğine genel bakış

Bu örnek, tekil bir zaman serisi analizi analizi olarak bilinen tek değişkenli bir zaman serisi analiz algoritması kullanarak bisiklet için talebi tahmin eden bir C# .NET Core konsol uygulamasıdır . Bu örneğin kodu, GitHub üzerinde DotNet/machinöğrenim-örnekleri deposunda bulunabilir.

Sorunu anlama

Verimli bir işlem çalıştırmak için, envanter yönetimi bir anahtar rol oynar. Ücretteki bir ürünün çok fazla olması, raflardan herhangi bir gelir üretmeden satışa açık ürünler anlamına gelir. Çok az ürün, rakiplerden satın alınan satışları ve müşterileri kaybetmeyecek. Bu nedenle, sabit soru, elinizin altında tutulacak en uygun stok miktarı nedir? Zaman serisi analizi, geçmiş verileri inceleyerek, desenleri tanımlayarak ve bu bilgileri gelecekte bir süre tahmin etmek için kullanarak bu sorulara yanıt sağlanmasına yardımcı olur.

Bu öğreticide kullanılan verileri çözümlemeye yönelik teknik, zaman serisi analizinden bağımsız bir yöntemdir. Tek bir zaman serisi analizi, aylık satış gibi belirli aralıklarda tek bir sayısal izlemeye göz atacağız.

Bu öğreticide kullanılan algoritma tekil bir Spekme analizidir (SSA). SSA, bir dizi sorumlu bileşen için zaman serisini kaldırarak işe yarar. Bu bileşenler, eğilimler, gürültü, mevsimsellik ve birçok başka etkene karşılık gelen bir sinyalin parçaları olarak yorumlanamaz. Ardından, bu bileşenler yeniden yapılandırılır ve gelecekte değerleri tahmin etmek için kullanılır.

Konsol uygulaması oluşturma

  1. "Bikeisteğtahmini" adlı bir C# konsol uygulaması oluşturun. İleri düğmesine tıklayın.

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

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

    Not

    Bu örnek, aksi belirtilmediği takdirde, belirtilen NuGet paketlerinin en son kararlı sürümünü kullanır.

    1. Çözüm Gezgini, projenize sağ tıklayın ve NuGet paketlerini yönet' i seçin.
    2. Paket kaynağı olarak "nuget.org" öğesini seçin, Gözden geçirme sekmesini seçin, Microsoft. ml aratın.
    3. Ön sürümü dahil et onay kutusunu işaretleyin.
    4. Install düğmesini seçin.
    5. Değişiklikleri Önizle Iletişim kutusunda Tamam düğmesini seçin ve ardından listelenen paketlerin lisans koşullarını kabul ediyorsanız Lisans Kabulü iletişim kutusunda kabul ediyorum düğmesini seçin.
    6. System. Data. SqlClient ve Microsoft. ml için bu adımları yineleyin. TimeSeries.

Verileri hazırlama ve anlama

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

Not

Bu öğreticide kullanılan veriler, UCI bisiklet paylaşımı veri kümesindengelir. Fanaee-T, hadi ve gama, Joao, ' olay etiketleme birleştirme algılayıcıları ve arka plan bilgisi ', yapay zeka 'da Ilerleme (2013): PP. 1-15, Sprümlberg, Web bağlantısı.

Özgün veri kümesi mevsimsellik ve hava durumu ile ilgili birkaç sütun içerir. Breçekimi ve bu öğreticide kullanılan algoritma yalnızca tek bir sayısal sütundan değer gerektirdiğinden, özgün veri kümesi yalnızca aşağıdaki sütunları içerecek şekilde yoğunlaştırılmış:

  • dteday: Gözlem tarihi.
  • yıl: gözlemin kodlanmış yılı (0 = 2011, 1 = 2012).
  • sayisi: o güne ait bisiklet salları toplam sayısı.

özgün veri kümesi, bir SQL Server veritabanında aşağıdaki şemaya sahip bir veritabanı tablosuyla 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 var olan using deyimleri şu şekilde değiştirin:

    using System;
    using System.Collections.Generic;
    using System.Data.SqlClient;
    using System.IO;
    using System.Linq;
    using Microsoft.ML;
    using Microsoft.ML.Data;
    using Microsoft.ML.Transforms.TimeSeries;
    
  2. ModelInput sınıfını oluşturun. 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; }
    }
    

    ModelInputSınıfı şu sütunları içerir:

    • Rentaldate: Gözlem tarihi.
    • Yıl: gözlemin kodlanmış yılı (0 = 2011, 1 = 2012).
    • Totalrentals: Bu güne ait toplam Bisiklet randevu sayısı.
  3. ModelOutputYeni oluşturulan sınıfın altında sınıf oluşturun ModelInput .

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

    ModelOutputSınıfı şu sütunları içerir:

    • ForecastedRentals: tahmin edilen dönem için tahmin edilen değerler.
    • Ials Boundrentals: tahmin edilen dönem için öngörülen minimum değerler.
    • Üsteboundrentals: tahmin edilen dönem için öngörülen maksimum değer.

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

  1. Using deyimlerinin altında, verilerinizin konumunu, Bağlantı dizenizi ve eğitilen modelin kaydedileceği yeri 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 MLContext Yolları tanımladıktan sonra aşağıdaki satırı ekleyerek değişkeni yeni bir örneğiyle başlatın.

    MLContext mlContext = new MLContext();
    

    MLContextsı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 genelinde paylaşılabilen yeni bir ML .net ortamı oluşturur. Entity Framework, kavramsal olarak da benzerdir DBContext .

Verileri yükleme

  1. DatabaseLoaderBu tür kayıtları yükleyen oluşturma ModelInput .

    DatabaseLoader loader = mlContext.Data.CreateDatabaseLoader<ModelInput>();
    
  2. Veritabanından verileri yükleyecek 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 olmasını bekler Single . Bu nedenle, tek duyarlıklı kayan noktalı bir değer olan, türünde olmayan veritabanından gelen sayısal değerlerin Real olarak dönüştürülmesi gerekir Real .

    YearVe TotalRental sütunları, veritabanındaki tamsayı türlerdir. CASTYerleşik işlevi kullanarak, her ikisi de ' a dönüştürülür Real .

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

    DatabaseSource dbSource = new DatabaseSource(SqlClientFactory.Instance,
                                    connectionString,
                                    query);
    
  4. Verileri bir öğesine yükleyin IDataView .

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

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

    İlk yılda, Year parametre 1 olarak ayarlanarak yalnızca sütundaki değerler 1 ' den az upperBound olacak şekilde seçilir. Bunun tersine, ikinci yıl için 1 ' den büyük veya eşit değerler lowerBound parametresi 1 olarak ayarlanarak seçilir.

Zaman serisi analizi ardışık düzenini tanımlama

  1. Bir zaman serisi veri kümesindeki değerleri tahmin etmek için Ssaforekılaringestimator 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 İlk yıl ve örnekler için 365 veri noktası alır ya da zaman serisi veri kümesini parametre tarafından belirtilen 30 günlük (aylık) aralıklarına böler seriesLength . Bu örneklerin her biri haftalık veya 7 günlük bir pencere ile çözümlenir. Sonraki dönemler için tahmini değerin ne olduğu belirlenirken, tahminde etmek için önceki yedi gün içinde yer alan değerler kullanılır. Model, parametresiyle tanımlandığı şekilde yedi noktanın geleceğe doğru tahminini yapmak için horizon ayarlanmıştır. Tahmin bilinçli bir tahmin olduğundan her zaman %100 doğru değildir. Bu nedenle, üst ve alt sınırlarla tanımlandığı gibi en iyi ve en kötü durum senaryolarında değer aralığını bilmek iyi bir fikirdir. Bu durumda, alt ve üst sınırların güven düzeyi %95 olarak ayarlanır. Güven düzeyi buna göre artırılabilir veya azaltılabilir. Değer ne kadar yüksekse, istenen güven düzeyini elde etmek için üst ve alt sınırların arasındaki aralık o kadar geniş olur.

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

    SsaForecastingTransformer forecaster = forecastingPipeline.Fit(firstYearData);
    

Modeli değerlendirme

Gelecek yılın verilerini tahmin eder ve gerçek değerlerle karşılaştırarak modelin ne kadar iyi performans sergileyecezini değerlendirin.

  1. Program.cs dosyasının en altında Evaluate 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 ikinci Transform yılın verilerini tahminde bulundurabilirsiniz.

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

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

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

    var metrics = actual.Zip(forecast, (actualValue, forecastValue) => actualValue - forecastValue);
    
  6. Ortalama Mutlak Hata ve Kök Ortalama Hata Karesi Değerlerini hesaparak 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çür. Bu değer 0 ile sonsuz arasında aralıklara sahiptir. 0'a ne kadar yakınsa modelin kalitesi o kadar iyi olur.
    • Kök Ortalama Hata Karesi: Modelde hatayı özetler. Bu değer 0 ile sonsuz arasında aralıklara sahiptir. 0'a ne kadar yakınsa modelin kalitesi o kadar iyi olur.
  7. Ölçümleri konsola çıkış olarak kullanın.

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

    Evaluate(secondYearData, forecaster, mlContext);
    

Modeli kaydetme

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

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

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

    forecastEngine.CheckPoint(mlContext, modelPath);
    

Talebi tahmin etmek için modeli kullanma

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

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

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

    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 çıkışında bir daha deneyin ve konsolda görüntüleniyor.

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

Uygulamayı çalıştırma

  1. Aşağıda yöntemini Checkpoint() çağırma yöntemi Forecast çağrılır.

    Forecast(secondYearData, 7, forecastEngine, mlContext);
    
  2. Uygulamayı çalıştırın. Konsolda aşağıdakine benzer bir çıktı görünmektedir. Daha fazla özetle, çıkış yoğun bir şekilde tamamlandı.

    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 tahmini değerlerin denetimi aşağıdaki ilişkileri gösterir:

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

Tahmin edilen değerler kiralamaların tam sayısını tahmin etmesa da, kaynakların kullanımını iyileştirmeye yönelik bir işlem sağlayan daha dar bir değer aralığı sağlar.

Tebrikler! Bisiklet kiralama talebini tahmin etmek için başarıyla bir zaman serisi makine öğrenmesi modeli tamamladın.

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

Sonraki adımlar