読者です 読者をやめる 読者になる 読者になる

Nuts and Bolts of Applying Deep Learning

CS231の講義の関連動画を辿ってAndrew Ng先生がNIPS2016で行った講演「Nuts and Bolts of Applying Deep Learning」を見つけました。これがすごく面白い内容だったので超主観的にポイントをまとめてみます。

講演のビデオやスライド、Web上で見つけたブログは以下にあります。

スライドと1番目のBlog記事がよくまとまっているのでそれを読めば十分な気はします。が、自分の勉強としてまとめていきます。。

Major Deep Learning Trends [2:50]

  • データが少ないときは ハンドエンジニアリングで性能の差がつく
  • ビッグデータ時代は データ量で性能が決まる

To hit the top margin, you need a huge amount of data and a large NN model.

定式: データ量 x 大きなモデル = 性能

End-to-end Deep learning [13:57]

  • End-to-endアプローチは 莫大なデータがある場合においてうまくいく
  • 例えば、自動運転では精度を満たすだけのデータが足りずまだ難しい
  • そういうケースではハンドエンジニアリングは依然として重要である

End-to-end works only when you have enough (x,y) data to learn function of needed level of complexity.

データ量万歳\(^o^)/です。

Bias-Variance tradeoff [27:04]

  • どんな状況であれ やるべきことは Bigger modelMore data
  • Bias と Variance を同時に改善できる(トレードオフの関係にならなくなる)
  • New model architectureの検討はハードル高いし大抵の問題はそこまで必要ない

基本的なワークフロー f:id:sanshonoki:20170520204228p:plain

Data synthesis (Data augmentation)[31:46]

  • データ合成はデータ量を増やせて性能改善にとても有効(More data)
    • ex. ノイズのない音声にノイズをのせるetc..
  • とはいえ、あくまでも人工的なデータなので学習にあまり効かない場合もある

Mismatched train/test (new bias/variance) [38:53]

学習用データの環境とアプリケーションの環境が異なるケースが増えてきている

学習環境とアプリケーション環境のデータセットの違いも考慮したワークフロー f:id:sanshonoki:20170520204239p:plain

Human-level performance [51:26]

  • 人間の認識精度をリファレンスとすべき
  • リファレンスと学習結果の差を見て 何にフォーカスするか判断できる

    human-levelエラーとtrainエラーの差が大 trainエラーとdevエラーの差が大
    Biasにフォーカス Varianceにフォーカス

What can AI/DL do ? [1:06:33]

AIアプリケーションとして有望なもの

  • 人間が1秒以内でできるタスク
  • 繰り返しシーケンスの次の結果の予測
    • ex. ユーザーが次の広告をクリックするかどうか

Personal advice (building ML career) [1:10:32]

  • 論文をたくさん読んで結果を再現する
  • Dirty work(データ収集、前処理、パラメータチューニング、デバッグ、データベースの最適化 etc…)をしよう

Dirty workは進捗がなかなか実感できないので勇気づけられます。「No magic」ということなので愚直にやりましょうということですね。。

ストリートビューのパノラマ画像をダウンロードする

React VRで使うパノラマ画像のサンプルとしてストリートビューの画像を使いたいなーと思ってネットで探したら extract-stretviewというツールを発見しました。

これがなかなか良かったので紹介します。(^○^)

www.npmjs.com

インストー

$ npm install extract-streetview -g

使い方の例

基本的に

$ extract-streetview 緯度 経度 -o 出力ファイル

です。

例えば、渋谷のスクランブル交差点 の緯度経度は

  • 緯度(latitude): 35.6595126
  • 経度(longitude): 139.7005696

なので

$ extract-streetview 35.6595126,139.7005696 -f jpg -q 100 -z 2 -s outdoor -o panorama.jpg

でダウンロードできます。

f:id:sanshonoki:20170512213334j:plain

ダウンロードした画像は アスペクト比 2:1 の Equirectangular形式になっていて そのまま各種VRアプリケーションの入力画像として使えるはずです。

ちなみに、 -zオプション は画像サイズとなっており目安は以下のようになります。

-z 画像サイズ ファイルサイズ
0 416 x 208 54 KB
1 832 x 416 165 KB
2 1664 x 832 568 KB
3 3328 x 1664 1.9 MB
4 6656 x 3328 5.6 MB

This tool is experimental とありますが パノラマ、VRを身近にする便利なツールだと思います。(*´ー`)

Cordovaで React VR をスマホアプリにしてみる

つい先日React VRがリリースされました。

以前VR系のベンチャー会社で働いていたので VRと聞くとつい触ってみたくなります。 ( ̄ー ̄)

以下の記事を参考に、Cordovaを使って React VR で作った Webアプリ を スマホアプリ化 してみました。

qiita.com

インストー
  1. cordovaのインストー

     $ npm install -g cordova
    
  2. React VRのインストー

     $ npm install -g react-vr-cli
    
プロジェクトの作成
  1. cordovaプロジェクトの作成

    $ cordova create path/to/your/dir com.example.hello.reactvr HelloCordovaReactVr
    

    createのパラメータは corodva create ディレクトリ 識別子 アプリ名 です。

    識別子でハイフンやアンダースコアを使うとハマるので要注意です。(AppIDとしてiOSではアンダースコア、Androidではハイフンを使えないため)

  2. iOSAndroidのプラットフォームを追加

     $ cordova platform add ios --save
     $ cordova platform add android --save
    
  3. React VRのプロジェクトを作成

    corodvaプロジェクトのルートディレクトリでReact VRのプロジェクトを作成します。

     $ react-vr init react_vr
    

    initのパラメータは react-vr init アプリ名です。

アプリのビルドとコードの修正
  1. React VRアプリのコード (js) の修正

    パノラマのテクスチャ画像をデフォルトから変更したいときは static_assetsディレクトリにEquirectangularのパノラマ画像を配置して index.vr.js を以下のように修正します。

    <View>
       <Pano source={asset('tsujido-house-pano.jpg')}
         style={{
           transform: [
             {rotateY : 0}
           ] }}
       />
      ....
     </View>
    
  2. React VRアプリをビルド

     $ cd react_vr
     $ npm run bundle
    
  3. React VRアプリのコード (html) の修正

    vr/index.html をエディタで編集します

    1. index.htmlにcordova.jsを追加

      <body>
            .....
           <script type="text/javascript" src="cordova.js"></script>
      </body>
      
    2. ビルドした js を使うようにパスを修正

      2箇所修正します。.jsをつけないとNGのようです

      client.bundle.js <script src="./build/client.bundle.js?platform=vr"></script>

      index.bundle.js './build/index.bundle.js?platform=vr&dev=true'

    3. static_assets が index.html があるディレクトリから見えるようにする

       ln -s ../static_assets .
      
    4. assetsRootのパラメータを追加

       ReactVR.init(
           // When you're ready to deploy your app, update this line to point to
           // your compiled index.bundle.js
           './build/index.bundle.js?platform=vr&dev=true',
           // Attach it to the body tag
           document.body,
           { assetRoot: 'static_assets' }  // 追加
         );  
      
  4. cordovaのwwwディレクトリがReact VRのコンテンツを参照するようにする

    cordovaプロジェクトのルートディレクトリに移動して

    $ mv www www.orig
    $ ln -s react_vr/vr www
    
  5. cordovaアプリをビルド

     $ cordova build [ios/android]
    

    この状態で $ cordova serve ios をするとブラウザ上で動作確認できます。

    f:id:sanshonoki:20170506174311g:plain

エミュレーターで確認

続いてエミュレーターで動作確認します

  1. iOS

     $ cordova emulate ios 
    

    必要に応じて --target=iPhone-6sのようにターゲット端末をオプションで指定します。

    f:id:sanshonoki:20170506152558p:plain:w250

    おお、出ました! ただし、シミュレーターではジャイロが使えないため真下向きのままから動きません… (´Д`。)

  2. Android

    Android は 最初にエミュレーターを起動してから コマンドを打ってください

     $ cordova emulate android
    

    f:id:sanshonoki:20170506152630p:plain:w250

    orz.. AndroidエミュレーターWebGLをサポートしてないようです..

実機で確認

手持ちのiPad mini でやってみます。

そのまま、$ cordova run ios すると

 `Code Sign error: No code signing identities found: No valid signing identities (i.e. certificate and private key pair) were found.` 

のエラーが出るので Xcodeのプロジェクトを開きます

$ open platforms/ios/HelloCorodvaReactVr.xcodeproj

Fix issueしてXcode上でビルド、実行します。 f:id:sanshonoki:20170511151122j:plain:w300

アプリは起動したもののテクスチャが表示されません..。(ノ゚ο゚)ノ
iPad miniが古いせいでしょうか…

Androidは手持ちのNexus5がいつの間にやら(Android6.0にアップデートしてから?)USBデバッグ接続できなくなっていて実機で確認できませんでした..

iOSAndroidとも最新の実機では動いてくれると信じています。。

実機で確認(続)

iPad mini の OS を10.3 に アップデートしたら見れるようになりました! ヾ(´▽`)ノ f:id:sanshonoki:20170507095044g:plain

アップデート前は動いてなかったThree.jsのサンプルがOSアップデート後に動くようになったのでそれでWebGL対応を判定できそうです。 https://threejs.org/examples/#webgl_animation_cloth

パッケージをアップデートしたらNVIDIAが認識されなくなった...

事件発生!

Ubuntuマシンで毎回パッケージアップデートのダイアログが出てウザいので何気なくパッケージアップデートを実行しました。

そして翌日、いつものように学習プログラムを走らせる

と、 あれ、GPUのエラー ?!?!

$ nvidia-smi してみる。

NVIDIA-SMI has failed because it couldn’t communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running.

マジか Σ( ̄ロ ̄ lll)

あぁ、やっちまった..。要らんことしなかったら良かった・・  o(;△;)o

解決。。

ドライバを再度インストールしたら直りました。。

wget http://us.download.nvidia.com/XFree86/Linux-x86_64/367.57/NVIDIA-Linux-x86_64-367.57.run
chmod a+x NVIDIA-Linux-x86_64-367.57.run
sudo service lightdm stop
sudo bash ./NVIDIA-Linux-x86_64-367.44.run --no-opengl-files

ふ〜焦ったよ.. ε-(´∀`*)

気をつけよう。

ディープラーニング学習メモ #5 CNN

Karpathy先生のCS231nの講義スライドも使いつつ覚えておきたいポイントをまとめてみます。

畳み込み(Convolution)のイメージ図

f:id:sanshonoki:20170410064711p:plain:w500

ポイント

  • 入力のdepthとフィルタのdepthは同じ。フィルタを適用して1つの値を出力
  • フィルタをスライドさせながら適用して 1枚の アクティベーションマップを 出力
  • N枚のフィルタから N枚のアクティベーションマップを 出力
畳み込みの演算

F = フィルタサイズ

np.sum(X[x:x+F, y:y+F, :] * W) + b
  • フィルタサイズで切り取った X に W を elementwise掛け算 して
  • 演算結果をすべて足し込んでさらに bias を足す


別の書き方をすると

np.dot(X[x:x+F, y:y+F, :].flatten(), W.flatten()) + b

とも書ける。

ネットワーク全体のイメージ図

INPUT -> [[CONV -> RELU]*N -> POOL?]*M -> [FC -> RELU]*K -> FC
  • N: 0 ~ 3程度
  • M: 0 ~
  • K: 0 ~ 3程度

f:id:sanshonoki:20170408074722j:plain

CONV層 + RELU層 と POOL層を重ねて 高次元の特徴を 複数抽出し、全結合(FC)レイヤで 各特徴の重みを学習する というイメージです。

覚えておきたい計算式

  1. アクティベーションマップのサイズ

    ( W − F + 2P ) / S +1

    TensorFlowの padding=‘same'は P=ceil(F/2)、padding='valid'はP=0です。正確な定義はこちらです。

  2. パラメータ数

    ( F * F * 入力フィルタ数 + 1) * 出力フィルタ数

    +1 は bias項になります。

  3. 必要なメモリサイズ

    ( W * H * フィルタ数 ) * 4 (=float32) バイト

    バッチサイズはGPUのメモリサイズに依存します。(GPUのメモリ上にのる限りは大きくしたほうがよい)

    VGGNetの場合だと

    • 画像1枚あたり 93 M (backwardもいれると x 2) となるようです。。

なぜディープにするのがよいのか?

7x7フィルタを1回適用した場合と3x3フィルタを3回適用した場合を比較してみます。

イメージ パラメータ数
7x7フィルタを1回 f:id:sanshonoki:20170408062235p:plain:w150 (7 * 7 * 3 + 1) * 3 = 444
3x3フィルタを3回 f:id:sanshonoki:20170408062304p:plain:w320 (3 * 3 * 3 + 1) * 3 * 3 = 252

出力アクティベーションマップのサイズは 26 x 26 で同じですが3層に積み重ねるほうがより大きな表現力があり(非線形処理を3回適用するので)、またパラメータ数も少なくなり学習効率がよくなります。

一方でメモリサイズはより必要になってくるのでトレードオフの関係にはなります。 GPUのスペックが向上することでよりディープに学習することが可能になったと言えるでしょう。

どんどんディープになっていくトレンドですが ILCVRC'15の勝者の ResNet は なんと.. 152層 です。 w|;゚ロ゚|w

f:id:sanshonoki:20170408071259j:plain

なぜCNNは成功しているのか?

次のような理解で大体あっていると思う。。

画像認識に適したアーキテクチャ
  • 畳み込み: 何層も畳み込むことで高次元の抽象的な特徴を抽出できる
  • プーリング: 位置のずれにロバストになる
以下の2つの大きな課題があったが解決された
  • 過学習 (Overfitting)
  • 勾配消失問題 (Vanishing gradient problem)
解決の要因
  • 手法の進化
    • ReLU: 深いネットワークでも勾配が逆伝搬できるようになった
    • Dropout: 擬似的にアンサンブル学習することで汎化性能が上がり過学習を抑制できるようになった
  • ハードウェアの進化(特にGPU
    • 大量のデータ、大量のパラメータを処理できるようになった

勾配降下法(gradient descent)の実装サンプル

1次元データでCNNのgradient descentをNumpyで実装してみました。 スクラッチで実装すると少し自信がつく気がします。。 (o・ω・o)

github.com

今回は以上です。次は RNN の記事を書いてみようと思います。

学習データ数と認識精度の関係

パドック画像から競走馬の距離適性を推測する学習をしてみたけど性能が全然よくない…!  

ヒィィ (ノ゚ρ゚)ノ

う〜ん、やっぱりデータのサンプル数が少なすぎるのかな・・

ということでchainerのCIFAR-10のサンプルコードを使って学習データ数と認識精度の関係をちょっと調べてみました。

実験条件
  • epoch数: 100
  • 学習データ数: 1000, 3000, 5000, 10000, 50000
結果

f:id:sanshonoki:20170407214433p:plain

やっぱり、機械学習の世界では 数は性能なり なんですね。。

CUDAを7.5から8.0にアップグレード

Udacityのディープラーニング講座の中で使うTensorFlowのバージョンが1.0となっていてCUDA7.5だと動かない… (>_<)

ということで自宅PCのCUDAを7.5から8.0にアップグレードしました。

今まで自分にとって開発環境のアップグレードは鬼門で 今まで動いていたものがいろいろ動かなくなって

ああ、やらんかったらよかった…

ということが多々あったのですが今回はあまりにもスムーズでうれしかったのでメモを残します。(´ー`)

CUDA8.0のインストール

  1. NVIDIAのダウンロードサイトからCUDAをダウンロードしてきます。

    自分のPCにあったものを選択します。Ubuntu14.04用は https://developer.nvidia.com/compute/cuda/8.0/Prod2/local_installers/cuda_8.0.61_375.26_linux-run

  2. ダウンロードしたスクリプトを実行
chmod a+x cuda_8.0.61_375.26_linux-run
sudo service lightdm stop # Stop X-Server
sudo bash ./cuda_8.0.61_375.26_linux.run --silent --no-opengl-libs --toolkit

1分ぐらい待つと何のメッセージ出力がなく終了します。

えっ?( ´・д・)

と思うぐらい拍子抜けです。

続いて以下のコマンドでCUDAがインストールされていることを確認します。

nvidia-smi # check GPU is available
nvcc -V # cuda version should be 8.0

cuDNN(v5.1)のインストール

続いてcuDNNをインストール。こちらもNVIDIAのサイトからダウンロードしてきます。 cuDNNはNVIDIAのユーザー登録が必要です。

ユーザー登録面倒な方はこちらからダウンロードしてください http://momonoki.blob.core.windows.net/data/cudnn/cudnn-8.0-linux-x64-v5.1.tgz

tar xvfz cudnn-8.0-linux-x64-v5.1.tgz
cat /usr/local/cuda/version.txt # /usr/local/cudaがcuda-8.0へのリンクになっていることを確認
sudo cp cuda/include/cudnn.h /usr/local/cuda/include
sudo cp cuda/lib64/* /usr/local/cuda/lib64

chainerやTensorFlowの再インストール

そのままだとCUDAのバージョン不一致で動かないので一度アンインストールしてからインストールします。

# reinstall chainer
pip uninstall chainer
pip install chainer

# reinstall TensorFlow
pip uninstall tensorflow
pip install tensorflow-gpu

再インストールしたらMNISTのサンプル等でGPUありで動くかを確認します。

以上です。

これで AWSGPUインスタンス(何かびびってしまう。。)を使わずに自宅PCで課題を進められます。 (*´Д`)