2019年04月17日

超入門 Swift for TensorFlow

エモトです.GWは引きこもろうと思ってます.

深層学習のコードを書くときは,Python + TensorFlow を使っています.Python は書きやすい言語だと思いますが,コード量が増えてくると,もっとモダンな言語で描きたい,コンパイラが欲しいと思います.私が完璧にPythonを理解してないのもありますが,ちょっと他の言語に浮気しました.

Swift For TensorFlow

Swift for TensorFlow は,Python 向けに開発された数値計算ライブラリ TensorFlow を Swift で利用することができます.一般的に多いラッパーではなく,Swift コンパイラを拡張したものになります.また,Swift は Python を使用することができるので,Python の豊富な数値計算ライブラリを使用できます.

インストール

公式サイトの Install Swift for TensorFlow に従えばインストールできます.なお,最近Swift 5がリリースされましたが,最新版の Xcode では上手くできず,Xcode 10.1 (Swift 4.2) で確認しました.

Google Colab を使おう

ローカル環境でインストール可能ですが,普段 iOS アプリ開発を行っていると,標準と拡張のコンパイラの管理が面倒になります.一先ずは,Google Colab を使用した方がおすすめです(ただし,補完などの補助機能がXcodeより貧弱なのが辛い).

これも公式の Using Swift for TensorFlow にて,Swiftが実行可能な blank Swift notebook が公開されているので,それを自身のドライブにコピーすれば,すぐに使えます.

以降のソースコードは,Colab上で動作確認したものです.

SwiftでPythonを使う

Swift for TensorFlow を使う前に,Swift 自体の機能で Python を使ってみました.Python の豊富な数値計算ライブラリを使用できます.SwiftでNumPyが動くのは,何か不思議な感じです.
import Python
PythonLibrary.useVersion(3, 6)

let np = Python.import("numpy")

let a = np.array([[1, 0], [0, 1]])
let b = np.array([[2], [3]])
let c = np.matmul(a, b)

Swift For TensorFlow を使ってみた

Swift For TensorFlow を使って,XOR を簡単な NN で学習しました.Keras もしくは TensorFlow2 を触っていれば,あまり違和感ない感じでした.
import Foundation
import TensorFlow

struct XOR: Layer {
  
  var layer1: Dense<Float>
  var layer2: Dense<Float>
  
  init(hiddenSize:Int = 2){
    self.layer1 = Dense(inputSize: 2,
                        outputSize: hiddenSize,
                        activation: sigmoid)
    self.layer2 = Dense(inputSize: hiddenSize,
                        outputSize: 1, 
                        activation: sigmoid)
  }
  
  @differentiable
  func applied(to input: Tensor<Float>, in context: Context) -> Tensor<Float> {
    return input.sequenced(in: context, through: layer1, layer2)
    }
}

let x: Tensor<Float> = [[0, 0], [0, 1], [1, 0], [1, 1]]
let y: Tensor<Float> = [[0], [1], [1], [0]]

var model = XOR()
let optimizer = SGD<XOR, Float>(learningRate: 0.1)
let context = Context(learningPhase: .training)

for _ in 1...5000 {
  let dmodel = model.gradient { m -> Tensor<Float> in
    let t = m.applied(to: x, in: context)
    let loss = sigmoidCrossEntropy(logits: t, labels: y)
    return loss
  }
  optimizer.update(&model.allDifferentiableVariables, along: dmodel)
}

let inference = round(model.inferring(from: x))
print(inference)

パフォーマンスは?

上記コードを Google Colab (CPU) で計算したところ,約13秒程度で終わりました.比較として,Python + TensorFlow2 (Keras) でもほぼ同様なモデルと学習方法で XOR を計算したところ,約6秒でした.コンパイラ言語であるSwiftの方が早いかと思いましたが,今回はPython版の方が早かったです.理由は分かりませんが,複雑な反復処理を行っていない,Swiftは複数のライブラリの読み込みがネックになった?のかなと.ColabのSwiftコンパイル時の最適化オプションなどは未調査です.

まとめ

Swift For TensorFlowを使用して,Swiftでも機械学習のコードを実装できました.まだまだPython版の方が良いかなと思いました.TensorFlow自体の更新頻度が高いうえに,Swiftもアップデートの頻度が高いので,安定性があるかは怪しいところです.また,入門エントリーが公式ぐらいしかないので,ちょっと調べ物は大変です.とはいえ,慣れたSwiftを使うことができる,実行する前にコンパイラが動くというメリットは感じました.
posted by Seesaa京都スタッフ at 16:00| Comment(0) | iOS | このブログの読者になる | 更新情報をチェックする

2019年03月08日

Swift でもRuntime Exceptionキャッチがしたい

エモトです.先日「翔んで埼玉」を見ました.京都も海がないのでよくわかります.中京区民なので洛外のことはよく分かりません.

先日,KyotoLT 第23回 にて,「Swift でもRuntime Exceptionキャッチがしたい」というタイトルで発表しました.

Swiftがリリースされた当初,「あれ?try-catchがない?」とモヤモヤしてました.後に実装された例外(エラー)処理を見て,「あれ?Objective-Cのときのような多様性がないぞ」とさらにモヤモヤしたことを覚えています.ランタイム例外が起こらないように実装するのが良いですが,あるなら保険として用意しておきたい.ある冬の夜の四条を歩いているとき,「あれ?Objective-Cを経由したらSwiftでもランタイム例外がキャッチできるんじゃね?」と色々やったことを発表しました.



Swiftでも色々やればランタイム例外は取得できました(実用的かは別として).より詳細はQiitaに投稿しています.ご興味があれば,「Swift の Runtime Exception はキャッチできるのかと試したこと - Qiita」をどうぞ.サンプルコードをGitHubにて公開しております.Swiftでもランタイム例外をキャッチしたい方は mitsuharu/demo_swift_catches_exceptions もどうぞ.

posted by Seesaa京都スタッフ at 12:00| Comment(0) | iOS | このブログの読者になる | 更新情報をチェックする

2018年12月06日

京都DevかふぇでiOSアプリ開発の昔話をしてきました

エモトです。近々公開のドラゴンボール映画のために,スーパーを見直してます.

先日,フリュー株式会社さんが主催の勉強会 京都Devかふぇ#4 〜レガシーシステム考古学〜 にて発表してきました.テーマがレガシーということで『iPhone OSアプリ開発の昔話』というタイトルで,まだiPhone OSだったころからのアプリ開発話をしてきました.資料作成で改めて,昔の開発を思い出すと,だいぶ苦労してたなーと.

posted by Seesaa京都スタッフ at 18:00| Comment(0) | iOS | このブログの読者になる | 更新情報をチェックする