乱数と擬似乱数
Random Numbers and Pseudorandom Numbers ・ らんすうとぎじらんすう
偶然を計算機の上で再現する仕組み。シミュレーションと無作為化の基盤
✦ 30秒で試す — 航海でたらめに見える乱数が、回すと平面の縞に並ぶRANDUで続けて出た2つが分かれば、次の1つは?予想してみる概要
乱数とは、次に何が出るか予測できない数の列のことです。サイコロを振って出た目を書き並べたものが典型で、どの値も等しい確率で現れ、過去の値から次の値を言い当てられない——この「偏りのなさ」と「予測できなさ」が乱数の本質です。統計学では標本抽出で対象を偏りなく選ぶために、実験では処置を無作為に割り付けるために、シミュレーションでは偶然そのものを実験材料にするために、乱数が欠かせません。
ところが計算機は決められた手順を正確に繰り返す機械で、本物の偶然を生み出せません。そこで使われるのが擬似乱数です。決定的な計算式で「乱数にしか見えない」数列を次々に作る仕組みで、出発点となる値(シード)が同じなら、まったく同じ列が再現されます。今日ソフトウェアで「乱数」と呼ばれるものの大半はこの擬似乱数です。
「乱数にしか見えない」とはどういうことか、が実はこの語彙の核心です。1つずつ見れば偏りのない値でも、続けて出る値どうしに隠れた規則があれば、シミュレーションの結果は静かに歪みます。どこまで本物らしければ十分か、再現できることは欠点か利点か——用途によって答えが変わります。
なぜ生まれたか
乱数がまとまった量で必要になったのは、20世紀前半の統計学からです。標本調査や実験計画法で「無作為に選ぶ・割り付ける」ことの重要性が確立すると、人間の恣意を排して選ぶ道具が要りました。人に適当な数を挙げさせると、特定の数字を避ける・同じ数字の連続を嫌うといった癖が必ず出るからです。そこで1927年のティペットの表を皮切りに、機械的に作った数字を並べた「乱数表」が出版され、研究者はそれを引いて標本を選びました。1955年にランド研究所が出した『百万個の乱数』はその集大成です。
決定打は電子計算機の登場でした。1940年代、核反応のモンテカルロ法シミュレーションのために乱数が大量に必要になりましたが、乱数表を計算機に読み込むのは遅く、物理的な乱数発生装置は同じ列を再現できないためデバッグが困難でした。そこでフォン・ノイマンは「前の値から計算式で次の値を作る」方法(平方採中法)を提案し、1949年にはレーマーが今も基本形として残る線形合同法を考案します。フォン・ノイマン本人が「算術的な方法で乱数を作ろうとする者は、言うまでもなく罪深い状態にある」と冗談めかしたとおり原理的には偶然の偽物ですが、高速・省メモリで、しかも同じ列を再現できる——科学計算にとってはむしろ本物より都合がよく、以後の標準になりました。
ただし「偽物」の代償は、やがて具体的な事故として現れます。1960〜70年代に広く使われた生成器 RANDU は、1つずつ見れば偏りがないのに、連続する3つの値が立体の中でわずか15枚の平面に並ぶという欠陥を抱えていました。1968年、マーサグリアは「乱数は主に平面に落ちる」という論文で、線形合同法で作った値の組が必ず有限個の平面に並ぶことを示し、RANDU はその最悪の例として知られるようになります。この教訓から、擬似乱数の評価は「1個ずつの偏り」から「連続する値の組の偏り」へと広がり、周期が長く多次元でも均一な生成器が求められるようになります。
詳細
擬似乱数の仕組み — シードと内部状態
擬似乱数生成器(PRNG: Pseudorandom Number Generator)の骨格は単純です。「内部状態」と呼ばれる数を持ち、決まった式で状態を更新しながら、状態から出力を取り出すことを繰り返します。最初の状態を決める値がシードです。
内部状態は有限の桁数しか持たないので、いつかは同じ状態に戻り、そこから先は同じ列の繰り返しになります。この長さが周期です。周期はふつう「状態の数」より長くはなれないため、状態を大きく取るほど長い周期を作れます。現代の標準的な生成器の周期は、宇宙の年齢のあいだ回し続けても使い切れない長さです。
線形合同法と「平面に落ちる」問題
初期の代表例である線形合同法は、「前の値に定数 a を掛け、定数 c を足し、m で割った余りを次の値にする」だけの式です。出力を m で割れば0〜1の数になります。計算が軽く、パラメータを正しく選べば周期も m 近くまで伸ばせるため、長く標準でした。
弱点は、掛け算と余りだけでできているために、連続する値のあいだに一次式の関係が残ることです。RANDU(a = 65539、c = 0、m = 2³¹)では 65539 = 2¹⁶ + 3 という選び方のせいで、どの3つの連続した値も xₙ₊₂ = 6xₙ₊₁ − 9xₙ(を1で割った余り)を満たしてしまいます。すると3つ組 (xₙ, xₙ₊₁, xₙ₊₂) を座標とする点は、立方体の中の15枚の平行な平面の上にしか乗りません。1つずつの値の分布(ヒストグラム)はきれいに平らで、どの値も同じくらい出るのに、です。
立体を準備しています…
1960〜70年代に広く使われた乱数生成器 RANDU の出力です。一見どこにも偏りのない雲ですね。ドラッグで回して、点が縞に並ぶ角度を探してみてください(見つからなければ「縞が見える角度へ」)。
点の座標 = 連続する3つの乱数 (xₙ, xₙ₊₁, xₙ₊₂)。良い生成器ならどの角度から見ても一様な雲になる
回して確かめると、平面は「ちょうど真横から見る角度」でしか見えず、少しずれただけで一様な雲に溶けてしまいます。これが RANDU が長く使われ続けた理由でもあります。1次元の頻度や2つ組の検定には合格してしまうので、3次元の構造を見るまで欠陥に気づけなかったのです。粒子を3次元空間にばらまく物理シミュレーションでこの生成器を使えば、粒子は空間の限られた層にしか置かれず、結果は気づかれないまま歪みます。
平面の枚数が少ないほど、その隙間に点が1つも来ない「空白の層」が厚くなり、生成器の質は悪くなります。線形合同法はどんなパラメータでも次元を上げれば必ずこの格子構造を持つので、現在の多くの言語では、周期が長く高次元でも均一に分布するよう設計されたメルセンヌ・ツイスタ(周期 2¹⁹⁹³⁷ − 1)や PCG、xoshiro 系などが標準です。生成器の品質は、TestU01 のような統計的検定の大規模な集合で「何次元まで、どれだけの検定に合格するか」で比べられます。
一様乱数から任意の分布へ
生成器が直接吐くのは、ふつう0〜1に均等に散らばる一様分布の乱数です。しかし実験で欲しいのは正規分布に従う値だったり、サイコロの目だったりします。そこで変換を使います。基本形は、目的の確率分布の累積分布関数(ある値以下になる確率を返す関数)の逆関数に一様乱数を通す逆関数法です。累積確率は必ず0〜1に収まるので、一様乱数を「累積確率の目盛り」とみなして逆引きすれば、任意の分布に従う値が得られます。正規乱数専用のボックス=ミュラー法、密度の形の下に点を打って採否を決める棄却法など変換法は豊富にあり、「一様乱数さえ良質なら、どんな分布の偶然でも作れる」ことが乱数ライブラリの設計原理になっています。裏を返せば、一様乱数の欠陥は、そこから作ったすべての分布に持ち込まれます。
再現性 — 欠点ではなく機能
「シードが同じなら同じ列」という決定性は、偶然の偽物としては欠点ですが、道具としては第一級の機能です。シミュレーション研究では、シードを明記すれば誰でも結果を追試できます。機械学習ではシードを固定して、条件の違いだけを比べられるようにします。乱数を使ったテストが失敗したときも、同じシードで再実行すればバグを確実に再現できます。ランダム化比較試験でも、割り付け表をシード付きの擬似乱数で作って記録しておけば、後から「本当に無作為に割り付けたのか」を第三者が検証できます。
実務の落とし穴
よくある失敗の多くは、生成器そのものではなく使い方にあります。第一に、シードの扱い。並列に走らせる複数のワーカーに同じシードを渡すと、全員が同じ乱数列を使い、1000回のつもりのシミュレーションが実質1回分の情報しか持たなくなります。逆に「毎回、現在時刻をシードにする」とそもそも再現できません。ライブラリが用意する「独立なストリームを分岐させる」仕組みを使い、元のシードを記録するのが定石です。第二に、整数への変換。32ビットの乱数を n で割った余りで 0〜n−1 を作ると、n が2のべきでない限り小さい値がわずかに出やすくなります(剰余バイアス)。ライブラリの範囲指定関数を使えば避けられます。第三に、「いい結果が出るまでシードを変えて回し直す」こと。これは乱数を使ったp値ハッキングであり、シードを事前に決めて記録する習慣が防波堤になります。
統計用と暗号用 — 混同してはいけない境界
擬似乱数には用途による決定的な区別があります。統計・シミュレーション用の生成器は、偏りのなさと速度を目的に設計されており、出力をしばらく観察すれば内部状態を逆算できるものが少なくありません(メルセンヌ・ツイスタは連続する624個の出力から以後の列を完全に予測できます)。パスワードやトークン、くじの当選番号をこれで作ると、攻撃者に「次の乱数」を当てられてしまいます。暗号用途には、予測不能性を保証するよう設計された暗号論的擬似乱数生成器(CSPRNG)や、OS が熱雑音などの物理現象から集めた乱数源を使わなければなりません。「統計的にランダムに見える」ことと「敵に予測されない」ことは別の要件であり、この境界の混同は実際に多くのセキュリティ事故を生んできました。
試問
1960〜70年代に広く使われた乱数生成器 RANDU の出力から、連続する3つの値を (x, y, z) の座標にして、立方体の中に点を打ってあります。一見どこにも偏りのない雲です。試問では「縞が見える角度へ」のボタンはありません。立体をドラッグして回してください。
立体を準備しています…
1960〜70年代に広く使われた乱数生成器 RANDU の出力です。一見どこにも偏りのない雲ですね。ドラッグで回して、点が縞に並ぶ角度を探してみてください(下の「平面とのずれ」が 0° に近づく向きへ)。
点の座標 = 連続する3つの乱数 (xₙ, xₙ₊₁, xₙ₊₂)。良い生成器ならどの角度から見ても一様な雲になる
