C#
Xamarin
MonoDevelop
TensorFlow
ubuntu16.04

TensorFlowSharp

Unity上で機械学習のフレームワークを動かしたいと思いたったので、どうにかして動かせる方法を検索した結果、TensorFlowSharpというものを見つけたので動かしてみた。

https://github.com/migueldeicaza/TensorFlowSharp

ubuntuでの実行

flatpakのインストール

参考: Install MonoDevelop preview via FlatPak

$ sudo add-apt-repository ppa:alexlarsson/flatpak
$ sudo apt update
$ sudo apt install flatpak

mono Devのインストール

$ flatpak install --user --from https://download.mono-project.com/repo/monodevelop.flatpakref
# 起動できるか確認する
$ flatpak run com.xamarin.MonoDevelop

ライブラリをシステムに追加する

linuxの共有ライブラリを落とす。今回はGPUでエラーが出ても面倒なので、CPU版を使用する。

参考1 : LD_LIBRARY_PATH を設定しても反映されないことがある
参考2 : Interop with Native Libraries

$ cd Downloads
$ wget https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-cpu-linux-x86_64-1.1.0.tar.gz
$ cd /usr/local
$ sudo tar xzvf ~/Downloads/libtensorflow-cpu-linux-x86_64-1.1.0.tar.gz
#パスを通す
$ cd /etc/ld.so.conf.d
$ sudo vim lib_path.conf
#↓を書き込んで保存
/usr/local/lib
#/etc/ld.so.cache を再構築する
$ sudo ldconfig
$ ldconfig -p > ~/out.txt
#ライブラリが追加されているか確認する
$ find ~/ -type f -name "out.txt" | xargs grep 'libtensorflow.so'

ソリューションをビルドする

クローン(またはダウンロード)したディレクトリの直下のソリューション(.sin)をMonoDevelopで開く。
Screenshot from 2017-03-17 23-33-57.png
次に, Build->Rebuild Allでソリューションをリビルドする。
Screenshot from 2017-03-17 23-34-52.png
SampleTestを動かしてみる。SampleTestを選択して、プロジェクトのビルド(△の-90°回転させたマーク)を押す。
Screenshot from 2017-03-18 00-55-02.png

コンソール上で生成した実行ファイルを起動する。

mono-completeのインストール

$ sudo apt-get install mono-complete
$ cd ~/workspace/c_sharp/TensorFlowSharp/SampleTest/bin/Debug
$ mono SampleTest.exe

しかし、t.WhileTest ();で例外になる。それ以外は動く。
それはコメントにも書いてあるので、そのうち修正される?

次にExampleのプロジェクトを実行する
Screenshot from 2017-03-17 22-36-56.png
あんまり精度はよくない?

[追記 2017.7.30]

参考:Nuget and “Unable to load the service index”

mono-dev v7.0.1 (buliid 24)だと、NuGetのパッケージの取得ができないバグがあるのでビルドが通らない。

Edit -> Preferences -> NuGet -> Sources
URLがhttps://api.nuget.org/v3/index.json
であるか確認する.

その後端末で

$ export MONO_TLS_PROVIDER=legacy

を実行する。

これでビルドが通るようになる.

Macでの実行

ここを参考にxamarinを入れる。

$ cd ~/Downloads
$ curl -O https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-cpu-darwin-x86_64-1.1.0.tar.gz
$ cd /usr/local
$ sudo tar zxvf ~/Downloads/libtensorflow-cpu-darwin-x86_64-1.1.0.tar.gz
$ cd lib
$ sudo mv libtensorflow.so libtensorflow.dylib
#一応確認する.
$ find /usr/local/ -type f -name "libtensorflow.dylib"

ubuntuと同様にクローンしたリポジトリの直下の.sln開いて、クリーンしてビルドすれば動いた。
同時に実行もしてくれるので、とても使いやすい。
スクリーンショット 2017-03-20 01.24.45.png

[追記]Windowsでの実行

ここからファイルを落とす。
展開後、tensorflow.dll から libtensorflow.dll に名前を変更して、C:\Windows\System32 に置く。
スクリーンショット 2017-05-15 23.50.34.png

TensorFlowSharpはC#7の文法を使用しているので、Visual Studio 2017をインストールする。

ubuntu,macと同様にクローン(またはダウンロード)したリポジトリの直下の.sln開き、指示に従いF#のツールのインストールを行う。
スクリーンショット 2017-07-04 00.15.00.png

再起動後、ビルド->リビルドする。その後、SampleTest.csに下記の「試しに足し算を行ってみる。」のコードを書き込んで、SampleTestを「開始」すると実行される。しかし、すぐに終了して流れてしまうので、main文の最後に

Console.ReadKey();

を書き込んでキー入力がされるまで待つようにする。
結果は次のようになり、ちゃんと実行されていることが分かる。
スクリーンショット 2017-05-15 23.49.45.png

試しに足し算を行ってみる。

placeholderとconstantの両方を用いて、TensorFlowを算数で理解するの記事に倣い、$ 2^{2} + 3 = 7 $ を計算してみる。

Screenshot from 2017-03-18 00-55-21.png

SampleTest.cs
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using TensorFlow;
using System.IO;
using System.Collections.Generic;
using Learn.Mnist;
using System.Linq;

namespace SampleTest
{
    partial class MainClass
    {
        static public void Assert (bool assert, [CallerMemberName] string caller = null, string message = "")
        {
            if (!assert){
                throw new Exception ($"{caller}: {message}");
            }
        }

        static public void Assert (TFStatus status, [CallerMemberName] string caller = null, string message = "")
        {
            if (status.StatusCode != TFCode.Ok) {
                throw new Exception ($"{caller}: {status.StatusMessage} {message}");
            }
        }

        public void Test_Session ()
        {
            // グラフを作成。
            using (var g = new TFGraph ()) {
                // セッションの作成。
                var s = new TFSession (g);

                // ここでは "int"を使用するので、演算時のキャストはintにする。
                // placeholderというデータが格納される箱(値は実行時に入れる).引数として予めグラフに与える。
                var feed = g.Placeholder (TFDataType.Int32);
                // 中身が2のconstantの作成。
                var x = g.Const (2);
                // xの2乗を求める。
                var x2 = g.Square (x);
                // 和を求める。
                var add = g.Add (x2, feed);

                // runnerの作成。
                var runner = s.GetRunner ();
                // Placeholderに値を入れる。
                runner.AddInput (feed, new TFTensor ((int)3));
                // 実行及び結果表示
                Console.WriteLine ("2^2 + 3 ={0}", runner.Run (add).GetValue ());
            }
        }
        public static void Main (string [] args)
        {
            Console.WriteLine (Environment.CurrentDirectory);
            Console.WriteLine ("TensorFlow version: " + TFCore.Version);


            var t = new MainClass ();
            t.Test_Session ();

        }
    }
}


こんなのも見つけたので、記述しておく

NuGet Gallery に "TensorFlowSharpCore" 使えるかどうかは未確認。
Screenshot from 2017-03-17 22-39-56.png

築いた屍

IronPython

インストール

ver
unity 5.5.1f1
IronPython 2.7.7
Windows 10 on Mac Parallels

Unity上でPythonを使う①【アセット組み込み編】
上記の記事のようにunity上でpythonのパッケージを読み込もうと考えた。

IronPythonはCドライブの直下に置く。program fliesだとアクセスできずに死ぬ。
インストール後には、ここに倣って、IronPython上でpipをインストールする.

$ ipy -X:Frames -m ensurepip
$ ipy -X:Frames -m pip install xxx

モジュールをインストールしようとすると、以下と同様のエラーが出てしまい、進まなかった。
参考1: pip not installing packages
参考2: pip IronPython and PTVS on VS 2015 doesn't seem to work well

また、以下の記事も見つけてしまった。
How do I install keras package in IronPython/VS2010?

SWIG

https://github.com/unrealwill/tensorflow-csharp-c-api

tensorflow-csharp-c-apiのbuildを動かすために
tensor_c_api.iの"tensorflow/core/public/tensor_c_api.h"
の記述があるので、それがあるv0.9をクローンして、build.shを実行したが、

$ ./build.sh
rm: 'wrap/*.cs' を削除できません: そのようなファイルやディレクトリはありません
Unable to open file wrapcxx/tensor_c_api_wrap.cc: No such file or directory
error CS2008: No files to compile were specified
Compilation failed: 1 error(s), 0 warnings
g++: error: wrapcxx/tensor_c_api_wrap.cc: そのようなファイルやディレクトリはありません
g++: error: callback.o: そのようなファイルやディレクトリはありません
g++: error: deallocator.o: そのようなファイルやディレクトリはありません
g++: error: tensor_c_api_wrap.o: そのようなファイルやディレクトリはありません

となり、wrapcxx/tensor_c_api_wrap.cc をGoogleで検索しても見つからず、解消できず諦めた。一から書き直す元気はなかった...