sql >> データベース >  >> RDS >> Sqlserver

SQL Server、ML.NET、C#を使用した機械学習モデルの構築

    この記事は、Matthew D. Grovesによる第4回C#アドベントカレンダーイニシアチブの一部です。コミュニティのメンバーや専門家によって毎日公開されている他の役立つ記事やチュートリアルもありますので、毎日チェックしてください。

    ML.NETは、.NET開発者向けに設計された、無料のオープンソースのクロスプラットフォームの機械学習フレームワークです。 ML.NETを使用すると、.NET開発者としてすでに持っているすべての知識、スキル、コード、ライブラリを再利用できるため、機械学習をウェブ、モバイル、デスクトップ、ゲーム、IoTアプリに簡単に統合できます。

    分類、回帰、時系列、さらには40人以上のトレーナー(タスクベースのMLアルゴリズム)を自由に使用できるコンピュータービジョン(深層学習、画像分類)シナリオに適用できます。

    バージョン1.4-プレビュー以降では、DatabaseLoaderクラスがサポートされています。つまり、SQL Server、Oracle、PostgreSQL、SQLiteなどのリレーショナルデータベースに対して直接モデルをトレーニングおよび構築できるようになりました。

    この例では、他の患者の履歴データに基づいて、女性が糖尿病を発症する可能性があるかどうかを特定するのに役立つモデルを構築します。ここからダウンロードできるKaggleデータセットを使用しています。

    その後、患者を作成します 情報を格納するテーブル。唯一の要件は、本物のを使用することです ML.NETはこのタイプのみを理解するため、数値フィールドのデータ型。もう1つのオプションは、データを取得してフィールドを実際のオンザフライに変換するときに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を使用したコレクション エレメント。もちろん、値はデータが存在するデータベースへの接続文字列です。

    たとえば、AzureSQLデータベースに接続します :

    {
      "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。 モデルを追加します プロジェクトへのフォルダ。内部で、患者という名前の新しいクラスを作成します 、テーブル構造に一致するいくつかのプロパティが含まれています。また、各プロパティは 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内 ファイル:

    a。これらの名前名を追加します。

    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;
    

    b。クラス内に、 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");
    }
    

    c。メインメソッドの場合:

    • MLContextインスタンスを作成する
    • Patientクラスに基づいてDatabaseLoaderインスタンスを作成します
    • GetDbConnectionメソッドを呼び出します
    • すべてのデータを読み取る(そしてIDを実際のフィールドに変換する)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オブジェクトにデータをロードし、それを他の2つのIDataViewに分割します。1つはトレーニング用で、もう1つは評価用です。
    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;
    
    • BinaryClassification機械学習モデルを構築するトレーニングパイプラインを準備して、ITransformerを作成します。予測される列を指定します(出力):
    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 Functionsなど)で使用できます。
    Console.WriteLine("Saving the model");
    context.Model.Save(model, trainingData.Schema, "MLModel.zip");
    

    ステップ7。 プログラムを実行すると、結果といくつかの予測に備えたMLモデルが得られます。

    コードはGitHubで入手できます。

    このブログ投稿がおもしろくて、お役に立てば幸いです。 Xamarin、Azure、および.NETエコシステムに関する技術的な投稿については、私のブログにアクセスしてください。 。私はスペイン語で書いています=)

    お時間をいただきありがとうございます。残りのC#アドベントカレンダーの出版物をお楽しみください!

    またね、
    ルイス


    1. SET TEXTSIZEがSQLServerで機能しませんか?これをチェックして。

    2. OracleのLEAST()関数

    3. 関数は、複数の列ではなく、単一の列として複数の列を返します

    4. オペレーター