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

interprism's blog

インタープリズム株式会社の開発者ブログです。

Deep Learningを理解したつもりになったので書いてみる(前半)

Deep Learning

この投稿は インタープリズムの面々が、普段の業務に役立つ記事を丹精込めて書き上げる! Advent Calendar 2016 - Qiitaの15日目 の記事です。

はじめに

最近、AI、特にDeep Learningについて知識を得たので、それについてなるべくわかりやすく解説したいと思います。

「Deep Learningとは何か?」

自分が得た結論は、

「ある定められた”多少曖昧でも構わない入力データ”に対して、”概ね期待する結果データ”を高い精度で得るための技術」

であると考えている。

  • ”多少曖昧でも構わない入力データ”
  • ”概ね期待する結果データ”

にポイントがあるわけだが、それをこれから解説していきたいと思います。

演繹的AIと帰納的AI

  • 自分のコマを常に最大にするように打ち手を選択するオセロ
  • マリオカートの敵キャラカートの動き
  • 電卓で四則演算を行う
  • ボタンひとつ最適なエレベータを呼び出す
  • カーナビに道を示唆してもらう

このどれもが広義の意味でAIと呼ぶことができる。 しかし上記のどれもがDeep Learningによって得られるAIと根本的に違う部分がある。

これらを区別するためにDeep Learningの技術を使わないAIを演繹的AI、Deep Learningの技術を使うAIを帰納的AIと呼ぶことにする。

その心は、、、

演繹的AIの特徴としては、入力データの形が極めて限定的であるという点がある。そして、これらの限定的なデータのパターンに対して、プログラマー(もしくは論理回路エンジニア)が網羅的に出力データを算出するプログラム(もしくは論理回路)を用意することで、次の動作を決めるという共通の特徴をもつ。このプログラムは用途により異なり、上記5つの例でいえば、5つの別々のプログラムをプログラマーが事前に作成しなければならない。入力ダータに対応する出力データを導き出すロジックを明確にする必要がある。プログラムが入力データに対応する出力データを演繹的に導き出すのである。

一方、帰納的AIは、入力データの形をより抽象的に定義することができる。Deep Learningするためのプログラムはプログラマーが予め作って置かなければならないが、個々の機能を果たすプログラムを個別に作る必要はない。プログラマーが特定の用途に応じたプログラムを作る変わりに、似たような入力と出力のパターンを大量に読み込ませる(学ばせる)ことで、その機能をもつプログラム(関数)を自動的に作り出すことができる。入力データに対応する出力データを導き出すロジックを明確にする必要はない。大量の前例から帰納的に導き出すのである。

少し話が抽象的になってしまったので、少し具体的な話をしてみよう。

自動運転のアルゴリズムは実装可能か?

自動車を運転する時の人の動きを追ってみよう。

  1. 座席に乗り込み、
  2. エンジンを始動し、ギアをドライブに入れる。
  3. 前方に危険がないかを確認し、ブレーキをはなしアクセルを踏む。
  4. 速度に注意しながらアクセルを調整し、
  5. 行きたい方向を確認しながらハンドルを切る。
  6. 信号を確認し赤信号ならば、ブレーキを踏んで、
  7. 停止線か前方の車の直後で止まる。
  8. 青信号になったら、また3.に戻る。

3.以降をAIが担当すると過程して、これを実現するにはどのようにプログラムすることになるのか、少し考えてみよう。

id 入力 出力
3. 前方を確認し アクセルを踏む
4. 速度をみて アクセルを調整する
5. 行きたい方向を見て ハンドルを切る
6. 赤信号を確認して ブレーキを踏む
7. 停止線か前方の車の距離を確認して ブレーキを踏む
8. 青信号を確認して 3.に戻る

基本的に自動車の運転の時、入力データは視覚に頼ることがほとんどだ。すなわちデジタル・ビデオカメラを360度の視野角で設置すれば、判断に必要な情報は全て揃うということになる。デジタルカメラからのデータをデジタルデータに変換可能であることは言わずもがな理解できる。

そして出力データはアクセル、ブレーキ、ハンドルを、それぞれ数十段階で調整できれば、十分ではないかと思われる。仮に、それぞれ100段階で調整ができたとして、パターンの識別子があれば、車を自在に操るのに十分な出力データの信号を表現することができる。

この入力データに対する出力データを導くプログラムもしくは関数さえあれば、原理的に自動運転技術は完成するのである。

これを演繹的AIで実現させようとした場合(すなわち、Deep Learningの技術を使わない場合)、このプログラムを人間(プログラマー)の手で作り出さなければならない。 デジタル・ビデオカメラで得られた情報は、コンピュータにとっては無味乾燥な01信号であり、まずこれらの01信号を景色として有機的な解釈が必要になる。すなわちその解釈をするプログラムを作らなければならない。自動車がまったく同じ道を走ったとしても、雨の時、晴れの時、朝、昼、夜等によっても入力データは異なる形で表現される。そのバリエーションは天文学的なパターンになることは比較的簡単な計算で予想ができる。赤信号と赤いランドセルをしょった女の子を見分けるだけでも大変なプログラムが必要であり、これは、演繹的アルゴリズムによって自動運転するソフトウェアを人間の手で開発することが現実的には不可能であることを意味している。

条件反射->パブロフの犬

条件反射(じょうけんはんしゃ)とは、動物において、訓練や経験によって後天的に獲得される反射行動のこと。(by wikipedia)

ソビエトの生理学者イワン・パブロフは、メトロノームを鳴らした後、犬に餌を与えることを繰り返すことで、例え餌を与えなくても、メトロノームを流すだけで、その犬が唾液を出すことを観測し、条件反射というものを定義付けた。

車の運転はパブロフの犬のような生理学的な意味での条件反射とは違うが、目から得られる決められた条件(入力)によって手足を反応(出力)させるという点においては、抽象的に類似するところがある。

メトロノームの音は特定のタイミングで特定の周波数の音波を作り出すことで得られ、まったく同じでないにしても概ね同じようなタイミングで同じような周波数の音波を作り出すことは可能であり、これをパブロフの犬は耳の鼓膜で捉え、脳に伝えられた電気信号から、一回づつの音色が完全に同じでなかったとしても、概ね同じであれば、メトロノームの音として解釈して、唾液を出すような指示を脳が送り出す。 パブロフの犬は、メトロノームの概念を知らないだろうし、特定の周波数で空気が震えて、それが鼓膜を揺らして、脳がそれを解釈して、論理的、演繹的に考えて、さあ唾液を出す時が来た、などと意識して行動するはずもないが、とにかく、パブロフの犬の脳に存在する脳神経細胞のネットワーク(ニューラルネットワック)が鼓膜で捉えた特定の入力情報から、唾液を出すという出力結果を繰り返しの学習により学んだのである。

Deep Learningはこのような技術の応用といえる。

帰納的方法による自動運転の実装

先程の自動運転の車の例に戻ろう。 例えば、ドライブレコーダーで、ある無事故無違反のタクシードライバーの運転を1年間録画して、その時々のアクセル、ブレーキ、ハンドルの捜査も(デジタルデータで)記録したとする。

これは一種の写像を形成することになる。

単純にするために、入力データを1000 x 1000すなわち100万画素のデジカメで0.1秒に1回づつ撮影したものとする。1画素あたりRGBをそれぞれ8bitづつ割り当てたとすると1枚の画像につき(非圧縮で)、

24bits (= 3bytes) x 1M = 3M bytes

の入力データを得る。1画素はint(32bit)整数値で表現可能なため、この1つの入力データを整数が100M個込合わさったものとみなすと の要素のベクトル値と考えることができる。

一方出力データは、アクセル、ブレーキ、ハンドルを1〜100の百段階で分けて数値表現するとすると の要素と考えることができる

すなわちデジカメから捉えたデータからアクセル、ブレーキ、ハンドルを適切に捜査するための信号を算出する関数(写像)を とするとその定義域、値域は

となる。

数学的な表現を使うと

となる。果たしてこの関数はどんな形をしているのだろうか?

実はこの多次元ベクトル関数の形はどんな形であるかを考える必要はない 。概ね車の運転とは似たような場面で似たようなことをすればよいのである。 すなわち、先程例に出したタクシードライバーの1年間のドライブ記録からこの関数 を導き出して、実際に走る際にデジカメから得た入力データをこの関数 で変換し、アクセル、ブレーキ、ハンドルに電気信号として送ることができれば、概ね車は正しく動いてくれるはずなのである。この概ねという部分がポイントで、元来コンピュータは離散的0,1信号の集合を厳格な論理回路で処理する特性上、正確さというメリットを得る。その反面、応用がきかないというデメリットを持っていたが、Deep Learningはこの厳格さを諦めることで、応用力という大きな武器を手に入れたのである。

普遍性定理

先の例で多次元ベクトル関数 があれば自動運転の自動車は完成するという話をしたが、これを少し抽象的に捉えると、「任意のデータサンプルからそのような出力(近似値)を得る多次元ベクトル関数を作り出すことは可能か」という命題に帰着することができる。

そんなことが可能なのだろうか?

実はニューラルネットワークによる比較的単純な関数を利用することで、それが可能であることが数学的に証明されている(らしい)。 これはある種の普遍性をもっており(任意の入力に対して任意の出力を返せる関数を作り出せるという点で)、普遍性定理と呼ばれている(らしい)。

何やら

を使って証明するらしいが、厳密な証明は偉い数学者に任せるとして、我々はもう少し直感的にそれを理解したい。(それでも多少の数学の知識は使う)

まずは、一次元でこのこと(任意の関数を作り出せること)を確認し、それの多次元化は読者の数学的センスに任せることにしたい。

例えば、関数

を作りたいとする。

どうやってこの関数を作り出すのだろうか。 わかりやすく結論からいえば、

ステップ関数を重ねて作り出す

のである。

ステップ関数とは特定の定義域でのみ一つの値をとって、それ以外の定義域では0を返す関数のことである。

関数 をステップ関数の和で表現するには

として

と定義すると はかなりラフであるが、-5 <= x < 5でそれなり(最大誤差 )に に近い値をとる関数になる。

もっと一般的な関数について考えてみよう。

仮に が具体的にどんな関数かをしらずに を満たす の組を10000個与えられたとする これを以下のとおり表現する

与えられた10000個のデータを

として

とする(すなわち を昇順に並び替える)。

この時 関数 を |

と定義し

|

とすると、 への近似関数になることはわかってもらえると思う。

このように、サンプリングデータから関数を作るプログラムは、比較的に簡単に実装可能であるが、この作り方によってできる関数 には重大な欠点がある。それはなんだろうか?

それは 関数の実行速度である。単純に考えて、サンプリングデータが増えれば増えるほど、 関数はその内部処理において条件分岐が比例して増えていく。

この関数は1次元の関数でサンプリング数も1万程度なので、実際にこのようなやり方で関数を作ったとしても、それなりの速度で動くかもしれないが、例えば画像データをサンプリングデータとして使う場合、入力データは100pixel*100pixelの比較的小さい画像でも、1万次元のベクトル値になり、10万枚の画像データを入力値で場合分けした場合、区分の場合分けは、 という天文学的数となり、その関数は実用的な速度で動作するとは思えない。

関数を作り出す時の時間がそれなりにかかったとしても、 使う時には高速に動作してほしいのである。

さらにこの手法は1次元の入力値の場合は比較的簡単に定義域を上記の手法で分割、well-definedな形で定義可能だが、n次元になった場合には、サンプリングデータが存在しない定義域が発生してしまうため、この定義域に対する結果をどのように設定すべきかは簡単には決められない。

この問題を解決するのが、ニューラルネットワークをヒントに生まれた関数である。

それは次のようなものだ

これはいわゆる隠れ層が1層で、個のニューロンを持つニューラルネットワークが作り出す関数である。 このを調整することで任意の関数の近似関数が得られるというわけだ。

「なぜこの関数により任意の関数の近似関数が得られるのか」、「近似関数を得るためのはどのように求めることができるのか」、をこれから丁寧に解説していきたい、と思っていた、、、

最後に

極めて言い訳がましいが、本当は普遍性定理の解説をしっかりしたいと思っていた。 が、それをしようとすると、文章はおそらく、3倍以上になり、しかも、その作成には、とってもとっても時間がかかり、さらにさらに

Neural networks and deep learning

より上手に解説できるとは到底思えない。 そもそも自分のDeep Learningに関する知識は99%このサイトによるものだ。 日本語の翻訳も

ニューラルネットワークと深層学習

にあるので、ひとまず一旦ここでこの記事は終わりにして、もし、万が一このブログを読んだ人から多くの要望があれば、改めて、普遍性定理の解説をしてみたいと思います。

interprism.hatenablog.com

インタープリズムの面々が、普段の業務に役立つ記事を丹精込めて書き上げる! Advent Calendar 2016 - Qiita16日目の記事

PAGE TOP