応用数学・機械学習
動画講義の要約
応用数学、機械学習について。 導き方込みで忘れていたものについて抜粋して復習。
応用数学
逆行列の求め方
行の基本変形
- ある行を定数倍する
- 二つの行を交換する
- ある行の定数倍を別の行に加える
掃き出し法
行列Aの右隣に単位行列Iをつけ、行基本変形を行い、[I B]に変形する。 つまり [A I] => [I B] この行列Bが行列Aの逆行列𝐴−1
行列式
行列式とは
正方行列の指標の一つでスカラーで表される大きさみたいなもの。 よく使われるのが、逆行列が存在するかどうかを確認する時で、この行列式の値が0の時、 存在にしない。ということになる。
2次元
3次元
固有値,固有ベクトル
固有値分解
$$ A = V \Lambda V ^ {-1} $$
と分解されること。
ただし Vは固有値ベクトル $$ (\vec{v} _ {1},\vec{v} _ {2},\vec{v} _ {3} , ...) $$
Λは固有値の対角行列 (3*3の正方行列の場合)
固有値分解のメリット
特異値分解
この時このように分解できる事を特異値分解という.
特異値分解 求め方
$$ M = USV ^ {T} $$
両辺に転置をかける $$ MM ^ {T} = USV ^ {T} * (USV ^ {T}) ^ {T} $$
転置の転置は順序が変わる。
$$ (USV ^ {T}) ^ {T} = VS ^ {T} U ^ {T} $$
なので $$ MM ^ {T} = USV ^ {T} * VS ^ {T} U ^ {T} $$
$$ V ^ {T} * V = I $$ 単位行列になるので消える。
$$ MM ^ {T} = USS ^ {T} U ^ {T} $$
Sは対角行列らしいので、
$$ MM ^ {T} = US ^ 2 T $$
これは $$ MM ^ {T} $$ を固有値分解した形
$$ P A P ^ {-1} $$ に相当する。
すわなち Uを決定するには、
$$ MM ^ {T} $$ を固有値分解すればよい。
特異値分解のメリット
正方行列でなくても分解が出来る。
ベイズ則
条件
$$ P(A)P(B|A)= P(B)P(A|B) $$
Aが起きる確率 * Aが起きた条件でBが起きる確率 = Bが起きる確率 * Bが起きた条件でAが起きる確率
確率変数
ある変数の値をとる確率が存在する変数のことです。例えば、さいころを投げて出る目は{1, 2, 3, 4, 5, 6}のいずれかであり、それぞれの目が出る確率は1/6であることから、サイコロの目が確率変数と言える。
$$ P(X) = 1/6 (X =1,2,3,4,5,6) $$
確率分布
確率変数がとる値と、その値がとる確率の対応の様子の対応のこと。 サイコロの場合の確率分布。シンプルだけどイメージがつきやすい。
確率変数 | 確率 |
---|---|
1 | 1/6 |
2 | 1/6 |
3 | 1/6 |
4 | 1/6 |
5 | 1/6 |
6 | 1/6 |
コインの場合の確率分布。これもシンプルだけどイメージがつきやすい。
確率変数 | 確率 |
---|---|
表(=1) | 1/2 |
裏(=0) | 1/2 |
期待値
一回の試行で、確率変数が出す値の平均値。 確率変数Xのとる値をx1,x2,x3,....xn,それに対応する確をp1,p2,p3,....pnとする場合 期待値Eは $$ E = \sum_{i=0}^n x _ {i} p _ {i} $$
サイコロの場合は $$ E = 1 * 1/6 + 2 * 1/6 + ・・・・ + 6 * 1/6 = 3.5 $$
一回サイコロ振ると、3.5が出るという感じ。
分散
データの散らばり具合を示す指標。
共分散
分散を二つのデータに拡張する。
以下のURLも普通に分かりやすかった。
(参考) http://arduinopid.web.fc2.com/P6.html
標準偏差
分散にルートする。
自己情報量
シャノンエントロピー
自己情報量の期待値
カルバックライブラーダイバージェンス
同じ事象・確率変数における異なる確率分布P,Qの違いを表す。 P、Q を離散確率分布とするとき、P の Q に対するカルバック・ライブラー情報量は以下のように定義される。
$$ D _ {KL} (P||Q)= \sum _{i} P(i) \log \frac {P(i)}{Q(i)} $$
機械学習
自分のためにやってるので、理解してそうなところは省略気味に、理解が浅いところを中心にまとめる。
線形回帰モデル
データを関数にして予測する、というのが回帰分析で、そのグラフが線形な場合は線形回帰という。
説明変数が1次元(一つだけのx)の時で考えてみる。
予測グラフ $$ \hat{y} = \omega _ {1} x + \omega _ {0} $$
現状のデータを下のように考える。予測された方程式からの誤差が今の実測値である。 $$ y = \omega _ {1} x + \omega _ {0} + \epsilon $$
平均二乗誤差
データの個数をn_train個とすると $$ E = \frac {1} {n _ {train}} \sum _ {i=1}^ {n_{train}} ( ( \omega _ {1} x + \omega _ {0} ) - y) ^ 2 $$
要するに予測値と実データの差の2乗和平均
最小二乗法
上記式が最小となるような(誤差が一番少ない)ω0,ω1を求める。解析的にとけるらしい。 そうするとω0,ω1がもとまり、予測グラフが出来上がる。
非線形回帰モデル
そのグラフが非線形な場合は線形回帰。
線形回帰時のxをφ(x)とする。もうyはxの1次関数ではないので。 xについてには非線形だが、重みについては線形のまま。 φは多項式とする。(たとえば j = 9なら9次関数)
$$ \phi _{j} = x ^ j $$
i番目のデータ .基底関数がk個 $$ y _ {i} = \omega _ 0 + \sum _ {j=1}^ {k} \omega _ {j} \phi _{j} (x _ {i}) + + \epsilon _ {i} $$
説明変数がm個
$$ x _ {i} = (x _ {i1}, x _ {i2}, ....,x _ {im}) $$
未知パラメータ(ω0やω1など)は線形回帰モデルと同様に最小2乗法や最尤法により推定する。
$$ \hat {y} = \phi \hat \omega $$
$$ \hat \omega = (\phi ^ {t} \phi ^ {-1}) \phi ^ {t} y $$
過学習
基底関数を増やすと(6次関数,7次関数, .....)、確かにテストデータに対しては精度は上がるが、検証データに対して同じように精度が上がるとは限らない。→ 過学習
正則化
パラメータの値が大きいと過学習が起きやすい。 そのためにパラメータの大きくなりすぎないように、パラメータの関数を追加する。
この関数の事を正則化項、あるいは罰則化項という。2次関数の時L2ノルム、1次の時はL1ノルム
ロジスティック回帰
分類問題.ベルヌーイ分布を利用する。1回の試行での確率 $$ P(y) = p ^ y (1 - p) ^ {1 -y} $$
すなわち。確率変数が y = 0 or 1の離散値と仮定 y = 1の時、 $$ P(1) = p ^ 1 (1 - p) ^ {1 -1} = p (1 - p) ^ {0} = p $$
確率変数 y = 0の時、 $$ P(0) = 1 - p $$
n回の試行での同時確率
1回目 $$ P(y ^ {1}) = p ^ {y ^ {1}} (1 - p) ^ {1 -y ^ {1}} $$
2回目 $$ P(y ^ {2}) = p ^ {y ^ {2}} (1 - p) ^ {1 -y ^ {2}} $$
つまりn回の試行で、y1,y2,....ynが同時におこる確率は
$$ P(y1,y2,....yn;p) = \prod_{i=1}^n p ^ {y ^ {i}} (1 - p) ^ {1 -y ^ {i}} $$
y1,y2,...ynは既知。たとえばコイン投げだと、1回目 表、 2回目 裏... で、これからその背後にある確率pを求めたい。
尤度関数とは
上記式において、データを固定しパラメータを変化させる事。 上記だとy1,y2,...ynは既知のデータ確率pが未知のパラメータにあたる。 となると、 上記式はy1,y2,...ynは固定で変数ではなくなるので、確率pをパラメータとする関数とみなせる。 これを尤度関数という。
シグモイド関数
入力を何かしらの重みで変換し、シグモイド関数(αとする)を使用して確率へと変換させると考えると
$$ p _ 1 = \alpha (w ^ T x _ 1) $$
$$ p _ n = \alpha (w ^ T x _ n) $$
とおいていけるので、結局尤度関数は ωの関数となり、これがパラメータ。
最尤推定
尤度を最大にするパラメータ(上記の場合だとω)を求める推定方法。 ωの成分はω0,ω1など。ω => ω0,ω1, ...とし、対数をとる。
$$ - \log L (\omega _ 0, \omega _ 1, ... ,\omega _ m) = \sum_{i=1}^n ( y _ {i} \log p _ {i} + (1 - y _ {i}) \log (1 - p _ {i})) $$
↑ EとするとEが最小になる ω0,ω1...を探す
勾配降下法
解析的には解けない。 Eが最小になる方向にどんどん進んでいく。 Eを パラメータで微分し、その方向で進んでいく。
確率的勾配法
勾配降下法を用いる時、全データだと計算量が多いので、いくつかにピックアップして計算をすすめていく。
主成分分析
たくさんの説明変数があるグラフで、より重要な説明変数だけに絞ったり、もしくは別の説明変数に変換したりして 要約しなおす分析のやり方。
次元圧縮するという事。これは、分散が最大となる方向に線形変換する。
k近傍法
教師あり学習の分類問題。 学習データを座標上ににプロット、そこに未知のデータが入ってくる。 そこから距離が近い順に任意のK個を取得し、多数決でデータが属するクラスを推定する。
kmeans
教師なし学習の分類問題 データの集合が座標上に存在するとする。
- まずはクラスタ数を決める
- 代表点をランダムに決める。
- データと各代表点とのユークリッド距離を測定
- 一番近い代表点にデータをクラスタリング
- クラスタリングされたデータの重心を測定
- 重心を新しい代表点にする。
- その代表点からまたユークリッド距離を測定し、一番近い代表点に再クラスタリング
- 繰り返し
- 重心が動かなくなったら、クラスタリング終了
(参考) https://toukei-lab.com/k-means
SVM
分類問題の一つ。クラスを明確に分ける境界線を引くための手法 主に2値分類について使われる。データの集合が座標上に存在するとする。
この図でいうと、決定境界の左右の線がサポートベクトルで真ん中の決定境界がちょうど中間のベクトル。このベクトルがマージンが最大化されたベクトルになるので、この線で境界線を引いて分類する手法をSVMという。
深層学習 Day4
動画講義の要約
強化学習について
Section1: 強化学習
報酬を最大化できるように、環境のなかで行動を選択できるエージェントを作ることを目標とする、機械学習の一分野。
(具体例)
たとえば、職場で頑張って問題を解決する。その結果何か目標を達成したらボーナスがもらえる。
つまり、何か報酬をもらえるにはどうすれば良いかを学習し、行動につなげていく。
方策(ポリシー)
どのように行動するか。ボーナス(報酬)を最大化させるための行動指針。
状態(ポリシー)
文字通り状態。オセロなら位置であり、上記例の職場なら職場環境という事になりそう。状態も変化していく。
行動(action)
ポリシーに従って行動する。
価値(value)
ポリシーに従って行動を選択するが、価値という状態に依存したものが存在する。 この状態に依存した価値は、この状態が今後ゴールに向かう際、どれだけの報酬を得る事が出来るか、で決められる。
探索と利用のトレードオフ
最初は、どのようにすれば価値がある行動を出来るか、報酬が貰えるかわからないので、探索のための行動。または探索の結果を利用する行動。 というのがあるらしい。
Eplison-Greedy法と呼ばれる。
(参考図書) pythonで学ぶ強化学習
これらの事柄を、数学的モデルに落とし込んでいく。つまり関数にしていく。 関数にするとニューラルネットワークに落とし込み、学習が出来る。
方策関数
と表すことが多い。方策関数は状態(s),行動(a)を引数とした関数である。
行動価値関数
行動価値関数は状態(s),行動(a)を引数とした関数である. もう一つ状態価値関数というのがあるが、これはaに依存しない。sのみに依存する。あまり使用されない。
学習する事で、優れた方策関数(ポリシー)を見つけていく。(policyベース)
ちなみにvalueベースの強化学習もあり、これは常に価値が最もたかい状態に遷移していくこと。
(参考図書) pythonで学ぶ強化学習
強化学習は方策関数と価値関数の精度が高ければより良いモデルとなり、その学習方法に勾配法がある。
方策勾配法
θは方策関数の重み。Jは $$ \theta ^ {(t + 1)} = \theta ^ {(t)} + e \nabla J (\theta) $$
これはニューラルネットワークの重みの学習 $$ w ^ {(t + 1)} = w ^ {(t)} - e \nabla E (w) $$ とほぼ同じ。- e => +e になってるくらい。 今回は最小に向かうわけではなく、最大の報酬を得る方向なので+になる。 Jとは、今の方策を続けて行った時に得られる期待報酬の関数。
Section2: Alpha Go
AlphaGoとは、Google DeepMindによって開発されたコンピュータ囲碁プログラムのこと。 AlphaGo Fan,AlphaGo Lee, AlphaGo Zero など、色んなバージョンがある。
学習のさせ方
まずは譜面データから教師あり学習で学習させる。それから強化学習を行う。
PolicyNet
方策関数によるネットワークのこと。
RollOutPolicy
PolicyNetの簡易版。計算量の多いPolicyNetより先に素早く学習させてしまう目的。
ValueNet
価値関数によるネットワークのこと。
モンテカルロ木探索
強化学習の学習手法の一つ。価値関数を学習させる時に用いる手法。
(参考) 強化学習入門 Part3 - AlphaGoZeroでも重要な技術要素! モンテカルロ木探索の入門 - - Platinum Data Blog by BrainPad
AlphaGo Zero
AlphaGo Leeの強化版?のようで、Leeとの違いは以下
ResidualNetwork
勾配消失や勾配爆発が起きないように、かつ精度が高くなるDeepな多層ネットワークになることを可能にしたモデル。ネットワークにショートカットを追加する。
Section3: 軽量化 高速化技術
近年、毎年10倍に学習に必要な計算量が増えている。との事。 より要領良くモデルの学習を進めるために、モデルの軽量化、計算の高速化をする必要がある。 (分散させて学習させる。並列化など。) 分散のさせ方として、演算機(CPU,GPU,TPU)を1台のコンピュータに複数用意させ、各演算機にデータを並列化して学習させる方法もある。
データ並列化
データを複数のコンピュータ(ワーカ)に分割し、学習をさせる。 データ並列化は各モデルのパラメータの合わせ方で、同期型か非同期型か決まる。
同期型
各ワーカーごとに算出された誤差、勾配を親に渡し、親は勾配の平均からパラメータを更新。 更新されたパラメータをまた各ワーカーに渡す。
つまり、全部のワーカーの学習を待ってから、親はその勾配の平均からパラメータを更新する。
非同期型
各々のワーカーは他のワーカーの処理を待たない。各ワーカーごとに学習し、モデルをパラメータサーバーにpushする。計算を待たないので、処理が早い。しかし、処理を待たない分最新のモデルで学習出来ない可能性がある。
モデル並列化
文字通り親モデルを各ワーカーに分割し、 ワーカーには分割された各モデルを学習させる。全てのデータで学習が終わった後で、一つのモデルに復元する事。 モデル並列化は1台のマシンの複数の演算機で実行する事が多い。理由はネットワーク遅延を防ぎたいため。
GPU
元々はゲームになどによく使われている演算機で、性能は低いがコアが多数。 なので、計算量の多さはともかく、シンプルな行列計算であるDeep Learnigの計算でGPUを使用すると、 コアが多数あるので並列的に処理が早い。
GPGPU
元々の使用目的であるグラフィック以外の用途で使用されるGPUの総称。 NVIDIAが有名。GPGPUで並列処理を行うためにプラットフォームにCUDAがあるが、ユーザーは GPU用の演算処理のやり方を改めて学習、実装する必要はない。 理由はDeep Learningフレームワーク(Tensorflow, Pytorch)内で実装されているから。 使用する際は指定すれば良い。
量子化
軽量化の手法の手法の一つ。 通常の重みの値、64bit浮動小数点を16bitなど、下位の精度に落とすことでメモリと演算処理の削減を行う事。欠点として、精度が落ちるという事があるが、そこまで著しく落ちるということはない。
蒸留
軽量化の手法の手法の一つ。
学習済みの精度の高いモデルの知識を軽量なモデルへ継承させること。 精度の高いモデルの知識を、軽量なモデルに継承させる。精度はさほど変わらない。 蒸留により、スマートフォンやIoTデバイスなどPCに比べてメモリが少ないデバイスでも、 モデルを利用することが出来る。 (参考): https://wirelesswire.jp/2016/09/56757/
プルーニング
モデルに影響が少ないパラメータを削除して、モデルの軽量化を行うこと。 例えば、値が0.1以下の重みはカットする。など。 以下の図がわかりやすい。
(参考) https://proceedings.neurips.cc/paper/2015/file/ae0eb3eed39d2bcef4622b2499a05fe6-Paper.pdf
Section4: 応用技術
MobileNet
文字通りモバイルデバイスでも動くくらいにモデルを軽量化する手法の一つ。
一般的な畳み込みレイヤーは計算量が多い。 MobileNetsはDepthwise ConvolutionとPointwise Convolutionの組み合わせで 計算量を減らす。
通常のCNNなら
- 入力サイズ (𝐻in,𝑊𝑙in,𝐶)
- カーネル (K,K,𝐶)
- フィルターがN個
の場合、出力マップは、
(𝐻out,𝑊out,N)
となる。(Hout, Woutはストライドやパディングによって決まる。)
この演算をDepthwise ConvolutionとPointwise Convolutionの組み合わせに分割する。
Depthwise Convolution
まずカーネルのフィルタ数を1に固定にした演算を行う。
入力(𝐻in,𝑊𝑙in,𝐶1) カーネル (𝐾,𝐾,𝐶1) フィルターは1つ! 出力(𝐻out,𝑊out,1) ← Hout, Woutはストライドやパディングによって決まる。
Pointwise Convolution
カーネルのサイズを1*1に固定した演算。フィルターはN個!
入力(𝐻out,𝑊out,1) カーネル (1,1,N) フィルターはN個! チャンネルは1つ。 出力(𝐻out,𝑊out,N) ← Hout, Woutはストライドやパディングによって決まる。
このように通常のCNNを分割することで、計算量が減る。
参考 https://agirobots.com/depthwise-pointwise-convolution/#DepthwisePointwise
DenseNet
出力層に、前の層の入力をチャネルに足しあわせていく。 入力がx 出力がkになるレイヤーがあったら、次の層への入力は x + kとなる。 以下の図がわかりやすかった。 Dense block イメージ
また、kをネットワークのgrouth rateと呼ぶ
このままだとチャネルが増えたままになるので、チャネルを戻すためのTransition Layerがある。
上記図でいうと k0 + 4kのチャンネル数をk0に戻すレイヤー(conv層とpooling層)
メリットとして、画像の特徴の伝達を強化する。などがある。
(参考) https://arxiv.org/pdf/1608.06993.pdf https://deepsquare.jp/2020/04/resnet-densenet
Batch正規化
ミニバッチ単位の正規化。 つまり1チャンネルあたりの画像をたとえばバッチサイズが6ならば、6枚単位で正規化。 過学習抑制などの効果があるが、ミニバッチ単位に環境依存がある(PC,mobile,CPU,GPU)ので、なるべく使いたくない。
Layer正規化
1つのデータの全チャネルに対して正規化を行う。 例として1枚のの画像行列が(r.g.b)と3チャンネルとして(H,W,C) = (28,28,3) の場合、この1枚の画像に対して正規化を行う。
Instance正規化
1つのデータの1つのチャネルに対して正規化を行う。 例として1枚のの画像行列が(r.g.b)と3チャンネルとして(H,W,C) = (28,28,3) の場合、この1枚のが1つのチャンネル(28,28,1)に対して正規化を行う。
Wavenet
自然な音声波形を生成する深層学習モデルのこと。 米Googleのスマートスピーカー「Google Home」や、Android端末に搭載される「Google アシスタント」にて使用されている。 音声を点にして、CNNを使っている。(チャンネルを考慮すると2次元) Dilated causal convolutionというアーキテクチャのCNNを使っている。
Dilated causal convolution
層が深くなるにつれて、畳み込む範囲を広くする。 深層学習を用いて結合確率を学習する際に、効率的に学習が行えるアーキテクチャを提案したことがWaveNet の大きな貢献の1 つである。 提案された新しいConvolution 型アーキテクチャは「Dilated causal convolution」と呼ばれ、結合確率を効率的に学習できるようになっている。
Dilated causal convolutionを用いた際の大きな利点は、単純なConvolution layerと比べて「パラメータ数に対する受容野が広い」ことである。
(参考)
* https://www.itmedia.co.jp/news/articles/1803/27/news053_2.html
Section5: Transformer
Seq2Seq
時系列データからある時系列データを生成する。エンコードして、デコードする。 翻訳などがSeq2Seqモデルである。
Transformer
RNNではなく、Attentionを使った文書生成モデル。RNNでの再起処理がない分、並列処理が可能になって学習時間が短くなった。 今後はこちらが主流になりそう。論文含めて、実装込みでよく読んで動かして理解していきたい。
[1706.03762] Attention Is All You Need
深層学習界の大前提Transformerの論文解説! - Qiita
論文解説 Attention Is All You Need (Transformer) - ディープラーニングブログ
Section6: 物体検知とSS解説
物体検出
ざっくり言うと、画像を入力、出力にラベルとラベル位置を示す矩形、このラベルが合ってるかどうかの値(conf)を返す機械学習モデル。以下に図を示す。
SSD
Single Shot Multibox Detectorの略で、物体検出アルゴリズムの一つ。 1度のCNN演算で物体の領域指定と「クラス分類」の両方を行う。なので高速。
アルゴリズムを簡単にまとめる
モデル
ざっくりというと、VGGネットワークに畳み込み層を追加した。
(参考) https://www.acceluniverse.com/blog/developers/2020/02/SSD.html https://avinton.com/blog/2018/03/single-shot-multibox-detector-explained1/
Segmentation
Segmentationとは各ピクセルに対し、単一にクラスラベルをつけて分割する機械学習の事。 入力は画像。 Semantic SegmentationとInstance Segmentationがある。ここでのまとめはSemantic Segmentationのみ。
Semantic Segmentation
物体の種類ごとに領域分割する。
Instance Segmentation
個体ごとに領域分割する。直感的にはこちらの方が難しそう。
アルゴリズム
FCN,SegNet,U-netなどがある。
(参考)
ディープラーニングによるSemantic Segmentationアルゴリズムまとめ | NegativeMindException
深層学習 Day3
- 動画講義の要約
動画講義の要約
RNN,LSTM、自然言語の処理について
Section1: 再帰型ニューラルネットワークの概念
RNNとは
時間に依存したニューラルネットワークの事。RNNと略される。
図
中間層への入力が、出力層の他に、前層からの中間層がある。
数学的記述
中間層入力 = 入力層の重み演算 + 前層の重み演算 + バイアス $$ u ^ t = W _ (in) x ^ t + Wz ^ {t-1} + b $$
活性化関数の演算で、中間層の値を出力 $$ z ^ t = f(W _ (in) x ^ t + Wz ^ {t-1} + b) $$
出力層入力 = 中間層の重み演算 + バイアス $$ v ^ t = W _ (out) z ^ t + c $$
活性化関数の演算で、出力層の値を出力
$$ y ^ t = g(W _ (out) z ^ t + c) $$
BPTTとは
RNNにおける誤差逆伝搬法の事。
数学的記述
の勾配は 中間層入力の勾配をδとすると、δと入力層の値の転置、との積である。 $$ \dfrac{\partial E}{\partial w _ {in}} = \dfrac{\partial E}{\partial u ^ {t}}[\dfrac{\partial u ^ {t}}{\partial W _ {in}}] ^ {T} = \delta ^ {t} [x ^ {t}] ^ {T} $$
対応するソースコードは
np.dot(X.T, delta[:,t].reshape(1,-1))
↑ delta[:,t]・・・t列目の抜き取り。これが1次元で、.reshape(1,-1))で2次元行列になる模様
の勾配は 出力層へ入力の勾配をとすると、δ outと,中間層出力の転置、との積である。 $$ \dfrac{\partial E}{\partial w _ {out}} = \dfrac{\partial E}{\partial v ^ {t}}[\dfrac{\partial v ^ {t}}{\partial W _ {out}}] ^ {T} = \delta ^ {out,t} [z ^ {t}] ^ {T} $$
対応するソースコードは
np.dot(z[:,t+1].reshape(-1,1), delta_out[:,t].reshape(-1,1)
の勾配は 中間層へ入力の勾配をとすると、δと,前奏の中間層出力の転置、との積である。 $$ \dfrac{\partial E}{\partial w} = \dfrac{\partial E}{\partial u ^ {t}}[\dfrac{\partial v ^ {t}}{\partial W }] ^ {T} = \delta ^ {t} [z ^ {t - 1}] ^ {T} $$
対応するソースコードは
np.dot(z[:,t].reshape(-1,1), delta[:,t].reshape(1,-1))
Section2: LSTM
RNNの課題時系列を遡れば遡るほど、勾配が消失もしくは爆発していく事がある。 この問題を解決するために、構造自体を変えて対応したものがLSTM。
CEC
RNNの今までの中間層の役割は、 * 前層までの値を保持する * 学習する
だったが、値を保持する役割のみをCEC(記憶セル)という機構に任す。
入力ゲート
CECのどのようの値を保持させるかを、この入力ゲートが学習する。(値の保持はしない。) この学習が進むと、CECが効率よく、精度があがるようの前層までの情報を記憶、保持する事が出来る。
出力ゲート
CECの値をどのように使うかを、この入力ゲートが学習する。(値の保持はしない。) この学習が進むと、CECが効率よく、精度があがるように次層へ情報を記憶、保持する事が出来る。
忘却ゲート
CECにとってあまり必要でない情報を忘れさせるゲート。 たとえば、今日はとても天気が暑い。=> 単語としては、「今日」 「は」 「とても」 「天気」 「が」 「暑い」 「。」
暑いを推論したい時、「とても」はあまり重要ではない。 こういった前層からの情報は、捨てて良い。そのためのゲート。
覗き穴結合
ゲートにCEC状態を見させること。CECの状態もそれぞれのゲートの判断材料に使おうという話。 大した改善はなかったらしい。
LSTMの課題
計算負荷が高い。パラメータが非常に多いため。
Section3: GRU
パラメータを減らして、計算負荷を下げたい。
LSTMからCEC,入力ゲート、忘却ゲートがいなくなる。 代わりに、リセットゲート、更新ゲートを設置する。
Section4: 双方向RNN
過去の情報だけでなく、未来の情報を加味することで、精度を向上させるためのモデル。 文章の推敲や、機械翻訳等に使用される。
Section5: Seq2Seq
時系列データからある時系列データを生成する。エンコードして、デコードする。 翻訳などがSeq2Seqモデルである。
図
エンコード
入力時系列データを何らかの意味のあるベクトル表現に変換する事。 具体的には最後の隠れ層の事。 最後の隠れ層は、今までの情報をすべて保持しているので、文脈の特徴を表したベクトルとなっている。
デコード
何らかの意味のあるベクトル表現から新たな時系列データを出力する事。
embedding表現
具体例
単語 | 単語ID | one hot 表現 | embedding |
---|---|---|---|
私 | 1 | [1,0,0,0,0・・・・] | [0.2,0.4,0.6,・・・] |
は | 2 | [0,1,0,0,0・・・・] | [・・・・・・・・] |
刺身 | 3 | [0,0,1,0,0・・・・] | [・・・・・・・・] |
昨日 | 4 | [0,0,0,1,0・・・・] | [・・・・・・・・] |
one-hot表現からサイズを減らしてembedding表現を作成する。 どのようにサイズを減らすか。deep learnigを使う。 単語の意味に着目。単語の意味が似ているものは、embeddingの行列の値が似るように学習させる。 embedding表現とは、単語の意味である。これをRNNの入力値として設定する。
Maked Langage Model
単語 | 単語ID | one hot 表現 | embedding |
---|---|---|---|
私 | 1 | [1,0,0,0,0,0,0・・・・] | [....] |
は | 2 | [0,1,0,0,0,0,0・・・・] | [....] |
昨日 | 3 | [0,0,1,0,0,0,0・・・・] | [....] |
ラーメン | 4 | [0,0,0,1,0,0,0・・・・] | [....] |
を | 5 | [0,0,0,0,1,0,0・・・・] | [....] |
食べ | 6 | [0,0,0,0,0,1,0・・・・] | [....] |
ました | 7 | [0,0,0,0,0,0,1・・・・] | [....] |
ベクトルを得たあと、モデルを学習する時に、ある一箇所を見えなくする。例えば、「昨日」 前後の単語から、どんな単語が入れば自然なのか。を学習させる。 「昨日」を出させるように学習させる。このような学習で、同じような意味が同じようなベクトル表現になる。らしい。
Seq2Seqの課題
一つの文に対して、一つの回答しか出来ない。
HRED
過去n-1 個の発話から次の発話を生成する。 Seq2seqでは、会話の文脈無視で、応答がなされたが、HREDでは、前の単語の流れに即して応答されるため、より人間らしい文章が生成される。文脈の流れが受け渡していくため、RNNのような機構。
HREDの課題
文脈は読み取れるが、ありがちな答えしか返さない。「うん」とか「そうだね」とか
VHRED
HREDに、VAEの潜在変数の概念を追加することで解決した構造。
オートエンコーダ
教師なし学習の一つ。つまり入力データは訓練データのみで教師データは使わない。 具体例として、28ピクセル * 28ピクセルの数字の画像を入れて、何か特徴を表したベクトルを生成。 そのベクトルから同じ画像を出力するニューラルネットワーク。
オートエンコーダの構造
入力データから潜在変数zに変換するニューラルネットワークをEncoder。逆に潜在変数zをインプットとして元画像を復元するニューラルネットワークをDecoder。
VAE
潜在変数zに正則化を行った構造のエンコーダ。(正則化の際の平均は0, 分散は1)
元のデータの類似度が、そのまま潜在変数に類似度に繋がって欲しいわけだが、 それを行ってくれるのが、VAE、とのこと。 エンコーダに少しノイズを加える事でデコーダに汎用性を持たす。
Section6: Word2vec
各単語の意味をベクトル表現で表す手法。具体例を以下に表す。
単語 | 単語ID | one hot 表現 | embedding |
---|---|---|---|
私 | 1 | [1,0,0,0,0・・・・] | [0.1,0.2,0.3] |
は | 2 | [0,1,0,0,0・・・・] | [0.4,0.5,0.6] |
刺身 | 3 | [0,0,1,0,0・・・・] | [0.7,0.8,0.9] |
昨日 | 4 | [0,0,0,1,0・・・・] | [1.0,1.1,1.2] |
embeddingとは重み行列の、one hot表現に対応する特定の行の抜き出しの事。
単語のone-hot表現と 重みの演算について(重みは3列とする)
$$ W = np.array([[0.1,0.2,0.3][0.4,0.5,0.6] [0.7,0.8,0.9][1.0,1.1,1.2]・・・・]) $$ の場合、単語id 1のembedding表現は以下
[1,0,0,0,0・・・・] * W = [0.1,0.2,0.3]
one-hot表現よりembedding表現にした方が次元数が削減され、パフォーマンスが良くなる。
Section7: AttensionMechanism
Seq2Seqの課題に対応したもの。 具体的には、seq2seq の問題は長い文章への対応が難しい。 seq2seq では、2単語でも、100単語でも、固定次元ベクトルの中に入力しなければならない。
文章が長くなるほどそのシーケンスの内部表現の次元も大きくなっていく、仕組みが必要になる。 これがAttention Mechanismで、「入力と出力のどの単語が関連しているのか」の関連度を学習する仕組みのことである。
確認テスト
P23 RNNのネットワークには大きくわけて3つの重みがある。1つは入力から現在の中間層を定義する際にかけられる重み、1つは中間層から出力を定義する際にかけられる重みである。残り1つの重みについて説明せよ。
(ans) 前層の中間層から現在の中間層を定義する際にかけられる重み
P45 下図のy1を1x・s0・s1・win・w・woutを用いて数式で表せ。 ※バイアスは任意の文字で定義せよ。 ※また中間層の出力にシグモイド関数g(x)を作用させよ。
(ans) $$ y _{1} = g(W _ {out} * S _ {1} + c) $$
$$ S _{1} = x _ {1} * W _ {in} + S _ {0} * W + b $$
P78 (ans) 忘却ゲート
「とても」はあまり影響を及ぼさない。このゲートは忘却ゲートで作用させる。
P88 LSTMとCECが抱える課題について、それぞれ簡潔に述べよ
(ans) 複雑で計算量が多くなった。
P92 LSTMとGRUの違いを簡潔に述べよ。
(ans) LSTM はGRUよりパラメータが多いので、GRUの方が計算量が少ない。
P109 (ans) 2
seq2seqとは、RNNを用いたEncoder-Decoderモデルの一種であり、機械翻訳などのモデルに使われる。
P119
seq2seqとHRED、HREDとVHREDの違いを簡潔に述べよ。 (ans)
- seq2seq・・・一文の一問一答に対して処理が出来る、ある時系列データからある時系列データを作り出すネットワークの事。
- HRED・・・seq2seqの機構に、それまでの文脈の意味ベクトルを解釈に加える事で、文脈の意味を汲み取った文の変換(encode ,decode)が出来るようにしたもの。
- VHRED・・・HREDが文脈に対して当たり障りのない回答(はい。とか、うん。とか。) しか出来なくなった対する解決策。VAEの考え方を取り入れて、当たり障りのない回答以上の出力を出せるように改良したもの。
P128 VAEに関する説明・・・自己符号化器の潜在変数に確率分布を導入したもの。
P137 (ans)
- RNN・・・時系列データを処理するのに適したニューラルネットワーク
- Word2Vec・・・単語の分散表現ベクトルを得る手法
- seq2seq・・・一つの時系列データから別の時系列データを得るネットワーク
- Attension・・・時系列データの中身に大して、関連性に重みをつける手法
演習チャレンジ
P26 (ans) 2
隣接単語(表現ベクトル)から表現ベクトルを作るという処理は、隣接している表現leftとrightを合わせたものを特徴量としてそこに重みを掛けることで実現する。つまり、W.dot(np.concatenate([left, right]))である。
P53 (ans) 2
RNNでは中間層出力h{t}が過去の中間層出力h{t-1},.., h{1}に依存する。RNNにおいて損失関数を重みWやUに関して偏微分するときは、それを考慮する必要があり、dh{t}/dh_{t-1} = Uであることに注意すると、過去に遡るたびにUが掛けられる。つまり、delta_t= delta_t.dot(U)となる。
P64 (ans) 1
勾配のノルムがしきい値より大きいときは、勾配のノルムをしきい値に正規化するので、クリッピングした勾配は、勾配×(しきい値/勾配のノルム)と計算される。つまり、gradient * rateである。
P79 (ans) 3
新しいセルの状態は、計算されたセルへの入力と1ステップ前のセルの状態に入力ゲート、忘却ゲートを掛けて足し合わせたものと表現される。つまり、
input_gate* a + forget_gate* c
P90 (ans) 4
(1-z) * h + z * h_bar
更新ゲート、前層の隠れ層から新しい隠れ層の値が算出される模様。
P95 (ans) 4
双方向RNNでは、順方向と逆方向に伝播したときの中間層表現をあわせたものが特徴量となるので、np.concatenate([h_f, h_b[::-1]], axis=1)である。
P110 (ans) 1 単語wはone-hotベクトルであり、それを単語埋め込みにより別の特徴量に変換する。これは埋め込み行列Eを用いて、E.dot(w)と書ける。
深層学習 Day2
動画講義の要約
Section1: 勾配消失問題について
勾配消失問題とは、逆伝搬でどんどん下位層(出力層に近づく)に行くに連れて、微分値 が、どんどん0になっていく事がある。そうなると、 による重みの更新がされず、学習が行われなくなることを言う。 活性化関数にシグモイド関数を用いるとなりやすい。
シグモイド関数を使用すると勾配消失が起きやすい理由
(1- f(u))(f(u))
となる訳だが、この場合f(u)の値が1か0に近い場合、微分値が0に近くなる。 逆伝搬でこの微分値が下流に渡っていく訳だから、重みの更新がされにくくなる。
解消するために以下のようなやり方がある
- 活性化関数をReLUにする。
- 重みの初期値設定でXavier,Heを使用する
- バッチ正規化
Xavier
重みの初期化において、重みの乱数を前層のノード数のルートで割る。
入力層,中間層1,中間層2の各ノード数を784,40,20の場合 $$ network['W1'] = \frac{np.random.randn(784,40)}{\sqrt{784}} $$ $$ network['W2'] = \frac{np.random.randn(40,20)}{\sqrt{40}} $$
He
重みの初期化において、重みの乱数を前層のノード数のルートで割り√2を掛ける
入力層,中間層1,中間層2の各ノード数を784,40,20の場合 $$ network['W1'] = np.random.randn(784,40) * \sqrt\frac{2}{{784}} $$ $$ network['W2'] = np.random.randn(40,20) * \sqrt\frac{2}{{40}} $$
バッチ正規化
平均0,分散1になるように正規化し、入力値に偏りをなくす。
Section2: 学習率最適化手法について
いかにして、損失関数が極小になる重み、バイアスを見つけ出すか。 それを効率的に探す方法が必要になってくる。
今までの求め方 $$ w^{(t+1)} = W^{(t)} - \epsilon\nabla E $$ はSGDと呼ばれる方法で、この方法で重みを更新していくと、非効率な経緯をたどり、極小点に行き着く事がある。 これを解消し、効率的に重みを更新していく方法を示す。
- モメンタム
- AdaGrad
- RMSProps
- Adam
モメンタム
2_4_optimizer.ipynbのソースコードを噛み砕いて表現すると、以下の式になる。
network.params[key] = network.params[key] + momentum * v[key] - learning_rate * grad[key]
↓
次回の重み = 前回の重み - 学習率 * 勾配 + momentum * 前回の重みの更新量
AdaGrad
学習率を過去の勾配から最定義して、学習を繰り返す。 $$ \epsilon => \epsilon \frac{1}{\sqrt{h_t} + 1} $$ $$ h_t = h_{t-1} + (\nabla E)^{2} $$ $$ h_0 = \theta $$
との事なので
$$
h_t = (\nabla E) _ {t-1}^{2} + (\nabla E) _ {t-2}^{2} + ...+ \theta
$$
となるので(便宜的に勾配の微分に添字使用)、学習率の再定義に使用されているhtは、過去の勾配の値を保持している。 鞍点問題には弱い
AdaGripのメリット・・・ 勾配の緩やかな斜面に対して、最適値に近づける。
AdaGripのデメリット・・・ 鞍点問題には弱い。
RMSprops
αはハイパーパラメータ。どれくらい前回までの情報を使い、今回の更新による情報を使うか。みたいなイメージ。 $$ h_t = \alpha h _ {t-1} + (1 -\alpha)(\nabla E)^{2} $$ 学習率の置き換え自体はAdaGridと変わらない、 $$ \epsilon => \epsilon \frac{1}{\sqrt{h_t} + 1} $$
RMSPropのメリット
局所的最適解にはならず、大域的最適解となる。
ハイパーパラメータの調整が必要な場合が少ない。
極小値への軌道のグラフィックは、これが分かりやすい。
https://github.com/Jaewan-Yun/optimizer-visualization
Adam
モメンタムとRMSPropのいいとこどり
Section3: 過学習について
過学習とは、学習が訓練データに特化し過ぎてしまい、テストデータに対してそのモデルがうまくフィットしない事。 訓練データに対するラベルの正解率の精度は高いが、テストデータに対しての正解率は高くない現象のことを示す。
過学習が起きやすい原因・
- 層の数が多い
- ノード数が多い
- 重みの値が大きい。
つまりモデルに自由度が高過ぎる時に過学習が起きやすい。 それらを数を抑制、制約すること。そのために正則化やドロップアウトを使用する。
正則化
誤差関数に正則化項を加える。pノルムとは距離の事。 以下の数式は入力層、中間層、出力層が1つずつのネットワークの場合(重みwが二つ) $$ Ez(w)=Ez(w) + \frac{1}{p}\lambda||x||_{p} $$
$$ ||x|| _ {p} = ||w^{(1)}|| _ {p} + ||w^{(2)}|| _ {p} $$
$$ ||w^{(1)}|| _ {p} = (|w^{(1)} _ {1}|^{p} + |w^{(1)} _ {2}|^{p} + ... + |w^{(1)} _ {n}|^{p})^\frac{1}{p} $$
$$ ||w^{(2)}|| _ {p} = (|w^{(2)} _ {1}|^{p} + |w^{(2)} _ {2}|^{p} + ... + |w^{(2)} _ {n}|^{p})^\frac{1}{p} $$
$$ Ez(w)=Ez(w) + \frac{1}{2}\lambda (||w^{(1)}|| _ {2} + ||w^{(2)}|| _ {2} ) $$
$$ ||x|| _ {p} = ||w^{(1)}|| _ {p} + ||w^{(2)}|| _ {p} $$
正則化項を加える事で誤差関数の最小値を少しずらす。(元々の最小値では過学習が起きるので、最小値を少しずらす。)
ドロップアウト
ノードの数が多い時に過学習が起きやすいので、ノードの数を減らす。
該当ソースはlayers.pyのDropoutクラス
xの行列から、乱数行列を作成し、dropout_ratioのしきい値を設定(boolean行列) self.mask = np.random.rand(*x.shape) > self.dropout_ratio 上の条件式を満たさない要素はすべて0にする事で、ノード数を減らす事を表現している。 return x * self.mask
Section4 CNN 畳み込みニューラルネットワークの概念
CNNを使う理由としては、例えば画像のニューラルネットワークの場合。 位置情報(2dim),色情報(r,g,bの3チャンネル)がある。 この情報を1dimに変換して学習を行うと、いろいろ学習する上で大事な情報が抜けてします。 なるべく次元を保ったまま、学習させるのが良い。そのために畳み込みニューラルネットワークを使う。
畳み込み層
畳み込みの演算概念としては、以下の図となる。strideが1の場合
バイアス
通常のニューラルネットワークと同じ概念。入力画像の一部にフィルターを通した後の行列に、バイアスを加える。
パディング
入力画像の行列の周囲に行列を足すイメージ。
たとえば以下の2✖︎2行列が、パディングによって周囲を0埋めされて4✖︎4行列になる。
beforePadding = np.array([[2,3],[4,5]]) → afterPadding = np.array([[0, 0, 0, 0], [0, 2, 3, 0], [0, 4, 5, 0], [0, 0, 0, 0]]) print(afterPadding.shape) (4,4)
ストライド
入力画像とフィルター(重み)の計算の際に、入力画像をどれだけ移動させるか。以下はストライド2の例。
チャンネル
フィルターの数の事。 色付き画像のディープラーニングでいうと、縦横は2次元、色も(r,g,bの3チャンネル)も次元を持つので3チャンネル、という事になる。
ブーリング層
入力画像の決められた範囲内で、平均とか最大値とがで抽出させてサイズを減らす処理。 概念図は以下。2 * 2 のMAX プーリングの場合。
畳み込み演算の計算速度を早めるテクニック
dot積で計算出来るように、行列を変換させる。 具体例として、以下の入力画像行列(4*4のチャンネル数1の画像が2枚)があるとする
input_data = np.random.rand(2, 1, 4, 4)*100// ↓ [[[[61. 44. 91. 71.] [31. 1. 94. 60.] [97. 63. 44. 28.] [ 1. 64. 29. 51.]]] [[[33. 68. 1. 43.] [90. 59. 27. 96.] [ 6. 86. 8. 55.] [26. 32. 75. 99.]]]]
この入力画像を、3*3のフィルター、ストライド1, パディング0で演算させる場合、 2_6_simple_convolution_network.ipynbのim2colメソッドによって 以下の(8,9)行列に変換される
col = im2col(input_data, filter_h=filter_h, filter_w=filter_w, stride=stride, pad=pad) ↓ [[61. 44. 91. 31. 1. 94. 97. 63. 44.] [44. 91. 71. 1. 94. 60. 63. 44. 28.] [31. 1. 94. 97. 63. 44. 1. 64. 29.] [ 1. 94. 60. 63. 44. 28. 64. 29. 51.] [33. 68. 1. 90. 59. 27. 6. 86. 8.] [68. 1. 43. 59. 27. 96. 86. 8. 55.] [90. 59. 27. 6. 86. 8. 26. 32. 75.] [59. 27. 96. 86. 8. 55. 32. 75. 99.]]
3*3の1ストライドで囲んだ行列を1行にまとめていく。
input_dataの(1,1)(1,2)(1,3)(2,1)(2,2)(2,3)・・・(3,3) => col(1,1)(1,2)・・・(1,9)
input_dataの(6,2)(6,3)(6,4)(7,2)(7,3)(7,4)・・・(8,4) => col(8,1)(8,2)・・・(8,9)
で、colの行列とdot積演算が出来るように、フィルターの行列を変換する。
col_W = W.reshape(フィルターの数, -1)の転置行列 ↓ 出力 = np.dot(col, col_W) + バイアス ↓ 元の行列形に戻す ↓ 元の出力 = 出力.reshape(・・・)
Section5 最新のCNN
モデルの構造5層の畳み込み層およびプーリング層など、それに続く3層の全結合層から構成される。 過学習を防ぐ施策として、サイズ4096の全結合層の出力にドロップアウトを使用している
畳み込みとプーリングによって、画像の行列の形が以下のように変化していく。 (224,224,3) => (55,55,96) => (27,27,256) => (13,13,384) => (13,13,256) => (4096,1) => (4096,1) => (1000,1)
確認テスト
【P12】連鎖率の原理を使い,dz/dyを求めよ。
$$ z = t^{2} $$
$$ t = x + y $$
$$ \frac{dz}{dy}=\frac{dz}{dt}\frac{dt}{dy} = 2t * 1 = 2t $$
【P20】シグモイド関数を微分した時、入力値が0の時に最大値をとる。その値として正しい物を選択肢から選べ
- 0.15
- 0.25
- 0.34
- 0.45
シグモイド関数が $$ f(u) = \dfrac{1}{1-e^{-u}} $$ で、それをを微分すると
(1- f(u))(f(u))
となる。u = 0を代入すると 0.25となる。 $$ (1- \dfrac{1}{1-e}) * \dfrac{1}{1-e} = 0.25 $$
【P28】重みの初期値に0を設定すると、どのような問題が発生するか。簡潔に答えよ。
(answer) 重みを0で初期化すると、正しい学習が行えない。 全ての重みの値が均一に更新されるため、多数の重みを持つ意味がなくなる。
【P31】一般的に考えられるバッチ正規化の効果を2点挙げよ。
- 学習のスピードアップ
- 過学習を抑える事が出来る。
【P35】例題チャレンジ バッチアルゴリズムとミニバッチアルゴリズム
data_x[i:i_end], data_t[i:i_end
バッチサイズだけデータを取り出す処理である。
【P47】モメンタム・AdaGrid・RMSPropの特徴をそれぞれ簡潔に答えよ。
- モメンタム・・・ 谷間についてから最も低い位置(最適値)にいくまでの時間が早い。大域的最適解となりやすい。
- AdaGrid・・・ 勾配の緩やかな斜面に対して最適地値に近づける。鞍点問題には陥りやすい。
- RMSProp・・・鞍点問題になりにくい。ハイパーパラメータの調整が少なくて済む。
【P63】正則化手法の中のリッジ回帰(L2正則化)という手法についてただしいものを選べ
(answer) (a) ハイパーパラメータを大きくすると、重みは限りなく0に近づく。
理由は、ハイパーパラメータを大きくすると、学習を重ねるごとに誤差関数の値は増えていく。 しかし、学習を重ねるごとに本来は誤差関数は小さくなる方法に向かう訳だから、 そのためには重みを0に近づけていくしか誤差関数が小さくなる方に向かう方法がなくなる。 と言う事だと思われる。
【P68】L1正則化を表しているグラフはどちらか答えよ。
横軸の重みが0になっているので、スパース化されている。
【P69】例題チャレンジ L2パラメータ正則化
(ans) param
L2ノルムは、||param||^2なのでその勾配が誤差の勾配に加えられる。つまり、2 * paramであるが、係数2は正則化の係数に吸収されても変わらないのでparamが正解である。
【P71】例題チャレンジ L1パラメータ正則化
(ans) sign(param)
L1ノルムは、|param|なのでその勾配が誤差の勾配に加えられる。つまり、sign(param)である。signは符号関数である。
【P73】例題チャレンジ データ集合の拡張
(ans)
image[top:bottom, left:right, :]
imageの形式が(縦幅, 横幅, チャンネル)であるのも考慮する
【P100】サイズ66の入力画像をサイズ22のフィルタで畳み込んだ時の入力画像のサイズを答えよ。 ストライドとパディングは1とする
(ans) 7 * 7
下記数式に当てはめれば解ける。
out_w = 1 + int((6 + 2 * 1 - 2) / 1) = 7 out_h = 1 + int((6 + 2 * 1 - 2) / 1) = 7
深層学習: Day1
動画講義の要約
Section1: 入力層~中間層
- 入力層とは、一番最初に値が入力される層の事である。そこに重み(入力層の値をどれくらいの割合で使うかの設定値)を作用させて、中間層へ出力させる
- 重みは は、入力 i と 中間層ユニット j に関して値が決定されていて、数式で表示させると、以下のようになる。 (入力層が4つの場合)
= WX + b
Section2: 活性化関数
ニューラルネットワークおいて、次の層への出力を決定する非線形の関数。 入力値によって、次の層への信号のON/OFF や強弱を定める働きを持つ。
中間層用の活性化関数と出力層用の活性化関数がある。
中間層用の活性化関数
出力層用の活性化関数
Section3: 出力層
【誤差関数】
ニューラルネットワークが導き出した答えと、実際のデータ(訓練データ)の答えが合ってるか間違っているかを確認する必要がある。 つまり、どれくらい合っているか間違っているかを確認する必要がある。その尺度に使われるのが誤差関数である。
yは正解ラベル dはニューラルネットワークが導いた出力値(yとd逆にしても、2乗和誤差は変わらない、と思う。)
- 2乗和誤差(回帰問題に使われる) :
- クロスエントロピー(分類問題に使われる) :
Section4: 勾配降下法
学習とは
誤差関数が最小になるように、最適な重みやバイアスを見つける事である。そのための手法が勾配降下法である。
学習率とは
誤差関数を最小になるように学習を繰り返す事中で、前回の学習から得られた誤差をどれだけ次の学習に生かすかを決定するパラメータ(下記のε)
勾配降下法の学習率の決定、収束性向上のアルゴリズムは以下のようなものがある。
* Momentum
* AdaGrad
* Adadelta
* Adam(よく使用されるらしい)
エポック
学習はエポックという単位で繰り返される。1エポックとは、例えば10000枚の訓練データ、100個のミニバッチだと、学習を100回行うと全ての訓練データを見た事になる。この場合1エポック = 100回となる。
勾配降下法には、バッチ勾配降下法, 確率的勾配降下法,ミニバッチ勾配降下法がある。
バッチ勾配降下法
- 一回のパラメータ更新に全部の訓練データすべてを利用ため、メモリ上にすべてデータが乗らない場合がある。
確率的勾配降下法
- 全サンプルからランダムに一つのデータ選んで、そこから誤差関数を求め、学習させていく方法。
- メリットとして、オンライン学習ができる。データが冗長な場合の計算コストの削減ができる。
ミニバッチ勾配降下法
の求め方
数値微分
の方法があるが、これだと計算量が多く、無駄が多い。→誤差逆伝搬法を用いる。
Section5: 誤差逆伝播法
- 誤差(関数)をパラメータで微分した関数を利用し、出力層側から、ネットワークのパラメータ更新を行う。
- 数値微分のように計算量が多くならない。最小限の計算で、解析的にパラメータの更新量を計算する事ができる。
- 誤差(関数)の重みでの微分値は、微分の連鎖率を利用し、上の層の微分値(出力層側から入力層に向けて)を再起的に利用しながら求められていく。
確認テスト
【P11】ディープラーニングは、結局何をやろうとしているか2行以内で述べよ。 また、次の中のどの値の最適化が最終目的か。 全て選べ。
明示的なプログラムの代わりに、多数の中間層を持つニューラルネットワークを用いて、入力値から目的とする出力値に変換する数学モデルを構築する事。
重みとバイアスの最適化が最終目的である。つまり3、4
(考察)重みとバイアスの最適化により、最適な出力値が算出される。
【P13】次のネットワークを紙にかけ。
入力層:2ノード1層
中間層:3ノード2層
出力層:1ノード1層
【P20】この図式に動物分類の実例を入れてみよう。
【P22】この数式をPythonで書け。
numpyを使って内積を計算する
= WX + b
import numpy as np u1 = np.dot(X,W) + b
【P24】1-1のファイルから 中間層の出力を定義しているソースを抜き出せ。
1_1_forward_propagation.ipynbの、順伝播(3層・複数ユニット)から抜き出す。 中間層は2つある。 reluは次のsectionで出てくる活性化関数
# 中間第1層の総入力 u1 = np.dot(x, W1) + b1 # 中間第1層の総出力 z1 = functions.relu(u1) # 中間第2層の総入力 u2 = np.dot(z1, W2) + b2 # 中間第2層の総出力 z2 = functions.relu(u2)
Section2: 活性化関数
【P27】線形と非線形の違いを図にかいて簡易に説明せよ。
【P34】配布されたソースコードより該当する箇所を抜き出せ。
1_1_forward_propagation.ipynbの、順伝播(単層・複数ユニット)から抜き出す。
活性化関数を使用している箇所は、
z = functions.sigmoid(u)
【P45】
なぜ、引き算でなく二乗するか述べよ 下式の1/2はどういう意味を持つか述べよ
(ans) 引き算を行うだけでは、各ラベルでの誤差で正負両方の値が発生し、全体の誤差を正しく表すのに都合が悪い。2乗する事で各ラベルの誤差を必ず正の値にする。1/2は便宜上の問題。実際にネットワークを学習する時に行う誤差逆伝搬法で、誤差関数の微分をするが、その際の計算を簡単にするため。本質的な意味はない。
【P52】①~③の数式に該当するソースコードを示し、一行づつ処理の説明をせよ。
# ソフトマックス関数 def softmax(x): ・・・・本質的な計算は以下の戻り値のみ return np.exp(x) / np.sum(np.exp(x))
①def softmax(x) ソフトマックス関数の値 ②np.exp(x) 分子.出力層の値xの指数関数 ③np.sum(np.exp(x)) 分母.各出力層の値xの指数関数の和ととっている
【P54】①~②の数式に該当するソースコードを示し、一行づつ処理の説明をせよ
# クロスエントロピー def cross_entropy_error(d, y): ・・・・本質的な計算は以下 return -np.sum(np.log(y[np.arange(batch_size), d] + 1e-7))
①def cross_entropy_error(d, y) dは正解ラベル(one-hot表現だと0 or 1), yはニューラルネットワークからの出力 ②return -np.sum(np.log(y[np.arange(batch_size), d] + 1e-7))
batch_sizeはバッチサイズであり、戻り値は交差エントロピーの値(one_hot表現であってもそうでなくても、対応する事ができる) また1e-7 をプラスしているのは、np.log(0)のような計算が発生した場合、-∞になってしまい、この先の交差エントロピー計算が出来なくなる。 そうならないようにするために微小な値を加算している。
【P57】該当するソースコードを探してみよう。
network[key] -= learning_rate * grad[key]
【P66】オンライン学習とは何か2行でまとめよ
学習データが入ってくるたびに都度パラメータを更新し、学習を進めていく方法。 一方バッチ学習では、一度の全ての学習データを使ってパラメータ更新を行う。
【P69】この数式の意味を図に書いて説明せよ。
エポックごとに、重みを更新し(更新量は誤差関数の勾配と学習率をかけたもの)最適な重みを計算していく。
【P79】誤差逆伝播法では不要な再帰的処理を避ける事が出来る。 既に行った計算結果を保持しているソースコードを抽出せよ。
def backward(x, d, z1, y): # print("\n##### 誤差逆伝播開始 #####") grad = {} W1, W2 = network['W1'], network['W2'] b1, b2 = network['b1'], network['b2'] # 出力層でのデルタ delta2 = functions.d_mean_squared_error(d, y) ## (1)↑ここで 誤差関数の導関数(誤差関数dを出力値yで微分したもの)の値を求めている。 # b2の勾配 grad['b2'] = np.sum(delta2, axis=0) ## (2)↑ここで (1) の値 (delta2) を利用している。 # W2の勾配 grad['W2'] = np.dot(z1.T, delta2) ## (3)↑ここでも (1) の値 (delta2) を利用している。 # 中間層でのデルタ delta1 = np.dot(delta2, W2.T) * functions.d_sigmoid(z1) ## (4)↑ここでも (1) の値 (delta2) を利用している。 delta1 = delta1[np.newaxis, :] # b1の勾配 grad['b1'] = np.sum(delta1, axis=0) ## (5)↑ここで (4) の値 (delta1) を利用している。 x = x[np.newaxis, :] # W1の勾配 grad['W1'] = np.dot(x.T, delta1) ## (6)↑ここでも (4) の値 (delta1) を利用している。 return grad
【P84】2つの空欄に該当するソースコードを探せ
1_3_stochastic_gradient_descent.ipynbのdef backward(x, d, z1, y):より抜き出す。
① → delta2 = functions.d_mean_squared_error(d, y) 恒等写像なのでdelta2と変わらない。
② → grad['W2'] = np.dot(z1.T, delta2)
node.js バージョンアップでエラー
経緯
0.12から4にnode.jsのバージョンを上げた際に発生
$ npm install ・・・・ Error: `libsass` bindings not found. Try reinstalling `node-sass`? at getBinding ・・・・
これで一発
rebuildすれば良いみたい。
$ npm rebuild node-sass
karmaでUnknown provider: ハマる。
karma.conf.js
files: [ '../../angular/angular/angular.js', '../../angular/angular/angular-mocks.js', 'scripts/*.js', 'specs/*_spec.js' ],
angularFilter.js
angular.module('app', []) .filter('upperFilter' , function () { return function(input){ return angular.uppercase(input); }; });
angularFilter_spec.js
describe("upperFilterのテスト", function () { beforeEach(module('app')); it('大文字に変換', inject(function ($filter) { var upperFilter = $filter('upperFilter'); expect(upperFilter('hello, world!')).toEqual('HeLLO, WORLD!'); })); });
Error: [$injector:unpr] Unknown provider: upperFilterFilterProvider <- upperFilterFilter
間違ってはないはずなんやけど。。 結果判明
モジュール名がマズかった。
モジュール名appを他で使ってた。
$ cat ./specs/timeout_spec.js angular.module('app', [])
なので、angularFilter.jsのモジュール名を他のファイルと被らないように修正すると、Unknown providerのエラーは無くなった。