In letzter Zeit bin ich auf immer mehr Informationen über das
Framework für maschinelles Lernen Ml.NET gestoßen . Die Anzahl der Hinweise darauf nahm an Qualität zu, und ich beschloss, zumindest mit einem Blick auf einen Blick zu sehen, um welche Art von Tier es sich handelte.
Zuvor haben wir versucht, das einfachste Vorhersageproblem mithilfe der linearen Regression im .NET-Ökosystem zu lösen. Dafür haben wir das Accord.NET Framework verwendet. Zu diesem Zweck wurde ein kleiner Datensatz
aus offenen Daten über die Aufrufe der Bürger an die Exekutivbehörden und persönlich
an den Bürgermeister von Moskau erstellt .
Nach einigen Jahren mit
einem aktualisierten Datensatz werden wir versuchen, das
einfachste Problem zu lösen. Mithilfe des Regressionsmodells in Ml.NET Framework prognostizieren wir, wie viele Anforderungen pro Monat eine positive Lösung erhalten. Unterwegs werden wir Ml.NET mit Accord vergleichen. NET- und Python-Bibliotheken.
Möchten Sie die Stärke und Kraft des Prädiktors beherrschen? Dann sind Sie unter Katze willkommen.
PS Lassen Sie S.S. Sobyanin, der Artikel wird kein Wort über Politik sagen.Inhalt:
Teil I: Einführung und ein bisschen über DatenTeil II: Schreiben von C # -CodeTeil III: SchlussfolgerungIch denke, es ist notwendig, Sie sofort zu warnen, dass ich weder ein Profi in der Datenanalyse und -programmierung im Allgemeinen bin, noch mit dem Moskauer Rathaus beschäftigt bin. Daher ist der Artikel eher von Anfänger zu Anfänger. Trotz meines begrenzten Wissens hoffe ich, dass der Artikel für Sie nützlich sein wird.Personen, die bereits mit früheren Artikeln aus dem Zyklus vertraut sind, erinnern sich möglicherweise daran, dass wir bereits versucht haben, das Problem der Vorhersage der Anzahl positiv gelöster Probleme aus den Appellen der an die Exekutive von Moskau gerichteten Bürger zu lösen. Dafür haben wir das
Python- und
Accord.Net-Framework verwendet .
Andere Fahrradartikel1. Lernen Sie die Grundlagen:
2. Wir üben die ersten Fähigkeiten
In jedem Fall ist es nicht überflüssig, den erneut verwendeten Datensatz zu analysieren.
Alle Artikelmaterialien, einschließlich Code und Datensatz, sind
auf GitHub frei verfügbar .
Daten auf GitHub werden im CSV-Format dargestellt, enthalten 44 Einträge und können (und sollten) im Prinzip nicht nur zur Analyse des Beispiels verwendet werden.
Datenspalten bedeuten Folgendes:
- num - record index
- Jahr - Jahr der Aufzeichnung
- Monat - Monat der Aufnahme
- total_appeals - Gesamtzahl der Treffer pro Monat
- appells_to_mayor - Gesamtzahl der Berufungen an den Bürgermeister
- res_positive- Anzahl positiver Entscheidungen
- res_explained - Anzahl der Aufrufe zur Klärung
- res_negative - Anzahl der Anrufe mit einer negativen Entscheidung
- El_form_to_mayor - die Anzahl der Berufungen an den Bürgermeister in elektronischer Form
- Pap_form_to_mayor - die Anzahl der Appelle an den Bürgermeister auf Papier an_10K_total_VAO ... to_10K_total_YUZAO - die Anzahl der Appelle pro 10.000 Einwohner in verschiedenen Bezirken Moskaus
- to_10K_mayor_VAO ... to_10K_mayor_YUZAO - die Anzahl der an den Bürgermeister und die Regierung von Moskau gerichteten Appelle pro 10.000 Einwohner in verschiedenen Bezirken der Stadt
Ich habe keine Möglichkeit gefunden, den Datenerfassungsprozess zu automatisieren und manuell zu erfassen, sodass ich mich leicht irren könnte. Andernfalls bleibt die Zuverlässigkeit der Daten dem Gewissen der Autoren überlassen.
Derzeit werden die Daten auf der Regierungswebsite in Moskau von Januar 2016 bis August 2019 vollständig dargestellt (einige Daten fehlen im September). Somit haben wir 44 Einträge. Ein bisschen natürlich, aber zur Demonstration wird dies ausreichen.
Bevor Sie beginnen, nur ein paar Worte über den Helden unseres Artikels.
ML.NET Framework - Open Source-Entwicklung von Microsoft. Laut Social Media-Werbung ist dies ihre Antwort auf Python-Bibliotheken für maschinelles Lernen. Das Framework ist plattformübergreifend und ermöglicht es Ihnen, eine Vielzahl von Aufgaben zu lösen, von einfacher Regression und Klassifizierung bis hin zu Deep Learning. Auf Habr haben Genossen bereits die Analyse von ML.NET und Bibliotheken in Python durchgeführt. Wen kümmert es, hier ist der
Link .
Ich werde keine detaillierte Anleitung zur Installation und Verwendung von Ml.NET geben, da im Wesentlichen alles "angepasst" wurde, basierend auf einem
Lehrbuch von der offiziellen Microsoft-Website .
Dort wurde das Problem mit den Preisen einer Taxifahrt gelöst, und um ehrlich zu sein, gibt es weitere VorteileAber ich denke, die kleinen Erklärungen werden nicht überflüssig sein.
Ich habe Visual Studio 2017 mit den neuesten Updates verwendet.
Das Projekt basierte auf der .NET Core-Konsolenanwendungsvorlage (Version 2.1).
Das Projekt musste die NuGet-Pakete Microsoft.ML, Microsoft.ML.FastTree installieren. Das ist in der Tat die ganze Vorbereitung.
Wir gehen direkt zum Code über.
Zu Beginn habe ich die MayorAppel-Klasse erstellt, in der ich die Spalten mit Daten aus CSV-Dateien der Reihe nach beschrieben habe.
Wie nicht schwer zu erraten [LoadColumn (0)]
- sagt uns, welche Spalte aus der CSV-Datei wir nehmen.
Als nächstes habe ich nach dem Tutorial die MayorAppelPrediction-Klasse erstellt - für Vorhersageergebnisse
Trotz der Tatsache, dass fast alle Spalten im Datensatz ganzzahlige Werte haben, musste ich ihnen einen Float-Typ zuweisen (damit alle Datentypen gleich sind), um Fehler beim Verkleben von Daten in der Pipeline zu vermeiden.
Die Liste ist groß genug, also legen Sie sie unter den Spoiler.
Klassencode für die Datenbeschreibungusing Microsoft.ML.Data; namespace app_to_mayor_mlnet { class MayorAppel { [LoadColumn(0)] public float Year; [LoadColumn(1)] public string Month; [LoadColumn(2)] public float TotalAppeals; [LoadColumn(3)] public float AppealsToMayor; [LoadColumn(4)] public float ResPositive; [LoadColumn(5)] public float ResExplained; [LoadColumn(6)] public float ResNegative; [LoadColumn(7)] public float ElFormToMayor; [LoadColumn(8)] public float PapFormToMayor; [LoadColumn(9)] public float To10KTotalVAO; [LoadColumn(10)] public float To10KMayorVAO; [LoadColumn(11)] public float To10KTotalZAO; [LoadColumn(12)] public float To10KMayorZAO; [LoadColumn(13)] public float To10KTotalZelAO; [LoadColumn(14)] public float To10KMayorZelAO; [LoadColumn(6)] public float To10KTotalSAO; [LoadColumn(15)] public float To10KMayorSAO; [LoadColumn(16)] public float To10KTotalSVAO; [LoadColumn(17)] public float To10KMayorSVAO; [LoadColumn(18)] public float To10KTotalSZAO; [LoadColumn(19)] public float To10KMayorSZAO; [LoadColumn(20)] public float To10KTotalTiNAO; [LoadColumn(21)] public float To10KMayorTiNAO; [LoadColumn(22)] public float To10KTotalCAO; [LoadColumn(23)] public float To10KMayorCAO; [LoadColumn(24)] public float To10KTotalYUAO; [LoadColumn(25)] public float To10KMayorYUAO; [LoadColumn(26)] public float To10KTotalYUVAO; [LoadColumn(27)] public float To10KMayorYUVAO; [LoadColumn(28)] public float To10KTotalYUZAO; [LoadColumn(29)] public float To10KMayorYUZAO; } public class MayorAppelPrediction { [ColumnName("Score")] public float ResPositive; } }
Fahren wir mit dem Hauptprogrammcode fort.
Vergessen Sie nicht, ganz am Anfang hinzuzufügen:
using System.IO; using Microsoft.ML;
Das Folgende ist eine Beschreibung der Datenfelder.
namespace app_to_mayor_mlnet { class Program { static readonly string _trainDataPath = Path.Combine(Environment.CurrentDirectory, "Data", "train_data.csv"); static readonly string _testDataPath = Path.Combine(Environment.CurrentDirectory, "Data", "test_data.csv"); static readonly string _modelPath = Path.Combine(Environment.CurrentDirectory, "Data", "Model.zip");
In diesen Feldern werden tatsächlich die Pfade zu den Datendateien gespeichert. Dieses Mal habe ich beschlossen, sie im Voraus zu trennen (im Gegensatz zu Accord.NET).
Übrigens, wenn Sie Ihr Projekt ausführen, vergessen Sie nicht, die Option "Spätere Version kopieren" in den Eigenschaften der Datendateien festzulegen, um einen Fehler aufgrund fehlender Assemblydateien zu vermeiden.
Als nächstes kommt die Herausforderung der Methoden, die das Modell bilden, seine Bewertung durchführen und uns eine Vorhersage geben.
static void Main(string[] args) { MLContext mlContext = new MLContext(seed: 0); var model = Train(mlContext, _trainDataPath); Evaluate(mlContext, model); TestSinglePrediction(mlContext, model); }
Lass uns in Ordnung gehen
Die Train-Methode wird benötigt, um das Modell zu trainieren.
public static ITransformer Train(MLContext mlContext, string dataPath) { IDataView dataView = mlContext.Data.LoadFromTextFile<MayorAppel>(dataPath, hasHeader: true, separatorChar: ','); var pipeline = mlContext.Transforms.CopyColumns(outputColumnName: "Label", inputColumnName: "ResPositive") .Append(mlContext.Transforms.Categorical.OneHotEncoding(outputColumnName: "MonthEncoded", inputColumnName: "Month")) .Append(mlContext.Transforms.Concatenate("Features", "Year", "MonthEncoded", "TotalAppeals", "AppealsToMayor", "ResExplained", "ResNegative", "ElFormToMayor", "PapFormToMayor", "To10KTotalVAO", "To10KMayorVAO", "To10KTotalZAO", "To10KMayorZAO", "To10KTotalZelAO", "To10KMayorZelAO", "To10KTotalSAO", "To10KMayorSAO" , "To10KTotalSVAO", "To10KMayorSVAO", "To10KTotalSZAO", "To10KMayorSZAO", "To10KTotalTiNAO", "To10KMayorTiNAO" , "To10KTotalCAO", "To10KMayorCAO", "To10KTotalYUAO", "To10KMayorYUAO", "To10KTotalYUVAO", "To10KMayorYUVAO" , "To10KTotalYUZAO", "To10KMayorYUZAO")).Append(mlContext.Regression.Trainers.FastTree()); var model = pipeline.Fit(dataView); return model; }
Zu Beginn lesen wir die Daten aus dem Trainingsmuster. Dann bestimmen wir in der Kette den Parameter, der vorhersagen wird (Label).
In unserem Fall ist dies die Anzahl der erfolgreich gelösten Probleme im Zusammenhang mit den Einsprüchen der Bürger pro Monat.
Da in diesem Fall das Modell der Erhöhung von Entscheidungsbäumen basierend auf Regression verwendet wird, müssen alle Vorzeichen auf numerische Werte gebracht werden.
Anders als bei Accord.NET wird die fertige OneHotEncoding-Lösung hier sofort in der Dokumentation vorgestellt.
Nachdem die Spalten, wie oben erwähnt, noch gebildet werden müssen, sollten sie alle vom gleichen Datentyp sein, in diesem Fall ein Float.
Abschließend bilden wir das fertige Modell und geben es zurück.
Als nächstes bewerten wir die Qualität der Vorhersage anhand unseres Modells.
private static void Evaluate(MLContext mlContext, ITransformer model) { IDataView dataView = mlContext.Data.LoadFromTextFile<MayorAppel>(_testDataPath, hasHeader: true, separatorChar: ','); var predictions = model.Transform(dataView); var metrics = mlContext.Regression.Evaluate(predictions, "Label", "Score"); Console.WriteLine(); Console.WriteLine($"*************************************************"); Console.WriteLine($"* Model quality metrics evaluation "); Console.WriteLine($"*------------------------------------------------"); Console.WriteLine($"* RSquared Score: {metrics.RSquared:0.##}"); Console.WriteLine($"* Root Mean Squared Error: {metrics.RootMeanSquaredError:#.##}"); }
Wir laden unsere Testprobe (die letzten 4 Monate ab dem Satz) und erhalten die Vorhersage unserer Testdaten auf dem trainierten Modell unter Verwendung der Transform () -Methode. Dann berechnen wir die Metriken und drucken sie aus. In diesem Fall ist es der Bestimmungskoeffizient und die Standardabweichung. Die erste sollte idealerweise gegen 1 und die zweite im Wesentlichen gegen Null tendieren.
Um eine Vorhersage zu treffen, brauchten wir diese Methode im Prinzip nicht, aber es ist schön zu verstehen, wie schlecht unser Modell etwas vorhersagt.
Die letzte Methode bleibt - die Vorhersage selbst.
Wir werden es auch unter dem Spoiler verstecken.
Vorhersagemethode und Daten private static void TestSinglePrediction(MLContext mlContext, ITransformer model) { var predictionFunction = mlContext.Model.CreatePredictionEngine<MayorAppel, MayorAppelPrediction>(model); var MayorAppelSampleMinData = new MayorAppel() { Year = 2019, Month = "August", ResPositive = 0 }; var MayorAppelSampleMediumData = new MayorAppel() { Year = 2019, Month = "August", TotalAppeals = 111340, AppealsToMayor = 17932, ResExplained = 66858, ResNegative = 8945, ElFormToMayor = 14931, PapFormToMayor = 2967, ResPositive = 0 }; var MayorAppelSampleMaxData = new MayorAppel() { Year = 2019, Month = "August", TotalAppeals = 111340, AppealsToMayor = 17932, ResExplained = 66858, ResNegative = 8945, ElFormToMayor = 14931, PapFormToMayor = 2967, To10KTotalVAO = 67, To10KMayorVAO = 13, To10KTotalZAO = 57, To10KMayorZAO = 13, To10KTotalZelAO = 49, To10KMayorZelAO = 9, To10KTotalSAO = 71, To10KMayorSAO = 14, To10KTotalSVAO = 86, To10KMayorSVAO = 27, To10KTotalSZAO = 68, To10KMayorSZAO = 12, To10KTotalTiNAO = 93, To10KMayorTiNAO = 36, To10KTotalCAO = 104, To10KMayorCAO = 24, To10KTotalYUAO = 56, To10KMayorYUAO = 12, To10KTotalYUVAO = 59, To10KMayorYUVAO = 13, To10KTotalYUZAO = 78, To10KMayorYUZAO = 23, ResPositive = 0 }; var predictionMin = predictionFunction.Predict(MayorAppelSampleMinData); var predictionMed = predictionFunction.Predict(MayorAppelSampleMediumData); var predictionMax = predictionFunction.Predict(MayorAppelSampleMaxData); Console.WriteLine($"**********************************************************************"); Console.WriteLine($"Prediction for August 2019"); Console.WriteLine($"Predicted Positive decisions (Minimum Features): {predictionMin.ResPositive:0.####}, actual res_positive : 22313"); Console.WriteLine($"Predicted Positive decisions (Medium Features: {predictionMed.ResPositive:0.####}, actual res_positive : 22313"); Console.WriteLine($"Predicted Positive decisions (Maximum Features): {predictionMax.ResPositive:0.####}, actual res_positive : 22313"); Console.WriteLine($"**********************************************************************"); }
In diesem Beispiel haben wir die PredictionEngine-Klasse verwendet, mit der wir eine einzelne Vorhersage basierend auf dem trainierten Modell und dem Testdatensatz erhalten können.
Wir werden drei "Sonden" mit Daten zur Vorhersage erstellen.
Die erste mit einem Mindestdatensatz (nur ein Monat und ein Jahr), die zweite mit einem Durchschnitt und die dritte mit einem vollständigen Satz von Attributen.
Wir erhalten drei verschiedene Vorhersagen und drucken sie aus.
Wie Sie im Screenshot (Windows 10 x64) sehen können, verdirbt das Hinzufügen von Daten zur Anzahl der Anrufe pro 10.000 Einwohner in den Distrikten in diesem Fall nur alles, aber das Hinzufügen der restlichen Daten erhöht die Genauigkeit der Vorhersage geringfügig.

Unter Linux lässt sich Mint 19 auch in Mono wunderbar kompilieren.
Es stellt sich heraus, dass das Framework ziemlich plattformübergreifend ist.

Abschließend werde ich, wie versprochen, eine kleine subjektive vergleichende Analyse von ML.NET mit Accord.NET- und Python-Bibliotheken für maschinelles Lernen geben.
1. Es wird davon ausgegangen, dass die Entwickler versuchen, den Trends im Bereich des maschinellen Lernens zu entsprechen. In
Python mit einer Reihe von in Anaconda installierten Bibliotheken könnte diese Aufgabe natürlich kompakter gelöst werden und weniger Zeit für die Entwicklung aufwenden. Im Allgemeinen scheint mir der Ansatz zur Lösung von Problemen mit ML.NET jedoch freundlich zu Menschen zu sein, die es gewohnt sind, Probleme des maschinellen Lernens mit Python zu lösen.
2. Im Vergleich zu
Accord.NET Framework sieht ML.NET für eine Person, die maschinelles Lernen in Python ausprobiert hat, bequemer und vielversprechender aus. Ich erinnere mich, als ich vor zwei Jahren versuchte, etwas auf Accord.NET zu schreiben, fehlten mir für einige Klassen und Methoden furchtbar Erklärungen und Beispiele. In dieser Hinsicht schneidet Ml.NET mit Dokumentation etwas besser ab, obwohl das Framework viel jünger als Accord.NET ist. Ein weiterer wichtiger Faktor ist, dass sich ML.NET nach der Aktivität auf GitHub viel intensiver entwickelt als Accord.NET und über mehr russischsprachige Schulungsmaterialien verfügt.
Auf den ersten Blick sieht ML.NET daher wie ein praktisches Tool aus,
das Ihr Arsenal ergänzt, wenn Python oder R nicht verwendet werden können (z. B. bei der Arbeit mit in .NET ausgeführten CAD-APIs).
Ich wünsche Ihnen eine gute Arbeitswoche!