sql >> Databasteknik >  >> RDS >> Sqlserver

Bygga en maskininlärningsmodell med SQL Server, ML.NET och C#

Den här artikeln är en del av initiativet The Fourth Annual C# Advent Calendar av Matthew D. Groves. Du hittar andra användbara artiklar och självstudiekurser som publiceras dagligen av communitymedlemmar och experter där, så se till att kolla in det varje dag.

ML.NET är ett gratis, öppen källkod och plattformsoberoende ramverk för maskininlärning designat för .NET-utvecklare. ML.NET låter dig återanvända all kunskap, färdigheter, kod och bibliotek du redan har som .NET-utvecklare så att du enkelt kan integrera maskininlärning i dina webb-, mobil-, dator-, spel- och IoT-appar.

Du kan använda det för scenarier för klassificering, regression, tidsserier och till och med datorseende (djupinlärning, bildklassificering) med mer än 40 tränare (uppgiftsbaserade ML-algoritmer) till ditt förfogande.

Från version 1.4-förhandsvisning och framåt stöds DatabaseLoader-klassen, vilket innebär att vi nu kan träna och bygga modeller direkt mot relationsdatabaser, inklusive SQL Server, Oracle, PostgreSQL, SQLite och andra.

För det här exemplet ska jag bygga en modell som hjälper till att identifiera om en kvinna kan utveckla diabetes baserat på historiska data från andra patienter. Jag använder en Kaggle-datauppsättning som du kan ladda ner härifrån.

Efter det skapar du en patient tabell för att lagra informationen. Det enda kravet är att använda en riktig datatyp för numeriska fält, eftersom ML.NET bara förstår denna typ. Ett annat alternativ är att utföra en CAST-operation när du hämtar data och konverterar fälten till riktiga i farten .

SKAPA TABELL Patient( Id int identitet(1,1) primärnyckel, Graviditeter verkligt inte null, Glukos verkligt inte null, Blodtryck verkligt inte null, SkinThickness verkligt inte null, Insulin verkligt inte null, BMI verkligt inte null , DiabetesPedigreeFunction real not null, Age real not null, Output varchar(1) not null) 

Och naturligtvis måste du infoga all data från csv-filen i tabellen .

Nu, låt oss skriva lite kod!

Steg 1. Skapa ett nytt C# Console-applikationsprojekt:

Steg 2. Lägg till följande Nuget-paket till ditt projekt:

  • Microsoft.ML
  • System.Data.SqlClient
  • Microsoft.Extensions.Configuration
  • Microsoft.Extensions.Configuration.Json
  • Microsoft.Extensions.Configuration.FileExtensions

Steg 3. Lägg till en appinställningsfil till ditt projekt.

Lägg till en ConnectionStrings i den här filen samling med en DbConnection element. Värdet är naturligtvis anslutningssträngen till databasen där din data finns.

Till exempel kommer jag att ansluta till en Azure SQL-databas :

{ "Logging":{ "LogLevel":{ "Default":"Warning" } }, "ConnectionStrings":{ "DbConnection":"Server=tcp:myserver.database.windows.net,1433;Initial Catalog=mindatabas;Persist Security Info=False;Användar-ID=myadmin;Password=MYadm1n;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Anslutningstid=30;" }} 

OBS:Ställ in Kopiera till utdatakatalog egenskap för denna fil, annars kommer den inte att läsas av programmet senare.

Steg 4. Lägg till en Modeller mapp till ditt projekt. Skapa en ny klass inuti som heter Patient , som inkluderar flera egenskaper som matchar tabellstrukturen. Varje fastighet är dessutom dekorerad med LoadColumnAttribute med ett nollbaserat index som representerar kolumnen som kommer att mappas från databastabellen.

med Microsoft.ML.Data;namespace DiabetesPrediction.Models{ public class Patient { [LoadColumn(0)] public float Id { get; uppsättning; } [LoadColumn(1)] public float Pregnancies { get; uppsättning; } [LoadColumn(2)] public float Glucose { get; uppsättning; } [LoadColumn(3)] public float BloodPressure { get; uppsättning; } [LoadColumn(4)] public float SkinThickness { get; uppsättning; } [LoadColumn(5)] public float Insulin { get; uppsättning; } [LoadColumn(6)] public float BMI { get; uppsättning; } [LoadColumn(7)] public float DiabetesPedigreeFunction { get; uppsättning; } [LoadColumn(8)] public float Age { get; uppsättning; } [LoadColumn(9)] public float Output { get; uppsättning; } }} 

Steg 5. Lägg till en DiabetesMLPrediction klass som ärver från Patient och inkluderar ytterligare egenskaper. Detta kommer att användas efter att maskininlärningsmodellen har byggts för att visa förutspådd data:

med Microsoft.ML.Data;namespace DiabetesPrediction.Models{ public class DiabetesMLPrediction :Patient { [ColumnName("PredictedLabel")] public float Prediction { get; uppsättning; } public float Sannolikhet { get; uppsättning; } public float[] Betyg { get; uppsättning; } }} 

Steg 6. I Program.cs fil:

a. Lägg till dessa namnområden:

använda System;använda System.IO;använda System.Linq;använda System.Data.SqlClient;använda Microsoft.ML;använda Microsoft.ML.Data;använda Microsoft.Extensions.Configuration;använda DiabetesPrediction.Models;  

b. Inuti klassen lägger du till en GetDbConnection metod som extraherar anslutningssträngen från appsettings.json fil:

privat statisk sträng GetDbConnection(){ var builder =new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", valfritt:true, reloadOnChange:true); return builder.Build().GetConnectionString("DbConnection");} 

c. I huvudmetoden:

  • Skapa en MLContext-instans
  • Skapa en DatabaseLoader-instans baserat på patientklassen
  • Anropa GetDbConnection-metoden
  • Förbered en SQL-sats som läser all data (och konverterar id:t till ett riktigt fält)
  • Förbered en DatabaseSource-instans som använder anslutningssträngen och satsen.
var context =new MLContext();var loader =context.Data.CreateDatabaseLoader();var connectionString =GetDbConnection();var sqlCommand ="Välj CAST(Id som REAL) som Id, Graviditeter , Glukos, Blodtryck, Hudtjocklek, Insulin, BMI, DiabetesPedigreeFunction, Age, CAST(Output as REAL) as Output From Patient";var dbSource =new DatabaseSource(SqlClientFactory.Instance, connectionString, sqlCommand); 
  • Läs in data från tabellen till ett IDataView-objekt och dela upp den i två andra IDataViews, en för utbildning och en annan för utvärdering:
Console.WriteLine("Laddar data från databasen...");var data =loader.Load(dbSource);var set =context.Data.TrainTestSplit(data, testFraction:0.2);var trainingData =set.TrainSet;var testData =set.TestSet; 
  • Skapa en ITransformer genom att förbereda en utbildningspipeline som kommer att bygga en maskininlärningsmodell för BinaryClassification. Ange kolumnen som kommer att förutsägas (Utdata):
Console.WriteLine("Förbereder träningsoperationer...");var pipeline =context.Transforms .Conversion.MapValueToKey(outputColumnName:"Etikett", inputColumnName:"Output") .Append(context.Transforms. Concatenate("Funktioner", "Graviditeter", "Glukos", "Blodtryck", "Hudtjocklek", "Insulin", "BMI", "DiabetesPedigreeFunction", "Ålder")) .Append(context.MulticlassClassification.Trainers.OneVersusAll( context.BinaryClassification.Trainers.AveragedPerceptron("Etikett", "Features", numberOfIterations:10)) .Append(context.Transforms.Conversion.MapKeyToValue("PredictedLabel"))); 
  • Dela nu träningsdatauppsättningen i 10 gånger. 9 veck används vid träning och resterande veck används för testning. Denna process upprepas 10 gånger för att byta tåg och testdatauppsättningar. Denna process är känd som 10-faldig korsvalidering (naturligtvis kan du ändra numret). Mätvärden visas också:
Console.WriteLine("================Startar 10-faldig korsvalidering ================");var crossValResults =context.MulticlassClassification.CrossValidate(data:trainingData, estimator:pipeline, numberOfFolds:10, labelColumnName:"Etikett");var metricsInMultipleFolds =crossValResults.Select(r => r.Metrics => r.Metrics => r.Metrics => r.Metrics => r.Metrics => r.Metrics => => m.MicroAccuracy);var microAccuracyAverage =microAccuracyValues.Average();var macroAccuracyValues ​​=metricsInMultipleFolds.Select(m => m.MacroAccuracy);var macroAccuracyAverage =macroAccuracyValues.Average();alu logMultipleFolds();alu logMultipleFolds m.LogLoss);var logLossAverage =logLossValues.Average();var logLossReductionValues ​​=metricsInMultipleFolds.Select(m => m.LogLossReduction);var logLossReductionAverage =logLossReductionValues.Average(); Console.WriteLine($"************************************************** ************************************************** ***************");Console.WriteLine($"* Metrics Multi-class Classification model ");Console.WriteLine($"*--------- -------------------------------------------------- ----------------------------------------------------------" );Console.WriteLine($"* Average MicroAccuracy:{microAccuracyAverage:0.###} ");Console.WriteLine($"* Average MacroAccuracy:{macroAccuracyAverage:0.###} ");Console.WriteLine( $"* Average LogLoss:{logLossAverage:#.###} ");Console.WriteLine($"* Average LogLossReduction:{logLossReductionAverage:#.###} ");Console.WriteLine($"**** ************************************************** ************************************************** *****"); 
  • Närnäst kan du träna modellen genom att anropa Fit-metoden:
Console.WriteLine($"Utbildningsprocessen startar. {DateTime.Now.ToLongTimeString()}");var model =pipeline.Fit(trainingData);Console.WriteLine($"Utbildningsprocessen har slutförts. {DateTime.Now.ToLongTimeString()}"); 

Denna process tar lite tid.

  • När modellen har skapats kan du börja göra förutsägelser genom att bygga en PredictionEngine och skicka ett patientobjekt till Predict-metoden:
(modell);var patient =new Patient(){ Ålder =42, Blodtryck =81, BMI =30,1f, DiabetesPedigreeFunction =0,987f, GlucoseFunction =0,987f =120, Insulin =100, Graviditeter =1, SkinThickness =26, Id =0, Output =0};var prediction =predictionEngine.Predict(patient);Console.WriteLine($"Diabetes? {prediction.Output} | Prognos:{(Convert.ToBoolean(prediction.Prediction) ? "Yes" :"No")} | Sannolikhet:{prediction.Probability} ");
  • Slutligen kan du spara modellen för att använda den i andra projekt (Web Api, Azure Functions, etc.)
Console.WriteLine("Spara modellen");context.Model.Save(model, trainingData.Schema, "MLModel.zip"); 

Steg 7. Kör programmet, du får resultaten och en ML-modell redo för några förutsägelser:

Koden är tillgänglig på GitHub.

Jag hoppas att det här blogginlägget var intressant och användbart för dig. Jag inbjuder dig att besöka min blogg för fler tekniska inlägg om Xamarin, Azure och .NET-ekosystemet . Jag skriver på spanska =)

Tack för din tid och njut av resten av C# Advent Calendar-publikationerna!

Vi ses nästa gång,
Luis


  1. Hur kan jag veta om ett SQL-undantag kastades på grund av brott mot främmande nyckel?

  2. SQLite ALTER TABELL

  3. SQL Server 2008 - ordna efter strängar med nummer numeriskt

  4. Logga frågetid i SQLite på Android