Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Изграждане на модел за машинно обучение със SQL Server, ML.NET и C#

Тази статия е част от инициативата The Fourth Annual C# Advent Calendar от Матю Д. Гроувс. Там ще намерите други полезни статии и уроци, публикувани ежедневно от членове на общността и експерти, така че не забравяйте да ги проверявате всеки ден.

ML.NET е безплатна, с отворен код и кросплатформена рамка за машинно обучение, предназначена за .NET разработчици. ML.NET ви позволява да използвате повторно всички знания, умения, код и библиотеки, които вече имате като .NET разработчик, за да можете лесно да интегрирате машинното обучение във вашите уеб, мобилни, настолни, игри и IoT приложения.

Можете да го приложите за сценарии за класификация, регресия, времеви серии и дори компютърно зрение (задълбочено обучение, класификация на изображения) с повече от 40 обучители (базирани на задачи алгоритми за ML) на ваше разположение.

От версия 1.4-preview нататък се поддържа класът DatabaseLoader, което означава, че сега можем да обучаваме и изграждаме модели директно срещу релационни бази данни, включително SQL Server, Oracle, PostgreSQL, SQLite и други.

За този пример ще изградя модел, който помага да се определи дали една жена може да развие диабет въз основа на исторически данни от други пациенти. Използвам набор от данни на Kaggle, който можете да изтеглите от тук.

След това създайте Пациент таблица за съхранение на информацията. Единственото изискване е да използвате истински тип данни за числови полета, тъй като ML.NET ще разбере само този тип. Друга възможност е да изпълните операция CAST, когато извличате данните и преобразувате полетата в реални в движение .

CREATE TABLE Patient(
  Id int identity(1,1) primary key,
  Pregnancies real not null,
  Glucose real not null,
  BloodPressure real not null,
  SkinThickness real not null,
  Insulin real not null,
  BMI real not null,
  DiabetesPedigreeFunction real not null,
  Age real not null,
  Output varchar(1) not null
)

И разбира се, трябва да вмъкнете всички данни от csv файла в таблицата .

Сега, нека напишем някакъв код!

Стъпка 1. Създайте нов проект на C# конзолно приложение:

Стъпка 2. Добавете следните пакети Nuget към вашия проект:

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

Стъпка 3. Добавете файл с настройки на приложението към вашия проект.

В този файл добавете ConnectionStrings колекция с DbConnection елемент. Стойността, разбира се, е низът за връзка с базата данни, където се намират вашите данни.

Например, ще се свържа с Azure SQL база данни :

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "ConnectionStrings": {
    "DbConnection": "Server=tcp:myserver.database.windows.net,1433;Initial Catalog=mydatabase;Persist Security Info=False;User ID=myadmin;Password=MYadm1n;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
  }
}

ЗАБЕЛЕЖКА:Задайте Копиране в изходна директория свойство за този файл, в противен случай той няма да бъде прочетен от програмата по-късно.

Стъпка 4. Добавете Модели папка към вашия проект. Вътре създайте нов клас с име Patient , който включва няколко свойства, които съответстват на структурата на таблицата. Освен това всяко свойство е украсено с LoadColumnAttribute с индекс, базиран на нула, който представлява колоната, която ще бъде картографирана от таблицата на базата данни.

using Microsoft.ML.Data;

namespace DiabetesPrediction.Models
{
    public class Patient
    {
        [LoadColumn(0)]
        public float Id { get; set; }

        [LoadColumn(1)]
        public float Pregnancies { get; set; }

        [LoadColumn(2)]
        public float Glucose { get; set; }

        [LoadColumn(3)]
        public float BloodPressure { get; set; }

        [LoadColumn(4)]
        public float SkinThickness { get; set; }

        [LoadColumn(5)]
        public float Insulin { get; set; }

        [LoadColumn(6)]
        public float BMI { get; set; }

        [LoadColumn(7)]
        public float DiabetesPedigreeFunction { get; set; }

        [LoadColumn(8)]
        public float Age { get; set; }

        [LoadColumn(9)]
        public float Output { get; set; }
    }
}

Стъпка 5. Добавете DiabetesMLPrediction клас, който наследява от Patient и включва допълнителни свойства. Това ще се използва след изграждане на модела за машинно обучение, за да се покажат прогнозирани данни:

using Microsoft.ML.Data;

namespace DiabetesPrediction.Models
{
    public class DiabetesMLPrediction : Patient
    {
        [ColumnName("PredictedLabel")]
        public float Prediction { get; set; }

        public float Probability { get; set; }

        public float[] Score { get; set; }
    }
}

Стъпка 6. В Program.cs файл:

а. Добавете тези пространства от имена:

using System;
using System.IO;
using System.Linq;
using System.Data.SqlClient;

using Microsoft.ML;
using Microsoft.ML.Data;
using Microsoft.Extensions.Configuration;

using DiabetesPrediction.Models;

б. Вътре в класа добавете GetDbConnection метод, който извлича низа за връзка от appsettings.json файл:

private static string GetDbConnection()
{
   var builder = new ConfigurationBuilder()
      .SetBasePath(Directory.GetCurrentDirectory())
      .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);

   return builder.Build().GetConnectionString("DbConnection");
}

° С. В основния метод:

  • Създайте екземпляр MLContext
  • Създайте екземпляр на DatabaseLoader въз основа на класа Patient
  • Извикайте метода GetDbConnection
  • Подгответе SQL оператор, който чете всички данни (и преобразува идентификатора в реално поле)
  • Подгответе екземпляр на DatabaseSource, който използва низа за връзка и израза.
var context = new MLContext();

var loader = context.Data.CreateDatabaseLoader<Patient>();

var connectionString = GetDbConnection();

var sqlCommand = "Select CAST(Id as REAL) as Id, Pregnancies, Glucose, BloodPressure, SkinThickness, Insulin, BMI, DiabetesPedigreeFunction, Age, CAST(Output as REAL) as Output From Patient";

var dbSource = new DatabaseSource(SqlClientFactory.Instance, connectionString, sqlCommand);
  • Заредете данните от таблицата в обект IDataView и ги разделете на два други IDataView, един за обучение и друг за оценка:
Console.WriteLine("Loading data from database...");
var data = loader.Load(dbSource);

var set = context.Data.TrainTestSplit(data, testFraction: 0.2);
var trainingData = set.TrainSet;
var testData = set.TestSet;
  • Създайте ITtransformer, като подготвите тръбопровод за обучение, който ще изгради модел на машинно обучение BinaryClassification. Посочете колоната, която ще бъде предвидена (Изход):
Console.WriteLine("Preparing training operations...");
var pipeline = context.Transforms
       .Conversion.MapValueToKey(outputColumnName: "Label", inputColumnName: "Output")
       .Append(context.Transforms.Concatenate("Features", "Pregnancies", "Glucose", "BloodPressure", "SkinThickness", "Insulin", "BMI", "DiabetesPedigreeFunction", "Age"))
       .Append(context.MulticlassClassification.Trainers.OneVersusAll(context.BinaryClassification.Trainers.AveragedPerceptron("Label", "Features", numberOfIterations: 10))
       .Append(context.Transforms.Conversion.MapKeyToValue("PredictedLabel")));
  • Сега разделете набора от данни за обучение на 10 пъти. 9 гънки се използват в тренировката, а останалата гънка се използва за тестване. Този процес се повтаря 10 пъти, като се променят наборите от данни за влака и теста. Този процес е известен като 10-кратно кръстосано валидиране (разбира се, можете да промените броя). Показват се и показатели:
Console.WriteLine("=============== Starting 10 fold cross validation ===============");
var crossValResults = context.MulticlassClassification.CrossValidate(data: trainingData, estimator: pipeline, numberOfFolds: 10, labelColumnName: "Label");
var metricsInMultipleFolds = crossValResults.Select(r => r.Metrics);
var microAccuracyValues = metricsInMultipleFolds.Select(m => m.MicroAccuracy);
var microAccuracyAverage = microAccuracyValues.Average();
var macroAccuracyValues = metricsInMultipleFolds.Select(m => m.MacroAccuracy);
var macroAccuracyAverage = macroAccuracyValues.Average();
var logLossValues = metricsInMultipleFolds.Select(m => 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($"*************************************************************************************************************");

  • След това можете да обучите модела, като извикате метода Fit:
Console.WriteLine($"Training process is starting. {DateTime.Now.ToLongTimeString()}");
var model = pipeline.Fit(trainingData);
Console.WriteLine($"Training process has finished. {DateTime.Now.ToLongTimeString()}");

Този процес отнема известно време.

  • След като моделът бъде създаден, можете да започнете да правите прогнози, като изградите PredictionEngine и предадете обект Patient на метода Predict:
var predictionEngine = context.Model.CreatePredictionEngine<Patient, DiabetesMLPrediction>(model);

var patient = new Patient()
{
  Age = 42,
  BloodPressure = 81,
  BMI = 30.1f,
  DiabetesPedigreeFunction = 0.987f,
  Glucose = 120,
  Insulin = 100,
  Pregnancies = 1,
  SkinThickness = 26,
  Id = 0,
  Output = 0
};

var prediction = predictionEngine.Predict(patient);
Console.WriteLine($"Diabetes? {prediction.Output} | Prediction: {(Convert.ToBoolean(prediction.Prediction) ? "Yes" : "No")} | Probability: {prediction.Probability} ");

  • Накрая можете да запазите модела, за да го използвате в други проекти (Web Api, Azure функции и др.)
Console.WriteLine("Saving the model");
context.Model.Save(model, trainingData.Schema, "MLModel.zip");

Стъпка 7. Стартирайте програмата, ще получите резултатите и ML модел, готов за някои прогнози:

Кодът е достъпен в GitHub.

Надявам се, че тази публикация в блога е била интересна и полезна за вас. Каня ви да посетите моя блог за още технически публикации относно Xamarin, Azure и екосистемата .NET . Пиша на испански =)

Благодаря за отделеното време и се насладете на останалите публикации на C# Advent Calendar!

Ще се видим следващия път,
Луис


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да се свържете с SQL Server по подразбиране инстанция и SQL Server наименувани екземпляри - SQL Server / TSQL Урок, част 2

  2. Часова част от поле DateTime в SQL

  3. Как да използвам SqlCommand за СЪЗДАВАНЕ НА БАЗА ДАННИ с параметризирано db име?

  4. Как да получите данни за последните 7 дни от текущата дата и час до последните 7 дни в sql сървър

  5. Добавете връзка с външен ключ между две бази данни