Open keitom61 opened 3 years ago
【実装演習結果のサマリーと考察】 2ノード・単層のニューラルネットワークの実装演習を行った。 ただし、重みWとバイアスbは更新しない。 また活性化関数は とする。結果は以下の通りとなった。
【確認テスト】 Q1:入力層から中間層モデルに動物分類の実例を入れる。
A1:
Q2:以下の数式をPythonで書け
A2: u = np.dot(x, W) + b
Q3:中間層の出力を定義しているソースを抜き出せ。
A3: z = functions.relu(u)
Section2:活性化関数 【要点】 ニューラルネットワークにおいて活性化関数は総出力uに対し で表され、次の層への出力zを決める関数f(u)である。
中間層の活性化関数は出力の強弱を調整するために用いられる。 中間層の活性化関数としては、①シグモイド関数②RELU関数が主に用いられる。ニューラルネットワークの前身であるパーセプトロンでは、ステップ関数が使用されていた。
シグモイド関数は で表される。 0~1の間を緩やかに変化するため、ステップ関数では信号の強弱を伝えられる。ただし微分値が小さいため、勾配消失問題を引き起こしやすい欠点を抱えていた。
RELU関数は で表される。現在は最も使用されている中間層の活性化関数である。
【実装演習結果のサマリーと考察】 活性化関数としてシグモイド関数を用いた場合、 出力は下記の通り0~1の間の値をとる。
一方、活性化関数としてシグモイド関数を用いた場合、 u>0の時は出力はuとなり、u<0の時は出力は0となった。
【確認テスト】 Q:配布されたソースコードより該当する箇所を抜き出せ。
A: z1 = functions.sigmoid(u)
なおsigmoid関数のコードは def sigmoid(x): return 1/(1+np.exp(-x)) となる。
Section3:出力層 【要点】 ニューラルネットワークの評価は、出力層からの出力yと正解ラベルdを用いた誤差関数E(w)にて行う。 回帰問題では誤差関数として二乗誤差が用いられる。 分類問題では誤差関数として交差エントロピーが用いられる。
二乗誤差は 交差エントロピーは で表される。
出力層と中間層では活性化関数の目的が異なる。 出力層では信号の大きさはそのまま変換する。また、分類問題の場合、出力層の出力は0~1の範囲に限定し、総和を1とする必要がある。
回帰問題では活性関数として主に恒等写像が用いられる。
二クラス分類問題では前述のシグモイド関数が用いられる。 多クラス分類問題では主にソフトマックス関数が用いられる。
【実装演習結果のサマリーと考察】 多クラス分類問題の場合、出力層ではソフトマックス関数を用いる。
ソフトマックス関数を用いることで出力の総和は1になる。 また、交差エントロピーを誤差関数とする。
回帰問題の場合、出力層では恒等関数を用いる。
また、二乗誤差を誤差関数とする。
【確認テスト】 Q1:二乗誤差が引き算でなく二乗するか述べよ。また1/2の持つ意味を述べよ。
A1:出力層からの出力yと正解ラベルdの誤差の総和をとる際に、正の誤差と負の誤差が打ち消しあわないため。また1/2は、二乗誤差を勾配降下する際に微分するため、発生する2とかけて1にするための数字である。
Q2:ソフトマックス関数に該当するソースコードを示し、一行ずつ処理の説明をせよ。
A2: def softmax(x): if x.ndim == 2: ←xが二次元データの場合のif文 x = x.T x = x - np.max(x, axis=0) y = np.exp(x) / np.sum(np.exp(x), axis=0) return y.T
x = x - np.max(x) ←オーバーフロー対策として最大値を0にする。
return np.exp(x) / np.sum(np.exp(x)) ←ソフトマックス関数
Q3:交差エントロピーに該当するソースコードを示し、一行ずつ処理の説明をせよ。
A3: def cross_entropy_error(d, y): if y.ndim == 1: ←yが一次元データの場合のif文 d = d.reshape(1, d.size) ←dはd.size個の要素を持つベクトルになる y = y.reshape(1, y.size) ←yはy.size個の要素を持つベクトルになる
# 教師データがone-hot-vectorの場合、正解ラベルのインデックスに変換
if d.size == y.size: ←dとyの要素数が同じ場合のif文
d = d.argmax(axis=1) ←dは最大要素(1のある要素)のインデックスになります。
batch_size = y.shape[0] ←batch sizeはy.sizeになる。
return -np.sum(np.log(y[np.arange(batch_size), d] + 1e-7)) / batch_size
Section4:勾配降下法 【要点】 深層学習はデータ学習を通して、誤差関数Eを最小化するパラメータを発見し、モデルを最適化する。 そのために、勾配降下法を利用して重みwとバイアスbを最適化する。 勾配降下法は次の式で表される。ここで重みとバイアスはベクトルwでまとめてあらわす。
tが現在のエポック、εが学習率というハイパーパラメータである。Eの勾配にεをかけたものを、現エポックをwから引き、次のエポックのwとする。
学習率によっては誤差関数Eを最小化するパラメータが発見できない恐れがある。 学習率が大きすぎた場合、最小値にたどり着かず発散する恐れがある。 学習率が小さすぎた場合、収束するまでに時間がかかったり、局所極小解に陥る恐れがある。
最も単純な勾配降下法は、全学習データを1バッチとしてwの更新を行う。 ほかには、確率的勾配降下法(SDG)とミニバッチ勾配降下法という手法がある。
SDGは1エポックにおいて学習データから、ランダムに抽出した学習データを用いてパラメータの更新を行う。 ・局所極小解に陥るリスクの低減 ・オンライン学習が可能になる というメリットがある。
ミニバッチ勾配降下法は、学習データをミニバッチに分割し、ミニバッチごとに学習してパラメータの更新を行う。 SDGのメリットに加えて、並列計算による学習の高速化というメリットがある。
【実装演習結果のサマリーと考察】 1_2_back_propagation.ipynbにfor文を追加して、5エポック学習されるプログラムにした。
for i in range(0,5):
y, z1 = forward(network, x)
# 誤差
loss = functions.cross_entropy_error(d, y)
grad = backward(x, d, z1, y)
for key in ('W1', 'W2', 'b1', 'b2'):
network[key] -= learning_rate * grad[key]
print("##### 結果表示 #####")
epoc = i+1
print('エポック:{0}'.format(epoc))
print("##### 更新後パラメータ #####")
print_vec("重み1", network['W1'])
print_vec("重み2", network['W2'])
print_vec("バイアス1", network['b1'])
print_vec("バイアス2", network['b2'])
初期ネットワークの出力は
5エポック後の出力は
となり、目標出力の[0,1]に近づいていることがわかる。 なお先のデータは学習率ε=0.01であった。
ε=0.1の場合 5エポック後の出力は となり誤差関数が最小となる解へ早く進んでいることがわかる。
【確認テスト】 Q1:オンライン学習とは何か A1:学習データが入るたびにパラメータの更新を行う、学習手法である。 逆にバッチ学習では一度にすべてのデータを使用してパラメータを更新する。
Q2:
この数式の意味を絵にかいて説明せよ
A2:
Section5:誤差逆伝播法 【要点】 勾配降下法を行うためには、誤差関数の勾配を求める必要がある。 数値微分は計算が膨大となるため、適切な手法ではない。 そのため誤差逆伝播法を用いる。
誤差逆伝播法は微分の連鎖律を用いる。算出された誤差を、出力層側から順に微分し、前層へ順に伝播する。先に微分した計算結果は、前層へ順に伝播する過程で用いるため、数値微分よりも計算量を減らせる。
仮に1層のニューラルネットワークとすると 誤差関数をE、活性化関数の総出力をy、重みwとの内積にバイアスbを足した出力をuとする。 この場合は に分解できる。 分解したそれぞれを計算することで、Eのwに関する偏微分を求めることができる。 また、は になる。
との共通部は計算結果を強要できるため、計算量を減らすことができる。
【実装演習結果のサマリーと考察】 確率勾配降下法を実装したプログラム 1_3_stochastic_gradient_descent.ipynb
に手を加えて、3次元ベクトルxを入力し関数f(x)を予測するモデルを作成した。 学習率を変化させた場合の結果を確認した。 ランダムシードは32で固定する。
学習率0.07の場合、誤差関数は1000エポックでも収束しきっていない。
学習率0.1の場合、誤差関数は100エポックで収束する。
学習率0.7の場合、誤差関数は発散して収束しない。
【確認テスト】 Q1:誤差逆伝播法では不要な再帰的処理を避ける事が出来る。既に行った計算結果を保持しているソースコードを抽出せよ。
A1:
delta2 = functions.d_sigmoid_with_loss(d, y)
# b2の勾配
grad['b2'] = np.sum(delta2, axis=0)
# W2の勾配
grad['W2'] = np.dot(z1.T, delta2)
Q2:2つの空欄に該当するソースコードを探せ
A2:
delta2 = function.d_mean_squared_error(d, y)
grad['W2'] = np.dot(z1.T, delta2)
Section1:勾配消失問題 【要点】 誤差逆伝播法は微分の連鎖律によって、誤差関数Eを重みwやバイアスbで微分する。 微分の連鎖律が増えることで、下位に進むにつれて勾配が緩やかになり、 重みwやバイアスbが更新されにくくなることを勾配消失問題と呼ぶ。 特に、各層の活性化関数の微分 が連鎖律の間に入るため、微分値が最大0.25しかないシグモイド関数を活性化関数として用いることは、 勾配消失問題を引き起こしやすくなる。
以下、勾配消失問題への対策を①~③で述べる。 ①適切な活性化関数の使用 tanh関数やRELU関数はシグモイド関数よりも、勾配が大きくなるため勾配消失問題を起こしにくくなる。
②適切な重みwの初期値設定 シグモイド関数やtanh関数は、xの絶対値が大きくなるほど勾配が小さくなる。 そのため、標準正規分布に従ったランダムな値に初期値を設定した場合、勾配消失問題が発生しやすくなる。 半面xが0に近い重みwを設定すると、モデルの表現力が失われる。 そのため、XavierやHeの初期値を用いて適切な重みwの初期値を決めることが重要である。
③バッチ正規化 次の層にデータを渡す前に、バッチごとにデータを正規化する。 正規化により重みwに極端な差が生じ、勾配消失が発生することを抑制する。
【実装演習結果のサマリーと考察】 2_2_2_vanishing_gradient_modified.ipynb にて活性化関数と初期値を変えた場合の結果を確認した。 ①活性化関数:シグモイド 初期値:標準正規分布 学習が進まなかった。
②活性化関数:ReLU 初期値:標準正規分布 テストデータに対する正答率が0.917まで向上した。
③活性化関数:シグモイド 初期値:Xavier ①と比較して学習が進んだ。テストデータに対する正答率が0.88まで向上した。
④活性化関数:ReLU 初期値:He テストデータに対する正答率が0.953まで向上した。
②' ②の隠れ層の数を倍にした。 テストデータに対する正答率が0.933まで向上した。
なお、今回のケースではシグモイド-He、ReLU-Xavierの組み合わせでも学習は③と④とさほど変わらず進んだ。
【確認テスト】 Q1:連鎖律の原理を使い、dz/dxを求めよ。
A1:
Q2:シグモイド関数を微分したときの、入力値が0の時の最大値は?
A2:0.25
Q3:重みの初期値を0に設定すると、どのような問題が発生するか?
A3:モデルの表現力が失われて、学習が進まなくなる。
Q4:一般的に考えられるバッチ正規化の効果を2点あげよ
A4: 1.重みの間の差異が小さくなり、勾配消失問題が発生しにくくなる。 2.学習データの桁数がそろうことで、計算コストが抑制される。
Section2:学習最適化手法 【要点】 勾配降下法を利用してパラメータwを最適化する際、 学習率εを適切に設定しなければ、パラメータwが発散したり、局所極小解に収束してしまう。 そのため学習最適化手法を利用して、学習率を最適化する必要がある。
学習最適化手法として①~④の手法を解説する。
①モメンタム であらわされる。誤差の勾配を学習率の積をとり、重みから減算するが、慣性μと前回のVの積の項が加わる。SDGより大域的最適解にたどり着きやすい。
②AdaGrad 誤差関数の勾配の二乗をを用いて、更新毎に学習率を徐々に減らす。勾配の緩やかな斜面に対して、最適解に近づけるメリットがある。
③RMSProp AdaGradに対して、更新率を決める項αが加わっている。そのため、学習率が極端に減少する事態が避けられ、ハイパーパラメータの調整が少なくてすむ。
④Adam モメンタムとRMSProp両方のアルゴリズムを取り入れた学習最適化手法である。それゆえ①~③のメリットをはらんでいる。
【実装演習結果のサマリーと考察】 2_4_optimizer_after.ipynbにて学習最適化手法の実装演習を行った。 学習対象はMNISTとした。
SGD 学習できなかった。
Momentum
AdaGrad
RMSprop 200エポックまででおおよその学習ができた。
Adam 300エポックまででおおよその学習ができた。
次にAdamをベースに活性化関数と重みの初期値を変更した。 Adam(Sigmoid ⇒ ReLU)
Adam(Sigmoid ⇒ ReLU, gauss ⇒ He) 初期エポックから精度が高く、学習スピードが速まった。
次にAdamをベースにバッチ正規化を実施した。 こちらも学習スピードを速める効果が確認できた。
【確認テスト】 Q1:モメンタム・AdaGrad・RMSPropの特徴をそれぞれ簡潔に説明せよ
A1: モメンタム:慣性項により前回の学習結果の一部を取り入れつつ、重みの更新を行う
AdaGrad:前回の重み更新値を用いて、学習率を徐々に減らしていく
RMSProp:前回の重み更新値の一部を用いて、学習率を徐々に減らしていく
Section3:過学習 【要点】 訓練データに対する誤差とテストデータ(検証データ)に対する誤差が乖離することを過学習と呼ぶ。 これはモデルが汎化性能を失ったことで発生し、原因はネットワークの自由度が高すぎることにある。 過学習対策として①正則化②ドロップアウトがあげられる。
①正則化 特定の重みが大きすぎると過学習が発生しやすくなる。誤差に対して、正則化項を加算することで、重みを抑制することができる。
式は以下の通りに表すことができる。
p=1の場合、正則化項はL1ノルムになる。p=2の場合、正則化項はL2ノルムになる。 正則化項がL1ノルムの場合Lasso回帰となり、スパースな解が得られやすい。 正則化項がL2ノルムの場合Lidge回帰となり、各項が0に近い解が得られやすい。
②ドロップアウト ドロップアウトとはランダムにノードを削除して、ニューラルネットワークに学習させる手法である。 データ量を変化させずに、異なるモデルを学習させることができる。
【実装演習結果のサマリーと考察】 2_5_overfiting.ipynbにて過学習対策の実装演習を行った。
未対策の時の精度は下記の通りであった。
L2ノルムの正則化項を加算(λ=0.1)
L1ノルムの正則化項を加算(λ=0.005)
1のλを変更した場合のモデルも学習させた。 1-1. λ=0.05
1-2. λ=0.2
λの値で学習結果が大きく異なることがわかる。
3 Dropout(drop out ratio 0.15)
3のdrop out ratioを変更したモデルでの学習もおこなった。 3-1 Dropout(drop out ratio 0.04)
ratioを適切に選べば学習データとテストデータに対する精度は向上した。
【確認テスト】
Q1:リッジ回帰の特徴として正しいものはどれか?
A1:(a)ハイパーパラメータを大きな値に設定すると、すべての重みが限りなく0に近づく。
Q2:L1正則化を表しているグラフはどちらか?
A2:
Section4:畳み込みニューラルネットワークの概念 【要点】 畳み込みニューラルネットワーク(CNN)は2次元以上の空間情報を保持して学習させたい場合に用いる。 例えば画像の縦、横、チャンネルの3次元データをそのまま学習し、次に伝えることができる。
畳み込み層では2次元以上の入力に対し、同次元のフィルタによる積をとり、その和を出力として返す。出力にバイアスを加算した結果を次の層に伝える。フィルターが一次元のニューラルネットワークにおける重みに相当する。
畳み込みの出力結果はフィルタが2以上の場合、入力に対し行数と列数が小さくなる。結果、層が進むにつれてデータ数が小さくなり、複雑さを伝えることができない。回避方法としてパディングを行い、元データの周囲を特定の数字で埋めて、行数と列数を増やす方法がある。
ストライドはフィルターの移動数である。
チャンネルは入力データが、二次元画像データであった場合、RGBの3チャンネルなどをさす。
プーリング層では入力に対し、対象領域の最大や平均を出力として返す層である。
【実装演習結果のサマリーと考察】 2_7_double_comvolution_network.ipynbにて畳み込みニューラルネットワークの実装演習を行った。
CNNの各層は 畳み込み - ReLU - プーリング - 畳み込み - ReLU - プーリング - 全結合 - ReLU - 全結合- ソフトマックス の順に積み重なっている。 Mnistを入力に識別するように学習させた。
100エポック後には約0.8の精度となった。
なお、この後エポック数を増やしても精度は約0.9で飽和した。
次に全結合層を1層減らした場合 畳み込み - ReLU - プーリング - 畳み込み - ReLU - プーリング - 全結合 - ReLU - ソフトマックス となり100エポック後の精度は0.63となった。
【確認テスト】 Q サイズ6×6の入力画像を2×2のフィルターでたたみ込んだ時の出力画像のサイズを答えよ。なおストライドとパディングを1とする。
A (6+2×1-2)/1+1=7 7×7の画像となる。
Section5:最新のCNN 【要点】 最新のCNNの例として、AlexNetをあげる。AlexNetは2012年のILSVRCにて圧倒的な精度で画像の識別と分類を行い、優勝したモデルである。 AlexNetの層構成は以下の通りである。
畳み込み→プーリング→畳み込み→プーリング→畳み込み×3→プーリング→全結合×3
入力には224×224の画像を用いる。
過学習を防ぐ施策として、サイズ4096の全結合層の出力にドロップアウトを使用している。このようにニューラルネットワークでドロップアウトを使用する場合は後段の層で使用する場合が多い。
【実装演習結果のサマリーと考察】 2_8_deep_convolution_net.ipynbにて多層CNNの実装演習を行った。
構造は下記の通り conv - relu - conv- relu - pool - conv - relu - conv- relu - pool - conv - relu - conv- relu - pool - affine - relu - dropout - affine - dropout - softmax
convは畳み込み層、reluは活性化関数ReLU、poolはプーリング層、affineは全結合層、dropoutはドロップアウト層 softmaxはソフトマックス層
100エポックで精度0.93に到達し、飽和した。
【関連記事レポート】
ILSVRCではAlexNet以降も、畳み込みとプーリング層をさらに増やして、精度を向上したモデルが登場した。
代表的なモデルにVGG16やGoogLeNetが挙げられる。
VGG16は3×3の小さな畳み込みフィルターのみを用いて、層を深くしたモデルである。13の畳み込み層と3層の全結合層から構成されている。
GoogleNetは3つの異なるサイズの畳み込みフィルタ(1×1,3×3,5×5)と3×3のmaxプーリングから構成されるInceptionモジュールを積み上げた構造をしている。
深層学習day1
Section1:入力層~中間層 【要点】 ニューラルネットワークへの入力をn次元ベクトルxとする。 中間層への総入力uは、重みWとxの内積にバイアスbを足したものになる。 数式で表すと、 になる。 これは線形重回帰と同じ数式になる。 得られた入力uを活性化関数に代入した結果が中間層の出力zになる。 数式で表すと になる。
ニューラルネットワークでは学習データを用いて、重みWとバイアスbを更新する。