AI時代的網站與手機App建置與開發Part20 - 使用ML.NET進行異常偵測
· 摘要
從一堆資料中找出異常的資料一直是資料分析很重要的課題, 例如生產線需要偵測NG商品, 公司想要找出異常的出貨單, 銀行想找出異常的信用卡交易, 科學家想找出氣溫異常, 金管單位想找出股價急漲/急跌的異常, 超巿想找出營收或利潤異常等等都是異常偵測的應用場合.
在這篇文章中, 我們將要為大家介紹如何使用ML.NET分析商品銷售資料的異常.
· 準備訓練資料
首先請啟動瀏覽器, 瀏覽至Product Sales Data下載商品銷售資料(下載網址: https://www.kaggle.com/datasets/ksabishek/product-sales-data?resource=download).
圖1所示即為下載得到的資料:
這份商品銷售資料的欄位詳細說明如下表:
|
欄位名稱 |
欄位說明 |
|
Date |
商品銷售日期 |
|
QP1 |
商品1的銷售量 |
|
QP2 |
商品2的銷售量 |
|
QP3 |
商品3的銷售量 |
|
QP4 |
商品4的銷售量 |
|
SP1 |
商品1的銷售利潤 |
|
SP2 |
商品2的銷售利潤 |
|
SP3 |
商品3的銷售利潤 |
|
SP4 |
商品4的銷售利潤 |
· 使用ML.NET執行銷售資料的異常偵測
以下會以分析商品銷售資料中的QP1欄位的內容為例, 有興趣的讀者可以自行修改程式以分析其他欄位的資料是否異常.
· 定義描述商品銷售資料的ProductSalesData類別
internal class ProductSalesData
{
[LoadColumn(1)]
public string Date;
[LoadColumn(2)]
public float
QP1;
}
· 定義描述異常偵測結果的ProductSalesPrediction類別
internal class ProductSalesPrediction
{
[VectorType(3)]
public double[]
Prediction { get; set; }
}
· 實作偵測商品銷售資料的異常
private void
btnProductSalesAnpmalyDetect_Click(object sender, RoutedEventArgs e)
{
MLContext mlContext = new MLContext();
// 載入資料
IDataView ProductSales =
mlContext.Data.LoadFromTextFile<ProductSalesData>(
"statsfinal.csv", separatorChar: ',', hasHeader: true);
List<ProductSalesData> data =mlContext.Data.CreateEnumerable<ProductSalesData>
(ProductSales, reuseRowObject: false).ToList();
IDataView dataView =
mlContext.Data.LoadFromEnumerable(data);
PlotSalesChart(data);
DetectSpike(mlContext, 36, dataView);
DetectChangepoint(mlContext, 36, dataView);
}
private void
DetectSpike(MLContext mlContext, int docSize, IDataView productSales)
{
var
iidSpikeEstimator = mlContext.Transforms.DetectIidSpike(outputColumnName:
nameof(ProductSalesPrediction.Prediction), inputColumnName:
nameof(ProductSalesData.QP1), confidence: 95.0,
pvalueHistoryLength: docSize / 4);
ITransformer iidSpikeTransform =
iidSpikeEstimator.Fit(productSales);
IDataView transformedData =
iidSpikeTransform.Transform(productSales);
var predictions = mlContext.Data.CreateEnumerable<ProductSalesPrediction>(
transformedData,
reuseRowObject: false);
Trace.WriteLine("Alert\tScore\tP-Value");
foreach (var p in predictions)
{
var results={p.Prediction[0]}\t{p.Prediction[1]:f2}\t{p.Prediction[2]:F2}";
if (p.Prediction[0] == 1)
{
results += "
<-- Spike detected";
}
Trace.WriteLine(results);
}
}
private void
DetectChangepoint(MLContext mlContext, int docSize,
IDataView
productSales)
{
var
iidChangePointEstimator =
mlContext.Transforms.DetectIidChangePoint(outputColumnName: nameof(ProductSalesPrediction.Prediction), inputColumnName: nameof(ProductSalesData.QP1), confidence: 95.0, changeHistoryLength: docSize / 4);
//訓練
var iidChangePointTransform = iidChangePointEstimator.Fit(productSales);
//取得訓練結果
IDataView transformedData =
iidChangePointTransform.Transform(productSales);
var predictions = mlContext.Data.CreateEnumerable<ProductSalesPrediction>(
transformedData, reuseRowObject: false);
//顯示預測結果
Trace.WriteLine("Alert\tScore\tP-Value\tMartingale value");
foreach (var p in predictions)
{
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";
}
Trace.WriteLine(results);
}
}
private void
PlotSalesChart(List<ProductSalesData> productSales)
{
//建立繪圖模型
var plotModel = new
PlotModel { Title = "Sales Data" };
//建立線形圖需要的序列資料
var lineSeries = new
LineSeries
{
Title = "Sales",
MarkerType = MarkerType.Circle,
ItemsSource = productSales,
Mapping = item =>
{
var data = (ProductSalesData)item;
DateTime date;
if (DateTime.TryParseExact(data.Date,
"dd-MM-yyyy", null,
System.Globalization.DateTimeStyles.None, out date))
{
return new
DataPoint(DateTimeAxis.ToDouble(date), data.QP1);
}
else
{
throw new FormatException(
$"The
input string '{data.Date}'
was not in a correct format.");
}
}
};
//將序列資料加入到繪圖模型
plotModel.Series.Add(lineSeries);
//建立顯示繪圖模型的PlotView檢視
var plotView = new
PlotView
{
Model = plotModel,
};
//顯示PlotView檢視
Content = plotView;
}
上述的程式碼首先會以線形圖的方式顯示欲偵測的商品鋿售資料, 如圖2所示:
圖2: 以線形圖的方式顯示欲偵測的商品鋿售資料
然後分析商品銷售資料是否有短暫的銷售異常, 如圖3所示:
圖3:商品銷售有短暫銷售異常者會標示為1, 並加註<--Spike detected
接下來再分析商品銷售狀況是否有反轉點, 如圖4所示:
圖4: 商品銷售有反轉點者會標示為1, 並加註<--alert is on, predicted changepoint
範例下載:https://github.com/CraigIII/ProductSalesAnomalyDetection.git





留言
張貼留言