crash.academy · 来たるべきai新時代に向けて...
TRANSCRIPT
ITの世界は、この10年で大きく変わったクラウドとモバイルの時代
2004年 Google上場
2006年 Amazon EC2, S3
2007年 Apple iPhone
2008年 Microsoft Azure
2008年 Google Android
2012年 Facebook上場
世界は、この先10年でどう変わるのか?
来たるべきAI新時代に向けて
モバイルとクラウドの時代が始まって10年が経った。次の10年を展望した時、AI技術が、その新しい技術的中核として登場しようとしている。
ただ、モバイルが携帯電話の、クラウドがデータセンターの、ある意味では連続的な発展だったのに対して、ニューラル・ネットワークは、ほとんどの技術者にとって全く新しい技術である。そこには、技術的な「断絶」がある。
問題は明確である。我々は、来たるべきAI新時代に向けて、学ぶことから始めなければならない。同時に、重要なことは、今後の10年を展望すれば、それはすべての技術者にとって必要な課題になるだろうだということである。
A. 統計的分析に基づく、数値予測・クラス分け
これは昔から統計学の手法として存在する、回帰分析やクラスター分析と考え方は、基本的に同じものである。
ただ、マシンのパワーが飛躍的に増大して、大量のデータを短時間で処理できるようになり、かつ効果的なビジュアリゼーションが可能になったのが、実践的には新しく、かつ重要な変化である。
現在、クラウドで提供されている、大部分の機械学習のサービスは、このクラスに属する。
同時に、「決定論的なアプローチ」に対する「統計的なアプローチ」の優位という方法論的な自覚は、現在の機械学習技術・AI技術の多くの領域に、大きな影響を与えつつある。
B. 経験的に構築された知識・推論・対話システム
パーソナル・アシスタント・システムGoogleのGoogle Now, AppleのSiri, MicrosoftのCortana, AmazonのAlexa等々。私たちの身近なところで、もっとも活発に応用が進んでいる分野。完成度の高い 「質問応答システム」として、(かつての)IBMのWatsonがある。
入力(Speech to Text)、出力(Text to Speech)に、ニューラル・ネットワーク技術を利用する。
「パーソナルアシスタント」のプログラムは、Turing Test
的には、「知的」にふるまっているように見えるのだが、その多くの実装は、「知的」なものとは言えない。
C. ニューラルネットワークに基づく、知覚・運動系へのアプローチ。Deep Learning
現在、活発に研究・応用が進んでいる分野である。文字認識・発話の文字列への変換、静止画・動画からの対象の判別・動きの検出等々で、大きな成功を収めている
基本的なモデルの起源は、生物の知覚・感覚(主要には、視覚・聴覚)を司る神経回路網にある。
生物の知覚・感覚の能力は、運動能力と密接に結びついて、感覚・運動系を構成しているので、ロボットの動作の制御、ドローンの姿勢制御、自動運転等にも、このアプローチは有効で、応用分野を拡大している。
「女性が公園でフリスビーを投げている」 「幼い子がテディベアを持ってベッドに座っている」
「一群の人たちが野外マーケットでショッピングをしている」「フルーツスタンドにはたくさんの野菜がある」
イメージからテキストへ
言語理解
D.人間固有の言語能力の機械による実現
「機械翻訳システム」 本来は、意味理解を含む人間の一般的な言語能力に関わっている。ただ、機械翻訳の場合、質問に答えることが求められているわけではない。それは、ある言語から他の言語への形式的な「書き換え」システムなのかもしれない。
この領域は、最終的には、機械が人間のように、言語の「意味」を理解して、「知識」を活用して「意味」のある活動をするのを目指している。ある意味、人工知能の本丸である。ただ、多くの課題が残されている。
HoTT(Homotopy Type Theory)とUnivalent Theory
論理=数学的には、 a : A には、様々な解釈がある。ここでは、他の解釈と比較して、HoTTでの a : A の解釈を見てみよう。
1. 集合論: Russellの立場Aは集合であり、aはその要素である。
2. 構成主義: Kolmogorovの立場Aは問題であり、aはその解決である
3. PAT: Curry & Howardの立場Aは命題であり、aはその証明である。
4. HoTT: Voevodskyの立場Aは空間であり、aはその点である。
”Propositions as Types” “Proofs as Terms”
数学的認識の理解
E. 人間の数学的・論理的な推論能力に関わるもの
ここでは、経験的な起源からは相対的に独立な、純粋に数学的な定理の証明や、複雑な証明の機械による支援が課題になる。この分野でも、COQ等の「証明支援システム」を中心に、興味ふかい前進がある。 マルレク「「型の理論」と証明支援システム -- Coqの世界」
http://bit.ly/1qbdXVE を参照されたい。
かつての日本の「第五世代」的な、AIに対する「論理的」な(というより「定理証明的」な)アプローチは、現在のAI
研究においては主流ではない。ただ、そのことは、他のすべての領域と同じように、数学的・論理的なアプローチの有効性を否定するものではない。
数学や物理といった知識の体系は、誰もが生得的に持つ言語能力や経験的な知識の体系には、還元されない。
AI技術を構成する複数の流れの中で、なぜ、ニューラル・ネットワークが重要なのか?
A) 既知のデータの統計的分析をもとに、数値予測・クラス分けを行うもの。機械学習技術。
B) 経験的に構築された知識・推論・対話システム。パーソナル・アシスタンス・システム etc。
C) ニューラルネットワークの手法を用いて、生物の感覚・運動系の能力の相同物を機械上で実現しようとするもの。ディープ・ラーニング。
D) 人間固有の言語能力の機械による実現。
E) 人間の数学的・論理的な推論能力に関わるもの。
ニューラル・ネットワークは、新しいAI技術の現在の技術的中核だから
A) 既知のデータの統計的分析をもとに、数値予測・クラス分けを行うもの。機械学習技術。
B) 経験的に構築された知識・推論・対話システム。パーソナル・アシスタンス・システム etc。
C) ニューラルネットワークの手法を用いて、生物の感覚・運動系の能力の相同物を機械上で実現しようとするもの。ディープ・ラーニング。
D) 人間固有の言語能力の機械による実現。
E) 人間の数学的・論理的な推論能力に関わるもの。
NNは、同等の能力を持つ
Speech2TextText2SpeechHumanInterface
CNN+RNN機械翻訳KnowledgeDatabase
未来の、「人工知能」
「視覚」の誕生と発展
生物の進化の歴史の中で、「視覚」の能力は、5億年前の「カンブリア紀」に獲得された。それは、長い長い歴史を持っている。当時の食物連鎖の頂点に立っていた「アノマロカリス」は、立派な眼を持っていた。
「眼」の獲得、同じことだが、「視覚」の能力の獲得は、「捕食者」にとっても(獲物を見つける)、「被捕食者」にとっても(捕食者から逃れる)、その「生き残り」に、死活的に重要な意味を持つことになった。人間を含めて、すべての動物で、強い淘汰の圧力のもとで、視覚処理の能力は、高度に発達している。
同時に、この「視覚」の能力は、追いかける、捉える、あるいは、逃げるといった「運動能力」に深く結びついている
例1A -> (A->B) ->B の証明
Coq < Lemma S1 : forall A B :Prop, A ->(A->B) ->B.1 subgoal
============================forall A B : Prop, A -> (A -> B) -> B
S1 < intros.1 subgoal
A : PropB : PropH : AH0 : A -> B============================B
Goalから、forallを消す。→の前提部分を仮説に移す。introsは、複数のintroを同時に適用する。
Γ1 新しい仮定
新しいゴール
機械証明脳研究の取り組み
脳研究の取り組み
現在は、それぞれ異なった道を歩いているのだが、ニューラル・ネットワークの研究と脳研究とは、「人間の知能」の解明という共通の目標で結ばれている。ここでは、脳研究のいくつかの取り組みを紹介する。
Blue Brain ProjectHenry Markram
“I wanted to model the brain because we didn’t understand it.”
“The best way to figure out how something works is to try to build it from scratch.”
in vivo
in vitro
in silico
EU Human Brain Projectビジョン
人間の脳を理解することは、21世紀の科学が直面している最も偉大な挑戦の一つである。もしも、我々が、それに対して立ちあがることが出来るならば、我々は、我々を人間にしているものが何であるかについて深い洞察を得て、革命的なコンピュータ技術を構築し、脳の異常に対して新しい治療法を開発出来るだろう。今日、初めて、現代のICT技術が、こうした目標を到達可能なものにしている。
脳研究をめぐる「対立」の構図認知科学 vs 脳科学、トップダウン vs ボトムアップ
発端は、次年度のプロジェクトの予算配分で、認知科学的なアプローチの予算が、ばっさりと切られたことにあるらしい。それに反発した研究者のグループが、150名の連名で、欧州委員会に公開質問状を提出した。
対立の根底にあるのは、脳研究でのアプローチの違い。Henry Markramら主流派は、ニューロンとシナプスの数学的モデルに基づいて脳全体のモデルをボトムアップに作り上げようというアプローチ。 一方、反対派は、脳研究には、認知科学の知見に基づいたトップダウンのリバース・エンジニア的なアプローチが必要だという。
「鳥の羽の全てをシミュレーションしたとしても、鳥が空を飛べることを解明出来ないのと同じことだ」
例1A -> (A->B) ->B の証明
Coq < Lemma S1 : forall A B :Prop, A ->(A->B) ->B.1 subgoal
============================forall A B : Prop, A -> (A -> B) -> B
S1 < intros.1 subgoal
A : PropB : PropH : AH0 : A -> B============================B
Goalから、forallを消す。→の前提部分を仮説に移す。introsは、複数のintroを同時に適用する。
Γ1 新しい仮定
新しいゴール
機械証明ニューロンの働き
ニューロンの働き
脳の働きも、最終的には、脳を構成する無数のニューロンの働きに帰着する。
コンピューター上のニューラル・ネットワークを構成する個々の「ニューロン」の動作原理は、生体のニューロンの働きをシミレートしたものである。
ヘッブの法則Donald O. Hebb
ヘッブの法則(ヘッブのほうそく)は、脳のシナプス可塑性についての法則である。ヘッブ則、ヘブ則とも呼ばれる。心理学者のドナルド・ヘッブによって提唱された。ニューロン間の接合部であるシナプスにおいて、シナプス前ニューロンの繰り返し発火によってシナプス後ニューロンに発火が起こると、そのシナプスの伝達効率が増強される。また逆に、発火が長期間起こらないと、そのシナプスの伝達効率は減退するというものである。
The Organization of Behavior. 1949年
https://goo.gl/2HsDwK
例1A -> (A->B) ->B の証明
Coq < Lemma S1 : forall A B :Prop, A ->(A->B) ->B.1 subgoal
============================forall A B : Prop, A -> (A -> B) -> B
S1 < intros.1 subgoal
A : PropB : PropH : AH0 : A -> B============================B
Goalから、forallを消す。→の前提部分を仮説に移す。introsは、複数のintroを同時に適用する。
Γ1 新しい仮定
新しいゴール
機械証明ニューラル・ネットワークとその表現
ニューラル・ネットワークとその表現(1)
一つのニューロンの動きを考える
一つのニューロンの内部の状態の表現
複数のニューロンからなる一つの層の内部の状態の表現
式は便利だ! Y = W・X + b が表すもの
X1
X2
X3
X4
H1
H2
H3
M1
M2
M3
M4
Y1
Y2
ニューラル・ネットワークの例
一つ一つの丸が、一個のニューロンを表している。一つのニューロンは、その「出力」を、他のニューロンに、送り出す。
一つのニューロンの動きを考える
以下の文中に現れる「ニューロン」は、コンピューター上でシミレートされた偽の「ニューロン」である。ただし、基本的な動作原理は、本物のニューロンを真似ていることを知っておくことは、役に立つと思う。
ニューロンの働きは、発火するか発火しないかの
1か0かのディジタル・スタイル
個々のシナプスの性質同じ発火信号を受けても、受け止めるニューロン内でのその信号の「強さ」は、シナプスごとに異なる。
興奮性シナプスからの信号の強さから抑制性シナプスからの信号の強さを引いた値がある閾値を越えると、ニューロンは、「発火」する。
興奮性シナプスからの信号の強さから抑制性シナプスからの信号の強さを引いた値がある閾値を越えると、ニューロンは、「発火」する。
ニューロンの働きは、発火するか発火しないかの
1か0かのディジタル・スタイル
個々のシナプスの性質同じ発火信号を受けても、受け止めるニューロン内でのその信号の「強さ」は、シナプスごとに異なる。
ニューロン発火の条件
あるニューロンが「発火」するかは、次のようにして決まる。
興奮性シナプスから受け取る信号の強さ全体 A から抑制性シナプスから受け取る信号の強さ全体 B を引いて、その値がある閾値 C より大きければ発火する。
A – B > C 発火 ( A – B – C > 0 )A – B < C 発火しない ( A – B – C < 0 )
発火賛成と発火反対の多数決。ただし、賛成票が、ある一定数以上(閾値)、反対票を上回らないといけないというルール。至極、単純である。
賛成票 - 反対票 > 閾値 発火賛成票 - 反対票 < 閾値 発火しない
賛成票:3+3+2=7反対票:2+1+2=5
賛成票 - 反対票 = 2 > 1(閾値)
発火!
ニューロン発火の判断賛成票 - 反対票 > 閾値 発火
閾値=1の場合
個々のシナプスの性質は異なる内部の数字は、シナプスごとに異なる
信号を受けた時に伝えられる、信号の「強さ」
X1=1
X2=1
X3=1
X4=1
X5=1
X6=1
2
3
1
32
2
賛成票:0+0+2=2反対票:2+1+2=5
賛成票 - 反対票 = -3 < 1(閾値)
発火せず!
ニューロン発火の判断賛成票 - 反対票 < 閾値 発火しない
閾値=1の場合X2, X4からの信号なし
X1=1
X2=0
X3=1
X4=0
X5=1
X6=1
2
3
1
32
2
個々のシナプスの性質は異なる内部の数字は、シナプスごとに異なる
信号を受けた時に伝えられる、信号の「強さ」
賛成票:3+3+0=6反対票:2+0+2=4
賛成票 - 反対票 = 2 > 1(閾値)
発火!
ニューロン発火の判断賛成票 - 反対票 > 閾値 発火
閾値=1の場合X3, X5からの信号なし
X1=1
X2=1
X3=0
X4=1
X5=0
X6=1
2
3
1
32
2
個々のシナプスの性質は異なる内部の数字は、シナプスごとに異なる
信号を受けた時に伝えられる、信号の「強さ」
「重み」と「バイアス」
賛成票の数 Aをプラスの値に反対票の数 Bをマイナスの値 B’ にし、閾値 Cの符号を逆にして C’ (バイアス)とすると、発火の条件 A – B > C (すなわち、A – B – C > 0)は、A + B’+ C’ > 0 の形になる。
各シナプスごとに異なる投票権の大きさを「重み」という。興奮性シナプスはプラスの「重み」を持ち、抑圧性シナプスはマイナスの「重み」を持つと考えるということ。
一つの入力Xi(0か1の値をとる)には、それに対応した一つのシナプスが存在する。そのシナプスの重みをWiとすれば、この一つのシナプスの投票数は、入力 Xi に 重みWi をかけたもの。
入力Xiと重みWiとバイアスbで発火の条件を表す
今、6つの入力Xi (i=1,2,...6)があったとしよう。この時、この入力に対応するシナプスの重みをWi (i=1,2,...6)とすれば、各シナプスでの投票数は、入力Xiに対応する重みWiをかけたものだから、一つのニューロン全体の投票数は、このニューロンのすべての6個のシナプスの投票を足し合わせたものになる(符号も込みで考えている)。
この投票数にバイアスを足し合わせたものがプラスの時、このニューロンは発火する。
式で表すと、入力 X1,X2,..X6は、0または1でW1X1+W2X2+W3X3+W4X4+W5X5+W6X6+ b > 0 の時発火ということになる。
X
X1,X2,..X6は、0または1で
W1X1+W2X2+W3X3+W4X4+W5X5+W6X6
+ b > 0
の時発火
重み:Wiシナプスごとの賛成票の投票権をプラスの値に反対票の投票権をマイナスの値にすると、式が簡単になる。
バイアス:bついでに、閾値 Cの符号を逆にすれば、
式はもっと簡単になる。それを「バイアス」という。
X1
X2
X3
X4
X5
X6
W2=3
W3=-1
W4=3W5=2
W6=-2
W1=-2
W1X1+W2X2+W3X3+W4X4+W5X5+W6X6
+ b =(-2)x1+3x0+(-1)x1+
3x0+2x1+(-2)x1-1 =
-2-2+2-2-1= -5<0
発火せず!
重みWi=[-2,3,-1,3,2,-2]バイアス b=-1
入力Xi=[1,0,1,0,1,1]の場合
X1=1
X2=0
X3=1
X4=0
X5=1
X6=1
-2
3
-1
32
-2
W1X1+W2X2+W3X3+W4X4+W5X5+W6X6
+ b =(-2)x1+3x1+(-1)x0+
3x1+2x0+(-2)x1-1 =
-2+3+3-2= 2>0
発火!
X1=1
X2=1
X3=0
X4=1
X5=0
X6=1
-2
3
-1
32
-2
重みWi=[-2,3,-1,3,2,-2]バイアス b=-1
入力Xi=[1,1,0,1,0,1]の場合
一つのニューロンの内部の状態の表現
一つのニューロンの内部の状態は、ニューロンがシナプスを通じて受け取る刺激である「入力」と、シナプスごとの「重み」と、発火の閾値に対応する「バイアス」の三つの量で表現できる。
X1
X2
X3
X4
X5
X6
W1X1+W2X2+W3X3+W4X4+W5X5+W6X6+b > 0 ?
重み W=[W1,W2,W3,W4,W5,W6]バイアス b
入力 X=[X1,X2,X3,X4,X5,X6]の場合の発火の条件
まず、一つのニューロンで考えてみよう
X1
X2
X3
X4
X5
X6
W1X1+W2X2+W3X3+W4X4+W5X5+W6X6+b > 0 ?
重み W=[W1,W2,W3,W4,W5,W6]入力 X= [X1, X2, X3, X4, X5, X6]
バイアス b
重みと入力の対応する項目同士をかけて、すべて足し合わせて、それにバイアス bを足したもの。
X1
X2
X3
X4
X5
X6
W1X1+W2X2+W3X3+W4X4+W5X5+W6X6+b > 0 ?
重み W=[W1,W2,W3,W4,W5,W6]バイアス b
入力 X=[X1,X2,X3,X4,X5,X6]の場合の発火の条件
X1
X2
X3
X4
X5
X6
先の行ベクトルXを列ベクトルに変えたものをXTで表す
XT =
行ベクトルと列ベクトルの積
行ベクトル W=[W1,W2,W3,W4,W5,W6] と行ベクトル X=[X1,X2,X3,X4,X5,X6] を列ベクトルに変えた XTとの積を次のように定義する。
W・XT = [W1,W2,W3,W4,W5,W6] ・
= W1X1+W2X2+W3X3+W4X4+W5X5+W6X6
対応する要素を掛けて、足し合わせたものである。
X1
X2
X3
X4
X5
X6
X1
X2
X3
X4
X5
X6
W・XT + b > 0 ?
この時、重み W=[W1,W2,W3,W4,W5,W6]
バイアス b入力 X=[X1,X2,X3,X4,X5,X6]の場合の発火の条件は、次のように、簡単に書ける。
もしも、Xが最初から行ベクトルの形で与えられていれば、重みWとバイアスbを持つあるニューロンの発火の条件は、W・X+b > 0 で与えられることになる。これは、y = ax + b > 0 と同じくらい、簡単な式の形である。
X1
X2
X3
X4
X5
X6
W・XT + b > 0 ?
この時、重み W=[W1,W2,W3,W4,W5,W6]
バイアス b入力 X=[X1,X2,X3,X4,X5,X6]の場合の発火の条件は、次のように、簡単に書ける。
この式は、ニューラルネットワークで、もっとも重要な式の一つである。
複数のニューロンからなる一つの層の内部の状態の表現
複数のニューロンの集まりが、一つの「層」として、入力を受け取り出力を返すことがある。
この層の内部の状態も、この層が受け取る「入力の全体」と、シナプスごとの「重みの全体」と、層を構成するニューロンの閾値に対応する「バイアスの全体」という三つの量で表現できる。
X1
X2
X3
ニューロン1
ニューロン2
ニューロン3
入力 X=[X1,X2,X3]
例えば、入力 X=[1,0,1] で
ニューロン1の重みが [2,-3,4] バイアスが -4ならニューロン1の出力は、2・1+(-3)・0+4・1-4=2>0で発火。
ニューロン2の重みが [-4,1,-5] バイアスが 5ならニューロン2の出力は、(-4)・1+1・0+(-5)・1+5=-4<0で発火せず。
ニューロン3の重みが [-4,-2,5] バイアスが 2ならニューロン3の出力は、(-4)・1+(-2)・0+5・1+2=3>0で発火。
三つのニューロンで考えてみよう
X1
X2
X3
ニューロン1W1・X
T + b1 > 0
ニューロン2W2・X
T + b2 > 0
ニューロン3W3・X
T + b3 > 0
入力 X=[X1,X2,X3]
重み W1=[W11,W12,W13]バイアス b1
重み W2=[W21,W22,W23]バイアス b2
重み W3=[W31,W32,W33]バイアス b3
ニューロン1の値: W1・XT + b1 = W11X1+W12X2+W13X3+b1
ニューロン2の値: W2・XT + b2 = W21X1+W22X2+W23X3+b2
ニューロン3の値: W3・XT + b3 = W31X1+W32X2+W33X3+b3
一般的には、
X1
X2
X3
ニューロン1W1・X
T + b1 > 0
ニューロン2W2・X
T + b2 > 0
ニューロン3W3・X
T + b3 > 0
入力 X=[X1,X2,X3]
重み W1=[W11,W12,W13]バイアス b1
重み W2=[W21,W22,W23]バイアス b2
重み W3=[W31,W32,W33]バイアス b3
W11X1+W12X2+W13X3+b1
W21X1+W22X2+W23X3+b2
W31X1+W32X2+W33X3+b3
これを、行列の積と和を使うと (あとで少し述べる)
W11,W12,W13 X1 b1
W21,W22,W23 X2 + b2 =
W31,W32,W33 X3 b3
これも、 W・XT + b の形をしている!
X1
X2
X3
X4
X5
X6
ニューロン1
ニューロン2
ニューロン3
ニューロン4
ニューロン5
ニューロン6
入力 X=[X1,X2,X3,X4,X5,X6]
六つのニューロンで考えてみよう。基本的には、同じである。
X1
X2
X3
X4
X5
X6
ニューロン1
W1・XT + b1 > 0
ニューロン2
W2・XT + b2 > 0
ニューロン3
W3・XT + b3 > 0
ニューロン4
W4・XT + b4 > 0
ニューロン5
W5・XT + b5 > 0
ニューロン6
W6・XT + b6 > 0
入力 X=[X1,X2,X3,X4,X5,X6]
重み W1=[W11,W12,W13,W14,W15,W16]バイアス b1
重み W2=[W21,W22,W23,W24,W25,W26]バイアス b2
重み W3=[W31,W32,W33,W34,W35,W36]バイアス b3
重み W4=[W41,W42,W43,W44,W45,W46]バイアス b4
重み W5=[W51,W52,W53,W54,W55,W56]バイアス b5
重み W6=[W61,W62,W63,W64,W65,W66]バイアス b6
X1
X2
X3
X4
X5
X6
ニューロン1
W1・XT + b1 > 0
ニューロン2
W2・XT + b2 > 0
ニューロン3
W3・XT + b3 > 0
ニューロン4
W4・XT + b4 > 0
ニューロン5
W5・XT + b5 > 0
ニューロン6
W6・XT + b6 > 0
入力 X=[X1,X2,X3,X4,X5,X6]
値:W11X1+W12X2+W13X3+W14X4+W15X5+W16X6+b1
値:W21X1+W22X2+W23X3+W24X4+W25X5+W26X6+b2
値:W31X1+W32X2+W33X3+W34X4+W35X5+W36X6+b3
値:W41X1+W42X2+W43X3+W44X4+W45X5+W46X6+b4
値:W51X1+W52X2+W53X3+W54X4+W55X5+W56X6+b5
値:W61X1+W62X2+W63X3+W64X4+W65X5+W66X6+b6
W11, W12, W13, W14, W15, W16 X1 b1
W21, W22, W23, W24, W25, W26 X2 b2
W31, W32, W33, W34, W35, W36 X3 + b3 =W41, W42, W43, W44, W45, W46 X4 b4
W51, W52, W53, W54, W55, W56 X5 b5
W61, W62, W63, W64, W65, W66 X6 b6
W11X1+W12X2+W13X3+W14X4+W15X5+W16X6+b1
W21X1+W22X2+W23X3+W24X4+W25X5+W26X6+b2
W31X1+W32X2+W33X3+W34X4+W35X5+W36X6+b3
W41X1+W42X2+W43X3+W44X4+W45X5+W46X6+b4
W51X1+W52X2+W53X3+W54X4+W55X5+W56X6+b5
W61X1+W62X2+W63X3+W64X4+W65X5+W66X6+b6
行列による表現(六個のニューロンの場合)
これも、 W・XT + b の形をしている!
式は便利だ!Y = W・XT + b が表すもの
数学的な表記を使うと、問題を簡潔に定式化できる。
ここでは、一つのニューロンの状態だけでなく、複数のニューロンからなる層も、一つの式で表現できる背景について述べる。
この節は、読み飛ばしてもらって結構です。
式は便利だ!
Y = W・XT + b が表すもの
ニューラル・ネットワークの本を読んで、最初につまずくのは、行列が出てくるあたりだと思う。ただ、ニューラル・ネットワークの理解で、当面、必要なことは、式 Y = W・XT + b が表現しているものを理解することだ。見慣れていないだけで、難しい数学ではない。
具体的な例で、式 Y = W・XT + b が表しているものを、紹介したいと思う。一見、複雑に見える沢山の関係が、この式一つで表現されていることがわかるはずだ。式は便利だということがわかってもらえると思う。
以下の例では、XもYもbも、最初から列ベクトルだとしよう(このことを、仮に、X=[X1,X2,...Xn]
Tのように表そう)。この時、 Y = W・X + b が、何を表すかを考えよう。
Y = W・X + b が表すもの
Wが数値(スカラー)の時
Y=y, X=x, W=a, b=b なら、この式は、y = ax + b という、式を表す。
Y=y, X=x, W=2, b=3 なら、この式は、y = 2x + 3 という、式を表す。
Y=y, X=x, W=4, b=0 なら、この式は、y = 4x という、式を表す。
Y = W・X + b が表すもの
Wがベクトルの時
Y=y, X=[x1,x2]T W=[w1,w2] b=b0 なら、この式は、
y = w1・x1+w2・x2+b0 という、式を表す。
Y=y, X=[c,d]T W=[m,n] b=b なら、この式は、y = m・c+n・d+b という、式を表す。
Y=y, X=[1,0]T W=[2,3] b=4 なら、この式は、y = 2・1+3・0+4 = 6 という、式を表す。
Y=y, X=[x1,x2,x3]T W=[w1,w2,w3] b=b0 なら、
y = w1・x1+w2・x2+w3・x3+b0
Y=y, X=[x1,x2,x3,x4]T W=[w1,w2,w3,w4] b=b0 な
ら、y = w1・x1+w2・x2+w3・x3+w4・x4+b0
Y = W・X + b が表すもの
Wが行列の時
2x2の行列(2行2列の行列)を、[ [a,b], [c,d] ]と表そう。同様に、3x3 (3行3列の行列)の行列を、[ [d,e,f], [g,h,i], [j,k.l] ] と表そう。 ....
Y=[y1,y2]T, X=[x1,x2]
T、W= [ [2,3], [4,5] ]、b=[1,2]Tのとき、 Y = W・X + b は、次の二つの式を表す。y1 = 2x1+3x2+1、 y2 = 3x1+5x2+2
Y=[y1,y2,y3]T, X=[x1,x2,x3]
T、W= [ [2,3,-1], [4,-5,1], [1,2,3] ]、 b=[1,2,3]Tのとき、 Y = W・X + b は、次の三つの式を表す。y1 = 2x1+3x2-x3+1、 y2 = 4x1+5x2+x3+2、y3 = x1+2x2+3x3+3
Y = W・X + b が表すもの
Wが行列の時
例えば、Wが6x6(6行6列)の行列の時、 Y = W・X + bが表すものの例については、先に見た。もちろんnが100でも10,000でも同じ式で、表現できる。
Wが n行 m列の行列の時、 Y = W・X + bが、n個の式を表していることを示すために、次のように書くこともある。Yn = Wn・X + bn
こうした表記は、数百・数千のノードからなるニューラル・ネットワークが満たす多数の関係式を、一つの式で簡潔にまとめることができるので、プログラミング上も極めて有用である。
Y=W・XT+b と Y=X・W+b という二つの表記
これまで、入力の X=[X1,X2,...,Xn] を行ベクトルとして、Y=W・XT+b という表記を用いてきた。多くのドキュメントもこうした表記を採用している。
X=[X1,X2,...,Xn]T として、 Y=W・X+bと表しても、この
二つの表記は、同じ内容を表し、重みを表す行列Wも、同じものである。 どちらでも XT, b は列ベクトルである。
ただ、 X=[X1,X2,...,Xn] を行ベクトルとした時、Y=X・W+b という表記も可能である。ここでのWは、先のWの行と列を入れ替えたものである。W=WT。bは、行ベクトルとなる。b=bTである。基本的には同じである。
ただ、TensorFlowでは、 Y=X・W+b の方の表記を採用している。TensorFlowに関連する部分に入ったら、この表記に切り替えたいと思う。
ニューロンを動かす-- 活性化関数 (Activator)
活性化関数は、その名前の通りに、一つのニューロンが発火(活性化)する時の条件と出力を関数の形で表したものである。いろいろな種類の活性化関数がある。
活性化関数
先に見たようにように、重みWとバイアスbを用いて、W・X + b という式で、ニューロンの興奮のレベルが計算できるとするなら、 「W・X + b > 0 なら、ニューロンは発火する」という条件は、どのように表現できるだろうか?
W・X + b は、ニューロンの内部の状態を表す量なので、その値を、ニューロンの出力に変える関数 φ をうまく定義して、φ (W・X + b ) がそのニューロンの発火・出力を表現するようにすればいい。こうした関数 φ を、「活性化関数」とよぶ。
例えば、ニューロンの発火の信号の強さが 1で、発火しない時は信号が 0 であるなら、次のような関数 φ を考えればいい。 0 x<=0 の時
1 x> 0 の時φ (x) =
sigmoid 関数 (logistic 関数)
先の φ を、右のグラフでは、赤線で示した。x=0の時に、非連続に変化する。
実際の応用では、こうした飛躍のない、青線のような関数が持ちいられることが多い。
これをsigmoid関数という。(logistic関数)
近似的には、x<0の時 0x>0の時 1 基本的には0と1の間の値をとる。
ReLU (rectified linear unit)
rectifier は、「整流器」。ReLUは、マイナスの値は通さず 0を返すが、プラスの値は、そのまま通す。(青線)
sigmoidは、0と1の間の値を出力するが、ReLUの出力には、そうした制限はない。
断続はないが、x=0のところで折れ曲がっている。それを、スムースに近似した関数も存在する。(Softplus 緑線)
x<0の時 0 x>0の時 x の値をとる。
(
W・X + b =(-2)x1+3x0+(-1)x1+3x0+2x1+(-2)x1 -1 =
-2-2+2-2-1= -5
φ(W・X + b ) =sigmoid(-5) ≒ 0
重み W=[-2,3,-1,3,2,-2]、バイアス b=-1入力 X = [1,0,1,0,1,1]T
φ(x) = sigmoid(x) の場合X1=1
X2=0
X3=1
X4=0
X5=1
X6=1
-2
3
-1
32
-2
0
一つのニューロンの出力は、φ( W・X + b )
の形で表せる。
W・X + b =(-2)x1+3x1+(-1)x0+3x1+2x0+(-2)x1 -1 =
-2+3+3-2= 2
φ(W・X + b ) =ReLU(2) =2
X1=1
X2=1
X3=0
X4=1
X5=0
X6=1
-2
3
-1
32
-2
重み W= [-2,3,-1,3,2,-2]、バイアス b=-1入力 X = [1,1,0,1,0,1]T
φ(x) = ReLU(x)の場合
2
一つのニューロンの出力は、φ( W・X + b )
の形で表せる。
X1
X2
X3
ニューロン1φ(W1・X + b1)
ニューロン2φ(W2・X + b2)
ニューロン3φ(W3・X + b3)
入力 X=[X1,X2,X3] T 出力 Yi = φ(Wi・X + bi)
重み W1=[W11,W12,W13]バイアス b1
重み W2=[W21,W22,W23]バイアス b2
重み W3=[W31,W32,W33]バイアス b3
W11,W12,W13 X1 b1
W21,W22,W23 X2 + b2
W31,W32,W33 X3 b3
φ
φ(W11X1+W12X2+W13X3+b1)
φ(W21X1+W22X2+W23X3+b2 =
φ(W31X1+W32X2+W33X3+b3)
複数のニューロンの出力も、 φ( W・X + b ) の形で表せる。
クラス分けの場合の出力に利用されるactivator。手書き数字画像の認識だと、提示された画像が0から9までの10個の数字のどれかだと判断しなければいけない。
ニューラル・ネットワークでは、こうした場合、出力層に、 0から9までの10個の数字に対応した10個のノードが並び、それぞれのノードの値が、「提示された画像がその数字である確率」であるようにする。
ノードごとに、確率を計算するのが softmax関数である。最終的には、10個のノードの中で、その確率が最大であるものが選ばれる。
softmax 関数
softmax 関数の性質
softmax関数は、それが適用される層のノードのsoftmac関数の値をすべて足し合わせると1になるという性質を持つ。それは、softmaxの出力が「確率」であることを考えれば、すぐわかる。
例えば、先の例で、ある画像が3である確率が 0.75であったとしよう。そのことは、その画像が3以外の数字である確率は、1 - 0.75 = 0.25 だということである。3以外のノードの確率(softmaxの出力の値)を全部足しても、0.25にしかならないということである。
次のこともわかる。あるノードのsoftmaxの値が上がれば、他のノードの値は下がる。あるノードの値を下げれば、他のノードの値は上がる。全部足して1になるように、値は変化する。
One-Hot-Vector
先のsoftmax関数の出力例の、一番上のノードは、「この画像は数字nである」という、ニューラル・ネットワークの判断を表しているの。もちろん、softmaxの値が一番大きいところが選ばれて、そこに一つだけに1が入っていて、残りはすべて0になっている。
こうした一つだけに1が、残りすべてが0のベクトルを、One-Hot-Vector と呼ぶ。
One-Hot-Vectorは、クタス分けの出力に現れるだけではない。ニューラル・ネットワークを「学習」させるための訓練用データは、画像と一緒に「この画像は数字nである」という「正解」の情報を持っていなければならない。訓練用データは、画像と正解を示すOne-Hot-Vectorの二種類のデータから構成されている。
例1A -> (A->B) ->B の証明
Coq < Lemma S1 : forall A B :Prop, A ->(A->B) ->B.1 subgoal
============================forall A B : Prop, A -> (A -> B) -> B
S1 < intros.1 subgoal
A : PropB : PropH : AH0 : A -> B============================B
Goalから、forallを消す。→の前提部分を仮説に移す。introsは、複数のintroを同時に適用する。
Γ1 新しい仮定
新しいゴール
機械証明ニューラル・ネットワークをグラフで表現する
複数のニューロンからなる一つの層を、グラフで表す
ここから、TensorFlowを使った、ニューラル・ネットワークの実装のスタイルを紹介する。
「グラフ」「演算ノード」「テンソル」というのが、基本的なコンセプトとなる。
複数のニューロンからなる一つの層の出力の計算、φ( W・X + b ) を、次のような図形で表わすことにしよう。
行列の積X
W
行列の和
b
φの適用
先の例で言うと、Xは、[X1,X2,X3]
T の列ベクトルで、Wは 3x3の行列、bは、[b1,b2,b3]
T の列ベクトルである。
複数のニューロンからなる一つの層の出力の計算、φ( X・W + b ) を、次のような図形で表わすことにしよう。
行列の積X
W
行列の和
b
φの適用
先の例で言うと、Xは、[X1,X2,X3] の行ベクトルで、Wは 3x3の行列、bは、[b1,b2,b3] の行ベクトルである。
TensorFlowのスタイルに準じて、表記を切り替えていることに注意!φ( X・W + b )
TensorFlowでは、こうした図形を「グラフ」と呼んでいる。グラフは、「ノード」とノード同士を結ぶ「辺」からできている。
行列の積X
W
行列の和
b
φの適用
TensorFlowのグラフのノードは、基本的には、演算を行う「演算ノード」である。様々な演算が用意されている。演算を行わない「変数ノード」「プレースゴルダー・ノード」も存在する。
変数ノード 変数ノード
プレースホルダー 演算ノード 演算ノード 演算ノード
TensorFlowのグラフが有用なのは、一つの同じグラフで、様々な複雑なニューラル・ネットワークを表現できるからである。(もちろん、X,W,bのタイプはことなるのだが)
行列の積X
W
行列の和
b
φの適用
もっとも、そのことは、基本的には、このグラフの場合には、すでに見た φ( X・W + b ) という数学的な抽象化に負っている。ただ、グラフの方が具体的に処理をイメージしやすい。
TensorFlowのスタイルに準じて、表記を切り替えていることに注意!φ( X・W + b )
いくつかの例で考えてみよう。4つの入力を受け取り、3つの出力を返す、3つのニューロンからなる「層」を考えてみよう。これも、このグラフで表現できる。
行列の積X
W
行列の和
b
φの適用
[X1,X2,X3 ,X4]
4行3列の行列 [b1,b2,b3]
ある「層」の出力の数は、その層に含まれるニューロンの数に等しいのは、当然である。
2つの入力を受け取り、5つの出力を返す、5つのニューロンからなる「層」を考えてみよう。これも、このグラフで表現できる。
行列の積X
W
行列の和
b
φの適用
[X1,X2]
2行5列の行列 [b1,b2,b3,b4,b5]
一般に、n個の入力を受け取り、m個の出力を返すニューロンの「層」では、Xはn次元の行ベクトル、Wはn行m列の行列、bはm次元の行ベクトルである。
複数の層からなるニューラル・ネットワークを、グラフで表す
もちろん、通常の表現でも、ニューラル・ネットワークはグラフとして表現される。ただ、TensorFlowのグラフは、それをさらに単純化する。
そうした単純化されたグラフ表現は、TensorFlowの大きな能力である。そのことと、グラフを流れる「テンソル」というデータの捉え方とは、結びついている。
X1
X2
X3
X4
H1
H2
H3
M1
M2
M3
M4
Y1
Y2
Full Connectなニューラル・ネットワークの旧来のグラフでの表現
Full Connectというのは、向かい合ったノードがすべて接続されているということ
X1
X2
X3
X4
H1
H2
H3
M1
M2
M3
M4
Y1
Y2
X層 H層 M層 Y層
H層の重み WH
バイアス bH
活性化 φH
M層の重み WM
バイアス bM
活性化 φM
Y層の重み WY
バイアス bY
活性化 φY
旧来のグラフ
X1
X2
X3
X4
H1
H2
H3
M1
M2
M3
M4
Y1
Y2
X層 H層 M層 Y層
H層の重み WH
バイアス bH
活性化 φH
M層の重み WM
バイアス bM
活性化 φM
Y層の重み WY
バイアス bY
活性化 φY
旧来のグラフ
積X
W
和
b
φ 積
W和
bφ 積
W和
bφ
H層のニューロン数:3重み W:4x3次元バイアス b:3次元
M層のニューロン数:4重み W:3x4次元バイアス b:4次元
Y層のニューロン数:2重み W:4x2次元バイアス b:2次元
X層 H層 M層 Y層
こっちのグラフの方が、ずっとわかりやすい!
X層の入力:44次元
TensorFlowのグラフ
積X
W
和
b
φ 積
W
和
b
φ
隠れ層のニューロン数:15重み WH:784x15次元バイアス bH:15次元
出力層のニューロン数:10重み WO:15x10次元バイアス bO:10次元
入力層 隠れ層 出力層
こっちのグラフの方が、ずっとわかりやすい!
隠れ層の入力:784784次元
TensorFlowのグラフ
Sigmoid SoftMax
グラフの例(学習用)
https://www.tensorflow.org/
Logit Layer, ReLu Layerを見れば、先に見た「層」のパターンが現れているのがわかる。
演算ノードの、MatMulは行列の積、BiassAddはバイアスの加算である。
Logit LayerのActivatorは、Softmaxで、ReLu LayerのActivatorは、ReLuである。
(このグラフ、GitHubで提供されているコードのグラフとは、少し、違っている。)
グラフの例(学習済み)
ニューラル・ネットワークでは、学習の過程と、学習済みの結果を利用する過程では、計算量には、大きな差がある。
学習に持ちいたグラフの一部を再利用して、学習済みのデータ(基本的には、学習された各レーヤーの重みとバイアスである)を利用すれば、スマホでも機械学習の成果を利用できる。TensorFlowは、それを可能にする
少し複雑なグラフの例(これは、LSTMのセル)σ(sigmoidのこと), tanh は、活性化関数
次の式をグラフで追ってみるといい。
Chris Olah "Understanding LSTM Networks"http://colah.github.io/posts/2015-08-Understanding-LSTMs/
例1A -> (A->B) ->B の証明
Coq < Lemma S1 : forall A B :Prop, A ->(A->B) ->B.1 subgoal
============================forall A B : Prop, A -> (A -> B) -> B
S1 < intros.1 subgoal
A : PropB : PropH : AH0 : A -> B============================B
Goalから、forallを消す。→の前提部分を仮説に移す。introsは、複数のintroを同時に適用する。
Γ1 新しい仮定
新しいゴール
機械証明ニューラル・ネットワークのグラフ表現とモジュール構造
ニューラル・ネットワークのグラフ表現とモジュール構造
それぞれのフレームワークごとに表現のスタイルには違いがあるものの、重要なことは、それが表現しているニューラル・ネットワークの「グラフ」は、同一のものであるということである。それは、基本的なモジュールの組み合わせでできている。
TensorFlowでは、複数のニューロンからなる一つの層は、次のようなグラフで表現される。
行列の積X
W
行列の和
b
φの適用
5つのノードがあるが、Wとbには、重みとバイアスの値が入り、残りの3つのノードは、演算を行うノードである。この層の働きは、φ(X・W+b) で表現される。
一つの層
積X
W
和
b
φ 積
W
和
b
φ
隠れ層のニューロン数:15重み WH:784x15次元バイアス bH:15次元
出力層のニューロン数:10重み WO:15x10次元バイアス bO:10次元
入力層 隠れ層 出力層
こっちのグラフの方が、ずっとわかりやすい!
隠れ層の入力:784784次元
TensorFlowのグラフ
# Hidden 1with tf.name_scope('hidden1'):
weights = tf.Variable(tf.truncated_normal([IMAGE_PIXELS, hidden1_units],
stddev=1.0 / math.sqrt(float(IMAGE_PIXELS))),name='weights')
biases = tf.Variable(tf.zeros([hidden1_units]),name='biases')
hidden1 = tf.nn.relu(tf.matmul(images, weights) + biases)# Hidden 2with tf.name_scope('hidden2'):
weights = tf.Variable(tf.truncated_normal([hidden1_units, hidden2_units],
stddev=1.0 / math.sqrt(float(hidden1_units))),name='weights')
biases = tf.Variable( tf.zeros([hidden2_units]),name='biases')
hidden2 = tf.nn.relu(tf.matmul(hidden1, weights) + biases)# Linear
....
....
TensorFlowでのDNNモジュールの記述例
DNNモジュールが、φ(X・W+b)の形をしていることは、簡単に確認できる。
DNN = [hiddenDim = 200
# DNNSigmoidLayer and DNNLayer are defined in Macros.ndlh1 = DNNSigmoidLayer(featDim, hiddenDim, featScaled, 1)ol = DNNLayer(hiddenDim, labelDim, h1, 1)
ce = CrossEntropyWithSoftmax(labels, ol)err = ErrorPrediction(labels, ol)
# Special NodesFeatureNodes = (features)LabelNodes = (labels)CriterionNodes = (ce)EvalNodes = (err)OutputNodes = (ol)
]
CNTKでのDNNモジュールの記述例
DNNSigmoidLayer, DNNLayerの定義は、Macro.ndlの中にある。
DNNLayer(inDim, outDim, x, parmScale) = [W = LearnableParameter(outDim, inDim,
init="uniform", initValueScale=parmScale)b = LearnableParameter(outDim, 1,
init="uniform",initValueScale=parmScale)t = Times(W, x)z = Plus(t, b)
]
DNNSigmoidLayer(inDim, outDim, x, parmScale) = [W = LearnableParameter(outDim, inDim,
init="uniform", initValueScale=parmScale)b = LearnableParameter(outDim, 1,
init="uniform",initValueScale=parmScale)t = Times(W, x)z = Plus(t, b)y = Sigmoid(z)
]
CNTKマクロでのDNNモジュールの記述例
DNNモジュールが、φ(X・W+b)の形をしていることは、簡単に確認できる。
例1A -> (A->B) ->B の証明
Coq < Lemma S1 : forall A B :Prop, A ->(A->B) ->B.1 subgoal
============================forall A B : Prop, A -> (A -> B) -> B
S1 < intros.1 subgoal
A : PropB : PropH : AH0 : A -> B============================B
Goalから、forallを消す。→の前提部分を仮説に移す。introsは、複数のintroを同時に適用する。
Γ1 新しい仮定
新しいゴール
機械証明グラフを流れる量 -- テンソル
4つの入力を受け取り、3つの出力を返す、3つのニューロンからなる「層」を考えてみよう。
行列の積X
W
行列の和
b
φの適用
[X1,X2,X3 ,X4]
4行3列の行列 [b1,b2,b3]
ただ、ここでは、ノードではなく辺の方に注目してみよう。どのようなタイプのデータが、辺の上を流れるかを考えよう。
4つの入力を受け取り、3つの出力を返す、3つのニューロンの「層」
行列の積X
W
行列の和
b
φの適用
[X1,X2,X3 ,X4]
4行3列の行列 [b1,b2,b3]
TensorFlowでは、こうしたデータをすべてテンソルと呼んでいる。どのような、タイプのデータか見てみよう。
4つの入力を受け取り、3つの出力を返す、3つのニューロンの「層」
行列の積X
W
行列の和
b
φの適用
[X1,X2,X3 ,X4]
4行3列の行列 [b1,b2,b3]
テンソルには、いろいろなタイプがある。
3次元の 3次元の 3次元の行ベクトル 行ベクトル 行ベクトル
2つの入力を受け取り、5つの出力を返す、5つのニューロンの「層」
行列の積X
W
行列の和
b
φの適用
[X1,X2]
2行5列の行列 [b1,b2,b3,b4,b5]
テンソルには、いろいろなタイプがある。
5次元の 5次元の 5次元の行ベクトル 行ベクトル 行ベクトル
TensorFlowとテンソル
TensorFlowのプログラムは、すべてのデータを表現するものとしてテンソル・データ構造を利用する。
TensorFlowのテンソルは、n次元の配列あるいはリストだと考えることができる。
テンソルは、静的な型と動的な次元を持っている。
計算グラフのノード間を移動するのは、テンソルだけである。
テンソルのランク(階数)
TensorFlowのシステムでは、テンソルは「ランク」と呼ばれる次元の単位で記述される。
テンソルのランクは、行列のランクとは異なるものである。
テンソルのランクは、(時には、位数(order)とか度数(degree)とかn次元とも呼ばれることがあるのだが)、テンソルの次元の数である。
例えば、Pythonのリストで定義された次のテンソルのランクは 2である。
t = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
テンソルのランク(階数)
ランク2のテンソルで、われわれが典型的に考えるのは「行列」である。
ランク1のテンソルは、「ベクトル」である。
ランク2のテンソルに対しては、t[i,j] という構文で、任意の要素にアクセスできる。
ランク3のテンソルには、t[i,j,k]でアクセスする必要がある。
ランク 数学的実体 Pythonでの表記
0 スカラー(大きさのみ) s = 483
1 ベクトル(大きさと向き) v = [1.1, 2.2, 3.3]
2 行列 (数字のテーブル) m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
3 3-テンソルt = [[[2], [4], [6]], [[8], [10], [12]], [[14], [16], [18]]]
n n-Tensor ....
テンソルのランク(階数)
テンソルの形
TensorFlowのドキュメントでは、テンソルの次元を記述するのに、ランク、形、次元数の三つを用いる。
Rank Shape
Dimension number
Example
0 [] 0-D A 0-D tensor. A scalar.
1 [D0] 1-D A 1-D tensor with shape [5].
2 [D0, D1] 2-D A 2-D tensor with shape [3, 4].
3 [D0, D1, D2] 3-D A 3-D tensor with shape [1, 4, 3].
n [D0, D1, ... Dn] n-D A tensor with shape [D0, D1, ... Dn].
ニューラル・ネットワークの「学習」と技術の特徴
データ依存:大量のデータの「学習」で、必要な能力をマシンに伝える。データを与えるのは、当面は、人間の仕事。
非言語的コントロール:プログラム言語によらず、マシンをコントロールする。
確率論的:ふるまいは、非決定論的で確率論的である。
学習・実行の非対称性:「学習」には、大規模・高機能なシステム(GPU・クラウド等)が必要だが、学習された能力は、小規模なモバイルでも、「実行」できる。
ハードウェア依存:学習・実行環境は、ともに、ハードウェアの進化に強く依存する。OSの進化にも大きな影響が及ぶだろう。
https://goo.gl/b5Pe5j
MS ResearchのDeep Learning “Project Adam”1,400万枚の画像を学習して、22,000のカテゴリーに分類できる。イヌとネコを区別できるだけでなく、イヌの犬種も正しく判別する。
http://goo.gl/2EMIkJ
非対称的
ニューラル・ネットワークの「学習」と技術の特徴
データ依存:大量のデータの「学習」で、必要な能力をマシンに伝える。データを与えるのは、当面は、人間の仕事。
非言語的コントロール:プログラム言語によらず、マシンをコントロールする。
確率論的:ふるまいは、非決定論的で確率論的である。
学習・実行の非対称性:「学習」には、大規模・高機能なシステム(GPU・クラウド等)が必要だが、学習された能力は、小規模なモバイルでも、「実行」できる。
ハードウェア依存:学習・実行環境は、ともに、ハードウェアの進化に強く依存する。OSの進化にも大きな影響が及ぶだろう。
機械学習の基本は、人間の知識を機械に移転すること
機械学習の基本を確認しよう。ただ、人間の知識を機械に移転するためには、単にマシンと大量のデータがあればいいというわけではない。正確にラベル付けられたデータの「作成」と「蓄積」が不可欠。それには、人間の根気強い、組織的な取り組みが必要。
「人間には容易でも機械には難しいこと」「機械には容易でも人間には難しいこと」
その境界は、動的に変化するのだが、いつの時点でも、機械に提供する学習データ作りは、前者。その段階を経なければ、機械は賢くならない。現実的には、それぞれに要する経済的なコストが、現実を動かす。その費用を、誰がどう負担するのか? 以下で、基本的な学習用データセットを見てみよう。
CIFAR-10 10のカテゴリーの画像データ
一つのカテゴリーに6,000枚。計60,000サンプル
https://www.cs.toronto.edu/~kriz/cifar.html
Tront大学
imagenet_fall11_urls.tgz http://goo.gl/BldrSR
WordNet ID n02084071 Dog, domestic dog, Canis familiaris
画像のURL
The Penn Treebank Project
https://www.cis.upenn.edu/~treebank/
Pennsylvania大学
https://www.ldc.upenn.edu/
基本的な性格をもつオープンなデータの共有が、機械学習のイノベーションをドライブしている
先の「データ作成のコスト」の問題に対する最も有力な回答は、オープンなコミュニティ(大学・学会を含む)が、基本的な性格をもつ学習用データを公開し、それを皆が共有すること。
(日本は、どうだろう? 少なくとも日本語は、日本がやるしかない。)
人間の自由時間の利用
2003 年に、ソリティアを遊んだ、人間の総時間は、90億時間。
ある 人たちは、コンピュータの無駄な計算サイクルについて話をしているが、人間の無駄なサイクルについては、どうなんだろう?
エンパイア・ステートビルを 作るために、人間が使った時間は、700万時間。
パナマ 運河を作るために、人間が使った時間は、2000万時間。(ソリティアの一日分以下)
Carnegy Melon Univ. Luis von Ahn
我々が、それぞれのドメインで持つ知識を、きちんとデータ化すること
それを機械に学習させる。量優先で質的規定が曖昧なBig Dataではなく、優れた質をもった、それぞれのドメインに固有のGood Data
を持つことが、より重要。ニッチでもいい。チャンスは、AIの応用領域の数ほど、たくさん存在している。もちろん、その前提は、基本的なオープンなデータの存在と共有なのだが。
ニューラル・ネットワークの学習 =「パラメーターを最適なものに修正すること」
ニューラル・ネットワークの学習というのは、大量の訓練用データを読み込んで、その出力が予想されるものに近い値を返すように、ネットワークのパラメーターの値を修正することである。
パラメーター修正の基本的な道具たち
ニューラル・ネットワークでのパラメーター修正を行うのに必要な道具立てを、あらかじめ、簡単に紹介しよう。その詳細については、その後に述べることにする。
Backpropagation
Loss Function
Gradient Descent
出力結果を見て、パラメーターを修正する
Backpropagation
ニューラルネットワークには 、膨大な数のパラメーターが存在する。望ましい結果を得るために、手動の試行錯誤で、パラメーターの修正を行っていては、ラチがあかない。
Rumelhart らが開発した(1986年) Backpropagation
は、こうしたパラメーターの修正を、システマチックに行う方法を提供する。
出力結果 が、予期していたものと異なっていたら、まず、その出力を行った一つ前の層にさかのぼって、パラメーター(重みWとバイアスb)を修正すればいい。
ニューラルネットワークが 、多段の層からなるならば、出力層の一つ前の層から始めて、順次、層をさかのぼってパラメーターの変更を行う。
出力結果と「正解」とのずれLoss Function (損失関数)
その為に、出力結果と予期していた「正解」とのズレを、何らかの方法で定式化する必要がある。そのズレを関数の形で表したものを Loss Function (損失関数)という。Cost Function (コスト関数)ということもある。
出力が「正解」と一致した時、 Loss Functionの値が最小値を取るようにする。この時、パラメーター修正の目的を、Loss Functionの値をできるだけ小さくすることだと言い換えることができる。
ある問題に対して、Loss Functionは一つとは限らない。どのようなLoss Functionを選ぶかで、パラメーター修正の効率は変化する。
Gradient Descent (勾配降下法)
パラメーター修正で、最もよく使われる方法が、このGradient Descent (勾配降下法)である。
Loss Functionを Jだとしよう。パラメーターのWとbの値が、それぞれ少し変化した時に、Jの値がどう変化するかを調べる。このJの変化が「勾配」である。「勾配」にそって、Jの値が下がるように、Wとbを変化させればいい。それが、Gradient Descent である。
数学的には、∂J/∂W と ∂J/∂b をチェックすることになる。Jは、ニューラル・ネットワークの出力と「正解」とのズレなので、φ(WX+b)という形の項を含んでいる。アクティベーターφとして、微分可能なものが好まれるのは、このGradient Descentに関係している。
一つのニューロンで数値予測する(線形回帰)
ここでは、ただ一つのニューロンでも、それが線形回帰の数値予測の能力を持つことを述べる。
単純なニューロンの集まりでも、パラメーター最適化のメカニズムと組み合わせれば、強力な機能を持ちうる。
ここでは、もっとも単純な一つのニューロンのパラメーター最適化が、線形回帰の数値予測の能力を持ちうることを示す。
一つのニューロンのパラメーターを動かす
ニューロン 一つの働きは、先に見たようにφ(W・X+b) と表現できる。φは活性化関数、W, X, b
はベクトルである。ここではさらに単純化して、入力を数字一つにする。この時、Wもただの数字になる。さらに、Activator φも取り除く。
このニューロン 一つの「ニューラル・ネットワーク」は、一つの数字の入力xに対して、内部のパラメーター(単なる実数である) a, b に応じて、ax+bを返すのである。この値をyとしよう。
y= ax+bは、直線を表す式である。この単純なニューラル・ネットワークでパラメーターを様々に変更するというのは、様々な直線を考えることに等しい。
入力が6つの場合シナプスが6つで重みも6つ
入力が1つの場合シナプスが1つで重みも1つ
これが、このニューロンの出力
入力X1=x
重みW1 = a
重みを a, バイアスを b とすると、ax+b が、このニューロンの出力になる
一つの入力と出力を持ち、一つだけのニューロンからなるネットワークは、y=ax+bという直線に対応している。このニューロンのパラメーターを動かすということは、下の図のようにこの直線を、いろいろに動かすということである。
a, b の値を変えれば、y=ax+bの形は変化する(傾きがaで、切片がbの直線である)
この図は、あるデータ(赤点)の分布を直線で近似しようというもの。統計学では「線形回帰」と飛ばれているものだ。(左の直線より、右の直線の方が「いい近似」を与えている。)
それでは、ある直線が、データの分布の「いい近似」であるとは、どういうことをいうのだろう。
データ群に一番「近い」直線?
ここでは、データ群と直線の「近さ」を、幾つかの図で、直感的に表してみよう。
実際的な応用では、一番「いい近似」の、直線が見つかれば、それに基づいて、数値予測が可能になる。もちろん、それはデータが線形に分布していると想定してのことなのだが。
入力X=x1
重みW = a
重みを a, バイアスを b とすると、ax+b が、このニューロンの出力になる
予測値 ax1+b 実際の値 y1
実際のyの値y1
実際のデータの値 x1から、ニューロンの出力で、Yの値を予測することを考える
入力X=x1
重みW = a
重みを a, バイアスを b とすると、ax+b が、このニューロンの出力になる
予測値 ax1+b 実際の値 y1
実際のyの値y1
予測値と実測値の誤差を、すべてのデータに対して最小にするような、a と b の値を求める。
ここでの「すべてのデータに対して」という条件に注意すること。
損失関数
どのように、データ群に一番「近い」直線を求めるか?その為に、「損失関数」という考え方を導入する。
損失関数(コスト関数ともいう)は、ニューラル・ネットワークで、重要な役割を果たす。ニューラル・ネットワークでの「学習」は、すべて「損失関数を最小のものにせよ」という指示に従ったパラメーター変更に帰着する。
誤差
誤差
誤差誤差
データの各点と、y=ax+b との誤差が、もっとも小さくなるように、a,b の値を修正する。
(x(i), y(i))
(ax(i)+b) – y(i)
( ax(i)+b), y(i) )
損失関数を定めて、誤差を最小にする a,bを求める
サンプル中のi 番目の点を (x(i), y(i))とすれば、y=ax+b上の点と点 (x(i), y(i)) との垂直方向の誤差は、(ax(i)+b) – y(i) となる。
誤差は、正負の値をとるので、単純に、誤差の平均を取っても、打ち消しあって、全体としての誤差の大きさはわからなくなる。
そこで、誤差の二乗をとって、その平均を最小にすることを考える。
a, b の関数である、この誤差の二乗の平均を、損失関数とすればいい。
誤差
誤差
誤差誤差
(x(i), y(i))
(ax(i)+b) – y(i)
( ax(i)+b), y(i) )
誤差の二乗の和を損失関数にする
こうした形の損失関数を、 “quadratic cost” という
係数1/2は計算上の便宜のためのもの
入力X=x1
重みW = a
重みを a, バイアスを b とすると、ax+b が、このニューロンの出力になる
予測値 ax1+b 実際の値 y1
実際のyの値y1
一つのデータについての垂直方向の誤差
(ax1+b) – y1
誤差が打ち消しあうのを避けるために二乗する((ax1+b) – y1)^2
すべてのデータについて、上の値を足し合わせる。
Σ ((axi+b) – yi)^2
損失関数
誤差
誤差
誤差誤差
(x(i), y(i))
(ax(i)+b) – y(i)
( ax(i)+b), y(i) )
あるa,b に対して、すべてのデータについての誤差の二乗の和が、損失関数の値になる
誤差
誤差
誤差誤差
(x(i), y(i))
(ax(i)+b) – y(i)
( ax(i)+b), y(i) )
あるa,b に対して、すべてのデータについての誤差の二乗の和が、損失関数の値になる
損失関数の値の計算
・・・・・全てのデータ
すべてのデータについて、与えられた a, b に基づいて予測値を計算し、実際の値との誤差を求める(赤い矢印)、その後、これらの誤差の二乗の和(あるいは、その平均)を、損失関数の値とする(緑の矢印)。
損失関数
クラス分けの場合の損失関数
出力が数値一つだけだったら、正解の数字との「誤差」を定義するのは容易である。それを損失関数にすればいい。
ただ、出力が、画像認識のようなクラス分けだったら、誤差の定義は簡単ではない。
クロス・エントロピー
クラス分けによく使われるSoftmaxの出力の場合で考えてみよう。例えば、数字の画像認識なら0から9までの数字に対応した10個のノードそれぞれに、その画像がそのノードに対応した数字である確率が入ってくる。こうした場合の損失関数に利用されるのが、クロス・エントロピーである。
p(x) q(x)
P(1)=2/3,p(2)=1/4,p(3)=5/24,p(4)=5/24 q(1)=1/8,q(2)=1/8, q(3)=5/8,q(4)=1/8
x=1の時 2/3log(1/8) = -2/3log8 = -2log2x=2の時 1/4log(1/8) = -1/4log(8) = -3/4log2x=3の時 5/24log(5/8)= 5/24log(5) - 15/24log2x=4の時 5/24log(1/8)= -5/24log(8) = -15/24log2全部足し合わせると
-(48log2+18log2-5log5+15log2+15log2)/24=-(96log2-5log5)/24
H(p,q) = (96log2-5log5)/24
Σ p(x)log(q(x))x
の計算
期待される目標の分布
実際のデータの分布
p(x) q(x)
P(1)=0,p(2)=1,p(3)=0,p(4)=0 q(1)=2/3,q(2)=1/4,q(3)=5/24,q(4)=5/24
x=1の時 0log2/3x=2の時 1log1/4x=3の時 0log5/24x=4の時 0log5/24全部足して
log1/4 = -log4 = -2log2H1(p,q) = 2log2
H1
Σ p(x)log(q(x))x
の計算
p(2) = 1 の場合の
「目標」のpの分布は、こういう形になる。
期待される目標の分布
実際のデータの分布
p(x) q(x)
P(1)=0,p(2)=1,p(3)=0,p(4)=0 q(1)=1/4,q(2)=2/3,q(3)=5/24,q(4)=5/24
x=1の時 0log1/4x=2の時 1log2/3x=3の時 0log5/24x=4の時 0log5/24全部で
log2/3 = log2 – log3
H2(p,q) = log3-log2
H2
Σ p(x)log(q(x))x
の計算
p(2) = 1 の場合の
「目標」のpの分布は、こういう形になる。
期待される目標の分布
実際のデータの分布
p(x) q(x)
P(1)=0,p(2)=1,p(3)=0,p(4)=0 q(1)=5/24,q(2)=2/3,q(3)=1/4,q(4)=5/24
x=1の時 0log5/24x=2の時 1log2/3x=3の時 0log1/4x=4の時 0log5/24全部足し合わせるとlog2/3
H3(p,q) = log3-log2
H3
Σ p(x)log(q(x))x
の計算
p(2) = 1 の場合の
「目標」のpの分布は、こういう形になる。
期待される目標の分布
実際のデータの分布
p(x) q(x)
P(1)=0,p(2)=1,p(3)=0,p(4)=0 q(1)=0,q(2)=1,q(3)=0,q(4)=0
x=1の時 0log0 = 0x=2の時 1log1 = 0x=3の時 0log0 = 0x=4の時 0log0 = 0
H5(p,q) = 0
H4
Σ p(x)log(q(x))x
の計算
p(2) = 1 の場合の
「目標」のpの分布は、こういう形になる。
期待される目標の分布
実際のデータの分布
p(x)が one-hot-value の時
ΣΣ p(x)log(q(x))N x
ー
= - { サンプル中の正解値をとった i についての log(q(i))の和 }
H(p,q) =
0 ≦ q(i) ≦ 1 で、 log(q(i)) ≦ 0 だが、q(i) 0 の時 log(q(i)) - ∞q(i) 1 の時 log(q(i)) 0
だから、q(i)が正解に近いほど、H(p,q)は小さくなる。
Σ log(q(i))N
ー=
クロス・エントロピーの値の計算
・・・・・全てのデータ
すべてのサンプル・データ x について、Σ p(x)log(q(x)) を計算し、(赤い矢印)、その後、これらをすべて足し合わせる。(緑の矢印)。
クロス・エントロピー損失関数
p(x)log(q(x)Σ
Σ
バイナリー・クロス・エントロピー
先に見たクロス・エントロピーは、二つの分布pとqが「似ているか?」については、あまり有効な情報を与えない。なぜなら、p(x)=1 以外のxの値でのqの値は、すべて無視するので。
ただ、次のように定義を変更すると、二つの分布の「近さ」を数値化できる。(計算が増えるので、必要ないかもしれないのだが)
この節は、読み飛ばしてもらって結構です。
H(p, q) = - { p(x)log(q(x)) + (1-p(x))log(1-q(x)) }Σx
P(x),q(x)は、確率を表しているので0 ≦ p(x) ≦ 1、 0 ≦ q(x) ≦ 10 ≦ 1-p(x) ≦ 1、 0 ≦ 1-q(x) ≦ 1
P(x) ≧ 0 で、log(q(x)) ≦ 0 だからp(x)log(q(x)) ≦ 0
(1−p(x)) ≧ 0 で、log(1-q(x)) ≦ 0 だから(1-p(x))log(1-q(x)) ≦ 0
よって、Σの中のp(x)log(q(x)) + (1-p(x))log(1-q(x)) ≦ 0 となる
Σの前に マイナス符号が付いているので、H(p, q) ≧ 0
H(p, q) = - { p(x)log(q(x)) + (1-p(x))log(1-q(x)) }Σx
マイナスが付いている
p(x)が成り立つ確率 p(x)が成り立たない確率
目標とする確率
データの確率
H(p, q) = - { p(x)log(q(x)) + (1-p(x))log(1-q(x)) }Σx
p(x)=0の時は、この項が消える
p(x)=1の時は、この項が消える
H(p) = - p(x)log(p(x))Σx
ShannonのEntoropy
Binary Entoropyの式の特徴
p(x) q(x)
P(1)=2/3,p(2)=1/4,p(3)=5/24,p(4)=5/24 q(1)=1/8,q(2)=1/8, q(3)=5/8,q(4)=1/8
x=1の時 2/3log(1/8)+(1-2/3)log(1-1/8) = 2/3log(1/8)+1/3log(7/8)x=2の時 1/4log(1/8)+(1-1/4)log(1-1/8) = 1/4log(1/8)+3/4log(7/8)x=3の時 5/24log(5/8)+(1-5/24)log(1-5/8) = 5/24log(5/6)+19/24log(3/8)x=4の時 5/24log(1/8)+(1-5/24)log(1-1/8) = 5/24log(1/8)+19/24log(7/8)全部足し合わせると
(-2/3log8+1/3(log7-log8)) + (-1/4log8+3/4(log7-log8)) +(5/24(log5-log6)+19/24(log3-log8) + (-5/24log8+19/24(log7-log8))
= ( -16log8+8log7-8log8-6log8+18log7-18log8 +5log5-5log6+19log3-19log8-5log8+19log7-19log8)/24
= ( -(16+8+6+18+19+5+19)log8+(8+18+19)log7-5log6+19log3)/24H(p,q) = - ( -91log8 + 45log7 – 5(log2+log3) +19log3)/24
= (278log2-45log7+14log3)/24
p(x) q(x)
P(1)=0,p(2)=1,p(3)=0,p(4)=0 q(1)=2/3,q(2)=1/4,q(3)=5/24,q(4)=5/24
x=1の時 0log2/3+1log(1-2/3) = log(1/3) = -log3x=2の時 1log1/4+0log(1-1/4) = log(1/4) = -2log2x=3の時 0log5/24+1log(1-5/24) = log(19/24) = log19 –log24x=4の時 0log5/24+1log(1-5/24) = log(19/24) = log19 –log24全部足し合わせると
-log3-2log2+log19-log24+log19-log24= -log3-2log2+2log19-2(log3+log8)= -3log3+2log19 – 8log2
H1(p,q) = 3log3+8log2-2log19
H1
p(x) q(x)
P(1)=0,p(2)=1,p(3)=0,p(4)=0 q(1)=2/3,q(2)=1/4,q(3)=5/24,q(4)=5/24
H’1
H(p, q) = - { p(x)log(q(x)) + (1-p(x))log(1-q(x)) }Σx
p(x)が、One Hot Valueの分布の場合でも、q(x)の分布の情報を拾っている。
p(x) q(x)
P(1)=0,p(2)=1,p(3)=0,p(4)=0 q(1)=1/4,q(2)=2/3,q(3)=5/24,q(4)=5/24
x=1の時 0log1/4+1log(1-1/4) = log(3/4) = log3 – log4x=2の時 1log2/3+0log(1-2/3) = log2/3 = log2 –log3x=3の時 0log5/24+1log(1-5/24) = log(19/24) = log19 –log24x=4の時 0log5/24+1log(1-5/24) = log(19/24) = log19 –log24全部足し合わせると
log3–log4+log2-log3+log19-log24+log19-log24= log4+2log19-2(log3+log8)= -log3-8log4+2log19
H2(p,q) = log3+8log2-2log19
H1-H2 = (3log3+8log2-2log19) –(log3+8log2-2log19)= 2log3 > 0
H2
p(x) q(x)
P(1)=0,p(2)=1,p(3)=0,p(4)=0 q(1)=5/24,q(2)=2/3,q(3)=1/4,q(4)=5/24
x=1の時 0log5/24+1log(1-5/24) = log(19/24) = log19 –log24x=2の時 1log2/3+0log(1-2/3) = log(2/3) = log2 – log3x=3の時 0log1/4+1log(1-1/4) = log(3/4) = log3 – log4x=4の時 0log5/24+1log(1-5/24) = log(19/24) = log19 –log24全部足し合わせると先のH2と同じになる
H3(p,q) = H2(p,q) =log3+8log2-2log19
H3
p(x) q(x)
P(1)=0,p(2)=1,p(3)=0,p(4)=0 q(1)=0,q(2)=3/4,q(3)=1/8,q(4)=1/8
x=1の時 0log0+1log(1- 0) = 0x=2の時 1log3/4+0log(1-3/4) = log(3/4) = log3 – log4x=3の時 0log1/8+1log(1-1/8) = log(7/8) = log7 –log8x=4の時 0log1/8+1log(1-1/8) = log(7/8) = log7 –log8全部足し合わせると
log3-log4+log7-log8+log7-log8= log3+2log7-8log2
H4(p,q) = 8log2-2log7-log3
H3-H4 = (log3+8log2-2log19) – (8log2-2log7-log3)= 2log3+ 2log7 -2log19 > 0
9x49 > 19x19
H4
p(x) q(x)
P(1)=0,p(2)=1,p(3)=0,p(4)=0 q(1)=0,q(2)=1,q(3)=0,q(4)=0
x=1の時 0log0+1log(1-0) = 0x=2の時 1log1+0log(1-1) = 0x=3の時 0log0+1log(1-0) = 0x=4の時 0log0+1log(1-0) = 0
H5(p,q) = 0
H5
Gradient descent勾配降下法
Gradient descent 勾配降下法は、ニューラル・ネットワークのパラメーター更新の基本的な手段である。多くのフレームワークでは、 Gradient descent が、標準的な関数として、あらかじめ組み込まれている。
仮説:
パラメーター: a, b
損失関数:
目標:
問題の整理
y(x) = ax + b
a, b y
a, ba, b
a, b の値を動かして、損失関数 J( a, b ) を最小のものにする
ある関数があって
その値を最小にしたい
基本的な考え方:
• ある からはじめる。
• の値を、 が減少するように
変化させる。
• 最小値になるまで、繰り返す。
Gradient descent(勾配降下法)
簡単にするために、二次元のグラフで考えよう。ある点から始めて、その点から極小点に近ずくためには、どうすればいいか?
二つの場合がある。その点が極小点の右側にある場合には、その点のx座標を少し減らせばいい。その点が極小点の左側にある場合には、その点のx座標を少し増やせばいい。
その点が、極小点の右にあるか左にあるかは、その点での接戦の傾きが、正であるか負であるかでわかる。
よって、α を正の数値とすれば、次の式が、より近づいた点の位置を与える。
直感的な説明
損失関数を、パラメーターで微分している
If α is too small, gradient descent can be slow.
If α is too large, gradient descent can overshoot the minimum. It may fail to converge, or even diverge.
アルファが、あまりに小さいと、Gradient descentは、ゆっくりにしか進まない。
アルファが、あまりに大きいと、Gradient descentは、最小値を通り越してしまう。場合によっては、振動したり、収束しない場合もある。
このアルファを学習率(Learning Rate)という。
Gradient descentは、アルファが固定されていても、極小値に収束できる。
局所的な最小値に近づくにつれ、gradient descent
は、自動的に小さなステップを取るようになるので、繰り返しアルファを小さくしてゆく必要はない。
入力X=xi
予測値 axi+b 実際の値 yi
実際のyの値yi
損失関数J(a,b)=
Σ ((axi+b) – yi)^2
重み= a, バイアス
= b
損失関数は、前向きの推論で生み出されるデータを持ちいて、計算される。
重み= a, バイアス
= b
予測値 axi+b 実際の値 yi
損失関数J(a,b)=
Σ ((axi+b) – yi)^2
パラメーターの変更
a’ = a - α∂/∂a(J(a,b))
b’ = b - α∂/∂b(J(a,b))
損失関数の微分を使って、今度は、後ろ向きに、損失関数を計算した層のパラメーターを、変更する
入力X=xi
予測値 a’xi+b’ 実際の値 yi
実際のyの値yi
損失関数J(a’,b’)=
Σ ((a’xi+b’) – yi)^2
重み= a’, バイアス
= b’
損失関数は、前向きの推論で生み出されるデータを持ちいて、計算される。
重み= a’, バイアス
= b’
予測値 a’xi+b’ 実際の値 yi
損失関数J(a’,b’)=
Σ ((a’xi+b’) – yi)^2
パラメーターの変更
a’’ = a’ - α∂/∂a’(J(a’,b’))
b’’ = b’ - α∂/∂b’(J(a’,b’))
損失関数の微分を使って、今度は、後ろ向きに、損失関数を計算した層のパラメーターを、変更する
損失関数の計算
パラメーターの変更
損失関数の計算
パラメーターの変更
⚫️ ⚫️ ⚫️ ⚫️
こうした過程を繰り返して、パラメーターは、少しづつ、変更されていく。繰り返しの結果、パラメーターの値が、一定の値に収束すれば、学習は成功したとみなされ、繰り返しは、中止される。
どう、重みとバイアスを修正するのか?
もう少し、一般的に、Gradient Descent をまとめてみよう。損失関数をCとするとき、次の式に従って、重みWkとバイアスbl を変更すればいい。
ηは学習率
損失関数が、 ここで見た、quadratic costの形をしていない場合(例えば、 Cross Entropyの場合)でも、この考え方は、変わらない。
二項分類のLogistic回帰の場合
コスト関数 (Log Likelihood)
Logitic回帰の微分も、線形回帰の場合のQuadratic Costの微分と同じ形になる!計算は省略したが、次の文献を参照されたい。“CS229 Lecture notes”http://cs229.stanford.edu/notes/cs229-notes1.pdf
Back Propagation
前向きの推論に対して、パラメータの変更は、勾配(Gradient)を用いて、後ろ向きに行われる。
先に見たのは、一つのニューロンの場合だったが、多段の層からなるニューロンの場合でも、ある層から一つ前の層に対して、後ろ向きに、同じような処理が行われる。そのプロセスをまとめてみよう。
F1(X0 , W1)
Fi(Xi-1 , Wi)
Fn(Xn-1 , Wn)Wn
Wi
W1
X0 (入力)
n層のネットワークの前向きの推論。推論の結果を X としよう。
簡単にするために、バイアスの項 bi は省略している。
Xi-1
Xi
X
省略
前向きの推論
F1(X0 , W1)
Fi(Xi-1 , Wi)
Fn(Xn-1 , Wn)Wn
Wi
W1
X0 (入力) Y (期待される出力)
Cost
C(X,Y, ...)
前向きの推論の結果Xは、Cost関数(Loss関数・損失関数)で、期待される出力Yと比較される。
その結果をCとしよう。
X
Xi
Xi-1
省略
Cost関数
F1(X0 , W1)
Fi(Xi-1 , Wi)
Fn(Xn-1 , Wn)dC/dWn
Cost
C(X,Y, ...)
各層の出力Xi について、Cに対する勾配dC/dXiが計算される。
同様に、各層の重みWi について、Cに対する勾配dC/dWiが計算される。この値に基づいて重みは更新される。
dC/dWi
dC/dW1
dC/dX
dC/dXi
dC/dXi-1
X
Xi
Xi-1
省略
Backpropagation/Gradient
F1(X0 , W1)
Fi(Xi-1 , Wi)
Fn(Xn-1 , Wn)dC/dWn
Cost
C(X,Y, ...)
Xi = Fi(Xi-1,Wi) なので、
dC/dXi-1
= dC/dXi ・ dXi/dXi-1
= dC/dXi ・ dFi(Xi-1,Wi)/dXi-1
dC/dWi
= dC/dXi ・ dXi/dWi
= dC/dXi ・ dFi(Xi-1,Wi)/dWi
dC/dWi
dC/dW1
dC/dX
dC/dXi
dC/dXi-1
省略
Chain Rule
Stochastic Gradient Descent
ここでは、まず、訓練実行の三つのスタイル、Batch, SDG, mini-Batch の違いを見る。実際の応用では、mini-Batchを用いるのが一般的である。最後に、mini-Batchも、その確率論的性格から、SDGと呼ばれることを述べる。
Batch
・・・・・全てのデータ
先のパラメータ更新のアルゴリズムを、そのまま実装したもの。すべてのデータについて前向き推論した後で、一つの更新が行われる
データの数が大きくなると、計算量とメモリー消費が巨大になり、現実的でない。
Stochastic Gradient Descent(SDG)
・・・・・
こういうやり方もある。ひとつのデータについて前向き推論した後で、一つのパラメータ更新を行う。これを、SDGという。
一つのデータのみで全てのパラメータをいじるので、収束性にやや問題がある。
Mini-Batch
・・・・・
先に見たBatchとSDGを組み合わせたスタイル。一定数のかたまりのデータで推論を行った後、それに基づいてパラメータを変更する。今の訓練の基本的スタイルである。
ミニバッチ ミニバッチ ミニバッチ ミニバッチ
SDGの現在の用法
現在のMLの文脈では、SDGは、一個のデータにつき一回全データの更新を行う前述のSDGではなく、mini-batchの処理を行う訓練のスタイルをSDGと呼ぶことがある。下のCNTKでのSDGの定義を見て欲しい。この時は、SDGとはmini-batchのことである。
SDGのStochasticというのは、全体のデータから少数のデータをサンプリングして、確率的に推定をおこなうということ。モンテカルロ法と同様のアプローチである。
訓練の定義と実行
ニューラル・ネットワークの学習は、基本的には、次のようなステップからなる。
訓練の定義 推論を行うネットワーク・グラフの定義
学習、すなわち、ネットワークのパラメーターの変更を行うアルゴリズムの定義
訓練、すなわち、データでの繰り返し学習を行う、繰り返しの定義
...
訓練の実行
訓練の実行例 TensorFlow
$ python –m モデル
$ python -m
tensorflow.models.image.mnist.convolutional
tensorflor-master/tensorflow/ 以下
訓練の実行例 CNTK
$ cntk configFile=cntk ファイル
$ cntk configFile=../Config/02_Convolution.cntk
CNTK/Examples/ 以下
訓練の定義-- TensorFlowとCNTK
TensorFlowとCNTKの訓練の定義を比較してみよう。TensorFlowはPythonで手続きをベタに記述し、CNTKは宣言的なDomain Specific Languageを使う。違いが目立つが、グラフの定義・最適化のアルゴリズムの指定・訓練の繰り返しの指定等で、基本的な対応が見え始める。
# Create the modelx = tf.placeholder("float", [None, 784])W = tf.Variable(tf.zeros([784, 10]))b = tf.Variable(tf.zeros([10]))y = tf.nn.softmax(tf.matmul(x, W) + b)
# Define loss and optimizery_ = tf.placeholder("float", [None, 10])cross_entropy = -tf.reduce_sum(y_ * tf.log(y))train_step = tf.train.GradientDescentOptimizer(0.01)¥
.minimize(cross_entropy)
# Traintf.initialize_all_variables().run()for i in range(1000):
batch_xs, batch_ys = mnist.train.next_batch(100) train_step.run({x: batch_xs, y_: batch_ys})
グラフの定義
最適化のアルゴリズム
グラフで訓練繰り返し
https://goo.gl/MwscZO
訓練の定義例 TensorFlow
ndlMacros = "$ConfigDir$/Macros.ndl”
train = [
action = "train”
NDLNetworkBuilder = [
networkDescription = "$ConfigDir$/02_Convolution.ndl”
] < ndlは、Net Definition Language 次にリストを示す>
SGD = [
epochSize = 60000
minibatchSize = 32
learningRatesPerMB = 0.5
momentumPerMB = 0*10:0.7
maxEpochs = 15
]
reader = [
...
]
]
訓練の定義例 CNTK
グラフの定義
繰り返しの指定
....run = DNN // 実際に DNNという名前のグラフを構成する
ndlMnistMacros = [ .... ]
DNN = [....
<省略: グラフの定義の一部を次ページに示す >....ce = CrossEntropyWithSoftmax(labels, ol ) err = ErrorPrediction(labels, ol)
# Special NodesFeatureNodes = (features)LabelNodes = (labels)CriterionNodes = (ce)EvalNodes = (err) OutputNodes = (ol)
]
最適化のアルゴリズム
02_Convolution.ndl
最適化の定義 CNTK
DNN = [....# conv1kW1 = 5; kH1 = 5; cMap1 = 16hStride1 = 1; vStride1 = 1# weight[cMap1, kW1 * kH1 * inputChannels]# ConvReLULayer is defined in Macros.ndlconv1_act = ConvReLULayer(featScaled, cMap1, 25,
kW1, kH1, hStride1, vStride1, 10, 1)# pool1 ...# conv2 ...# pool2 ...# DNNImageSigmoidLayer and DNNLayer are defined in Macros.ndlh1 = DNNImageSigmoidLayer(4, 4, cMap2, h1Dim, pool2, 1)ol = DNNLayer(h1Dim, labelDim, h1, 1)
ce = CrossEntropyWithSoftmax(labels, ol)...
]
02_Convolution.ndl
グラフの定義 CNTK
Macros.ndlを参照している
ConvReLULayer(inp, outMap, inWCount, kW, kH, hStride, vStride, wScale, bValue) = [
convW = LearnableParameter(outMap, inWCount, init="uniform",initValueScale=wScale)
convB = ImageParameter(1, 1, outMap, init="fixedValue", value=bValue, imageLayout=$imageLayout$)
conv = Convolution(convW, inp, kW, kH, outMap, hStride, vStride, zeroPadding=false, imageLayout=$imageLayout$)
convPlusB = Plus(conv, convB);act = RectifiedLinear(convPlusB);
]DNNImageSigmoidLayer(inW, inH, inC, outDim, x, parmScale) = [ ... ]DNNLayer(inDim, outDim, x, parmScale) = [
W = LearnableParameter(outDim, inDim, init="uniform",initValueScale=parmScale)
b = LearnableParameter(outDim, 1,init="uniform", initValueScale=parmScale)
t = Times(W, x)z = Plus(t, b)
]
Macro.ndl
グラフの定義 CNTK
マクロを見るとネットワークの見慣れた形が見えてくる
TensorFlowでは、複数のニューロンからなる一つの層は、次のようなグラフで表現されることを、思い出して欲しい。
行列の積X
W
行列の和
b
φの適用
5つのノードがあるが、Wとbには、重みとバイアスの値が入り、残りの3つのノードは、演算を行うノードである。この層の働きは、φ(X・W+b) で表現される。
一つの層
Wとbの値は、この層の中での計算に利用されるだけでなく、その次の段階では、Back Propagationで修正を受ける。それは、変数Variableである。
行列の積X
W
行列の和
b
φの適用
PythonのTensorFlowプログラムでは、固有の役割をもったそれぞれのノードは、固有の名前が割り当てられている。先頭の tf はTensorFlow、nnはNeural Netの略だと思えばいい。
tf.Variable tf.Variable
tf.matmul + tf.nn.relu
φ(X・W+b)
グラフ定義は、次のようなわずか3行のプログラムになる。
weights = tf.Variable( ... ) # weight を入れる変数の定義bias = tf.Variable( ... ) # biasを入れる変数の定義# 層の働きを φ(X・W+b) で定義する。# ここではφにreluを使っている# imagesは、この層が受ける入力# hidden1は、この層の出力であるhidden1 = tf.nn.relu(tf.matmul(images, weights) + biases)
φ(X・W+b)
このプログラムに出てくる、 images, weights, bias, hidden1は、いずれもテンソルである。それがどのような形をしているかは、ここでは省略したVariableの定義を述べる際に詳しく述べる。Variableの定義によってテンソルの形は決まる。
二層からなるグラフのプログラムを見てみよう。
# 第一層weights1 = tf.Variable( ... ) bias1 = tf.Variable( ... )hidden1 = tf.nn.relu(tf.matmul(images, weights1) + biases1)
# 第二層weights2 = tf.Variable( ... ) bias2 = tf.Variable( ... )hidden2 = tf.nn.relu(tf.matmul( hidden1, weights2) + biases2)
第一層の出力のhidden1テンソルが、第二層の入力に、そのまま利用されているのがわかる。
積
W
images 和
b
φ 積
W
和
b
φ
weight1 bias1 weight2 bias2
relu relu
images hidden1 hidden2
# 第一層weights1 = tf.Variable( ... ) bias1 = tf.Variable( ... )hidden1 = tf.nn.relu(tf.matmul(images, weights1) + biases1)
# 第二層weights2 = tf.Variable( ... ) bias2 = tf.Variable( ... )hidden2 = tf.nn.relu(tf.matmul( hidden1, weights2) + biases2)
TensorFlowプログラムと対応するグラフ
三層からなるグラフのプログラムも簡単に書ける。
# 第一層weights1 = tf.Variable( ... ) bias1 = tf.Variable( ... )hidden1 = tf.nn.relu(tf.matmul(images, weights1) + biases1)
# 第二層weights2 = tf.Variable( ... ) bias2 = tf.Variable( ... )hidden2 = tf.nn.relu(tf.matmul( hidden1, weights2) + biases2)
# 第三層weights3 = tf.Variable( ... ) bias3 = tf.Variable( ... )logit = tf.matmul( hidden2, weights3) + biases3)
この例では、第三層は、Activatorを呼んでいない。
TensorFlowの変数定義
TensorFlowの変数(Variable)は、データの格納場所として、他のプログラミング言語の変数と同じ役割を果たす。ただ、TensorFlowの変数は、テンソルの格納場所である。変数の定義では、それがどのような「形」のテンソルの格納場所であるかを定義することが、重要な意味を持つ。
TensorFlowの変数
他のプログラミング言語での変数と同じように、TensorFlowの変数も、プログラムの中で、その値を読みだしたり、値を変更したりできる。
ただ、TensorFlowの変数は、一つの値を持つのではなく、多次元の行列であるテンソルを格納している。実装としては、それは、大きなメモリー・バッファーである。
TensorFlowの変数は、どのようなテンソルを格納するのかの情報をはじめとして、利用前に明示的に初期化されなければならない。
TensorFlowの変数は、その値を直接ディスクにSaveでき、また、プログラムの中で、それをディスクからRestoreできる。
TensorFlowの変数の生成
変数を生成するためには、そのコンストラクターに初期値としてテンソルを渡す必要がある。そのための幾つかのHelper関数が用意されている。
この例では、 tf.random_normal と tf.zeros という Helperを使っている。前者は乱数で、後者はゼロで変数を初期化する。
重要なことは、このHelperの第一引数が、この変数の初期化に使われたテンソルの形(shape)を示しているということである。
# Create two variables. weights = tf.Variable(
tf.random_normal([784,200], stddev=0.35), name="weights") biases = tf.Variable(tf.zeros([200]), name="biases")
変数の初期化
# 二つの変数を生成するweights = tf.Variable(tf.random_normal([784, 200],
stddev=0.35), name=“weights”)biases = tf.Variable(tf.zeros([200]), name="biases") ... # この変数を初期化する演算を追加しておくinit_op = tf.initialize_all_variables()
# モデルを起動した後で、この初期化を呼び出す。with tf.Session() as sess:
# Run the init operation. sess.run(init_op)
... # モデルを使う...
ここではまだ実行されないノードが追加されただけ
ノードで構成されたモデルはSessionで初めて動き出す呼出には、runを使う
[784,200]あるいは[200]の形をしたテンソルが用意されている。
変数の初期化(他の変数から)
# 乱数からなる変数を作る。784x200の行列。weights = tf.Variable(tf.random_normal([784, 200],
stddev=0.35), name="weights")
# 先のweightsの初期値と同じ値を持つ変数w2を作るw2 = tf.Variable(weights.initialized_value(), name="w2")
# weightsの初期値を二倍した値を持つ変数 twice を作るtwice = tf.Variable(weights.initialized_value() * 2.0,
name="w_twice")
変数のsave
# 変数を作るv1 = tf.Variable(..., name="v1") v2 = tf.Variable(..., name="v2") ...
# 変数を初期化する init_opノードを追加init_op = tf.initialize_all_variables() # すべての変数をsave,restoreするsaveノードを追加saver = tf.train.Saver()
# モデルを起動し、変数を初期化し、何かの仕事をした後で# 変数をディスクにsaveするwith tf.Session() as sess:
sess.run(init_op) # モデルで何かの仕事をする...# 変数をディスクにsaveするsave_path = saver.save(sess, "/tmp/model.ckpt") print("Model saved in file: %s" % save_path)
変数のrestore
# 変数を作るv1 = tf.Variable(..., name="v1") v2 = tf.Variable(..., name="v2") ... ...# すべての変数をsave,restoreするsaveノードを追加saver = tf.train.Saver()
# モデルを起動し、 変数をディスクからrestoreして# 何かの仕事をするwith tf.Session() as sess: # 変数をディスクにsaveする
saver.restore(sess, "/tmp/model.ckpt") print("Model restored" )
# モデルで何かの仕事をする...
訓練: ニューラル・ネットワークのパラメーター(重みとバイアス)を最適化をする
ニューラル・ネットワークの「訓練」は、プログラム上では簡単に記述されているが、計算時間の大部分は、この「訓練」に費やされる。
パラメーター(重みとバイアス)の最適化
パラメーター(重みとバイアス)の最適化は、次のような繰り返しのステップで行われる。(幾つかのバリエーションあり)
1. グラフが組みあがったら、そのグラフで入力データに対して出力を計算する。
2. その出力結果を、正しい答えと比較する。比較には、あらかじめ定義していた損失関数を用いる。
3. Gradient Descent(勾配降下法)を使って、損失関数の値が小さくなるようにパラメーター(重みとバイアス)を修正する。
4. 新しいパラメーターのもとで、入力データに対して出力を計算し、2.に戻る。損失関数が十分小さくなるまでこの処理を繰り返す。
GradientDescentOptimizer
TensorFlowでは、GradientDescentを使ったパラメーターの最適化のための最適化演算GradientDescentOptimizerがあらかじめ用意されている。
このOptimizerを使って、損失関数を最小化せよという指示を出せば、ニューラル・ネットワークのパラメーターは、自動的に更新される。
TensorFlowでは、こうして、パラメーター最適化のアルゴリズムが極めて簡単に書ける。
最適化のアルゴリズムの例1(数値予測の場合)
loss = tf.reduce_mean(tf.square(y - y_data)) optimizer = tf.train.GradientDescentOptimizer(0.5) train = optimizer.minimize(loss)
(y-y_data)2Σ1/2m損失関数 C =
学習率
最適化のアルゴリズムの例(クラス分けの場合)
y_ = tf.placeholder("float", [None, 10])cross_entropy = -tf.reduce_sum(y_ * tf.log(y))optimizer = tf.train.GradientDescentOptimizer(0.01)train = optimizer.minimize(cross_entropy)
(y_*log(y))Σ損失関数 C =
学習率
....W = tf.Variable(tf.random_uniform([1], -1.0, 1.0)) b = tf.Variable(tf.zeros([1]))y = W * x_data + b
# Minimize the mean squared errors. loss = tf.reduce_mean(tf.square(y - y_data)) optimizer = tf.train.GradientDescentOptimizer(0.5) train = optimizer.minimize(loss)
# Before starting, initialize the variables. We will 'run' this first. init = tf.initialize_all_variables()
# Launch the graph. sess = tf.Session() sess.run(init)
# Fit the line. for step in xrange(201):
sess.run(train) if step % 20 == 0:
print(step, sess.run(W), sess.run(b))
....W = tf.Variable(tf.random_uniform([1], -1.0, 1.0)) b = tf.Variable(tf.zeros([1]))y = W * x_data + b
# Minimize the mean squared errors. loss = tf.reduce_mean(tf.square(y - y_data)) optimizer = tf.train.GradientDescentOptimizer(0.5) train = optimizer.minimize(loss)
# Before starting, initialize the variables. We will 'run' this first. init = tf.initialize_all_variables()
# Launch the graph. sess = tf.Session() sess.run(init)
# Fit the line. for step in xrange(201):
sess.run(train) if step % 20 == 0:
print(step, sess.run(W), sess.run(b))
グラフの定義
最適化のアルゴリズム
グラフの起動
グラフで訓練繰り返し
....# Create the modelx = tf.placeholder("float", [None, 784])W = tf.Variable(tf.zeros([784, 10]))b = tf.Variable(tf.zeros([10]))y = tf.nn.softmax(tf.matmul(x, W) + b)
# Define loss and optimizery_ = tf.placeholder("float", [None, 10])cross_entropy = -tf.reduce_sum(y_ * tf.log(y))train_step = tf.train.GradientDescentOptimizer(0.01)
.minimize(cross_entropy)
# Traintf.initialize_all_variables().run()for i in range(1000):
batch_xs, batch_ys = mnist.train.next_batch(100) train_step.run({x: batch_xs, y_: batch_ys})
ソースの全体は、こちらにある。https://goo.gl/MwscZO
....# Create the modelx = tf.placeholder("float", [None, 784])W = tf.Variable(tf.zeros([784, 10]))b = tf.Variable(tf.zeros([10]))y = tf.nn.softmax(tf.matmul(x, W) + b)
# Define loss and optimizery_ = tf.placeholder("float", [None, 10])cross_entropy = -tf.reduce_sum(y_ * tf.log(y))train_step = tf.train.GradientDescentOptimizer(0.01)¥
.minimize(cross_entropy)
# Traintf.initialize_all_variables().run()for i in range(1000):
batch_xs, batch_ys = mnist.train.next_batch(100) train_step.run({x: batch_xs, y_: batch_ys})
グラフの定義
最適化のアルゴリズム
グラフで訓練繰り返し
ソースの全体は、こちらにある。https://goo.gl/MwscZO