はじめに
F#と機械学習に関する本は、日本語のものは見当たらないので、英語の本で勉強することになります。いくつかある中で、最近発刊された"F# for Machine Learning Essentials" (Sudipta Mukherjee 著)は手軽に勉強できそうな感じだったので、ちょっと見て見ることにしました(以下では「原著」と呼ぶ)。ここでは、第1章に出てくる k-nearest neighbour algorithmをUnityで実行してみました。
扱う問題
こちらにある手書き文字のデータを使い、文字認識を行います。各手書き文字は28*28の行列を一列に広げたものとして表現され、入力するデータと一番近いデータをk-nearest neighbour algorithm (参考資料)で抽出します。
Unityでの実行
UnityでのF#の使い方は、こちらの過去記事を参考にしてください。
こちらの記事でも書いた通り、UnityからF#のライブラリを呼び出すにはnamespaceを定義しますが、namespaceは直接に値や関数を持てないので、moduleを指定する必要があります。原著のサンプルコードではmoduleは指定されてないので、こちらで加えます。
また、Unityでは、Monoのバージョンの関係で F# 3.0しか使えないので、F# 4.0の文法を使っている部分は修正が必要です。
Unity用の修正版
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名を使用します。
using UnityEngine;
using DigitRecognition;
public class ReadFSharp : MonoBehaviour {
void Start () {
Debug.Log(DigitRecognitionEntry.guess);
}
}
実行すると「9」と出るはずです。簡単ですね。