アラカン"BOKU"のITな日常

文系システムエンジニアの”BOKU”が勉強したこと、経験したこと、日々思うことを書いてます。

超文系向け/レイヤー「Affine」(全結合層)の仕組をわかりやすく解説してみる/Neural Network Console

Neural Network Consoleは、レイヤーをGUIでペタペタと貼り付けるだけで、それなりの精度をだすニューラルネットワークが組めたりします。

最初のとっかかりとして、手をだしやすいです。

f:id:arakan_no_boku:20181030211624j:plain

でも。

レイヤーリファレンスの説明は、文系の人間には難しい。

そんな話を聞きました。

そもそもの部分・・がわかんないそうです。

言われてみればそうだよな・・と思ったので、いまさらながら・・でありますが、頭の整理がてらまとめてみようかなあ・・というのが今回のお題です。

一回にいっぱいは書けないので、一回につき一テーマにしときます。

 

まずは一番基本的なレイヤー「Affine」から

 

今回は、Affineです。

SONYさんのレイヤーリファレンスには、こう説明されてます。

全ての入力値から、OutShapeプロパティで指定する全ての出力ニューロンへの結合を持つ全結合層です。

o = Wi+b

(iは入力、oは出力、Wは重み、bはバイアス項を示す)

ディープラーニングを勉強しようというなら、これでわかるだろう・・なんですかね。

ここでの「そもそもの部分」とは。

なぜ、全結合層が必要なのか?

全ての出力ニューロンへの結合を持つということと、「o = Wi+b」という計算式が、どうつながるんだろう?

このあたりでしょう。

 

機械学習ディープラーニング含む)の目的は何か

 

ちょっと、回り道。

まずは、Neural Network Consoleの「そもそも」から。

Neural Network Consoleは、そもそも、何か?

それは「ディープラーニング・ツール」です。

で。

ディープラーニングは、機械学習の方法論のひとつです。

じゃあ、機械学習全般の目的は・・というと。

ざっくり言えば「個体を識別できる特徴をつかむ」ことなわけです。

どういうことか?

例えば、以下のような2つの図形があります。

f:id:arakan_no_boku:20181028144011j:plain

f:id:arakan_no_boku:20181028144027j:plain

黒字に白いバーが縦にはしってますが、位置が違います。

この2つを違うものとして識別するのなら、話は簡単です。

左からどの位離れているか?とか。

白いバーの幅とか。

いくつかの違いを見つけて、識別するプログラムを作るのは人間でも簡単にできます。

でも。

上記は同じものである・・が正解として与えられたらどうでしょうね。

共通のルールを見つけ出すのは、ちょっと面倒な作業になります。

2つなら何とかなるでしょうけど。

こういう、ちょっとずつ違う似たような画像が100個、1000個、1万個になって、それらを皆同じものとみなすような共通の特徴を・・となると、もうお手上げです。

人間がプログラミングなんてできません。

じゃあ。

コンピュータにまかせて、共通の特徴を見つけてもらえばいいじゃん!

機械学習って、乱暴に言えば、そういうもんだと、個人的に理解してます。

 

特徴をつかみやすい形に加工する

 

コンピュータに共通の特徴を見つけてもらおう。

これで目的はOK。

次は方法論の話になります。

コンピュータにできることは「計算」だけです。

なので、「計算」で共通の特徴を見つける方法を考えるわけです。

たとえば。

画像データの黒い部分を「カラー:0」、白い部分は「カラー:255」のような数値データとして扱うことができます。

f:id:arakan_no_boku:20181028152127j:plain

f:id:arakan_no_boku:20181028152148j:plain

でも。

ここから計算で「同じものと認識できる共通の特徴を抽出する」には、このままそのままの「生データ」だと、扱いずらいだろうな・・というのは、何となくわかります。

そこで。

なんとかして「同じものと認識できる共通な特徴を抽出」しやすいように加工する必要があります。

その加工の方法が、「Affine=全結合」だったり「Convolution=畳み込み演算」だったりするんだろうな。

そうと考えるとイメージしやすい気がします。

 

行列の内積計算っての肝なんだな

 

さて、Affineにおける、その加工の方法は、リファレンスの以下の計算式です。

o = Wi+b (iは入力、oは出力、Wは重み、bはバイアス項を示す)

このoもWもiも行列データです。

行列データってこんな感じのやつ。

なお、上記画像なら「28×28」ですが、そうすると滅茶苦茶見づらくなるので、見やすくするため「6×6」のサイズの例にしてます。 

f:id:arakan_no_boku:20181029194959j:plain

さて、行列のイメージがわかったら、計算です。

計算式の「Wi」は「W(ウエイト)とi(入力)の掛け算(内積)」を計算するということです。

行列の内積計算の計算の仕方の例です。

さらに見やすくするため、2×2の行列の例にしてます。

f:id:arakan_no_boku:20181029195357j:plain

左側の行(横)と右側の列(縦)を掛け合わせて足して、結果の数値をもとめます。

例えば、上の例だと。

左上の「19」は、「(1 × 5) + (2 × 7)」。

左下の「43」は、「(3 × 5) + (4 × 7)」

右上の「22」は、「(1 × 6) + (2 × 8)」

右下の「50」は、「(3 × 6) + (4 × 8)」

と計算してるわけです。

こういう行列同士の「Wi+b 」みたいな演算のことを「Affine変換」というので、レイヤーの名前が「Affine」なわけです。

ちなみに、全結合層の「+b」は同じ値を足して、Wiの結果が極端に小さな値でエラーになるとかを防ぐための保険みたいなものですかね。

 

やっと全結合層の話にはいります

 

上記計算例は「2 × 2」の行列で計算しました。

それを見て「全結合じゃねーじゃないか」と思った人、鋭いです。

当たりです。

上記例だと、左側の上2つ、下2つずつしか一度に計算してません。

だから。

実際の全結合層では、平にならして計算します。

平にする・・とは、例えば、(28,28,1)=幅28×高さ28×1チャンネルのデータなら、一旦 28×28×1=>784のサイズの1次元にするということです。

以下みたいなイメージですね。

f:id:arakan_no_boku:20181029005046j:plain

なんで、平にならすと「全結合」になるのか?

そのイメージをつかむため、超シンプルなモデルにして計算してみます。

(784とかで書くと、とても見づらいので)

入力サイズ「6」(笑)の小さな2種類のデータにしてみます。

f:id:arakan_no_boku:20181029225407j:plain

出力サイズは「3」にします。

かけあわせるW(ウエイト)は、単純化のため全部0.5にしてやってみます。

まず、入力①のほう。

f:id:arakan_no_boku:20181029231038j:plain

横×縦の計算ですから、1次元だと、一度の計算で左側の全部が対象になります。

上記だと、結果の128は、「0*0.5+255*0.5+0*0.5+0*0.5+0*0.5+0*0.5」で計算して求めているわけです。

入力すべてと、ウエイトを掛け合わせる。

これが「全ての入力値から、OutShapeプロパティで指定する全ての出力ニューロンへの結合を持つ」のイメージです。 

さて。

続けて、入力②の方も計算してみます。

f:id:arakan_no_boku:20181029231152j:plain

 

かなり、わざとらしいですが・・(笑)

①と②で、結果の数字が同じになってます。

元のままだと、255の出現位置がずれている違うデータなわけです。

ところが。

間にW(ウエイト)を挟んで内積計算をすることで同じになる。

これは、つまり、入力①②にあった位置関係のずれによる誤差が吸収されていると言えると思うんですよね。

まあ、実際はこんな風に全部が同じ数値のW(ウエイト)なんて、まず使いませんから、結果が同じになるようなことはないのですが、イメージはこんな感じです。

まとめます。

結局。

目的として「同じものと認識できる共通な特徴を抽出」したいわけです。

そのために、こういうふうに微妙なズレを吸収することができれば、「共通の特徴を抽出する」ために有利な加工方法になります。

これが「全結合層が必要な理由」・・なんだろうな。

個人的にはそう理解してます。

もっとも。

自分は文系なので、学校で機械学習について、ちゃんと学んだわけでもありません。

ディープラーニングの本を読んでも、こんなことまでは書いてありません。

あくまで、上記は自分が実際に計算して確かめた経験からの話ですから、バリバリの理系の方から「論文と違う」みたいな指摘があるかもしれないのはご容赦ください。

 

 

ちょっと補足です

 

今回の記事のテーマについては、前章で終わりです。

でも。

上記の例を見て、なんで真ん中のW(ウエイト)の部分が3列もあるんだ?とわからない人もいると思うので、補足しときます。

実は。

行列の内積計算は、左側が「2行3列」なら「3行2列」みたいに内側の数が一致してないといけません。

出力サイズは、「2行3列」×「3行2列」なら「2行2列」になるみたいに、外側の数で決まります。

こんな感じ。

f:id:arakan_no_boku:20181030000816j:plain

なので。

入力が「6」。

出力を「3」。

そう決めた時点で、掛け合わせる相手(真ん中)は「6行3列」に決まるわけです。

f:id:arakan_no_boku:20181030001119j:plain

さて。  

今回は、こんなところで。