Projekt

Obecné

Profil

Stáhnout (9.32 KB) Statistiky
| Větev: | Tag: | Revize:
1
//
2
// Author: Roman Kalivoda
3
//
4

    
5
using System;
6
using System.Collections.Generic;
7
using ServerApp.Connection.XMLProtocolHandler;
8
using ServerApp.Parser.Parsers;
9
using Newtonsoft.Json;
10
using ServerApp.WeatherPredictionParser;
11
using ServerApp.Parser.OutputInfo;
12
using log4net;
13
using System.IO;
14
using System.Text.RegularExpressions;
15
using System.Linq;
16

    
17
namespace ServerApp.Predictor
18
{
19
    /// <summary>
20
    /// Implentation of the <c>IPredicitionController</c> interface.
21
    /// </summary>
22
    public class PredictionController : IPredictionController
23
    {
24
        private static readonly ILog _log = LogManager.GetLogger(typeof(PredictionController));
25

    
26
        /// <summary>
27
        /// ID of the current predictor instances.
28
        /// </summary>
29
        private string PredictorID;
30

    
31
        /// <summary>
32
        /// Configuration of the <c>Predictor</c>
33
        /// </summary>
34
        public PredictorConfiguration Configuration { get; set; }
35

    
36
        /// <summary>
37
        /// Names of the files used to train the current predictor instances.
38
        /// </summary>
39
        private IEnumerable<string> DataFilenames;
40

    
41
        /// <summary>
42
        /// Current predictor instances
43
        /// </summary>
44
        private IPredictor[] Predictors;
45

    
46
        /// <summary>
47
        /// A reference to a data parser.
48
        /// </summary>
49
        private IDataParser DataParser;
50

    
51
        /// <summary>
52
        /// A feature extractor instance.
53
        /// </summary>
54
        private FeatureExtractor FeatureExtractor;
55

    
56
        /// <summary>
57
        /// A weather prediction parser service
58
        /// </summary>
59
        private IJsonParser weatherService;
60

    
61
        /// <summary>
62
        /// Instantiates new prediction controller.
63
        /// </summary>
64
        /// <param name="dataParser">A data parser used to get training data.</param>
65
        public PredictionController(IJsonParser weatherService, IDataParser dataParser, string pathToConfig = null)
66
        {
67
            // TODO look for existing predictors
68
            _log.Info("Constructing a new PredictionController instance.");
69
            this.weatherService = weatherService;
70
            // load config or get the default one
71
            if (pathToConfig is null)
72
            {
73
                pathToConfig = PredictorConfiguration.DEFAULT_CONFIG_PATH;
74
            }
75
            try
76
            {
77
                string json = File.ReadAllText(pathToConfig);
78
                this.Configuration = JsonConvert.DeserializeObject<PredictorConfiguration>(json);
79
            }
80
            catch (System.IO.IOException e)
81
            {
82
                Console.WriteLine("Warning: could not find a configuration file, creating a new one:");
83
                Console.WriteLine(e.Message.PadLeft(4));
84
                this.Configuration = PredictorConfiguration.GetDefaultConfig();
85
            }
86

    
87
            this.DataParser = dataParser;
88
            this.Predictors = new IPredictor[this.Configuration.PredictorCount];
89
            this.FeatureExtractor = new FeatureExtractor(this.DataParser, this.Configuration);
90
            this.DataFilenames = dataParser.WeatherDataUsed.Concat(dataParser.ActivityDataUsed);
91
            this.PredictorID = DateTime.Now.ToString();
92

    
93
            for (int i = 0; i < this.Configuration.PredictorCount; i++)
94
            {
95
                Predictors[i] = new NaiveBayesClassifier();
96
            }
97
            PredictorConfiguration.SaveConfig(PredictorConfiguration.DEFAULT_CONFIG_PATH, Configuration);
98
        }
99
        public List<string> GetPredictors()
100
        {
101
            return new List<string>(this.Configuration.BuildingsToAreas.Keys);
102
        }
103

    
104
        public void Load(string predictorID)
105
        {
106
            DirectoryInfo di = new DirectoryInfo(Configuration.ModelDataPath);
107
            FileInfo[] files = di.GetFiles($"{predictorID}_*.zip");
108
            IPredictor[] newPredictors = new IPredictor[this.Configuration.PredictorCount];
109
            for (int i = 0; i < this.Configuration.PredictorCount; i++)
110
            {
111
                newPredictors[i] = new NaiveBayesClassifier(Array.Find(files, f => Regex.IsMatch(f.Name, $"{predictorID}_{i}.zip")).FullName);
112
            }
113
            this.Predictors = newPredictors;
114
            files = di.GetFiles($"{predictorID}.txt");
115
            this.DataFilenames = File.ReadLines(files[0].FullName);
116
            this.PredictorID = predictorID;
117
        }
118

    
119
        public void Rollback()
120
        {
121

    
122
        }
123

    
124
        public Response Predict(Request request)
125
        {
126
            _log.Info($"Received a prediction request: endDate={request.useEndDate}, weather={request.useWeather}");
127
            DateTime start = new DateTime(year: request.start.year, month: request.start.month, day: request.start.day, hour: request.start.hour, minute: 0, second: 0);
128
            List<Prediction> predictions = new List<Prediction>();
129
            if (request.useEndDate)
130
            {
131
                DateTime end = new DateTime(year: request.end.year, month: request.end.month, day: request.end.day, hour: request.end.hour, minute: 0, second: 0);
132
                DateTime current = start;
133
                while (current < end)
134
                {
135
                    _log.Debug($"Predicting for date {current.Date.ToShortDateString()}");
136
                    while (current.Hour < Date.MAX_HOUR)
137
                    {
138
                        _log.Debug($"Predicting for time {current.TimeOfDay.ToString()}");
139
                        var prediction = PredictSingle(request, current);
140
                        predictions.Add(prediction);
141
                        current = current.AddHours(this.Configuration.TimeResolution);
142
                    }
143
                    current = current.AddHours(23 - current.Hour + Date.MIN_HOUR);
144
                }
145
            }
146
            else
147
            {
148
                _log.Debug("Predicting for single DateTime.");
149
                predictions.Add(PredictSingle(request, start));
150
            }
151
            var response = new Response();
152
            response.hoursPerSegment = Configuration.TimeResolution;
153
            response.predicitons = predictions.ToArray();
154
            _log.Debug($"Created a response.");
155
            return response;
156
        }
157

    
158
        private Prediction PredictSingle(Request request, DateTime predictionTime)
159
        {
160
            double[] predictedValues = new double[this.Configuration.BuildingsToAreas.Count];
161
            string[] predictedLabels = new string[this.Predictors.Length];
162
            for (int i = 0; i < this.Predictors.Length; i++)
163
            {
164
                if (request.useWeather)
165
                {
166
                    _log.Debug("Predicting for requested weather.");
167
                    predictedLabels[i] = this.Predictors[i].Predict(new ModelInput
168
                    {
169
                        Rain = (float)request.rain,
170
                        Temp = (float)request.temperature,
171
                        Wind = (float)request.wind,
172
                        Hour = predictionTime.Hour,
173
                        Time = predictionTime
174
                    });
175
                }
176
                else
177
                {
178
                    _log.Debug("Retrieving weather info from the weather service.");
179
                    weatherService.ParsePrediction();
180
                    WeatherInfo weatherInfo = weatherService.Predictions.Find(info => info.startTime.Date.Equals(predictionTime.Date) && predictionTime.TimeOfDay.Subtract(info.startTime.TimeOfDay).Hours < info.intervalLength);
181
                    if (weatherInfo is null)
182
                    {
183
                        predictedLabels[i] = null;
184
                    }
185
                    else
186
                    {
187
                        predictedLabels[i] = this.Predictors[i].Predict(new ModelInput
188
                        {
189
                            Rain = weatherInfo.rain,
190
                            Temp = (float)weatherInfo.temp,
191
                            Wind = (float)weatherInfo.wind,
192
                            Hour = predictionTime.Hour,
193
                            Time = predictionTime
194
                        });
195
                    }
196
                }
197
            }
198
            for (int i = 0; i < predictedValues.Length; i++)
199
            {
200
                predictedValues[i] = this.FeatureExtractor.LabelToRatio(predictedLabels[this.Configuration.BuildingsToAreas[TagInfo.buildings[i]]]);
201
            }
202

    
203
            Prediction prediction = new Prediction();
204
            prediction.dateTime = new Date
205
            {
206
                year = predictionTime.Year,
207
                month = predictionTime.Month,
208
                day = predictionTime.Day,
209
                hour = predictionTime.Hour
210
            };
211
            prediction.predictions = predictedValues;
212
            _log.Debug($"Created prediction for DateTime: {prediction.dateTime}");
213
            return prediction;
214
        }
215

    
216
        public void Train()
217
        {
218
            DataParser.Parse(DateTime.MinValue, DateTime.MaxValue, this.Configuration.TimeResolution, wholeDay: false);
219
                for (int i = 0; i < this.Predictors.Length; i++)
220
                {
221
                    // train on all available data
222
                    List<ModelInput> data = FeatureExtractor.PrepareTrainingInput(i);
223
                    Console.WriteLine("Training predictor with {0} samples.", data.Count);
224
                    this.Predictors[i].Fit(data);
225
                }
226
        }
227

    
228
        public IEnumerable<string> GetDataFileNames()
229
        {
230
            return this.DataFilenames;
231
        }
232
    }
233
}
(8-8/9)