Hatena::ブログ(Diary)

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

2017-01-11

「シリコンバレーで働くエンジニアと考える、これからのキャリア」という授業をしました

オンライン動画学習サービスSchoo(スクー)で、「シリコンバレーで働くエンジニアと考える、これからのキャリア」と題した授業をさせていただきました。*1



撮影を生放送で行い、視聴者参加型で行う授業でした。もちろんキャリアに正解なんてないし、キャリア観も人によって千差万別なので、僕が何かを教える、というよりは、まずは僕の経験や考えを共有して、あとはコメント・質疑応答ベースでみんなで考えていきましょう、的なコンセプトです。


f:id:shu223:20170111081424j:image:w600


講義

最初に30分(ホントは20分の予定だったのですが🙇🏻)の講義パートがありました。


講義資料はこちら。*2



  1. 自己紹介(僕のキャリアの変遷をざっと説明)
  2. 僕のキャリア観(理想)
  3. その実現のために意識していること4つ

という3段構成です。


以下に簡単に抜粋します。


自己紹介(キャリアの変遷)

20代は大企業志向 → ベンチャー → スタートアップ → フリーランス → いまは30人ぐらいのスタートアップ


f:id:shu223:20170111081032j:image:w600

給与の変遷グラフというちょっと生々しい話もあります) *3


僕のキャリア観
  • グリーンカードを取得し、海外に移住したい
  • いずれは起業し、世界を変えたい
  • 技術で世界を良くしたい

いずれも素晴らしいことだと思うけど、そこを目指しているかというとそうでもない。


f:id:shu223:20170111205931j:image:w600


時流や自分の興味が移り変わる中で、その時々でおもしろいと思える選択肢を取れる自分でありたい


→ 言うのは簡単だけど、実践するのはなかなか大変

  • 同じ程度の成功では達成感を感じられない
    • かといってより大きい成功をし続けるのは簡単ではない
  • 同じことをやっていると飽きる
    • アプリをつくることが「無条件に」楽しい、という時代はとうに過ぎた
    • 海外で仕事してテンション上がっても3日で慣れる
  • 新しい技術を短時間でマスターするような天才でもない

「おもしろがり続ける」のは大変!


そんなキャリア観の実現のために意識していること4つ

1. 勉強を仕事に繋げる

  • 新たな刺激のある仕事を獲得するために、新しい技術を習得する必要がある
    • 短時間でマスターするような天才ではない
    • 必要に迫られてない勉強を継続することは難しい
  • 20時間の法則:未経験の人から見ると「すごい!」っていうぐらいのレベルにはなる
  • 自分の得意領域と組み合わせれば、仕事を獲得できる
    • フルタイムで経験を積める
    • 仕事だから続けられる!稼げる!

2. "Searchable"になる

  • おもしろい仕事が来るポジションにいるには?
    • 求人が出たり、プロダクトが話題になるタイミングで自分からアクションするのでは遅い
    • おもしろい人がおもしろいことを始めるタイミングで声をかけてもらいたい
  • 「自分が何ができる人で、何をやりたい人か」を示し、それを必要とする人に見つけてもらえるようにする

3.「許容できるリスク」を知る

  • 技術力だけ追い求めても上には上がいてキリがない
    • ので、何か別のところで違いを出したい
    • 自分の経験上、ちょっとした「行動力」で意外な程に違いが出る
  • 他人はなかなかやらない「ハイリスク・ハイリターン」な行動があるとして、そのリスクを「自分は」許容できるのであれば、それは自分にとって「ローリスク・ハイリターン」な行動となる
  • → リスクを取らずにリターンを得られる
  • 例:英語も話せないのに海外に飛び込む「不安」は自分にとって許容できるリスク
  • 逆の例:車を運転して事故るかもしれないというのは他人にとって許容できるリスクのようだが僕にとっては許容できないリスク(怖くてできない)

4. 引き際も大事

  • モチベーションMaxで取り組むほうが雇い主/自分双方にとって良い
  • おもしろい仕事をやってるときは遊びの予定よりも仕事の方がおもしろい
  • 日曜夜に残念な気持ちになるなら黄色信号
  • → 引き際も大事

質疑応答

残りの時間は質疑応答でした。やはりキャリアについてはみなさん気になるところが多いようで、授業が延長されるぐらいにコメント、質問をたくさんいただきました。


実際のQ&Aはスクーで見ていただくとして、以下に目次を載せておきます。

  • アメリカに行った理由
  • Q.英語はどのようにして身につけたのでしょうか?
  • Q.日本と海外で働くのどちらが面白いですか?
  • Q.アメリカの就職事情は?スタートアップへの就職で大切なポイントはどこでしょうか?
  • Q.質問です!海外で仕事することに関して奥様から反対とか無かったのですか?
  • Q.シリコンバレーだからこそ日本と環境面で何が異なるかを知りたいです。
  • Q.アメリカで求められるエンジニアってどんな人ですか。データ分析?人工知能?
  • Q.現在、海外で働きながらフロントエンジニアを目指していますが、カヤック時代は一日に何時間、プログラミング学習をしていましたか?(平均睡眠時間が8時間と仰っていたので)
  • Q.シリコンバレーで起業する準備としてするべきことを教えてください。
  • Q.堤さんがエンジニアとして海外に居ても日本に居ても1日の中で最も大切にしていることは何でしょう
  • Q.シリコンバレーにおいて、エンジニアのキャリアはどういうものがあるのですか?ずっとプログラマーのままの人もいらっしゃいますか?
  • Q.日本とアメリカでは開発に対する考え方(リスク等)に違いがあると思います。その考え方の違いについてお話を伺いたいです。
  • Q.面白い仕事をどのように探し続けているですか?教えて頂けますか?
  • 受講生の皆様へのメッセージ

撮影風景

スタジオはこんな感じでした。


f:id:shu223:20170106201910j:image:w600

(カメラが3台、モニタも3台、でかい照明もあります)


スタジオに行くまで、普通のハンディカムみたいなので撮影するもんだと思ってました。。こういう本格的な撮影は初めてなので、楽しかったです。


関連記事/参考資料

本授業に関連する記事をまとめておきます。

プログラミング初心者時代の話
海外登壇
フリーランス時代の海外での仕事
その他海外関連
今回の就職の経緯
情報発信について

おわりに

スクーの皆様、生放送に参加していただいた皆様、どうもありがとうございました!

f:id:shu223:20170111081523j:image:w600

(スクーのみなさんと)


最後に改めて授業へのリンクを載せておきます。


*1:僕が働いてるのはサンフランシスコであってシリコンバレーには含まれないらしいのですが、僕自身も最近知ったぐらいなので、そこらへんは許容していただけるとありがたいです😅

*2:スライド共有サービスにアップしてブログに載せてもいいかはスクーさんに確認済みです

*3:こうやってみると今が一番高くて「さすがアメリカ!」ってなるかもしれませんが、僕のアメリカでの評価はまだまだで、1日単価でいうと日本でのフリーランス時代の方が少し多いぐらいでした。フリーランス時代はお客さん仕事は6〜7割にして、残りの時間を新しい技術の勉強や書籍の執筆に充てていたので、年収としては今より低くなっています。

2016-11-13

iOS/MetalのシェーダをWebGL/GLSLから移植する

Metalでグラフィック処理を行うにしろ並列演算を行うにしろ、GPUに処理をさせるためのシェーダを書かないといけないわけですが、これがまだ情報が少なくて、「こういうシェーダを書きたいんだけど、誰かもう書いてないかな・・・」というときに参考になる近いものとかはそうそう都合よく出てこないわけです。


ただ、WebGL/GLSLの情報はググると山ほどあって、GLSL Sandbox という、Web上で編集できてプレビューできてシェアできるサイトもあり、何がどうなってそうなるのか理解できない難しそうなものから、ただの円といったシンプルなものまで、既に偉大な先人たちのサンプルがたくさんアップされています


f:id:shu223:20161113192400j:image:w600



Metalのシェーダというのは正しくは Metal Shading Language といいまして、C++をベースとする独自言語なのですが、まー概ねGLSLと一緒です。


実際にやってみたところ、GLSL -> Metal Shader の移植はほとんど単純置き換えで済み、Swift 2をSwift 3に直すのよりも簡単という感覚でした。


f:id:shu223:20161113192821j:image


いずれも画像等のリソースは使用しておらず、iOSデバイス上で、GPUによってリアルタイム計算されたものです。


実際のところ自分はゲーム開発やVJをやったりしているわけではないので、こういう派手なエフェクトではなく、線とか円とかグラデーションとかのもっと単純なものをMetalで動的描画したいだけだったりするのですが *1、移植が簡単に行えることがわかっていれば、GLSLを参考にMetalシェーダを書けるというのはもちろんのこと、GLSL Sandboxで動作確認しつつシェーダを書いて、できたものをiOSに移植する、ということもできるので、個人的にはMetalシェーダを書く敷居がグッと下がりました。


というわけで、以下GLSLのコードをMetalに移植する際のメモです。


雛形となるプロジェクトを作成する

プロジェクトテンプレートに "OpenGL ES" はあっても "Metal" というのはないのですが、"Game" というのがあり、次の画面で [Game Technology] の欄で Metal を選択すると、シンプルなMetalのプロジェクトが生成されます。


f:id:shu223:20161113194605j:image:w500


これをベースに、GLSLのコードを移植して来やすいように次のように手を入れました。(現時点ではGLSL SandboxのコードをiOSで動かしてみるべく、フラグメントシェーダだけに手を入れています)


1.「画面の解像度」をフラグメントシェーダに渡す

多くのGLSLのサンプルでは、xy平面における座標を 0.0〜1.0 に正規化した状態で取り扱っています。ピクセルベースの座標値をシェーダ側で正規化できるよう、画面の解像度をシェーダに渡すよう修正します。


まずはシェーダ側。下記のように引数に float2型の "resolution" を追加します。

fragment float4 practiceFragment(VertexInOut     inFrag      [[stage_in]],
                                   constant float2 &resolution [[buffer(0)]])

次にSwift側。下記のようにバッファを用意して、

var resolutionBuffer: MTLBuffer! = nil
let screenSize = UIScreen.main.nativeBounds.size
let resolutionData = [Float(screenSize.width), Float(screenSize.height)]
let resolutionSize = resolutionData.count * MemoryLayout<Float>.size
resolutionBuffer = device.makeBuffer(bytes: resolutionData, length: resolutionSize, options: [])

フラグメントシェーダ関数の引数にバッファをセットします。

renderEncoder.setFragmentBuffer(resolutionBuffer, offset: 0, at: 0)

こんな感じで正規化した座標値を算出します。

float p_x = inFrag.position.x / resolution.x;
float p_y = inFrag.position.y / resolution.x;
float2 p = float2(p_x, p_y);

GLSL Sandboxはスクリーンが必ず正方形なのですが、iOSデバイスはそうではないので、比率が変わらないようどちらもx方向の解像度(つまり幅)で割っています。


2. 「経過時間」をフラグメントシェーダに渡す

ほとんど同様です。シェーダ側では、引数に float型の "time" を追加します。

fragment float4 practiceFragment(VertexInOut     inFrag      [[stage_in]],
                                   constant float2 &resolution [[buffer(0)]],
                                   constant float  &time       [[buffer(1)]])

Swift側。下記のようにバッファを用意して、

var timeBuffer: MTLBuffer! = nil
timeBuffer = device.makeBuffer(length: MemoryLayout<Float>.size, options: [])
timeBuffer.label = "time"

フラグメントシェーダ関数の引数にバッファをセットします。インデックスが変わる点に注意。

renderEncoder.setFragmentBuffer(timeBuffer, offset: 0, at: 1)

時刻の更新時にバッファを更新します。

let pTimeData = timeBuffer.contents()
let vTimeData = pTimeData.bindMemory(to: Float.self, capacity: 1 / MemoryLayout<Float>.stride)
vTimeData[0] = Float(Date().timeIntervalSince(startDate))

GLSLを移植する際の改変点

GLSL を Metal に移植してくる準備が整いました。ほとんど同じ、と書きましたが細部はやはり違います。以下、大まかな移行ポイントです。

  • GLSLのフラグメントシェーダでは、最後に gl_FragColor にvec4値をセットすることで出力とするが、return で float4 なり half4 なりを返す

(例)GLSLの場合

gl_FragColor = vec4(color, 1.0 );

Metalの場合

return float4(color, 1.0);
  • 関数はプロトタイプ宣言が必要
    • これがないと、ビルド時に "No previous prototype for function 〜" というwarningが出る
  • vec2, vec3, vec4 -> float2, float3, float4
  • ivec2, ivec3, ivec4 -> int2, int3, int4
  • mat2, mat3, mat4 -> float2x2, float3x3, float4x4
    • コンストラクタも微妙に違う(float2x2ならfloat2を2つ渡す。公式ドキュメントp15あたり)
  • const -> constant
  • mouse.x, mouse.y -> 適当に0.5とか

また出てきたら追記します。


GLSL Sandboxから移植してみる

GLSL Sandboxでいくつかピックアップして上記手順でMetalに移植し、iOSで動かしてみました。それぞれの移植にかかった時間は5分ぐらいです。ほとんど単純置き換えで済みました。


http://glslsandbox.com/e#36694.0

f:id:shu223:20161113193424g:image


http://glslsandbox.com/e#36538.3

f:id:shu223:20161113193507g:image

※デフォルトのITERATIONS 128では3fpsぐらいしか出なかったので、ITERATIONS 64に変更


http://glslsandbox.com/e#36614.0

f:id:shu223:20161113194708g:image


まとめ

GLSLをMetalに移植する手順について書きました。


上にも書きましたが、Metalをさわりはじめたときはシンプルなものすら書き方がわからなくて四苦八苦したので、「GLSLのコードも参考になるんだ!」と気付いたときはMetalの敷居がグッと下がった気がしました。


MetalはiOS 10からニューラルネットワーク計算のライブラリも追加されたこともあり、自分的に今一番熱い分野です。引き続きシェーダの具体的な書き方や、SceneKitを併用して3D空間内のノード上にMetalでテクスチャを動的描画する方法、デバッグツールの使い方等、色々と書いていきたいと思います。



*1:線とか円とかの単純なものでも、カメラプレビューで動的かつリアルタイムに、かつ他の重い画像処理と一緒に、といった場合、そして描画数が多かったり毎フレームの更新が必要な場合、やはりUIKitやCoreGraphicsでは厳しい場面が出てきます。

2016-09-29

フリーランスを休業して就職します

2014年からフリーランスiOSプログラマとして活動を始めて2年と8ヶ月。フリーランスという働き方は自分には最高にしっくりきてて、毎日楽しくお仕事させていただいてたのですが、色々とタイミングが重なりまして、タイトルの通り、いったん休業して「会社員」になることにしました。


どこに就職するのかと言いますと、サンフランシスコにあるFyusionというスタートアップにジョインします。


f:id:shu223:20160929075342p:image:w400


無事H-1Bビザが通りまして、ちょうど昨日、スタンプの押されたパスポートが郵送されてきたところです。


フリーランスとしての実績もまとめたいところですが長くなるのでここでは省略して、ご報告の意味でも、自分の考えを整理しておく意味でも、就職することにした経緯や理由等を書いておこうと思います。


経緯

上述しましたが、僕はフリーランスという立場を100%楽しんでいましたし、海外企業も含めて「就職」したいという願望はありませんでした *1


以下は今年の3月ごろの話です。当時の状況としては、

という感じで、「フリーランスとして」「日本をベースにしつつ」「たまに海外に」行けたら楽しいなというスタンスで動いていました。


投資家からのコンタクト

3月はじめ頃のある日、とあるベンチャーキャピタルの方から会いたいという連絡をいただきました。この時点では何の用事かわからなかったのですが、普通に考えて投資先のアプリ開発を手伝って欲しいという話だろうなと。


(VCの人とか上位レイヤーすぎて、末端で手を動かしてるエンジニアなんて駒としか思ってなさそう)・・・という勝手な偏見もありつつ、ちょっと疑心暗鬼のままお会いしたのですが、まずは自己紹介がてらそのVCの投資先について一通りご説明いただいて、これがまた僕的にはどの会社のプロダクトもおもしろかったわけです。*3


で、実は投資先の会社のCEOが僕と話したいと言ってきてる、と。(たぶんGitHubで見つけたんだと思います。それしか入り口がないので)


その会社がFyusionなわけですが、この時点でもう僕は少なくとも何らかの形で関わりたいと思うぐらいには惹かれていて(後述します)、でもどういう「話」なのかはわからないのでまずは話してみよう、という感じでした。


CEOとのスカイプ

その翌週ぐらいにCEOのRaduとスカイプすることになり、僕が次の用事があったので実質3分ぐらいしか話せなかった *4 のですが、その3分でRaduは、ユーと仕事をしたい、働き方はパートタイムでもフルタイムでもリモートでも希望通りでいいよと。で、僕は働くなら一緒に顔を突き合わせてやりたい、と。おおそれじゃあビザの申請マジで急がないといけないからすぐにファウンダー達と話してよ、と。


3分で一気に事が進みました。


ちなみにこのとき確か3月中旬ぐらい。H-1Bビザの申請は4/1にオープンして、一瞬で埋まります。そしてさらに僕が3月後半からドイツに行く予定があり、申請書類の準備期間は実質一週間ぐらいしかありませんでした。


ファウンダー陣とのスカイプ

メールで時間調整して、翌日の午前中にはファウンダー陣とスカイプすることになりました。


正直、グダグダ、どころか95%相手が何言ってるかわからなかったです。第一声でPardon?って言った気がしますが聞き返しても聞き取れないのでそれも言わなくなりました。


唯一、"Printer"とか特徴的な単語がひとつだけ聞き取れたりして、「Canon時代の仕事について聞いてますか?」と確認してしゃべる、みたいな感じでどうにかこうにか乗り切りました。


参考:


そしてオファー

とはいえ全然トンチンカンなコミュニケーションをしてたとは思うので、これは「ない」だろうなと思ってたら、スカイプの30分後だか1時間後だかにオファーのメールが!


条件を確認して、外出していた奥さんに電話かけて「〜ということなんだけどサインしていい?」って聞いて、サインして返送。あちらからもすぐにサイン入りのが返ってきました。


のべ2時間ぐらいのスピード就活でした。ビザ申請の期限という後押しがなかったらもっと迷っていたかもしれません。


Fyusionに惹かれた点

大きく分けて2点あります。

「欲しいスキル」が得られそうだった

僕が身につけたいと思っているスキルに、「英語」「コンピュータビジョン」「3Dプログラミング」「機械学習」があります。


で、Fyusionは、

  • CEOのRaduは、3D点群処理のオープンソース・プロジェクト「Point Cloud Library (PCL) 」の設立者
  • OpenCVのコミッタでもある
  • 他のファウンダー陣・メンバーもロボット工学・3Dコンピュータビジョン・機械学習とかの博士号もってる人がゴロゴロ
  • 提供しているサービスもそれらの技術をベースとしている
  • もちろん英語を使う

というわけで、全部揃っているなと。


やろうとしていることが腹落ちした

彼らは「空間写真」を撮るアプリ「Fyuse」というプロダクトを既に世に出していて、


f:id:shu223:20160929091526p:image:w300

(Fyuseのわかりやすい記事:動画ともパノラマとも違う“空間写真”ってなんだ? Fyuse創業者に話を聞いた | TechCrunch Japan


こういうものを撮影してソーシャル上にシェアできるアプリです。

f:id:shu223:20160929085556g:image:w200

(Fyuseの空間写真をアニメーションGIFに変換したもの)


このアプリは一見飛び道具感があるのですが、中では実際に撮影された動画とスマホの各センサの値から対象を3次元モデルとして解析しています。


f:id:shu223:20160929041931p:image:w600


上に貼った例をよく見ると、人間の向きと3次元のロゴの向きが一致していることがわかると思います。



これはいわば「普通のスマホのカメラを3Dスキャナにする技術」をSNSという使ってもらいやすい形で提供しているようなもので、


「3次元データがたくさんあれば我々の得意分野である3Dコンピュータビジョンの技術でいろんなおもしろいことができるぞ!」


というところに彼らのやりたいことがあります。単にギミッキーな写真撮影SNSをつくってるわけじゃないぞと。



たとえば最近では、このFyuseで撮ったデータをHoloLensでホログラム投影、みたいなことをやってたりします。


僕はハードウェアという「現実世界のモノ」と繋がるアプリの開発を色々やってきて、やはりその「現実世界を見る『目』」のところで技術的強みがあると楽しいよなー、ということを常々感じていたので、彼らのやろうとしていることは非常に腹落ちしたわけです。



あと、Fyuseは普通に撮影フォーマットとしてもかなり可能性があるんじゃないかと思っています。一見ギミッキーですが、写真よりも多面的に記録でき、動画よりも軽量で柔軟に閲覧でき、2Dだけど3Dモデル的な情報も持っているという点で、「空間を捉える」ためのフォーマットとして普遍的な良さがあるなと。


2ヶ月間リモートワークしてみてのPros/Cons

フリーランスでお手伝いしていたところは7月までに収束させて、8月からリモートで手伝い始めてます。当然Pros/Cons両方あります。

Pros
  • AVFoudation, Core Image, Metal/MetalKit/MetalPerformanceShaders, Acceralateと、iOSアプリ開発の中でも特に興味のある部分の実装に携われている
  • iOS 10とかの新機能を積極的に使っていく雰囲気がある
    • バージョン互換とかは後から考えよう、という感じ
  • CEO, CTO, その他ファウンダー陣全員が毎日ゴリッゴリにコードを書いている
    • 一番ソースを把握してるのは彼ら。
Cons
  • チャットの速さに全然ついていけない
    • 全部読んでたら仕事にならない
    • 流し読みしても情報量0%なのでもはやメンションくれない限り読んでいない
  • フリーランスとしての立場が恋しい
    • おもしろい仕事の話をいただいたり、おもしろいことをやってる人に会っても、そこから展開させられないのがもどかしい

サンフランシスコには引っ越しません

あっちに住んで仕事をしてもOKなビザを獲得したわけですが、家庭の事情もあり、基本的には東京にいます。今のところは、1ヶ月アメリカ(オフィス)、2ヶ月日本(リモートワーク)、ぐらいのつもりです。


が、変わるかもしれません。フリーランスとしての働き方も、最初はリモート指向だったけど早々にお客さんのところに行ってやるスタイルに変えたり、短納期案件が楽しいとかじっくりやる方が楽しいとか時期によって色々変遷があったりもしたので、日米往復生活もやりながら試行錯誤していくつもりです。


まとめ

というわけで、長くなりましたが、フリーランス生活をエンジョイしていたところで急に降ってきたご縁で大きく方向転換することになりました。


そもそもの目的である「身につけたいスキル」は身につくのか、アメリカと日本の往復生活は成立するのか、会議では全然聞き取れないだろうけど仕事になるのか等々、いろいろと不安もあります。通用しなくてすぐに逃げ帰ってくるかもしれません。


が、せっかくの機会なので、楽しみつつ色々と吸収してこようと思います!


*1:3年ほど前はありましたが

*2:詳細はこちら:iOSDCで発表しました『海外のiOSカンファレンスに登壇する - 完全版』 #iOSDC - Over&Out その後

*3:今回就職する会社ではないところで、その後アプリ開発をお手伝いしたところもあります。そこのプロダクトも相当ぶっ飛んでておもしろいので許可がとれたら紹介したい

*4:27分ぐらいRaduが会社の説明をしてて、残り3分になったところで「11時から別のスカイプあるんだけど・・・」とやっと切り出した

2016-09-14

iOS 10の新機能のサンプルコード集「iOS-10-Sampler」を公開しました

iOS 10でも大量のAPIが追加されました。が、新しいAPIはどう使うのか、実際に何がどこまでできるのか、といった具体的なところが、英語のドキュメントやWWDCのセッション動画をながめているだけだと正直あまりピンときません。やはり実際にコードを書いて動かしてみるのが一番わかりやすい・・・ということで今年もつくりました!


iOS-10-Sampler


f:id:shu223:20160914063446j:image:w600


恒例の新機能のサンプルコード寄せ集めアプリです。ソースコードは GitHub に置いてあるので、ご自由にご活用いただけると幸いです。


使い方は Xcode 8 でビルドするだけ なので、デザイナーさんやディレクターさんもぜひお近くのエンジニアにビルドしてもらってください。


f:id:shu223:20160914072119j:image:w600


iOSももうかなり成熟してしまい、話題になる革新的な新機能とか、どの開発者にとっても嬉しい新機能というのはなかなかないわけですが、実装してみると思ったより簡単なので自分のアプリにも取り入れたくなったとか、他の誰も話題にしてないけど自分的には熱いみたいな機能もあったので、ぜひ一度お試しいただけると嬉しいです。


また、Samplerシリーズでは「余計な実装を混ぜずに、新機能のメリットをできるだけシンプルな実装で伝える」というところに気をつけています *1。コピペもしやすいと思うので、自分のアプリに取り入れて動かしてみるとより楽しいかもしれません。


今のところ18個のサンプルが入っています。随時追加していきます。機能追加プルリク大歓迎です!


以下各サンプルの紹介です。


Speech Recognition

新たに追加された Speech Framework を利用した音声認識のサンプルです。


f:id:shu223:20160914070235j:image:w405


Appleのサンプルをベースに、全58種類の対応言語を選択する機能を追加しています。


Looper

AVFoundationに新規追加されたクラス AVPlayerLooper を用いた動画のループ再生のサンプルです。


f:id:shu223:20160914070311g:image:left f:id:shu223:20160914070308g:image



このクラス自体はプレイヤー機能は持っておらず、AVQueuePlayer と AVPlayerItem のインスタンス、そしてループする範囲を示す CMTimeRange オブジェクトを渡して使用します。

public init(player: AVQueuePlayer, templateItem itemToLoop: AVPlayerItem, timeRange loopRange: CMTimeRange)

Live Photo Capturing

写真撮影用に追加された新クラス AVCapturePhotoOutput を使用したライブフォト撮影サンプルです。*2


f:id:shu223:20160914070434j:image:w200


Live Photo のビューワーは iOS 9.1 から使えましたが、今回から撮影もできるようになりました。


Audio Fade-in/out

すごーく地味だし、このAPIがなくてもできたといえばできたことなんですが、実際に使う人は多いかもしれません。AVAudioPlayerにフォードイン/アウトするためのメソッドが追加されました。

// Fade In
player.setVolume(1, fadeDuration: 3)

// Fade Out
player.setVolume(0, fadeDuration: 3)

これタイマーとかでやってた人は嬉しいんじゃないでしょうか。


Metal CNN Basic: Digit Detection

Metal Performance Shaders フレームワークに追加されたCNN (Convolutional Neural Network / 畳み込みニューラルネットワーク)を用いた手書き数字認識のサンプルです。*3


f:id:shu223:20160914070517g:image


この「Metal AcceleratedなCNN計算処理」は個人的には今回一番熱い新機能です。



Metal CNN Advanced: Image Recognition

上のサンプルに引き続き、Metal Performance ShadersのCNNを利用したリアルタイム一般物体認識のサンプルです。*4


f:id:shu223:20160914070509g:image


速くて見づらいかもしれませんが、ノートパソコン(notebook)→ リモコン(remote control) → iPhone(iPod)と認識しています。


Metal ShaderというぐらいなのでGPUで処理されます。6s利用ですが、処理速度も申し分なしでした。(ちなみにMetalはAppleのハードウェアに最適化されたグラフィックスAPIで、「OpenGLより最大10倍速い」と言われています)


ちなみにミスリードもあるかもしれないので念のためですが、「一般物体認識」という新機能があるわけではないです。本サンプルで使用しているモデルはImageNetデータセットを用いてInception v3ネットワークをTensorFlowで学習させたもので、新機能はあくまで「Metal(GPU)でCNN処理」という部分になります。


PropertyAnimator: Position

アニメーション用の新クラス、UIViewPropertyAnimatorを用いて UIView オブジェクトの位置と、背景色をアニメーションさせるサンプルです。


f:id:shu223:20160914070727g:image


画面上をタッチしたままグリグリと動かしてみてください。touchMovedが呼ばれるたびにアニメーションが追加するという単純な処理をやっているのですが、いい感じに追随してくれるのが今回のクラスがアニメーションの追加をいい感じにやってくれてる *5 おかげなのかなと。


PropertyAnimator: Blur

UIViewPropertyAnimator の `fractionComplete` を用いて UIVisualEffectView / UIBlurEffect のブラーをアニメーションさせるサンプルです。


f:id:shu223:20160914070720g:image


やってることは超シンプルで、`effect` プロパティから UIBlurEffect を削除する処理を UIViewPropertyAnimator に登録しておいて、

animator = UIViewPropertyAnimator(duration: 0, curve: .linear) {
    self.effectView.effect = nil
}

スライダーの値に応じて `fractionComplete` を変化させています。*6

@IBAction func sliderChanged(sender: UISlider) {
    animator.fractionComplete = CGFloat(sender.value)
}

Preview Interaction

新クラス、UIPreviewInteraction で、3D Touchでピーク&ポップするサンプルです。


f:id:shu223:20160914070939g:image


Notification with Image

新しい通知のフレームワーク、UserNotifications framework を用いて、画像付きローカル通知を発行するサンプルです。


f:id:shu223:20160914033106j:image:w200:left f:id:shu223:20160914033113j:image:w200



Sticker Pack

iMessage のステッカーパックのサンプルです。


f:id:shu223:20160914032800j:image:w200


Messagesってメッセンジャーアプリとしてどれだけのシェアがあるの?という声も効きますが、ステッカーパックは画像をアセットカタログに入れていくだけの超超簡単実装なので、いい感じの画像を持っているアプリはやっといて損はないのかなと。


Core Data Stack

NSPersistentContainer を使うと Core Data の実装がシンプルになるよ、というサンプルです。


f:id:shu223:20160914034038j:image:w200


noliliさんよりpull requestいただきました!


TabBar Customization

UITabBarのバッジをカスタマイズするためのAPIが追加されました。*7


f:id:shu223:20160914034330j:image:w200


センスがなく、全然いい感じにカスタマイズできてないのが心残りですが。。


New filters

CIFilterで追加されたフィルタのサンプル。


f:id:shu223:20160914034350j:image:w200:left f:id:shu223:20160914034353j:image:w200



前回は豊作だったのですが、今回はちょっとしかありませんでした。。


New Fonts

新規追加されたフォントのサンプル。こちらも今回は少なく、4種だけ。*8


f:id:shu223:20160914034359j:image:w200


Proactive: Location Suggestions

NSUserActivityに新たに追加された `mapItem` プロパティを用いた "Location Suggestions" のサンプル。


f:id:shu223:20160914054654j:image:w200:left f:id:shu223:20160914071309j:image:w200



いわゆる「Proactive」というやつで、Appleから出てるサンプルがあるのですが、どの実装が何に効いているのか、というかこのサンプルをどう試すのか、というのがちょっとわからず(WWDCセッションをちゃんと見ればいいのかもしれませんが)、下記記事に助けられました。


Attributed Speech

AVSpeechUtterance に、NSAttributedStringを渡せるイニシャライザが新たに追加されたので、これを試すデモです。


NSAttributedString は文字列に色んな属性を指定できるわけですが、


これを音声合成の「Utterance」に渡せるということは、例えば、NSFontAttributeNameを用いてある範囲のフォントをboldにすると、その部分だけ強調されて発声されるとか、何か別の属性を使ってアクセントを制御できるとか、そういうことを期待したわけです。


が、結果は・・・何も起こりませんでした



同ツイートのメンションで岸川さんから `kCTLanguageAttributeName` で言語を切り替える、`kCTRubyAnnotationAttributeName` でルビをふる、といった文字列だけではなくて音声にも有用そうな属性を示唆いただきましたが、これらを試してみてもやはりあり/なしで違いは発声しませんでした。


何か私の実装が間違っているのかもしれませんし、プルリクをいただけるかもしれないので、サンプルとしては残してあります。


Haptic Feedback

iPhone 7のTapticEngineを利用するフィードバックのサンプルです。UI

ImpactFeedbackGenerator、UINotificationFeedbackGenerator、UISelectionFeedbackGeneratorの全てのパターンを試せます。


f:id:shu223:20170103172859j:image:w200


所感

箇条書きで。。

  • Notificationのカスタマイズ、ロック画面でプレビューは嬉しい
  • 標準で、ローカルで音声認識ができるようになったのも嬉しい
  • MPSCNNは熱いのでここはもっと勉強したい
  • iMessage app / Sticker Pack は当初まったく期待してなかったけど自分でやってみるとその簡単さとやっておいて損はない(親アプリがiOS 9でもok)という点で意外と熱い
  • UIViewPropertyAnimator、あまりワクワクするような新しさのあるものではなかったが、従来のものよりは便利なのでiOS 10以上のアプリでは普段使いすると思う
  • 3D TouchでPeek&Popは3D Touchデバイスが普及するまでは静観
  • Proactiveは今は静観
  • SiriKitは良いサンプルが思いつかず今回は入れなかった

デュアルカメラとか、Taptic Engine APIとか新デバイス系はまた後ほど。


おわりに

最初は個人的な勉強として始めたものがすっかり恒例になって、もうかれこれ4年もこれをやっています。


f:id:shu223:20160914061757j:image:w320


これがまぁなかなか大変で、それなりに時間がかかるので、周りの人には毎年「今年はやらないかも」とか毎年言ってて、なんだかんだやっぱり今年もつくってしまったという。







まぁ自分はやっぱり「新しいAPIが追加されると開発者としてできることが増える」のが好きなのと、(冒頭に毎年書いていることですが)自分で手を動かさないと全然理解できないというのがあるので、これはやっぱり続けた方がいいなと。


そんなわけで Apple Watch Series 2 が届いたら「watchOS-3-Sampler」もつくりたいと思います!


*1:Appleによる公式サンプルではアプリとしての体裁を整えるために新機能とは直接は関係ない実装がたくさん入っていたりしてややこしくなっているケースが多々ある

*2:Appleの「AVCam」サンプルをベースに、Live Photo撮影の実装だけを抜き出し、シンプルにしたもの

*3:本サンプルは、Appleの「MPSCNNHelloWorld」サンプルをベースに、不要な実装を除去しシンプルにしたもの

*4:本サンプルのモデルデータと、ネットワークの実装は、Appleの「MetalImageRecognition」サンプルをベースにしています

*5:WWDC16のセッション216でそんな感じのことを言ってました

*6:この手法は、こちらのコードで知りました: https://github.com/manuelCarlos/IOS10-Animate

*7:これらの追加APIについては、こちらの記事で知りました: [iOS 10] UITabBarのバッジを少しカスタマイズできるようになった - Qiita

*8:しかもFutura、AmericanTypewriterは従来からあるfamilyの太さ違い

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

(参考:Convolutional Neural Networkとは何なのか - Qiita


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:このとき食べていたアイスクリームも見事に認識してくれたのですが、食べかけだったのでカットしました

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 |
2017 | 01 |