tangxu
2024-04-30 866efc04569009746d28ed1c434e0126ad00ad09
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
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; }
        }*/
 
 
    }
}