ABONAMENTE VIDEO REDACȚIA
RO
EN
×
▼ LISTĂ EDIȚII ▼
Numărul 97
Abonament PDF

Este Microsoft ML.NET încă un framework de machine learning?

Daniel Costea
Senior Software Developer @ EU Agency
PROGRAMARE

În lumea data science și a machine learning, limbajul de programare Python face regulile. În plus, frameworkurile existente- TensorFlow, Keras, Torch, CoreML, CNTK- nu sunt ușor de integrat cu proiectele .NET. Frameworkul ML.NET este bazat pe .NET Core și .NET Standard (moștenind capacitatea de a rula pe Linux, macOS și Windows), fiind conceput ca o platformă extensibilă. Așadar se pot consuma modele create cu alte frameworkuri populare cum sunt: TensorFlow, ONNX , CNTK, Infer.NET. Microsoft ML.NET este mai mult decât machine learning, deoarece include deep learning și vă oferă acces la o mare varietate de scenarii de deep learning, cum ar fi clasificarea de imagini sau detectarea de obiecte.

Este Microsoft ML.NET ușor de utilizat?

Utilizatorii Python au la dispoziție mediul interactiv Jupyter Notebook, care este un instrument excelent în care puteți integra text (compatibil markdown), cod și diagrame.

Până de curând, ML.NET nu avea un instrument REPL (read-eval-print-loop) pentru a lucra interactiv cu cod și date, dar acum, dezvoltatorii .NET pot rula scenarii interactive de machine learning (și nu numai!), cu Jupyter Notebook folosind C #, F # sau Powershell într-un browser web.

Instalarea Jupyter Notebook

Există mai multe moduri de a folosi Jupyter Notebook cu .NET. Dacă doriți să rulați Notebook Jupyter local, trebuie să instalați Jupyter Notebook folosind Anaconda (distribuție de Python pentru data science). Dacă ați instalat cu succes Jupyter Notebook, îl puteți lansa din Windows pentru a deschide / crea un notebook.

Definirea unui scenariu practic

Să presupunem că avem un sistem capabil să măsoare temperatura, luminozitatea, radiația infraroșie și distanța până la o sursă de energie (sursa poate fi o lanternă, o brichetă, lumina ambientală sau o lanternă cu radiație infraroșie). Măsurătorile se fac cu ajutorul unor senzori conectați la un dispozitiv IoT (Raspberry Pi 3) și avem un set de date format din câteva sute de observații. Aceste observații sunt etichetate, ceea ce înseamnă că avem sursa fiecărei observații din setul de date. Cu alte cuvinte, vrem să prezicem sursa pentru fiecare nouă observație.

Să analizăm un document Jupyter Notebook

Una dintre cele mai importante caracteristici ale Jupyter Notebook, XPlot.Plotly, este o bibliotecă excelentă de vizualizare a datelor, responsabilă de randarea diagramelor.

Să presupunem că am inclus dependințele, am inițializat contextul ML și am încărcat seturile de date pentru antrenarea modelului (training) și pentru testarea modelului (testing).

#r "nuget:Microsoft.ML,1.4.0"
using Microsoft.ML;
using Microsoft.ML.Data;
using XPlot.Plotly;

private static readonly MLContext 
 mlContext = new MLContext(seed: 2020);

Comanda "display"

Într-un document Jupyter Notebook putem folosi Console.WriteLine pentru a afișa date, dar comanda display este net superioară, deoarece este capabilă să afișeze text, html, svn și diagrame.

var features = mlContext.Data
.CreateEnumerable(trainingData, true);

display(features.Take(10));

Bineînțeles că nu înțelegem foarte mult datele în forma lor tabulară, dar Jupyter Notebook aduce câteva tipuri de diagrame eficiente prin intermediul bibliotecii XPlot.Plotly, care este capabilă să agrege datele într-un mod mult mai coerent.

Segmentarea Box Plot

Dacă dorim să aflăm mai multe informații despre datele noastre, putem folosi un alt tip de diagramă, segmentarea box plot.

var featuresDiagram = Chart.Plot(new[] {
 new Graph.Box 
  { y = featuresTemperatures, name = "Temperature" },
 new Graph.Box 
  { y = featuresLuminosities, name = "Luminosity" },
 new Graph.Box 
  { y = featuresInfrareds, name = "Infrared" },
 new Graph.Box 
  { y = featuresDistances, name = "Distance" }
});
display(featuresDiagram);

Privind diagrama putem extrage informații valoroase, cum sunt:

Mai târziu, putem utiliza aceste informații pentru a îmbunătăți exactitatea modelului, dar acum există un alt lucru care ne atrage atenția: unele măsurători (features), cum ar fi Distanța, par să cântărească "mai greu" decât celelalte. Să vedem ce se întâmplă dacă încercăm să le aducem pe toate la aceeași scară sau, cu alte cuvinte, să le normalizăm.

var preprocessingPipeline = mlContext.
  Transforms.Conversion.MapValueToKey("Label")
    .Append(mlContext.Transforms
      .CustomMapping(parseDateTime, null))

    .Append(mlContext.Transforms
      .Concatenate("Features", featureColumns))

    .Append(mlContext.Transforms
      .NormalizeMinMax("Features", "Features"));

Măsurătorile (features) sunt acum normalizate, iar influența lor asupra modelului care va fi antrenat este echilibrată.

Matricea de Corelație

Privind datele, se desprinde o altă întrebare: Chiar avem nevoie de toate măsurătorile? Cel mai probabil, unele sunt mai puțin importante decât celelalte. Matricea de corelație este un instrument capabil să măsoare corelația dintre coloane sau măsurători, două câte două, după cum urmează:

#r "nuget:MathNet.Numerics, 4.9.0"
using MathNet.Numerics.Statistics;

var correlationMatrixHeatmap = Chart.Plot(
  new Graph.Heatmap { 
    x = featureColumns, 
    y = featureColumns.Reverse(), 
    z = z, 
    zmin = -1,
    zmax = 1 });

display(correlationMatrixHeatmap);

Două măsurători puternic corelate nu transmit informații suplimentare, de aceea una dintre ele poate fi eliminată (nu este cazul aici!).

De exemplu, caracteristicile noastre cele mai corelate sunt Distanța și Infraroșu (0,48), iar Temperatura pare să fie cea mai "necorelată" în comparație cu celelalte.

Pregătirea pipeline-ului de preprocesare

Prin convenție, ML.NET caută în pipeline coloana "Features" (input) și coloana "Label" (output). Însă, dacă avem aceste coloane, nu mai trebuie să le furnizăm, altfel se impune să facem unele transformări pe date pentru a obține și expune aceste coloane. În plus, dacă folosim pentru construirea modelului o clasificare binară sau multiplă, trebuie să transformăm coloana "Label" într-un număr folosind MapValueToKey (pentru că machine learning lucrează intern doar cu numere!).

var featureColumns = new string[] { 
  "Temperature", 
  "Luminosity", 
  "Infrared", 
  "Distance" };
var preprocessingPipeline = 
  mlContext.Transforms.Conversion
   .MapValueToKey("Label")
   .Append(mlContext.Transforms
   .Concatenate("Features", featureColumns));

În cele mai multe cazuri, avem mai multe coloane (măsurători) relevante pe care vom dori să le concatenăm într-una singură, numită "Features".

Construirea și antrenarea modelului

În sfârșit, avem tot ce ne trebuie să construim modelul și să îl antrenăm, folosind unul dintre algoritmii de multi-clasificare, Stochastic Dual Coordinate Ascent (SDCA). Dar am putea dori să încercăm și alți algoritmi.

var modelPipeline = preprocessingPipeline
 .Append(mlContext.MulticlassClassification.Trainers
   .SdcaNonCalibrated("Label", "Features"));

var postprocessingPipeline = modelPipeline
 .Append(mlContext.Transforms.Conversion
    .MapKeyToValue("PredictedLabel"));

var model = postprocessingPipeline.Fit(trainingData);

Matricea de confuzie

După ce am obținut un model, primul lucru de care trebuie să ne preocupăm este performanța modelului, iar Matricea de confuzie este o măsurare excelentă a performanței pentru machine learning în cazul clasificării.

Folosind setul de date de testare putem face predicții și putem compara rezultatele preconizate cu rezultatele reale. În diagrama următoare remarcăm cum clasa Infraroșu a fost prezisă corect (ca Infraroșu) de 40 de ori, a fost prezisă incorect ca FlashLight de 5 ori, și incorect ca Lighter o singură dată, rezultând o rată de precizie de 0,8696.

Importanța caracteristicilor de permutare

Un alt instrument util este diagrama PFI (Permutation Feature Importance). PFI calculează scorul de importanță pentru fiecare dintre coloane (măsurători) prin permutări aleatorii ale funcției, rezultând că unele caracteristici sunt mai mult sau mai puțin importante.

var pfi = mlContext.MulticlassClassification
  .PermutationFeatureImportance(
    linearPredictor, transformedData, 
    permutationCount: 3);

var sortedMetrics = 
  pfi.Select((metrics, index) => new { 
    index, metrics.MacroAccuracy })
    .OrderBy(feature => Math.Abs(
     feature.MacroAccuracy.Mean))
     .Select(feature => feature.MacroAccuracy.Mean);

var pfiDiagram = Chart.Plot(new[] {
    new Graph.Bar { x = sortedMetrics, 
     y = featureColumns.Reverse(), 
     orientation = "h", 
     name = "Permutation Feature Importance" 
  }
});
display(pfiDiagram);

În diagrama noastră, Distanța pare să aibă un scor foarte mic. Excluderea acestei măsurători de la construirea modelului nu va afecta semnificativ performanța modelului nostru.

Concluzie

Avem, în sfârșit, o platformă și avem un set de instrumente cu care să îmbunătățim performanța modelului nostru într-un mod iterativ. O dată ce suntem mulțumiți de precizia modelului, putem să mutăm secvența de cod care conține pipeline-ul în proiectul nostru și putem începe să facem predicții pe date noi de intrare. Dacă doriți să experimentați cu Jupyter Notebook, îl puteți găsi la adresa:

https://github.com/dcostea/DotnetJupyterNotebooks

VIDEO: NUMĂRULUI 100

Sponsori

  • comply advantage
  • ntt data
  • Betfair
  • Accenture
  • Siemens
  • Bosch
  • FlowTraders
  • MHP
  • Connatix
  • Cognizant Softvision
  • BoatyardX
  • Colors in projects