閉じる

NumPyのrandnで正規分布を生成する方法:最新のGeneratorによる推奨実装まで解説

NumPyは、Pythonにおける数値計算を支える最も重要なライブラリの一つです。

データサイエンスや機械学習の現場では、シミュレーションやテストデータの作成のために「乱数」を生成する機会が非常に多くあります。

特に、平均が0で標準偏差が1である「標準正規分布」に従う乱数は、統計的な解析において頻繁に利用されます。

かつてのNumPyではnumpy.random.randnという関数が主流でしたが、現在のバージョンではより効率的で安全な新しい生成方法が推奨されています。

本記事では、従来のrandnの使い方から、2026年現在の標準となっているGeneratorを用いた推奨実装までを詳しく解説します。

NumPyで正規分布を扱うための基礎知識

正規分布とは、左右対称な釣鐘型の形状を持つ確率分布のことで、ガウス分布とも呼ばれます。

自然界の現象や社会的なデータの多くが、この正規分布に近い形を示すことが知られています。

NumPyはこの正規分布に従う乱数を高速に生成するための機能を備えています。

具体的には、特定の形状を持つ多次元配列として乱数を得ることが可能です。

まず、正規分布には「標準正規分布」と「一般の正規分布」の2種類があることを理解しておきましょう。

標準正規分布は、平均が0、標準偏差が1となる特別な正規分布です。

一方で、実務では平均や標準偏差を自由に指定した乱数が必要になることも多いでしょう。

NumPyでは、これらのどちらも簡単なコードで実装することができます。

従来の主流だったnumpy.random.randnとは

numpy.random.randnは、長らくNumPyにおける標準正規分布の生成関数として親しまれてきました。

この関数の最大の特徴は、引数に配列の形状を直接渡すだけで乱数を生成できる手軽さにあります。

例えば、2行3列の行列を作成したい場合は、引数に「2, 3」と指定します。

Python
import numpy as np

# 2行3列の標準正規分布に従う乱数を生成
data = np.random.randn(2, 3)
print(data)
実行結果
[[ 0.45612345 -1.23456789  0.98765432]
 [ -0.12345678  0.56789012 -0.87654321]]

非常にシンプルですが、現在のNumPyではこの関数を含むレガシーなnp.randomモジュールの直接使用は推奨されていません

それでも多くの既存コードで目にすることが多いため、仕組みを知っておくことは重要です。

randnを使用した平均と標準偏差の調整方法

randn関数はそのままでは標準正規分布(平均0、標準偏差1)の乱数しか生成しません。

しかし、数学的な変換を行うことで、任意の平均(μ)と標準偏差(σ)を持つ正規分布へと変換可能です。

変換式は非常に単純で、「(生成した乱数 × 標準偏差) + 平均」という計算を行います。

具体的に、平均を50、標準偏差を10に変更したい場合のコードを見てみましょう。

Python
import numpy as np

mu = 50       # 平均
sigma = 10    # 標準偏差

# 標準正規分布から乱数を生成し、変換を行う
samples = sigma * np.random.randn(1000) + mu

print(f"平均: {np.mean(samples)}")
print(f"標準偏差: {np.std(samples)}")
実行結果
平均: 49.982341...
標準偏差: 10.023412...

このように、基本的な四則演算を組み合わせるだけで、自由な分布を作成できます。

しかし、この計算を毎回手動で行うのは、コードの可読性を下げる要因にもなりかねません。

レガシーなnp.random関数の懸念点

なぜ現在、np.random.randnのような古い関数が推奨されなくなっているのでしょうか。

大きな理由の一つは、グローバルな乱数生成器の状態に依存していることです。

np.random.seed()を使用してシード値を固定すると、プログラム全体に影響が及びます。

これは、大規模な開発や複数のライブラリを組み合わせる際に、予期せぬ副作用を生む原因となります。

また、古い実装はパフォーマンスや統計的な品質の面でも、最新のアルゴリズムに劣る場合があります。

これらの問題を解決するために導入されたのが、次節で紹介するGeneratorです。

最新の推奨実装:Generatorオブジェクトの活用

2020年以降のNumPyでは、numpy.random.default_rng()を使用して生成器(Generator)を作成することが強く推奨されています。

この方法は、オブジェクト指向的なアプローチであり、乱数の状態をカプセル化できます。

これにより、他のコードと干渉することなく、再現性の高い乱数生成が可能になります。

default_rng()の基本的な使い方

まずは、Generatorのインスタンスを作成するところから始めます。

Python
import numpy as np

# Generatorの作成
rng = np.random.default_rng()

# 標準正規分布の生成
data = rng.standard_normal((2, 3))
print(data)

standard_normalメソッドは、従来のrandnと似ていますが、引数としてタプルで形状を渡す点が異なります。

この小さな違いが、NumPyの他の関数(np.zerosnp.onesなど)との一貫性を保つことにつながっています。

rng.normalによる柔軟な正規分布生成

最新のGeneratorでは、平均や標準偏差を直接指定できるnormalメソッドが非常に便利です。

先ほどのように手動で計算する必要はなく、引数にパラメータを渡すだけで済みます。

Python
import numpy as np

rng = np.random.default_rng(seed=42)

# 平均(loc), 標準偏差(scale), 形状(size)を指定
samples = rng.normal(loc=10.0, scale=2.0, size=(5,))
print(samples)
実行結果
[10.60848824  8.12511477 11.50057404 11.88457004 10.1518107 ]

このように、「loc」が平均、「scale」が標準偏差に対応しています。

コードが非常に読みやすくなり、意図が明確に伝わるようになります。

正規分布生成メソッドの比較表

NumPyで利用可能な正規分布生成メソッドの違いを表にまとめました。

メソッド名推奨度主な特徴
np.random.randn非推奨(レガシー)手軽だがグローバルな状態に依存する。引数の指定が独特。
rng.standard_normal推奨標準正規分布に特化。高速かつ安全な新しい生成器を使用。
rng.normal推奨平均や標準偏差を直接指定可能。汎用性が非常に高い。

正規分布データの可視化

生成した乱数が本当に正規分布に従っているかを確認するために、可視化を行ってみましょう。

Pythonの描画ライブラリであるMatplotlibを使用すると、簡単にヒストグラムを作成できます。

Python
import numpy as np
import matplotlib.pyplot as plt

# 乱数生成器の初期化
rng = np.random.default_rng()

# 大量のデータを生成
data = rng.normal(loc=0, scale=1, size=10000)

# ヒストグラムの描画
plt.hist(data, bins=50, density=True, alpha=0.7, color='skyblue')
plt.title("Normal Distribution (loc=0, scale=1)")
plt.xlabel("Value")
plt.ylabel("Frequency")
plt.show()

このコードを実行すると、美しい左右対称のベルカーブが表示されるはずです。

サンプルサイズ(size)を大きくするほど、理論的な正規分布の形状に近づいていきます。

実務での活用例:ノイズの付加

正規分布の乱数は、シミュレーションだけでなく、機械学習の学習データに「ノイズ」を加える際にも多用されます。

例えば、きれいな直線データに正規分布のノイズを加えることで、より現実に近いデータセットを作成できます。

Python
# 直線データ y = 2x + 1 の作成
x = np.linspace(0, 10, 100)
y_pure = 2 * x + 1

# 正規分布に従うノイズを生成
noise = rng.normal(loc=0, scale=1.0, size=x.shape)

# ノイズを付加
y_noisy = y_pure + noise

このような処理により、モデルの堅牢性をテストするためのデータを容易に準備できます。

現実世界のデータには必ずと言っていいほど誤差が含まれるため、この手法は非常に重要です。

再現性を保つためのシード値の管理

科学的な計算やレポートの作成において、「再現性」は極めて重要な要素です。

乱数を使用しながらも、毎回同じ結果を得るためにはシード(種)を固定する必要があります。

Generatorを使用する場合、default_rngの引数に整数を渡すだけで設定が完了します。

Python
# シード値を42に固定
rng1 = np.random.default_rng(42)
print(rng1.random())

# 再び同じシード値で生成器を作成
rng2 = np.random.default_rng(42)
print(rng2.random())

これにより、rng1rng2は全く同じ乱数列を生成することが保証されます。

共同開発や論文執筆の際には、必ずシード値を明示するようにしましょう。

まとめ

本記事では、NumPyを用いて正規分布に従う乱数を生成する方法について詳しく解説しました。

従来のnp.random.randnは非常にシンプルで使いやすい関数でしたが、現在のNumPyではGeneratorオブジェクトの使用が推奨されています。

rng.standard_normalrng.normalを活用することで、安全かつ柔軟に乱数を生成できるようになります。

特にrng.normalは平均と標準偏差を直感的に指定できるため、多くのケースで第一選択となるでしょう。

グローバルな状態を操作する古い手法から、インスタンスベースの新しい手法へと移行することで、プログラムの信頼性は大きく向上します。

今回紹介した最新の実装パターンを、ぜひあなたのプロジェクトでも活用してみてください。

URLをコピーしました!