UnityとF#で機械学習①  k-nearest neighbour algorithm

#はじめに

F#と機械学習に関する本は、日本語のものは見当たらないので、英語の本で勉強することになります。いくつかある中で、最近発刊された"F# for Machine Learning Essentials" (Sudipta Mukherjee 著)は手軽に勉強できそうな感じだったので、ちょっと見て見ることにしました（以下では「原著」と呼ぶ）。ここでは、第1章に出てくる k-nearest neighbour algorithmをUnityで実行してみました。

#扱う問題

[こちら](https://www.kaggle.com/c/digit-recognizer)にある手書き文字のデータを使い、文字認識を行います。各手書き文字は28*28の行列を一列に広げたものとして表現され、入力するデータと一番近いデータをk-nearest neighbour algorithm ([参考資料](https://ja.wikipedia.org/wiki/K%E8%BF%91%E5%82%8D%E6%B3%95))で抽出します。


#Unityでの実行

UnityでのF#の使い方は、[こちらの過去記事](http://qiita.com/yanosen_jp/items/74fe2b279aa2ff51858a)を参考にしてください。

こちらの記事でも書いた通り、UnityからF#のライブラリを呼び出すにはnamespaceを定義しますが、namespaceは直接に値や関数を持てないので、moduleを指定する必要があります。原著のサンプルコードではmoduleは指定されてないので、こちらで加えます。

また、Unityでは、Monoのバージョンの関係で F# 3.0しか使えないので、F# 4.0の文法を使っている部分は修正が必要です。

 

#Unity用の修正版

```fsharp:Library1.fs
namespace DigitRecognition //追加
open System.IO
open System

module DigitRecognitionEntry = //追加

    type Entry = {Label: string; Values: int list } 

    let distance (values1: int list, values2: int list) = 
　　＊＊省略　原著参照＊＊


    let loadValues (filename: string ) = 
　　＊＊省略　原著参照＊＊

    let kNN (entries : Entry list, newEntry : string * int[] , k: int) = 
　　＊＊省略　原著参照＊＊

    let loaded = loadValues @"＊パス＊\train.csv"
    let newEntry = ("X,",[|0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;15;48;143;186;244;143;31;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;83;209;253;252;252;252;252;192;15;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;5;166;241;252;253;252;170;162;252;252;113;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;5;61;234;252;252;243;121;44;2;21;245;252;122;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;80;252;252;243;163;50;0;0;0;5;101;88;8;0;0;0;0;0;0;0;0;0;0;0;0;0;0;105;234;252;210;88;0;0;0;0;74;199;240;43;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;185;252;210;21;0;4;12;41;231;249;252;252;55;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;242;252;218;154;154;184;252;253;252;252;248;184;22;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;209;252;252;252;252;252;252;253;252;252;196;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;17;57;142;95;142;61;81;253;252;209;20;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;11;177;255;230;86;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;12;124;252;245;57;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;135;252;252;86;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;79;248;252;233;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;231;252;202;12;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;20;175;248;252;136;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;109;252;252;159;6;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;33;218;252;252;192;141;14;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;132;252;252;252;205;74;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;132;252;252;146;13;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0|])　//原著では途切れていて読めないので、修正した
　　＊＊省略　原著参照＊＊
    let guess = fst (List.nth labels 0) //原著はF# 4.0文法だったので修正
```

Unity C#側はこういう感じで。F#側で指定したnamespaceとmodule名を使用します。

```csharp:ReadFSharp.cs
 
using UnityEngine;
using DigitRecognition;

public class ReadFSharp : MonoBehaviour {

	void Start () {
        Debug.Log(DigitRecognitionEntry.guess);
    }

}
```

実行すると「９」と出るはずです。簡単ですね。