世界を動かす技術を、日本語で。

不確実

2025年8月29日原文(nshipster.com)

概要

  • 現代のソフトウェア開発 では、「確信」と「不確実性」のバランスが重要課題
  • Uncertain<T> の導入により、プログラムで不確実性を直接扱う方法を解説
  • 確率分布やモンテカルロ法 を使った実践的なコード例を紹介
  • パフォーマンスと精度のトレードオフ、現実的な導入ステップも提案
  • 不確実性を認める設計思想 が、より賢いソフトウェアにつながる主張

人はなぜ「確信」に惹かれるのか

  • 人間社会 では「自信」が魅力となりやすい傾向
  • ソフトウェア開発 では、経験を積むほど「it depends」と言わざるを得ない現実
  • 個人ブランディング において、ニュアンスよりも断言が注目されやすい現状
  • 「正しさ」よりも「確信」が求められる 風潮
  • 現場の会話 で「let’s ship it and iterate」や「that won’t scale」が多用される理由

プログラムにおける「不確実性」の扱い

  • GPS座標 など多くのデータは本質的に「ノイズ」を含む
  • Bool型 などの従来の型では「確率的な不確実性」を表現できない問題
  • currentLocation.distance(to: target) < 100 のようなコードは、曖昧さを反映できない
  • CLLocationのhorizontalAccuracy など、実際は「だいたい」の値
  • 現行のプログラミングモデル は「波動関数を早期に収束させてしまう」比喩

Uncertain<T>型による新しい抽象化

  • Uncertain<T> は「不確実性」を型システムに組み込む発想

  • University of WashingtonとMicrosoft Research による論文「Uncertain<T>: A First-Order Type for Uncertain Data」が起源

  • C#実装 だが、Swiftへの移植も容易

  • Uncertain<CLLocation>.from(currentLocation) のような使い方で「不確実な値」を生成

  • 比較演算子 もUncertain<Bool>を返し、確率として扱える

    • 例: nearbyEvidence.probability(exceeds: 0.95) で95%信頼度を判定
  • 計算グラフ を構築し、必要な時だけサンプリング

  • Sequential Probability Ratio Testing (SPRT) でサンプル数を自動調整

    • 単純な比較なら十数回、複雑な計算なら数百回サンプリング

モンテカルロ法で直感的に理解

  • 確率計算 が難しい場合、 モンテカルロ法 で「試行回数」を増やし期待値を算出
  • スロットマシン の実装例で、理論値ではなく「実際に回してみる」ことで期待値を推定
  • 例: Uncertain<Int> { SlotMachine.spin() }.expectedValue(sampleCount: 10_000)

多様な確率分布と統計演算

  • Uncertain<T> は様々な確率分布を標準搭載

    • 正規分布(センサーのノイズ)
    • ベルヌーイ分布(ユーザー行動)
    • 指数分布(ネットワーク遅延)
    • 混合分布(カフェ来店時間など)
  • 統計操作 も簡単

    • 期待値、標準偏差、信頼区間、歪度、尖度、エントロピー、最頻値など
    • cdf で累積確率も取得可能
  • サンプリング数 は用途に応じて調整可能

実践的な導入ステップと注意点

  • 段階的移行 が推奨、重要な経路からUncertain<T>型を導入
  • 拡張メソッド で既存型に「uncertain」プロパティを追加可能
  • UI用途は高速・低精度、重要判定は高精度・多サンプル で使い分け
  • 計算コスト を意識し、パフォーマンスに注意

不確実性を受け入れる設計思想

  • 「不確実性を消す」ではなく「受け入れて扱う」ことがゴール
  • 現実世界 では「不確実性」こそが唯一の確実
  • よりスマートなソフトウェア を目指すための道筋

まとめ

  • Uncertain<T> は「確率的な不確実性」をプログラムで自然に扱うための強力な抽象化
  • 段階的な導入パフォーマンス配慮 が現実的なアプローチ
  • 人間の認知や現実世界に即した設計 が、信頼性と使いやすさを両立する鍵

Hackerたちの意見

これは異なる変数間の共分散を扱ってるの?例えば、距離を測ってる対象の位置にも誤差があるだろうし、それが自分の位置と相関してるかもしれないよね(例えば、同じ時間に動作してる別のGPSからのデータだったら)。確かに、型システムの中で単変量モデルは役立つかもしれないけど、共分散を扱えるとさらに強力で正確になると思う。

量子力学を正しくモデル化するには、絡み合った変数のセットに複素数値の波動関数を関連付ける必要があるよ。

共分散を追跡する必要があるなら、Pythonでgvarを使ってみるといいかも。 https://gvar.readthedocs.io/en/latest/

小さな注意点だけど、GPSは特定の条件、つまり開けた空や長時間のフィックスの時にだけ円形の不確実性でうまく近似されるんだ。完全な不確実性モデルはもっと複雑だから、エラーを測定する方法がたくさんあるんだよね。これは、フィックスを最初から点の位置として扱わなくなるような多くの状況でも重要になる。具体的な例を挙げると、自動運転車は、位置特定の不確実性が非円形のマルチパス効果に支配される状況に直面することがある。これを突き詰めていくと、最終的にはパーティクルフィルターやそれに似たものを再発明することになるよ。

車両のGPSは、通常、スピードメーターやコンパス、マップに載ってる道路のどれかにいるという前提など、たくさんの追加センサーや仮定によって強化されてるんだ。最後に電源を入れてから位置が変わってないと仮定できるから、早くフィックスが取れるのも大きいよね。

たぶん、Uncertainがデフォルトで、ほんとに確信があるときだけタイプをcertain Tとして注釈を付けるべきだよね。 ;)

Optionalの補完だね。

物理的な測定だけの話だね。お金みたいなものは、かなり正確に、時には小数点以下のセントまで確信を持っているべきだよ。現代のFortranライブラリのいくつかでも、似たようなアプローチが実装されているみたい。

機械工学の図面で職人とコミュニケーションを取るためには、許容範囲を使うんだ。例えば、10cm +8mm/-3mmみたいに、許容される範囲を示す。GPSに「もう着いた?」みたいなことを言うときは、エラーの方向や不確実性のどの方向が良いか悪いかを理解してるべきだと思う。

この表記について気になっているのは、時々「限界を超えられない」という意味になったり、時々「限界を超えるのは10%の確率である」という意味になったりすることなんだよね。

もっと「近似的」な考え方をしているなら(実験物理学のラボやその学部の授業でよくある、実世界の再サンプリングされた歪んだ分布を得るためのシミュレーションによる伝播とは対照的に)、小さな誤差のための誤差伝播(https://en.wikipedia.org/wiki/Propagation_of_uncertainty)の簡略化ができるよ。それから「ルート」誤差を「下流誤差」に変換するのは、単純な連鎖律の微積分の話だね。(毎週か二週間に一度は使っているNimライブラリがあるよ。タイミングを測るときにね。)データや測定を誤差が小さい領域に持っていくには、ちょっとした「工夫」が必要だから、現実のデータに見られる長い/太い/重い尾を持つ奇妙な形の分布に対しては、こういう不確実性を使う方がいいと思う。{ もしコストが他の面で邪魔にならないなら、という前提だけどね。記事のシニアエンジニアの言う通り。 }

これはこのクラシックなファンクショナルパールに密接に関連しているね:https://web.engr.oregonstate.edu/~erwig/papers/PFP_JFP06.pdf すごくクールだよ!僕はHaskellの入門コースを始めるときに、モンティ・ホール問題を確率モナドを使ってデモするんだ。2つの戦略で勝つ確率を分数で正確に出すために有理数を使うんだよ。

Hacker Newsで議論の続きを見る