下り坂:Gradient Descentと、誰もが飛ばす2つのステップ
学習率の厳密な上限を計算し、3,600方向の総当たり探索が、教えられずにgradientを再発見する様子を見ます。
このページの内容
前章は谷で終わりました。
比喩としての谷ではありません。実際の曲線です。損失を1つのパラメータに対してプロットすると、下がって底を打ち、また上がっていく。その下にある損失は、扱いやすいから選ばれたものではありません。測定ノイズについての仮定から導かれ、その結果として二乗誤差が現れました。慣習ではなく、帰結としてです。
つまり、底のある地形があり、その底こそが行くべき場所だと信じる理由もあります。まだないのは、そこへたどり着く方法です。
この章ではその方法を作ります。そしてそれは、このコースの残りで登場するすべてのモデルを訓練するアルゴリズムです。例外なくすべて、数千億パラメータを持つものまで含めてです。コードにすれば20行ほどに収まります。難しい部分はその20行の中にはありません。ほとんどすべての説明が飛ばす、次の2つです。
- なぜマイナス符号なのか。 更新ではgradientを引きます。どのチュートリアルもそう書きますが、なぜgradientが上りの方向なのかを説明するものはほとんどありません。この事実だけが、マイナス符号を信仰ではないものにします。
- どれだけ大きく進むのか。 「大きすぎると発散し、小さすぎると遅い」は正しく、そして役に立ちません。厳密な数値があります。損失から計算でき、この章ではそれを2回計算します。1回はおもちゃの放物線で、もう1回は実データでです。
設定、そしてなぜ単に探索できないのか
セクション「設定、そしてなぜ単に探索できないのか」へのリンクこの章だけで読めるように言い直します。第1章のコンベヤーベルトから来た8個の部品を使いますが、問うことを変えます。受け入れるか拒否するかではありません。それは後で戻ってきます。ここでは、部品の幅から重さを予測します。
import numpy as np
WIDTH = np.array([18.0, 19.5, 20.2, 21.0, 24.0, 25.5, 23.0, 26.0])
WEIGHT = np.array([47.0, 52.0, 49.0, 55.0, 61.0, 66.0, 70.0, 58.0])
x = WIDTH - WIDTH.mean() # 22.15 mm
y = WEIGHT - WEIGHT.mean() # 57.25 g測定値は中心化されています。第1章とまったく同じで、この章が終わる前にその理由は利子つきで戻ってきます。モデルは直線 で、損失は前章で導いた平均二乗誤差です。
パラメータは2つです。たくさん値を試せばよいのではないでしょうか。実際にやってみましょう。 から まで、 から までを、刻み幅 のグリッドで試します。
grid 501 x 1001 = 501,501 evaluations in 3.67 s
best found: a = 2.1000, b = -0.0000, L = 24.5924502つの数値を小数第2位まで突き止めるのに、50万回の評価が必要です。そしてその秒数は1台のマシンでの壁時計時間なので、再実行すれば3秒から6秒のどこかに落ちます。再現するのは評価回数と最小値です。この章の最後でgradient descentは、8ステップで小数第4位まで、36ステップでfloat64の完全な答えまで到達します。
しかし速度が論点ではありません。ここがコース全体を決めるポイントです。グリッド探索は、 個のパラメータそれぞれについて 個の値を試すなら、 回の評価を要します。各軸に1,000個の値があるとすると、こうなります。
| モデル | パラメータ | グリッド評価回数 |
|---|---|---|
| この直線 | 2 | |
| 第5章のXORネットワーク | 9 | |
| 小さな多層ネットワーク | 20,000 |
3行目は大きな数ではありません。意味を失った数です。観測可能な宇宙にある原子は、およそ 個です。探索はモデルが大きくなると遅くなるのではありません。存在できなくなります。以降のすべては、この表があるから存在します。
導関数は測定できる量である
セクション「導関数は測定できる量である」へのリンクひとまず を固定し、パラメータが1つ、曲線が1本だけの状態にします。前章が最後に残した絵です。その上の点 を取り、こう問います。 を小さな量 だけずらしたら、損失はずらし1単位あたりどれだけ動くでしょうか。
この比は上昇量を水平距離で割ったもの、つまり曲線上の2点を通る直線の傾きです。 が小さくなるにつれて、2点は互いに近づき、直線は接線になります。その傾きが導関数 です。 の変化1単位あたり、損失が変化する速さです。何かの近似ではなく、無限小の量でもありません。普通の比の極限です。
実行してみる価値があります。数字が、定義だけでは見えないことを語るからです。
def loss1(a):
return np.mean((a * x - y) ** 2)
for h in [1.0, 1e-2, 1e-4, 1e-6, 1e-8, 1e-10, 1e-12, 1e-14]:
q = (loss1(1.0 + h) - loss1(1.0)) / h
print(f"h = {h:<8.0e} slope estimate = {q:.10f} error = {abs(q + 16.385):.3e}")h = 1e+00 slope estimate = -8.9400000000 error = 7.445e+00
h = 1e-02 slope estimate = -16.3105500000 error = 7.445e-02
h = 1e-04 slope estimate = -16.3842555001 error = 7.445e-04
h = 1e-06 slope estimate = -16.3849925556 error = 7.444e-06
h = 1e-08 slope estimate = -16.3850003787 error = 3.787e-07
h = 1e-10 slope estimate = -16.3850444324 error = 4.443e-05
h = 1e-12 slope estimate = -16.3851154866 error = 1.155e-04
h = 1e-14 slope estimate = -17.0530256582 error = 6.680e-01ここでは2つのことが起きていて、どちらも本質的です。
誤差は に何となく比例しているのではありません。正確に です。 を100分の1にすると、誤差も100分の1になります。毎回、有効数字4桁までそうなります。この定数は飾りではありません。損失の2階導関数の半分であり、2つ先の節で出てくる考え方の初登場です。すなわち、点の近くの曲線は、直線に に比例する補正を加えたものに見える、という考え方です。
そしてパターンが壊れます。 より下では推定が悪くなり、 では2桁目から間違います。数学的なことが起きたのではありません。前章の浮動小数点の箱が起きました。 と は最初の10桁が一致し、それらを引き算するとその桁が破壊されます。残骸を小さな数で割ると、残った誤差が増幅されます。最適な があります。ここでは あたり、機械イプシロンの平方根くらいです。小さくするほど慎重になるのではありません。むしろ不慎重になります。覚えておいてください。この章の最後に出てくる関数が、それに依存します。
測定ではなく微積分から得る正確な傾きは です。これで測定をやめ、導出を始められます。
合成、そして連鎖律
セクション「合成、そして連鎖律」へのリンクこのコースの残りが依って立つ考え方を、ここで一度だけ、平明に述べます。
2つの関数を合成するとは、一方をもう一方に入力することです。。それ以上のことではありません。
深いネットワークは合成に似ているのではありません。合成そのものです。層は関数であり、層を積み重ねることはそれらを合成することです。「深さ」とは、その鎖に含まれる関数の数です。第5章でネットワークを作るとき、作っているのは であり、それ以外ではありません。つまり、私たちの目的にとって微積分で最も重要な規則は、合成を微分する規則です。
変化率は掛け合わされます。 が の3倍の速さで変化し、 が の2倍の速さで変化するなら、 は の6倍の速さで変化します。内容はそれで全部です。そしてそれが、10層を逆向きに通る信号が10個の数を掛けられる理由です。だから第6章では、それらの数がすべて1より少し小さいと何が起きるかに1節を費やします。
これを私たちの損失に使います。残差を と書くと、 です。各 は、内側の関数 を通じて に依存し、その導関数は です。項ごとに連鎖律を適用します。
波打った の記号は偏導関数を表します。1つの変数について微分し、他のすべてを定数として扱うということです。新しいことは何も起きません。前と同じ極限を、1つの軸に沿って取っているだけです。偏導関数をベクトルにまとめると、gradientが得られます。
点 で、このベクトルは です。2つの数です。問題は、それが何を意味するかです。そしてここが、誰もが飛ばす最初のステップです。
なぜgradientは上りを向くのか
セクション「なぜgradientは上りを向くのか」へのリンクgradientは、軸に沿った傾きのベクトルです。ここまでで証明したのはそれだけです。それらをベクトルに組み立てると、どこか特定の方向を向く、というのは自明ではありません。自明であってはいけません。
そこで、私たちが本当に欲しいものを定義します。単位ベクトル 、つまり方向を1つ選びます。方向微分とは、その方向に歩いたときに損失が変わる速さです。
連鎖律により、これは計算可能なものになります。 に沿って歩くと、 は の速さで、 は の速さで変わり、それらの寄与が足し合わされます。
任意の方向の変化率は、gradientとその方向の内積です。そして結論は、幾何の1行です。2つのベクトルの間の角度を として内積を書くと、
の長さは1なのでこうなります。あなたが制御できるのは だけです。これは で最大になり、半回転した 度で最小になります。つまり、
- 最急上昇は そのものの方向で、その傾きは正確に です。
- 最急下降は の方向で、その傾きは です。
- gradientに垂直な方向では、損失はまったく変わりません。等高線図の線がgradientと直角に交わるのはそのためです。
これがマイナス符号です。慣習ではなく、誰かが選んだ符号反転でもありません。最速で減少する方向が負のgradientであるのは、 が半回転で最小化されるからであり、それ以外の理由はありません。
これは全方向についての主張なので、全方向に対してテストします。3,600方向を、0.1度ごとに1つずつサンプリングし、それぞれを少しずらして測ります。
theta = np.array([1.0, 4.0])
g = grad(theta)
print("gradient ", g)
print("its length ", np.linalg.norm(g))
print("its angle ", np.degrees(np.arctan2(g[1], g[0])) % 360, "degrees")
best = max(
((loss(theta + 1e-6 * u) - loss(theta - 1e-6 * u)) / 2e-6, np.degrees(ang))
for ang, u in (
(a, np.array([np.cos(a), np.sin(a)])) for a in np.arange(3600) * 2 * np.pi / 3600
)
)
print("steepest slope", best[0], "at", best[1], "degrees")gradient [-16.385 8. ]
its length 18.23371122399386
its angle 153.97598928042032 degrees
steepest slope 18.233709624837502 at 154.0 degreesgradientについて何も知らない探索が、3,600方向の中から最も急な上りを154.0度に見つけます。探索の0.1度の解像度の範囲で、gradient自身の方向です。そしてそこで見つけた傾き18.2337は、gradientの長さと6桁一致します。この定理はgradientが何を意味するかについての物語ではありません。測定可能な事実であり、これがその測定です。
なぜ下りの小さな一歩は本当に効くのか
セクション「なぜ下りの小さな一歩は本当に効くのか」へのリンク次は2つ目の飛ばされがちなステップです。どちらが下りかは分かりました。しかし、その方向に歩けば損失が下がるとは限りません。「下り」は無限小のずらしについての発言であり、ステップは無限小ではないからです。
橋渡しになるのが線形化です。滑らかな関数は、ある点の近くでは接線に補正を加えたものです。
これは1次のTaylor展開です。捨てられた が曲率です。傾きの表の推定を正確に だけ間違わせた、あの項です。これから取るつもりのステップ を入れます。
損失は だけ下がります。その各部分は非負なので、約束は本物です。ただし、十分小さい に対してです。無視した項は のように増え、やがてそれを食い尽くすからです。理論はこれで全部です。約束が守られ、そして破られる様子を見ます。
eta = 0.2 promised 66.49364500 delivered -16.01619240 ratio -0.240868
eta = 0.1 promised 33.24682250 delivered 12.61936315 ratio 0.379566
eta = 0.01 promised 3.32468225 delivered 3.11840766 ratio 0.937957
eta = 0.001 promised 0.33246822 delivered 0.33040548 ratio 0.993796
eta = 0.0001 promised 0.03324682 delivered 0.03322620 ratio 0.999380
eta = 1e-05 promised 0.00332468 delivered 0.00332448 ratio 0.999938下から読みます。 が小さくなるにつれ、実際に得られた低下量は約束された低下量に収束します。比は0.99938、次に0.99994です。Taylorの定理が正しいということです。上から読むと、 では実際の「低下量」はマイナス16です。ステップは下りに進んだのに、損失は上がりました。
したがって更新規則は
です。そして誰も述べない条件が付いています。 が十分小さいことです。では、正確には何と比べて十分小さいのでしょうか。次の節です。
学習率には上限があり、それは計算できる
セクション「学習率には上限があり、それは計算できる」へのリンク最も単純な谷 から始めます。ここで です。gradient descentの1ステップは
です。
位置は各ステップで 倍されます。これは等比数列です。そして等比数列には規則が1つだけあります。倍率の絶対値が1より小さいと縮み、そうでなければ成長します。したがって 、つまり です。
境界は正確に です。 「1くらい」ではなく、「1はたいてい大きすぎる」でもありません。 では倍率が となり、点は と の間を永遠に跳ね返ります。近づくことも逃げることもありません。それ未満なら収束し、それを超えると発散します。この区間は でもう一度分かれます。そこで倍率の符号が変わるからです。それ未満では単調に近づき、それを超えると点は行き過ぎて左右を交互に移ります。ちょうど では倍率が0になり、たった1ステップで最小値に着地します。
4行の代数から4つの領域が出ます。自分で境界を越えてみてください。
そして興味深いものがこちらです。
一般則も、同じ議論から出てきます。倍率 は実は であり、最小値の近くでは、多パラメータの損失に方向ごとにそのような数が1つあります。2階導関数の行列の固有値です。すべての方向が同時に安定でなければならないので、上限は最大のものによって決まります。
では 、上限は1で、これは今導いた通りです。私たちのベルトでは、2階導関数の行列は で、 は入力の2列行列です。その固有値は2と14.89なので、上限は です。これは有効数字5桁を持つ予測です。テストします。
lr=0.1343 -> L = 24.5924
lr=0.13431 -> L = 24.5924
lr=0.13432 -> L = 4707.8 BLEW UP
lr=0.13433 -> L = 4.00452e+16 BLEW UP
lr=0.1344 -> L = 1.18229e+107 BLEW UP線形代数の1行と、for ループ10万回との一致は小数第5位までです。
そしてここで第1章が戻ってきます。 ここまでのすべては中心化された測定値を使っていました。生のミリメートルとグラムに対して同じコードを実行すると、固有値は2と14.89ではなく、0.0298と998.1になります。上限は0.134から0.002004へ崩れます。同じく厳密に、lr=0.002003 では収束し、lr=0.002004 では吹き飛びます。
上限より悪いのが、固有値同士の比です。条件数は、谷がどれほど丸くないかを測ります。長く細い溝では、急な壁に合わせて率を小さくせざるを得ず、その同じ遅さで溝の床を歩くことになります。私たちの場合、中心化では7.44だったものが、生では33,452になります。それぞれが取れる最良の率を使うと、こうなります。
| 特徴量 | 条件数 | 最良の率 | 最適値の1%以内に到達するステップ数 |
|---|---|---|---|
| 中心化 | 7.44 | 0.1184 | 10 |
| 生のミリメートルとグラム | 33,452 | 0.0020037 | 79,513 |
同じデータ、同じコード、最後の答えも同じです。ただし平均を引かなかっただけで、作業量は8,000倍です。第1章では、同じ省略がパーセプトロンにエポック数6,000倍の代償を払わせました。そこでの診断は幾何でした。データが原点から遠く浮いていたのです。ここでも同じ幾何が、最適化の衣装を着て現れています。だから入力の正規化は衛生上の助言ではなく、算術なのです。1
ここまでのことにライブラリは不要でした。これがoptimiser全体です。
def loss(theta):
a, b = theta
return np.mean((a * x + b - y) ** 2)
def grad(theta):
a, b = theta
residual = a * x + b - y
return np.array([np.mean(2 * residual * x), np.mean(2 * residual)])
def descend(theta, lr, steps):
theta = np.array(theta, dtype=float)
for _ in range(steps):
theta = theta - lr * grad(theta)
return theta
theta = descend([0.0, 0.0], lr=0.05, steps=60)
print(theta, loss(theta))[ 2.10040296e+00 -2.76445533e-15] 24.592448791134984この8点に対する閉形式の最小二乗解は 、 で、損失は です。ループは、閉形式が存在することを知らないまま、有効数字8桁までそれを見つけました。これが重要なのは、第5章以降では閉形式が存在しないからです。
軌跡です。見ることこそが要点です。
0 a=0.000000 b=0.000000 L=57.437500
1 a=1.563750 b=0.000000 L=26.736582
2 a=1.963288 b=-0.000000 L=24.732418
5 a=2.098116 b=-0.000000 L=24.592488
10 a=2.100400 b=-0.000000 L=24.592449
60 a=2.100403 b=-0.000000 L=24.592449距離の大半は最初の2ステップで進みます。底から遠いほどgradientが大きく、近づくほど小さくなるからです。gradient descentは最小値の近くで自動的に遅くなります。それは機能であり、第6章では問題でもあります。
傾きがゼロになる別の場所
セクション「傾きがゼロになる別の場所」へのリンクここまでの議論には穴があります。ステップは で止まり、私たちはそれを「最小値」と呼んできました。gradientがゼロの点は臨界点であり、最小値であることは、その一種にすぎません。
- 局所最小値:どの方向にも上りだが、全体で最も低い点とは限らない。
- 局所最大値:どの方向にも下り。
- 鞍点:ある方向では上り、別の方向では下り。曲面 は を持ち、これは原点でゼロです。そこでは関数は 軸に沿っては最小であり、同時に 軸に沿っては最大です。
gradient descentはこれらを区別できません。見るのは常にgradientだけであり、3つすべてでgradientはゼロだからです。
私たちの直線には臨界点が1つだけあり、それが答えです。線形モデル上の二乗誤差損失は凸で、単一のボウルであり、その上の降下は大域最小値を見つけ損ねることがありません。この性質は、このコースと接触すると生き残りません。ニューラルネットワークの損失は凸ではありません。第5章以降、「その最小値」というものは存在しません。深さの異なる多数の最小値があり、どれを得るかは開始点に依存します。これは1文であり、1文のままにします。理論は大きく、実用上の帰結は小さいからです。
その帰結全体は1本の曲線で見られます。深さの異なる2つの谷を持つ を取ります。
x = -1.046681 f(x) = -0.352386 minimum
x = 0.101031 f(x) = 0.005026 maximum
x = 0.945649 f(x) = -0.152639 minimum浅い谷に着地すると、損失は56.7%悪くなります。そしてアルゴリズムにはそれを知る方法がありません。谷の内側から見れば、どの方向も上りだからです。gradient descentにこれを修理する方法はなく、これからも出てきません。実際にあるのは、これがこの図から想像するほど重要ではない、という発見です。実ネットワークの非常に高い次元では、ほとんどの臨界点は罠ではなく鞍点であることが分かっています2。第5章では、小さなネットワークが実際にどれほど頻繁に詰まるかを測ります。
より安いステップ:確率的、minibatch、momentum
セクション「より安いステップ:確率的、minibatch、momentum」へのリンク上の grad について、気になるべきことが1つあります。すべてのステップでデータセット全体にわたって和を取っていることです。8個の部品なら何でもありません。100万個なら、パラメータを1回動かすのに100万回のgradient計算です。
逃げ道は、gradientが平均であり、平均はサンプルから推定できるという点です。ランダムな少数、つまりminibatchで計算し、それでステップします。推定はノイズを含みます。しかし不偏でもあり、高価で正確な1ステップより、安くてノイズの多い数百ステップの方が勝ちます。10万個の合成部品で、ステップ数ではなく例ごとのgradient数を数えると、こうなります。
| 手法 | 最適値の0.1%以内に到達するステップ数 | 例ごとのgradient数 |
|---|---|---|
| full batch | 7 | 700,000 |
| minibatch of 32 | 100 | 3,200 |
| 1例ずつ | 17,580 | 17,580 |
同じ場所に到達するのに、算術量は219分の1です。そして極端な場合、つまり1例ずつの処理、RobbinsとMonroの元の確率近似3は、勝者ではありません。32個のbatchより5倍悪いのです。行列を掛けるハードウェアでは32例は1例よりほとんど高くつかず、一方でノイズはbatchサイズの平方根で減るからです。このトレードオフこそ、あなたがこれから読むあらゆる訓練スクリプトに batch_size が含まれる理由です。
Momentumはもう1つの安い修正で、狙いはまさに溝です。条件の悪い谷では、ステップは狭い方向をジグザグに横切りながら、長い方向にはゆっくり進みます。Momentumは過去のgradientの移動平均を保つので、振動する成分は打ち消され、一貫した成分は蓄積します。4
追加は2行です。中心化していない生のベルト、条件数33,452という、私たちが持つ最悪ケースで、通常の降下が取れる最良の率を使うと、
momentum beta=0.0 -> 79,513 steps to 1%
momentum beta=0.9 -> 1,609 steps to 1%
momentum beta=0.99 -> 461 steps to 1%2行のコードで172倍です。第6章ではこれがAdamになります。仕組みはすでにここにあります。
第5章で必要になるチェック
セクション「第5章で必要になるチェック」へのリンクこの章のすべてのgradientは手で導出したので、間違っている可能性があります。修正は冒頭の傾き表です。導関数を数値的に測り、比較します。中心差分 を使います。これは主要な誤差項を打ち消し、同じ でずっと高精度です。
def numeric_grad(f, theta, h=1e-5):
theta = np.asarray(theta, dtype=float)
out = np.zeros_like(theta)
for i in range(theta.size):
bump = np.zeros_like(theta)
bump[i] = h
out[i] = (f(theta + bump) - f(theta - bump)) / (2 * h)
return out
def gradcheck(f, df, theta, h=1e-5):
analytic = np.asarray(df(theta), dtype=float)
numeric = numeric_grad(f, theta, h)
return np.max(np.abs(analytic - numeric) / np.maximum(1e-8, np.abs(analytic) + np.abs(numeric)))比較では相対形式が重要です。 の絶対差は、大きさ のgradientでは大惨事ですが、大きさ のgradientでは無関係です。
relative error: 1.8929136036763527e-11
with 2 dropped: 0.333333333316507441行目は上で手で導いたgradientです。2行目は、片方の成分で2倍の係数を落とした同じ関数です。たった1文字のタイプミスですが、チェックは即座に捕まえます。およそ 未満なら一致、 を超えればバグです。この関数を残しておいてください。第5章ではautomatic differentiationエンジンのデバッグに使います。そして、間違ったgradientをそもそも見つけられる唯一の理由です。
次に向かう先
セクション「次に向かう先」へのリンクこの章のすべては、明言されなかった1つの仮定に支えられていました。 を書き下せる、という仮定です。
2パラメータの直線なら、それは代数1行でした。ほとんどすぐに、そうではなくなります。シンボリック代数システムに、ネットワークの損失を単一の第1層の重みに関して、単一の例について微分させ、その答えに含まれる演算を数えると、こうなります。
| ネットワーク | 1つの偏導関数に含まれる演算 |
|---|---|
| 隠れユニット4個、1層 | 40 |
| 隠れユニット4個、2層 | 301 |
| 隠れユニット4個、3層 | 1,717 |
3行目は57パラメータのネットワークです。第6章なら脚注にしかならないほど小さいネットワークです。それでも、そのgradientを手で書き出すとは、1つの訓練例につき約97,869演算を意味します。これを救う記法はありません。救うのは、合成に連鎖律を適用すると巨大な構造が現れるという観察です。同じ中間量が何度も現れ、それらを正しい順序で計算すれば、1回のforward passとおおよそ同じ代価ですべての導関数が得られます。それが第5章です。
しかしその前に、もっと小さな問題があり、すぐ先で待っています。
いま私たちは、任意の微分可能な損失の上を下り坂に転がる機械を手にしました。それをベルトの元の問い、つまり受け入れるか拒否するか、targetが1または0である問題に向けます。出力にシグモイドを付けて確率を予測させ、二乗誤差を最小化します。動きます。しかし最も間違っているときに、ほとんど動きません。gradientがその理由を示します。
| 出力 | 予測 | 真値 | 二乗誤差でのgradient | cross-entropyでのgradient |
|---|---|---|---|---|
| 0.5000 | 1 | |||
| 0.1192 | 1 | |||
| 0.0025 | 1 | |||
| 1 |
答えが1なのに0.0000454と予測する、自信満々で破滅的に間違ったモデルが、二乗誤差では のgradientしか出しません。自分が困った状況にいることをまったく理解していません。まだ導いていない損失から来るもう一方の列は、1.0を報告します。最大の緊急度です。まさにそれがふさわしい場所で。
ここで、次章が冒頭で扱う問いが立ち上がります。前章は、損失とはノイズについての仮定だと言いました。そして二乗誤差はガウスノイズを仮定します。では、はい・いいえの答えにはどんなノイズモデルがあり、同じ導出をそれに適用すると、どんな損失が出てくるのでしょうか。
出典と方法
セクション「出典と方法」へのリンクこの方法は、これらすべてより古いものです。Cauchyは1847年にAcadémie des Sciencesへのノートで、残差二乗和の上を下り坂に歩くことで方程式系を解く方法として記述しました。この章と並べて読む価値があるものとして、Sebastian Ruderの An overview of gradient descent optimization algorithms(arXiv:1609.04747)があります。momentumからAdamまでを読みやすい14ページで扱っています。Nocedal and Wrightの Numerical Optimization(第2版、Springer、2006)の第3章も有用です。定理3.3は、二次関数上の最急降下の収束率を条件数で与えており、条件付けがステップ数を決める理由の背後にある理論です。ただし、ここで測定した固定ステップの 上限ではなく、line searchを扱っています。同じ範囲を少ない装置で学ぶなら、Deisenroth, Faisal and Ongの Mathematics for Machine Learning の§5.8と§7.1もあります。Princeの Understanding Deep Learning §6.1、Goodfellow, Bengio and Courvilleの Deep Learning §4.3、そして Dive into Deep Learning §12.1–12.3もあります。後者は、ここに入れる余地がないほど多くの測定とともにminibatch分析を扱っています。Géronの Hands-On Machine Learning(第3版)第4章は、学習率を導出するものではなくチューニングするものとして扱う、最も実践的な説明です。MIT 6.390のノートは、このコースと同じく、分類の前にgradient descentを置いています。理由も同じです。
参考文献
セクション「参考文献」へのリンク-
LeCun, Y., Bottou, L., Orr, G. B. and Müller, K.-R. Efficient BackProp, in Neural Networks: Tricks of the Trade (Springer, 1998), pp. 9–50. 4.3節は推奨を、5.1節は上の詳細ボックスで使った議論を与えています。入力を中心化・スケーリングすると、2階導関数行列の固有値が変わり、したがってステップ数が変わります。単なる数値上の快適さではありません。 ↩
-
Dauphin, Y. N., Pascanu, R., Gulcehre, C., Cho, K., Ganguli, S. and Bengio, Y. Identifying and attacking the saddle point problem in high-dimensional non-convex optimization, arXiv:1406.2572 (2014). 高次元では臨界点の圧倒的多数が局所最小値ではなく鞍点である、という議論です。最小値であるには、何千もの方向すべてが同時に上向きに曲がっていなければならないからです。 ↩
-
Robbins, H. and Monro, S. A Stochastic Approximation Method. Annals of Mathematical Statistics 22(3), pp. 400–407 (1951). 適切に縮むステップサイズがあれば、gradientのノイズを含む推定で十分であることを確立した論文です。 ↩
-
Polyak, B. T. Some methods of speeding up the convergence of iteration methods. USSR Computational Mathematics and Mathematical Physics 4(5), pp. 1–17 (1964). heavy-ball法です。これは上のmomentum更新であり、backpropagationがこの分野に届く22年前のものです。 ↩