random —疑似乱数を生成します
ソースコード: :source: `Lib / random.py`
このモジュールは、さまざまな分布の疑似乱数ジェネレーターを実装します。
整数の場合、範囲から均一に選択されます。 シーケンスの場合、ランダム要素の均一な選択、リストのランダム順列をインプレースで生成する関数、および置換なしのランダムサンプリングの関数があります。
実数直線には、一様分布、正規分布(ガウス分布)、対数正規分布、負の指数分布、ガンマ分布、およびベータ分布を計算する関数があります。 角度の分布を生成するために、フォンミーゼス分布が利用可能です。
ほとんどすべてのモジュール関数は、基本関数 random()に依存しています。この関数は、セミオープン範囲[0.0、1.0)で均一にランダムフロートを生成します。 Pythonは、コアジェネレーターとしてメルセンヌツイスターを使用します。 53ビットの高精度フロートを生成し、周期は2 ** 19937-1です。 Cの基本的な実装は、高速でスレッドセーフです。 メルセンヌツイスターは、現存する中で最も広範囲にテストされた乱数ジェネレーターの1つです。 ただし、完全に決定論的であるため、すべての目的に適しているわけではなく、暗号化の目的にはまったく適していません。
このモジュールによって提供される関数は、実際には random.Random クラスの非表示インスタンスのバインドされたメソッドです。 Random の独自のインスタンスをインスタンス化して、状態を共有しないジェネレーターを取得できます。
クラス Random は、独自に考案した別の基本ジェネレーターを使用する場合にもサブクラス化できます。その場合、random()
、seed()
、 [をオーバーライドします。 X167X]、およびsetstate()
メソッド。 オプションで、新しいジェネレーターはgetrandbits()
メソッドを提供できます。これにより、 randrange()は任意の広い範囲で選択を生成できます。
random モジュールは、システム関数 os.urandom()を使用してオペレーティングシステムによって提供されるソースから乱数を生成する SystemRandom クラスも提供します。
も参照してください
NS。 松本とT。 西村、「メルセンヌツイスター:623次元で等分配された均一疑似乱数ジェネレータ」、モデリングとコンピュータシミュレーションに関するACMトランザクションVol。 8、いいえ。 1、1月pp.3–301998。
Complementary-Multiply-with-Carryレシピは、長期間で比較的単純な更新操作を備えた互換性のある代替乱数ジェネレーターです。
簿記機能
- random.seed(a=None, version=2)
乱数ジェネレーターを初期化します。
a を省略した場合または
None
の場合は、現在のシステム時刻が使用されます。 ランダム性ソースがオペレーティングシステムによって提供される場合、システム時間の代わりにそれらが使用されます(可用性の詳細については、 os.urandom()関数を参照してください)。a がintの場合、直接使用されます。
バージョン2(デフォルト)では、 str 、 bytes 、または bytearray オブジェクトが int とそのすべてのビットに変換されます使用されています。
バージョン1(古いバージョンのPythonからランダムシーケンスを再現するために提供)では、 str および bytes のアルゴリズムがより狭い範囲のシードを生成します。
バージョン3.2で変更:文字列シードのすべてのビットを使用するバージョン2スキームに移行しました。
- random.getstate()
- ジェネレータの現在の内部状態をキャプチャするオブジェクトを返します。 このオブジェクトを setstate()に渡して、状態を復元できます。
- random.setstate(state)
- state は、 getstate()の前回の呼び出しから取得されている必要があり、 setstate()は、ジェネレーターの内部状態をその時点の状態に復元します。 getstate()が呼び出されました。
バイトの関数
- random.randbytes(n)
n ランダムバイトを生成します。
このメソッドは、セキュリティトークンの生成には使用しないでください。 代わりに secrets.token_bytes()を使用してください。
バージョン3.9の新機能。
整数の関数
- random.randrange(stop)
random.randrange(start, stop[, step]) range(start, stop, step)
からランダムに選択された要素を返します。 これはchoice(range(start, stop, step))
と同等ですが、実際には範囲オブジェクトを作成しません。位置引数パターンは、 range()のパターンと一致します。 関数が予期しない方法でキーワード引数を使用する可能性があるため、キーワード引数は使用しないでください。
バージョン3.2で変更: randrange()は、均等に分散された値の生成に関してより洗練されています。 以前は、
int(random()*n)
のようなスタイルを使用していたため、わずかに不均一な分布が生成される可能性がありました。バージョン3.10以降非推奨:非整数型から同等の整数への自動変換は非推奨になりました。 現在、
randrange(10.0)
はロスレスでrandrange(10)
に変換されています。 将来的には、これにより TypeError が発生します。バージョン3.10以降非推奨:
randrange(10.5)
やrandrange('10')
などの非整数値に対して発生した例外は、 ValueError から TypeErrorに変更されます。
- random.randint(a, b)
a <= N <= b
のようなランダムな整数 N を返します。randrange(a, b+1)
のエイリアス。
- random.getrandbits(k)
k ランダムビットを含む非負のPython整数を返します。 このメソッドはMersenneTwisterジェネレーターで提供され、他のいくつかのジェネレーターもAPIのオプション部分として提供する場合があります。 使用可能な場合、 getrandbits()を使用すると、 randrange()で任意の広い範囲を処理できます。
バージョン3.9で変更:このメソッドは、 k に対してゼロを受け入れるようになりました。
シーケンスの関数
- random.choice(seq)
- 空でないシーケンス seq からランダムな要素を返します。 seq が空の場合、 IndexError が発生します。
- random.choices(population, weights=None, *, cum_weights=None, k=1)
母集団から選択された要素の k サイズのリストを置き換えて返します。 集団が空の場合、 IndexError が発生します。
weights シーケンスが指定されている場合、相対的な重みに従って選択が行われます。 あるいは、 cum_weights シーケンスが指定されている場合、累積重みに従って選択が行われます(おそらく、 itertools.accumulate()を使用して計算されます)。 たとえば、相対的な重み
[10, 5, 30, 5]
は、累積的な重み[10, 15, 45, 50]
と同等です。 内部的には、相対的な重みは選択を行う前に累積的な重みに変換されるため、累積的な重みを指定すると作業を節約できます。weights も cum_weights も指定されていない場合、選択は同じ確率で行われます。 重みシーケンスを指定する場合は、母集団シーケンスと同じ長さである必要があります。 weights と cum_weights の両方を指定するのは TypeError です。
weights または cum_weights は、 random()によって返される float 値(整数、浮動小数点数を含む)と相互運用する任意の数値型を使用できます。 、および分数ですが、小数は含まれません)。 重みは非負で有限であると想定されます。 すべての重みがゼロの場合、 ValueError が発生します。
特定のシードに対して、均等に重み付けされた choices()関数は、通常、 choice()を繰り返し呼び出すのとは異なるシーケンスを生成します。 choices()で使用されるアルゴリズムは、内部の一貫性と速度のために浮動小数点演算を使用します。 choice()で使用されるアルゴリズムは、丸め誤差による小さなバイアスを回避するために、デフォルトで整数演算になり、選択が繰り返されます。
バージョン3.6の新機能。
バージョン3.9で変更:すべての重みがゼロの場合、 ValueError を発生させます。
- random.shuffle(x[, random])
シーケンス x を所定の位置でシャッフルします。
オプションの引数 random は、[0.0、1.0)でランダムな浮動小数点数を返す0引数の関数です。 デフォルトでは、これは関数 random()です。
不変のシーケンスをシャッフルして新しいシャッフルリストを返すには、代わりに
sample(x, k=len(x))
を使用します。len(x)
が小さい場合でも、 x の順列の総数は、ほとんどの乱数ジェネレーターの期間よりも急速に大きくなる可能性があることに注意してください。 これは、長いシーケンスのほとんどの順列を生成できないことを意味します。 たとえば、長さ2080のシーケンスは、メルセンヌツイスター乱数ジェネレーターの期間内に収まる最大のものです。
- random.sample(population, k, *, counts=None)
母集団シーケンスまたはセットから選択された一意の要素の k 長さリストを返します。 置換なしのランダムサンプリングに使用されます。
元の母集団を変更せずに、母集団の要素を含む新しいリストを返します。 結果のリストは選択順になっているため、すべてのサブスライスも有効なランダムサンプルになります。 これにより、ラッフルの当選者(サンプル)を大賞と2位の当選者(サブスライス)に分割できます。
母集団のメンバーは、ハッシュ可能または一意である必要はありません。 母集団に繰り返しが含まれている場合、各出現はサンプルで可能な選択です。
繰り返される要素は、一度に1つずつ指定することも、オプションのキーワードのみの counts パラメーターを使用して指定することもできます。 たとえば、
sample(['red', 'blue'], counts=[4, 2], k=5)
はsample(['red', 'red', 'red', 'red', 'blue', 'blue'], k=5)
と同等です。整数の範囲からサンプルを選択するには、 range()オブジェクトを引数として使用します。 これは、
sample(range(10000000), k=60)
の大規模な母集団からサンプリングする場合に特に高速で、スペース効率が高くなります。サンプルサイズが母集団サイズよりも大きい場合、 ValueError が発生します。
バージョン3.9で変更: counts パラメーターが追加されました。
実数値分布
次の関数は、特定の実数値分布を生成します。 関数パラメーターは、一般的な数学的手法で使用されているように、分布の方程式の対応する変数にちなんで名付けられています。 これらの方程式のほとんどは、統計テキストに記載されています。
- random.random()
- [0.0、1.0)の範囲内の次のランダムな浮動小数点数を返します。
- random.uniform(a, b)
a <= b
の場合はa <= N <= b
、b < a
の場合はb <= N <= a
となるように、ランダムな浮動小数点数 N を返します。終点値
b
は、式a + (b-a) * random()
の浮動小数点の丸めに応じて、範囲に含まれる場合と含まれない場合があります。
- random.triangular(low, high, mode)
low <= N <= high
であり、これらの境界の間に指定された mode があるように、ランダムな浮動小数点数 N を返します。 low および high の境界は、デフォルトで0と1になります。 mode 引数は、デフォルトで境界間の中間点になり、対称的な分布になります。
- random.betavariate(alpha, beta)
- ベータ分布。 パラメータの条件は、
alpha > 0
およびbeta > 0
です。 戻り値の範囲は0から1です。
- random.expovariate(lambd)
- 指数分布。 lambd は、1.0を目的の平均で割ったものです。 ゼロ以外である必要があります。 (パラメーターは「ラムダ」と呼ばれますが、Pythonでは予約語です。)戻り値の範囲は、 lambd が正の場合は0から正の無限大、 lambdの場合は負の無限大から0です。 は負です。
- random.gammavariate(alpha, beta)
ガンマ分布。 ( Not ガンマ関数!)パラメータの条件は
alpha > 0
とbeta > 0
です。確率分布関数は次のとおりです。
x ** (alpha - 1) * math.exp(-x / beta) pdf(x) = -------------------------------------- math.gamma(alpha) * beta ** alpha
- random.gauss(mu, sigma)
ガウス分布とも呼ばれる正規分布。 mu は平均であり、 sigma は標準偏差です。 これは、以下で定義する normalvariate()関数よりもわずかに高速です。
マルチスレッドに関する注意:2つのスレッドがこの関数を同時に呼び出すと、同じ戻り値を受け取る可能性があります。 これは3つの方法で回避できます。 1)各スレッドに乱数ジェネレーターの異なるインスタンスを使用させます。 2)すべての通話をロックします。 3)代わりに、低速ですがスレッドセーフな normalvariate()関数を使用してください。
- random.lognormvariate(mu, sigma)
- 正規分布をログに記録します。 この分布の自然対数を取ると、平均 mu と標準偏差シグマの正規分布が得られます。 mu には任意の値を指定でき、 sigma はゼロより大きくする必要があります。
- random.normalvariate(mu, sigma)
- 正規分布。 mu は平均であり、 sigma は標準偏差です。
- random.vonmisesvariate(mu, kappa)
- mu は、0〜2 * pi のラジアンで表される平均角度であり、 kappa は集中度パラメーターであり、ゼロ以上である必要があります。 。 kappa がゼロに等しい場合、この分布は0〜2 * pi の範囲で均一なランダム角度に減少します。
- random.paretovariate(alpha)
- パレート分布。 alpha は形状パラメータです。
- random.weibullvariate(alpha, beta)
- ワイブル分布。 alpha はスケールパラメータであり、 beta は形状パラメータです。
代替発電機
- class random.Random([seed])
random モジュールで使用されるデフォルトの疑似乱数ジェネレーターを実装するクラス。
- class random.SystemRandom([seed])
- os.urandom()関数を使用して、オペレーティングシステムによって提供されるソースから乱数を生成するクラス。 すべてのシステムで利用できるわけではありません。 ソフトウェアの状態に依存せず、シーケンスは再現できません。 したがって、 seed()メソッドは効果がなく、無視されます。 getstate()および setstate()メソッドが呼び出されると、 NotImplementedError が発生します。
再現性に関する注意事項
疑似乱数ジェネレーターによって与えられたシーケンスを再現できると便利な場合があります。 シード値を再利用することにより、複数のスレッドが実行されていない限り、同じシーケンスを実行から実行まで再現できるはずです。
ランダムモジュールのアルゴリズムとシード関数のほとんどは、Pythonのバージョン間で変更される可能性がありますが、次の2つの側面が変更されないことが保証されています。
- 新しいシード方法が追加されると、下位互換性のあるシーダーが提供されます。
- ジェネレータの
random()
メソッドは、互換性のあるシーダーに同じシードが与えられた場合、同じシーケンスを生成し続けます。
例
基本的な例:
>>> random() # Random float: 0.0 <= x < 1.0
0.37444887175646646
>>> uniform(2.5, 10.0) # Random float: 2.5 <= x <= 10.0
3.1800146073117523
>>> expovariate(1 / 5) # Interval between arrivals averaging 5 seconds
5.148957571865031
>>> randrange(10) # Integer from 0 to 9 inclusive
7
>>> randrange(0, 101, 2) # Even integer from 0 to 100 inclusive
26
>>> choice(['win', 'lose', 'draw']) # Single random element from a sequence
'draw'
>>> deck = 'ace two three four'.split()
>>> shuffle(deck) # Shuffle a list
>>> deck
['four', 'two', 'ace', 'three']
>>> sample([10, 20, 30, 40, 50], k=4) # Four samples without replacement
[40, 10, 50, 30]
シミュレーション:
>>> # Six roulette wheel spins (weighted sampling with replacement)
>>> choices(['red', 'black', 'green'], [18, 18, 2], k=6)
['red', 'green', 'black', 'black', 'red', 'black']
>>> # Deal 20 cards without replacement from a deck
>>> # of 52 playing cards, and determine the proportion of cards
>>> # with a ten-value: ten, jack, queen, or king.
>>> dealt = sample(['tens', 'low cards'], counts=[16, 36], k=20)
>>> dealt.count('tens') / 20
0.15
>>> # Estimate the probability of getting 5 or more heads from 7 spins
>>> # of a biased coin that settles on heads 60% of the time.
>>> def trial():
... return choices('HT', cum_weights=(0.60, 1.00), k=7).count('H') >= 5
...
>>> sum(trial() for i in range(10_000)) / 10_000
0.4169
>>> # Probability of the median of 5 samples being in middle two quartiles
>>> def trial():
... return 2_500 <= sorted(choices(range(10_000), k=5))[2] < 7_500
...
>>> sum(trial() for i in range(10_000)) / 10_000
0.7958
サンプルの平均の信頼区間を推定するために置換を伴うリサンプリングを使用する統計的ブートストラップの例:
# http://statistics.about.com/od/Applications/a/Example-Of-Bootstrapping.htm
from statistics import fmean as mean
from random import choices
data = [41, 50, 29, 37, 81, 30, 73, 63, 20, 35, 68, 22, 60, 31, 95]
means = sorted(mean(choices(data, k=len(data))) for i in range(100))
print(f'The sample mean of {mean(data):.1f} has a 90% confidence '
f'interval from {means[5]:.1f} to {means[94]:.1f}')
薬物とプラセボの効果の間に観察された差の統計的有意性または p値を決定するためのリサンプリング順列テストの例:
# Example from "Statistics is Easy" by Dennis Shasha and Manda Wilson
from statistics import fmean as mean
from random import shuffle
drug = [54, 73, 53, 70, 73, 68, 52, 65, 65]
placebo = [54, 51, 58, 44, 55, 52, 42, 47, 58, 46]
observed_diff = mean(drug) - mean(placebo)
n = 10_000
count = 0
combined = drug + placebo
for i in range(n):
shuffle(combined)
new_diff = mean(combined[:len(drug)]) - mean(combined[len(drug):])
count += (new_diff >= observed_diff)
print(f'{n} label reshufflings produced only {count} instances with a difference')
print(f'at least as extreme as the observed difference of {observed_diff:.1f}.')
print(f'The one-sided p-value of {count / n:.4f} leads us to reject the null')
print(f'hypothesis that there is no difference between the drug and the placebo.')
マルチサーバーキューの到着時間とサービス提供のシミュレーション:
from heapq import heappush, heappop
from random import expovariate, gauss
from statistics import mean, quantiles
average_arrival_interval = 5.6
average_service_time = 15.0
stdev_service_time = 3.5
num_servers = 3
waits = []
arrival_time = 0.0
servers = [0.0] * num_servers # time when each server becomes available
for i in range(100_000):
arrival_time += expovariate(1.0 / average_arrival_interval)
next_server_available = heappop(servers)
wait = max(0.0, next_server_available - arrival_time)
waits.append(wait)
service_duration = gauss(average_service_time, stdev_service_time)
service_completed = arrival_time + wait + service_duration
heappush(servers, service_completed)
print(f'Mean wait: {mean(waits):.1f} Max wait: {max(waits):.1f}')
print('Quartiles:', [round(q, 1) for q in quantiles(waits)])
も参照してください
Statistics for Hackers Jake Vanderplas による、シミュレーション、サンプリング、シャッフル、相互検証などのいくつかの基本的な概念を使用した統計分析に関するビデオチュートリアル。
経済シミュレーション Peter Norvig による市場のシミュレーションで、このモジュールが提供する多くのツールと分布(ガウス、均一、サンプル、ベータ変量、選択、三角形、およびrandrange)。
確率の具体的な紹介(Pythonを使用) Peter Norvig によるチュートリアルで、確率論の基礎、シミュレーションの記述方法、Pythonを使用したデータ分析の実行方法について説明します。
レシピ
デフォルトランダム() 範囲内の2⁻⁵³の倍数を返します 0.0≤x<1.0 。 このような数値はすべて等間隔であり、Pythonの浮動小数点数として正確に表すことができます。 ただし、その間隔内の他の多くの表現可能なフロートは、可能な選択ではありません。 たとえば、0.05954861408025609
は2⁻⁵³の整数倍ではありません。
次のレシピは別のアプローチを取ります。 間隔内のすべてのフロートが可能な選択です。 仮数は、範囲内の整数の一様分布に由来します 2⁵²≤仮数<2⁵³ 。 指数は、 -53 よりも小さい指数が次に大きい指数の半分の頻度で発生する幾何分布に由来します。
from random import Random
from math import ldexp
class FullRandom(Random):
def random(self):
mantissa = 0x10_0000_0000_0000 | self.getrandbits(52)
exponent = -53
x = 0
while not x:
x = self.getrandbits(32)
exponent += x.bit_length() - 32
return ldexp(mantissa, exponent)
クラス内のすべての実数値分布は、新しいメソッドを使用します。
>>> fr = FullRandom()
>>> fr.random()
0.05954861408025609
>>> fr.expovariate(0.25)
8.87925541791544
レシピは、範囲内の2⁻¹⁰⁷⁴のすべての倍数から選択するアルゴリズムと概念的に同等です。 0.0≤x<1.0 。 このような数値はすべて等間隔ですが、ほとんどの場合、最も近い表現可能なPython浮動小数点数に切り捨てる必要があります。 (値2⁻¹⁰⁷⁴は最小の正の正規化されていないフロートであり、math.ulp(0.0)
に等しくなります。)