ML.NETのチュートリアルが親切になっていたのでやってみた。

#発端

Youtubeで「How to Port Desktop Applications to .NET Core 3.0」という動画を見ていたら、ML.NETがなんかいい感じになっているらしい。
https://youtu.be/upVQEUc_KwU?t=1560

久しぶりに気になって、ML.NETのサイトを訪れたらチュートリアルがとても簡素化されて綺麗になっていました。
https://dotnet.microsoft.com/learn/machinelearning-ai/ml-dotnet-get-started-tutorial/intro
ちゃんとdotnetを使ったチュートリアルになっている…(以前はVS2017使えとか言っていたのに…
Win/Linux/Mac向けにチュートリアルも別れている…(以前は環境ごとの説明なんてなかったのに…
しかもうまく動かなかったら`I ran into an issue`で問題を解決しろと‥(なんて慈悲深いサポート…

すばらしい…

ちなみに、古いチュートリアルのdocs.microsoftの記事は下記です。
https://docs.microsoft.com/ja-jp/dotnet/machine-learning/tutorials/

過去に古いチュートリアルを解読して今と同様のことをやったことがありますが、
本当に簡素化されて感動したので、この記事を読んだ人にも感動を伝えたいと思います。
ちなみに環境はMacOSでやります。

#やってみた
## Download and install
チュートリアルだと.NET SDK2.2.105をダウンロードしてインストールしろ言われます。
[.NET SDK2.2.105のダウンロードリンク](https://download.visualstudio.microsoft.com/download/pr/a4b4e61e-0905-4eb8-9d2c-9f5f390312e7/e1edac05922be70b51007739ed0db49e/dotnet-sdk-2.2.105-osx-gs-x64.pkg)

速攻脱線なんですが、私は.NET SDK３.０previewをインストールしました。
MacOS向けのインストーラーでポチポチすれば、問題なくインストールできます。
https://dotnet.microsoft.com/download/dotnet-core/3.0

## Create your app

プロジェクトを作ります。

```
dotnet new console -o myApp
cd myApp
```

dotnet初心者のために説明しておくと、上記はconsoleアプリケーション向けのテンプレートを使ってmyAppのプロジェクトを作成しています。
詳しくは、`dotnet new --help`で調べてください。

## Install ML.NET package
ML.NETのパッケージを追加します。

```
dotnet add package Microsoft.ML --version 0.11.0
```

##Download data set
学習用のデータセットをダウンロードします。
https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data
一つ注意したいのが、このデータセットは`iris-data.txt`という名前で保存してください。
(リンク先のファイル名も同じにしてくれれば、手間が減るのですが…)


##Write some code
`myApp/Program.cs`を下記の通り書き換えます。

```myApp/Program.cs
using Microsoft.Data.DataView;
using Microsoft.ML;
using Microsoft.ML.Data;
using System;

// CS0649 compiler warning is disabled because some fields are only 
// assigned to dynamically by ML.NET at runtime
#pragma warning disable CS0649

namespace myApp
{
    class Program
    {
        // STEP 1: Define your data structures
        // IrisData is used to provide training data, and as
        // input for prediction operations
        // - First 4 properties are inputs/features used to predict the label
        // - Label is what you are predicting, and is only set when training
        public class IrisData
        {
            [LoadColumn(0)]
            public float SepalLength;

            [LoadColumn(1)]
            public float SepalWidth;

            [LoadColumn(2)]
            public float PetalLength;

            [LoadColumn(3)]
            public float PetalWidth;

            [LoadColumn(4)]
            public string Label;
        }

        // IrisPrediction is the result returned from prediction operations
        public class IrisPrediction
        {
            [ColumnName("PredictedLabel")]
            public string PredictedLabels;
        }

        static void Main(string[] args)
        {
            // STEP 2: Create a ML.NET environment  
            MLContext mlContext = new MLContext();

            // If working in Visual Studio, make sure the 'Copy to Output Directory'
            // property of iris-data.txt is set to 'Copy always'
            IDataView trainingDataView = mlContext.Data.LoadFromTextFile<IrisData>(path: "iris-data.txt", hasHeader: false, separatorChar: ',');

            // STEP 3: Transform your data and add a learner
            // Assign numeric values to text in the "Label" column, because only
            // numbers can be processed during model training.
            // Add a learning algorithm to the pipeline. e.g.(What type of iris is this?)
            // Convert the Label back into original text (after converting to number in step 3)
            var pipeline = mlContext.Transforms.Conversion.MapValueToKey("Label")
                .Append(mlContext.Transforms.Concatenate("Features", "SepalLength", "SepalWidth", "PetalLength", "PetalWidth"))
                .AppendCacheCheckpoint(mlContext)
                .Append(mlContext.MulticlassClassification.Trainers.StochasticDualCoordinateAscent(labelColumnName: "Label", featureColumnName: "Features"))
                .Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel"));

            // STEP 4: Train your model based on the data set  
            var model = pipeline.Fit(trainingDataView);

            // STEP 5: Use your model to make a prediction
            // You can change these numbers to test different predictions
            var prediction = model.CreatePredictionEngine<IrisData, IrisPrediction>(mlContext).Predict(
                new IrisData()
                {
                    SepalLength = 3.3f,
                    SepalWidth = 1.6f,
                    PetalLength = 0.2f,
                    PetalWidth = 5.1f,
                });

            Console.WriteLine($"Predicted flower type is: {prediction.PredictedLabels}");

            Console.WriteLine("Press any key to exit....");
            Console.ReadLine();
        }
    }
}
```

##dotnet run
では動かしましょう！！

```
$ dotnet run
Predicted flower type is: Iris-virginica
Press any key to exit....
```

どうやら、この学習データでは以下のIrisはIris-virginicaに区分されるようです。
SepalLength = 3.3f,
SepalWidth = 1.6f,
PetalLength = 0.2f,
PetalWidth = 5.1f,


##おわりに
ちなみに2019/03/16時点ではこのチュートリアルが終わると、古いチュートリアルに飛ばされてしまいます…
他のチュートリアルも簡素化して拡散したいですね！！
というわけで、みんなもML.NETで手軽に機械学習を始めちゃおう！！(雑な締め方)