損失関数はどこから来るのか:慣習ではなく likelihood
同じ20個の測定値に目で引いた3本の直線。3つの採点ルールが別々の勝者を選ぶ。二乗誤差は選択です。
このページの内容
部品を切る刃は摩耗していきます。10時間のシフトのあいだに刃先は十分になまり、ベルトから出てくる部品は最初よりほんの数分の1ミリメートル広くなります。そして23.5ミリメートルを超えると検査ではねられます。工場の誰も、それがいつ起きるのかを知りません。手元にあるのはノギスとノート、そして先週火曜日の20個の読み取り値だけです。刃を交換してからの経過時間と、その時点で測った部品の幅です。
誰かが点のあいだに線を引きます。別の誰かが少し違う線を引きます。3人目が3本目を引きます。紙の上では3本とももっともらしく見えますが、刃をいつ交換するべきかについては数時間も食い違います。この工場では、それが静かな一週間と廃棄されるバッチの差になります。
どの線がよりよいのでしょうか。
このままでは、その問いに答えはありません。難しい答えではなく、答えがまったくないのです。「よりよい」は傾きのように直線そのものの性質ではありません。直線と、直線を採点するルールが組になって初めて持つ性質です。誰かがそのルールを書き下すまでは、計算するものがありません。この章ではその一文を本気で受け止め、machine learningで最も一般的なルールが慣習ではなく、世界についてのある主張の帰結であることを見つけます。その主張は検証でき、そしてときどき間違っています。
最初のコードに入る前に、ひとつ告白しておきます。この20個の読み取り値は実際の工場から来たものではありません。私が選んだ直線 に、およそ0.1ミリメートルの広がりを持つランダムノイズを足して生成しました。これは重要です。以下のすべては、ある方法が真実を回収できるかどうかについてであり、それを確かめる唯一の方法は、あらかじめ真実を知っていることだからです。つまり、巻末の答えは1時間あたり0.30ミリメートルです。使ってはいけません。照合するためだけに使えます。
3つのルール、3人の勝者
セクション「3つのルール、3人の勝者」へのリンク読み取り値と3本の直線を、3つの方法で採点してみます。誰もがまず手を伸ばす二乗誤差、統計家なら選びそうな絶対誤差、そして機械工が選ぶであろう最大誤差です。検査員はあなたの平均など気にしません。公差外の1個をはねるだけです。
NumPyは、pure-Pythonのperceptronから1章遅れてここで登場します。理由はひとつだけです。この章の終わりまでに、40万本の候補直線を、それぞれ20個の読み取り値に対して評価します。その作業にPythonのループは向いていません。また、以下で引用するあらゆる資料が書かれている表記でもあります。
import numpy as np
# Hours since the blade was changed, and the width of the part measured then.
SHIFT = np.array([
(0.5, 20.17), (1.0, 20.28), (1.5, 20.53), (2.0, 20.61), (2.5, 20.69),
(3.0, 20.94), (3.5, 21.21), (4.0, 21.31), (4.5, 21.27), (5.0, 21.35),
(5.5, 21.58), (6.0, 21.80), (6.5, 21.67), (7.0, 22.07), (7.5, 22.10),
(8.0, 22.31), (8.5, 22.48), (9.0, 22.66), (9.5, 22.90), (10.0, 23.13),
])
h, y = SHIFT[:, 0], SHIFT[:, 1]
LINES = {"A": (20.10, 0.26), "B": (20.20, 0.28), "C": (20.30, 0.26)}
for name, (a, b) in LINES.items():
r = y - (a + b * h)
print(f"{name} mean square {np.mean(r**2):.5f}"
f" mean absolute {np.mean(np.abs(r)):.5f}"
f" worst {np.max(np.abs(r)):.3f}") ハイライトした行の量は残差です。直線が言った値からノギスが言った値を引いたもの、読み取り値ごとに1つの数です。この章のすべての採点ルールも、その後28章に出てくるすべての損失関数も、残差のリストを1つの数に押しつぶす何らかの方法です。違うのは、どう押しつぶすかだけです。
A mean square 0.02699 mean absolute 0.12600 worst 0.430
B mean square 0.02524 mean absolute 0.13700 worst 0.350
C mean square 0.03179 mean absolute 0.15000 worst 0.320行ではなく列を読んでください。二乗誤差はB、絶対誤差はA、最大誤差はCを選びます。同じ20点に対して、3つのルール、3人の勝者です。
この3本の直線は、食い違うように私が選びました。そのことははっきり言っておくべきです。重要なのは、それがどれほど簡単だったかです。もっともらしい切片と傾きを数分探索するだけで、このような三つ組は何百も見つかります。順位はあなたが選んだルールの性質であって、直線についての事実ではありません。だからルールは実装の細部ではありません。ルールこそが問題の定義です。そこで、この章が答えるために存在する問いが出てきます。何を根拠にそのルールを選ぶのでしょうか。
1つのパラメータと谷
セクション「1つのパラメータと谷」へのリンクまず小さな問題から始めます。直線は3本ではなく無限にあるからです。ひとまず二乗誤差を使います。誰もがそうするものだからです。そして、第1章でperceptronから1万1000epochを節約したトリックを使い、問題を1つの数に縮めます。両方の列から平均を引くのです。点群が原点を中心に来ると、二乗誤差のもとで最良の直線は原点を正確に通ります。したがって切片は決まり、残る選択は傾きだけです。
u, v = h - h.mean(), y - y.mean() # 5.25 hours, 21.553 mm
def mse(theta):
return np.mean((v - theta * u) ** 2)
grid = np.arange(0.0, 0.6001, 0.001)
curve = np.array([mse(t) for t in grid])
print(grid.size, "candidates ->", f"theta={grid[curve.argmin()]:.3f}", f"mse={curve.min():.6f}")601 candidates -> theta=0.293 mse=0.010115601個の候補傾き、1つの勝者。真実0.300に対して、1時間あたり0.293ミリメートルです。20個のノイズ入り読み取り値とfor-loopで、1時間あたり100分の1ミリメートル以内、つまり2.3%まで近づきました。
面白いのは勝者ではなく、探索の形です。損失が左から右へ走るように全体の曲線を回転して表示します。
ts = np.arange(0.0, 0.6001, 0.04)
ls = np.array([mse(t) for t in ts])
for t, l in zip(ts, ls):
col = round(l / ls.max() * 50)
print(f"theta={t:.2f} |{' ' * col}*{' ' * (50 - col)}| mse={l:7.4f}")theta=0.00 | * | mse= 0.7244
theta=0.04 | * | mse= 0.5428
theta=0.08 | * | mse= 0.3878
theta=0.12 | * | mse= 0.2593
theta=0.16 | * | mse= 0.1575
theta=0.20 | * | mse= 0.0822
theta=0.24 | * | mse= 0.0336
theta=0.28 | * | mse= 0.0116
theta=0.32 | * | mse= 0.0161
theta=0.36 | * | mse= 0.0473
theta=0.40 | * | mse= 0.1050
theta=0.44 | * | mse= 0.1894
theta=0.48 | * | mse= 0.3004
theta=0.52 | * | mse= 0.4379
theta=0.56 | * | mse= 0.6021
theta=0.60 | *| mse= 0.7928横から見た谷です。底は1つで、両側の壁はなめらかに上がっています。そして、第1章の階段にはなかったことですが、その上のあらゆる点で「下り坂」の向きがきちんと定まっています。この形を覚えておいてください。第3章は、601点すべてを訪れずにこの谷を下る話と、谷に底が複数あると何が変わるかの話に丸ごと使います。
では、なぜ二乗するのか
セクション「では、なぜ二乗するのか」へのリンク二乗したから谷があります。絶対誤差なら底に折れ目ができます。最大誤差なら、直線を動かしても何も変わらない平らな区間ができます。二乗が便利であることは否定できません。そして多くの講義が与える理由は、だいたいその便利さです。4通りに着飾ってはいます。誤差を正にする(絶対値でもできます)。大きな誤差をより罰する(なぜそうすべきなのでしょうか)。微分可能である(4乗もそうです)。みんなが使っている(たしかにそうですが、それは論拠ではありません)。
正直な立場はこうです。二乗誤差は直線Bを選び、絶対誤差は直線Aを選びました。この工場にとってそのどちらかは正しく、もう片方は間違っています。そしてここまで述べたことだけでは、どちらかを教えてくれません。ルールを選ぶには、読み取り値がどのように直線からずれたのかについて何かを知る必要があります。それは数学についての問いではなく、世界についての問いです。それに答えるには、小さな道具立てがひとつ必要です。
直線の likelihood
セクション「直線の likelihood」へのリンク「どの直線がよりよいか」を、答えのある問いに変える主張はこれです。
部品の幅は直線にランダム誤差を足したものだと仮定します。そして、その誤差は平均0、標準偏差 のGaussian、つまりベル曲線から引かれると仮定します。
Gaussianの密度は
ここでperceptronにはできなかったことをします。ある候補傾き が与えられたとき、すべての読み取り値には残差があります。上の式は、その残差を1つの数に変換します。この傾きが真実だとしたら、ちょうどその大きさの誤差はどれくらいもっともらしいか、という数です。直線上の読み取り値は大きな数になり、0.5ミリメートル外れた読み取り値は小さな数になります。
読み取り値は独立です。ノギスは前の部品を覚えていません。したがって積の法則により、ノート全体のもっともらしさは、個々の密度の積です。この積が のlikelihoodです。1 向きに注意してください。Bayesの規則が問題にしている向きだからです。dataは固定され既知であり、変わるのはパラメータです。これは「傾きの確率」ではありません。実際に得られたdataにmodelが割り当てる確率を、傾きの関数として読んだものです。
SIGMA = 0.12
def gaussian(r, sigma):
return np.exp(-r ** 2 / (2 * sigma ** 2)) / (sigma * np.sqrt(2 * np.pi))
def likelihood(theta):
return np.prod(gaussian(v - theta * u, SIGMA))
for t in (0.25, 0.293, 0.35):
print(f"theta={t} likelihood = {likelihood(t):.6g}")theta=0.25 likelihood = 521.952
theta=0.293 likelihood = 2.42028e+07
theta=0.35 likelihood = 0.190312傾き0.293は、このノートを0.25より4万6000倍もっともらしくし、0.35より1億2700万倍もっともらしくします。Maximum likelihoodとは、実際に観測したものをできるだけ驚きの少ないものにするパラメータを選ぶ、という原理です。これは定理ではなく、「最良」が何を意味すべきかについての提案です。そして中身のある提案です。何かを採点してよいことになる前に、ノイズについての仮定を明言させるからです。
積は壊れる
セクション「積は壊れる」へのリンク同じ3行のコードを、1シフトではなく1か月分のシフトに対して走らせると、方法は倒れます。
rng = np.random.default_rng(7)
u_big = rng.uniform(-5.25, 5.25, 2000) # 2000 readings, not 20
v_big = 0.30 * u_big + 0.12 * rng.standard_normal(2000)
print("2000 readings, sigma = 0.12 mm :", np.prod(gaussian(v_big - 0.30 * u_big, 0.12)))
noisy = 0.30 * u_big + 2.0 * rng.standard_normal(2000)
print("2000 readings, sigma = 2.00 mm :", np.prod(gaussian(noisy - 0.30 * u_big, 2.0)))
print("largest float64 :", np.finfo(np.float64).max)RuntimeWarning: overflow encountered in reduce
2000 readings, sigma = 0.12 mm : inf
2000 readings, sigma = 2.00 mm : 0.0
largest float64 : 1.7976931348623157e+3082000回の掛け算の答えは inf です。定数を1つ変えます。ノギスがより雑で、密度が1より大きくなく小さく出るようにします。すると同じコードは 0.0 を返します。どちらの答えも間違っていて、向きは正反対です。どちらも捕まえられる例外を投げず、2つ目は警告すら表示しません。
数学には何も問題がありません。その設定でのlikelihoodは、完全に定義された有限の数です。その自然対数は1400.91なので、数そのものはおよそ です。問題は、あなたのコンピュータがその数を持っていないことです。そして、どの数なら持っているのかを正確に理解する価値があります。結果をコンピュータが決めてしまうのは、今回が最後ではないからです。
二乗はどこから来るのか
セクション「二乗はどこから来るのか」へのリンク爆発する積の修正はいつものものです。対数を取ります。対数は積を和に変え、厳密に増加するので最大の位置を動かせず、2000個の穏やかな数の和ならfloat64は文句なく扱えます。慣例として負のlog-likelihoodを取ります。良いほど小さい、にするためです。ここでGaussian密度を代入し、何が起きるかを見ます。
-
積から始める。 likelihoodは で、 は上のGaussian密度です。
-
マイナスのlogを取る。 積は和になり、密度の中の指数関数は対数と正面から打ち消し合います。
- を含まないものをすべて捨てる。 第1項は定数です。和の前の は正の定数であり、関数に正の定数を掛けても最小の位置は動きません。残るのは
で、これは残差平方和です。この章の最初に出てきた、誰もが最初に思いつくものです。
これこそがこの章のための結果であり、遠慮なく述べる価値があります。二乗誤差は慣習ではありません。定数を取り除いたGaussianの負のlog-likelihoodです。 二乗誤差を最小化することは、あなたの誤差がGaussianであると主張し、どのパラメータがdataを最も驚きの少ないものにするかを問う行為と正確に同じです。あなたはずっとその主張をしていました。ただ、そう教えられていなかっただけです。
同値性は確かめられるので、確かめます。同じ601個の傾きを、定数込みの完全な負のlog-likelihoodと、素朴な二乗誤差でscanします。
N = v.size
def nll(theta):
r = v - theta * u
return N * np.log(SIGMA * np.sqrt(2 * np.pi)) + np.sum(r ** 2) / (2 * SIGMA ** 2)
nlls = np.array([nll(t) for t in grid])
mses = np.array([mse(t) for t in grid])
print(f"argmin of the negative log-likelihood : theta={grid[nlls.argmin()]:.3f} nll={nlls.min():.6f}")
print(f"argmin of the mean squared error : theta={grid[mses.argmin()]:.3f} mse={mses.min():.6f}")
print("same index:", nlls.argmin() == mses.argmin())argmin of the negative log-likelihood : theta=0.293 nll=-17.001977
argmin of the mean squared error : theta=0.293 mse=0.010115
same index: True縦軸の数値は違い、片方は負です。平方和は決して負になりませんが、負のlog-likelihoodは0を下回ることがあります。密度は1を超えられるからです。同じ谷の同じ底であり、最後のgrid点まで一致します。
導出過程をすべて表示
正確には、どの捨て方が安全なのでしょうか。同じ手口は、損失を導くすべての章に現れますが、いつも無害とは限りません。
加法定数を落とすのは、それが最適化しているパラメータに依存しないとき常に安全です。正の乗法定数を落とすのも安全です。任意の について だからです。どちらも、 もfitしている瞬間に失敗します。そのとき はまったく定数ではなく、modelが と無限のもっともらしさを主張するのを止める項です。まさに次の節がそれです。
第3章では別の形でも失敗します。乗法定数は最小の位置を動かしませんが、gradientをscaleします。そしてgradientはlearning rateで掛けられます。 で割って平均二乗誤差を得るか、和を使うかは答えには見えませんが、training runには非常によく見えます。和を使うと、batch sizeを2倍にすることは、取る各stepを2倍にすることになります。
sigmaも無料ではない
セクション「sigmaも無料ではない」へのリンクは0.12に固定しました。恣意的にです。そして工場の誰も、ノギス誤差の広がりを知りません。これを2つ目の未知数として扱い、maximum likelihoodにも決めさせます。ここでは、さきほど捨てた定数項が戻ってきます。modelと完全精度の主張とのあいだに立っている唯一のものだからです。
r = v - 0.293 * u
sigmas = np.arange(0.01, 1.0001, 0.0001)
nll_sigma = N * np.log(sigmas * np.sqrt(2 * np.pi)) + np.sum(r ** 2) / (2 * sigmas ** 2)
print("best sigma on the grid :", round(float(sigmas[nll_sigma.argmin()]), 4))
print("sqrt(mean squared residual) :", round(float(np.sqrt(np.mean(r ** 2))), 4))best sigma on the grid : 0.1006
sqrt(mean squared residual) : 0.10062つは小数第4位まで一致します。そして偶然ではありません。その式を微分してゼロに置くと、正確に が得られます。つまり平均二乗誤差は分散に似ているだけではありません。このmodelのもとでは、ノイズ分散のmaximum-likelihood推定量そのものです。あなたがずっと最小化してきた数は、sensorがどれだけノイジーかの推定値だったのです。
ひとつ小さな注意があります。述べるのは安いですが、後で再発見すると高くつきます。その推定値は低めに偏っています。残差は、それ自体を小さくするように選ばれたfitに対して測られたものだからです。simulationしてみます。真の分散が正確に1である分布から、20個の読み取り値からなるノートを20万冊作り、その読み取り値自身からfitの1つのパラメータを推定します。平方和を で割ると平均は0.9501、 で割ると1.0001になり、 はぴったり0.95です。fitする各パラメータは自由度を1つ消費します。これは、はるかに大きな問題の最小の可視例です。modelは、自分がfitされたdata上では常に良く見えます。第4章ではこれをdataを取っておく規律へ変え、第6章ではこの効果に名前を与えます。
損失はノイズについての主張である
セクション「損失はノイズについての主張である」へのリンク二乗誤差がノイズはGaussianであると主張するなら、次の問いは、その主張が偽だったら何が起きるかです。少し偽なのではなく、現実の測定が偽であるように偽だったら、です。
現場では、ほとんどのノギス読み取りは0.1ミリメートル程度まで良好です。そして1シフトに1、2回、切りくずがあごの下に入り、読み取りが数ミリメートル外れます。そのような誤差はheavy-tailedです。ほとんどの場合は小さく、ときどき巨大で、ベル曲線が許すよりはるかに頻繁に巨大になります。Cauchy分布はその振る舞いの標準的で清潔なmodelであり、密度はGaussianと同じくらい単純です。
違いはtailです。Gaussianは のように、容赦なく速く落ちます。Cauchyは のように、ほとんど落ちません。結果は、言うより見るほうが簡単です。
rng = np.random.default_rng(3)
g = 0.12 * rng.standard_normal(10 ** 6) # Gaussian noise
c = 0.12 * rng.standard_cauchy(10 ** 6) # Cauchy noise, same scale
for k in (10 ** 2, 10 ** 3, 10 ** 4, 10 ** 5, 10 ** 6):
print(f"{k:>9,} samples gaussian var {g[:k].var():.4f} cauchy var {c[:k].var():10.2f}") 100 samples gaussian var 0.0164 cauchy var 0.26
1,000 samples gaussian var 0.0146 cauchy var 59.88
10,000 samples gaussian var 0.0145 cauchy var 358.17
100,000 samples gaussian var 0.0144 cauchy var 3097.98
1,000,000 samples gaussian var 0.0144 cauchy var 32886.10Gaussianのsample varianceは0.0144、つまり に落ち着き、そこに留まります。Cauchyのものは上がり続け、sampleし続ける限り上がり続けます。収束する先がないからです。Cauchy分布には分散がなく、平均もありません。二乗誤差は、平方の平均を最小化することを本業としていますが、存在しない量を求められているのです。
では、ノギスがだまされた1シフトを見ます。同じ20時間、同じ刃、同じ1時間あたり0.30ミリメートルのdriftです。ただしノイズだけがCauchyです。2回fitします。1回は二乗残差を最小化し、もう1回はdataを実際に生成したノイズの負のlog-likelihoodを最小化します。centeringのトリックはここでは役に立ちません。切片を固定できるのは二乗誤差に対してだけだからです。したがって、どちらのfitも切片と傾きのgridを総当たりします。谷の底を見つける方法は、まだ訪れる以外にないからです。
SWARF = np.array([
(0.5, 20.08), (1.0, 21.95), (1.5, 20.86), (2.0, 27.51), (2.5, 20.64),
(3.0, 20.75), (3.5, 21.01), (4.0, 21.03), (4.5, 21.37), (5.0, 20.60),
(5.5, 22.03), (6.0, 21.95), (6.5, 21.98), (7.0, 22.01), (7.5, 21.73),
(8.0, 22.97), (8.5, 22.60), (9.0, 22.66), (9.5, 22.44), (10.0, 22.78),
])
hs, ys = SWARF[:, 0], SWARF[:, 1]
A = np.arange(18.0, 22.001, 0.005) # 801 intercepts
B = np.arange(-0.20, 0.8001, 0.002) # 501 slopes
R = ys - (A[:, None, None] + B[None, :, None] * hs) # every line against every point
SCALE = 0.12
square = np.sum(R ** 2, axis=2) # least squares
cauchy = np.sum(np.log(1 + (R / SCALE) ** 2), axis=2) # Cauchy likelihood
for name, surface in (("least squares", square), ("Cauchy likelihood", cauchy)):
i, j = np.unravel_index(surface.argmin(), surface.shape)
print(f"{name:>18}: width = {A[i]:.3f} + {B[j]:.4f} * hours"
f" -> 23.5 mm at hour {(23.5 - A[i]) / B[j]:.2f}")
print(f"{'the truth':>18}: width = 20.000 + 0.3000 * hours"
f" -> 23.5 mm at hour {(23.5 - 20.0) / 0.30:.2f}")
print(f"{A.size * B.size:,} candidate lines evaluated")ハイライトした2行が、fitの違いのすべてです。Cauchy密度のlogを取り、前とまったく同じように定数を落とすと、 が残ります。同じrecipe、ノイズについての違う主張です。
least squares: width = 21.380 + 0.1080 * hours -> 23.5 mm at hour 19.63
Cauchy likelihood: width = 19.935 + 0.3020 * hours -> 23.5 mm at hour 11.80
the truth: width = 20.000 + 0.3000 * hours -> 23.5 mm at hour 11.67
401,301 candidate lines evaluatedleast squaresは1時間あたり0.108ミリメートルのdriftを報告します。実際のrateのおよそ3分の1です。そして刃は19.6時間まで使えると結論します。真の答えは11.7時間です。そのfitに従って行動すると、工場は現場で最も標準的な損失関数のお墨付きにより、公差外の部品を作りながらpressを8時間余分に動かすことになります。Cauchy fitは、同じ20個の読み取り値、同じgrid、そしてコードの1行の違いだけで、11.8時間に着地します。
2つの反論には答えておく価値があります。どちらも優れたエンジニアが最初に言うことだからです。
外れ値は明らかだ。消せばよい。 できますし、助けにもなります。しかし十分ではありません。最悪の読み取り値を1つ削除すると、least-squaresの傾きは0.108から0.239へ移動します。それでも刃の交換は13.1時間になり、1時間半遅れます。最悪のものを消し、refitし、今度最悪になったものを消すと0.286まで来ます。ただし、これはすでに観察ではなく手続きです。元のfitで残差が最大の2つを消すなら0.223に着地します。あなたは今、書き下すことも擁護することもできない判断を下しました。ルールを自動化しても救われません。最大残差を落としてからrefitする方法を1000回のsimulated shiftで走らせると、傾き誤差の中央値はlikelihood fitの0.0100に対して0.0177であり、0.05を超えて外れる割合はlikelihood fitの1.3%に対して14.7%です。削除は間違った仮定の上に貼るpatchです。likelihoodにはpatchが要りません。外れ値が不可能だと仮定したことが一度もないからです。
運のよいdatasetを選んだだけだ。 その反論はまさに正しいです。だから最後の実験では、1000個の独立したshiftをsimulateし、それぞれで両方の方法をrefitします。
A = np.arange(18.0, 22.001, 0.02) # a coarser grid: a thousand fits to do
B = np.arange(-0.20, 0.8001, 0.005)
lines = A[:, None, None] + B[None, :, None] * hs
rng = np.random.default_rng(2026)
err_sq, err_ca = [], []
for _ in range(1000): # 1000 independent shifts
ys = 20.00 + 0.30 * hs + SCALE * rng.standard_cauchy(hs.size)
R = ys - lines
_, j = np.unravel_index(np.sum(R ** 2, axis=2).argmin(), (A.size, B.size))
_, q = np.unravel_index(np.sum(np.log1p((R / SCALE) ** 2), axis=2).argmin(), (A.size, B.size))
err_sq.append(abs(B[j] - 0.30))
err_ca.append(abs(B[q] - 0.30))
err_sq, err_ca = np.array(err_sq), np.array(err_ca)
for name, e in (("least squares", err_sq), ("Cauchy likelihood", err_ca)):
print(f"{name:>18}: median slope error {np.median(e):.4f} mm/h"
f" off by more than 0.05 in {100 * np.mean(e > 0.05):4.1f}% of shifts"
f" worst {e.max():.3f}")
print(f"the likelihood fit is the closer of the two in {100 * np.mean(err_ca < err_sq):.1f}% of shifts") least squares: median slope error 0.0350 mm/h off by more than 0.05 in 40.4% of shifts worst 0.500
Cauchy likelihood: median slope error 0.0100 mm/h off by more than 0.05 in 1.3% of shifts worst 0.090
the likelihood fit is the closer of the two in 75.6% of shifts平均ではなく中央値です。この節のすべてと同じ理由です。least-squaresの誤差はCauchyに動かされているので、その平均は報告するのに安定したものではありません。least squaresは5シフトに2回、大きく間違います。likelihood fitが大きく間違うのは77シフトに1回であり、1000シフト中の最悪の失敗もleast squaresの最悪の5分の1未満です。
これは二乗誤差を悪いものにする話ではありません。二乗誤差を具体的なものにする話です。そして算術がその理由を正確に示します。0.1 mmの残差と7 mmの残差を考えます。二乗すると、悪い読み取りは良い読み取りの4900倍だけ合計に寄与します。だから直線は体ごとそこへ引きずられます。Cauchy log-likelihoodのもとでは、同じ2つの残差の寄与は0.527と8.133で、比は15.4です。悪い読み取りはなお数えられますが、決定権は持ちません。ここがrobust statisticsの始まりです。Huberの1964年のlossは、小さい残差では二次的に、大きい残差では線形に振る舞うことで中間を取ります。7 そしてTukeyはそれ以前に、sample varianceがmean absolute deviationより悪い道具になるために必要な汚染がどれほど少ないかを示していました。8
歴史的な注記も、あまりに面白いので省けません。least squaresは1805年にLegendreによって最初に発表されました。便利な代数的装置としてであり、うまくいくという以上の正当化はありませんでした。9 その4年後、Gaussは議論を逆向きに走らせました。反復測定を組み合わせる正しい方法は算術平均であることを所与とし、どの誤差分布なら平均が最も確からしい値になるのかを問い、本質的に1つだけがそうであることを示しました。いま彼の名で呼ばれる分布です。10 この章の導出は彼のもので、2世紀以上前のものです。そして今でも、多くの講義が省いてしまう部分です。
いま言えること、まだできないこと
セクション「いま言えること、まだできないこと」へのリンク得たもの。 損失関数は採点ルールであり、それが生む順位は候補の性質ではなくルールの性質です。このcourseのあらゆる損失は、ノイズについての何らかの仮定の負のlog-likelihoodから、定数を捨てたものです。ここではGaussianが二乗誤差を与え、第4章ではBernoulliがcross-entropyを与え、第8章では語彙上のcategorical distributionがnext-token lossを与えます。recipeは変わりません。ノイズを述べ、likelihoodを書き、マイナスのlogを取ります。そして仮定が間違っているとき、modelは単に不正確なのではなく、予測できる向きに間違います。
まだ欠けているもの。 私たちは谷の底を、その中のあらゆる点を訪れることで見つけました。これは1つのパラメータと600個の候補では機能しましたし、2つのパラメータで401,301個の候補になっても5分の1秒で生き残りました。同じ解像度で3つのパラメータにすると201,051,801個の候補になり、もはや1つのarrayに収まりません。第5章の小さなnetworkには数千個のパラメータがあり、第10章が価格を付けるmodelには数十億個があります。ここでの総当たりは遅いのではありません。算術的に不可能です。そしてこの章のどこにも、代替案は示されていません。
ただし、谷を振り返ってください。 に立ち、損失が0.0822であるとき、「下り坂」の向きは謎ではありません。紙の上で見えます。曲線は右へ下っています。もし、今立っている点でどちらへ傾いているかを、どこも他に評価せずに損失関数へ尋ねられるなら、その方向へ一歩進み、もう一度尋ね、地面が平らになるまで繰り返せます。
その問いには名前があります。ある点における関数の傾きはderivativeであり、多数のパラメータを持つ関数では、あらゆる方向の傾きを同時に集めたものが勾配です。第1章はそれを使えませんでした。perceptronの誤差は階段であり、傾きを尋ねる相手がなかったからです。この章はもっと良いものを作りました。どこでもなめらかで、好みではなく明示された仮定から来た損失です。
したがって第3章の問いは、もはや傾きが存在するかどうかではありません。それをどう計算するのか、なぜそれに逆らって動くと上り坂ではなく下り坂になるのか、ほとんどすべての講義が信じるよう求めるその符号はなぜなのか、そしてもう一度尋ねる前にどれだけ進むべきなのか、です。この最後の1つの数が、training runが収束するか、答えの周りで永遠に振動するか、無限大へ走り去るかを決めます。
出典と方法
セクション「出典と方法」へのリンクこの章とあわせて読む価値があるものも挙げておきます。Prince, Understanding Deep Learning §5.1–5.2 and Appendix C は、本書と同じ順序でmaximum likelihoodからあらゆる損失を構築しています。Goodfellow, Bengio and Courville, Deep Learning §3.1–3.11 and §5.5 のmaximum-likelihood節は、第4章で必要になるKL divergenceも導出しています。Murphy, Probabilistic Machine Learning: An Introduction chapter 2 and §4.2 は、maximum likelihoodが何を保証し、何を保証しないかについてです。Deisenroth, Faisal and Ong, Mathematics for Machine Learning §6.1–6.4 は、和の法則、積の法則、Bayesの規則をきちんと扱っています。Tom Mitchellの短いCMU note Estimating Probabilities: MLE and MAP (2016)、そして同じ結果に実行可能なコードで到達する Dive into Deep Learning の§22.7も有用です。
参考文献
セクション「参考文献」へのリンク-
Fisher, R. A. On the mathematical foundations of theoretical statistics. Philosophical Transactions of the Royal Society A 222, pp. 309–368 (1922). likelihoodが一般的方法として提示され、「parameter」「statistic」、十分性、効率性も示された文献です。命名そのものと、probabilityからの分離は1年前です。Fisher, R. A., On the probable error of a coefficient of correlation deduced from a small sample, Metron 1, pp. 3–32 (1921), pp. 24–25. ↩
-
IEEE Standard for Floating-Point Arithmetic, IEEE 754-2019. binary32とbinary16、および和の実験がそのような結果になる丸め規則を定義しています。 ↩
-
Kalamkar, D. et al. A Study of BFLOAT16 for Deep Learning Training. arXiv:1905.12322 (2019). formatのパラメータと、mantissa bitsをexponent bitsへ交換する根拠です。 ↩
-
Micikevicius, P. et al. Mixed Precision Training. ICLR 2018, arXiv:1710.03740. loss scalingと、float16でそれを必要にする測定されたgradient magnitudesについてです。 ↩
-
Goldberg, D. What Every Computer Scientist Should Know About Floating-Point Arithmetic. ACM Computing Surveys 23(1), pp. 5–48 (1991). 2つの加算順序が食い違う理由について、今でも最良の単一の説明です。 ↩
-
Kahan, W. Pracniques: further remarks on reducing truncation errors. Communications of the ACM 8(1), p. 40 (1965). 半ページで説明される補償和です。 ↩
-
Huber, P. J. Robust estimation of a location parameter. The Annals of Mathematical Statistics 35(1), pp. 73–101 (1964). ゼロ付近では二次、tailでは線形になるlossで、継ぎ当てではなく導出されています。 ↩
-
Tukey, J. W. A survey of sampling from contaminated distributions, in Contributions to Probability and Statistics (Stanford University Press, 1960), pp. 448–485. ↩
-
Legendre, A. M. Nouvelles méthodes pour la détermination des orbites des comètes (Paris, 1805), appendix Sur la méthode des moindres quarrés. 計算上の装置としてleast squaresを最初に発表した文献です。 ↩
-
Gauss, C. F. Theoria Motus Corporum Coelestium (Hamburg, 1809), Book II, §§175–179. 算術平均から正規誤差法則へ、そこからleast squaresへ至る議論です。 ↩