前書き
F#向けのDeeplearningライブラリ「Deep.Net(http://www.deepml.net) 」をMac上で試してみたが失敗。その過程を示すことによって、 誰かが解決策を教えてくれるかもしれない という淡い期待を抱きつつ、記してみようと思う。
尚、Windows上では動きはしたが、また別の問題が発生していたので、これは改めて記事にしたいと思う。
動機
- F# Deeplearningでググってたら発見した。
- Nugetで簡単に入れられるよーって書いてあったので、じゃぁVS Code+Ionide+Paketでもいけるんじゃね?と思い立つ
実際にやってみた
環境
- Visual Studio Code
- Ionideパッケージ一式(VS Codeの機能拡張)
- Mac上でF#を実行する環境(monoとか色々)ご参考
Paket経由でDeep.Netをインストール
VS Code上でコマンドパレットを開きPaket Add Nugget Package
を実行し、Deep.Net
と続けて入力。これで必要なものは全部入る。
公式サイトを参考にMNIST云々を書いてみる
使い方については公式サイトのここを参考にした。
.fsx
による実行だったので、ライブラリを手動で参照しなければならず、こんな感じに書いた
#r @"../packages/DeepNet/lib/net461/DeepNet.dll"
#r @"../packages/ManagedCuda-80/lib/net46/ManagedCuda.dll"
#r @"../packages/Tensor/lib/net461/Tensor.dll"
#r @"../packages/DeepNet/lib/net461/SymTensor.dll"
#r @"../packages/DeepNet/lib/net461/SymTensorCuda.dll"
#r @"../packages/DeepNet/lib/net461/MLOptimizers.dll"
#r @"../packages/DeepNet/lib/net461/MLModels.dll"
#r @"../packages/DeepNet/lib/net461/MLDatasets.dll"
そして、最初のハマりポイント!
open ArrayNDNS //<-------- エラー!!!!!
open SymTensor
open SymTensor.Compiler.Cuda
open Datasets
え? マジで?
Github側にある本家ソースを見ながら推測
本家の例題にも(Working with Tensor)
let a = ArrayNDHost.initIndexed [7; 5] (fun [i; j] -> 5.0 * float i + float j)
って書いてあるぐらいだから、ソース眺めてみるとHostTensor
なるものを見つけた。これはもしかして、Arrayという表記をやめて今流行り(?)のTensorにしたのではと勝手に推測。
したがって、こう書き換える
open Tensor
open SymTensor
// open SymTensor.Compiler.Cuda // <---- とりあえずCudaは後回し
open Datasets
適当にテンソルを定義してみると
let a = HostTensor.init [7L; 5L] (fun [|i; j|] -> 5.0 * float i + float j)
printfs "%A" a
[[ 0.0000 1.0000 2.0000 3.0000 4.0000]
[ 5.0000 6.0000 7.0000 8.0000 9.0000]
[ 10.0000 11.0000 12.0000 13.0000 14.0000]
[ 15.0000 16.0000 17.0000 18.0000 19.0000]
[ 20.0000 21.0000 22.0000 23.0000 24.0000]
[ 25.0000 26.0000 27.0000 28.0000 29.0000]
[ 30.0000 31.0000 32.0000 33.0000 34.0000]]
できたーーーーーー。
なんか、intからint64に変わっていたり、Listを受け取ると思ったら配列になっていたり、地味に変わっているけどドキュメントが変わっていないという。
そして迷宮入りする
さて、MNISTの例題の続きをやる。
let mnist = Mnist.load (__SOURCE_DIRECTORY__ + "../../../Data/MNIST") 0.0
|> TrnValTst.ToHost // <--- 本家はToCudaだけど、今はCPUで試しているのでToHostにした
printfn "MNIST training set: images have shape %A and labels have shape %A"
mnist.Trn.All.Img.Shape mnist.Trn.All.Lbl.Shape
printfn "MNIST test set: images have shape %A and labels have shape %A"
mnist.Tst.All.Img.Shape mnist.Tst.All.Lbl.Shape
実行。
System.TypeInitializationException: The type initializer for 'HDF.PInvoke.H5P' threw an exception.
---> System.NotImplementedException: The method or operation is not implemented.
NotImplementedExceptionって……。
よくみるとHDF.PInvoke.H5P
と書いてあるので何かしらのネイティブライブラリを要求しているようだ。
メカニズムから考えるに「.NET」→「P/Invoke」→「ネイティブライブラリ」っぽいから、このパッケージってどう考えてもWindows向けに作られているから、これ以上無理なんじゃね?
終わりに
いわゆるマネージドコードからネイティブライブラリを呼び出すメカニズム「P/Invoke」を経由している時点で、Macネイティブが「.dll」じゃないから無理じゃない?という結論に至ってしまった。
もし、別の方法があったら誰か教えてください。時間があれば、もうちょっと調べてみるか………。