Revize 0d31f7e0
Přidáno uživatelem Roman Kalivoda před téměř 4 roky(ů)
Server/Directory.Build.targets | ||
---|---|---|
1 |
<Project> |
|
2 |
<Target Name="AddInternalsVisibleTo" BeforeTargets="BeforeCompile"> |
|
3 |
<!-- Add default suffix if there is no InternalsVisibleTo or InternalsVisibleToSuffix defined --> |
|
4 |
<ItemGroup Condition="@(InternalsVisibleToSuffix->Count()) == 0 AND @(InternalsVisibleTo->Count()) == 0"> |
|
5 |
<InternalsVisibleToSuffix Include="Tests" /> |
|
6 |
<InternalsVisibleToSuffix Include="UnitTests" /> |
|
7 |
<InternalsVisibleToSuffix Include="FunctionalTests" /> |
|
8 |
</ItemGroup> |
|
9 |
|
|
10 |
<!-- Handle InternalsVisibleTo --> |
|
11 |
<ItemGroup Condition="'@(InternalsVisibleTo->Count())' > 0"> |
|
12 |
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo"> |
|
13 |
<_Parameter1>%(InternalsVisibleTo.Identity)</_Parameter1> |
|
14 |
</AssemblyAttribute> |
|
15 |
</ItemGroup> |
|
16 |
|
|
17 |
<!-- Handle InternalsVisibleToSuffix --> |
|
18 |
<ItemGroup Condition="@(InternalsVisibleToSuffix->Count()) > 0"> |
|
19 |
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo"> |
|
20 |
<_Parameter1>$(AssemblyName)%(InternalsVisibleToSuffix.Identity)</_Parameter1> |
|
21 |
</AssemblyAttribute> |
|
22 |
</ItemGroup> |
|
23 |
</Target> |
|
24 |
</Project> |
Server/ServerApp/App.config | ||
---|---|---|
1 |
<?xml version="1.0" encoding="utf-8" ?> |
|
2 |
<configuration> |
|
3 |
<configSections> |
|
4 |
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" /> |
|
5 |
</configSections> |
|
6 |
<log4net> |
|
7 |
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender"> |
|
8 |
<param name="File" value="server.log"/> |
|
9 |
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> |
|
10 |
<appendToFile value="true" /> |
|
11 |
<rollingStyle value="Size" /> |
|
12 |
<maxSizeRollBackups value="2" /> |
|
13 |
<maximumFileSize value="5MB" /> |
|
14 |
<staticLogFileName value="true" /> |
|
15 |
<threshold>DEBUG</threshold> |
|
16 |
<layout type="log4net.Layout.PatternLayout"> |
|
17 |
<param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/> |
|
18 |
</layout> |
|
19 |
</appender> |
|
20 |
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender"> |
|
21 |
<layout type="log4net.Layout.PatternLayout"> |
|
22 |
<param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/> |
|
23 |
</layout> |
|
24 |
</appender> |
|
25 |
<root> |
|
26 |
<level value="ALL" /> |
|
27 |
<appender-ref ref="LogFileAppender" /> |
|
28 |
<appender-ref ref="ConsoleAppender" /> |
|
29 |
</root> |
|
30 |
</log4net> |
|
31 |
</configuration> |
Server/ServerApp/Predictor/ModelInput.cs | ||
---|---|---|
47 | 47 |
/// </summary> |
48 | 48 |
[ColumnName("Rain"), LoadColumn(4)] |
49 | 49 |
public float Rain { get; set; } |
50 |
|
|
51 |
public override string ToString() |
|
52 |
{ |
|
53 |
return $"ModelInput: {Time}; {Label}; {Temp}, {Hour}, {Wind}, {Rain}"; |
|
54 |
} |
|
50 | 55 |
} |
51 | 56 |
} |
Server/ServerApp/Predictor/NaiveBayesClassifier.cs | ||
---|---|---|
5 | 5 |
using System; |
6 | 6 |
using System.Collections.Generic; |
7 | 7 |
using System.Linq; |
8 |
using System.Reflection; |
|
9 |
using log4net; |
|
8 | 10 |
using Microsoft.ML; |
9 | 11 |
|
10 | 12 |
namespace ServerApp.Predictor |
... | ... | |
14 | 16 |
/// </summary> |
15 | 17 |
class NaiveBayesClassifier : IPredictor |
16 | 18 |
{ |
19 |
private static readonly ILog _log = LogManager.GetLogger(typeof(NaiveBayesClassifier)); |
|
20 |
|
|
17 | 21 |
/// <summary> |
18 | 22 |
/// Context of the ML.NET framework. |
19 | 23 |
/// </summary> |
... | ... | |
49 | 53 |
.Append(_mlContext.Transforms.Conversion.MapKeyToValue(nameof(ModelOutput.PredictedLabel))); |
50 | 54 |
|
51 | 55 |
var cvResults = _mlContext.MulticlassClassification.CrossValidate(this._trainingDataView, pipeline); |
52 |
foreach (var result in cvResults) |
|
53 |
{ |
|
54 |
var testMetrics = result.Metrics; |
|
55 |
Console.WriteLine($"*************************************************************************************************************"); |
|
56 |
Console.WriteLine($"* Metrics for Multi-class Classification model - Model #{result.Fold} "); |
|
57 |
Console.WriteLine($"*------------------------------------------------------------------------------------------------------------"); |
|
58 |
Console.WriteLine($"* MicroAccuracy: {testMetrics.MicroAccuracy:0.###}"); |
|
59 |
Console.WriteLine($"* MacroAccuracy: {testMetrics.MacroAccuracy:0.###}"); |
|
60 |
Console.WriteLine($"* LogLoss: {testMetrics.LogLoss:#.###}"); |
|
61 |
Console.WriteLine($"* LogLossReduction: {testMetrics.LogLossReduction:#.###}"); |
|
62 |
Console.WriteLine($"* Confusion Matrix: {testMetrics.ConfusionMatrix.GetFormattedConfusionTable()}"); |
|
63 |
Console.WriteLine($"*************************************************************************************************************"); |
|
64 |
} |
|
56 |
_log.Debug("Cross-validated the trained model"); |
|
65 | 57 |
this._trainedModel = cvResults.OrderByDescending(fold => fold.Metrics.MicroAccuracy).Select(fold => fold.Model).First(); |
66 |
Console.WriteLine($"Selected the model #{cvResults.OrderByDescending(fold => fold.Metrics.MicroAccuracy).Select(fold => fold.Fold).First()} as the best.");
|
|
58 |
_log.Info($"Selected the model #{cvResults.OrderByDescending(fold => fold.Metrics.MicroAccuracy).Select(fold => fold.Fold).First()} as the best.");
|
|
67 | 59 |
this._predictionEngine = _mlContext.Model.CreatePredictionEngine<ModelInput, ModelOutput>(this._trainedModel); |
68 | 60 |
|
69 | 61 |
} |
70 | 62 |
|
71 | 63 |
public string Predict(ModelInput input) |
72 | 64 |
{ |
65 |
_log.Debug($"Predicting for input: {input}"); |
|
73 | 66 |
return this._predictionEngine.Predict(input).PredictedLabel; |
74 | 67 |
} |
75 | 68 |
|
Server/ServerApp/Predictor/PredictionController.cs | ||
---|---|---|
9 | 9 |
using Newtonsoft.Json; |
10 | 10 |
using ServerApp.WeatherPredictionParser; |
11 | 11 |
using ServerApp.Parser.OutputInfo; |
12 |
using System.Reflection; |
|
13 |
using log4net; |
|
12 | 14 |
|
13 | 15 |
namespace ServerApp.Predictor |
14 | 16 |
{ |
... | ... | |
17 | 19 |
/// </summary> |
18 | 20 |
public class PredictionController : IPredictionController |
19 | 21 |
{ |
22 |
private static readonly ILog _log = LogManager.GetLogger(typeof(PredictionController)); |
|
23 |
|
|
20 | 24 |
/// <summary> |
21 | 25 |
/// Configuration of the <c>Predictor</c> |
22 | 26 |
/// </summary> |
... | ... | |
45 | 49 |
/// <param name="dataParser">A data parser used to get training data.</param> |
46 | 50 |
public PredictionController(IJsonParser weatherService, IDataParser dataParser, string pathToConfig = null) |
47 | 51 |
{ |
52 |
_log.Info("Constructing a new PredictionController instance."); |
|
48 | 53 |
this.weatherService = weatherService; |
49 | 54 |
// load config or get the default one |
50 | 55 |
if (pathToConfig is null) |
... | ... | |
55 | 60 |
{ |
56 | 61 |
string json = System.IO.File.ReadAllText(pathToConfig); |
57 | 62 |
this.Configuration = JsonConvert.DeserializeObject<PredictorConfiguration>(json); |
58 |
} catch (System.IO.IOException e) |
|
63 |
} |
|
64 |
catch (System.IO.IOException e) |
|
59 | 65 |
{ |
60 | 66 |
Console.WriteLine("Warning: could not find a configuration file, creating a new one:"); |
61 | 67 |
Console.WriteLine(e.Message.PadLeft(4)); |
... | ... | |
91 | 97 |
|
92 | 98 |
public Response Predict(Request request) |
93 | 99 |
{ |
100 |
_log.Info($"Received a prediction request: endDate={request.useEndDate}, weather={request.useWeather}"); |
|
94 | 101 |
DateTime start = new DateTime(year: request.start.year, month: request.start.month, day: request.start.day, hour: request.start.hour, minute: 0, second: 0); |
95 | 102 |
List<Prediction> predictions = new List<Prediction>(); |
96 | 103 |
if (request.useEndDate) |
... | ... | |
99 | 106 |
DateTime current = start; |
100 | 107 |
while (current < end) |
101 | 108 |
{ |
109 |
_log.Debug($"Predicting for date {current.Date.ToShortDateString()}"); |
|
102 | 110 |
while (current.Hour < Date.MAX_HOUR) |
103 | 111 |
{ |
112 |
_log.Debug($"Predicting for time {current.TimeOfDay.ToString()}"); |
|
104 | 113 |
var prediction = PredictSingle(request, current); |
105 | 114 |
predictions.Add(prediction); |
106 | 115 |
current = current.AddHours(this.Configuration.TimeResolution); |
107 | 116 |
} |
108 | 117 |
current = current.AddHours(23 - current.Hour + Date.MIN_HOUR); |
109 | 118 |
} |
110 |
} else |
|
119 |
} |
|
120 |
else |
|
111 | 121 |
{ |
112 |
if (request.useWeather) |
|
113 |
{ |
|
114 |
predictions.Add(PredictSingle(request, start)); |
|
115 |
} |
|
122 |
_log.Debug("Predicting for single DateTime."); |
|
123 |
predictions.Add(PredictSingle(request, start)); |
|
116 | 124 |
} |
117 | 125 |
var response = new Response(); |
118 | 126 |
response.hoursPerSegment = Configuration.TimeResolution; |
119 | 127 |
response.predicitons = predictions.ToArray(); |
128 |
_log.Debug($"Created a response."); |
|
120 | 129 |
return response; |
121 | 130 |
} |
122 | 131 |
|
... | ... | |
128 | 137 |
{ |
129 | 138 |
if (request.useWeather) |
130 | 139 |
{ |
140 |
_log.Debug("Predicting for requested weather."); |
|
131 | 141 |
predictedLabels[i] = this.Predictors[i].Predict(new ModelInput |
132 | 142 |
{ |
133 | 143 |
Rain = (float)request.rain, |
... | ... | |
139 | 149 |
} |
140 | 150 |
else |
141 | 151 |
{ |
142 |
List<WeatherInfo> weatherInfos = weatherService.GetPredictionForTime(from: current, to: current.AddHours(this.Configuration.TimeResolution)); |
|
152 |
_log.Debug("Retrieving weather info from the weather service."); |
|
153 |
weatherService.ParsePrediction(); |
|
154 |
WeatherInfo weatherInfo = weatherService.Current; |
|
143 | 155 |
predictedLabels[i] = this.Predictors[i].Predict(new ModelInput |
144 | 156 |
{ |
145 |
Rain = weatherInfos[0].rain,
|
|
146 |
Temp = (float)weatherInfos[0].temp,
|
|
147 |
Wind = (float)weatherInfos[0].wind,
|
|
157 |
Rain = weatherInfo.rain, |
|
158 |
Temp = (float)weatherInfo.temp, |
|
159 |
Wind = (float)weatherInfo.wind, |
|
148 | 160 |
Hour = current.Hour, |
149 | 161 |
Time = current |
150 | 162 |
}); |
... | ... | |
164 | 176 |
hour = current.Hour |
165 | 177 |
}; |
166 | 178 |
prediction.predictions = predictedValues; |
179 |
_log.Debug($"Created prediction for DateTime: {prediction.dateTime}"); |
|
167 | 180 |
return prediction; |
168 | 181 |
} |
169 | 182 |
|
Server/ServerApp/Program.cs | ||
---|---|---|
1 |
using ServerApp.Connection; |
|
1 |
using log4net.Config; |
|
2 |
using ServerApp.Connection; |
|
2 | 3 |
using ServerApp.Connection.XMLProtocolHandler; |
3 | 4 |
using ServerApp.DataDownload; |
4 | 5 |
using ServerApp.Parser.InputData; |
... | ... | |
33 | 34 |
|
34 | 35 |
static void Main(string[] args) |
35 | 36 |
{ |
36 |
|
|
37 |
// SETUP FOLDERS
|
|
38 |
Config config = FillConfigInfo(args);
|
|
37 |
XmlConfigurator.Configure(); |
|
38 |
// SETUP FOLDERS
|
|
39 |
Config config = FillConfigInfo(args);
|
|
39 | 40 |
if (config == null) |
40 | 41 |
{ |
41 | 42 |
Console.ReadLine(); |
... | ... | |
180 | 181 |
// TODO nastavit čas |
181 | 182 |
IDataParser p = new DataParser(dd); |
182 | 183 |
// FIXME pass the right references to the JsonParser constructor |
183 |
IJsonParser jsonP = new JsonParser(dd, null);
|
|
184 |
IJsonParser jsonP = new JsonParser(dd, new CsvDataLoader());
|
|
184 | 185 |
IPredictionController predictionController = new PredictionController(jsonP, p); |
185 | 186 |
predictionController.Train(); |
186 | 187 |
//var results = predictionController.Predict() |
Server/ServerApp/Properties/launchSettings.json | ||
---|---|---|
2 | 2 |
"profiles": { |
3 | 3 |
"ServerApp": { |
4 | 4 |
"commandName": "Project", |
5 |
"commandLineArgs": "C:\\Users\\kalivoda\\Temp\\serverAppNetCore\\ServerAppNETCore\\ServerApp\\server_config"
|
|
5 |
"commandLineArgs": "C:\\Users\\kalivoda\\University\\KIV-ASWI\\aswi2021tri-musketyri\\Server\\ServerApp\\server_config"
|
|
6 | 6 |
} |
7 | 7 |
} |
8 | 8 |
} |
Server/ServerApp/ServerApp.csproj | ||
---|---|---|
8 | 8 |
</PropertyGroup> |
9 | 9 |
|
10 | 10 |
<ItemGroup> |
11 |
<PackageReference Include="log4net" Version="2.0.12" /> |
|
11 | 12 |
<PackageReference Include="Microsoft.ML" Version="1.5.5" /> |
12 | 13 |
</ItemGroup> |
13 | 14 |
|
... | ... | |
26 | 27 |
</EmbeddedResource> |
27 | 28 |
</ItemGroup> |
28 | 29 |
|
29 |
<ItemGroup> |
|
30 |
<!--<ItemGroup>
|
|
30 | 31 |
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute"> |
31 | 32 |
<_Parameter1>ServerAppUnitTests</_Parameter1> |
32 |
<!-- We use the value of AssemblyName to declare the value of the attribute -->
|
|
33 |
--><!-- We use the value of AssemblyName to declare the value of the attribute --><!--
|
|
33 | 34 |
</AssemblyAttribute> |
34 |
</ItemGroup> |
|
35 |
</ItemGroup>-->
|
|
35 | 36 |
|
36 | 37 |
</Project> |
Server/ServerAppFunctionalTests/Predictor/PredictionControllerTests.cs | ||
---|---|---|
1 |
using Microsoft.VisualStudio.TestTools.UnitTesting; |
|
2 |
using ServerApp.Predictor; |
|
3 |
// |
|
4 |
// Author: Roman Kalivoda |
|
5 |
// |
|
6 |
|
|
7 |
using System; |
|
8 |
using System.Collections.Generic; |
|
9 |
using System.Linq; |
|
10 |
using System.Text; |
|
11 |
using System.Threading.Tasks; |
|
12 |
using ServerApp.WeatherPredictionParser; |
|
13 |
using ServerApp.Parser.Parsers; |
|
14 |
using ServerApp.Parser.InputData; |
|
15 |
using ServerApp.Connection.XMLProtocolHandler; |
|
16 |
using ServerApp.DataDownload; |
|
17 |
|
|
18 |
namespace ServerApp.Predictor.Tests |
|
19 |
{ |
|
20 |
[TestClass()] |
|
21 |
public class PredictionControllerTests |
|
22 |
{ |
|
23 |
[TestMethod()] |
|
24 |
public void PredictSingleTimeWeatherTest() |
|
25 |
{ |
|
26 |
System.IO.Directory.CreateDirectory(@".\data"); |
|
27 |
DataDownloader dd = new DataDownloader(@".\data\dd\", "http://openstore.zcu.cz/", "OD_ZCU_{type}_{month}_{year}_{format}.zip"); |
|
28 |
PredictionController instance = new PredictionController(new JsonParser(dd, new CsvDataLoader()), new DataParser(dd)); |
|
29 |
|
|
30 |
dd.DownloadData(DataType.JIS, DataFormat.CSV, new DataDownload.Date(1, 2019), new DataDownload.Date(12, 2020)); |
|
31 |
dd.DownloadData(DataType.STROJE, DataFormat.CSV, new DataDownload.Date(1, 2017), new DataDownload.Date(12, 2020)); |
|
32 |
dd.DownloadData(DataType.POCASI, DataFormat.CSV, new DataDownload.Date(1, 2017), new DataDownload.Date(12, 2020)); |
|
33 |
instance.Train(); |
|
34 |
|
|
35 |
Request request = new Request() |
|
36 |
{ |
|
37 |
useEndDate = false, |
|
38 |
useWeather = false, |
|
39 |
start = new Connection.XMLProtocolHandler.Date() |
|
40 |
{ |
|
41 |
day = DateTime.Now.Day, |
|
42 |
month = DateTime.Now.Month, |
|
43 |
year = DateTime.Now.Year, |
|
44 |
hour = 10 |
|
45 |
} |
|
46 |
}; |
|
47 |
Response actual = instance.Predict(request); |
|
48 |
CollectionAssert.AllItemsAreInstancesOfType(actual.predicitons, typeof(Prediction)); |
|
49 |
Assert.AreEqual(1, actual.predicitons.Length); |
|
50 |
} |
|
51 |
} |
|
52 |
} |
Server/ServerAppUnitTests/Predictor/NaiveBayesClassifierTests.cs | ||
---|---|---|
1 |
using Microsoft.VisualStudio.TestTools.UnitTesting; |
|
2 |
using ServerApp.Predictor; |
|
3 |
// |
|
4 |
// Author: Roman Kalivoda |
|
5 |
// |
|
6 |
|
|
7 |
using System; |
|
8 |
using System.Collections.Generic; |
|
9 |
using System.Linq; |
|
10 |
using System.Text; |
|
11 |
using System.Threading.Tasks; |
|
12 |
using System.Text.RegularExpressions; |
|
13 |
|
|
14 |
namespace ServerApp.Predictor.Tests |
|
15 |
{ |
|
16 |
[TestClass()] |
|
17 |
public class NaiveBayesClassifierTests |
|
18 |
{ |
|
19 |
static IPredictor predictor; |
|
20 |
|
|
21 |
static readonly List<ModelInput> trainInput = new() |
|
22 |
{ |
|
23 |
new ModelInput |
|
24 |
{ |
|
25 |
Label = "10%", |
|
26 |
Temp = 12, |
|
27 |
Hour = 7, |
|
28 |
Rain = 10, |
|
29 |
Time = DateTime.Now, |
|
30 |
Wind = 10 |
|
31 |
}, |
|
32 |
new ModelInput |
|
33 |
{ |
|
34 |
Label = "100%", |
|
35 |
Temp = 32, |
|
36 |
Hour = 7, |
|
37 |
Rain = 0, |
|
38 |
Time = DateTime.Now, |
|
39 |
Wind = 70 |
|
40 |
}, |
|
41 |
new ModelInput |
|
42 |
{ |
|
43 |
Label = "90%", |
|
44 |
Temp = 32, |
|
45 |
Hour = 15, |
|
46 |
Rain = 20, |
|
47 |
Time = DateTime.Now, |
|
48 |
Wind = 50 |
|
49 |
}, |
|
50 |
new ModelInput |
|
51 |
{ |
|
52 |
Label = "70%", |
|
53 |
Temp = 32, |
|
54 |
Hour = 18, |
|
55 |
Rain = 0, |
|
56 |
Time = DateTime.Now, |
|
57 |
Wind = 70 |
|
58 |
}, |
|
59 |
new ModelInput |
|
60 |
{ |
|
61 |
Label = "30%", |
|
62 |
Temp = 6, |
|
63 |
Hour = 10, |
|
64 |
Rain = 70, |
|
65 |
Time = DateTime.Now, |
|
66 |
Wind = 30 |
|
67 |
} |
|
68 |
}; |
|
69 |
|
|
70 |
[ClassInitialize()] |
|
71 |
public static void SetUpClass(TestContext context) |
|
72 |
{ |
|
73 |
predictor = new NaiveBayesClassifier(); |
|
74 |
predictor.Fit(trainInput); |
|
75 |
} |
|
76 |
|
|
77 |
[TestMethod()] |
|
78 |
public void PredictTest() |
|
79 |
{ |
|
80 |
string actual = predictor.Predict(new ModelInput |
|
81 |
{ |
|
82 |
Temp = 19, |
|
83 |
Hour = 17, |
|
84 |
Rain = 20, |
|
85 |
Time = DateTime.Now, |
|
86 |
Wind = 7 |
|
87 |
}); |
|
88 |
StringAssert.Matches(actual, new Regex(@"\d0%")); |
|
89 |
} |
|
90 |
} |
|
91 |
} |
Server/ServerAppUnitTests/Predictor/PredictionControllerTests.cs | ||
---|---|---|
1 |
using Microsoft.VisualStudio.TestTools.UnitTesting; |
|
2 |
using ServerApp.Predictor; |
|
3 |
using System; |
|
4 |
using System.Collections.Generic; |
|
5 |
using System.Linq; |
|
6 |
using System.Text; |
|
7 |
using System.Threading.Tasks; |
|
8 |
|
|
9 |
namespace ServerApp.Predictor.Tests |
|
10 |
{ |
|
11 |
[TestClass()] |
|
12 |
public class PredictionControllerTests |
|
13 |
{ |
|
14 |
[TestMethod()] |
|
15 |
public void PredictionControllerTest() |
|
16 |
{ |
|
17 |
throw new NotImplementedException(); |
|
18 |
} |
|
19 |
|
|
20 |
[TestMethod()] |
|
21 |
public void GetPredictorsTest() |
|
22 |
{ |
|
23 |
throw new NotImplementedException(); |
|
24 |
} |
|
25 |
|
|
26 |
[TestMethod()] |
|
27 |
public void LoadTest() |
|
28 |
{ |
|
29 |
throw new NotImplementedException(); |
|
30 |
} |
|
31 |
|
|
32 |
[TestMethod()] |
|
33 |
public void PredictTest() |
|
34 |
{ |
|
35 |
throw new NotImplementedException(); |
|
36 |
} |
|
37 |
|
|
38 |
[TestMethod()] |
|
39 |
public void TrainTest() |
|
40 |
{ |
|
41 |
throw new NotImplementedException(); |
|
42 |
} |
|
43 |
} |
|
44 |
} |
Také k dispozici: Unified diff
Re #8953 tests