C#でTensorFlowを動かす。

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

https://github.com/migueldeicaza/TensorFlowSharp


## ubuntuでの実行
### flatpakのインストール
参考: [Install MonoDevelop preview via FlatPak](http://www.monodevelop.com/download/linux/ "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 を設定しても反映されないことがある](https://kokufu.blogspot.jp/2016/01/ldlibrarypath.html "LD_LIBRARY_PATH を設定しても反映されないことがある")
参考2 : [Interop with Native Libraries](http://www.mono-project.com/docs/advanced/pinvoke/ "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](https://qiita-image-store.s3.amazonaws.com/0/70879/eb95faf2-839b-f075-d082-ff96760cb067.png)
次に, Build->Rebuild Allでソリューションをリビルドする。
![Screenshot from 2017-03-17 23-34-52.png](https://qiita-image-store.s3.amazonaws.com/0/70879/28353ddb-4aae-c0d1-bb24-958c4c0777d6.png)
SampleTestを動かしてみる。SampleTestを選択して、プロジェクトのビルド(△の-90°回転させたマーク)を押す。
![Screenshot from 2017-03-18 00-55-02.png](https://qiita-image-store.s3.amazonaws.com/0/70879/fd556ade-8d0a-ee75-8898-79f0316710af.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](https://qiita-image-store.s3.amazonaws.com/0/70879/88a82131-6f81-2f8f-fa8f-2d64db3cc4b0.png)
あんまり精度はよくない？

**[追記　2017.7.30]**

参考:[Nuget and “Unable to load the service index”](https://stackoverflow.com/questions/44688192/nuget-and-unable-to-load-the-service-index "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での実行
[ここ](https://blogs.msdn.microsoft.com/chomado/xamarin/getting-started-xamarin-on-mac-for-free/ "Mac で Xamarin 使ってみた！インストール〜実行まで【完全無料】[Getting Started Xamarin on 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開いて、クリーンしてビルドすれば動いた。
同時に実行もしてくれるので、とても使いやすい。
<img width="1440" alt="スクリーンショット 2017-03-20 01.24.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/70879/a933250b-aa92-c598-82f7-0a11069477d8.png">

## [追記]Windowsでの実行

[ここ](https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-cpu-windows-x86_64-1.2.0-rc0.zip")からファイルを落とす。
展開後、tensorflow.dll から libtensorflow.dll に名前を変更して、C:\Windows\System32 に置く。
<img width="1440" alt="スクリーンショット 2017-05-15 23.50.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/70879/848ef169-320f-827c-78e6-533e93c2e646.png">

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


ubuntu,macと同様にクローン(またはダウンロード)したリポジトリの直下の.sln開き、指示に従いF#のツールのインストールを行う。
<img width="1440" alt="スクリーンショット 2017-07-04 00.15.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/70879/08b5b87c-782c-c9ac-87a5-92b83190712d.png">


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

```  
Console.ReadKey();
```
を書き込んでキー入力がされるまで待つようにする。
結果は次のようになり、ちゃんと実行されていることが分かる。
<img width="1440" alt="スクリーンショット 2017-05-15 23.49.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/70879/beb5cec4-2958-aa92-984e-b9085b1d498f.png">

<!--
## エラーコード
ubuntu

```
/home/tama/workspace/c_sharp/TensorFlowSharp/SampleTest/bin/Release
TensorFlow version: 1.0.0-rc0
Handle: 15529552
FinishHandle: 140414189396128
Handle: 12921168
FinishHandle: 140414189396128
W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.2 instructions, but these are available on your machine and could speed up CPU computations.
Variables
Result of variable read 0 -> 1.5
Result of variable read 1 -> 2
Result of variable read 2 -> 2.5
Result of variable read 3 -> 3
Result of variable read 4 -> 3.5

Unhandled Exception:
System.EntryPointNotFoundException: TF_NewWhile
  at (wrapper managed-to-native) TensorFlow.TFGraph:TF_NewWhile (intptr,TensorFlow.TFOutput[],int,intptr)
  at TensorFlow.TFGraph.While (TensorFlow.TFOutput[] inputs, TensorFlow.WhileConstructor constructor, TensorFlow.TFStatus status) <0x41f7eea0 + 0x0010f> in <filename unknown>:0
  at SampleTest.MainClass+WhileTester.Init (Int32 ninputs, TensorFlow.WhileConstructor constructor) <0x41f7eb60 + 0x0015f> in <filename unknown>:0
  at SampleTest.MainClass.WhileTest () <0x41f7e7c0 + 0x000cb> in <filename unknown>:0
  at SampleTest.MainClass.Main (System.String[] args) <0x41f72d50 + 0x000f3> in <filename unknown>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.EntryPointNotFoundException: TF_NewWhile
  at (wrapper managed-to-native) TensorFlow.TFGraph:TF_NewWhile (intptr,TensorFlow.TFOutput[],int,intptr)
  at TensorFlow.TFGraph.While (TensorFlow.TFOutput[] inputs, TensorFlow.WhileConstructor constructor, TensorFlow.TFStatus status) <0x41f7eea0 + 0x0010f> in <filename unknown>:0
  at SampleTest.MainClass+WhileTester.Init (Int32 ninputs, TensorFlow.WhileConstructor constructor) <0x41f7eb60 + 0x0015f> in <filename unknown>:0
  at SampleTest.MainClass.WhileTest () <0x41f7e7c0 + 0x000cb> in <filename unknown>:0
  at SampleTest.MainClass.Main (System.String[] args) <0x41f72d50 + 0x000f3> in <filename unknown>:0
```

mac

```
/Users/tama/workspace/c_sharp/TensorFlowSharp/SampleTest/bin/Debug
TensorFlow version: 1.0.0-rc0
Handle: 140489346399424
FinishHandle: 140489311658688
Handle: 140489346605632
FinishHandle: 140489336971968
W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.1 instructions, but these are available on your machine and could speed up CPU computations.
W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.2 instructions, but these are available on your machine and could speed up CPU computations.
W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use AVX instructions, but these are available on your machine and could speed up CPU computations.
W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use AVX2 instructions, but these are available on your machine and could speed up CPU computations.
W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use FMA instructions, but these are available on your machine and could speed up CPU computations.
Variables
Result of variable read 0 -> 1.5
Result of variable read 1 -> 2
Result of variable read 2 -> 2.5
Result of variable read 3 -> 3
Result of variable read 4 -> 3.5

Unhandled Exception:
System.EntryPointNotFoundException: TF_NewWhile
  at (wrapper managed-to-native) TensorFlow.TFGraph:TF_NewWhile (intptr,TensorFlow.TFOutput[],int,intptr)
  at TensorFlow.TFGraph.While (TensorFlow.TFOutput[] inputs, TensorFlow.TFGraph+WhileConstructor constructor, TensorFlow.TFStatus status) [0x00054] in /Users/tama/workspace/c_sharp/TensorFlowSharp/TensorFlowSharp/Tensorflow.cs:731
  at SampleTest.MainClass+WhileTester.Init (System.Int32 ninputs, TensorFlow.TFGraph+WhileConstructor constructor) [0x0007a] in /Users/tama/workspace/c_sharp/TensorFlowSharp/SampleTest/SampleTest.cs:200
  at SampleTest.MainClass.WhileTest () [0x00027] in /Users/tama/workspace/c_sharp/TensorFlowSharp/SampleTest/SampleTest.cs:231
  at SampleTest.MainClass.Main (System.String[] args) [0x00044] in /Users/tama/workspace/c_sharp/TensorFlowSharp/SampleTest/SampleTest.cs:569
[ERROR] FATAL UNHANDLED EXCEPTION: System.EntryPointNotFoundException: TF_NewWhile
  at (wrapper managed-to-native) TensorFlow.TFGraph:TF_NewWhile (intptr,TensorFlow.TFOutput[],int,intptr)
  at TensorFlow.TFGraph.While (TensorFlow.TFOutput[] inputs, TensorFlow.TFGraph+WhileConstructor constructor, TensorFlow.TFStatus status) [0x00054] in /Users/tama/workspace/c_sharp/TensorFlowSharp/TensorFlowSharp/Tensorflow.cs:731
  at SampleTest.MainClass+WhileTester.Init (System.Int32 ninputs, TensorFlow.TFGraph+WhileConstructor constructor) [0x0007a] in /Users/tama/workspace/c_sharp/TensorFlowSharp/SampleTest/SampleTest.cs:200
  at SampleTest.MainClass.WhileTest () [0x00027] in /Users/tama/workspace/c_sharp/TensorFlowSharp/SampleTest/SampleTest.cs:231
  at SampleTest.MainClass.Main (System.String[] args) [0x00044] in /Users/tama/workspace/c_sharp/TensorFlowSharp/SampleTest/SampleTest.cs:569

Press any key to continue...
```
-->

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

placeholderとconstantの両方を用いて、[TensorFlowを算数で理解する](http://qiita.com/icoxfog417/items/fb5c24e35a849f8e2c5d "TensorFlowを算数で理解する")の記事に倣い、$ 2^{2} + 3 = 7 $ を計算してみる。

![Screenshot from 2017-03-18 00-55-21.png](https://qiita-image-store.s3.amazonaws.com/0/70879/54423882-1719-35e0-d6d3-27e3603f1114.png)

```c#: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](https://qiita-image-store.s3.amazonaws.com/0/70879/1f12dfc7-5de2-2c91-ceb1-b3e59b22e95d.png)


# 築いた屍
## IronPython
### インストール

ver
unity 5.5.1f1
IronPython 2.7.7
Windows 10 on Mac Parallels

[Unity上でPythonを使う①【アセット組み込み編】](http://tkitao.hatenablog.com/entry/2015/05/18/225902 "Unity上でPythonを使う①【アセット組み込み編】")
上記の記事のようにunity上でpythonのパッケージを読み込もうと考えた。

IronPythonはCドライブの直下に置く。program fliesだとアクセスできずに死ぬ。
インストール後には、[ここ](http://ironpython.net/blog/2014/12/07/pip-in-ironpython-275.html "Pip in IronPython 2.7.5")に倣って、IronPython上でpipをインストールする.

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

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

また、以下の記事も見つけてしまった。
[How do I install keras package in IronPython/VS2010?](http://stackoverflow.com/questions/38328893/how-do-i-install-keras-package-in-ironpython-vs2010/38385151 "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で検索しても見つからず、解消できず諦めた。一から書き直す元気はなかった...