Hatena::ブログ(Diary)

Over&Out その後 このページをアンテナに追加 RSSフィード

2017-07-25

Core ML vs MPSCNN vs BNNS #fincwwdc

昨日FiNCさんのオフィスで開催された「WWDC2017振り返り勉強会」で『Core ML vs MPSCNN vs BNNS』というタイトルでLTしてきました。



iOS 11で追加されたCore MLが非常に注目を集めていますが、「既存の機械学習フレームワークを使って学習させたモデル(のパラメータ)をiOS側に持ってきて推論を実行する」ということ自体はiOS 10からあって、そこに不便さがあったので広まらず、Core MLでやっと使われるようになった、という側面はもちろんありつつも、いややはりそれでも単にそういうことがiOS 10できるようになったということ自体が知られていなかっただけなのではと。




確かに自分も Metal Performance Shaders のCNN APIを用いた機能を実装しようとしたときに、情報があまりに少なく、何ができて何ができないのか、どうやるのかがよくわからなかった、ということがありました。


で、そのへんをシンプルに説明したら、もっと興味をもつ人も出てくるんじゃないかなと思い、実装手順を3ステップで解説してみました。


  • Step 1: モデルをつくる

f:id:shu223:20170725070344j:image:w600


  • Step 2: ネットワークを実装する

f:id:shu223:20170725070345p:image:w600

f:id:shu223:20170725070347p:image:w600


  • Step 3: 推論の実行処理を書く

f:id:shu223:20170725070346p:image:w600



意外と簡単そう/使えそうではないでしょうか?



ところが・・・


f:id:shu223:20170725070348p:image:w600


f:id:shu223:20170725070349p:image:w600


っていうつらさがあり、他にも色々と面倒な点があり、やっぱりCore ML & Visionのおかげで各段に便利になった、という話でした。



最後にAccelerateフレームワークのBNNSの使いどころについてWWDC17のMetal Labで聞いた話が出てきます。


f:id:shu223:20170725073011p:image:w600



(登壇の様子 by yucovin さん)


なぜこの話をしたのか

上の説明だけを読むとまるでMPSCNNの普及活動をしている人みたいですが、動機はそこではなくて、来月登壇する アメリカのiOSカンファレンス で、"Deep Learning on iOS" というタイトルで発表することが決まっていて、


f:id:shu223:20170725070350p:image:w600


で、これってWWDC17開催前にCfPを出して通ったやつなので、応募当時はMPSCNNの話をするつもりだったのに、Core MLが出てしまって事情が変わってしまった、どうしよう、という。。


じゃあCore MLの話をすればいいじゃん、と思うかもしれません。その通りかもしれません。でも僕自身がまだあまり試せてないのと、Core MLの場合はiOS側が便利になりすぎてむしろ機械学習フレームワーク側(Kerasとか)がメインになるけどそっちは初心者とすらいえないレベルだし、ってことでMPSCNNの方に解説を寄せよう、という試行錯誤の中で「こんな切り口はどうだろう」と考えたのが昨日の発表なのでした。


実際に話してみて、正直なところコレジャナイ感はちょっとありました。もうちょっとワクワクする感じにならないか、実例とかデモとかを増やす感じでブラッシュアップしてみようと思ってます。(来月のカンファレンスは発表時間が45分もあるので、個々の解説ももうちょっと丁寧にやる予定)


おわりに

WWDCには参加したものの、そのままアメリカにいたのでこういう振り返り勉強会に参加できず(※例年勉強会発表ドリブンで新APIを勉強していた)、あっちではこういうLTで気軽に登壇できる勉強会もあまりないので、1ヶ月後というわりとWWDC勉強会としては珍しいタイミングで開催された本イベントは大変ありがたかったです。


LTですが非常に中身の濃い発表が多く、勉強になりました。懇親会で出てくる料理もさすがFiNCさん、ヘルシーで美味しいものばかりでした。どうもありがとうございました!


追記:BNNSについていただいたコメント

Facebookでsonsonさんからコメントいただきました。


f:id:shu223:20170725124035p:image:w400


BNNSとMPSCNNの使い分けは,難しいけど,電力と計算スピードのバランスかなぁと思います.


あと,GPUのメモリとCPUのメモリ間の転送に時間がかかるので,オーバーヘッドをカバーできるくらい,データや計算量大きくないと,GPUは意味ないでしょう.

BNNSは,SIMDなので,これも当然CPUのコンテキストスイッチのためのオーバーヘッド(ノーマルモードとSIMDモードの切り替え)があるのですが,GPUほどではないので,小さいネットワークだとGPUよりBNNSの方が速いというのはありそうです.


まぁ,なんで,電力と速度の限界に挑戦する場合は,ベンチマークとって極限を目指そうって感じですかねw


なるほど、単に「CNNの計算はGPUが向いてるでしょ」とか「Appleの人も言ってた」とかってだけでBNNSのことは忘れようとか言ってちゃいけないですね。確かにGPU↔CPU間の転送速度のボトルネックとGPUによる高速化がどれぐらい見込まれるかのバランスによる、というのは非常に納得です。また「SIMDモードへの切り替えのオーバーヘッド」(はあるがGPUとの転送ほどではない)というあたりもまったく考慮できてなかったところです。


CPU、GPUの負荷がそれぞれどれぐらいか、というのはXcodeで簡単に見れますが、GPU↔CPU間の転送状況を見る方法もあるのでしょうか?GPUまわりの計測・デバッグ手法はもうちょっと勉強したいところです。


ちなみにsonsonさんは例の(私も参加させていただく)クラウドファンディング本で「Core ML」のパートを担当されます。


7/28まで買えるみたいなのでまだの方はぜひご検討を!


2017-03-06

try! Swift Tokyo 2017で「クライアントサイド・ディープラーニング」というLTをしました #tryswiftconf

先週開催された "try! Swift Tokyo 2017" にて、"Client-Side Deep Learning" というタイトルでLTしました。発表資料はこちら。



ディープラーニングは強力なコンピューティングパワーが必要なので、従来はモバイルデバイスでやるものではなかったのですが、iOS 10でMetal Performance Shadersフレームワークに追加された新たしいAPIにより、クライアントサイドのGPUで学習済みCNNの計算を行えるようになったという話です。


その話前もしてたんじゃ・・・と思われるかもしれませんが、今回は自分でモデル作成からアプリ実装まで一通りやってみた上で話をしていたので、僕の中では大違いでした。まぁ、5分のLTなのでそこで得た知見や具体的な実装についてはあまり話せませんでしたが。。


実際にLTの中でライブデモもやりました。手元のネームプレートにあるSwiftロゴの認識に見事成功しました。


f:id:shu223:20170306090025j:image:w600

(Photo by @inamiy


緊張かライブデモの恐怖かわかりませんが手がプルプル震えるし、学習データはオレンジバックの白抜きのお馴染みのロゴ画像が中心で、木製ネームプレートに立体的に刻印されたロゴはそもそも今回作成したモデル的には認識が難しいということもあったのですが、無事うまくいって良かったです。


手が震えてたのが逆に良かったというフィードバックもちょこちょこいただきましたw




ちなみにこちらはライブデモがうまくいかなかったとき用に用意しておいた動画:


f:id:shu223:20170306091242g:image

(try! Swiftの会場で撮ったもの)


niwatakoさんによる聞き起こし記事:


実装について詳細を知りたい方は

MPSCNNについては記事をいろいろ書いてます。今回の実装に関係ありそうな話はこのへん。


デモ作成にあたって自分でも自分の記事を何度も見返しました。書いといて良かった。。


LTの難しさ

今回は5分しかないLT枠だったわけですが、「何を話さないか」はそれこそ開催前日ぐらいまで悩んでました。色んなものを泣く泣く削りました。

  • 自己紹介
    • せっかく日本中、世界中から700人ものSwift/iOSエンジニアが集まっているわけだから、自分をアピールしたい
    • が、発表の流れの中で不可欠なものではないのでカット
  • 弊社での事例紹介
    • うちの会社はそれこそiOS 10が出た直後にMPSCNNを利用した機能をリリース*1していて、それを紹介したい気持ちはあった
    • が、それをやると付随して説明することが増えてしまうのでカット
  • CNNとは何か、ディープラーニングとは何か
    • CNN、CNN言いまくってるし、タイトルにDeep Learningとあるので、説明しないわけにはいかない
    • この概念は短く説明しても「わかったような、わからないような」にしかならないし、今回の趣旨的にそこをハッキリ理解することは重要ではないので、思い切って"Something great"(何かすごいもの)っていう理解でいいです、ってことにした
  • 実装コードの紹介
    • ちゃんと実装した上で話してるし、try! "Swift"なのでコードは出したかった
    • CNNについての説明なしに、CNNを構築するコードを出しても「既にわかってる人にしかわからない」のでカット

どこかのカンファレンスのCfPに応募して完全版で発表したいなーと思ってます。


発表の様子(2017.4追記)

プロの方によるオフィシャル写真が公開されたので記念に載せておきます。


f:id:shu223:20170412115653j:image:w600

(セットアップ中)


f:id:shu223:20170412115722j:image:w600

(はじまりました!固い。。)


f:id:shu223:20170412115255j:image:w600

("Something great")


f:id:shu223:20170412115259j:image:w600

(手がプルプル震えながらも無事ライブデモ成功!)


f:id:shu223:20170412115257j:image:w600

(プレッシャーから解放された顔)



後日(これを書いてる今日)、初日に機械学習の話をされていたAlexis Gallagherさんと、サンフランシスコのお寿司屋さんでランチしてきました。(ごちそうさまでした!)


f:id:shu223:20170412120433j:image:w600


AlexisさんはTopology EyewearのCTOなのですが、そのオフィスがなんと僕の働いているFyusionのオフィスとわずか3ブロック違いという。


Topology Eyewearは顔をスマホで撮って3Dモデルを作成し、そのモデル上で自分にあったメガネを検討して注文までできるサービス。技術的にもメガネユーザーとしても非常に興味深いです。


その他余談

CfPについて

今回のLTはCfP(Call for Proposal)によって選ばれたわけですが、競争率は7〜8倍あったそうです。


僕は自慢ではないのですが(自慢ですが)国内にしろ海外にしろCfPはほぼ毎回通ってまして、書く際に意識しているポイント等を下記トークの中で話したので、もしよろしければ見てみてください。


ちなみに、タイトルは"Client-Side Neural Network"の方が適切なのでは、という声もありましたが、それはその通りでそのタイトルも候補にはあったのですが、「キャッチーさ」を重視して現行のものにしました。


英語

海外から多くのスピーカー/聴講者が集まる本カンファレンスで、サンフランシスコで働いている僕が日本語で話しはじめてズッコケた人もいるんじゃないかと思うのですが、日本での開催だし、素晴らしい同時通訳もあるし、上述の通り直前まで発表内容がfixできずにいたし、デモはそれこそ当日まで作ってたし、というわけで、英語での発表は早々に諦めてました🙇🏻 *2


こうしてある程度割り切る判断ができるようになったのも前進だ、とか思ってましたが、やっぱり他の日本人スピーカーの方々が堂々とした英語でプレゼンしてるのを見て心に響くものがあったのも事実。来年またチャンスがあればがんばりたいと思います。


弊社チームメンバーとの思い出

うちの会社から僕を含めて4人、try! Swiftに参加してました。


f:id:shu223:20170306091906j:image:w600

(開催前日、全員集合。渋谷dots.さんにて。この後Ninjaレストランへ)


f:id:shu223:20170306092016j:image:w600

(配布バッグに入れてもらったチラシ)


3人はサンフランシスコから、1人はブラジルからの参加で、そのブラジルの彼は動画ミーティングではずっと顔を合わせていたものの、直接会うのは初めてだったので、感慨深いものがありました。


f:id:shu223:20170306092106j:image:w600

(ロボットレストランからのゴールデン街)


チームで長い時間を一緒に過ごせたのも開発合宿的で良かったです。


try! Swiftの感想

セッション内容については、わりと、「デキる」人達からは、辛口の意見を聞きました。内容が浅い、とか。で、僕はどう思ったかというと、自分のトークの準備(主にデモの実装)をまだやってたのと、気持ちがフワフワしてたのとで、実はほとんど聞けてません。後ほど復習します。


が、来年もまたやって欲しいかというと、ぜひやってほしい派です。やっぱりこうして日本中・世界中からSwift/iOSエンジニアが集まって、一つの場・時間を共有するというのは代えがたい体験です。僕はWWDCに求めるものはセッションでもラボでもなく、iOSエンジニアのお祭り的な空気感だということに気付いてWWDCのチケットがなくても毎年SFに行くようになったのと同様に、try! Swiftもそういう価値があると思います。Swiftについての知見を得られる、ということ以外に、このカンファレンスが日本のSwift/iOSエンジニアコミュニティに与えている影響は相当あるんじゃないかと。


これだけの規模のカンファレンス、早朝の準備から夜のパーティが終わるまで、しかもそれが3日間と、主催・運営された皆様の労力は想像を絶するものかと思います。頭が下がるばかりです。素晴らしいカンファレンスを開催していただき、どうもありがとうございました!


*1:僕が実装したわけではない

*2:海外スピーカーの発表も、去年は「お、この人の英語は聴きやすいしちょっと同時通訳なしでがんばってみようかな」とかやってましたが、今年は最初からがっつり同時通訳レシーバーに頼りました

2017-02-07

それでもCourseraの機械学習コースをオススメする理由

先日、オンライン学習サイトCourseraの機械学習コース "Machine Learning by Stanford University" を修了しました。


f:id:shu223:20170207160051j:image

(感動のエンディング動画)


ただ、機械学習に興味があって情報収集を始めてる人にとって、「Courseraの機械学習コースがおすすめですよ」という話は


「はい、知ってます


という感じではないでしょうか。


僕もそんな感じで、幾度となく人や記事に同コースを薦められたりしつつ、たぶん2年ぐらいスルーし続けてきたと思います。


しかし約2ヶ月前、ひょんなきっかけから本講座を始めてみて、やはり評判通り最高だったと思うと同時に、僕と同じような感じでこのコースが良いらしいと知りながらもスルーし続けてる人は多いんじゃないかと思いまして、(おせっかいながらも)自分の脳内にあった「やらない理由」を列挙しつつ、「いや、それでもやった方がいいですよ」というのを書いてみたいと思います。


「スタンフォードの授業」レベル高そう

世界最高峰のスタンフォード大学の授業、いくら「入門です」と言われても、


「それはレベルの高い中での入門でしょ?」


と思ってました。技術書を読んでもさっぱり頭に入ってこない人の気持ちなんてわからないでしょうよ、と。


いえ、この授業はサルでもわかります。・・・とは言えません


やっぱり数式がたくさん出てきて何言ってるのかわからなくなります。眠くなります。でも少なくともスタンフォードに入学できる程の世界最高峰の前提知識が必要ってことはないです。


高校レベルの数学、プログラミングが出来れば前提知識としては十分で、Andrew先生は数式の意味を説明するのがめちゃくちゃうまいです。項を削ぎ落としてシンプルにしたところから、順序立ててその数式の性質を説明してくれて、それが機械学習でどう役立つのか、という話をしてくれるので、納得感・腹落ち感があります。


そして時には、「この数式の意味はわかってなくても偉い人が実装したライブラリ使えば機械学習はできるから大丈夫だ」と言ってくれたりもします。わからない人の気持ちがわかってる先生だなと随所で感じます。


わからない分野の話を、英語で学ぶなんて...

全編に日本語字幕があります。自動翻訳の気持ち悪い日本語ではなくて、ボランティアによる自然な日本語です。


当初僕には「英語の動画を日本語字幕で見るのは何か負けた感がある」「英語で観ると英語の勉強にもなって一石二鳥」という変なこだわりもありましたが、

  • 機械学習を学ぶのが先決
  • (英語で観ることで)心理的ハードルが高くなって講座をやらなくなっては本末転倒

と開き直って全て日本語で観ました。


その後色々なオンラインコースが出てきてるし、もっと良いのがあるんじゃない?

このコースがいつからあるのかわかりませんが、たぶん2012年にはもうあったと思います。今では最初から日本人が日本語で解説している講座もあるでしょうし、ディープラーニングまでカバーしているものもありますし、評価が高いものもあります。


このコースが優れている点として、Andrew先生の説明がわかりやすい、実践的な内容である、といったことがよく挙げられますが、それらももちろん良いわけですが、


毎週のプログラミング課題の提出が義務付けられている


という点で、僕は他のオンライン講座と比べて圧倒的に良いと思いました。


動画で学んだニューラルネットワークとかレコメンドシステムを自分で実装して、毎週提出する必要があります*1


これが本当に素晴らしくて、

  • 動画を見てよく理解できなくても、自分でプログラムを書いてみるとよく理解できる
  • 動画を見て理解できたと思っていても、自分でプログラムを書いてみると理解が曖昧だった部分が浮き彫りになることがある
  • ちゃんと学んだという実感がある

という効果があると感じました。他のオンライン講座ではあまりこの形式は見たことなくて、どんなに動画が良くても、結局これがないと意味ないような、とさえ思います*2



ちなみに最近、『ゼロから作るDeep Learning』という書籍がとても評判が良く、これでゼロから学び始めた/学ぼうと思っている、という人も多いと思います。


ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装
斎藤 康毅
オライリージャパン
売り上げランキング: 65


僕も最近買って読んでみて、この本の「手を動かして自分で実装してみる」というコンセプトの良さに通ずるものが、このCourseraの機械学習コースもある、と思いました。上述しましたが学んだことは全て自分で実装することになるので。


ちなみにこの本とCourseraの機械学習コースは(被る部分もありますが)カバーする範囲が違うので両方ともやって損はないと個人的には思います。ディープラーニング本はディープラーニングに到達するための要素技術/知識を最短距離で学ぶ感じですが、Coursera機械学習コースはもっと機械学習の基本事項を広く網羅する感じです。*3


OctaveじゃなくてPythonでやりたい

「今機械学習やるならPythonだし、なぜOctave・・・?」というところで避けてしまう人も多いかもしれません。


もちろん僕もOctaveは初めて触りましたしこの講座以外でもう触ることもないんじゃないかとさえ思いますが、Octave独自の使い方とか記法を学ぶ、というオーバーヘッドはほとんどなかったと思います *4


プログラミング課題でやった実装は自分で中身を理解している(どういう関数を使っているか、なぜそういう計算をしているか)ので、つくったものをあとから他の言語やフレームワークに移植するのも簡単そう、と思っています。


今忙しいから落ち着いたらやろう

ここまで読んで、「良さそうだな」って思った方もいらっしゃるかもしれません。でも同時に「今忙しいので、落ち着いたらやろう」と思った方は多いんじゃないかなと推察します。仕事は毎日あるし、エンジニアは学ぶことは他にもいくらでもあるし。


僕もそうでした。仕事もプライベートもめちゃめちゃ忙しかったし、優先的に学ぶべき技術も他にあったので、「1ヶ月後ぐらいには今よりは落ち着いてるはずだからそのときに」って思いかけたのですが、ふとコースのカリキュラムを見て考えが変わりました。


「ニューラルネットワークぐらいはちゃんと理解したいな」と思っていたのですが、本コースでニューラルネットワークについて学ぶのはWEEK4, 5。ちゃんと1ヶ月後に受講開始したとして、順当に進めて、ニューラルネットワークの基礎を学べるのがその1ヶ月後。


この機械学習/ディープラーニングが盛り上がってる中、最低でもあと2ヶ月は自分はスタート地点にすら立てていないことになるのか、と愕然とし、すぐに始めることにしたわけです。


当初は修了することは重視してなかったので、いきなりニューラルネットの章だけやることも考えました。が、本コースのカリキュラムは知識が積み上がっていくようにデザインされていて、序盤の「線形回帰」とか「ロジスティック回帰」で学んだ知識はその後の章のあらゆる部分に関係してきたので、最初から通しでやってよかった、と思っています。


続けるコツ

こうやっておすすめしているわけですが、機械学習で何かをやる具体的な予定があるわけでもなく、仕事もプライベートも普通に忙しい、という状況においては実際のところ完走するのはなかなか大変なんじゃないかと思います。


僕は第1週目は「機械学習の歴史」みたいな流し見しても良い内容だろうと思って最初は気軽に始めてみたのですが、最初の動画だか2つ目の動画だかでもういきなり数式がバリバリ出てきて面食らった記憶があります。普通に気が重いです。


そんな中でも続けられた理由が3つほどあるなと思うので参考までに書いておきます。


1. 中間目標があった

当初は完走するつもりはなくて、とりあえず第5週のニューラルネットワークまではやろう、と思っていました。


で、第5週目までやって、修了証書が欲しいわけでもなかったのでやめてもよかったわけですが、その先のカリキュラムに「次元削減」「レコメンドシステム」等いくつか学びたい項目があったので、もうちょっとやってみるか、と。


8週目ぐらいまでやったとき、最後の第10週、第11週はプログラミング課題がないことに気づきました。実質あと2週がんばれば完走じゃん!と。


そんなこんなで、中間目標を見ているうちに完走できた、という話です。


2. 「挫折したらもう一生オンライン講座で勉強できない体になる」という意識があった

自分の性質上、一度自分の意志を折った前例をつくってしまうと、もうダメなんですよね。そこが基準になってしまう。


「今週めっちゃ忙しいけど、一週でもサボったらもうこの講座をやることはないだろう」


「この講座を完走しなかったら、もう一生どんなオンライン講座も完走することはないだろう」


極端だと思われるかもしれませんが、人生を40年近くやってきて実際そんな感じだったので、「ここでオンライン講座という貴重な学習の選択肢を失うわけにはいかない」という思いで後半は進めていました。


3. 適度に飛ばしながら進めた

例えば(上述した通り)Octaveの書き方の動画は飛ばしましたし、前半には結構あるテキストによる解説とPDFは全部飛ばしましたし、プログラミング課題の"optional"問題も容赦なく飛ばしました。やった方がいいのは間違いありませんが、挫折するよりは前に進んだほうがいいので。


まとめ

というわけでCourseraの"Machine Learning"、おすすめです!


*1:自動ですぐに採点されるようになっています

*2:宿題として課されなくても自分で手を動かして学べる人は別

*3:個人的には、先にCourseraの方をやり、後からこの本で(既に知っているところは飛ばしつつ)やった方がわかりやすいのでは、と思いました。

*4:序盤でOctaveの使い方の動画があるが、ほとんど飛ばして、テストと課題で必要になる度にググる、という方法で十分乗り切れました

2016-09-02

iOSDCのリジェクトコンで『iOSとディープラーニング』について話しました

一昨日メルカリさんのオフィスで開催された iOSDC Reject Conference days2 で、「iOSとディープラーニング」というタイトルで登壇させていただきました。



大層なタイトルですが、僕はディープラーニングや機械学習について詳しいわけではなく、「これから勉強したい」だけの素人です。iOSDCのCFPではLT枠の場合はトーク概要を書く必要がなかったので、タイトルは大きめにしておいて、内容は勉強の進捗に応じて、という算段でした。


で、先週あたりから夜な夜なこのへんの勉強をしていて、

この次に「自分でモデルをつくる」というステップに進みたかったのですが、次から次へとわからないことがでてきて、結局「誰かがつくったサンプルを動かす」「拾ってきたモデルを使う」止まりの発表になってしまいました。


そこは引き続き精進してまいります、ということで、以下補足を。


iPhoneでInception-v3モデルによるリアルタイム物体認識を動かす

TensorFlowのInception-v3を使った一般物体認識のデモをiPhoneで動かしたときの動画がこちらです。


f:id:shu223:20160902082200g:image


最初 [Notebook] [Laptop] を認識していて、カメラが下の方にいくと [Computer Keyboard] の順位が上がり、リモコンを映すと [Remote Control]、メガネを映すと [Sunglasses] が候補の上に上がってきます。*1


パフォーマンスもなかなかではないでしょうか。(用いたデバイスがiPhone 6sなので、ちょっとずるいですが。。)


サンプルを試す手順の詳細は下記記事にあります。


iOS 10で追加されたニューラルネットワーク機能群

LT5分だったのでここまで話せなかったのですが、iOS 10では2つのフレームワークにニューラルネットワークを高速計算するための機能群が追加されました。


ひとつは BNNS (Basic Neural Network Subroutines) と呼ばれていて、Accelerate Framework に新規追加されました。Accelerate は CPUで高速計算を行うためのフレームワークです。


そしてもうひとつは CNN(Convolutional neural network) で、MetalPerformanceShaders Frameworkに新規追加されました。Metal Performance Shaders はGPUで高速計算を行うためのフレームワークです。


で、どちらも同じような用途の機能が用意されていて、素人からするとGPUで処理するほうが良さそう、と思うのですが、わざわざ2種類出してきたからにはきっと一長一短あるのでしょう。もっと詳しい方が書いた記事があり、その記事ではこれらの比較についてこう述べられています。

AccelerateとMetalは、非常によく似たニューラルネットワーク関数群を提供しているので、どちらを選択するかは、各アプリケーションに依存します。GPUは、通常、機械学習に必要な種類の計算には望ましい反面、データの局所性によって、Metal CNNのパフォーマンスが、Accelerate BNNSバージョンより劣る場合があります。GPUにロードされた画像上でニューラルネットワークを動かす場合、例えば、MPSImageと新しいMPSTemporaryImageを使うと、Metalの方が明らかにパフォーマンスが上です。


MPSCNNのサンプル

BNNSの方も公式サンプルはあるのですが、今のところMac OS X用のものしかありません。MPSCNNの方はメリットやパフォーマンスを把握するのに最適なiOS向け公式サンプルが2つ出ています。

  • MPSCNNHelloWorld・・・MPSCNNで手書き数字認識
  • MetalImageRecognition・・・MPSCNN+Inceptionモデルで物体認識

ちなみに"MPS"は MetalPerformanceShaders のプレフィックスで、CNN関連の機能にはMPSCNNというプレフィックスが付いています。


で、上の手書き文字認識の方(MPSCNNHelloWorld)がシンプルで非常に理解しやすく、最初の一歩にすごく良いです。ベータ期間中につきサンプルのスクショは控えます。


f:id:shu223:20160902080706j:image:w500


上の画像(発表資料p35)はWWDC16のセッションスライド内にあった多層ネットワークの概念図に、該当するMPSCNNのクラス名を書いたものですが、わりとそのまんまで、CNNの概念を理解していれば非常に使いやすそうです。

  • Convolution Layer(特徴量の畳み込みを行う層): MPSCNNConvolution
  • Pooling Layer(レイヤの縮小を行い、扱いやすくするための層): MPSCNNPooling
  • Fully Connected Layer(特徴量から、最終的な判定を行う層): MPSCNNFullyConnected

(参考:no title


iOS 9以下でも使えるオープンソースのDL/NNライブラリ

iOS 10の話ばかりしても現実感がないかもしれませんが、"ios deep learning" とか "ios neural" とか "swift neural" とかでGitHub検索するとOSSがざくざく出てきます。


そのうち、100スター以上ついているものをピックアップしてみました。


f:id:shu223:20160902080845p:image:w500


TensorFlowがサンプル含めObjC、C++であるのに対して、Swiftで書かれているものも多いですし、Metal or Acceleratedフレームワークで高速化してあるものも多く、充実している印象です。


が、いざ試してみようとすると、サンプルもなかったり、最近はメンテされてなさそうだったりで、実際に使えるのは実はあまり多くないのかも、とも思いました。


もっともスターが多くついている「Swift-AI」については下記記事で紹介しています。


ディープラーニングの基本概念を学ぶのに良かった本

発表内では触れてないのですが、ディープラーニングというか人工知能というかそういう系の話はWebに解説記事も多く、逆にどこから手を付けていいかわからない、という状態に長らく陥っていました。で、とある機会に会ったこの分野でゴリゴリやってる人に教えてもらったのが下の書籍です。


脳・心・人工知能 数理で脳を解き明かす (ブルーバックス)
講談社 (2016-05-27)
売り上げランキング: 6,089


人間の脳のしくみから読みやすい文章で紹介してあって、いきなり数式ベースの解説があると「また今度にしよう」となってしまう自分には入り口として最適でした。


今後の展望

TensorFlowにしろiOSのBNNS/CNNにしろ、学習済みモデルの中身というかフォーマットがよくわかってないので、次はそのあたりを調べたいと思ってます。


*1:このとき食べていたアイスクリームも見事に認識してくれたのですが、食べかけだったのでカットしました

2016-07-20

TensorFlowをiOSで動かしてみる

TensorFlow に iOS サポートが追加された というニュースを見かけたので、ビルドして、iOSで動作させてみました。


f:id:shu223:20160720074930j:image:w240

たまたま目の前にあった扇風機もバッチリ認識してくれました)


本記事では最終的にうまくいった手順を書いています。この手順をなぞってみるにあたってTensorFlowや機械学習・ディープラーニングについての専門知識は不要ですのでぜひお試しください!


ビルド手順

(2017.4.15追記)v1.1.0 RC2 のビルド

現時点での最新Release(候補)である v1.1.0 RC2 も、tensorflow/contrib/makefile/build_all_ios.sh を実行するだけでビルドできました。


(2016.8.22追記)v0.10.0 RC0 のビルド

現時点での最新Releaseである v0.10.0 RC0 は、上記手順でビルドしようとすると compile_ios_tensorflow.sh を実行するところでコケてしまったのですが、今は各ビルドの手順がまるっと入ったスクリプトが用意されているようです。

tensorflow/contrib/makefile/build_all_ios.sh

依存ライブラリのダウンロードからiOSアーキテクチャ向けビルドまで、これ一発でokでした。


(※旧バージョンでの手順)v0.9.0 のビルド

iOSサポートバージョンであるv0.9.0をチェックアウトして、以下の手順でビルドしていきます。手順はこの通りになぞるだけですし、ほぼスクリプトを実行するだけで非常に簡単です(が、実行時間がかなりかかります)。


  • スクリプトを実行して Eigen や Protobuf 等の依存ライブラリをダウンロード
cd tensorflow
tensorflow/contrib/makefile/download_dependencies.sh

  • protobuf をビルド&インストール
cd tensorflow/contrib/makefile/downloads/protobuf/
./autogen.sh
./configure
make
sudo make install

ここで、僕の環境では `./autogen.sh` 実行時に

Can't exec "aclocal": No such file or directory at /usr/local/Cellar/autoconf/2.69/share/autoconf/Autom4te/FileUtils.pm line 326.
autoreconf: failed to run aclocal: No such file or directory
shuichi-MacBook-Pro-Retina-15inch:protobuf shuichi$ ./configure
-bash: ./configure: No such file or directory

というエラーが出ました。”aclocal”というのは、”automake”パッケージに含まれているらしいので、automakeをインストール。

brew instal automake

で、改めて

./autogen.sh
./configure
make
sudo make install

  • iOS native版のprotobufをビルド
cd ../../../../..
tensorflow/contrib/makefile/compile_ios_protobuf.sh

  • iOSアーキテクチャ向けにTensorFlowをビルド
tensorflow/contrib/makefile/compile_ios_tensorflow.sh

サンプルをビルドする

`tensorflow/tensorflow/contrib/ios_example` に2種類のサンプルがあります。


simple と名付けられたサンプルアプリは、今回ビルドした static library をアプリ内に組み込む際の最小実装としての参考にはなりそうですが、デモとして見て楽しい機能があるわけではないので、本記事ではもう一方の camera の方を紹介します。


まず、このファイルをダウンロードして、解凍すると入っている、

  • imagenet_comp_graph_label_strings.txt
  • tensorflow_inception_graph.pb

の2つのファイルを、`tensorflow/contrib/ios_examples/camera/data` に置きます。*1


この Inception というのはGoogleが提供する画像認識用の学習済みモデルのようです。


cameraサンプル実行例

cameraサンプルを実行すると、すぐにカメラが起動します。身近のものを色々と映してみました。(リアルタイムカメラ入力に対する認識結果を表示してくれます)


MacBook

f:id:shu223:20160720080028j:image:w240


"Notebook" "Laptop" どっちでも正解!


扇風機

f:id:shu223:20160720074930j:image:w240


"Electric Fan" 正解!


椅子

f:id:shu223:20160720080106j:image:w240


"Folding Chair"(折りたたみ椅子) 惜しい。。ですが、そもそも `imagenet_comp_graph_label_strings.txt` には chair が3種類しかなくて、その中では一番近いと言ってもいいかもしれません。


iPhone

f:id:shu223:20160720080129j:image:w240


"iPod"・・・惜しい!iPhoneなのでほぼ正解と言ってもいいかもしれません。


パフォーマンス

今回cameraサンプルを試したデバイスはiPhone 6だったのですが、認識はまだまだリアルタイムとは言い難く、数秒単位の遅延がある感じでした。まだiOS向けにビルドできるようになったというだけでiOSにおける GPU Accelerated はされてないですし、パフォーマンスの最適化はまだまだこれからのようです。


(2017.4.15追記)v1.1.0 rc2 / iPhone 7 で試したところ、それなりにリアルタイムで動きます。`contrib/ios_examples` 配下のコミットログを見たところ、Metal等による最適化はまだされてないようですが、いくつかパフォーマンスに関連しそうな改善はあったようです。

(追記ここまで)


ちなみにiOS 10 で Accelerate.framework に追加された BNNS (Basic neural network subroutines) や MetalPerformanceShaders.framework に追加されたCNNのAPIを使用する最適化もissueに挙がっています。


MPSCNNについてはいくつか記事を書いたのでよろしければ:


ビルド手順の情報ソース

iOSサポートバージョンである0.9.0トップ階層にあるREADMEを見ても、iOSについては書かれていません


上述したビルド手順は`contrib/makefile` 配下のREADMEに書かれています。

関連情報を以下にまとめておきます。


サンプルのソースコードを読んでみる

サンプルは全編Objective-C++で書かれています。読んでもわからないだろうと思いつつ、せっかくなので読んでみます。


tensorflow_utils

モデルとラベルデータを読み込むメソッドと、認識結果を返すメソッドを持つユーティリティクラスのようです。

tensorflow::Status LoadModel(NSString* file_name, NSString* file_type,
                             std::unique_ptr<tensorflow::Session>* session);
tensorflow::Status LoadLabels(NSString* file_name, NSString* file_type,
                              std::vector<std::string>* label_strings);
void GetTopN(const Eigen::TensorMap<Eigen::Tensor<float, 1, Eigen::RowMajor>,
             Eigen::Aligned>& prediction, const int num_results,
             const float threshold,
             std::vector<std::pair<float, int> >* top_results);

汎用的に使えそう。


ios_image_load

画像ファイルを読み込むクラス。

std::vector<tensorflow::uint8> LoadImageFromFile(const char* file_name,
             int* out_width,
             int* out_height,
             int* out_channels);

プロジェクトには追加されているけど使われてないっぽい。


CameraExampleViewController

サンプル本体。肝っぽいところだけを拾っていくと、


`std::unique_ptr<tensorflow::Session>` なメンバ変数を定義して、

std::unique_ptr<tensorflow::Session> tf_session;

viewDidLoadのタイミングでモデルを〜.pbファイルからロード

tensorflow::Status load_status =
  LoadModel(@"tensorflow_inception_graph", @"pb", &tf_session);

で、カメラからのリアルタイム入力が得られるたびに呼ばれるデリゲートメソッドを見てみると、

- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
       fromConnection:(AVCaptureConnection *)connection {
  CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
  [self runCNNOnFrame:pixelBuffer];
}

CMSampleBufferRef から CVPixelBufferRef を取得して `runCNNOnFrame:` を呼んでいるだけのようです。


`runCNNOnFrame:` はコードが若干長いですが、このへんと、

tensorflow::Tensor image_tensor(
    tensorflow::DT_FLOAT,
    tensorflow::TensorShape(
        {1, wanted_height, wanted_width, wanted_channels}));
auto image_tensor_mapped = image_tensor.tensor<float, 4>();
tensorflow::uint8 *in = sourceStartAddr;
float *out = image_tensor_mapped.data();

このへんが肝っぽいです。

if (tf_session.get()) {
  std::string input_layer = "input";
  std::string output_layer = "output";
  std::vector<tensorflow::Tensor> outputs;
  tensorflow::Status run_status = tf_session->Run(
      {{input_layer, image_tensor}}, {output_layer}, {}, &outputs);
  if (!run_status.ok()) {
    LOG(ERROR) << "Running model failed:" << run_status;
  } else {
    tensorflow::Tensor *output = &outputs[0];
    auto predictions = output->flat<float>();

    // ラベル取得
  }
}

が、すみません、それぞれ何をやっているのかを解説するにはTensorFlowの処理をちゃんと理解する必要がありそうです。。(勉強します)


自分のアプリに組み込む

試せていませんが、こちら に手順が示されていました。

  • ユニバーサルなstatic library(libtensorflow-core.a)をビルドしてプロジェクトに追加する
    • [Library Search Paths] にも追加。

The `compile_ios_tensorflow.sh' script builds a universal static library in tensorflow/contrib/makefile/gen/lib/libtensorflow-core.a. You'll need to add this to your linking build stage, and in Search Paths add tensorflow/contrib/makefile/gen/lib to the Library Search Paths setting.

  • libprotobuf.a と libprotobuf-lite.a をプロジェクトに追加する。
    • [Library Search Paths]にも追加

You'll also need to add libprotobuf.a and libprotobuf-lite.a from tensorflow/contrib/makefile/gen/protobuf_ios/lib to your Build Stages and Library Search Paths.

  • [Header Search paths] を追加

The Header Search paths needs to contain the root folder of tensorflow, tensorflow/contrib/makefile/downloads/protobuf/src, tensorflow/contrib/makefile/downloads, tensorflow/contrib/makefile/downloads/eigen-eigen-, and tensorflow/contrib/makefile/gen/proto.

  • [Other Linker Flags] に `-force_load` を追加

In the Linking section, you need to add -force_load followed by the path to the TensorFlow static library in the Other Linker Flags section. This ensures that the global C++ objects that are used to register important classes inside the library are not stripped out. To the linker, they can appear unused because no other code references the variables, but in fact their constructors have the important side effect of registering the class.

  • bitcodeを無効にする

The library doesn't currently support bitcode, so you'll need to disable that in your project settings.


まとめ

TensorFlowをiOS向けにビルドし、付属のサンプルを動かしてみました。パフォーマンスの最適化等、まだまだこれから感はありますが、扇風機や椅子、ノートパソコンやiPhone等、大きさも形も全然違うものを認識してくれて未来を感じます。


試してみるだけなら機械学習やTensorFlowについての専門知識を必要としませんし、ぜひお手元で動かしてみてください!


次のステップとしては、下記記事で紹介されているテンソルの計算部分に特化してSwiftで書かれたライブラリと比較したりしつつ、ちゃんとTensorFlowでやっていることを理解したいと思います。


また、本記事同様に「とりあえず動かしてみる」シリーズとして、こちらもよろしければどうぞ:


*1:ちなみにこのとき、 https://github.com/miyosuda/TensorFlowAndroidDemo/find/master にある同名ファイルを使っても、ちゃんと動きません。参考

2009 | 08 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2012 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2013 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2014 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2015 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2016 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 11 | 12 |
2017 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2018 | 02 |