2015年9月4日の「プログラマのための数学勉強会@福岡 #1」でのプレゼン資料です。 https://maths4pg-fuk.connpass.com/event/18609/
(2023/4/12に再アップ)
ぼくの実装した最弱のディープラーニング2015/9/4 きしだ なおき
View Slide
機械学習
学習が進むにつれて正答グラフがなんとなくあがってきているなんかAirplaneって言ってる現在の状況
機械学習とは• 多数のデータからパラメータを学習する• いろいろ判定に使う• あんまりファンタジーじゃない
ニューラルネットワーク• ニューロンを模した構造
各ユニットの計算• 入力に重みをかけてバイアスを足して活性化関数を適用
活性化関数• 入力に、なにか掛けて足すだけでは線形にしかならない• 非線形な活性化関数を入れる– シグモイド関数– ReLU(正規化線形関数)• 計算が速い!
ニューラルネットワークの学習
最急降下法• 微分して傾きを求めて深いほうに進む• 最適ではない谷に落ちないように工夫が必要
バックプロパゲーション• 誤差を逆伝播させる
ディープラーニングによる画像識別
ディープラーニング• 階層の深いニューラルネット• 最近、人工知能っていわれてるのは、ほぼこれ• いままでできなかったわけ– コンピュータが遅かった• GPUで速い計算– データがなかった• インターネッツ!– データあさり放題• クラウドソーシング!– ImageNetの1400万の画像はクラウドソーシングでタグ付けしてるらしい
参考文献• 「深層学習」– 広い範囲が解説してある– http://www.amazon.co.jp/dp/4061529021• AlexNet論文– パラメータなどが詳しく説明してあるhttp://www.cs.toronto.edu/~fritz/absps/imagenet.pdf
畳み込みニューラルネット• 畳み込み層やプーリング層といった、特徴的なレイヤーを持つニューラルネット• 画像識別に向いている• AlexNetで有名に– 2012年のILSRVCで2位に大差をつけて優勝
畳み込み層• フィルターを畳み込む• 重み共有
プーリング層• 区域の最大値をとったり平均をとったりする• 学習パラーメタはない
正規化層• 値の平均や分散を一定にする• 学習パラメータはない
AlexNetの構造• C->P->N->C->P->N->C->C->C->P->F->F->F– C:畳み込み層• 96/256/384/384/256– P:プーリング層– N:正規化層– F:全結合• 4096/4096/1000• いま動いてるやつ– C->P->N->C->P->N->F->F• C:48/96• F:1024/256
学習の工夫
データ正規化• 入力画像の画素ごとの平均をとっておいて、入力画像から引く
ミニバッチ• 一枚の画像ごとに重み更新するんではなくて、何枚かの画像の差分を平均して重みを更新する
モメンタム• 重みの更新に慣性をつける。• 谷に落ちにくくなる
局所正規化• 近いフィルタの出力を使って正規化する
ドロップアウト• 複数の機械学習の結果を平均させるといい結果になる。• 複数の機械学習器を用意するのは面倒• ニューラルネットのユニットを確率的に省く– 構造の違うニューラルネット!
doubleではなくfloatを使う• 学習に精度はあまり関係ない– 「誤差の減り方は殆ど同じであり、数値に高い精度は必要ない」http://news.mynavi.jp/articles/2015/04/08/gtc2015_google/• 速くなった!– float 95枚/分– double 75枚/分
ぼくの機械学習が学習してくれなかったわけ• フィルタの初期値が大きすぎた– フィルタは標準偏差0.01、平均0のガウスノイズに– バイアスは0か1• 青イルカ本に書いてない工夫– 局所正規化• となりのフィルタ出力と平均化させる– 重み減衰を取り入れる• aparapiのバグ!– これはひどい
GPU対応
GPUつよい!• GPU– ちょうたくさんコアがある– 同じ処理を行う– 行列計算に向いてる• GTX 970– 1664コア!– 衝動買い!
aparapi– A PARalell API– Javaで書いたコードを実行時にOpenCLのコードに自動変換してくれる。– JavaでGPUコードが書ける!– Mac Book Proでもいける!(Intel Iris Pro)
記述• Kernelを継承• runを実装– getGlobalId()でインデックスを取る• executeを呼び出し– 引数で与えた回数runが呼び出される@Overridepublic void run() {int fxy = getGlobalId();float d = result[fxy] >= 0 ? delta[fxy] : 0;tempBiasDelta[fxy] = learningRate * d;}execute(outputChannels * outputWidth * outputHeight);
効果• AlexNetの学習• 自宅 (Core i7 4コア+GTX 970)– CPU 15枚/分– GPU 95枚/分• このMac(Core i7 4コア+Intel Iris Pro)– CPU 12枚/分– GPU 16枚/分• ImageNetのサンプル1400万枚が100日で学習できる!– CPUなら640日!
バグがある・・・• 三項演算子のカッコが反映されない– (修正してプルリクなげてます)• CPUとの結果と比較するテストを用意したほうがいい– けど、丸めの違いを考慮するの面倒void proc(int fxy) {float d = (result[fxy] >= 0 ? 1 : 0) * delta[fxy];tempBiasDelta[fxy] = learningRate * d;}void kishida_cnn_kernels_ConvolutionBackwordBiasKernel__proc(This *this, int fxy){float d = (float)(this->result[fxy]>=0.0f)?1:0 * this->delta[fxy];this->tempBiasDelta[fxy] = this->learningRate * d;return;}
〆
課題• ミニバッチ内のサンプルが偏らないようにする• 学習結果の保存・読み込み– (9/5-6の土日に実装した)• 学習結果を使った判定– いまはドロップアウトしたまま
まとめ• 一ヶ月がんばればなんでも組める気がする• お金さえあればたくさんデータが処理できる