見出し画像

ML.NETで機械学習①-MNISTの学習-

こんにちは。
C#erとして機械学習をC#で行えるようなライブラリはないかなと探していると、Microsoftが「ML.NET」というよさげなライブラリをリリースしていたので、それを使ってみることにしました。

ML.NETとは?

ML.NETとは.NETアプリケーションに機械学習の機能を追加するためのライブラリになります。

C#で機械学習が行えるようになると、ゲームやモバイルアプリにも機械学習を構築することができますし、リッチなUIを開発することも他の言語に比べて容易にできます。
個人的にC#で機械学習を行う一番のメリットはセキュリティ管理が厳しい製造業の工場にあると思っています。
例えば、クラウドにデータをあげることができないような現場とか、余計なソフトをインストールすることができない環境(Windows PCにPythonを入れることが禁止されていたりなど)にAIの学習環境を構築するとなると、開発手段の選択肢もかなり限られてしまいます。
商用ソフトとして見栄えよく開発するとなると、C#を使いたいなと思う場面も多々あるはずです(実際、僕もそうでした)。
なので、「ML.NET」はそういった現場に素早く機械学習を取り入れるための有用な手段になり得ると考えています。

MNISTの学習

「ML.NET」をプログラミングしていくうえで、まずは手始めにMNISTの学習から行っていきたいと思います。
MNISTを学習するサンプルプログラムが公式GitHubに公開されているのでそれをもとにプログラミングしていきます。

学習用のデータセットもGitHubからダウンロードすることができます。
データセットをダウンロードすると、中に「optdigits-train.csv」と「optdigits-val.csv」という2つのCSVファイルが入っています。trainと付いているほうがAIに学習させるデータで、valと付いているほうがAIの性能を検証するためのデータになります。
32x32ピクセルの手書き文字の画像を4x4ピクセルごとに領域分割し、分割した領域ごとに輝度値が0でないピクセル数をカウントします。そうやってカウントされた64個のデータと手書き文字の正解ラベル1個をセットにした65個のデータがCSVファイルの1行のデータになります。

自分のプロジェクトに「ML.NET」をインストールする場合は、NuGetパッケージから「Micorosoft.ML」というパッケージをインストールしてください。

画像1

CSVファイルを読み込むためには以下のように記述します。

// STEP 1: Common data loading configuration
var trainData = mlContext.Data.LoadFromTextFile(path: TrainDataPath,
   columns: new[]
     {
        new TextLoader.Column(nameof(InputData.PixelValues), DataKind.Single, 0, 63),
          new TextLoader.Column("Number", DataKind.Single, 64)
     },
     hasHeader: false,
     separatorChar: ','
     );

プログラムの中では、CSVファイルの0~63列目までをピクセルデータとして、64列目を正解ラベルとして読み込んでいます。列は0インデックスで始まることに気を付けてください。また、ヘッダーのありなしや、データを分割する上での文字列(ここではカンマを指定)などの設定も行えます。

また、データをML.NETで扱えるように変換し、学習する際のアルゴリズムを選択します。

// STEP 2: Common data process configuration with pipeline data transformations
// Use in-memory cache for small/medium datasets to lower training time. Do NOT use it (remove .AppendCacheCheckpoint()) when handling very large datasets.
var dataProcessPipeline = mlContext.Transforms.Conversion.MapValueToKey("Label", "Number", keyOrdinality: ValueToKeyMappingEstimator.KeyOrdinality.ByValue).
   Append(mlContext.Transforms.Concatenate("Features", nameof(InputData.PixelValues)).AppendCacheCheckpoint(mlContext));

// STEP 3: Set the training algorithm, then create and config the modelBuilder
var trainer = mlContext.MulticlassClassification.Trainers.SdcaMaximumEntropy(labelColumnName: "Label", featureColumnName: "Features");
var trainingPipeline = dataProcessPipeline.Append(trainer).Append(mlContext.Transforms.Conversion.MapKeyToValue("Number", "Label"));

サンプルプログラムで選択しているアルゴリズムはSDCA(StochasticDualCoordinateAscent)となっています。

選択したアルゴリズムでデータを学習する際は、生成した「trainingPipeline」に対してFit関数を呼び出します。また、学習したモデルに対して、評価を行いたい場合には、MulticlassClassification.Evaluate関数を呼び出します。

// STEP 4: Train the model fitting to the DataSet            
ITransformer trainedModel = trainingPipeline.Fit(trainData);

var predictions = trainedModel.Transform(testData);
var metrics = mlContext.MulticlassClassification.Evaluate(data:predictions, labelColumnName:"Number", scoreColumnName:"Score");

Common.ConsoleHelper.PrintMultiClassClassificationMetrics(trainer.ToString(), metrics);

Evaluateを実行すると、混合行列の適合率や再現率、損失関数のLossの値などが自動的に計算されて戻り値が返ってきます。自動的に計算してくれるのはとても便利です。

実際にプログラムを実行してみると、コンソールには以下のような内容が出力されます。

画像2

正解率やLoss値が出力されているのがわかります。
データの読み込みから学習までとても簡単に行うことができました。

まとめ

ML.NETは自分でアルゴリズムを構築する必要なく、簡単に機械学習を実行することができます。
複雑な処理を行うのには向かないかもしれませんが、今回扱った手書き文字の分類以外にも異常検出やクラスタリング、時系列予測といったタスクを行うこともできるので、汎用性は高いと言えるでしょう。
今も開発が行われているので、今後の開発にも期待したいと思います。

この記事が気に入ったらサポートをしてみませんか?