はじめに
こんにちは、iOSエンジニアのしだです。UniFa Advent Calendarで、普段の開発であまり関わりの少ないメンバーの記事を見てにやにやしてます 😏
こちらは、UniFa Advent Calendar 2019 の12日目の記事になります。
もう2019年が終わりますが、今年は、TensorFlow Dev Sumit 2019があったり、TensorFlow 2.0になったり、O'Reilly主催のTF World '19があったりTensorFlowのアップデートが多かった気がします。 その中で、以下の Swift for TensorFlow (TF World '19) の動画を見ていたところ、何やら Jupyter notebook に Swift を書いていてなんじゃこりゃと思って調べてみたらSwift-Jupyterというものを知ったので使ってみます。
Swift-Jupyter
swift-jupyter はそのまま jupyter の Swift 用のカーネルを提供しています。 これを使うと notebook にswiftが書けます。すごいです。
準備
最初に swift-jupyter をインストールします。 README.md には、いくつかインストール方法がありますが docker 経由でやります。
$ git clone https://github.com/google/swift-jupyter.git $ cd swift-jupyter // requirements に Pillow だけ追加しておきます $ echo "Pillow" >> docker/requirements_py_graphics.txt $ docker build -f docker/Dockerfile -t swift-jupyter .
起動方法
コンテナを立ち上げると Jupyter が立ち上がるようになっています。swift-jupyter を起動してといつもの localhost:8888
を開けば Jupyter が使えます。あとは好きなようにPythonではなく、Swiftを書いていきます。
// swift-jupyter を起動する $ docker run -it -p 8888:8888 --cap-add SYS_PTRACE -v /path/to:/notebooks swift-jupyter // もし GPUを使う場合は、 `--gpus` オプションを付けます $ $ docker run -it -p 8888:8888 --gpus all --cap-add SYS_PTRACE -v /home/ubuntu:/notebooks swift-jupyter
Python (Numpy, PIL)
Swift for TensorFlowでは、Pythonを使うこともできます。Swift上ではPythonのオブジェクトはすべて PythonObject
というオブジェクトになるので、Swift for TensorFlow の Tensor や Arrayへの相互に変換する必要があります。
numpy と Tensorの変換するときは、型に気をつける必要があります。変換できない場合は nil が返ってきます。
また、Pillow
をインストールしておけば、numpy と同じように使えます。
試しに画像ファイルを読み込んで、notebook上に画像を表示します。
Load image in Swift for TensorFlow
Differentiable
Swift for TensorFlow では、 @differentiable
という Attributes を付けると微分可能な関数を定義することができます。そして @differentiable
を付けると gradient(at:)
や valueWithGradient(at:)
という関数を呼ぶことができ勾配を計算できるようになります。以下は sigmoid
の微分の例になります。
Differentiable in Swift for TensorFlow
Custom differentiable
こちらは動画の中にもあった例なのですが、
独自に微分可能な関数を定義することができます。
次の例ですと Glibc の pow関数は @differentiable に対応した関数ではないのですが、@derivative(of:) を付けることで @differentiable に対応することができます。
また、pow関数の と のそれぞれ に対する微分を自分で記述してあげます。
Custom differentiable in Swift for TensorFlow
念の為、TensorFlow 2.0 (Python) でやった結果と同じになっているので合っていると思います。
// これは Python です。 import tensorflow as tf a = tf.constant(0.5) b = tf.constant(3.0) with tf.GradientTape() as tape: tape.watch((a, b)) y = a ** b dy_dx = tape.gradient(y, (a, b)) dy_dx[0].numpy(), dy_dx[1].numpy() # ==> (0.75, -0.0866434)
さいごに
Swift for TensorFlow の学習がてら swift-jupyter を使ってみました。
Pythonは、PythonObjectの変換があるので扱いずらいですが、案外使えるかもしれません。iOSやってた身としてはかなり面白いなぁと感じてます。
本当は、Head Pose Estimation(頭部姿勢推定)を Swift for TensorFlowでやるつもりでしたが機会があったら書きます😂