ダメなベンチマークと評価:Senior SWE-Bench、napkin math、そして冬用タイヤ
原文は Dan Luu により に公開されました。 このブログを購読する
今回は3種類のベンチマークを見ていきます。パフォーマンスの“napkin math(ナプキン計算)”のためのベースライン数値の計算、AIモデルの評価、そして自動車用タイヤに関するものです。物事への直感を養うために、私は説明を見る前に自分で考えてみるのが好きなので、まずはベンチマークの情報だけを提示し、解説は後回しにしています。私の考えを見る前に、ぜひご自身でも答えを考えてみてください。
29. 私の友人は、コンピュータのパフォーマンスに関する面接対策として桁数のオーダーを見直していて、https://github.com/sirupsen/napkin-math(5.4kスター)がトップヒットだったと気づきました。READMEの表には次のように書かれています:
| 操作 | レイテンシ | スループット | 1 MiB | 1 GiB |
|---|---|---|---|---|
| シーケンシャルメモリ R/W (64 bytes) | 0.5 ns | |||
| ├ シングルスレッド | 20 GiB/s | 50 μs | 50 ms | |
| ├ マルチスレッド | 200 GiB/s | 5 μs | 5 ms | |
| 同一ゾーン内ネットワーク | 10 GiB/s | 100 μs | 100 ms | |
| ├ VPC内 | 10 GiB/s | 100 μs | 100 ms | |
| ├ VPC外 | 3 GiB/s | 300 μs | 300 ms | |
| ハッシュ、非暗号学的安全 (64 bytes) | 10 ns | 5 GiB/s | 200 μs | 200 ms |
| ランダムメモリ R/W (64 bytes) | 20 ns | 3 GiB/s | 300 μs | 300 ms |
高速シリアライゼーション [8] [9] † | N/A | 1 GiB/s | 1 ms | 1s |
高速デシリアライゼーション [8] [9] † | N/A | 1 GiB/s | 1 ms | 1s |
| システムコール | 300 ns | N/A | N/A | N/A |
| ハッシュ、暗号学的安全 (64 bytes) | 100 ns | 1 GiB/s | 1 ms | 1s |
| シーケンシャルSSDリード (8 KiB) | 1 μs | 8 GiB/s | 100 μs | 100 ms |
コンテキストスイッチ [1] [2] | 10 μs | N/A | N/A | N/A |
| シーケンシャルSSDライト、-fsync (8KiB) | 2 μs | 3 GiB/s | 300 μs | 300 ms |
| TCP Echoサーバー (32 KiB) | 50 μs | 500 MiB/s | 2 ms | 2s |
| ランダムSSDリード (8 KiB) | 100 μs | 70 MiB/s | 15 ms | 15s |
展開(デコンプレッション) [11] | N/A | 1 GiB/s | 1 ms | 1s |
圧縮(コンプレッション) [11] | N/A | 500 MiB/s | 2 ms | 2s |
| ソート (64ビット整数) | N/A | 500 MiB/s | 2 ms | 2s |
| プロキシ: Envoy/ProxySQL/Nginx/HAProxy | 50 μs | ? | ? | ? |
| 同一リージョン内ネットワーク | 250 μs | 2 GiB/s | 500 μs | 500 ms |
| ゾーン/VPC内プレミアムネットワーク | 250 μs | 25 GiB/s | 50 μs | 40 ms |
| シーケンシャルSSDライト、+fsync (8KiB) | 300 μs | 30 MiB/s | 30 ms | 30s |
| {MySQL, Memcached, Redis, ..} クエリ | 500 μs | ? | ? | ? |
シリアライゼーション [8] [9] † | N/A | 100 MiB/s | 10 ms | 10s |
デシリアライゼーション [8] [9] † | N/A | 100 MiB/s | 10 ms | 10s |
| シーケンシャルHDDリード (8 KiB) | 10 ms | 250 MiB/s | 2 ms | 2s |
| ランダムHDDリード (8 KiB) | 10 ms | 0.7 MiB/s | 2 s | 30m |
| Blob Storage GET、if-not-match 304 | 30 ms | |||
| Blob Storage GET、1接続 (128KiB) | 80 ms | 100 MiB/s | 10 ms | 10s |
| Blob Storage GET、n接続 (offsets) | 80 ms | NW limit | ||
| Blob Storage LIST | 100 ms | |||
| Blob Storage PUT、1接続 (128KiB) | 200 ms | 100 MiB/s | 10 ms | 10s |
| Blob Storage PUT、n接続 (multipart) | 200 ms | NW limit | 10 ms | 10s |
リージョン間ネットワーク [6] | Varies | 25 MiB/s | 40 ms | 40s |
| ネットワーク NA Central <-> East | 25 ms | 25 MiB/s | 40 ms | 40s |
| ネットワーク NA Central <-> West | 40 ms | 25 MiB/s | 40 ms | 40s |
| ネットワーク NA East <-> West | 60 ms | 25 MiB/s | 40 ms | 40s |
| ネットワーク EU West <-> NA East | 80 ms | 25 MiB/s | 40 ms | 40s |
| ネットワーク EU West <-> NA Central | 100 ms | 25 MiB/s | 40 ms | 40s |
| ネットワーク NA West <-> Singapore | 180 ms | 25 MiB/s | 40 ms | 40s |
| ネットワーク EU West <-> Singapore | 160 ms | 25 MiB/s | 40 ms | 40s |
このベンチマークの何が問題でしょうか?
30. 人々がDeepSWEやSenior SWE-Benchを参照して、お気に入りのモデルが他の人のお気に入りのモデルより優れていることや、単に一般的に優れたベンチマークであることを「証明」しようとするのをよく見かけます。例えば以下のようなものです。


これらのベンチマークの何が問題でしょうか?
31. 寒い天候では冬用タイヤがオールシーズンタイヤより優れているとよく言われます。例えば「all season tires during winter cold」(引用符なし)でググると、GoogleのAI要約は次のように始まります。
オールシーズンタイヤは凍えるような冬の気温ではトラクションを失い、硬化します。そのゴムコンパウンドは暖かい天候向けに設計されており、7°C(45°F)を下回ると硬くなり、制動距離が大幅に伸び、グリップが低下します……オールシーズンタイヤのゴムは氷点下の気温では柔軟性を保てず、雪や氷の上では硬いプラスチックのようになります。
トレーニングデータにはインターネット上のコメントが大量にあることを考えると、これは妥当なコメントです。というのも、どのタイヤを使うべきかという議論で、このコメントのバリエーションを頻繁に見かけるからです。
このベンチマークの何が問題でしょうか?
29. Napkin mathの数値
ランダムメモリアクセスのレイテンシ
友人(Jamie)がすぐに奇妙だと感じたのは、ランダムメモリR/Wが20nsとされている点でした。ランダムメモリR/Wは(キャッシュヒットではなく)実際のDRAMリードを意味するはずで、桁数の見積もりとしては100ns前後であるべきだと彼は考えたのです。
話しているうちに、彼はREADMEが「レイテンシ」という用語を、実際にはレイテンシではないものに対して使っていると指摘しました。そして、ランダムメモリリードのレイテンシのコードを確認したところ、次のようなコードが見つかりました(もう一つの演習として、下の説明を読む前に、次のコードの何が問題か考えてみてください):
while test.i < test.vec.len() {
let random_index = test.order[test.i];
black_box(test.vec[random_index]);
test.i += 1;
}
Jamieは、ループの各イテレーション間にデータ依存がないため、ここでのメモリリードは並列に実行されると指摘しました。主張されているレイテンシの数値はアクセスあたりの平均時間を求めることで算出されているため、CPUが複数のロードを同時に実行できることを考えると、これは正しくありません。この方法でレイテンシを測りたいのであれば、重なるアクセスを防ぐためにロード間に依存関係を持たせる必要があります(関連するトピックについては本シリーズのパート4、演習19で議論しました)。
ランダムSSDリード
私はJamieの指摘のすべてに同意しますが、「レイテンシ」という用語の使い方自体は、私はあまり問題視しませんでした。というのも、場合によってはレイテンシの略称であり、別の場合にはレイテンシに近いもの(例えばスループットの逆数)を指しているのかもしれず、そうすることで表がシンプルになるからです。
メモリレイテンシの数値以外で、最初に私の目を引いたのは他のいくつかの数値でした。例えば、ランダムSSDリードは100us / 70 MB/sとされています。もっと高速な(あるいはもっと低速な)SSDはたくさんあります。例えば、高速だが特別ではない(例えばOptaneではない)デバイスであれば、40usを下回るレイテンシが見られることもあります。例えばKioxia CD9P-Rはこちらで約30usと測定されています。些細なスクリプト以外では、ディスクパフォーマンスが重要になるような作業をしたことがないので、どんな数値を念頭に置くべきか直感がありません1が、DRAMアクセスの場合よりも、ランダムリードのレイテンシとスループットに単一の数値を用いることの有用性は低いように思えます。ディスクのベンチマークを見る限り、リードサイズ、キュー深度、ジョブ数によって結果の幅が非常に大きいように見えます(例えば、先ほどのKioxia CD9P-Rのリンクを参照)。もちろん、DRAMのレイテンシや帯域幅に影響する類似の要因もありますが、メモリアクセスについて考える際には、1つか2つの数値を知っておくことが役に立つ状況にいることの方がはるかに多いように思えます。私はディスクパフォーマンスについて何も知らないので、Postgresのディスクパフォーマンスに取り組んだことのあるPeter Geogheganに尋ねてみたところ、彼も同意し、ディスクパフォーマンスの複雑さについて追加のコメントを以下に書いてくれました。
このSSDランダムリードの数値のコードを見ると、ランダムメモリリードのコードがJamieにとって違和感があったのと同じように、私にとっても違和感があります。オフセットは次のように生成されています。
for i in 0..(buffer.len() / page_size) {
pages.push((i * page_size + 1) as u64);
}
そして8 KiBのリードを行います(オフセットはシャッフルされてランダムリードが作られます)。ここで正しくないと感じられる点は次の通りです:
- +1によってすべてのリードがアラインされなくなります。4KiBページサイズでは、1回のリードが3ページにまたがります
- 異なるオフセットが同じページに重なる可能性があり、意図しないページキャッシュからのリードが発生します
- ページサイズによっては、リードがファイル末尾を超えてしまい、パニックを引き起こす可能性があります
「buffer.len() / page_size」という構造はアクセスを範囲内に収めることを意図しているようですが、これはアクセス長とは無関係です。正確なオフセットを考えるのをサボって、4 GiBのような巨大なアクセス長を考えてみましょう(バッファサイズは8 GiBです)。これは確実にオーバーフローします。より正確に言えば、オーバーフローするケースは4KiBページで8KiBのアクセス長のような場合ですが、考え方は同じです。
最後のオフセットはSIZE - 4096 + 1になります。これでは4095バイトしかアクセスできませんが、8192バイトをアクセスしようとします。ベンチマークは5秒間しか実行されないため、実際にEOFを超えて読み込んで失敗するかどうかはランダムですが、特定の実行でランダムに失敗するかどうかに関わらず、ここにはバグがあります。
シーケンシャルSSDリード
コードだけを見ても、多くの部分がどうもしっくりきません。例えば、1usのレイテンシと8 GiB/sのスループットを持つとされるシーケンシャルな8 KiB SSDリードを生成するために使われているコードを考えてみましょう。前述の通り、私はディスクパフォーマンスが重要になるような問題に取り組んだことがないので、このような数値が妥当かどうか直感がありませんが、コードは違和感があります。コードは1 GiBのファイルを用意し、フラッシュした後、それを繰り返し読み直すというものです。つまり、1回のキャッシュされていないリードの後に、キャッシュされたリードが続くことになります。意図はキャッシュされていないリードを測定することにあるように思えますが、もしキャッシュされたリードを測定することが意図なのであれば、コードはそれも正しく行っていません(これはfsyncありのリードが3 GiB/sとされているなど、他の数値についても同様の問題があるようです)。キャッシュされていない1回のリードの後にキャッシュされたリードが続くのが現実的だという主張も可能ですが、集計された数値である1回の非キャッシュリードとN回のキャッシュリードの平均値を、まったく同じワークロードを持たない人がどう使えばよいのかは不明です。Nは分かりやすい形で示されていないので、同じワークロードを持っているかどうかさえ分かりません。
数値がどうあるべきか私にはまったく見当がつかないので、数値を調べてみましょう。測定はc4-standard-48-lssdで行われたとされています。そのインスタンスについてGoogleのドキュメントでは、接続された8台すべてのディスクの最大スループットは5000 MiB/s(Googleの表によると、これは接続されたディスク数に応じてスケールし、ディスク1台あたり625 MiB/s)とされています。私のディスクベンチマークに関するわずかな知識からすると、ピークスループットの数値は一般的に大きなリードを使った場合に得られるものなので、8 GiB/sは過大に思え、コードから感じた違和感が正しいことが裏付けられます。そして他の数値を見ても、特定のリードサイズに対する数値をいくつか持っておくことが、一般的にディスクパフォーマンスを代表しているわけではないという、より広い指摘が当てはまるように思えます。
代表性
しかし、この種の「napkin math」の背後にある考え方は、特定のクラウドインスタンスが正確にどう動作するかを知ることではなく、様々な方法でパフォーマンスを見積もるために使える基本的な数値を得ることです。Kioxia CD9Pのベンチマークに戻ってみると、様々なパラメータでそれよりも高い帯域幅を持つリードベンチマークがたくさんあります(もちろん、様々なパラメータでより低い帯域幅のものもたくさんあります)。レイテンシについては、レイテンシを最小化する設定でのシーケンシャルリードでさえ、レイテンシはより高くなっており(ベンチマーク内の他のディスクについても同様です)、これはsirupsenのベンチマークがうっかりキャッシュから読み込んでいることの別の兆候ですが、たとえ数値が正しかったとしても、その数値をどう使えばよいのかは不明です。
sirupsenのコードは、キャッシュとプリフェッチを防ぐ試みをしているようです。Linux上でテストが実行されていることを検出すると、アドバイザリであるPOSIX_FADV_RANDOMを設定し、テスト開始前にアドバイザリであるPOSIX_FADV_DONTNEEDを設定しますが、これらのどちらもこのベンチマークにおいてOSレベルでのキャッシュを防ぐことはなく、SSD内部などのより低レベルなキャッシュを防ぐことも期待すべきではありません。Macでは、ベンチマークは事前にCommand::new("sudo").arg("purge").output().expect("failed to flush page cache")を呼び出しますが、POSIX_FADV_RANDOMに相当するものはなく、他のOS(BSDやWindowsなど)では何も行われていないようです。
コードの他の部分にも他の問題がありますが、すべての具体的な問題や提示された値のほとんどについて細かく掘り下げるのではなく、異なるレジームでの数値の範囲を知りたい場面があるという考え方に立ち戻ると、そうであるように思える箇所がかなりあります。別の例を挙げると、READMEは「Decompression(展開)」を1 GiB/s、「Compression(圧縮)」を500 MiB/sとしています。もちろん、どんなnapkin mathも正確ではありませんが、異なるzstd圧縮オプションを試すだけで、圧縮速度に2桁以上の差が出ますし、高速圧縮に特化したアルゴリズムを使えばさらに大きな幅が生じます(もちろん、より多くの労力をかけてより低速で高密度な圧縮を行うことも可能です)。
ディスクの例に戻ると、ディスクの数値は8台のディスクを持つVM構成から来ていると述べました。数値は誤っているように見えますが、もし数値が正しかったとしても、例えばリード帯域幅について、VMのシングルディスク版を使えば異なる数値が得られるのは当然です。ページキャッシュから読み込んでいないのであれば、リードベンチマークの読み取り帯域幅は約1/8になるはずです。GCP上の特定の8ディスク構成の読み取り帯域幅の数値を、napkin mathの数値として暗記しておくことが、なぜ特に有用なのかは不明です。
何を学ぶのが有用か
全体として、私はこの種の数値のいくつかを知っておくことは有用だと思いますが、表を見て数値を覚えようとは必ずしも思わないかもしれません(面接対策として、面接で聞かれると信じる十分な理由がある場合に、面接直後に忘れることを前提に覚える場合を除けば)。一般的に、こうした数値を知っておくことが理にかなうようなことをしているのであれば、使っているうちに自然と覚えていきます。例えば、標準的なシングルモードファイバーの分散が17 ps / nm * kmであることを今でも覚えていますが、これは20年前に光学・フォトニクスの仕事をしたことがあるためです。これは概算計算で頻繁に出てくるので、十分に使えばいずれ覚えるものです。2の累乗(例えば2^8 = 256、2^16 = 65536など)についても同様で、暗記しようとしたわけではありませんが、こうした数値に触れるコーディングを十分に行えば、役に立つ数値は自然と覚えるものです。
リンクされているnapkin mathリポジトリは「数は暗記のために丸められている」と記しており、これらを暗記することが理にかなっていることを示唆しています。上で述べたことに加えて、これらの数値の多くは導出可能であり、私の意見では、仕事でこれらを使うのであれば、たとえ概算の数値を暗記していたとしても、その導出を理解しておくことの方がしばしば理にかなっています。例えば、パート4でSandy Bridgeプロセッサのシングルコアメモリ帯域幅の数値を基本的なパラメータから導出しました。コードがどれくらい速く動くかだけを知りたいのであれば、通常はすべてを第一原理から再導出する必要はありません。しかし、何かを変更することの意味を理解しようとする場合、どのようなメカニズムが働き、それらがどう相互作用するのかを知っておくことが役に立ち、それは数値をいくつか暗記しただけでは得られないものです。
この質問の文脈に戻ると、面接準備をしていた私の友人が最後に懸念していたのは、このリポジトリが非常に人気があるため、面接官が掲載されている数値のほとんどが間違っていることを知らずに使ってしまうかもしれないということでした。
おまけ:時間経過によるメモリレイテンシ
ところで、実際のシステムで観測されるメモリレイテンシがどうなっているのか気になったので、instlatx64サイトのデータをプロットしてみました。結果は以下の通りです:
ここには2つのグラフがあります。なぜなら、比較不可能な2つの異なる手法が使われているからです。元々の手法では、1024バイトストライドでのアクセスを用いてメモリレイテンシを求めていましたが、これは十分に大きなデータセットに対するアクセスであれば古いプロセッサではうまく機能しました。新しいプロセッサではこれが純粋なDRAMアクセスにならないようにするメカニズムが追加されたため、新しい手法ではランダムアクセスを用いてメモリレイテンシを求めています(古い手法を使った後期の数値の一部は、ランダムメモリアクセス時間として考えると実際には有効ではありません)。レイテンシはinstlatx64サイトから取得したもので、CPUの発売年は検証なしにcodexでGPT-5.6 Sol ultraに尋ねて見つけたものなので、年が間違っているものもおそらくあります。
グラフをざっと見ただけでも、メモリレイテンシはしばらくの間は劇的に改善しましたが、やがてその改善は頭打ちになり、実際には時間の経過とともにより高いレイテンシが観測されるようになっていることがわかります。その理由は本稿の範囲外です。
690ns?
90年代の結果には非常に高い外れ値も見られます。これらの結果をあまり時間をかけずに見た限りでは、結果が間違っているとは一概に言えません。Intel側で大きな外れ値は83 MHzのIntel Pentium Overdriveです。他の古いIntelの結果はすべて非OverdriveのPentiumです。
Overdrive Pentiumは、前世代のCPU用マザーボードにそのまま挿せるチップでした。テストはGigabyte GA-5486ALマザーボード上で、ALi M1489/M1487チップセットを33 MHzのバス速度に設定して実行されたようです。ALi M1489/M1487のデータシートによると、DRAMリードタイミングには4つの可能な設定があります。「normal」設定に構成されている場合、リードページミスはCP+8で、リードタイミングは4-4-4です。私は486のバスタイミングについてはディスクパフォーマンス以上に詳しくないので、LLMにこれについて尋ねてみたところ、これは正しく、ここでのメモリアクセスには21、22、または23サイクルを期待すべきだと教えてくれました。これはどうもしっくりきません。というのも、LLMにこれらの数値が何を意味するのかを尋ねると、最初のワードに続く各追加ワードに対するものなので、そのサイクル数はフルキャッシュラインのフィルに対するものだからです。ワードアクセスの実際のload-to-useレイテンシはその最初の部分、つまり11バスサイクルになるはずですが、キャッシュライン全体の時間を求めたいのであれば、その数値はベンチマークとして妥当な範囲にあるように思えます。
外れ値であるAMD K5 PR166の結果を見ると、少し奇妙な点がありますが、現代のコンピュータパフォーマンスに関する質問としてはかなり脇道にそれてしまうので、これはシリーズ後半の別の質問にとっておくことにしましょう。
30. DeepSWE / Senior SWE-Bench
全体的なもっともらしさ
これらのベンチマークの手法を見る前に、結果だけを見ても、DeepSWEもSenior SWE-Benchも、コーディングエージェントが全体としてどれくらい優れているかの要約としては、どちらももっともらしく感じられません。DeepSWEのホームページを表面的に読むと、OpenAIの前世代モデル(GPT-5.5)がAnthropicの現行世代モデル(Fable 5)と同等に優れていることになり、Senior SWE-Benchを表面的に読むと、Anthropicの前世代モデル(Opus 4.8)がOpenAIの現行世代モデル(GPT-5.6)よりも優れていることになります。一般的に、表面的な読み取りがほとんどの人が受け取る印象であり、これが私がこれらが使われるのを一般的に見かける方法です(例えば、仕事のSlackや、人々が直接私に送ってくる場合など)。
手法の問題
実際にどう作られているかを見ると、公開されているベンチマークのうち、コーディングエージェントがどれくらい優れているかについて一般的なアイデアを得るために信頼できるものはほとんどないように思えます。手法という点では、ベンチマークは一般化可能な結果を得るために測定すべきことに関してあまり筋が通っていません。ディスクパフォーマンスについて何も知らないのと同様に、私はAIについても何も知らないので、Anthropicでしばらく評価チームを率いていた人物(Aaron Levin)に推論と結論をレビューしてもらいましたが、彼は全体的な考えと推論に同意しました。ディスクパフォーマンスの専門家への相談と同様に、ここでのポイントは、専門家が同意したから同意すべきだということではなく、その分野に関する専門知識がなくても、専門家と同じ結論に至るために必要なのは、どんなベンチマークや実験計画の問題を評価する際にも使うような、一般的な推論を適用することだけだということです。
要約スコアの代表性
前回の投稿で、単一の要約スコアは、サブベンチマークの結果を見ればモデルXをモデルYより有利にするものがたくさんあるため、ほぼ何とでも言えてしまうという大まかな考えについて議論しました。また、世の中にあるタスクの分布をサンプリングして、ベンチマークAがより代表的だからベンチマークBより優れていると言うための、特に良い方法はないということについてもです。
これらのベンチマークの詳細をもう少し見てみると、DeepSWEでは113のタスクがあり(少なくともcodexがそう教えてくれましたが)、それぞれが4回実行され、一般的に合否のスコアが付けられているようです(モデルは各タスクで0%、25%、50%、75%、または100%のスコアを取っているように見えます)。グラフを見ると、GPT-5.5がOpus 4.8よりはるかに優れていることがわかります。GPT-5.5とOpus 4.8の差は、Opus 4.8とGemini-3.5 Flashの差とほぼ同じくらい大きいのです。上で述べたように、これらのモデルを使ったことがあれば、これは私や私が信頼する誰かの全体的な経験とはあまり一致しません(もちろん、このことが当てはまる特定のタスクやサブベンチマークはあります)。
なぜそうなっているとされているのかを見ると、GPT-5.5 xhighはOpus 4.8 xhighよりもやや安価で、はるかに優れている(67%対54%)とされています。113のタスクのうち、モデルが引き分けたのは34タスク、GPT-5.5 xhighが勝ったのは57タスク、Opus 4.8が勝ったのは22タスクです。私や他のプログラマーにとって、これらのタスクが私たちが行うタスクを代表しているのであれば、これは意味があるかもしれません。113のタスク(あるいは異なる結果となった79のタスクでさえ)は、この投稿で詳細に見るには多すぎますが、タスク名を見る限り、私が行うタスクにまったく関連していると思えるものはほとんど、あるいはまったくありません。そして言語で見ると、結果が異なるタスクのうち、私がコーディングエージェントをよく使う言語(Rust)のタスクは4つだけで、残りのタスクは私がコーディングエージェントを使わないか、どのモデルでも問題ないような些細な問題にしか使わない言語のものです2。
結果が異なる4つのRustタスクは次の通りです:
Boaにおける階層的評価キャンセル(https://deepswe.datacurve.ai/data/v1.1/tasks/boa-hierarchical-evaluation-cancellation)、fdにおける決定論的マルチキーソート(https://deepswe.datacurve.ai/data/v1.1/tasks/fd-deterministic-multi-key-sorting)、oxvgにおけるスタイルシート・セレクタ構造の保持(https://deepswe.datacurve.ai/data/v1.1/tasks/oxvg-structural-selector-preservation)、そしてwasmiにおけるトラップ時のコアダンプ生成(https://deepswe.datacurve.ai/data/v1.1/tasks/wasmi-trap-coredumps)です。これらのどれも、私がコーディングエージェントを使うこととあまり関係があるようには思えず、私にとっては無価値です。
このうち1つは過去1年間に私がやったことに漠然と似ているように思えますが、他の3つはそうではありません。個々のベンチマークを見れば、異なるベンチマーク間で結果に大きなばらつきがあることがわかります(例えば、前回の投稿のOptimization 1ベンチマークでは漠然とDeepSWEのようなモデルランキングが得られますが、GameAIではSenior SWE-Benchのようなランキングが得られます。しかし、その投稿でも観察したように、私たちが気にするタスクに名目上似ているように見える1つのベンチマークが、実際のタスクで見られる結果とは逆の結果をもたらすこともあります。これもまた、ばらつきが非常に大きいためです)。113のタスクのうち1つだけが私が行ったタスクとある程度似ているということは、DeepSWEのベンチマークスコアは私個人にとっては無意味であることを意味します。
Senior SWE-Bench
もう一方のベンチマークに移ると、Senior SWE-Benchは上記のすべての問題を抱えている上に、結果をよりミスリーディングな形で提示しており、さらに結果の主観的な採点という追加の問題も抱えています。ここで超長い逐語的な批判をするつもりはありませんが、問題の一つを見てみると、「tasteful solve(洗練された解決)」とみなされるためには、解決策が複数の基準を満たす必要があります。これには、ルーブリックで一定のスコア以上を取ることや、結果が参照結果の長さの2倍以上でないことなどが含まれます。
恣意的で主観的なスコアリング関数
より深く見なくても、これは古典的なhttps://danluu.com/discontinuities/の状況であることがわかります。ベンチマークはこれらの連続的なスコアを持ちながら、厳格なカットオフを要求することで閾値効果を導入しています。私が見てきた限り、このようなことは物事をシンプルにするためによく行われますが、根底にある基準が重要だと信じるのであれば、一般的に、スコアXは合格でスコアX-εは不合格と言うようなことはしたくないはずです。代わりに、スコアは何らかの非連続的でない方法で集計されるべきです。私はしばしばこれを行うことを躊躇する理由は、式を書き下そうとすると重みが恣意的でスコアが無意味であることが明らかになるからだと思います。参照がR LOCである場合に1 LOCの解決策に対してN点のボーナスを与えるべきではないことはおそらくわかっているので、そこで価値を上限付ける何らかの関数が必要です。おそらく(2R)/(R+N)のようなことをしてボーナスを2で上限付けることができます。おそらくこれは大きな関数に対して十分にペナルティを与えないので、(2R^2)/(R^2+N^2)に切り替えるべきでしょう。この振る舞いは1+tanh(ln(R/N))と書けばより見やすくなるかもしれませんので、お好みでそちらに置き換えて考えてください。次に、これを他のスコアと組み合わせる必要があるので、少なくともM-1個の、M個の式に対する相対的な重み付けのための式を追加する必要があります。
これは明らかに正当化が難しい恣意的な式になるでしょう。しかし、実際に使われている不連続性を持つ式も、まったく別の恣意的な関数でありながら、正当化をさらに困難にするより悪い特性を持っています!ただ、それを書き下す人がそれを式として考えなくても済むため、どれだけ恣意的であるかを考えずに済むだけなのです。
閾値効果
Senior SWE-Benchで定義されているLOC(コード行数)の指標に具体的に目を向けると、もちろん閾値効果が見られます。例えば、https://senior-swe-bench.snorkel.ai/tasks/paperless-ngx-perf-workflow-queriesでは、GLM-5.2は参照の61 LOCに対して121 LOCでtastefulとスコアされています。もし1 LOCでも多ければ122となり、2倍になるため、GLM-5.2は合格ではなく不合格になります。また、リンクからわかるように、ベンチマークは条件ごとに1回実行されています。LLMを使ったことがある人なら誰でも知っているように、そして前回の投稿で見たように、実行間には莫大なばらつきがあります(しばしば、前回の投稿で観察したように、異なるモデルやエフォートレベル間のばらつきよりも、実行間のばらつきの方が一般的にはるかに大きいのです)。これは、すでにある種の妥当な連続スコアで採点した場合でも、1回の実行はあまり意味を持たないことを意味します。こうしたノイズの多い指標が、閾値効果によって情報が削ぎ落とされると、結果はさらに無意味になります。
それはLOCスコアに関して特に問題のあるベンチマークでさえありません。plausible-fix-top-pages-comparisonの方が、参照解決策が1 LOC(追加と削除がそれぞれ1 LOCとしてカウントされるため、2 LOCとしてスコア付けされます)であるため、より悪いです。これにより、tastefulな解決の最大サイズは3 LOCとなります。追加と削除の両方が発生する場合、これは削除1 LOC、追加2 LOC、あるいはその逆でなければなりません。
コード品質
実際の結果を見ると、筋が通りません。このタスクでは、Opus 4.8が「tasteful」とスコアされている一方で、Opus 4.7とFable 5はそうなっていません。実際の差分を参照解決策と比較すると、以下のようになります(LOC基準でカウントされるのは実際のコードへの変更のみで、テストのLOC、コメントなどはカウントされません)。
リファレンス
--- a/lib/plausible_web/controllers/api/stats_controller.ex
+++ b/lib/plausible_web/controllers/api/stats_controller.ex
@@ -723,7 +723,7 @@ defmodule PlausibleWeb.Api.StatsController do
else
json(conn, %{
results: pages,
- meta: Map.merge(meta, Stats.Breakdown.formatted_date_ranges(query)),
+ meta: Map.new(meta.values) |> Map.merge(Stats.Breakdown.formatted_date_ranges(query)),
skip_imported_reason: meta[:imports_skip_reason]
})
end
Opus 4.8(合格)
--- CHANGELOG.md
+++ CHANGELOG.md
+- Fixed blank comparison dates in row tooltips on the Top Pages report
--- lib/plausible_web/controllers/api/stats_controller.ex
+++ lib/plausible_web/controllers/api/stats_controller.ex
- meta: Map.merge(meta, Stats.Breakdown.formatted_date_ranges(query)),
+ meta: Map.merge(Map.new(meta), Stats.Breakdown.formatted_date_ranges(query)),
--- test/plausible_web/controllers/api/stats_controller/pages_test.exs
+++ test/plausible_web/controllers/api/stats_controller/pages_test.exs
+ assert json_response(conn, 200)["meta"] == %{
+ "date_range_label" => "2 Jan 2021",
+ "comparison_date_range_label" => "1 Jan 2021"
+ }
Opus 4.7(不合格)
--- lib/plausible_web/controllers/api/stats_controller.ex
+++ lib/plausible_web/controllers/api/stats_controller.ex
- meta: Map.merge(meta, Stats.Breakdown.formatted_date_ranges(query)),
+ meta:
+ meta.values
+ |> Map.new()
+ |> Map.merge(Stats.Breakdown.formatted_date_ranges(query)),
--- test/plausible_web/controllers/api/stats_controller/pages_test.exs
+++ test/plausible_web/controllers/api/stats_controller/pages_test.exs
+ assert json_response(conn, 200)["meta"]["date_range_label"] == "2 Jan 2021"
+ assert json_response(conn, 200)["meta"]["comparison_date_range_label"] == "1 Jan 2021"
Fable 5(不合格)
--- lib/plausible/stats/breakdown.ex
+++ lib/plausible/stats/breakdown.ex
%{
results: build_breakdown_result(results, query_with_metrics, metrics),
- meta: meta
+ # `meta` is a `Jason.OrderedObject` - convert it to a plain map so that
+ # callers can safely `Map.merge/2` extra fields into it. Merging into the
+ # struct would add keys outside of its `values` field, which the JSON
+ # encoder for `Jason.OrderedObject` silently ignores.
+ meta: Map.new(meta.values)
}
--- lib/plausible_web/controllers/api/external_stats_controller.ex
+++ lib/plausible_web/controllers/api/external_stats_controller.ex
- defp maybe_add_warning(payload, %Jason.OrderedObject{} = meta) do
+ defp maybe_add_warning(payload, meta) do
--- test/plausible_web/controllers/api/stats_controller/pages_test.exs
+++ test/plausible_web/controllers/api/stats_controller/pages_test.exs
+ assert json_response(conn, 200)["meta"] == %{
+ "date_range_label" => "2 Jan 2021",
+ "comparison_date_range_label" => "1 Jan 2021"
+ }
私はElixirプログラマーでも、このコードベースに詳しいわけでもありませんが、コードだけを見ても、不合格で「tastefulでない」とされたOpus 4.7の解決策は、参照解決策と意味的に同一に見えます。唯一の違いは、パイプラインが可読性のために複数行に展開されていることです。Elixirを知らなくても、これを「tastefulness」に基づいて不合格にするのは馬鹿げていると感じます。
私はこのようなパイプ演算子をよく使う他の言語(F#やtidyverseを使ったRなど)を使ったことがありますが、Opus 4.7の変更を「洗練されていない」として却下する人に会ったことは一度もありません(厳格なスタイルガイドで何を複数行に展開すべきか、すべきでないかが決められている場合は別ですが、もしそうであれば、自動フォーマッタがこれを処理すべきであり、解決策のフォーマットは無関係です)。
Fable 5の解決策は、変更の範囲を広げすぎているため却下されるべきだと主張することもできますが、他の理由で却下されるべきかどうかは別として、長さのためにさらに「tastefulでない」として却下するのは間違っているように思えます。
採点者のばらつき
LLMのばらつきは採点自体にも当てはまります。もちろん、1回の実行結果をLLM採点者に複数回与えれば、同じ問題をLLMに複数回解かせたときにしばしば大きく異なる結果が得られるのと同じ理由で、異なるスコアが得られるのは当然です。私は手近なコーディングエージェントに、GPT-5.6 SolとOpus 4.8がテストされた各条件について採点を10回ずつ再実行させてみました(codexによると採点はSonnet 4.6を使って行われたとのことなので、それで再実行しました)。同じモデルとエフォートレベルを使った場合、期待されるLLMによるtastefulnessの採点結果が公式の結果から反転する確率は23%でした(サブ結果に関しては、相対的なtasteが32%、practice alignmentが5%、task rubricが3%のケースで反転しました)。代わりに、公式の結果が典型的/中央値の結果と異なった割合を見ると、全体で21%の差がありました(相対的なtasteで27%、practice alignmentで3%、task rubricで2%)。全体の反転率が個々の反転率より低いのは、全体のスコアがすでにtastefulでない場合に、サブスコアでtastefulからtastefulでないへ反転したケースがあるためです。
はっきりさせておくと、これは実行間のばらつきではありません。これは1回の実行に対するLLM採点を用いた場合のばらつきであり、公開されているGPT-5.6 SolとOpus 4.8のベンチマーク全体で見ると、約20%の確率で誤った結果を与えているように見えます(測定されているものが正しく、そもそも測定するのが妥当であり、最も可能性の高いSonnetのスコアが正しいスコアであると仮定した場合)。
もちろん、異なるモデルで採点すれば異なる結果が得られます。Sonnet 4.6の代わりにGPT-5.6 Solで再採点すると、両モデルともにtastefulと判断される解決策の数は半分以下に減少します。それがより正確なのか、そうでないのかは、誰にもわかりません。
全体的な妥当性
時には、ベンチマークを見て、個々の結果は間違っているものの、全体としてノイズが相殺され、全体的な結果は筋が通っていると言えることもあります。ここではそうではないと思います。多くの人々がSenior SWE-Benchを広めているのを見かけますが、それは現実的な問題を提示し、妥当な方法で採点していると謳っているからのようです。すでに述べたように、表面的には結果はもっともらしく見えず、手法を見ても、その結果は意味がないという表面的な考えが裏付けられます3。
結果の提示方法にも改善の余地があります。私が参加しているあるSlackでは、誰かがこれにリンクを張り、以下のようなプレビュースニペットが表示されました:
- Claude Fable 5: 29.1%
- Claude Opus 4.8: 25.0%
- GPT-5.6 Sol: 24.4%
彼らは肯定的なコメントを添え、これは他のベンチマーク(GPT-5.5をOpus 4.8より上位に置く多くのベンチマークの一つ)よりも現実的だと述べました。実際に結果を見れば、25.0%と24.4%の差はほとんど意味がないことは明らかですが、結果はこれらが意味のある差であるかのように提示されています。ページではGPT-5.6 SolがOpus 4.8よりはるかに安価であることが明確に示されていますが、Senior SWE-Benchに言及する議論のほとんどで、その点は省略され、ヘッドラインの結果だけが言及されています。また、ヘッドラインの結果でFable、Opus、Sonnetにはmaxが、GPT-5.6、GPT-5.5、GPT-5.4にはxhighが使われているのも奇妙に思えます。
31. 寒冷時のタイヤ性能
人々はよく、オールシーズンタイヤは7℃/45℉で固くなる(なぜか「ホッケーパックのように固くなる」という表現がよく使われます)ためグリップが悪いと言いますが、ベンチマークは存在しません!これは本シリーズで共通するテーマです。人々は測定に基づく根拠がまったくない主張を繰り返しているのです4。
幸いなことに、プラットフォームと収益化に関するこの投稿で議論したように、Jonathan Bensonはタイヤに関する詳細な探究を収益化することができ、それにより、これまでにないレベルの詳細さを持つ公開タイヤベンチマークが生まれました。彼は異なる種類のタイヤが異なる温度や異なる条件下でどれだけ性能を発揮するかをテストしました。タイヤメーカーはこのようなテストをあらゆる種類行っているはずですが、私の知る限り、これが包括的な形で公開されたのは初めてでした(これは、コーディングエージェントの公開ベンチマークとそれほど変わらないように思えます)。
Bensonのテストでは、乾燥した条件下では、0℃/32℉まで(それより寒い条件ではテストしていません)サマータイヤが最もグリップが良く、次にオールシーズン、ウィンタータイヤはサマータイヤとオールシーズンの両方よりもかなり大きな差で劣ることがわかりました。ウェットな条件下では、0℃では単なるウェットではなく氷の状態になるため、2℃までしかテストしていません。順位は少し異なり、2℃のウェットではオールシーズンタイヤがサマータイヤを大きく上回りましたが、サマータイヤはそれでもウィンタータイヤを上回りました。
なお、動画でBensonがウィンタータイヤと呼んでいるものはUHPウィンタータイヤで、これは米国やカナダではほとんど見かけないものです(ただし、私は住んでいる地域の条件に合うため、ウィンタータイヤとしてこれを使っています)。彼が「ノルディック」タイヤと呼んでいるものは、ここや私がこれまで住んできた他のすべての場所で、ほとんどの人がウィンタータイヤとして使っているものです。これらの場所は、山に頻繁に車で行く場合(それでも、私が住んできたほとんどの人にとってはおそらくまだ適切な選択ではありません)や、氷の上で運転する時間が長い場合を除けば、その種のタイヤがあまり意味をなさない場所です。しかし、UHPウィンタータイヤの結果をオールシーズンと比較してみても、0℃以上の乾燥またはウェットな条件下ではオールシーズンの方が優れているということは依然として当てはまります。ただし、その差の大きさは、米国でほとんどの人が使っている「ノルディック」ウィンタータイヤと比較した場合よりもはるかに小さいです(彼が使っている用語はヨーロッパではより一般的なのかもしれません?)。
もちろん、タイヤが異なれば性能も異なり、異なるタイヤを使えば結果にもある程度のばらつきが出るでしょうし、もちろん、オールシーズンタイヤやサマータイヤよりもウィンタータイヤの方が優れている条件もたくさんありますが、寒さだけでオールシーズンタイヤが硬くなりすぎてグリップしなくなり、ウィンタータイヤが必須になるという考えは明らかに誤りです。
タイヤなんて誰が気にするのか?
ところで、そもそもなぜタイヤを気にすべきなのか疑問に思うかもしれませんが、平均すると、自動車事故はかなり主要な死因ですし、事故の深刻度に対する速度の影響を見るとかなり大きいので、もう少し速くブレーキをかけられたり、少しコーナリングが良くなったりして、事故を回避したり、衝撃を少し逸らせたりできるタイヤがあれば、事故の深刻度に大きな影響を与えるだろうと考えるのは理にかなっています。これは本当に良いデータがあるようなものではないと思います(ランダム化試験を実行するのは非常に困難ですし、観察データは一般的に大きく交絡します)。しかし、昨年行った分析の一環として、実際の衝突試験データにおけるHICと速度の関係を見つけようとしました。驚いたことに、これを行った論文は見つかりませんでした(ただし、このシリーズの演習になりうる論文はいくつか見つかりました)。しかし、素直な分析では、その関係はおよそ4乗に比例していました。本当はそれを衝突試験に関するこの他の投稿のような、HICや様々な車両の脳震盪リスクについて具体的に書いた投稿にまとめるべきなのですが!いずれにせよ、私は自分の安全のために、住んでいる地域に合った適切なタイヤを履いた車を運転するようにしています。なぜなら、それは1ドルあたり、あるいは労力あたりで、私自身の安全のためにできる影響が比較的大きい介入の一つであるように思えるからです。しかし、私の非常に優れたタイヤが違いを生んだような状況に遭遇したことは一度もありませんし、安全のために適切なタイヤを探そうとする人は、そもそも事故に遭う可能性が低いのかもしれないので、これはまったく意味のない単なる趣味かもしれません。
ベンチマークと評価におけるさらなる問題
この投稿が気に入った方は、これはベンチマーク、評価、実験計画に関する一連の演習の一部です(1、2、3、4、5、6)5。
Peter Geoghegan、Aaron Levin、Luke Burton、Em Chu、Jamie Brandon、Yossi Kreinin、Jeshua Smith、Ikhwan Leeの各氏に、コメント/修正/議論に感謝します。
付録:ディスクパフォーマンスに関する補足
以下は、ディスクパフォーマンスについて実際に詳しいPeter Geogheganによる補足コメントです:
特定のアクセスパターンについて、多少同等なSSD間でもパフォーマンスに大きなばらつきがあるのを見てきました。これはおそらくFTL/ファームウェアレベルの違いによるものです。一部のSSDは、OSのread ahead(先読み)とは無関係に、後方へのシーケンシャルリードが他のSSDよりはるかに優れているようです(direct IOの場合)。PostgresでインデックススキャンのためのIOプリフェッチに一緒に取り組んでいる人物による、この件についてのブログ投稿はこちらです:https://vondra.me/posts/fun-and-weirdness-with-ssds。
これらのことは依然としてOS/ファイルシステムからは不透明なままであると確信しています。このやや古いLWN.netの記事が、その根拠を提供しています:https://lwn.net/Articles/353411、「ファイルシステム開発者へのメッセージは『ただ我々を信じてくれ』そして『かわいいシステムプログラマーの頭でSSDの実装について心配しないでくれ』です。SSD実装についてもっと情報を求めるたびにそう言われるのです」。
2023年にLinuxハッカーのMatthew Wilcoxにこのことを尋ねたところ、状況はほぼ同じだと言われました。マイクロベンチマーク目的でパフォーマンスのばらつきを考慮したいのであれば、最善の方法は依然としてプロビジョニングについて非常に慎重になり、定期的にTRIMを実行することなどだとのことでした。
かつて(2015年頃だったと思います)、CPUパフォーマンスに関する演習やチュートリアルにしようと思ってコードを書いたことがあります。それはnapkin mathリポジトリのようなものでしたが、ずっと狭い範囲のものでした。アイデアは、次のような質問を用意することでした:
- CPU Xがあります。このループがどれくらい速いか知りたい場合、どんなパラメータを知る必要がありますか?
- これらのパラメータが与えられたとき、ループはどれくらい速いはずですか?
様々なことについて必要なコードは用意できましたが、なぜか私が書いたコードではDRAMのオープンページアクセスとクローズドページアクセスの違いが現れず、その後他のことに気を取られて書き上げることができませんでした。LLM以前は、この種のことを正しく行うのはかなり時間がかかりました。なぜなら、正しく行うためには、関与するメカニズムが何であるかについて十分に知り、その上でコードを書く際に注意を払い、何をしているかを確認する必要があるからです。そして、私は何かを間違えてしまい、それをデバッグする時間を十分に取らなかったため、コードに少なくとも1つの問題があることを示唆する謎が残ったまま、演習を書き上げることができませんでした。
いずれにせよ、ディスクはずっと複雑で、良い数値を得るにははるかに多くの注意が必要です。LLMがあれば、今ならそれほど時間をかけずに実現可能だと思いますが、それでもある程度の注意は必要でしょう。
P.S. (29)で言及した私の友人はJamie Brandonで、現在就職活動中で仕事を探しています。彼はデータベース(クエリエンジン)やストリーミングシステムに関する仕事をかなり行ってきました。彼の最もよく知られた文章はおそらくAgainst SQLですが、ストリーミングシステムの一貫性バグに関するこの分析など、他にも私の好きな記事をかなり書いています。彼は主にバンクーバー現地の仕事かリモートの仕事を探しています。彼と話をしたい方は、[email protected]まで連絡できます。
- 私はしばしばパフォーマンスエンジニアと間違われますが、どちらかというと、ハードウェアのバックグラウンド(そこではベンチマーク/評価/実験計画がソフトウェアよりも成熟した分野です。こちらで議論した通り)による、プログラマーとしては異常なほどのベンチマーク/評価/実験計画の経験と、このような、あるいはこのような金銭的価値に容易に結びつけられる問題に取り組む傾向が組み合わさって、時にパフォーマンス問題を解決することがある、という方が近いと思います。しかし、私は他の問題と同じくらいパフォーマンス問題を解決する可能性があり、日々パフォーマンスの仕事をしている人々と比べて、パフォーマンス問題に関する特に深く広い知識を持っているわけではありません。[return]
- 言語でフィルタリングすることが理にかなっているかどうかというトピックについては、この投稿で言語のトークン効率について人々が言及しているのを見た後に調べました。その投稿の結果は自明でないタスクでは再現しませんでしたが、言語間には言語でフィルタリングすることがもっともらしく理にかなうほどの、十分に現実的な違いがあるように思えました。特に、エージェントが何かを実装できないとき、特に低エフォートレベルでは、しばしば言語の特異で誤った使い方に起因します。例えば、その投稿のzstd評価では、Clojureを使うエージェントはバイト変換の誤ったセマンティクスに非常に頻繁に依存しましたが、根本的に同じ操作が利用可能なJavaを使うエージェントはその間違いを犯しませんでした。[return]
メタレベルでは、他のトピックでは私が妥当だと思うコメントをする人々は、一般的にこれらのヘッドライン/要約結果をあまり真剣に受け止めていません。
例えば、これらのベンチマークの有用性についてのコメントで、Em Chuは次のように述べました:
誤解を招くほど正確になることのないtwitter/hacker newsのセンチメントの方が、モデルが有用かどうかを知るためのより良い方法のように感じます。奇妙なことですが(残念ながらhacker newsの投稿を大量に読む必要があるので、お勧めはできません)。LLMベンチマークのように見えるものは、読む価値がある可能性がほぼゼロなので、目が勝手に飛ばしてしまいます。(hacker newsのコメントに対してもそうできればいいのですが)。
私が判断を信頼しているほとんどの人は同様のアプローチを取っています(時にオンラインのセンチメントの代わりに知り合いの意見を参考にします)。これの例外は一般的に、その分野で働いていて大量のベンチマークを見て、それらを頭の中で集約している人々です。例えば、RL環境のスタートアップを運営しているMax Bitkerと話すとき、彼は一見すべての公開ベンチマークに精通しており、世にあるすべてのベンチマークの集約的な全体像という彼のメンタルモデルに基づいて、モデルリリースの数週間後にセンチメントがどうなるかを予測できるように見えます。しかし、それは要約スコアの指標を見ることとはまったく異なることであり、AIの仕事をしていない限り、モデルの有効性を評価するために合理的に行うというよりは、趣味的な興味のように思えます(趣味的な興味を否定するつもりはありません。私にも趣味的な興味はたくさんあります)。
これらのベンチマークの結果を真剣に受け止めることと、現実世界で観察されることの具体例として、こちらのスレッドがあります。そこでは誰かがDeepSWEの結果を使って、当時新しい5.6 Sol/Terra/Lunaと5.5の有効性 vs. コストの表を作成しています。誰か(私も同意しますが、言い方は違うでしょう)がこう返信しています:
でたらめだ。実際にそのモデルを使ったのか、それともオナニーしてるだけなのか?この表によると5.6-sol xhighは5.5 xhighより安くて優れていることになる。一体どんな現実でそれが本当なんだ?
別の人が彼にこう返信しています:
どの現実でもない。ベンチマークのタスクは本当に単純なんだと思う。その場合はこの表は正しいかもしれない。
それはまったく公平ではないと思います(それが正しいように思えるタスクも試しました)。しかし、一般的に、人々は公開されているベンチマークが示しているものとは大きく異なる経験をしています。これは、直接知っている人々からランダムなインターネットのコメンターまで、かなりの数の人々に理解されているようです。しかし、それは普遍的ではなく、今でもこれらのスコアを広めて、なぜあるモデルやエフォートレベルを使っているのかを説明しようとする人々を見かけますが、一般的には正当化されるとは思えません。
[return]- 一般的に、私は多くの人が何度も目にするような一般的な主張でない限り、これらの例を演習にしません。なぜなら、まったく裏付けのない誤った主張は、一般的なケースではあまりにも頻繁に起こるため、それ自体はそれほど興味深いものではないからです。[return]
私はこれらを特に強い理由もなくPatreonで公開してきました。Patreonで少しお金は稼いでいますが、お金を最適化するのであれば、潜在的な仕事につながる可能性から得られる収益の潜在的な差が、Patreonで直接稼げる額をはるかに上回ることを考えると、すべてを公開するのが明らかに正しい選択だと思います。私が面接が非常に苦手であることを考えるとなおさらです(私は面接が形式的なだけの仕事でしかほぼ採用されたことがなく、そうでなければ面接に合格する確率はゼロに近いです。最後に面接を受けたときは、LeetCode形式の質問で電話スクリーニングに落ちましたし、それを通過しても、本当の面接であれば後で落ちるのが常です)。
私はもともと、「本物の」ブログ投稿にするには小さすぎたり、取るに足らなかったりすると思ったものをPatreonで公開し始めましたが、その後Patreonで公開する習慣がついてしまい、しばらく公開ブログをあまり書いていませんでした。
このような、一連の演習の一部である投稿は、まさにメインブログに載せるには小さすぎ、取るに足らないと感じられるカテゴリーに当てはまります。これについて意見があれば、ぜひ聞かせてください。
このシリーズの背後にある考えは、ベンチマークや評価をより良く行うための何らかのチュートリアルやブログ投稿を書きたいということでした。しかし、評価についての私の考えは、特定のプロセスに従うことよりも、間違いを避けることの方が重要だというものです。なので、一般的なケースで機能するステップバイステップのガイドという形式は実際にはありません。因果グラフを描き、そのグラフを見て潜在的な問題を把握するといった、実験計画へのアプローチがあることは知っています。例えば交絡(コライダーバイアス)などです。こうした手法を学ぶ前後で人々がどのようにデータ分析を行うかを見る限り、平均するとそれほど大きな違いは生まないと思います(少数の人々にとっては非常に有用ですが)。
実験計画の問題を回避するための一般化された方法としてのこれに対する批判をどこか(おそらくAndrew Gelmanから)で見かけましたが、問題はすべてがすべてと関連しているため、因果グラフを作成する際にも依然として自分の判断を適用しているということです。グラフが作成されれば機械的に問題を見つけられるようになっても、そもそも間違ったグラフを描くことを止めることはできません。
私が何年も前にMcElreathの『Statistical Rethinking』の最初の部分を読んだときに、厳密な統計分析につながる何らかのプロセスを学ぼうとして見かけた、漠然と関連する考えとして、実際にはそのようなプロセスは存在せず、最終的には何かが理にかなっているかどうかを判断するために自分の判断を使わなければならない、というものがありました。
そうであるなら、一連の演習がうまくいくのではないかと思い、1つの投稿に50問か100問ほどの演習を書くアイデアを思いつきました。それは小さな演習であれば十分に実現可能に思えますが、様々なことを学ぶ人々を見ていると、小さな演習をたくさん与えて、人々がその手法をより大きく複雑な演習に一般化してくれることを期待しても、通常はあまりうまくいかないことは明らかです。より大きく複雑な演習を加え始めると、すぐに長い投稿の長さを超えてしまいます。このブログの基準でさえ、Googleに対するFTCの2011-2012年の調査でFTCが何を間違えたかについての32,000語の投稿があります(参考までに、典型的な小説は80,000〜100,000語と言われることが多いです)。
一般的に、私はブログで複数回に分けた投稿を避けてきました。というのも、読者として、物事が1つの投稿にまとまっている方が、何回にもわたる長いシリーズに分散しているよりもずっと好ましいからです。著者はしばしば複数回投稿を好むことは理解しています。なぜなら、一般的にトラフィックが増え、投稿がソーシャルメディアでバイラルになる可能性が高まるからです。しかし、私は常にこのブログを、ページビューを最大化するよりも、自分が読みたいものにより近いものになるように最適化してきました。この場合、単一投稿バージョンはドアストッパーのような分厚いファンタジー小説と同じくらいの長さに簡単になり得ます(参考までに、Brandon Sandersonの『ストームライト・アーカイブ』は1冊あたり約450,000語と言われています)。この投稿の3つの演習で約7,000語であることを考えると、そのペースでは64投稿必要になり、まだ7つしかやっていませんが、64投稿分を書き上げるのに十分な問題は世の中に確実にあり、あとは時間を確保するだけの問題です。
[return]
記事をランダムに読む
コメント
ログインしてコメントする