Бөлісу құралы:


Руководство. Обнаружение аномалий в продажах продуктов с помощью ML.NET

Узнайте, как создать приложение обнаружения аномалий для данных о продажах продуктов. В этом руководстве создается консольное приложение .NET с помощью C# в Visual Studio.

В этом руководстве вы узнаете, как:

  • Загрузка данных
  • Создайте трансформацию для обнаружения аномалий всплесков
  • Обнаружение аномалий пиков с помощью преобразования
  • Создание преобразования для обнаружения аномалий точки изменения
  • Обнаружение аномалий точки изменения с помощью преобразования

Исходный код для этого руководства можно найти в репозитории dotnet/samples .

Предпосылки

Замечание

Формат product-sales.csv данных основан на наборе данных "Продажи шампуней за три года", первоначально созданном из DataMarket и предоставленном библиотекой данных временных рядов (TSDL), созданной Робом Хайндманом. "Набор данных «Продажи шампуня в течение трехлетнего периода» лицензирован по лицензии DataMarket Default Open."

Создайте консольное приложение

  1. Создайте консольное приложение C# с именем ProductSalesAnomalyDetection. Нажмите кнопку Далее.

  2. Выберите .NET 8 в качестве платформы для использования. Нажмите кнопку Создать.

  3. Создайте каталог с именем Data в проекте, чтобы сохранить файлы набора данных.

  4. Установите пакет NuGet Microsoft.ML:

    Замечание

    В этом примере используется последняя стабильная версия упомянутых пакетов NuGet, если не указано иное.

    В обозревателе решений щелкните проект правой кнопкой мыши и выберите пункт "Управление пакетами NuGet". Выберите "nuget.org" в качестве источника пакета, перейдите на вкладку "Обзор", найдите Microsoft.ML и выберите "Установить". Нажмите кнопку "ОК " в диалоговом окне "Предварительные изменения" , а затем нажмите кнопку "Принять" в диалоговом окне принятия лицензий, если вы согласны с условиями лицензии для перечисленных пакетов. Повторите эти действия для Microsoft.ML.TimeSeries.

  5. Добавьте следующие using директивы в верхней части файла Program.cs :

    using Microsoft.ML;
    using ProductSalesAnomalyDetection;
    

Скачайте свои данные

  1. Скачайте набор данных и сохраните его в ранее созданной папке данных :

    • Щелкните правой кнопкой мыши product-sales.csv и выберите "Сохранить ссылку (или цель) как..."

      Убедитесь, что файл *.csv сохранен в папке данных или после сохранения в другом месте, переместите файл *.csv в папку данных .

  2. В обозревателе решений щелкните правой кнопкой мыши файл *.csv и выберите "Свойства". В разделе "Дополнительно" измените значение Копировать в выходной каталог на Копировать, если новее.

Следующая таблица — это предварительная версия данных из файла *.csv:

Месяц ProductSales
1-январь 271
2-январь 150.9
..... .....
1-февраль 199.3
..... .....

Создание классов и определение путей

Затем определите структуры данных входных и прогнозирующих классов.

Добавьте новый класс в проект:

  1. В обозревателе решений щелкните проект правой кнопкой мыши и выберите пункт "Добавить > новый элемент".

  2. В диалоговом окне "Добавление нового элемента" выберите класс и измените поле "Имя " на ProductSalesData.cs. Затем нажмите кнопку "Добавить".

    Файл ProductSalesData.cs откроется в редакторе кода.

  3. Добавьте следующую using директиву в начало ProductSalesData.cs:

    using Microsoft.ML.Data;
    
  4. Удалите существующее определение класса и добавьте следующий код, имеющий два класса ProductSalesData и ProductSalesPredictionфайл ProductSalesData.cs :

    public class ProductSalesData
    {
        [LoadColumn(0)]
        public string? Month;
    
        [LoadColumn(1)]
        public float numSales;
    }
    
    public class ProductSalesPrediction
    {
        //vector to hold alert,score,p-value values
        [VectorType(3)]
        public double[]? Prediction { get; set; }
    }
    

    ProductSalesData указывает входной класс данных. Атрибут LoadColumn указывает, какие столбцы (по индексу столбца) в наборе данных должны быть загружены.

    ProductSalesPrediction задает класс данных прогнозирования. Для обнаружения аномалий прогноз состоит из оповещения, указывающего, существует ли аномалия, необработанный показатель и p-значение. Чем ближе p-значение равно 0, тем более вероятно, произошла аномалия.

  5. Создайте два глобальных поля для хранения недавно скачаемого пути к файлу набора данных и сохраненного пути к файлу модели:

    • _dataPath имеет путь к набору данных, используемому для обучения модели.
    • _docsize содержит количество записей в файле набора данных. Вы будете использовать _docSize для вычисления pvalueHistoryLength.
  6. Добавьте следующий код в строку справа от using директив, чтобы указать эти пути:

    string _dataPath = Path.Combine(Environment.CurrentDirectory, "Data", "product-sales.csv");
    //assign the Number of records in dataset file to constant variable
    const int _docsize = 36;
    

Инициализация переменных

  1. Замените Console.WriteLine("Hello World!") строку следующим кодом, чтобы объявить и инициализировать mlContext переменную:

    MLContext mlContext = new MLContext();
    

    Класс MLContext — это отправная точка для всех операций ML.NET, и инициализация mlContext создает новую среду ML.NET, которую можно совместно использовать для объектов рабочего процесса создания модели. Это концептуально похоже на DBContext в Entity Framework.

Загрузка данных

Данные в ML.NET представлены в виде интерфейса IDataView. IDataView — это гибкий, эффективный способ описания табличных данных (числовых и текстовых данных). Данные можно загрузить из текстового файла или из других источников (например, базы данных SQL или файлов журналов) в IDataView объект.

  1. Добавьте следующий код после создания переменной mlContext :

    IDataView dataView = mlContext.Data.LoadFromTextFile<ProductSalesData>(path: _dataPath, hasHeader: true, separatorChar: ',');
    

    LoadFromTextFile() определяет схему данных и считывает его в файле. Он принимает переменные пути к данным и возвращает значение IDataView.

Обнаружение аномалий временных рядов

Флаги обнаружения аномалий непредвиденного или необычного события или поведения. Он дает подсказки, где искать проблемы и помогает ответить на вопрос "Это странно?".

Пример обнаружения аномалий «Это странно».

Обнаружение аномалий — это процесс обнаружения вылитых данных временных рядов; указывает на заданный временный ряд входных данных, где поведение не является ожидаемым или "странным".

Обнаружение аномалий может быть полезно во многих отношениях. Например:

Если у вас есть автомобиль, вам может захотеться узнать: нормально ли показывает датчик уровня масла, или у меня утечка? Если вы отслеживаете потребление электроэнергии, вы хотите знать: Есть ли сбой?

Существует два типа аномалий временных рядов, которые можно обнаружить:

  • Пики указывают на временные всплески аномального поведения в системе.

  • Точки изменения указывают на начало постоянных изменений с течением времени в системе.

В ML.NET алгоритмы обнаружения выбросов IID или точек изменения IID подходят для независимых и одинаково распределенных наборов данных. Предполагается, что входные данные представляют собой последовательность точек данных, которые независимо отбираются из одного стационарного распределения.

В отличие от моделей в других руководствах, детектор аномалий временных рядов осуществляет преобразования непосредственно на входных данных. Метод IEstimator.Fit() не нуждается в обучающих данных для создания преобразования. Однако для нее требуется схема данных, которая предоставляется представлением данных, созданным из пустого ProductSalesDataсписка.

Вы проанализируете одни и те же данные о продажах продуктов, чтобы обнаружить пики и точки изменения. Процесс построения и обучения модели совпадает с обнаружением пиковых точек и обнаружением точек изменения; Основное отличие — это конкретный алгоритм обнаружения, используемый.

Обнаружение пиков

Цель обнаружения пиков заключается в выявлении внезапных временных всплесков, которые значительно отличаются от большинства значений данных временных рядов. Важно своевременно обнаружить эти подозрительные редкие элементы, события или наблюдения, чтобы свести их к минимуму. Следующий подход можно использовать для обнаружения различных аномалий, таких как сбои, кибератаки или вирусное веб-содержимое. На следующем рисунке показан пример пиков в наборе данных временных рядов:

Снимок экрана, на котором показаны два обнаружения пиков.

Добавление метода CreateEmptyDataView()

Добавьте следующий метод Program.cs:

IDataView CreateEmptyDataView(MLContext mlContext) {
    // Create empty DataView. We just need the schema to call Fit() for the time series transforms
    IEnumerable<ProductSalesData> enumerableData = new List<ProductSalesData>();
    return mlContext.Data.LoadFromEnumerable(enumerableData);
}

Создает CreateEmptyDataView() пустой объект представления данных с правильной схемой, которая будет использоваться в качестве входных данных метода IEstimator.Fit() .

Создание метода DetectSpike()

Метод DetectSpike():

  • Создает преобразование из оценщика.
  • Обнаруживает пики на основе исторических данных о продажах.
  • Отображает результаты.
  1. DetectSpike() Создайте метод в нижней части файла Program.cs с помощью следующего кода:

    DetectSpike(MLContext mlContext, int docSize, IDataView productSales)
    {
    
    }
    
  2. Используйте метод IidSpikeEstimator для обучения модели для обнаружения пиков. Добавьте его в DetectSpike() метод со следующим кодом:

    var iidSpikeEstimator = mlContext.Transforms.DetectIidSpike(outputColumnName: nameof(ProductSalesPrediction.Prediction), inputColumnName: nameof(ProductSalesData.numSales), confidence: 95d, pvalueHistoryLength: docSize / 4);
    
  3. Создайте преобразование обнаружения пиков, добавив следующую строку кода в DetectSpike() методе:

    Подсказка

    confidence И pvalueHistoryLength параметры влияют на обнаружение пиков. confidence определяет, насколько чувствительна модель к пикам. Чем ниже достоверность, тем более вероятно, что алгоритм будет обнаруживать "меньшие" пики. Параметр pvalueHistoryLength определяет количество точек данных в скользящем окне. Значение этого параметра обычно является процентом всего набора данных. Чем ниже pvalueHistoryLength, тем быстрее модель забывает предыдущие большие пики.

    ITransformer iidSpikeTransform = iidSpikeEstimator.Fit(CreateEmptyDataView(mlContext));
    
  4. Добавьте следующую строку кода для преобразования productSales данных в следующую строку метода DetectSpike() :

    IDataView transformedData = iidSpikeTransform.Transform(productSales);
    

    Предыдущий код использует метод Transform() для прогнозирования для нескольких входных строк набора данных.

  5. Преобразуйте объект transformedData в строго типизированный IEnumerable для упрощения отображения с помощью метода CreateEnumerable() со следующим кодом:

    var predictions = mlContext.Data.CreateEnumerable<ProductSalesPrediction>(transformedData, reuseRowObject: false);
    
  6. Создайте строку заголовка отображения с помощью следующего Console.WriteLine() кода:

    Console.WriteLine("Alert\tScore\tP-Value");
    

    В результатах обнаружения пиков вы увидите следующие сведения:

    • Alert указывает оповещение о пике для заданной точки данных.
    • Score ProductSales— значение заданной точки данных в наборе данных.
    • P-Value "P" означает вероятность. Чем ближе p-значение равно 0, тем более вероятно, что точка данных является аномалией.
  7. Используйте следующий код, чтобы выполнить итерацию predictionsIEnumerable и отобразить результаты:

    foreach (var p in predictions)
    {
        if (p.Prediction is not null)
        {
            var results = $"{p.Prediction[0]}\t{p.Prediction[1]:f2}\t{p.Prediction[2]:F2}";
    
            if (p.Prediction[0] == 1)
            {
                results += " <-- Spike detected";
            }
    
            Console.WriteLine(results);
        }
    }
    Console.WriteLine("");
    
  8. Добавьте вызов DetectSpike() к методу под вызовом LoadFromTextFile() метода:

    DetectSpike(mlContext, _docsize, dataView);
    

Результаты обнаружения пиков

Ваши результаты должны быть похожи на следующие. Во время обработки отображаются сообщения. Вы можете видеть предупреждения или обрабатывать сообщения. Некоторые сообщения были удалены из следующих результатов для ясности.

Detect temporary changes in pattern
=============== Training the model ===============
=============== End of training process ===============
Alert   Score   P-Value
0       271.00  0.50
0       150.90  0.00
0       188.10  0.41
0       124.30  0.13
0       185.30  0.47
0       173.50  0.47
0       236.80  0.19
0       229.50  0.27
0       197.80  0.48
0       127.90  0.13
1       341.50  0.00 <-- Spike detected
0       190.90  0.48
0       199.30  0.48
0       154.50  0.24
0       215.10  0.42
0       278.30  0.19
0       196.40  0.43
0       292.00  0.17
0       231.00  0.45
0       308.60  0.18
0       294.90  0.19
1       426.60  0.00 <-- Spike detected
0       269.50  0.47
0       347.30  0.21
0       344.70  0.27
0       445.40  0.06
0       320.90  0.49
0       444.30  0.12
0       406.30  0.29
0       442.40  0.21
1       580.50  0.00 <-- Spike detected
0       412.60  0.45
1       687.00  0.01 <-- Spike detected
0       480.30  0.40
0       586.30  0.20
0       651.90  0.14

Обнаружение точек изменения

Change points представляют собой постоянные изменения в распределении значений потоков событий временных рядов, таких как изменения уровня и тенденции. Эти постоянные изменения длились гораздо дольше, чем spikes и могут указывать на катастрофические события. Change points обычно не видны невооруженным глазом, но их можно обнаружить в ваших данных, используя подобные подходы, как в следующем методе. На следующем рисунке показан пример обнаружения точки изменения.

Снимок экрана: обнаружение точки изменения.

Создание метода DetectChangepoint()

Метод DetectChangepoint() выполняет следующие задачи:

  • Создает преобразование из оценщика.
  • Обнаруживает точки изменения на основе исторических данных о продажах.
  • Отображает результаты.
  1. DetectChangepoint() Создайте метод сразу после объявления метода с помощью следующего DetectSpike() кода:

    void DetectChangepoint(MLContext mlContext, int docSize, IDataView productSales)
    {
    
    }
    
  2. Создайте в методе DetectChangepoint() со следующим кодом:

    var iidChangePointEstimator = mlContext.Transforms.DetectIidChangePoint(outputColumnName: nameof(ProductSalesPrediction.Prediction), inputColumnName: nameof(ProductSalesData.numSales), confidence: 95d, changeHistoryLength: docSize / 4);
    
  3. Как и ранее, создайте преобразование из оценщика, добавив следующую строку кода в DetectChangePoint() метод:

    Подсказка

    Обнаружение точек изменений происходит с небольшой задержкой, так как модель должна убедиться, что текущее отклонение является постоянным изменением, а не только некоторыми случайными пиками перед созданием оповещения. Сумма этой задержки равна параметру changeHistoryLength . Увеличив значение этого параметра, оповещения об обнаружении изменений при более постоянных изменениях, но компромисс будет более длительным.

    var iidChangePointTransform = iidChangePointEstimator.Fit(CreateEmptyDataView(mlContext));
    
  4. Transform() Используйте метод для преобразования данных, добавив следующий код DetectChangePoint()в:

    IDataView transformedData = iidChangePointTransform.Transform(productSales);
    
  5. Как и ранее, преобразуйте приложение transformedData в строго типизированный IEnumerable для упрощения отображения с помощью CreateEnumerable()метода со следующим кодом:

    var predictions = mlContext.Data.CreateEnumerable<ProductSalesPrediction>(transformedData, reuseRowObject: false);
    
  6. Создайте заголовок отображения с помощью следующего кода в следующей строке метода DetectChangePoint().

    Console.WriteLine("Alert\tScore\tP-Value\tMartingale value");
    

    В результатах обнаружения точек изменения отображаются следующие сведения:

    • Alert указывает оповещение о точке изменения для заданного значения данных.
    • Score ProductSales— значение заданной точки данных в наборе данных.
    • P-Value "P" означает вероятность. Чем ближе P-значение равно 0, тем более вероятно, что точка данных является аномалией.
    • Martingale value используется для определения того, как "странная" точка данных основана на последовательности P-значений.
  7. Выполните итерацию predictionsIEnumerable и отображение результатов с помощью следующего кода:

    foreach (var p in predictions)
    {
        if (p.Prediction is not null)
        {
            var results = $"{p.Prediction[0]}\t{p.Prediction[1]:f2}\t{p.Prediction[2]:F2}\t{p.Prediction[3]:F2}";
    
            if (p.Prediction[0] == 1)
            {
                results += " <-- alert is on, predicted changepoint";
            }
            Console.WriteLine(results);
        }
    }
    Console.WriteLine("");
    
  8. Добавьте следующий вызов метода DetectChangepoint() после вызова метода DetectSpike().

    DetectChangepoint(mlContext, _docsize, dataView);
    

Результаты обнаружения точек изменения

Ваши результаты должны быть похожи на следующие. Во время обработки отображаются сообщения. Вы можете видеть предупреждения или обрабатывать сообщения. Некоторые сообщения были удалены из следующих результатов для ясности.

Detect Persistent changes in pattern
=============== Training the model Using Change Point Detection Algorithm===============
=============== End of training process ===============
Alert   Score   P-Value Martingale value
0       271.00  0.50    0.00
0       150.90  0.00    2.33
0       188.10  0.41    2.80
0       124.30  0.13    9.16
0       185.30  0.47    9.77
0       173.50  0.47    10.41
0       236.80  0.19    24.46
0       229.50  0.27    42.38
1       197.80  0.48    44.23 <-- alert is on, predicted changepoint
0       127.90  0.13    145.25
0       341.50  0.00    0.01
0       190.90  0.48    0.01
0       199.30  0.48    0.00
0       154.50  0.24    0.00
0       215.10  0.42    0.00
0       278.30  0.19    0.00
0       196.40  0.43    0.00
0       292.00  0.17    0.01
0       231.00  0.45    0.00
0       308.60  0.18    0.00
0       294.90  0.19    0.00
0       426.60  0.00    0.00
0       269.50  0.47    0.00
0       347.30  0.21    0.00
0       344.70  0.27    0.00
0       445.40  0.06    0.02
0       320.90  0.49    0.01
0       444.30  0.12    0.02
0       406.30  0.29    0.01
0       442.40  0.21    0.01
0       580.50  0.00    0.01
0       412.60  0.45    0.01
0       687.00  0.01    0.12
0       480.30  0.40    0.08
0       586.30  0.20    0.03
0       651.90  0.14    0.09

Поздравляю! Теперь вы успешно создали модели машинного обучения для обнаружения пиков и аномалий точки изменения в данных о продажах.

Исходный код для этого руководства можно найти в репозитории dotnet/samples .

Из этого руководства вы узнали, как:

  • Загрузка данных
  • Обучение модели для обнаружения пиковых аномалий
  • Обнаружение аномалий пиков с помощью обученной модели
  • Обучение модели для обнаружения аномалий точки изменения
  • Обнаружение аномалий точки изменения с помощью обученного режима

Дальнейшие шаги

Ознакомьтесь с примерами в репозитории GitHub по машинному обучению, чтобы изучить образец обнаружения аномалий в данных о сезонности.