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

実験やめたった シマエナガ編

劇団「実験やめたった」の活動報告

nVidia社DIGITSでDeep Learningをいじくる

はじめに:いきさつ

 2014年ごろから画像分類の技術として「Deep Learning」というのをよく目にするようになりました。筆者はこの技術をなんとか使いたいと思い、2014年の夏から機械学習について、2015年の正月ごろから実際に動かす方法について色々と調べてきました。そしてこのまえ(2015年の6月中旬)、nVidia社の開発したDIGITSという開発ツールがあることを知りました。これをインストールしてみたところこれまでの苦労はなんだったのかというくらいインストールが簡単でした。色々サンプルを動かすうちにDeep Learningとは何かということが分かってきて楽しくなってきたわけで、脳内情報の整理のために記事を書こうと思います。なおこの記事は適宜加筆修正しますのでもし参考にされる方いらしたらご注意ください。内容がまちがっていたらすいません。出典、参考ページはのちほど追加します。 

 

基礎知識

Deep Learningとは

 Deep Learningとは人工ニューラルネットワーク(ANN, Artificial Neural Network)の発展形です。

人工ニューラルネットワーク(ANN)とは

 名前の由来はさておき、まずANNの使い道について解説します。ANNをつかう簡単な例として次のような問題を挙げます。

・x-y平面上に、2種類の点が分布している。2種類の点は、ある程度固まりを形成している。これらの境界線を機械的に決めたい。

 

f:id:jikkenyametatta:20150627203436p:plain

 

 ANNを使ってこの境界線を決めます。ANNはこのような状況を与えられると、x-y平面に適当な線をひいてはその妥当性を評価し、また修正した線を引いては妥当性を評価し、試行錯誤を繰り返して、2種類の点たちを一番良く分ける境界線を決めます。つまり「与えられた正解」と「線引きの結果」の食い違いが最小になるように、適当なアルゴリズムに基づいて線の傾きと切片の組み合わせを探索するわけです。

 この線引きが実際なんの役に立つのか。さっきのx-y平面を温度&湿度、2種類の点を晴れ&雨と置き換えてみましょう。さきほど求めた境界線というのは、温度&湿度のデータをもとに晴れor雨を分類(未知のデータに関しては推測)するのに対応します。これがいわゆる「人工知能」です。この線引きの仕組みを「何かしらのデータに基づいて人間に役立つ判断を勝手にやってくれるモノ=人工知能」として利用するのです。

数学的には

 この問題を解くのに、f(x,y) = y - (a*x  + b)という関数を考えます。ある点(x,y)が線の上側にあるか下側にあるかを表現するのに、この関数の正負でもって判定をします。なお、この関数は見方を変えると、2つのベクトル:(x,y,1)と(-a,1,-b)の内積を表現しているともいえます。

 この関数をかわいく描いたものが「パーセプトロン」です。パーセプトロンは脳の神経回路を構成するニューロンをモデルにしているとされています。これが連結してネットワークを形成していきます。

 

f:id:jikkenyametatta:20150627203443p:plain

学習

 ここまでは境界線の式の形を直線:y=ax+bとして話を進めてきました。ところが状況によっては、境界線を折れ線にしたい場面が出てきます。そういう場合はパーセプトロンを横にならべ、さらに多段に連結することで、線形関数のいくつか繋がった折れ線が表現できます。また活性化関数なるものをかませることで、パーセプトロンの応答を非線形にすることができます。こうしてパーセプトロン同士が繋がったネットワークがANNです。ANNを解説する文章ではよく「段数を増やすことでANNの表現力が増す」と説明されています。

 ANNが最適値を探索する経過は、脳の神経回路が最適化されていくことに似せて「学習」と呼ばれています。各パーセプトロンのパラメータを最適値に収束させるのに、Back propagationというアルゴリズムが使われます。

 

ANNと画像認識

 ANNを画像認識に使うことが可能です。2つの画像の類似度は、数学的にはベクトルの内積計算によって表現できます。詳しくは「テンプレートマッチング」、「コンボリューション、たたみ込み演算」、「たたみ込みニューラルネットワーク」で調べてみてください。さきほど紹介した線引き問題を発展させると画像認識の問題に応用できる、と覚えておいてください。

 

Deepであるということ

 段数を増やし識別の表現力を増したANNを使うのがDeep Learningです。ANNの段数をむやみに増やすとパラメータが収束しなくなってくるのですが、以下に挙げるような技術によって実用化され、従来の識別手法の性能を凌駕するまでのブレイクスルーが実現したとのことです。また筆者の理解では、計算機の高速化、ビッグデータといった状況もDeep Learningのブレイクスルー生む重要な要素であったと思っています。

・pre-trainingで適当な基底関数を用意する。Autoencoders。

・Restricted Boltzmann Machines

・activation functionとしてReLUやmaxout。

過学習を抑制するDropoutというテクニック

 

GPUとの相性

 もともとGPUは3Dゲームのリアルな映像を表現するために作られた演算装置です。比較的単純な演算を一気に大量のデータに実施するのに特化されています。先述の畳み込み演算はGPUによる並列化がしやすく、適切にチューニングすればCPUに対して10倍程度の高速化が可能とのことです。

 GPUメーカーの大手であるnVidia社は、画像認識、Deep LearningをGPUの応用の柱の一つとして位置づけているようで、ソフト、ハード両面からDeep Learning人口を増やすべく色々製品を出してきています。

NVIDIA® DIGITS™ DevBox

 nVidia社によると、CaffeというDeep LearningのツールGPUを使うと、CPUの約8~9倍の高速化、さらにcuDNNというライブラリの利用で約16~17倍の高速化ができたとのことです。

cuDNN v2: Higher Performance for Deep Learning on GPUs | Parallel Forall

 

python

 ネットワークの検証や自作のプログラムへの組み込みにはpythonが良く使われます。pythonを覚えましょう。

 

Deep Learningのツール

 有名どころではCaffe, Pylearn2, Cuda-convnet2, Torch7などが挙げられます。

現在のところ一番はじめやすいのはChainerだと思います(筆者しらべ)。筆者のメインのマシンはWindows7で、WindowsというのはDeep Learningをやるのに向いていない環境のようですが、Chainerはpythonのインストールの枠組み(pip)を使うことで簡単にインストールできます。

 

chainer.org

 しかし、ChainerでGPUを使った演算をしようとするとうまくいきませんでした。pycudaというライブラリのインストールがうまくいきません。しかしこれはインストーラが改良されればクリアできる問題だと思いますので、筆者は今後もひきつづきChainerを注目していきたいと思っています。

DIGITS

 こうして色々ツールを試していくなかで筆者が一番楽だと思ったのはCaffe+DIGITSです。Caffeはthe Berkeley Vision and Learning Centerが開発したもので、GithubのDeep Learningのカテゴリの中で一番人気があると見えます。nVidia社もCaffeのことをなんだか贔屓にしているように見えます。そしてnVidia社が作ったCaffeの開発ツールがDIGITSです。

 

DIGITSを動かすまで

環境

 筆者の環境は以下のとおりです。

 OS:Ubuntu 14.04 LTS

 CPU:Corei7-4790@3.60GHz*8

 MEM:8GB

 GPUGeForce GTX 750

  

インストール方法

 本家サイトからファイル一式をダウンロードします。このファイル一式の中にはcudaやcuDNNが予め入っています。ただしダウンロードするにはnVidiaのDeveloper Programsに登録する必要があったと思います。上級者はgithubからダウンロードしてきて自分で設定しても良いです。

developer.nvidia.com

 

githubのページにインストール方法が載っています。

NVIDIA/DIGITS · GitHub

install.shを実行するとpythonの環境とMNISTのデータがインストールされます。runme.shを実行するとhttpサーバーが起動します。ウェブブラウザでlocalhostを指定し、表示されるページがDIGITSの操作画面です。

チュートリアルの実行

  チュートリアルのMNISTのデータをいじってみましょう。

DIGITS/GettingStarted.md at master · NVIDIA/DIGITS · GitHub

 筆者のマシンではMNIST10kでLeNetを学習させるのに2分40秒程度でした。validationデータのaccuracyは99.07%と出ています。

 いっぽうAlexNetやGoogLeNetというもっとDeepなネットワークモデルを選択することができますが、筆者のマシンで学習を実行したところ、cudaのout of memoryエラーが出て落ちました。Batch sizeというパラメータを最低値の1に減らしても落ちます。どうやら筆者のGPUではメモリが足りないようで、動かすにはもっと大きなメモリをつんだ高級GPUを買ってくれということのようです。

DIGITSのここが便利

・データセット、ネットワークモデルの管理が楽

・学習の様子がリアルタイムでモニターできる

・ジョブを連投できる。前のジョブが終わったら勝手に次のジョブが始まる。

・識別の際、ネットワークの各レイヤーで何が起こっているのかをすぐ可視化できる。チューニングにかなり役立つ。

 

自作データで学習させる

 自作のデータで学習をさせてみましょう。ここではテスト用に抽象的なデータを生成します。画像の生成にはOpenCVを、乱数発生にはnumpyを使っています。

gista89b3f29fc41189ba270

 

これを実行すると64*64pixのサイズの以下のような3種類の画像が、それぞれ個別のフォルダの中に生成されます。生成する数は10個としています。この後紹介する実験ではこの数字を1万にして、計3万枚の画像を使っています。

f:id:jikkenyametatta:20150627192951p:plainラベル「n」。もやもやした背景+点というノイズ画像

f:id:jikkenyametatta:20150627192946p:plainラベル「c」。中央付近に黒い直線がある

f:id:jikkenyametatta:20150627192958p:plainラベル「o」。中央付近に黒い丸がある

 これら3つのフォルダのあるフォルダをDIGITSでTraining Imagesのfolderとして指定します。このファイル名尾がそのまま教師データのラベルになります。フォルダ構造が深い場合は直下のフォルダ構造がラベルになります。この中からデフォルトではランダムに選んだ25%ぶんが検証用データになります。

 これをLeNetを使って学習させてみます。LeNetはIntended image sizeが28x28(gray)と書いてありますが、チャンネル数(カラーか白黒か)と画像のサイズは、データセットに応じて勝手に調整されるので、サイズを無理矢理合わせる必要はありません。ただし、コンボリューションのカーネルサイズやレイヤーの深さは、画像に写っている物体の構造の大きさに応じて変更したほうがいいです。変更したい場合は「Custom Network」の編集欄で編集しましょう。

 学習を始めると学習経過をあらわすグラフが表示され、随時更新されていきます。所要時間は9分50秒、accuracy=99.8%、loss=5.8*10^-3でした。

f:id:jikkenyametatta:20150627195533p:plain

 

 学習済みのモデルを使って、適当な画像の識別をさせることができます。このとき「Show visualizations and statistics」をオンにすると、中身でどのような計算が行われているのかを覗くことができます。また

・学習の途中の状態(エポック毎のスナップショット)で識別を試せる

複数の画像をテキストファイルで指定して一気に識別させる

という機能もあります。

 

さいごに

 筆者がポスドクの任期が切れて無職になったら、AV業界に転職して、この技術をアダルト動画のモザイク処理に応用したいと思います。

 

謝辞

 機械学習系の情報やUbuntuの設定のしかたを色々おしえてくれる後輩のよこやまくんに御礼もうしあげます。