public Signal(Accesspoint accesspoint, float value) { Accesspoint = accesspoint ?? throw new ArgumentNullException(nameof(accesspoint)); Value = value; }
private static void Main(string[] args) { // Simuliert die Messungenauigkeit. Ist der relative Standardfehler. 0.1 bedeutet also, // dass bei einem berechneten Wert von 70 der Messwert in 68% der Fälle // (Normalverteilung) zwischen 70 +/- 7 ist. float bias = 0.1f; Randomizer.Seed = new Random(82541); Faker fkr = new Faker(); Accesspoint[] accesspoints = new Accesspoint[] { new Accesspoint("a1", new Point(0, 30)), new Accesspoint("a2", new Point(10, 20)), new Accesspoint("a3", new Point(0, 0)) }; // WIr positionieren 30 virtuelle Smartphones im Stockwerk. var devices = (from i in Enumerable.Range(0, 30) select new { Id = Guid.NewGuid().ToString("N"), Point = new Point(fkr.Random.Float(0, 10), fkr.Random.Float(0, 30)) }).ToArray(); List <Measurement> measurements = new List <Measurement>(); // Nun führen wir jede Minute eine Messung durch. for (DateTime date = new DateTime(2020, 1, 1, 12, 0, 0); date < new DateTime(2020, 1, 1, 13, 0, 0); date = date.AddMinutes(1)) { // Jedes Gerät liefert einen Messwert. foreach (var device in devices) { // Wir bekommen zwischen 1 und (Anz AP) pro Messung gesendet. Da nicht immer alle // APs empfangen werden, ist das ein guter Test, ob unser Programm damit umgehen // kann. var measuredAccesspoints = fkr.Random.ListItems(accesspoints, fkr.Random.Int(1, accesspoints.Length)); var signals = from ap in measuredAccesspoints let signalStrength = device.Point.SignalStrength(ap, val => fkr.Random.GaussianFloat(val, val * bias)) select new Signal(ap, signalStrength); Measurement m = new Measurement(device.Id, date, device.Point, signals); measurements.Add(m); } } var avgAp = measurements.Select(m => m.Signals.Count()).Average(); Console.WriteLine($"{measurements.Count} Messungen, {avgAp:0.00} APs pro Messung im Mittel."); var table = from m in measurements select new { m.Device, m.Date, m.Location.Room, // Floatarray mit den gemessenen Feldstärken der Accesspoint. Ist genau in // der Reihenfolge und größe wie unser accesspoints Array. // Details siehe in der Funktion Spread in der Datei ArrayExtensions.cs. Signals = m.Signals.Spread(accesspoints, s => s.Accesspoint).Select(s => s?.Value ?? 0).ToArray() }; using (var outStream = new StreamWriter("measurements.txt", false, Encoding.UTF8)) { outStream.WriteLine($"DEVICE\tROOM\tDATE\t{string.Join('\t', accesspoints.Select(s => s.Mac))}"); foreach (var row in table) { outStream.WriteLine($"{row.Device}\t{row.Room}\t{row.Date}\t{string.Join('\t', row.Signals)}"); } } // https://docs.microsoft.com/en-us/dotnet/api/microsoft.ml.lightgbmextensions.lightgbm?view=ml-dotnet // Define trainer options. var options = new LightGbmMulticlassTrainer.Options { LabelColumnName = nameof(RoomMeasurement.Label), FeatureColumnName = nameof(RoomMeasurement.Values), Booster = new DartBooster.Options() { TreeDropFraction = 0.15, XgboostDartMode = false } }; var mlContext = new MLContext(seed: 0); var trainData = mlContext.Data.LoadFromEnumerable(from m in measurements select new RoomMeasurement { Label = m.Location.Room, Values = m.Signals.Spread(accesspoints, s => s.Accesspoint).Select(s => s?.Value ?? 0).ToArray() }); // Define the trainer. var pipeline = mlContext.Transforms.Conversion.MapValueToKey(nameof(RoomMeasurement.Label)) .Append(mlContext.MulticlassClassification.Trainers.LightGbm(options)); var model = pipeline.Fit(trainData); // Create testing data. Use different random seed to make it different // from training data. var testData = trainData; // Wandelt die Label in UInt32 Werte für die interne Verarbeitung. var transformedTestData = model.Transform(testData); // Convert IDataView object to a list. var predictions = mlContext.Data .CreateEnumerable <RoomPrediction>(transformedTestData, reuseRowObject: false).ToList(); // Look at 5 predictions foreach (var p in predictions.Take(5)) { Console.WriteLine($"Label: {p.Label}, Prediction: {p.PredictedLabel}"); } var metrics = mlContext.MulticlassClassification.Evaluate(transformedTestData); PrintMetrics(metrics); }