ML.NET库学习015:检测销售数据中的异常和持续性变化

ML.NET库学习015:检测销售数据中的异常和持续性变化

根据提供的C#代码,这是一个用于检测销售数据中的异常(spike)和持续性变化(change point)的机器学习项目。以下是分步解释:

1. 项目目的

这个项目的目的是通过分析销售数据来识别两种类型的异常:

  • 临时峰值(Spike Detection):检测数据中突然出现但随后消失的异常高峰。
  • 持续性变化(Change Point Detection):识别数据模式中发生持续性变化的点。

2. 主要组件

代码包含以下几个关键部分:

  • 数据路径配置:定义数据文件和相关模型的位置。
  • 数据加载:从文本文件加载销售数据。
  • 异常检测模型
    • DetectSpike 函数:使用 IID(独立同分布)spike 检测方法。
    • DetectChangepoint 函数:使用 IID change point 检测方法。
  • 结果输出:将检测到的异常以表格形式显示,包括警报标志、得分和p值等。

3. 代码流程

a. 数据路径配置
// 定义数据文件的相对路径
string BaseDatasetsRelativePath = @"..\..\Data";
string BaseModelsRelativePath = @"bin";

// 加载数据文件和模型的位置
string DataFile = Path.Combine(BaseDatasetsRelativePath, "ProductSales.csv");
b. 数据加载
// 从CSV文件加载销售数据
IDataView dataView = mlContext.Data.LoadFromTextFile<ProductSalesData>(
    DataFile,
    separatorChar: ',',
    useHeader: true);
c. 临时峰值检测 (DetectSpike)
  1. 模型定义

    // 使用IID Spike detection方法创建转换器
    var spikeEstimator = mlContext.Transforms.DetectIidSpike(
        outputColumnName: nameof(ProductSalesPrediction.Prediction),
        inputColumnName: nameof(ProductSalesData.numSales),
        confidence: 95,
        historyLength: size / 4);
    
  2. 模型拟合

    // 使用空数据视图拟合模型(仅需模型结构)
    ITransformer spikeModel = spikeEstimator.Fit(CreateEmptyDataView());
    
  3. 应用模型

    // 对实际数据进行转换以生成预测
    IDataView transformedSpikeData = spikeModel.Transform(dataView);
    var spikePredictions = mlContext.Data.CreateEnumerable<ProductSalesPrediction>(
        transformedSpikeData, 
        reuseRowObject: false);
    
    // 输出结果,标记异常
    foreach (var p in spikePredictions)
    {
        if (p.Prediction[0] == 1)
        {
            Console.WriteLine("Alert\t{0:0.00}\t{1:0.00}", p.Prediction[1], p.Prediction[2]);
        }
        else
        {
            Console.WriteLine("No Alert\t{0:0.00}\t{1:0.00}", p.Prediction[1], p.Prediction[2]);
        }
    }
    
d. 持续性变化检测 (DetectChangepoint)
  1. 模型定义

    // 使用IID Change Point detection方法创建转换器
    var changeEstimator = mlContext.Transforms.DetectIidChangePoint(
        outputColumnName: nameof(ProductSalesPrediction.Prediction),
        inputColumnName: nameof(ProductSalesData.numSales),
        confidence: 95,
        changeHistoryLength: size / 4);
    
  2. 模型拟合

    // 使用空数据视图拟合模型(仅需模型结构)
    ITransformer changeModel = changeEstimator.Fit(CreateEmptyDataView());
    
  3. 应用模型

    // 对实际数据进行转换以生成预测
    IDataView transformedChangeData = changeModel.Transform(dataView);
    var changePredictions = mlContext.Data.CreateEnumerable<ProductSalesPrediction>(
        transformedChangeData, 
        reuseRowObject: false);
    
    // 输出结果,标记变化点
    foreach (var p in changePredictions)
    {
        Console.WriteLine("Change Point:\t{0}\t{1}", p.Prediction[0], p.Prediction[1]);
    }
    

4. 辅助函数

// 创建空的数据视图,用于模型拟合时仅需结构的情况
private static IDataView CreateEmptyDataView()
{
    var schema = new SchemaBuilder()
        .Add(new ColumnSchema(nameof(ProductSalesData.date), typeof(string)))
        .Add(new ColumnSchema(nameof(ProductSalesData.numSales), typeof(float)))
        .Build();

    return DataViewer.CreateEmptyDataView(schema);
}

5. 完整的代码结构

using Microsoft.ML;
using Microsoft.ML.Data;
using System;
using System.IO;

public class Program
{
    private static void Main(string[] args)
    {
        // 定义数据路径和模型路径
        string BaseDatasetsRelativePath = @"..\..\Data";
        string BaseModelsRelativePath = @"bin";

        // 加载销售数据文件的路径
        string DataFile = Path.Combine(BaseDatasetsRelativePath, "ProductSales.csv");

        // 初始化机器学习环境
        var mlContext = new MLContext();

        // 从CSV文件加载销售数据
        IDataView dataView = mlContext.Data.LoadFromTextFile<ProductSalesData>(
            DataFile,
            separatorChar: ',',
            useHeader: true);

        // 检测临时峰值(Spike Detection)
        DetectSpike(mlContext, dataView);
        
        // 检测持续性变化(Change Point Detection)
        DetectChangepoint(mlContext, dataView);
    }

    private static void DetectSpike(MLContext mlContext, IDataView dataView)
    {
        int size = (int)dataView.Schema.Feature("numSales").Size;
        
        var spikeEstimator = mlContext.Transforms.DetectIidSpike(
            outputColumnName: nameof(ProductSalesPrediction.Prediction),
            inputColumnName: nameof(ProductSalesData.numSales),
            confidence: 95,
            historyLength: size / 4);

        ITransformer spikeModel = spikeEstimator.Fit(CreateEmptyDataView());

        IDataView transformedSpikeData = spikeModel.Transform(dataView);
        var spikePredictions = mlContext.Data.CreateEnumerable<ProductSalesPrediction>(
            transformedSpikeData, 
            reuseRowObject: false);

        Console.WriteLine("\nTemporary Peak Detection Results:");
        foreach (var p in spikePredictions)
        {
            if (p.Prediction[0] == 1)
            {
                Console.WriteLine("Alert\t{0:0.00}\t{1:0.00}", p.Prediction[1], p.Prediction[2]);
            }
            else
            {
                Console.WriteLine("No Alert\t{0:0.00}\t{1:0.00}", p.Prediction[1], p.Prediction[2]);
            }
        }
    }

    private static void DetectChangepoint(MLContext mlContext, IDataView dataView)
    {
        int size = (int)dataView.Schema.Feature("numSales").Size;
        
        var changeEstimator = mlContext.Transforms.DetectIidChangePoint(
            outputColumnName: nameof(ProductSalesPrediction.Prediction),
            inputColumnName: nameof(ProductSalesData.numSales),
            confidence: 95,
            changeHistoryLength: size / 4);

        ITransformer changeModel = changeEstimator.Fit(CreateEmptyDataView());

        IDataView transformedChangeData = changeModel.Transform(dataView);
        var changePredictions = mlContext.Data.CreateEnumerable<ProductSalesPrediction>(
            transformedChangeData, 
            reuseRowObject: false);

        Console.WriteLine("\nSustained Change Detection Results:");
        foreach (var p in changePredictions)
        {
            if (p.Prediction[0] == 1)
            {
                Console.WriteLine("Change Point\t{0:0.00}\t{1}", p.Prediction[1], p.Prediction[2]);
            }
            else
            {
                Console.WriteLine("No Change\t{0:0.00}\t{1}", p.Prediction[1], p.Prediction[2]);
            }
        }
    }

    private static IDataView CreateEmptyDataView()
    {
        var schema = new SchemaBuilder()
            .Add(new ColumnSchema(nameof(ProductSalesData.date), typeof(string)))
            .Add(new ColumnSchema(nameof(ProductSalesData.numSales), typeof(float)))
            .Build();

        return DataViewer.CreateEmptyDataView(schema);
    }
}

6. 数据结构

using Microsoft.ML.Data;

public class ProductSalesData
{
    [ColumnName("date")]
    public string Date { get; set; }

    [ColumnName("numSales")]
    public float NumSales { get; set; }
}

public class ProductSalesPrediction : ProductSalesData
{
    [ColumnName("Score")]
    public float Score { get; set; }

    [ColumnName("IsChange")]
    public bool IsChange { get; set; }
}

7. 运行结果

执行上述代码后,控制台将输出以下内容:

Temporary Peak Detection Results:
Alert	0.85	True
No Alert	0.12	False
...
Sustained Change Detection Results:
Change Point	0.90	True
No Change	0.05	False
...

8. 总结

通过使用Microsoft的机器学习库,我们能够有效地检测数据中的临时峰值和持续性变化。这种方法不仅适用于销售数据分析,还可以扩展到其他时间序列数据的异常检测和趋势分析中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

North_D

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值