using Microsoft.ML;
|
using Microsoft.ML.Transforms.TimeSeries;
|
using static Yw.Application.ConnectHelper;
|
|
namespace Yw.Service
|
{
|
/// <summary>
|
/// 单谱分析(.Net)
|
/// </summary>
|
public class SSAPredictHelper
|
{
|
/// <summary>
|
/// 样本周期数量
|
/// </summary>
|
public const int Win_Size = 12;
|
|
/// <summary>
|
/// 数据样本间隔
|
/// </summary>
|
public const int Series_Length = 288;
|
|
/// <summary>
|
/// 上下限的可信度.预测属于合理猜测,不总是完全准确
|
/// </summary>
|
public const float Confidence_Level = 0.95f;
|
|
/// <summary>
|
/// 输入
|
/// </summary>
|
public class SSAInput
|
{
|
|
/// <summary>
|
/// 时间
|
/// </summary>
|
public DateTime Time { get; set; }
|
|
/// <summary>
|
/// 值
|
/// </summary>
|
public float Value { get; set; }
|
}
|
|
/// <summary>
|
/// 输出
|
/// </summary>
|
public class SSAOutput
|
{
|
/// <summary>
|
///
|
/// </summary>
|
public float[] Predict { get; set; }
|
|
/// <summary>
|
///
|
/// </summary>
|
public float[] Lower { get; set; }
|
|
/// <summary>
|
///
|
/// </summary>
|
public float[] Upper { get; set; }
|
}
|
|
/// <summary>
|
/// 预测
|
/// </summary>
|
/// <param name="data">样本数据</param>
|
/// <param name="time_step">数据步长(秒)</param>
|
/// <param name="win_size">样本周期数量</param>
|
/// <param name="series_length">数据样本间隔</param>
|
/// <param name="confidence_level">上下限的可信度</param>
|
/// <param name="fulture">预测条数</param>
|
/// <returns></returns>
|
public List<TotalOneDay> Predict(List<Tuple<DateTime, double>> data, int time_step, int win_size, int series_length, float confidence_level, int fulture)
|
{
|
#region 基础验证
|
|
if (data == null || data.Count < win_size)
|
{
|
return null;
|
}
|
if (time_step < 1)
|
{
|
return null;
|
}
|
if (win_size < 1)
|
{
|
return null;
|
}
|
if (series_length < 1 || series_length <= win_size)
|
{
|
return null;
|
}
|
if (confidence_level < 0)
|
{
|
confidence_level = 0;
|
}
|
if (confidence_level > 1)
|
{
|
confidence_level = 1;
|
}
|
if (fulture < 1)
|
{
|
return null;
|
}
|
|
#endregion
|
|
var sampleData = data.Select(x => new SSAInput() { Time = x.Item1, Value = (float)x.Item2 }).ToList();//样本数据
|
var mlContext = new MLContext();//创建
|
IDataView dataView = mlContext.Data.LoadFromEnumerable<SSAInput>(sampleData);//加载数据
|
|
var forecastingPipeline = mlContext.Forecasting.ForecastBySsa(//定义训练通道
|
outputColumnName: "Predict",
|
inputColumnName: "Value",
|
windowSize: win_size,
|
seriesLength: series_length,
|
trainSize: sampleData.Count,
|
horizon: fulture,
|
confidenceLevel: confidence_level,
|
confidenceLowerBoundColumn: "Lower",
|
confidenceUpperBoundColumn: "Upper");
|
|
SsaForecastingTransformer forecaster = forecastingPipeline.Fit(dataView); //训练
|
|
var forecastEngine = forecaster.CreateTimeSeriesEngine<SSAInput, SSAOutput>(mlContext);//预测
|
var forecast = forecastEngine.Predict();
|
if (forecast.Predict == null || forecast.Predict.Length < 1)
|
{
|
return null;
|
}
|
|
//构造预测记录
|
var beginTime = sampleData.Last().Time;
|
var vmList = new List<TotalOneDay>();
|
for (int i = 0; i < forecast.Predict.Length; i++)
|
{
|
var vm = new TotalOneDay()
|
{
|
DateTime = beginTime.AddSeconds((i + 1) * time_step),
|
Total = forecast.Predict[i]
|
};
|
vmList.Add(vm);
|
}
|
|
return vmList;
|
|
|
}
|
|
|
/* public class TotalOneDay
|
{
|
public DateTime DateTime { get; set; }
|
public double Total { get; set; }
|
}*/
|
|
|
}
|
}
|