##はじめに
本記事は機械学習の個人的な勉強におけるメモとして活用しています。
数式や実装は間違っている可能性がありますので、ご了承願います。
参考書籍:ゼロから作るDeepLearning①
#【深層学習Day1】
##Section1:入力層〜中間層
###要点のまとめ
- 入力層では身長や体重といった特徴ベクトルを入力
- 特徴ベクトルに重みwを掛けたりバイアスbを加えたりして中間層へ出力
###実装演習結果と考察
import numpy as np
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# 入力
X = np.random.randint(10, size=(2))
# 重み
W = np.random.rand(2, 3)
# バイアス
B = np.random.rand(1, 3)
# 出力
A = np.dot(X, W) + B
Z = sigmoid(A)
###確認テストなどの考察
(問題)
ディープラーニングは、結局何をやろうとしているか
(回答)
データを入力することで、重みやバイアスといったパラメータを自動で学習し、目的の数値を出力する。
(考察)
「ニューラルネットワーク」や「中間層」といったディープラーニングの特徴となるキーワードを用いるのがベター
(問題)
最適化が最終目的となる値は何か
(回答)
重み、バイアス
(考察)
最適化の意味と使い方について調べた結果、「制約条件がある中で複数の選択肢を組み合わせ何らかの成果を出すとき、その成果を最小または最大にすること」ということを理解しました。ここでのポイントは、「制約条件がある」ということ。例えば、サッカーでは得点は多いに越したことはなく、最適な得点というものはないため、得点の最適化とは言いません。一方で、例えば飛行機の速度では、設計速度よりも速すぎると空気抵抗が多くなり機体の構造が耐えられなかったり、燃費が悪くなります。また、遅すぎても失速したり目的地への飛行時間が長くなってしまいます。このため、空気抵抗、空気密度、燃費などを考慮した早すぎず遅すぎない「最適な」飛行速度というものがあります。
##Section2:活性化関数
###要点のまとめ
- 活性化関数とは、入力信号の総和を出力信号に変換する関数
- 代表的な活性化関数は次のとおり
- 中間層:シグモイド関数
- 中間層:ReLU関数
- 中間層:ステップ関数
- 出力層:ソフトマックス関数
- 出力層:恒等関数
- 出力層:シグモイド関数
###実装演習結果
中間層:シグモイド関数
def sigmoid(x):
return 1 / (1 + np.exp(-x))
中間層:ReLU関数
def relu(x):
return np.maximum(0, x)
中間層:ステップ関数
def step_function(x):
if x > 0:
return 1
else
return 0
###確認テストなどの考察
(問題)
「中間層を出力するコードを書け
(回答)
z = functions.sigmoid(u)
###コラム
さまざまな活性化関数が存在するが、ニューラルネットワークの起源であるパーセプトロンではステップ関数が使われていた。パーセプトロンを多層化し、活性化関数をステップ関数からシグモイド関数へと変更したものがニューラルネットワークとなる。しかしながら、シグモイド関数は万能ではなく、中間層が多くなればなるほど誤差逆伝播時に勾配消失が起きるといった問題があることから今日ではReLU関数などが使われている。
##Section3:出力層
###要点のまとめ
- 出力層における活性化関数は、分類問題か回帰問題かで異なる
- 一般的に分類問題ではシグモイド関数やソフトマックス関数を、回帰問題では恒等関数を用いる
- 恒等関数は入力値をそのまま出力する
- ソフトマックス関数は総出力のうち、各出力の占める割合を個別に出力する
- ソフトマックス関数は出力の総和が1になるという重要な性質を持つ
- 出力の総和が1ということは、出力を確率的に扱うことが可能となる
y_{k} = \cfrac{exp(a_{k})}{\displaystyle\sum_{i=1}^{n} exp(a_{i})}
=\cfrac{exp(a_{k}+logC )}{\displaystyle\sum_{i=1}^{n} exp(a_{i}+logC )}
=\cfrac{exp(a_{k}+C^{'})}{\displaystyle\sum_{i=1}^{n} exp(a_{i}+C^{'})}
###実装演習結果
ソフトマックス関数
def softmax(a):
exp_a = np.exp(a)
sum_exp_a = np.sum(exp_a)
y = exp_a / sum_exp_a
return y
###確認テストなどの考察
(問題)
誤差の計算ではなぜ、引き算ではなく2乗するのか
(回答)
符号による影響を排除するため
(問題)
誤差関数において1/2を掛けている理由は何か
(回答)
決定的な理由はないが、勾配を求める際の微分計算がしやすいというメリットがある。
###コラム
ソフトマックス関数は指数関数を計算することから値が極端に大きくなることがあるというデメリットがある。この値のオーバーフロー対策として、分母分子に$log C$を加えている。これは、ソフトマックス関数においては、分母分子に定数を足し引きしても計算結果が変わらないことを利用している。一般に、定数の値は入力における最大値を用いる。
def softmax(a):
c = np.max(a)
exp_a = np.exp(a - c) #オーバーフロー対策
sum_exp_a = np.sum(exp_a)
y = exp_a / sum_exp_a
return y
##Section4:勾配降下法
###要点のまとめ
- ニューラルネットワークにおける学習の目的は誤差を最小にするパラメータを推定すること
- 誤差が最小になる点は下に凸の2次の損失関数の勾配が0の点と言える
- この勾配が0となる点を求める代表的な手法が勾配降下法である
$$
w^{t+1}=w^{t}-\epsilon\Delta E
$$ - 勾配降下法には次のような手法がある
- 勾配降下法:全サンプルの誤差を使用(バッチ学習)
- 確率的勾配降下法:ランダムに抽出したサンプルの誤差を使用(オンライン学習)
- ミニバッチ勾配降下法:ランダムに分割したデータの集合における誤差を使用(ミニバッチ学習)
###実装演習結果
def numerical_gradient(f, x):
h = 1e-4
grad = np.zeros_like(x)
for idx in range(x.size):
tmp_val = x[idx]
x[idx] = tmp_val + h
fxh1 = f(x)
x[idx] = tmp_val - h
fxh2 = f(x)
grad[idx] = (fxh1 - fxh2) / (2*h)
x[idx] = tmp_val
return grad
def gradient_descent(f, init_x, lr=0.01, step_num=100):
x = init_x
for i in range(step_num):
grad = numerical_gradient(f, x)
x -= lr * grad
return x
###確認テストなどの考察
(問題)
オンライン学習とは何か
(回答)
サンプルを個別に選定して学習する手法→❌
(考察)
正しくは、学習データが入ってくる都度パラメータを更新する手法。一方で、バッチ学習は一度に全てのデータを用いてパラメータを更新する。
###コラム
微分の求め方は微小な変化量の差分による数値微分と数式の展開により求める解析的な微分に大別することができる。数値微分は計算上、誤差が発生しやすく、計算コストも高いというデメリットがあります。一方、解析的に微分することで、数値微分のデメリットを克服することが可能となります。
勾配降下法は勾配の最小値を求める手法でしたが、現実の損失関数のグラフは2次関数よりも複雑な場合が多いです。このため、関数の極小値や極大値または鞍点(平坦な場所)にパラメータが誤収束したり、学習が停滞することがあります。この学習が進まない状態を「プラトー」と言います。
##Section5:誤差逆伝播法
###要点のまとめ
- 勾配の計算を解析的に解く手法
- 入力から出力方向への計算を順伝播という
- 逆方向の計算を逆伝播という
- 誤差逆伝播法のメリットは誤差が分かれば、数値微分を行う必要がないこと
- 誤差逆伝播の計算には連鎖律という原理を利用する
- 誤差逆伝播の計算には連鎖律を用いる他に、計算グラフを用いて計算することもできる
###実装演習結果
class MulLayer:
def __int__(self):
self.x = None
self.y = None
def forword(self, x, y):
self.x = x
self.y = y
out = x * y
return out
def backword(self, dout):
dx = dout * self.y
dy = dout * self.x
return dx, dy
###確認テストなどの考察
(問題)
次の通式に対応するコードを書け
\cfrac{\partial E}{\partial y}\cfrac{\partial y}{\partial u}
(回答)
delta2 = functions.d_mean_squared_error(d, y)
(問題)次の通式に対応するコードを書け
\cfrac{\partial E}{\partial y}\cfrac{\partial y}{\partial u}\cfrac{\partial u}{\partial w_{ij}^{(2)}}
(回答)
grad['W2'] = np.dot(z1.T, delta2)
###コラム
ニューラルネットワークの順伝播では、行列の積を演算するが、この演算のことを「Affine変換」という。また、このAffine変換を全結合と呼ぶこともある。Affine変換は行列の演算となるため、変数同士の次元に注意しなければならない。必要に応じて行列を転置させて演算を行うこともある。
#【深層学習Day2】
##Section1:勾配消失問題
###要点のまとめ
- 勾配消失は誤差逆伝播法において、入力層に向かって微分回数が増えるほど勾配が小さくなる問題
- 中間層におけるパラメータの更新は勾配情報を基にしているため、勾配が小さいということはパラメータが更新されなくなる
- 勾配消失に影響を与える要因の一つに活性化関数があり、代表的な活性化関数であるシグモイド関数はこの勾配消失問題を起こしやすい
- 勾配消失問題対策として次の3つの工夫がある
- 活性化関数の選択(ReLU関数の登場)
- 重みの初期値設定(Xavierの初期値、Heの初期値)
- バッチ正規化(ミニバッチ単位で入力値のデータの偏りをなくす)
###実装演習結果
バッチ正規化実装コード
###確認テストなどの考察
(問題)シグモイド関数を微分し、0を代入した値はいくつか
(回答)0.25
(考察)
\begin{align}
\cfrac{d}{dx}\sigma(x=0)&=\cfrac{d}{dx}\cfrac{1}{1+exp(-(x=0)}\\
&=\cfrac{1}{1+exp(-(x=0))}\cfrac{1+exp(-(x=0)-1}{1+exp(-(x=0)}\\
&=\sigma(x=0)(1-\sigma(x=0))\\
&=0.5(1-0.5)\\
&=0.25
\end{align}
(問題)
重みの初期値を0にするとどのような問題が起きるか
(回答)
パラメータの更新がされなくなる→❌
(考察)
重みの初期値を0にするということは、全ての重みを均一化することに等しい。このため、パラメータ更新時に全ての重みが等しく更新されてしまい、重みを持つ意味がなくなってしまう。
(問題)
一般的なバッチ正規化の効果を2つ述べよ
(回答)
過学習を抑制することができる。初期値依存度が低くなる。
(考察)
バッチ正規化はミニバッチごとに正規化を行い、データの分布が平均0、分散1にすることです。また、バッチ正規化は学習が早く進むという効果もあります。これは、バッチ正規化により学習係数を大きくすることが可能となるためです。
###コラム
勾配消失問題に対する工夫の一つに重みの初期値設定がありました。初期値設定ではXavierの初期値やHeの初期値を使う手法があります。Xavierの初期値とは重みの初期値を1/${\sqrt{n}}$の標準偏差を持つ分布に初期化したものです。Xavierの初期値は線形の活性化関数を対象にしています。具体的にはシグモイド関数やtanh関数を指します。ここで、この2つの活性化関数が非線形ではないのかという疑問が生じますが、両者は左右対称のグラフであり、中央付近は直線的とみなせることからXavierの初期値が適していると言えます。一方で、Heの初期値は重みの初期値を2/${\sqrt{n}}$の標準偏差を持つ分布に初期化したものです。Heの初期値はReLU関数に適しています。
##Section2:学習率最適化手法
###要点のまとめ
- 学習率はパラーメータを更新する際に勾配の影響をどれだけ反映するかを決めるハイパーパラメータ
- 学習率が大きすぎる場合、最適値にたどりつかず発散してしまう
- 学習率が小さすぎる場合、学習が全然進まない
- つまり、学習率は最適化する必要がある
- 学習率の最適化の代表的な手法は次のとおり
- SGD
- デメリット:ジグザグな動きとなり、最適化効率が悪い
- Momentum
- メリット:SGDより滑らかかつ早く最適値に辿り着ける
- AdaGrad
- メリット:早く学習できるかつ学習係数を大きくしても発散しにくい
- デメリット:学習率が徐々に小さくなるため鞍点問題の可能性
- RMSprop
- メリット:学習を進めるほど更新されなくなるというAdagradの課題を克服
- Adam
- メリット:モメンタムとRMSpropを融合
- SGD
###実装演習結果
Optimizer実装コード
###確認テストなどの考察
(問題)
モメンタム、AdaGrad、RMSpropの特徴を簡潔に説明せよ
(回答)
####Momentum
メリット:SGDより滑らかかつ早く最適値に辿り着ける
####AdaGrad
メリット:早く学習できるかつ学習係数を大きくしても発散しにくい
デメリット:学習率が徐々に小さくなるため鞍点問題の可能性
####RMSprop
メリット:学習を進めるほど更新されなくなるというAdagradの課題を克服
###コラム
学習率の最適化手法はどの手法を用いるのが良いのか。結論は、問題に応じて使い分けるとなります。理由は、どのような問題にも万能の手法は今のところ無いからです。それぞれの手法には得意、不得意があるため、試行錯誤しながら最も効果のある手法を選択するのがベストな選択だと言えます。しかしながら、研究者や技術者の間ではAdamを好んで使っているということです。
##Section3:過学習
###要点のまとめ
- 過学習とは学習において訓練データに過度に適合する一方で、未知のデータに対して適合しない状態のこと
- 機械学習で目標としているのは未知のデータに対する汎化性能の向上であるので、過学習は防ぎたい
- 過学習が起きる原因の一つは、パラメータが大量で表現力が高すぎるもしくは値が適切でないこと
- もう一つの原因は、訓練データが不足していること
- 過学習を抑制するテクニックとして、Weightdecay(正則化)とドロップアウトの2つがある
- Weightdecayとは損失関数に罰則項を与えることで重みを抑制する手法
- ドロップアウトとはノードをランダムに削除しながら学習する手法
###実装演習結果
Weight_decay実装コード
Dropout実装コード
###確認テストなどの考察
(問題)
L1正則化を示すグラフはどれか
(回答)
(考察)
L1正則化はいくつかのパラメータが完全に0なるのが大きな特徴。
一方で、L2正則化は完全に0とはならないものの、0に近くなるという特徴がある。
###関連記事レポート
アンサンブル学習とDropoutには深い関連があります。まず、アンサンブル学習とは、学習時に複数のモデルを用いて学習し、推論時にその平均を出力します。このアンサンブル学習を行うことで、精度が数%向上するというメリットがあります。Dropoutという手法は、学習の過程でニューロンを削減しますが、ニューロンを削減するということは、別のモデルを作ることと等しいと言えます。従って、Dropoutは擬似的にアンサンブル学習を行なっていると言えます。
##Section4:畳み込みニューラルネットワーク
###要点のまとめ
- 畳み込みニューラルネットワークとは主に画像認識で用いられている識別に関する手法
- 通常のニューラルネットワークに加えて畳み込み層とプーリング層が登場
- 畳み込み層ではフィルターを介して、入力特徴マップを別の特徴マップに変換処理をしている
- 畳み込み処理の前には、出力サイズを調整するために入力データの周囲に固定のデータを埋めるパディングという処理を行うことがある
- 畳み込み処理において、フィルターを移動させる間隔のことをストライドと言い、ストライドを大きくすると出力サイズは小さくなる
- プーリング層では特徴マップのサイズを圧縮しており、具体的な手法としてMaxプーリングやAverageプーリングがある
###実装演習結果
CNN実装コード
###確認テストなどの考察
(問題)
サイズ6×6の入力画像を、サイズ2×2のフィルタで畳み込んだ時の出力画像のサイズを答えよ。なおストライドとパディングは1とする。
(回答)
7×7
(考察)
$O(H, W)=\cfrac{(H, W)+2P-F(F, W)}{S}+1$
###コラム
入力が3次元となる場合、チャンネルが追加される。例えば、画像データであればRGBの3チャンネルとなる。3次元となっても基本的な考え方は変わらない。
##Section5:最新のCNN
###要点のまとめ
-
入力において3×224×224の画像データに11×11のフィルターを用いて畳み込みを行なっている
-
2層目では96×55×55、3層目では256×27×27・・・といった畳み込みを5層行なっている
-
中間層の活性化関数はReLUを用いている
-
畳み込み処理後は全結合を行なっている
-
全結合にはFratten、Global MaxPooling、Global AveragePoolingといった手法があり、AlexNetではFrattenが用いられている
-
全結合層の出力にDorpoutを適用し、過学習を抑制している
###実装演習結果
AlexNet実装コード
###コラム
有名なデータセットの一つであるImageNetは、100万枚を超える画像のデータセットです。このデータセットはILSVRCという画像認識のコンペティションに用いられていました。2012年に開催されたILSVRCにおいて、AlexNetが画像認識において極めて優秀な成績を収めたことからディープラーニングの勢いが増してきたとも言われています。AlexNet登場以前のモデルでは誤差が25%以上あったのに対し、AlexNetは16.4%と格段に精度が向上しています。現在では人間の精度と言われている約5%を超える精度のモデルが登場しています。