文章目录
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
)
-
模型定义:
// 使用IID Spike detection方法创建转换器 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); // 输出结果,标记异常 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
)
-
模型定义:
// 使用IID Change Point detection方法创建转换器 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); // 输出结果,标记变化点 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的机器学习库,我们能够有效地检测数据中的临时峰值和持续性变化。这种方法不仅适用于销售数据分析,还可以扩展到其他时间序列数据的异常检测和趋势分析中。