コンテンツへスキップ
4/30第4章 / 全30章

分類、クロスエントロピー、そして自分を欺かない方法

ロジスティック分類器を構築し、98%の精度が何も見つけないmodelを意味し得る理由を学びます。

このページの内容

ベルトから流れてくるすべての部品について、この部品は問題ない と答えるmodelは、98.15 %の確率で正しいです。同時に、それは無価値でもあります。test setにある74個の不良部品のうち、1つも捕まえられないからです。

どちらの文も、同じmodelを説明しています。その2つの距離が、この章の内容です。

前半ではclassifierを構築します。新しく必要なものはほとんどありません。第2章では、dataがどのように生成されるかについての仮定をloss functionに変えるレシピを示し、第3章では、そのレシピが渡してくる任意のlossを下るための仕組みを示しました。この2つをyes/noの問いに適用するとlogistic regressionが出てきます。さらに新しい考え方が1つ、logit です。これは第17章で再び支払いを求められます。

後半のほうが難しい部分です。この先のコースのすべては、誰かが測定した数字によって評価されます。本当の改善と測定上の artefact を見分けられないなら、以降の章はすべて飾りになります。したがって扱うのは、confusion matrix、precision と recall、3つのsplit、leakage、そしてほとんど誰も正直に答えない問い――実際にtest exampleはいくつ必要なのか? です。

ここでの計算は20,000行にわたるため、全体を通してvectoriseしています。NumPyは第2章からずっと仕事をしてきましたし、ここから先はいちいち言及する価値もなくなります。

第1章と同じ工場ですが、問いはより難しくなります。受け入れるか、拒否するか ではなく、問いは この部品は不良か です。そして不良はまれです。このため、この章の測定の半分は難しくなり、modelingの半分は見かけより簡単になります。

belt.pyPYTHON
import numpy as np

rng = np.random.default_rng(4)
N = 20_000
width  = rng.normal(22.0, 0.9, N)      # millimetres
weight = rng.normal(57.0, 3.0, N)      # grams

z_true = -5.90 + 1.90 * (width - 22.0) + 0.42 * (weight - 57.0)
y = (rng.random(N) < 1 / (1 + np.exp(-z_true))).astype(float)

perm = rng.permutation(N)
train, val, test = perm[:12_000], perm[12_000:16_000], perm[16_000:]
TEXT
N = 20000  defects = 337  base rate = 0.0169
defects per split = 203 60 74

splitは2つではなく3つです。その理由は独立した節に値するので、下で1節を割きます。今は、1つ目でtrainし、2つ目でtuneし、3つ目は見ないでください。

featuresは標準化します――平均を引き、標準偏差で割ります――ただし training statisticsだけ を使います。理由は、第1章がperceptronのconvergence boundで示した通りです。中心化されていないdataはgeometryを敵対的にします。そして、その平均をどの行から計算してよいのかは、この章の後半で現実の問いになります。

perceptronは符号を返しました。符号では、reject と rejectだが、ほんのわずかに を区別できません。そしてその差こそ、工場がどの部品を人間に先に再検査させるかを決めるために必要なものです。

そこで第2章のレシピを文字通りたどります。labelがどのように生成されると主張するのかを書き下し、likelihoodを取り、logを取り、符号を反転するとlossが得られます。yes/noの結果に対する主張は Bernoulli 分布です。部品が不良である確率 pp があり、

P(y∣p)=p y (1−p) 1−yP(y \mid p) = p^{\,y}\,(1-p)^{\,1-y}

これは「y=1y = 1 なら pp、y=0y = 0 なら 1−p1-p」をコンパクトに書いただけです。そのlogを取り、符号を反転すると、1つのexampleに対するlossは

L=−[ ylog⁡p+(1−y)log⁡(1−p) ]L = -\big[\,y \log p + (1 - y)\log(1 - p)\,\big]

これが binary cross-entropy です。便利だから選んだのではありません。coin flipが取り得る唯一の分布のnegative log-likelihoodだからです。他に選択肢はありませんでした。

まだ足りないのは、pp がどこから来るかです。modelはweighted sum s=w⋅x+bs = \mathbf{w}\cdot\mathbf{x} + b を計算します。これは実数であり、数直線全体を取り得ます。一方、確率は (0,1)(0,1) に収まらなければなりません。その間を移動する関数が logistic sigmoid です。

σ(s)=11+e−s\sigma(s) = \frac{1}{1 + e^{-s}}
TEXT
logit -4.0  ->  p = 0.0180        loss when y=1 and p=0.9  : 0.1054
logit -1.0  ->  p = 0.2689        loss when y=1 and p=0.5  : 0.6931
logit  0.0  ->  p = 0.5000        loss when y=1 and p=0.01 : 4.6052
logit  4.0  ->  p = 0.9820

右側の列を価格表として読んでください。90 %のconfidenceで正しいことのコストは0.105です。判断を避けることのコストは0.693――つまり log⁡2\log 2、肩をすくめる価格です。自信満々に間違えることのコストは4.6で、44倍以上です。そしてmodelが間違いにより確信を深めるほど、その価格は無限に上がります。cross-entropyは単にerrorを数えるのではありません。傲慢さに課金します。

新着記事を受信トレイにお届け

AIニュース、ガイド、プロダクトアップデートを、読む価値のある記事を公開したときだけ短いメールでお送りします。

第3章では、何かをtrainするには、各parameterに対するlossのderivativeを得るのだと言いました。1つのexampleでやってみます。s=w⋅x+bs = \mathbf{w}\cdot\mathbf{x} + b と p=σ(s)p = \sigma(s) のもとで、

∂L∂s=p−y,∂L∂w=(p−y) x,∂L∂b=p−y\frac{\partial L}{\partial s} = p - y, \qquad \frac{\partial L}{\partial \mathbf{w}} = (p - y)\,\mathbf{x}, \qquad \frac{\partial L}{\partial b} = p - y
詳細を表示

ごちゃごちゃを打ち消す2行。 sigmoidには非常に都合のよいderivative、σ′(s)=σ(s) (1−σ(s))=p(1−p)\sigma'(s) = \sigma(s)\,(1 - \sigma(s)) = p(1-p) があります。そしてlossを微分すると、

∂L∂p=−yp+1−y1−p=p−yp (1−p)\frac{\partial L}{\partial p} = -\frac{y}{p} + \frac{1-y}{1-p} = \frac{p - y}{p\,(1-p)}

chain ruleで2つを掛けると、p(1−p)p(1-p) が上にも下にも1回ずつ現れます。これはぴったり打ち消し合い、p−yp - y だけが残ります。この相殺は偶然ではありません。lossがある分布のnegative log-likelihoodであり、output functionがその分布が自然に使うものになっているとき、常に起きることです。この組み合わせには名前があります――generalised linear model――そしてこの整ったgradientはその指紋です。1

したがってupdateは prediction minus truth, times the input です。それだけです。trainer全体を示します。これは第3章のdescentで、1行だけ変わっています。

logistic.pyPYTHON
def sigmoid(z):
    return np.where(z >= 0, 1.0 / (1.0 + np.exp(-z)),
                    np.exp(np.minimum(z, 0)) / (1.0 + np.exp(np.minimum(z, 0))))


def fit_logistic(X, y, lr=0.5, epochs=4000):
    w, b = np.zeros(X.shape[1]), 0.0
    for _ in range(epochs):
        p = sigmoid(X @ w + b)
        g = p - y                        
        w -= lr * (X.T @ g) / len(y)     
        b -= lr * g.sum() / len(y)       
    return w, b

sigmoid の中の np.where は見た目の問題ではありません。1/(1+e−s)1/(1+e^{-s}) を大きな負の ss に対して直接計算するとoverflowします。このbranchは、代数的には同一で、かつexponentを負に保つ形式を選びます。これは第2章のfloating-pointの箱が最初の負債を取り立てる場面であり、2節後にはさらに大きな負債を取り立てます。

なぜsquared errorではないのか、そしてなぜ答えはgradientにあるのか

セクション「なぜsquared errorではないのか、そしてなぜ答えはgradientにあるのか」へのリンク

cross-entropyをsquared errorより好む標準的な説明は、上のlikelihoodの議論です。squared errorはGaussian noiseを仮定したときに得られるもので、labelはGaussianではない。したがって使うな、というものです。これは正しいですが、誰も納得させません。sigmoidの上に L=(p−y)2L = (p - y)^2 を書けば、それでもtrainできるからです。

効く議論はgradientに関するものです。sigmoidの上にsquared errorを置くと、chain ruleにより

∂L∂s=2 (p−y) p (1−p)\frac{\partial L}{\partial s} = 2\,(p - y)\,p\,(1-p)

この余分な p(1−p)p(1-p) が、先ほど打ち消された項です。今度は打ち消されません。そしてmodelが自信を持つたびに0へ向かいます――modelが自信満々に 間違っている ときも含めて。true labelが1のexampleについて、いくつかのscoreで両者を評価してみます。

score ssppcross-entropy ∂L/∂s\partial L/\partial ssquared error ∂L/∂s\partial L/\partial sratio
−8-80.000335−0.999665-0.999665−0.000670-0.0006701,491
−4-40.017986−0.982014-0.982014−0.034690-0.03469028.3
−2-20.119203−0.880797-0.880797−0.184956-0.1849564.8
000.500000−0.500000-0.500000−0.250000-0.2500002.0
+2+20.880797−0.119203-0.119203−0.025031-0.0250314.8

s=−8s = -8 では、modelは可能な限り間違っています。そしてsquared errorは、cross-entropyの1,491分の1のgradientで応答します。間違いがひどいほど、modelがそこから学ぶ量は少なくなるのです。一方、cross-entropyのgradientは −1-1 でsaturateします。最大限に間違うと最大限に大きいsignalが出て、それ以上にはなりません。

競争させてみましょう。balancedな2,000点、同一のinitial weightsは自信満々に間違うように選び(w=[−6,−6]\mathbf{w} = [-6, -6])、learning rateも同一、違うのはlossだけです。どちらのrunもcross-entropyでscoreし、列を比較可能にしています。

epochcross-entropy lossaccuracysquared-error lossaccuracy
15.48650.23005.94990.2290
101.55250.24605.90420.2290
500.46420.77805.69130.2320
1000.46390.77705.39550.2410
2000.46390.77704.63110.2745
5000.46390.77700.52910.7660
1,0000.46390.77700.46400.7765

cross-entropyはepoch 50で終わっています。squared errorはepoch 100でもaccuracy 24 %にとどまっています――epoch 10の23 %からほとんど動いていません――推測より悪いのです。自信満々に間違った状態から始まり、それを救うはずのgradientが0.0007倍されていたからです。epoch 500あたりで脱出し、同じ場所に着地します。したがって正直な要約は、sigmoid上のsquared errorは 間違っている わけではない、しかし 速度が最も重要な場所で正確に遅い ということです。2-parameter modelなら450 epochを失います。100 layerのnetworkでは、どこかのunitが常に自信満々に間違っているので、training runを失います。

3つの量です。第8章ではperplexityのために、第11章ではfine-tuningされたpolicyをreferenceの近くに保つpenaltyのために、正しく必要になります。評判ほど難しくありません。2

Entropy は、ある分布からのdrawを通信するために、最良のcodeを使った場合に平均して必要なbit数です。

H(p)=−∑ipilog⁡2piH(p) = -\sum_i p_i \log_2 p_i

Cross-entropy は、本当は pp から来るdataに対して、qq 用に作られたcodeを使うときに支払う量です。

H(p,q)=−∑ipilog⁡2qiH(p, q) = -\sum_i p_i \log_2 q_i

KL divergence は余分です。真実が pp なのに qq を信じることで生じる、bit単位の無駄です。

DKL(p∥q)=H(p,q)−H(p)D_{\mathrm{KL}}(p \parallel q) = H(p,q) - H(p)

ベルト上で3つすべてを確認します。

TEXT
test defect rate                                = 0.0185
entropy of that coin                            = 0.1329 bits
cross-entropy of the constant predictor on test = 0.1330 bits
KL(test coin || fair coin)                      = 0.8671 bits
H + KL                                          = 1.0000 bits
cross-entropy of the p=0.5 predictor on test    = 1.0000 bits

ここでは2つのことが見えます。第一に、training base rateである1.69 %を単に報告するmodelは、0.1330 bitsのcross-entropyを達成します。これはtest labelsのentropyとほぼ完全に同じです。そうでなければなりません。正しい分布を持っていて、個別情報は何もないからです。Entropyは、個体について無知であることが買ってくれるfloorです。第二に、肩をすくめて0.5と言うmodelはちょうど1 bitを支払い、その差0.8671 bitsがまさにKL divergenceです。H+DKL=H(p,q)H + D_{\mathrm{KL}} = H(p,q) は暗記すべきidentityではありません。積み上がっていく請求書として見られるものです。

そしてtrainingへのつながりに戻ると、labelが単一の既知classであるとき、「true」distributionはone-hotで、そのentropyは0です。したがってcross-entropyはKL divergenceに 等しく なります。cross-entropyを最小化することと、modelのdistributionをtruthへ引き寄せることは、同じ行為です。

不良は1種類ではありません。mouldingでは、部品は short shot(材料不足)、flash(多すぎてmouldからはみ出す)、あるいは burn として出てくることがあります。4つの結果なので4つのlogitsがあり、それらは合計1になる4つの確率にならなければなりません。それが softmax です。

softmax⁡(z)i=ezi∑jezj\operatorname{softmax}(\mathbf{z})_i = \frac{e^{z_i}}{\sum_j e^{z_j}}

softmaxには、偶然に見えて実は実装全体である性質があります。

softmax⁡(z+c)=softmax⁡(z)\operatorname{softmax}(\mathbf{z} + c) = \operatorname{softmax}(\mathbf{z})

任意の定数 cc について成り立ちます。なぜなら ezi+c=ecezie^{z_i + c} = e^{c} e^{z_i} となり、ece^c が分子と分母で打ち消されるからです。意味を持つのはlogits間の 差 だけです。絶対的なlevelは情報ではありません。

幸いにもそうです。なぜなら、その絶対的なlevelこそcomputerを壊すものだからです。

TEXT
logits            = [800. 801. 799.]
naive softmax     = [nan nan nan]
shifted by -max   = [0.2447 0.6652 0.09  ]
same softmax after adding 1000 to every logit: True

e800e^{800} は64-bit floatでoverflowし、sumはinfinityになり、infinityをinfinityで割ると nan になります――errorでもcrashでもなく、3つの確率があった場所に静かな穴が空くだけです。最大logitを引いても数学的には何も変わらず、数値的にはすべてが変わります。最大のexponentがちょうど e0=1e^0 = 1 になるからです。これは第2章の logsumexp trickが作業着を着た姿であり、真面目な実装はすべてそうします。

softmax.pyPYTHON
def softmax(Z):
    Z = Z - Z.max(axis=1, keepdims=True)   
    E = np.exp(Z)
    return E / E.sum(axis=1, keepdims=True)


def fit_softmax(X, Y, lr=1.0, epochs=6000):
    W, b = np.zeros((X.shape[1], Y.shape[1])), np.zeros(Y.shape[1])
    for _ in range(epochs):
        G = (softmax(X @ W + b) - Y) / len(X)   
        W -= lr * (X.T @ G)
        b -= lr * G.sum(0)
    return W, b

gradientは再び prediction minus truth です。今度は YY がone-hotです。binary caseは最初からspecial caseだったのです。

3,000個の部品でtrainし、1,000個でtestします。各部品には3つのmeasurement(width、weight、melt temperature)があります。結果は 94.00 % accuracy です。この数字が隠しているものを示します。

truth ↓ / predicted →okshort shotflashburnrecall
ok8505900.984
short shot2221000.488
flash2003010.588
burn300390.929
precision0.9500.8080.7690.975

modelはshort shotの半分未満しか見つけていません。accuracyにはこれが見えません。部品の86 %が問題なく、それらを正しく当てるだけで平均を支えられるからです。Macro F1――classごとのF1 scoreの平均で、rare classをcommon classと同じ重みで扱うもの――は0.7983 です。一方、micro F1は0.9400で、定義上accuracyと同一です。誰かがF1を1つだけ報告したら、どちらかを尋ねてください。

modelingはここまでです。章の残りは数字についてです。

train済みのbinary modelを取り、すべてのlogitに定数を掛けて2つのvariantを作ります。hesitantなversionには0.35、overconfidentなversionには4です。正の数を掛けても符号は変わらないので、3つのmodelは4,000個すべてのtest partsについて まったく同じlabel を予測します。accuracyでは区別できません。cross-entropyならまったく問題ありません。

modelaccuracycross-entropymean loss when rightmean loss when wrongworst single loss
hesitant (logits × 0.35)0.98300.15490.13691.19902.80
as trained0.98300.05640.01472.46897.82
overconfident (logits × 4)0.98300.15630.00099.142727.63

hesitantなmodelは、正しく当てた何千個も含め、すべての部品に小さな税金を払います。overconfidentなmodelは正しいときほぼ無料で、間違ったとき壊滅的です。このtest setのある1部品だけで27.63 natsのコストがかかります。2つは正反対の道を通ってほぼ同じtotalに着地し、dataにcalibrateされた確率を持つtrained modelは、その両方の3分の1の位置にいます。

これが loss と metric の違いを最も鋭く述べる方法です。lossはoptimiseするものです。differentiableでなければならず、modelが言ったすべてを見ます。どれだけ確信していたかも含みます。metricは評価されるものです。step functionでも、business ruleでも、見逃した不良のcountでも構いません。これらは同じobjectではなく、常に一致するわけでもありません。だから始める前に両方を定義し、画面に表示されているからという理由でlossをmetricの代わりにしてはいけないのです。

modelの前に必要なのは、最も怠けた答えは何点を取るのか? です。このベルトでは、常に問題なしと言う です。

TEXT
always-say-fine baseline: accuracy = 0.9815
confusion (tn, fp, fn, tp) = (3926, 0, 74, 0)

98.15 %。次に、default threshold 0.5でのtrained logistic modelです。

TEXT
logistic @0.5: accuracy=0.9830 precision=0.8000 recall=0.1081 F1=0.1905
confusion (tn, fp, fn, tp) = (3924, 2, 66, 8)

98.30 %。baselineを 0.15 percentage point 上回りました。そしてaccuracyで止まるreportはこれを勝利と呼ぶでしょう。confusion matrixは実際に何が起きたかを示します。

predicted finepredicted defective
actually fine3,9242
actually defective668

74個の不良部品のうち8個を見つけ、66個を通してしまいました。この表の3通りの読み方に名前を付けるのが、3つの数字です。

  • Precision =TP/(TP+FP)=8/10=0.800= \mathrm{TP}/(\mathrm{TP}+\mathrm{FP}) = 8/10 = 0.800。flagした部品のうち、実際に不良だったものはいくつか。これは無駄な検査のcostです。
  • Recall =TP/(TP+FN)=8/74=0.108= \mathrm{TP}/(\mathrm{TP}+\mathrm{FN}) = 8/74 = 0.108。不良部品のうち、捕まえたものはいくつか。これは不良品をcustomerへ出荷するcostです。
  • F1 =2PR/(P+R)=0.190= 2PR/(P+R) = 0.190。両者のharmonic meanで、小さいほうに近く留まるため、片方だけにおだてられることを拒みます。

何が重要かは工場次第であって、数学次第ではありません。検査には数秒かかり、出荷された不良にはrecall noticeのcostがかかります。したがってここではrecallが支配的であり、0.108は失敗です。

しかしmodelが問題なのではありません。thresholdが問題 です。そしてthresholdはmodelの一部ではありません。確率に対して後から適用されるbusiness decisionです。sweepしてみます。

thresholdTPFPFNaccuracyprecisionrecallF1
0.50082660.98300.8000.1080.190
0.2002728470.98120.4910.3650.419
0.10042118320.96250.2630.5680.359
0.05054236200.93600.1860.7300.297
0.0206757070.85580.1050.9050.188
0.005711,36030.65930.0500.9590.094

accuracy列を下へ読んでください。98.30 %から65.93 %までずっと下がっていきます。その間にmodelは、不良を8個見つける状態から74個中71個を見つける状態へ進みます。このmodelができる有用なことはすべて、accuracyを悪化させます。 見出しの数字をoptimiseするteamは、何も見つけないversionを出荷するでしょう。

詳細を表示

Class weightingはsignalを作らない。operating pointを動かすだけ。 imbalanced classesへの通常の最初の反応は、lossでrare classにweightを付けることです。positivesに1、10、60のweightを付けると、

weight on positivesaccuracyprecisionrecallF1AUC
10.98300.8000.1080.1900.9363
100.96050.2530.5810.3520.9361
600.82900.0910.9190.1660.9361

precisionとrecallは大きく動きます。AUC――modelがrandomな不良部品をrandomな良品より上にrankする確率で、thresholdを完全に無視するもの――は0.0002しか動きません。これは何もないのと同じです。reweightingは、同じmodelを同じtrade-off curveに沿って滑らせただけです。それはしばしば望むことであり、決して新しい情報ではありません。rankingが悪いなら、どんなweighting schemeも救えません。

なぜ2つではなく3つのsplitなのでしょうか。exampleのsetを使って何かを 選ぶ その瞬間――threshold、learning rate、6つのmodelのうちどれをshipするか――そのsetはfittingに使われたことになり、そのscoreはunbiasedではなくなるからです。3 このベルトで測定すると、validation set上でthresholdをsweepすると0.196が選ばれ、そのmodelは未接触のtest setで F1 = 0.4122 を出します。もしtest set上で直接sweepしていたら、そこでのbest achievableは 0.4186 でした――誰も報告する権利のない数字です。

ここでのgapは0.006と小さいです。これは4,000個のvalidation examplesに対して、1つのhyperparameterを1回sweepしただけだからです。追加のdecisionが増えるたび、validation setが小さくなるたびに、gapは大きくなります。また、1回のrunで方向が保証されるわけではないことにも注意してください。選ばれたthresholdはvalidationで0.3902、testで0.4122だったので、今回はvalidationが 過小評価 しました。biasは多くのdecisionにわたってsystematicに現れるもので、1回では見えません。4

ここで演習です。ベルトlogに3つ目の列 station_seconds が届きます。各部品がinspection stationにいた時間です。これを加えるのはpreprocessingへの1行の変更です。結果はこうなります。

modelaccuracyprecisionrecallF1cross-entropyAUC
width + weight0.98300.8000.1080.1900.05640.9363
+ station_seconds0.99200.7920.7700.7810.02360.9970

recallは10.8 %から77.0 %へ上がります。F1は4倍以上になります。そしてaccuracyがどうなったかに注目してください。98.30 % → 99.20 %、0.9 pointのgainです。summary slideでは「どちらにせよ約99 %」と丸められがちな種類の数字です。accuracyは先ほどfailureを見抜けず、今度はfraudを見抜けません。

読み進める前に、このmodelはcheatingしています。どうやってかを見つけてください。

leakを狩る方法、最速で見つける順番。

  1. trainとtestを比較する。 overfittingは大きなgapとして現れます。ここでは、honest modelが0.9838 train / 0.9830 test、leaky modelが0.9936 train / 0.9920 testです。どちらのgapも0.2 point未満です。leakはoverfittingのようには見えません――leaky featureはtest timeでも同じようにavailableなので、modelは存在しない世界へ美しくgeneraliseします。

  2. featureごとに単独でmodelをtrainする。 答えを運ぶものは、自分から名乗り出ます。

    feature aloneaccuracyrecallF1AUC
    width0.98150.0140.0260.8691
    weight0.98150.0000.0000.7914
    station_seconds0.98500.4050.5000.9960

    ある1列だけで、単独で、AUC 0.9960でdefectsをrankします。caliperとscaleで取った2つのmeasurementは0.87と0.79です。この非対称性がalarmです。

  3. 各数字がいつ書き留められたかを尋ねる。 平均dwell timeは、passedした部品で 2.23秒、failedした部品で 15.56秒 です。もちろんそうです。部品がstationに留まるのは、inspectorがそれをベルトから外したから です。それは誰かが不良だと判断した後に、そしてその判断があったからこそ起こります。この列は部品のmeasurementではありません。verdictのmeasurementです。

the planted leakPYTHON
station = 1.8 + rng.exponential(0.35, N)                     # a part just passing through
audited = rng.random(N) < 0.006                              # random spot checks
station[audited] += rng.uniform(6.0, 26.0, audited.sum())
station[y == 1] = 9.0 + rng.exponential(7.0, (y == 1).sum())  

highlightされた行がleakです。不良部品のdwell timeは別の分布からdrawされています。人間がそれをベルトから外したからです。これはapplied machine learningで最も一般的な深刻なbugであり、名前があります。target leakage――predictionを行わなければならない瞬間にはavailableでない情報がtraining featuresに入っていることです。5 exceptionは投げません。より良い数字を生みます。project内のあらゆるincentiveは、それを残す方向に働きます。

防御策は、すべての列に対して1つの質問をすることです。このpredictionが必要なその瞬間に、この値はすでに存在しているか? live beltでは、station_seconds は部品が検査された後まで不明です。そして検査こそ、modelが置き換えるはずだったものです。

20個のexampleでmodelをscoreし、17個正解したとします。85 %と報告します。

TEXT
17 correct out of 20 -> accuracy 0.8500
  Wilson    95% CI : [0.6396, 0.9476]
  bootstrap 95% CI : [0.7000, 1.0000]
  P(a 65% model scores 17 or more out of 20) = 0.0444
  P(an 85% model scores 17 or more out of 20) = 0.6477

17/20の正直な読み方は、64 %から95 %のどこか です。本当に65 %のmodelでも、この結果を4.4 %の確率で出します――23回に1回です。そしてもしあなたが一握りのpromptsを試し、bestを報告したなら、そのrunを自分で製造したことになります。20個中17個では、85 %のmodelと65 %のmodelを区別できません。

rateにintervalを付ける方法は2つあり、どちらもtoolkitに入れるべきです。

uncertainty.pyPYTHON
def wilson(k, n, z=1.959963985):
    """95% interval for k successes in n trials. Correct at small n; no simulation."""
    ph, d = k / n, 1 + z * z / n
    centre = (ph + z * z / (2 * n)) / d
    half = z * (ph * (1 - ph) / n + z * z / (4 * n * n)) ** 0.5 / d
    return centre - half, centre + half


def bootstrap_ci(correct, n_resamples=10_000, alpha=0.05, seed=0):
    """95% interval for the mean of any per-example score array. Works on F1 too."""
    rng = np.random.default_rng(seed)
    correct = np.asarray(correct, dtype=float)
    draws = correct[rng.integers(0, len(correct), size=(n_resamples, len(correct)))]
    lo, hi = np.quantile(draws.mean(axis=1), [alpha / 2, 1 - alpha / 2])
    return float(correct.mean()), float(lo), float(hi)

通常のsuccess rateには Wilson6 を使ってください。任意の nn でwell behavedであり、randomnessを必要としません。上で n=20n = 20 のときbootstrapのupper endが1.0000であることに注意してください。20点をresampleすると20個正解を簡単にdrawできるため、自身のgranularityより狭いintervalを表現できません。bootstrap7 はformulaが存在しない場合に使います。それが興味深いcaseの大半です。F1、macro-averages、BLEU、pass@1、rubric-based judgeのscoreなどです。このベルトでは、tuned modelのF1 0.4122には [0.3009, 0.5156] のbootstrap intervalが付きます。reportに載せるべき数字はこちらです。point estimateだけでは、それが支えられない比較を誘ってしまうからです。

もう1つmeasurementします。2つのmodelを比較する方法が変わるからです。同じ500 examplesでscoreされた2つのmodelです。

TEXT
model A: 0.8580  95% CI [0.8260, 0.8880]
model B: 0.8120  95% CI [0.7780, 0.8460]
the two intervals overlap: True
paired difference A-B: 0.0460  95% CI [0.0260, 0.0680]
they disagree on 31 of 500 examples (A right 27, B right 4)

intervalは重なっています。そして民間rule――error barsが重なっているなら有意差はない――なら、この比較をinconclusiveと呼ぶでしょう。しかしそうではありません。2つのmodelは 同じexamples 上で走っているので、正しい量はexampleごとの差です。そのintervalは [0.0260, 0.0680] で、十分に0を上回っています。両者がdisagreeするのは500 items中31個だけで、Aはそのdisagreementのうち27個で勝っています。easyもhardも含む共有examplesは、noiseを追加するのではなく相殺します。modelはpairedで比較してください。そうすれば、dataのごく一部で同じ結論に到達できます。

これで、calibrateされた確率を出力するmodel、便利さで選んだのではなくdataについての主張から導かれたloss、文字通り prediction minus truth であるgradient、そして――さらに重要なことに――それが機能しているかどうかを見つけるための仕組みが手に入りました。上の10行のWilson intervalは、そのまま再利用されます。第15章のprompt variants、第19章のretrieval tables、第29章のgolden setを支えます。formulaが存在しないときに手を伸ばすのがbootstrapです。

しかしmodelはまだ1 layerです。線を引くだけであり、第1章はXORの4行で、線では足りないことを証明しました。修正はstackすることです。第一のlayerがspaceを曲げ、第二のlayerがその曲がったspaceで線を引きます。

ここで、この章の整ったgradientは限界を迎えます。上のすべてが機能したのは、inputとlossの間に1 layerしかないmodelについて、∂L/∂s=p−y\partial L/\partial s = p - y を一度だけ手で書き下せたからです。中央に第二のlayerを置くと、問いの形が変わります。outputにまったく触れていないweight――その影響が別のlayerを通じて、場合によっては複数のpathを同時に通って届くweight――に対するlossのderivativeとは何か。

そのderivativeは存在します。toyより大きなものについて手で計算するのは絶望的であり、parameterを1つずつ計算するのも別のscaleで絶望的です。必要なのは、forward passがたどった同じgraphを1回backward passするだけで、network内のすべてのderivativeを得るprocedureです。

それが第5章であり、このコースの残りを動かすengineです。


この章と併せて読む価値があるものとして、Bishop, Pattern Recognition and Machine Learning §1.2, §1.5, §1.6 and §4.3 があります。この章がたどる順序で、probability、decision theory、information theory、linear classificationを扱っています。また、Murphy, Probabilistic Machine Learning: An Introduction, chapters 6 and 10、Prince, Understanding Deep Learning §5.4–5.7、そして Saito and Rehmsmeier, The Precision-Recall Plot Is More Informative than the ROC Plot When Evaluating Binary Classifiers on Imbalanced Datasets (PLOS ONE, 2015) も参照してください。上で引用したAUCが、部品の1.7 %しか不良でないときに見るべき唯一のthreshold-freeな数字であってはならない理由が分かります。

  1. Ma, T. and Ng, A. CS229 Lecture Notes, Stanford University, chapters 2 and 3. p−yp - y を生む相殺がluckに見えなくなる場所です。outputに合うexponential-family distributionを選び、そのcanonical linkを使えば、gradientは常にprediction minus truthになります。 ↩

  2. Olah, C. Visual Information Theory (2015), colah.github.io/posts/2015-09-Visual-Information。entropy、cross-entropy、KL divergenceをformulaとしてではなく、bits単位のcostとして説明した、入手可能な中で最も明快な解説です。 ↩

  3. Abu-Mostafa, Y. S., Magdon-Ismail, M. and Lin, H.-T. Learning From Data (AMLBook, 2012), lectures 13 and 17 of the Caltech course. Lecture 13はvalidation、3つのlearning principlesを扱うlecture 17は data snooping が名付けられる場所です。この2つが、この章の規律のsourceです。data setを見るたび、それはfitting decisionです。optimiserを走らせたかどうかは関係ありません。 ↩

  4. James, G., Witten, D., Hastie, T. and Tibshirani, R. An Introduction to Statistical Learning, 2nd edition (Springer, 2021), chapters 2 and 5。bias–variance decompositionとresamplingについて。companion volumeではselection trapが明示的に述べられています。Hastie, Tibshirani and Friedman, The Elements of Statistical Learning, 2nd edition, §7.10.2, The Wrong and Right Way to Do Cross-validation。 ↩

  5. Kaufman, S., Rosset, S., Perlich, C. and Stitelman, O. Leakage in Data Mining: Formulation, Detection, and Avoidance. ACM Transactions on Knowledge Discovery from Data 6(4), 2012. 上で示したfailureのformal treatmentであり、dataの組み立て方のartefactをmodelがlearnしたことで勝利したcompetitionのcase studiesを含みます。 ↩

  6. Wilson, E. B. Probable Inference, the Law of Succession, and Statistical Inference. Journal of the American Statistical Association 22(158), pp. 209–212 (1927). 上の wilson() で使ったscore intervalで、proportionに対する今でも正しいdefaultです。避けるべきなのは教科書的なinterval p^±zp^(1−p^)/n\hat{p} \pm z\sqrt{\hat{p}(1-\hat{p})/n} です。0や1の近くでnonsenseを出し、小さな nn ではcoverageがひどく不足します。 ↩

  7. Efron, B. Bootstrap Methods: Another Look at the Jackknife. The Annals of Statistics 7(1), pp. 1–26 (1979). sampling theoryがないものも含め、計算できる任意のstatisticにintervalを付けられるようにする考え方です。 ↩

この章を動画で見る

この章のアイデアをわかりやすく解説する短い動画です。

すべての動画を見る

新着記事を受信トレイにお届け

AIニュース、ガイド、プロダクトアップデートを、読む価値のある記事を公開したときだけ短いメールでお送りします。


作成者

David Vicente Campos

NeuraLIA Labs創業者、MyRealFood共同創業者

レオン大学出身のコンピューターエンジニアです。MyRealFoodを共同創業し、CTOとして、何百万人もの人がより良い食生活のために使ってきたアプリを開発しました。また、NeuraLIA Labsを創業し、そこでAIプロダクトを開発しています。ここでは、私がその過程で理解する必要があったことを、誰かにこう説明してほしかったと思う形で書いています。

著者について詳しく

NeuraLIA Labsが公開しています。

コース目次

Abstract software decision engine with branching paths, probability nodes, and glowing gates.
jev読了15分

Jev AIモデルは文章ではなく意思決定のために作られている

TypeSafe AIのJevが注目されているのは、ソフトウェアの知能を確率の問題として扱うからです。適切な分岐を選び、信頼度を添え、コードが必要としているのが意思決定であるときに、LLMに文章を書かせるためのコストを避けます。

Abstract legal research workspace with documents, search nodes and governance controls.
openai読了14分

OpenAIのAstra for Lawは新モデルではなく、法律AIシステム

OpenAIの法律分野での発表の本質は、新しい基盤モデルそのものではなく、その周辺にあるシステムです。ドメイン検索、信頼できるツール、権限、ベンチマーク、レビュー経路が重要になります。

今日からAIを仕事に活用しましょう

あらゆるモデルとツールを1か所に。無料で開始でき、カードは不要です。