Hatena::ブログ(Diary)

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

2016-02-01

第2回フリーランス海外遠征と2016年の生存戦略

1/12〜30の19日間、とあるスタートアップのお手伝いでドイツの首都ベルリンに行ってまいりました。


f:id:shu223:20160201082426j:image:w600

(今回の雇い主、Norman氏と、ベルリン大聖堂前にて。)


「あれ、前も行ってなかったっけ?」と思ったかもしれませんが昨年11月に行ったのは同じドイツでもバンベルクという都市で、今回とはお手伝いした会社も別です。


きっかけ

昨年9月に Hacker Paradise へ参加するためにベルリンに行った際にお会いした方よりご紹介いただきました。今回お手伝いした会社のCEO、Norman氏がiOSエンジニアを探してるという話が出た際に、僕のことを思い出して繋いでくれたと。


「フリーランスです、iOSが得意です、海外のお仕事大歓迎です」と何ができる/やりたい人かをなるべく多くの人に言っておくといいことある、とつくづく思いました。


条件面の調整

既にNorman氏の中でタスクリストとスケジュールが決まってて、全日程分の報酬+航空券+住居(後述)が最初のメールで提示されていました。僕を使うかどうか判断するための面接みたいなものはなく、たぶんLinkedInプロフィールやGitHubアカウントでスクリーニング的なことは完了していたものと思われます。


で、少しだけ金額面で交渉させてもらって *1、あとはスケジュールについて「順調にいけばそんなな感じのスケジュールで進むかもしれないけど、大抵なんやかんや想定外のことが起こるものなので、全部のタスクはできないかもしれないよ」というところは事前に言って承知していただきました。(このあたりの見積もりの考え方は こちらの記事 にも書きました)


やったこと

例によって詳しい内容はconfidentialですが、もちろんiOSアプリ開発ではあります。


利用技術的にはわりとオーソドックスなもの(一般的なUI+画像処理+ソーシャル機能)なので、漫然と既存スキルで時間を切り売りするようなことにならないよう、個人的なこだわりとして、なるべく「Swift的」な書き方を意識して書くようにしたりはしてました。(たとえば今まではCスタイルのfor文で書いてたところをSwiftスタイルで書いたりとか)


あと数年ぶりに In-App Purchase の実装をしたのも勉強になりました。*2


勤務時間は8:30〜17:30ぐらい。後述するように僕が住んでいたところがオフィスでもあるので、朝Normanが来て、一緒に仕事して、17:00〜17:30のキリがいいところでNormanが帰る、という感じでした *3


休日

当初の予定では 12日間 + 残りはフリータイムというスケジュールでしたが、10日で前倒しで作業が無事完了したので、余った2日分はお金いらないのでそこもフリータイムにしてほしい、と申し出ました。


というわけでまるまる1週間を自由に過ごせることになり、現地のSwift勉強会に行ったり、


f:id:shu223:20160130094423j:image:w600


あとは去年から始めたもののなかなか手を付けられてなかったプライベートな開発をやったりしてました。このへんはベルリンじゃなくてもできることですが、超有意義に過ごせたと思っています。*4


暮らし

オフィスが普通に住めるアパートなので、そこに住まわせてもらってました。ベルリンの一等地にあるビルの最上階にあり、見晴らしもよく、シャワーやら何やらすべて完備で最高に快適でした。


f:id:shu223:20160201083129j:image:w600

(オフィス兼宿。ベッドはロフトにあります)


食事は周囲にレストランがたくさんあるので、毎日「今日は○○料理が食べたい」みたいな感じでリクエストして、Normanにおすすめの店に連れて行ってもらう、みたいな感じで飽きることがなく、食生活の面でも充実してました。


英語

最近海外案件を受けるようにしているのは、単純に海外に行くのが楽しいし嬉しい、という以外に、ずっと苦手意識のある英語をそろそろ何とかしないと、ということで自分を英語を使わざるをえない環境に追い込むという目的もあります。


たかが2週間ちょっとでいきなり飛躍的に英語力が向上するわけもないのですが、マシになってきた気はします。Normanと飲みにいってわりと込み入った話をしたり。この仕様はこうこうこういう理由でおかしいからやめたほうがいい、と進言したり。まぁ、彼が文脈を大いに汲んで理解してくれる、というところも大きいですが。。


ただやっぱりまだまだまだまだ。なんというか、相手が自分のスキルを認めて雇ってくれて、こっちに歩み寄りつつコミュニケーションしてくれる、という前提の上であれば大丈夫なのですが、そうでないケースでの雑談とかはまだまだ厳しいです。引き続き機会を増やしていこうと思います。


今後の展望

まず、海外で仕事して毎回感じることですが、同じようなコードを書いてるだけでもめちゃくちゃ楽しいです。AutoLayoutのconstraintをポチポチ貼ってるだけでも「うぉー楽しい!」って思います。こういう高揚感は大事にしていきたいなと。


一方、これもベルリンだけでなくシリコンバレー等に行っても毎回感じることですが、無力感が半端ないです。仕事をやってみたりハッカソンに出てみたりして、技術的に通用しないということはないと思ってますが、誰も僕のことを知らないし(知名度以前に知り合いがいないという意味で)、そういう僕がベルリンに行ったところで、現地の他のスタートアップの方から「会いたい」とか言われることはありません。ミートアップに出ても誰にも話しかけられないし、ましてや人に紹介されることもありません。


で、自分から現地のスタートアップにアポとって会いに行ったり、ミートアップで話しかけたり、といったことをすればいいのですが、それは対症療法的だと思っていて、やはり日本でそうしてきたように、英語でブログ書いて、現地の勉強会でLTして、できれば英語で本を出す、ということをしないといけないなぁと。


たとえば僕の数々のBLE関連プロダクトに関わった経験・実績は世界のiOSエンジニアの中でも(今のところは)貴重な方だと思ってますが、


僕がニュースとかで海外のそういう系の魅力的なプロダクトを見るタイミングではもう遅くて(メディアに出て話題になっているということはある程度開発が進んでいるか完了しているケースが多い)ファウンダーが資金調達して本格的に開発をしようとするタイミングであちらから見つけてもらえるようにならないといけない。


で、LinkedIn や AngelList で人を探す場合は大抵「住んでいる場所」でフィルタされてしまうので *5英語ブログという「海外スタートアップに自分を見つけてもらうためのチャネル」を用意する必要があるなと。


僕のGitHubアカウントは今でも多少そういう感じの機能をしてくれてますが、

iOS Samplerシリーズのスター数に関して言えば、スクリーニングフェーズで僕が悪くないエンジニアであることを判断する材料にはなってるものの、海外に住んでるエンジニアを選ぶ「きっかけ」にはなっていない、と思っています。エンジニアにとって役立つ内容なので多くのスターをもらえてはいるものの、要素技術でみれば誰にでもつくれるものではあるので。


逆に、watchOS-2-Sampler はそんなにスターついてないけど、「(現時点ではニッチな)watchOS 2 の開発経験のあるエンジニア」というところで海外から僕を選ぶ「きっかけ」になってくれたわけで、そういうリポジトリを増やしていかないと、と。


長々と書きましたが、2016年の方針としては、もっと海外のお客さんに自分を見つけてもらえるように、

  • 英語でブログを書く
  • 「ニッチスキルに関わる」OSSをGitHubに積極的に上げていく
  • 海外にいったらLT枠とかに応募してみる

といったあたりをがんばっていきます。


*1:貴重な海外オファーなので最初に提示された価格でも受けたとは思いますが、普段の半分以下だったので一応

*2:数年前にローカルにまとめてた実装手順のメモがあったのですが、その頃のコードの酷いこと。。

*3:僕のプライベートを邪魔しないように気遣ってくれてるのか、いつもいそいそと帰る。あと絶対にいきなり部屋に来たりしない

*4:ひとりだとサボるので、現地で起業した日本人スタートアップのオフィスに毎日のようにお邪魔して作業させてもらったり、知り合いのエンジニアをさそってもくもく開発したりしてました

*5:本当にそうなのか実際のところ知らないのですが、住所がマウンテンビューだったときはめちゃくちゃメール来たのでそうだと思っています

2016-01-30

ドイツのSwift勉強会「swift.berlin #14」参加レポート #swiftberlin @swiftberlin

所用でドイツはベルリンに来てまして、1/18に開催されたSwiftのミートアップ「swift.berlin」に参加してきました。


f:id:shu223:20160130094509j:image


つい最近まで猛烈に英語に対して苦手意識があり *1、WWDC等でサンフランシスコ周辺に行く機会があってもあまりミートアップには参加してこなかったので、海外ミートアップ参加は3年ぶり人生2回目です。


概要

募集は meetup.com にて。


イベントページによると、参加人数は97人。実際に会場にそんなにいたかわかりませんが、50人は確実にいたと思います。


f:id:shu223:20160130094423j:image:w600


会場提供は wimdu 社、またビール等の飲み物もスポンサー(すみません、社名は失念)から提供されていました。


言語について

ドイツの公用語はもちろんドイツ語なわけですが、イベントは特に断りもなく(イベントページにそういう記載もなく)当然のように英語で始まり、その後のプレゼンも質疑応答もすべて英語でした。こちらでは当然なのかもしれませんが、日本ではなかなかないことなので、軽く一人でカルチャーショックを受けてました。。


※そういえば、前回参加したドイツのハッカソンでも当然のようにチーム内コミュニケーションもプレゼンも英語でした。


あと、こちらはプログラミング言語の話ですが、最初の主催者の方のトークで、「Swift書いてる人〜?」という質問があり、ほとんどの人が手を挙げていました。


で、次に、「まだObjective-Cしか書いてない人〜?」という質問があったとき、参加者側からクスクスと笑いが起きました。で、挙手した人はゼロ。


Swiftのミートアップなのでそりゃそうだという話はありますが、未だにObjCから移行しようとしないというのはそういうムードなんだなと。


発表1: Swift Package Manager

トップバッターは「try! Swift」にも登壇される Boris Bügling (@neonacho) さん。

Borisはベルリン在住のCocoaデベロッパーです。現在はContentfulでiOSのSDKを開発に携わっています。Java開発者としての一面や、たくさんのiOSアプリを開発した経験を持っています。彼はまたオープンソースの強力なコントリビュータでもあります。Xcodeをより使いやすくするためのプラグインを開発したり、“Senior VP of Evil”という肩書きでCocoaPodsの不具合を直しています。Ya tu sabes.(それじゃ、また。)

(try! Swift の紹介文より)


発表内容は先日のSwiftオープンソース化に合わせて公開された「Swift Package Manager」について。



簡単な使い方から始まり、現在の制限事項、自作パッケージのつくり方、テスト方法、パッケージマネージャの内部モジュールやビルドプロセスの解説、Packega.swiftの書き方、CocoaPodsやCarthageとの比較(この方は CocoaPods のコミッタでもある)等々、実に詳しい解説でした。


発表2: Beyond JSON with FlatBuffers

Maxim Zaks (@iceX33) さんの発表。JSONパーサ「FlatBuffersJson」について。



CocoaPods で swift, json で検索すると300以上のOSSが見つかるそうで、FlatBuffersSwift はその決定版になるとのこと。

そもそも FlatBuffers というのは Googleがゲーム開発またはパフォーマンスがクリティカルなアプリケーション用に作成 した serialization library だそうです。


発表3: Taking Swift to the Server

最後は Jens Ravens (@JensRavens) さんによる発表。Swift でサーバーサイドのコードを書く話です。



僕はサーバーサイドはできないので聞いてもポカーンとしそう、と思いましたが、スライドを見ればお分かりの通り、ブラウザにURLを入力するとHTMLが返ってくるまでにDNSサーバやアプリケーションサーバが何をするのかというところから始まり、リクエストやレスポンスをSwiftで書いてみましょう、次はルーティング処理を書いてみましょう、という感じでうまく噛み砕いて説明してくれて、わかりやすく面白かったです。


Swiftは今やとても人気のある言語ですし、Railsやnode.jsに代わるWebフレームワークの作者になれるかも、という一大チャンスが転がっている時期なんだということに今更ながら気づきました。この分野が今後どうなるか非常に楽しみです。


所感

各発表30分〜60分あり、プラス質疑応答は無限に受け付ける感じで、かなりのボリューム感でした。大変勉強になりました。またタイミングが合えばぜひ参加させていただきたいと思います。


ベルリンのデベロッパーの方々と知り合いになるべく発表側にもなってみたいところですが、発表枠を公募してる感じではないような気もします(僕がイベントを見つけたときには発表枠が決まっていた)。中心人物的な人に話しかけて「こういう発表がしたい」的なことを言えば入れてもらえるとかでしょうか。次回はもっとコミュニケーションもがんばろうと思います。


*1:ここ半年ほど、あえて英語を使わざるを得ない状況に自分を追い込むようにしていて、苦手意識はだいぶ改善されてきました

2016-01-24

Swiftで書かれた人工知能・機械学習ライブラリ「Swift-AI」をiOSで動かしてみる

全編Swiftで書かれたオープンソースの人工知能/機械学習ライブラリが出てきました。その名も「Swift-AI」。


デモが入っていて、こんな感じで手書き文字認識してくれます(詳細は後述します)。


f:id:shu223:20160124095306g:image


今のところ iOS と OS X をサポート しているとのこと。MITライセンス。


できること

README の Features を見ると、2016年1月現在、フィードフォワード(順伝播型)ニューラルネットワークと、高速行列演算ライブラリはできあがっているようです。


それぞれドキュメントがあります。


ベクトル・行列演算には Accelerate Framework を利用しているとのことで、パフォーマンス面も考慮されてそうです。


デモを試してみる

同梱されているデモプロジェクト「Swift-AI-iOS」を実行してみると、下記のように、「サイン波(sin)のグラフがあって、トレーニング開始するとオレンジの点の集合がそのサイン波のグラフに近づいていく」というものでした。


f:id:shu223:20160124095129j:image



・・・学習の過程を視覚化したデモなのかもしれませんが、ちょっとありがたみがわかりにくいなと。


で、そのXcodeプロジェクトの中を見てみると「HandwritingViewController」というソースコードがありました。


あれ、手描き文字認識のデモもあるのかなと思ってソースを追いかけてみると、どうやら他にもデモがあるらしい。デモを起動して画面を見てみて、もしや、と思い左上のSwift燕画像をタップしてみると・・・


f:id:shu223:20160124095428j:image

ハンバーガーメニューが出てきました。なんともわかりにくいUI。。


まぁそれはここでは本質的な問題ではないので置いといて、Handwriting のデモを試してみると、


f:id:shu223:20160124095306g:image


バシッと手書き認識してくれました。


手書き文字認識デモの実装

ライブラリの中身を読んでもたぶん理解できないので、あくまでライブラリを利用する側として、デモではどう実装しているのか「Handwriting」デモのソースを見てみました。


フィードフォワードニューラルネットワーク(FFNN)の準備

学習済みデータのファイルを指定して、FFNNクラスを初期化します。

let url = NSBundle.mainBundle().URLForResource("handwriting-ffnn", withExtension: nil)!
self.network = FFNN.fromFile(url)

ニューラルネットの準備としてはこれだけ。


手書き画像の領域を切り出す

認識するタイミングですが、本デモでは `touchesEnded` イベントが検出さてから0.4s以内に次の `touchesBegan` もしくは `touchesMoved` が検出されなければ認識処理が走るように実装されています。


で、手書き画像領域の切り出しは `scanImage()` というメソッドで行われています。

private func scanImage() -> [Float]? {
    var pixelsArray = [Float]()
    guard let image = self.handwritingView.canvas.image else {
        return nil
    }
    // Extract drawing from canvas and remove surrounding whitespace
    let croppedImage = self.cropImage(image, toRect: self.boundingBox!)
    // Scale character to max 20px in either dimension
    let scaledImage = self.scaleImageToSize(croppedImage, maxLength: 20)
    // Center character in 28x28 white box
    let character = self.addBorderToImage(scaledImage)
    
    self.handwritingView.imageView.image = character
    
    let pixelData = CGDataProviderCopyData(CGImageGetDataProvider(character.CGImage))
    let data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)
    let bytesPerRow = CGImageGetBytesPerRow(character.CGImage)
    let bytesPerPixel = (CGImageGetBitsPerPixel(character.CGImage) / 8)
    var position = 0
    for _ in 0..<Int(character.size.height) {
        for _ in 0..<Int(character.size.width) {
            let alpha = Float(data[position + 3])
            pixelsArray.append(alpha / 255)
            position += bytesPerPixel
        }
        if position % bytesPerRow != 0 {
            position += (bytesPerRow - (position % bytesPerRow))
        }
    }
    return pixelsArray
}

画像をクロップしたりリサイズしたり、といった処理は本ライブラリを利用するにあたって本質的な部分ではないので割愛しようと思ったのですが、あえて載せたのは、その後の処理に渡すにあたって、出力データの型が重要だと思ったからです。ポイントとしては、RGBAではなくA1チャンネルだけを取り出していること(手書き文字認識なので色情報は利用しない)と、UIImage型ではなくFloatの配列としてピクセルデータを返していること、といったあたりでしょうか。


認識処理の実行

上述した処理で取り出した手書き画像情報(Floatの配列)を引数に渡して、FFNNクラスの `update` メソッドを実行します。

let output = try self.network.update(inputs: imageArray)

認識結果を取り出す

先ほどの `update` メソッドの返り値である Float の配列は、数字0〜9を配列のインデックスとして、値には Confidence(信頼度/その数字である可能性の高さ?)が入っているようです。


なので、次のように、最も Confidence の高い数字(=認識結果)を探し、その認識結果の数字の値と、Confidenceを取り出しています。

private func outputToLabel(output: [Float]) -> (label: Int, confidence: Double)? {
    guard let max = output.maxElement() else {
        return nil
    }
    return (output.indexOf(max)!, Double(max / 1.0))
}

こうしてみてみると、実質的には

  • FFNNクラスの初期化
  • `update:` メソッドを呼ぶ

この2ステップだけで手書き文字認識ができていることがわかります。非常に簡単そうです。


自分のプロジェクトへの導入方法

CocoaPodsやCarthageはサポートしてないとのこと。

Swift is open-source now, and it remains to be seen how these dependency managers will cooperate with other platforms.


まだ試してないですが、デモプロジェクトを見る限り、

  • FFNN.swift
  • Storage.swift
  • FFNN+Storage.swift

あたりのファイルを追加すれば使えそうです。


他にも設定がいるかもしれませんが、ちゃんと動くデモプロジェクトが用意されているので、何かあればそちらと比較してみればよいかと。


所感

ピュアSwift、MITライセンスなオープンソースで、ちゃんとパフォーマンスも考慮されていて、簡単に使える、ということでかなり期待の持てるライブラリではないでしょうか。


今後いろんな学習済みデータや応用事例が出てくるとさらに楽しくなりそうです。


2016-01-05

ディープラーニングの有名ライブラリ5種を最短距離で試す半日コース(TensorFlow, Chainer, Caffe, DeepDream, 画風変換)

「いつか勉強しよう」と人工知能/機械学習/ディープラーニング(Deep Learning)といったトピックの記事の見つけてはアーカイブしてきたものの、結局2015年は何一つやらずに終わってしまったので、とにかく一歩でも足を踏み出すべく、本質的な理解等はさておき、とにかく試してみるということをやってみました。


試したのは、TensorFlow、Chainer、Caffe といった機械学習およびディープラーニングの代表的なライブラリ/フレームワーク3種と、2015年に話題になったディープラーニングを利用したアプリケーション2種(DeepDream、chainer-gogh)。


f:id:shu223:20160105091448j:image:w600

(DeepDreamで試した結果画像)


タイトルに半日と書きましたが、たとえばTensorFlowは環境構築だけなら10分もあれば終わるでしょうし、Chainerなんてコマンド一発なので5秒くらいです。Caffeは僕はハマりましたが、うまくいった最短手順を書いているので、同じ環境の方はすんなりいくかもしれません。


おすすめは、Chaffe&DeepDream(要Caffe) は飛ばして、TensorFlow, Chainer&画風変換を試すコースです。環境構築にハマらないので簡単に終わると思います(実行時間はかかりますが)。僕のように「気にはなってたけど全然触ってない」という方はぜひ今日の昼休みにでもお試しください!


試した環境:

  • Mac OS X 10.11.1 El Capitan
  • Xcode 7.2 インストール済み

TensorFlow

2015年11月に発表された、Google製の機械学習ライブラリ。「テンソルフロー」と読むそうです。同社のサービスでも実際に使われているとのこと。

よく話を聞く音声認識や翻訳だけでなく、Googleフォトの被写体認識や顔認識、ウェブ検索結果の最適化、Gmailのメール分別、新生メールソフトInboxの自動返信文作成、さらにYouTubeや広告事業まで、ほとんどのプロダクトを支える新たな根幹技術となっています。

TensorFlow の特徴は、データフローグラフとして表せればなんでも処理でき、その気になればローレベルのオペレータも手書きできる汎用性、Googleの実製品で使われる高いパフォーマンス、CPUでもGPUでも走りノートPCから巨大なデータセンターまで同じコードで動きモバイル端末にもデプロイできるスケーラビリティ、計算機科学の研究から実プロダクトまで扱える効率性、ドキュメンテーションやサンプルが揃いPythonでもC++でも書ける扱いやすさなどなど。


オープン化の狙い

ライセンスは商用利用も可能な Apache 2.0 で、自社製品のコアにもなっているこんなすごいものをなぜ Google はオープン化したのか?というところは気になるところです。

TensorFlowをオープンソース化することで、学術研究者からエンジニア、趣味として取り組むユーザーまで、あらゆる人々の機械学習コミュニティーが、研究論文よりも動作するコードを介してアイデアを格段にすばやく交換できるようになると期待している。これが機械学習に関する研究の促進につながり、最終的に技術がすべての人々にとってより適切に機能するものになるだろう。さらに、TensorFlowの応用分野は機械学習だけにとどまらない。タンパク質のフォールディングから宇宙データの処理にいたるまで、非常に複雑なデータの解明に取り組むあらゆる分野の研究者らにとって有用であるかもしれない。


Googleいわく、機械学習はこれからの画期的なプロダクトや技術に欠かせない重要な要素となるもので、世界中で研究が進められているものの、標準となるツールが存在していないことが課題。Google では TensorFlow を研究者から学生、製品開発者まで使える標準ツールとして提供することで、機械学習や機械知能そのものの研究と普及を加速したい考えです。


環境構築手順(所要時間:10分)

OS X El Capitan (10.11.1) へのインストール手順です。


1. pip をインストール

$ sudo easy_install pip

2. Virtualenv をインストール

$ sudo pip install --upgrade virtualenv

3. Virtualenv 環境を作成(下記コマンドだと `~/tensorflow` につくられる)

$ virtualenv --system-site-packages ~/tensorflow

4. つくった環境をアクティベート

$ source ~/tensorflow/bin/activate

→ コマンドプロンプトが変わる


5. TensorFlow をインストール

(tensorflow)$ pip install --upgrade https://storage.googleapis.com/tensorflow/mac/tensorflow-0.5.0-py2-none-any.whl

Successfully installed numpy-1.10.2 six-1.10.0 tensorflow-0.5.0


以上です。


動作確認:Hello World を実行してみる

スクリプトを作成し、適当なファイル名で保存します。

import tensorflow as tf
import multiprocessing as mp
 
core_num = mp.cpu_count()
config = tf.ConfigProto(
    inter_op_parallelism_threads=core_num,
    intra_op_parallelism_threads=core_num )
sess = tf.Session(config=config)
 
hello = tf.constant('hello, tensorflow!')
print sess.run(hello)

TensorFlow 環境で実行します。

(tensorflow)$ python {ファイル名}.py

実行結果:

I tensorflow/core/common_runtime/local_device.cc:25] Local device intra op parallelism threads: 4

I tensorflow/core/common_runtime/local_session.cc:45] Local session inter op parallelism threads: 4

hello, tensorflow!


参考ページ:


手書き数字を学習してみる

TensorFlow オフィシャルページに、「MNIST For ML Beginners」という手書き文字データセットを利用したチュートリアルがあります。

f:id:shu223:20160105090618p:image

(MNISTデータセット)


ここでは一番手っ取り早そうな、公式チュートリアルのコード(GitHubにある)を実行する方法を試すことにします。


ソースコードを clone してきて、

$ git clone --recurse-submodules https://github.com/tensorflow/tensorflow

fully_connected_feed.py の30,31行目を次のように修正します。*1

  • 修正前
from tensorflow.examples.tutorials.mnist import input_data
from tensorflow.examples.tutorials.mnist import mnist
  • 修正後
import input_data
import mnist

fully_connected_feed.py を実行します。

$ cd tensorflow/
$ python tensorflow/examples/tutorials/mnist/fully_connected_feed.py 

MNISTデータセットを手動でダウンロードしたりする必要はなく、このスクリプトがデータセットの取得からモデルの学習までやってくれます。


実行結果:

Successfully downloaded train-images-idx3-ubyte.gz 9912422 bytes.

Extracting data/train-images-idx3-ubyte.gz

//中略

Step 0: loss = 2.32 (0.025 sec)

Step 100: loss = 2.19 (0.003 sec)

Step 200: loss = 1.97 (0.003 sec)

//中略

Step 1900: loss = 0.46 (0.004 sec)

Training Data Eval:

Num examples: 55000 Num correct: 49489 Precision @ 1: 0.8998

Validation Data Eval:

Num examples: 5000 Num correct: 4534 Precision @ 1: 0.9068

Test Data Eval:

Num examples: 10000 Num correct: 9019 Precision @ 1: 0.9019

データセットのダウンロード、トレーニング、テストデータでの評価が行われています。最終的な精度は約90%。


参考ページ:


学習結果を可視化する TensorBoard を試す

なんと、学習結果をグラフにしてくれたり、モデルをビジュアライズして表示してくれる TensorBoard というものも用意してくれているようです。


学習経過のログデータのあるディレクトリを絶対パスで指定 *2 して `tensorboard` コマンドを実行すると、

$ tensorboard --logdir=/Users/xxxx/xxxx/tensorflow/tensorflow/data

TensorBoard が起動します。

Starting TensorBoard on port 6006

(You can navigate to http://localhost:6006)


で、このURLにブラウザからアクセスするとGUIが表示され、


学習回数とxentropy_mean(交差エントロピー)の関係を示すグラフや、


f:id:shu223:20160105090658j:image:w400


モデル(ニューラルネットワーク)を可視化したものを見ることができます。


f:id:shu223:20160105090721j:image:w538


More

Chainer

Preferred Networks社が開発したニューラルネットワークを実装するためのライブラリ。2015年6月公開。特徴としては、

  • Python のライブラリとして提供
  • あらゆるニューラルネットの構造に柔軟に対応
  • 動的な計算グラフ構築による直感的なコード
  • GPU をサポートし、複数 GPU をつかった学習も直感的に記述可能

が挙げられています。


TensorFlow との比較

上記特徴を見ると TensorFlow とポジショニング的には似ているように見えたので、どんな違いがあるのかググッてみました。

たぶんできることそのものに大きな違いはないんだろうけど、Chainerの場合マルチGPUにするときには自分でGPUの管理をしなきゃなんないのが、TenrorFlowだともうちょっとラクなのかなあと思ったりする。


TensorFlow、GPU使うのにリビルドが必要で、そのためにbazelが必要で、そのためにJava8が必要で、しかもGPUにCC3.5以上の制約があるみたいで、使えるなら使えば?感が凄い。同じPythonならChainerの方が敷居が低く感じる。


TensorFlowはDistBeliefの2倍の速いそうなのですが、Chainerはそれを上回っていました。

記述量的にはそこまで変わらないですし個人的にはChainerの方が扱い易いというのが感想です(慣れの問題だとは思いますが。)。


TensorFlow,Chainerとも精度は同じでした。そもそもMNISTは問題が簡単なのでDeep Learningでなくても高い精度が出るそうです。実行時間はChainerの方が速かったのです。


インストール手順(所要時間:5秒)

公式ドキュメントに Install Guide というページがあるのですが、Ubuntu, CentOS 向けに書かれているようなので、Mac向けのはないかなと探してたら、本家Webサイトに QUICK START という項目がありました。


やることは

$ pip install chainer

これだけ。


Successfully installed chainer-1.5.1 filelock-2.0.5

素晴らしい!


手書き数字を学習してみる

公式リポジトリにサンプルが用意されています。cloneしてきてスクリプトを実行するだけ。

$ git clone https://github.com/pfnet/chainer.git
$ python chainer/examples/mnist/train_mnist.py

MNISTデータセットのダウンロードと、学習、テストが行われます。

load MNIST dataset

Downloading train-images-idx3-ubyte.gz...

(中略)

epoch 1

graph generated

train mean loss=0.190947790003, accuracy=0.942850003242

test mean loss=0.0990746175707, accuracy=0.96930000484

(中略)

epoch 20

train mean loss=0.0104963570454, accuracy=0.996966669559

test mean loss=0.102703116325, accuracy=0.982000006437

最終的な識別精度は98%になったようです。


More

Caffe

C++で実装されたディープラーニングのオープンソースライブラリ。カリフォルニア大学バークレー校の研究センターBVLCが中心となって開発、C++・Python・MATLABで利用可能。


具体的な公開日はわかりませんが、ChainerやTensorFlowの登場以前から存在する分、ネットで見つかるおもしろそうなディープラーニングを利用した研究や試みはCaffeをベースにしたものを多く見かける気がします。


環境構築手順(所要時間:約4時間)

所要時間は個人差(環境差)があると思いますが、確実にTensorFlowやChainerよりは時間がかかると思います。依存ライブラリが多く、その中にはインストールの待ち時間が長いものがありますし、各自の環境に依存した設定を手動で行う必要があるので、そのあたりでハマることもあると思います。また個人的にはnumpyのバージョンが違うというエラーにかなり悩まされました。


GPUが絡むとハマりそうなのでCPUモードで、インストールしていきます。PyCaffeも入れます。


1. 諸々インストール

$ brew install --fresh -vd snappy leveldb gflags glog szip lmdb
$ brew tap homebrew/science
$ brew install hdf5 opencv
$ brew install --build-from-source --with-python --fresh -vd protobuf
$ brew install --build-from-source --fresh -vd boost boost-python
$ brew install openblas

※1 opencv のインストールはかなり時間がかかります。

※2 OpenBLAS は入れなくてもいいそうですが(Macでは標準でBLASが入っているとのこと)、この後の手順で Makefile の `BLAS_INCLUDE` のパスを修正したりしてから make を実行しても `fatal error: 'cblas.h' file not found` が出てしまうので、入れることにしました。


2. caffe をclone してきます。

$ git clone https://github.com/BVLC/caffe.git

3. Makefile.config を雛形からコピーしてきて、編集します。

$ cd caffe
$ cp Makefile.config.example Makefile.config

  • `# CPU_ONLY := 1` のコメントアウトを外す
  • `BLAS := atlas` を `BLAS := open` に変更する
  • 以下のコメントアウトを外す
# BLAS_INCLUDE := $(shell brew --prefix openblas)/include
# BLAS_LIB := $(shell brew --prefix openblas)/lib
  • `PYTHON_INCLUDE` のパスを自分の環境に合わせて書き換える *3
    • 修正前
PYTHON_INCLUDE := /usr/include/python2.7 \
    /usr/lib/python2.7/dist-packages/numpy/core/include
    • 修正後
PYTHON_INCLUDE := /usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/include/python2.7 \
    /usr/local/lib/python2.7/site-packages/numpy/core/include/


4. ビルド&テスト。

$ make clean
$ make all -j4
$ make test -j4
$ make runtest

ここでエラーがでなければインストール成功です。

[ PASSED ] 927 tests.


5. caffe/python フォルダに移動し、PyCaffe に必要なライブラリをインストールします。

$ cd python/
$ for li in $(cat requirements.txt); do sudo pip install $li; done 

6. PyCaffe のビルド

$ cd ../
$ make pycaffe
$ make distribute

7. Caffe用の環境変数を設定します。~/.bashrc に下記を追記し、

export PYTHONPATH={caffe/pythonのパス}:$PYTHONPATH

`source ~/.bashrc` で反映します。


8. 動作確認

PythonのインタプリタからCaffeをimportしてみて、問題が起きなければOK。

$ python 
>>> import caffe

ちなみに本記事では最終的にうまくいった手順のみを書いていますが、大いにハマったトラブルシューティングの過程も別記事として書いておきました。


参考ページ:


DeepDream

ここからひとつレイヤーは上がって、ディープラーニングライブラリ/フレームワークを利用した応用アプリケーション的なものをいくつか試してみます。


DeepDream は 2015年7月にGoogleが公開 したOSSで、

画像から少しでも見覚えのある物体を見つけ出し、それを再構成して出力する

人工神経回路網は10〜30のレイヤーから構成されており、1枚目のレイヤーは画像の情報をインプットして「角」や「端」を探し、2枚目・3枚目と続くレイヤーは基本的な物体の情報を把握、最終的なレイヤーが情報を組み立てて物体が「何か」を判断する、という仕組みです。

というもの。


環境構築の手順(所要時間:10分)

要Caffe(インストール手順は上述)。Caffeさえ入っていればさっくり試せます。


1. iPython notebook を入れます。*4

$ pip install ipython
$ pip install ipython[notebook]

2. Caffe のあるフォルダと同階層に DeepDream のソースを clone します。

$ git clone git@github.com:google/deepdream.git

3. ここ から学習済みのcaffeモデルをダウンロードし、{caffeのパス}/models/bvlc_googlenet/ に保存します。


試す

cloneしてきたdeepdreamフォルダに移動し、iPython notebookを起動します。

$ cd deepdream
$ ipython trust dream.ipynb
$ ipython notebook

ブラウザが立ち上がるので、dream.ipynb を選択して、上部にある再生ボタンをポチポチ押していき、最後まで到達したらしばらく待っていると・・・ deepdream/frames/ フォルダに結果画像が 0000.jpg, 0001.jpg, ...と出力されていきます。


f:id:shu223:20160105091354j:image:w600

(左:0000.jpg と、右 0010.jpg)



手っ取り早く好きな画像で試したい場合は、sky1024px.jpg にリネームして同じ場所に置いておけばOKです。または dream.ipynb の画像名を指定している箇所を編集します。


さわやかな食事風景が、

f:id:shu223:20160105091426j:image:w600


こうなりました。

f:id:shu223:20160105091448j:image:w600



参考記事:


画風変換アルゴリズム chainer-gogh

mattya氏が2015年9月に公開した、Deep Neural Networkを使って画像を好きな画風に変換できるプログラム。


Chainerを利用。アルゴリズムの元論文は A Neural Algorithm of Artistic Stlye


環境構築の手順(所要時間:1分)

1. ソースを clone してきます。

$ git clone https://github.com/mattya/chainer-gogh.git

2. モデルを下記URLからダウンロードし、cloneしてきた chainer-gogh フォルダ配下に置きます。


実行する

お手軽にCPU実行してみます。コンテンツ画像(input.png)とスタイル画像(style.png)を用意して chainer-gogh フォルダ配下に置き、スクリプトを実行するだけ。

python chainer-gogh.py -m nin -i input.png -s style.png -o output_dir -g -1

f:id:shu223:20160105091523j:image:w600

(左:input.png、右:style.png)


f:id:shu223:20160105091655p:image

(結果画像)


今後の展望

今回は環境構築と既に用意されているサンプルを実行してみただけなので、次のステップとしては、下記記事の例のように、OpenCVを活用して自前データセットつくって、Chainer なり TensorFlow なりで画像識別をやってみたいと思っています。

ただデータセット収集はそれなりに時間かかりそうなので、下記記事のように既存のデータセットを Chainer および TensorFlow に食わせるところから始めるのが現実的かも。


また、iOSエンジニアとしては、モバイルデバイスでの利用についても模索したいと思っています。

あらかじめ学習済みモデルを用意して識別専用として利用するだけなら可能なのか、学習機能自体をモバイル側でやってみたらどんだけ重いのか(そもそもできるのか)とか。TensorFlow は「モバイル端末にもデプロイ可能」と謳ってますし。


あと、画像以外にも、自然言語処理への利用等も試してみたいです。


おわり。


*1:これをやらないと、実行時に "ImportError: No module named examples.tutorials.mnist" というエラーが出ます。

*2:パスが間違ってても TensorBoard は起動するのですが、アクセスしてもグラフ等は表示されません。

*3:`/usr/include` が最近のOSXでなくなってることに関しては、`$ xcode-select --install` をすればいいみたいなのですが、古いコマンドラインツールをダウンロードしないといけないっぽく、あまりXcodeまわりの環境をいじりたくないので直接pythonのincludeパスを指定するようにしました

*4:なぜか ipython: command not found になったので こちら を参考にインストールしなおしました

2016-01-03

Caffe(PyCaffe)のインストールでハマったメモ

Caffe をインストールしてて大いにハマった際の、トラブルシューティングメモ。


環境は Mac OS X 10.11 El Capitan です。


問題1: numpy のバージョン違いと El Capitan の System Integrity Protection

PyCaffe をビルドしたあと動作確認として

$ python 
>>> import caffe

ってやると、

RuntimeError: module compiled against API version a but this version of numpy is 9

って怒られた。


そこでnumpy をアップデートしようと、

$ sudo pip install -U numpy

をしたら、パーミッションがどうのこうの、どうやら El Capitan の "System Integrity Protection" という新機能が邪魔をしてるらしい。


$ sudo pip install --upgrade numpy --ignore-installed six

ってやるとコマンドは通るが、古いnumpy(1.8.0rc1)がまたインストールされるだけ・・・

Collecting numpy
  Downloading numpy-1.10.2-cp27-none-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl (3.7MB)
(中略)
Successfully installed numpy-1.8.0rc1 six-1.4.1

対処1: HomebrewでPythonをインストール & numpyアップデート

あれこれ試してうまくいかず困って、こちらの Mario さんの回答 を参考に(ベストアンサーの System Integrity Protection を無効にする方法は怖いのでやらなかった)Homebrew で Python をインストールして、

$ brew install python

その後もう一度

$ sudo pip install -U numpy

したら最新の 1.10.2 にアップデート成功。

$ sudo pip list
numpy (1.10.2)

ただ `$ brew doctor` してその指示に従って `$ brew prune` したりもしたのでそちらが効いたのかもしれない。。


問題2: 古いnumpyが利用される

numpyのアップデートに成功したものの、まだ

>>> import numpy
>>> print numpy.__version__
1.8.0rc1

となる。(1.10.2 の方を見ていない)


パスを出力してみると、Mac標準の方が使用されている。

>>> import numpy
>>> print numpy.__path__
['/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/numpy']

この記事 に書いてある方法だとMacに標準で入ってた方をリネームしているが、そういう操作は El Capitan だと怒られるので基本的にできない。


対処2: 環境変数のPATHを変更

python コマンドの場所を見てみる。

$ which python
/usr/bin/python

PATH の優先度を変更するため、~/.bash_profile を編集

  • 修正前
PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin
  • 修正後
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin

反映

$ source ~/.bash_profile

確認

$ which python
/usr/local/bin/python

問題3: Segmentation fault: 11

このままmakeやらをやりなして動作確認しようとしたら、

>>> import caffe
Segmentation fault: 11

でクラッシュ。

対処3: Makefile.config を修正

こちらのページ を見ていて思い出したが、Python の場所を変えたので Makefile.config のパスを修正してから諸々やりなおさないといけない。


  • 修正前
PYTHON_INCLUDE := /System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 \
    /usr/local/lib/python2.7/site-packages/numpy/core/include/
  • 修正後
PYTHON_INCLUDE := /usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/include/python2.7 \
    /usr/local/lib/python2.7/site-packages/numpy/core/include/

  • 修正前
PYTHON_LIB := /usr/lib
  • 修正後
PYTHON_LIB := /usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib

問題4: ValueError: unknown locale: UTF-8

import caffe したら今度は

ValueError: unknown locale: UTF-8

ってのが出た


対処4: ビルドのやりなおし

http://stackoverflow.com/questions/19961239/pelican-3-3-pelican-quickstart-error-valueerror-unknown-locale-utf-8:こちらの回答] の通りに

export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8
$ source ~/.bash_profile 

動作確認

インタプリタを起動して

>>> import caffe
>>> 

やっと成功・・・!



こういう苦労の果てに書いた記事がこちら:


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 |