E試験のシラバスに沿って概要をメモしたものです。
シラバスは2024#2に準拠しています
本記事は3.深層学習のうち
- 畳み込みニューラルネットワーク
- リカレントニューラルネットワーク
- Transformer
までについてとなります。
試験範囲外部分は割愛しています。
他の記事へのリンクは以下にリストしています。
CNN:畳み込みニューラルネットワーク
基本的な畳み込み演算
元の画像データに対して、フィルタ(下記画像内ではKernel)と呼ばれるものを適用していき出力を得る。
従来の重みパラメータの更新はこのKernel内の各数値の更新が行われる。
(出所:https://www.geeksforgeeks.org/apply-a-2d-convolution-operation-in-pytorch/)
このKernelはまさに画像フィルタのことであって、
例えば縦方向の輪郭検出をしたい場合は
\begin{pmatrix}
0 & 1 & 0 \\
0 & -1 & 0 \\
0 & 0 & 0 \\
\end{pmatrix}
というKernelを適用すると縦方向の輪郭検出ができる。
このように様々なフィルタを元画像にかけることによって、色々な視点から画像を見ることになり特徴を捉えるようなフィルタが重み更新の中で作成されていく。
パディング、ストライド
-
パディング
フィルタを端っこからかけると、フィルタのサイズが大きければ大きいほど元画像のサイズが小さくなってしまう。
元画像のサイズを維持するため、画像の外側に余白(主に0を入れておく)を設けてもと画像のサイズを維持するなどするための手段 -
ストライド
フィルタの一回の移動距離。ストライドが大きいと出力画像が小さくなる。(下記画像の下が上がstride2で動かした場合)
(出所:https://www.researchgate.net/figure/Schematic-of-2D-CNN-for-stride-1-and-stride-2-with-zero-padding-adding-additional-layers_fig13_350386951)
パディングとストライドを加味した入力の画像サイズに対する出力画像サイズは以下の関係となる。
$I_w$:入力画像幅 $O_w$:出力画像幅 $F_w$:フィルタ幅 P:パディングサイズ S:ストライド量
$Ow=\cfrac{I_w+2P-F_w}{S}+1$
高さについても同様の式
チャネル
画像は縦横だけではなく色情報がある。
このように多次元部分をチャンネルという
(出所:https://qiita.com/kuroitu/items/35d7b5a4bde470f69570)
im2col
im2colはpython numpyにおける四次元配列である画像を二次元配列へと変換する関数
畳み込みは多次元に対して繰り返し処理でフィルタを動かしていく形となるが、多次元を二次元行列演算の形にし高速に処理をする。計算後に高次元配列に戻す。
(出所:https://qiita.com/MA-fn/items/45a45a7417dfb37a5248)
特別な畳み込み
Depthwise Separable Convolution
- depth-wise畳み込み
チャネル毎に畳み込みを行う - point-wise畳み込み(1x1畳み込み)
ピクセル毎にチャネル方向の畳み込みを行う手法
depth-wise→point-wiseと畳み込みを行うのがDepthwise Separable Convolution
(出所:https://viso.ai/deep-learning/convolution-operations/)
パラメーターの次元数を減らせる、演算量を減らせる、層の多重化ができるといった特徴がある。
通常フィルタサイズ3x3で「レイヤ数4,W4,H4」を「レイヤ3,W3,H3」に畳み込みを行う場合3x3x4x4x4x3=5184の計算が必要になるが。
Depthwise Separable ConvolutionだとDepthwiseで3x3x4x4x4=576とPointWiseで4x3x3x3=36 合計576+36=612と計算量が少なくなる。
https://developers.agirobots.com/jp/depthwise-pointwise-convolution/
グループ化畳み込み、
グループ化畳み込み層(Grouped Convolution Layer)とは,全チャンネル一気に畳み込まず,分割した各グループ内のチャンネル内でのみ,それぞれ畳み込みを並列に行う層である.畳み込みの処理をグループに分解することで,計算速度向上およびワイド化による表現力向上が狙える.
アップサンプリングと逆畳み込み
プーリングやフィルタの結果小さくなった画像のアップサンプリングを行う。
セグメンテーションや精製分野で使用される。
この際に使用されるのが逆畳み込み(Deconvolution) 。
青→緑
https://datascience.stackexchange.com/questions/6107/what-are-deconvolutional-layers
プーリング Max pooling、Lp pooling、Global Average Pooling
縦・横方向の空間を小さくする演算
画質を粗くする事でエッジがボケて境界があいまいになり、写真が多少変わっても、同じものだと認識できるようになります。
過学習に陥りやすい
- Lp Pooling
$$ u_{ijk} = \left( \frac{1}{H^{2}} \sum_{(p,q) \in P_ij} z_{pqk}^P \right)^{\frac{1}{P}} $$
P=1とすると平均プーリングとなる。
P=∞とするとMaxプーリングとなる。
RNN
RNN:リカレント(回帰型)ニューラルネットワーク
時系列データを考慮できるニューラルネットワーク。
時系列データ、音声データ、機械翻訳、自然言語処理などで使用される。
(出所:https://www.sbbit.jp/article/cont1/60676)
順伝播の計算
https://medium.com/@balajicena1995/rnn-26914e8d19b7
$x$:入力
y:出力
$W_{hy}$:出力層の重み
$W_{xh}$:入力層の重み
h:隠れ層
f:隠れ層による重みと活性化関数(主にtanhやReLUが使用される)
tは時間軸上の前後関係
ここで現在の状態を計算する式は以下で
$h_{t} = f(h_{t-1} ,x_{t})$
前の層の状態$h_{t-1}$と現在の入力$x_{t}$が使用される
活性化関数にtanhを使用したとすると
$h_{t}=\tanh(W_{hh}*h_{t-1},W_{xh}*x_{t})$ ※W_{hh}隠れ層の重み
出力は
$o_{t}=W_{hy}*h_{t}$
RNNは時間軸方向に伝播する多層のニューラルネットワークととらえることができる。(一つ前の時間軸の出力を、次の時間軸の入力の一つとして使用。)
逆伝搬の計算(Back Propagation Through Time; BPTT)
時間軸方向に展開する事で、長いニューラルネットワークとみなし、誤差は、ある時点時刻tから時刻0に向かって誤差が伝播していく。
時系列が長期になると、勾配消失問題が発生、過去の情報が消失してしまう「長期依存性の課題」
また、並列処理ができないため学習に時間がかかる
Bidirectional RNN:双方向RNN
Bidirectional RNN は、中間層の出力を、未来への順伝播と過去への逆伝播の両方向に伝播するネットワークである。BRNN では、学習時に、過去と未来の情報の入力を必要とすることから、運用時も過去から未来までのすべての情報を入力してはじめて予測できるようになる。
両方の情報を使用することで精度の向上が期待出来る。
-
順伝播
順伝播では、状態 t における中間層は、入力値と状態 t-1 から入力を受け取り、それぞれに重みをかけて、活性化関数に代入して得られる値を、この中間層の出力値としている。
-
逆伝播
逆伝播では、状態 t における中間層は、入力値と状態 t+1 から入力を受け取り、それぞれに重みをかけて、活性化関数に代入して得られる値を、この中間層の出力値としている。
-
出力層
状態 t における出力層の出力値は、順伝播および逆伝播の中間層の値から計算する。
(出所:https://axa.biopapyrus.jp/deep-learning/rnn/brnn.html)
ゲート機構
前述のとおりRNNには時系列が長くなると勾配消失問題が発生する「長期依存性の課題」がある。
LSTM(長期短期記憶:Long short-term memory)という機構にて実現されているモデルにて
忘却ゲート、入力ゲート、出力ゲートという「ゲート機構」によりこの問題を解決したもの。
ゲート機構とは各情報を「どのくらい通すか」。0~1の間の値を乗ずることによって該当の情報をゲートにて通し具合を決める。0だったら通さない(情報を使わない)、1だったら情報をそのまま使う。
0~1にする関係から各ゲートにはシグモイド関数(σ)が使用される。
ゲートごとに異なる重みUと重みW、バイアスbを学習する
cはCell Stateと呼ばれる長期記憶と担当する部分で過去の情報を維持する。
短期記憶はhが担当する。
- 忘却ゲート
前の状態$C_{t-1}$をどの程度残すのかを制御するゲート
$f_t=\sigma(W_f[h_{t-1},x_t])$
- 入力ゲート
現時刻の入力をどの程度$C_t$に取り込むかを制御するゲート
$i_t=\sigma(W_i\cdot[h_{t-1},x_t])$
$\tilde{c_t}=\tanh(W_c\cdot[h_{t-1},x_t])$
赤矢印部分は全結合して$\tilde{c}\bigotimes i_t$
$c_{t}$は図の通り、前のc_{t-1}と忘却、入力を足し合わせた
$c_{t}=(c_{t-1}\bigotimes f_t) \bigoplus (\tilde{c_t}\bigotimes i_t)$
- 出力ゲート
現在の状態をどの程度出力するかを制御するゲート
$o_t=\sigma(W_o\cdot[h_{t-1},x_t])$
(出所:https://medium.datadriveninvestor.com/how-do-lstm-networks-solve-the-problem-of-vanishing-gradients-a6784971a577 より一部編集)
結果的に
$c_{t}=(c_{t-1}\bigotimes f_t) \bigoplus (\tilde{c_t}\bigotimes i_t)$
$h_t=o_t \bigotimes \tanh(c_t)$
が次の層に渡される。
$c_t$は前のc新しい入力を足し合わせていく形になる、ただし忘却ゲートの値で前の情報はどれくらいかを忘れていく
GRU:Gated Reccurent Unit
LSTMはパラメータ数が多く計算量が多いため、LSTMの考え方を継承しつつパラメータ数の削減と計算時間の短縮を行ったユニット
※精度についての進化ではなく計算量の進化のため、精度に関してはLSTMの方がよいといわれている。
リセットゲート
過去の隠れ層の出力$h_{t-1}$をどれだけ無視するか。LSTMの忘却ゲートの役割に近い。
1に近ければ過去の情報を生かす。0に近ければ過去の情報を入力のみから受ける。
\mathbf{r}_{t} = \sigma \left( \mathbf{W}_{r} \mathbf{x}_{t} + \mathbf{U}_{r} \mathbf{h}_{t-1} + \mathbf{b}_{r} \right)
更新ゲート
過去の出力と新しい隠れ状態をどの程度混ぜあわせるかを決めるゲート
1に近いと新しい情報を多く使う。
0に近いと新しい情報を使わない。
\mathbf{z}_{t} = \sigma \left( \mathbf{W}_{z} \mathbf{x}_{t} + \mathbf{U}_{z} \mathbf{h}_{t-1} + \mathbf{b}_{z} \right)
出力は
新しい隠れ層の出力は$x_t$と、$h_{t-1}$に対してリセットゲートの出力で適度に忘れたものにtanhをとり
\tilde{\mathbf{h}}_{t} = \tanh \left( \mathbf{W}_{h} \mathbf{x}_{t} + \mathbf{r}_{t} \odot \left( \mathbf{U}_{h} \mathbf{h}_{t-1} \right) + \mathbf{b}_{h} \right)
$\tilde{h_t}$と$h_{t-1}$どちらをより多く使うかを更新ゲートの比率を使って
\mathbf{h}_{t} = \left( 1 - \mathbf{z}_{t}\right) \odot \mathbf{h}_{t-1} + \mathbf{z}_{t} \odot \tilde{\mathbf{h}}_{t}
が隠れ層の出力$h_t$となる
(出所:https://axa.biopapyrus.jp/deep-learning/rnn/gru.html)
系列変換
seqence-to-sequence(seq2seq)
入力も出力もシーケンスになっているモデル。時系列データを別の時系列データに変換する。
機械翻訳などで使用される。
二つのRNN(EncoderとDecoder)を使用する。
(出所:https://minatosato.com/2018/02/encoder-decoder%E3%83%A2%E3%83%87%E3%83%AB%E3%81%A8teacher-forcingscheduled-samplingprofessor-forcing/)
入力をEncoderにて最後の隠れ層の状態を固定長ベクトルに変換し、Decoderに渡す。
DecoderはEncoderから来た値と、て出力の時系列データに変換する。
(最初はnullとEncoderから来た値、次は「これ」という出力とEncoderから来た値がDecoderに渡される。)
アテンション(注意)機構
seq2seqの仕組みではEncoderから最後の隠れ層の情報を受け取って固定長ベクトルに変換するが
- 固定長ベクトルのため情報を適切に扱えない可能性(長い分には長いベクトルを、小さい分には小さいベクトルを)
- Encoderの途中の情報は利用できない
アテンション機構はエンコーダーの全てとデコーダに隠し状態を持ち、
出力の際に「注意」すべきエンコーダーの入力がどれであるかを見る。
ステップ 1: すべてのエンコーダの隠れ状態のスコアを取得
スコア関数はいくつか種類があるが
図の例ではデコーダー状態:Qとエンコーダの状態:Kの内積
$QK^T$
- スコアをsoftmaxにかける
$softmax(QK^T)$
- エンコーダーの出力:Vとスコアをかけたものをとる(アノテーションベクトル)
$softmax(QK^T)V$
- アノテーションベクトルの総和を取る(文脈ベクトル:context vector)
$c_t=\sum{softmax(QK^T)V}$
- デコーダーに文脈ベクトルを入力
(出所:https://towardsdatascience.com/attn-illustrated-attention-5ec4ad276ee3)
デコーダーの時刻tそれぞれに文脈ベクトルを作成する。
どの単語に注目するべきかを加味した文脈ベクトルを単語ごとに作ることによって長文でも精度が落ちないように実現
Transformer
2017年6月にGoogleから発表された論文「Attention Is All You Need」にて提唱された、Attention機構にて元の文全体を意識して翻訳を行うモデル。
自然言語処理の精度を大幅にあげた
- Encoderの構造
- Embedding層によって入力文章を512次元のベクトルに圧縮
- Positional Encoder層によって位置情報を付加
- Multi-Head Attention層でSelf Attentionを計算し、データ内照応関係を付加
- 各種Normalizationを行う
- Point-wise順伝播ネットワーク(PFFN:Position-Wise Feed-Forward Networks)で活性化関数を適用
- 各種Normalizationを行う
3〜6を6層繰り返します
- Decoderの構造
- Embeddingレイヤによって入力文章を512次元のベクトルに圧縮
- Positional Encoder層によって位置情報を付加
- Masked Multi-Head AttentionでSelf Attentionを計算し、データ内照応関係を付加
- 各種Normalizationを行う
- ここまでの出力をQueryに、Encoderの出力をKeyとValueにしてMulti-Head AttentionでAttentionを計算し、異なる時系列データの照応関係情報を獲得
- 各種Normalizationを行う
- PFFNで変換
- 各種Normalizationを行う
3〜8を6層繰り返します
- Transformerのポイントとなる層
①PositionalEncoding層(単語の位置情報を埋め込む層)
②Attention層
・Self-Attention層(入力文章内の照応関係(類似度や重要度)を獲得する層)
・MultiHead-Attention層(アンサンブル学習の様にすることでSingle-Self-Attention層だけのときよりも取りこぼしを少なくします)
・Masked Multi-Head Attention層(PositionalEncoding層によって受け取ってしまう情報を隠す=カンニングの様な状態になることを避けるため)
・Source‐Target‐Attention層(異なる文章同士の照応関係(類似度や重要度)を獲得する層)
(出所:https://deepsquare.jp/2020/07/transformer/)
Self-Attention
Self-Attentionは、入力シーケンス内および出力シーケンス内の単語間の相互作用をキャプチャするために、繰り返し単位を置き換えるために使用される。
(出所:https://leadinge.co.jp/rd/2021/01/13/218/)
Self-Attentionでは、まずQueryとKeyとValueを計算
QueryとKeyとValueは全て同じ場所からくる。これがSelfといわれている理由。
softmaxをかける。この行列はattention matrixと呼ばれる。
attention層の結果の出力隠し状態は、Attention MatrixとVの行列乗算。
attention層から得られる各隠し状態は、attentionが重みとなる値の加重平均として解釈できる。
(出所:https://newsletter.theaiedge.io/p/understanding-the-self-attention)
Multi-Head Attention
(出所:https://leadinge.co.jp/rd/2021/01/13/218/)
Multi-Head Attentionは複数のAttention Matrixを一つのSelf-Attention Layerに内蔵する方法。
Self-Attention Layer内のQuery, KeyとValueを複数にして、独立にAttention Matrixを計
算することで、層内で複数のAttention Matrixを得る事ができる。
‐ Scaled Dot-Product Attention
Valueを入力とし、QとKから生成されたAttention Matrixを重み行列とするニューラルネットワークと見なすことができます。
Attention Matrixは入力に応じて変化するので、これを重み行列とするニューラルネットワークは、入力に応じてネットワークの特性を変えることができるのです。(通常のNNは入力によらず重みは一定)
(出所:https://developers.agirobots.com/jp/essence-of-scaled-dot-product-attention/)
Masked Attention
https://leadinge.co.jp/rd/2021/01/13/218/
Masked Attentionは未来の情報にアクセスしてしまうと「答え」にアクセスする形になるので未来の情報にマスクをかける。
Source Target Attention,
Self Attentionは、上の図だと、ある層において、各ポジションごとに他の入力とのAttention Weightを計算し、上の層の内部状態を計算するようになっています。
Source-Target Attentionは、基本的にエンコーダの最後の層(一番上)の内部状態を使います。こちらはRNNと同じようにAttentionを計算し、デコーダの次の層(上の層)を計算していきます。デコーダの最終層(一番上)から、出力単語を推定します。
(出所:https://www.matsuoka-peoffice.com/technology4/)
Positional Encoding
RNNはデータ同士の長期依存関係をもっていたが、Attentionのみでは実現できない。
PositionalEncoding層は各要素に「n番目」というような文中の位置が一意に定まる情報を付与する。各要素データを並列処理したとしても、もともと入力データが持っていた文章上の前後要素との関係情報を維持できるようにした。つまり、Attentionによって意味的つながりが付与され、PositonalEncodingによって文章上の位置的つながりが付与されることになる。
(出所:https://machinelearningmastery.com/a-gentle-introduction-to-positional-encoding-in-transformer-models-part-1/)