random --- 生成偽隨機(jī)數(shù)?
源碼: Lib/random.py
該模塊實(shí)現(xiàn)了各種分布的偽隨機(jī)數(shù)生成器。
對(duì)于整數(shù),從范圍中有統(tǒng)一的選擇。 對(duì)于序列,存在隨機(jī)元素的統(tǒng)一選擇、用于生成列表的隨機(jī)排列的函數(shù)、以及用于隨機(jī)抽樣而無(wú)需替換的函數(shù)。
在實(shí)數(shù)軸上,有計(jì)算均勻、正態(tài)(高斯)、對(duì)數(shù)正態(tài)、負(fù)指數(shù)、伽馬和貝塔分布的函數(shù)。 為了生成角度分布,可以使用 von Mises 分布。
幾乎所有模塊函數(shù)都依賴于基本函數(shù) random() ,它在半開(kāi)放區(qū)間 [0.0,1.0) 內(nèi)均勻生成隨機(jī)浮點(diǎn)數(shù)。 Python 使用 Mersenne Twister 作為核心生成器。 它產(chǎn)生 53 位精度浮點(diǎn)數(shù),周期為 2**19937-1 ,其在 C 中的底層實(shí)現(xiàn)既快又線程安全。 Mersenne Twister 是現(xiàn)存最廣泛測(cè)試的隨機(jī)數(shù)發(fā)生器之一。 但是,因?yàn)橥耆_定性,它不適用于所有目的,并且完全不適合加密目的。
這個(gè)模塊提供的函數(shù)實(shí)際上是 random.Random 類的隱藏實(shí)例的綁定方法。 你可以實(shí)例化自己的 Random 類實(shí)例以獲取不共享狀態(tài)的生成器。
如果你想使用自己設(shè)計(jì)的不同基礎(chǔ)生成器,類 Random?也可以作為子類:在這種情況下,重載 random() 、 seed() 、 getstate() 以及 setstate()?方法??蛇x地,新生成器可以提供 getrandbits() 方法——這允許 randrange() 在任意大的范圍內(nèi)產(chǎn)生選擇。
random 模塊還提供 SystemRandom 類,它使用系統(tǒng)函數(shù) os.urandom() 從操作系統(tǒng)提供的源生成隨機(jī)數(shù)。
警告
不應(yīng)將此模塊的偽隨機(jī)生成器用于安全目的。 有關(guān)安全性或加密用途,請(qǐng)參閱 secrets 模塊。
參見(jiàn)
M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-dimensionally equidistributed uniform pseudorandom number generator", ACM Transactions on Modeling and Computer Simulation Vol. 8, No. 1, January pp.3--30 1998.
Complementary-Multiply-with-Carry recipe 用于兼容的替代隨機(jī)數(shù)發(fā)生器,具有長(zhǎng)周期和相對(duì)簡(jiǎn)單的更新操作。
簿記功能?
-
random.seed(a=None, version=2)? 初始化隨機(jī)數(shù)生成器。
如果 a 被省略或?yàn)?
None,則使用當(dāng)前系統(tǒng)時(shí)間。 如果操作系統(tǒng)提供隨機(jī)源,則使用它們而不是系統(tǒng)時(shí)間(有關(guān)可用性的詳細(xì)信息,請(qǐng)參閱os.urandom()函數(shù))。如果 a 是 int 類型,則直接使用。
對(duì)于版本2(默認(rèn)的),
str、bytes或bytearray對(duì)象轉(zhuǎn)換為int并使用它的所有位。對(duì)于版本1(用于從舊版本的Python再現(xiàn)隨機(jī)序列),用于
str和bytes的算法生成更窄的種子范圍。在 3.2 版更改: 已移至版本2方案,該方案使用字符串種子中的所有位。
-
random.getstate()? 返回捕獲生成器當(dāng)前內(nèi)部狀態(tài)的對(duì)象。 這個(gè)對(duì)象可以傳遞給
setstate()來(lái)恢復(fù)狀態(tài)。
-
random.setstate(state)? state 應(yīng)該是從之前調(diào)用
getstate()獲得的,并且setstate()將生成器的內(nèi)部狀態(tài)恢復(fù)到getstate()被調(diào)用時(shí)的狀態(tài)。
-
random.getrandbits(k)? 返回帶有 k 位隨機(jī)的Python整數(shù)。 此方法隨 MersenneTwister 生成器一起提供,其他一些生成器也可以將其作為API的可選部分提供。 如果可用,
getrandbits()啟用randrange()來(lái)處理任意大范圍。
整數(shù)用函數(shù)?
-
random.randrange(stop)? -
random.randrange(start, stop[, step]) 從
range(start, stop, step)返回一個(gè)隨機(jī)選擇的元素。 這相當(dāng)于choice(range(start, stop, step)),但實(shí)際上并沒(méi)有構(gòu)建一個(gè) range 對(duì)象。位置參數(shù)模式匹配
range()。不應(yīng)使用關(guān)鍵字參數(shù),因?yàn)樵摵瘮?shù)可能以意外的方式使用它們。在 3.2 版更改:
randrange()在生成均勻分布的值方面更為復(fù)雜。 以前它使用了像``int(random()*n)``這樣的形式,它可以產(chǎn)生稍微不均勻的分布。
-
random.randint(a, b)? 返回隨機(jī)整數(shù) N 滿足
a <= N <= b。相當(dāng)于randrange(a, b+1)。
序列用函數(shù)?
-
random.choice(seq)? 從非空序列 seq 返回一個(gè)隨機(jī)元素。 如果 seq 為空,則引發(fā)
IndexError。
-
random.choices(population, weights=None, *, cum_weights=None, k=1)? 從*population*中選擇替換,返回大小為 k 的元素列表。 如果 population 為空,則引發(fā)
IndexError。如果指定了 weight 序列,則根據(jù)相對(duì)權(quán)重進(jìn)行選擇。 或者,如果給出 cum_weights 序列,則根據(jù)累積權(quán)重(可能使用
itertools.accumulate()計(jì)算)進(jìn)行選擇。 例如,相對(duì)權(quán)重``[10, 5, 30, 5]``相當(dāng)于累積權(quán)重``[10, 15, 45, 50]``。 在內(nèi)部,相對(duì)權(quán)重在進(jìn)行選擇之前會(huì)轉(zhuǎn)換為累積權(quán)重,因此提供累積權(quán)重可以節(jié)省工作量。如果既未指定 weight 也未指定 cum_weights ,則以相等的概率進(jìn)行選擇。 如果提供了權(quán)重序列,則它必須與 population 序列的長(zhǎng)度相同。 一個(gè)
TypeError指定了 weights 和*cum_weights*。weights 或 cum_weights 可以使用任何與
random()返回的float值互操作的數(shù)值類型(包括整數(shù),浮點(diǎn)數(shù)和分?jǐn)?shù)但不包括十進(jìn)制小數(shù))。對(duì)于給定的種子,具有相等加權(quán)的
choices()函數(shù)通常產(chǎn)生與重復(fù)調(diào)用choice()不同的序列。choices()使用的算法使用浮點(diǎn)運(yùn)算來(lái)實(shí)現(xiàn)內(nèi)部一致性和速度。choice()使用的算法默認(rèn)為重復(fù)選擇的整數(shù)運(yùn)算,以避免因舍入誤差引起的小偏差。3.6 新版功能.
-
random.shuffle(x[, random])? 將序列 x 隨機(jī)打亂位置。
可選參數(shù) random 是一個(gè)0參數(shù)函數(shù),在 [0.0, 1.0) 中返回隨機(jī)浮點(diǎn)數(shù);默認(rèn)情況下,這是函數(shù)
random()。要改變一個(gè)不可變的序列并返回一個(gè)新的打亂列表,請(qǐng)使用``sample(x, k=len(x))``。
請(qǐng)注意,即使對(duì)于小的
len(x),x 的排列總數(shù)也可以快速增長(zhǎng),大于大多數(shù)隨機(jī)數(shù)生成器的周期。 這意味著長(zhǎng)序列的大多數(shù)排列永遠(yuǎn)不會(huì)產(chǎn)生。 例如,長(zhǎng)度為2080的序列是可以在 Mersenne Twister 隨機(jī)數(shù)生成器的周期內(nèi)擬合的最大序列。
-
random.sample(population, k)? 返回從總體序列或集合中選擇的唯一元素的 k 長(zhǎng)度列表。 用于無(wú)重復(fù)的隨機(jī)抽樣。
返回包含來(lái)自總體的元素的新列表,同時(shí)保持原始總體不變。 結(jié)果列表按選擇順序排列,因此所有子切片也將是有效的隨機(jī)樣本。 這允許抽獎(jiǎng)獲獎(jiǎng)?wù)撸颖荆┍粍澐譃榇螵?jiǎng)和第二名獲勝者(子切片)。
總體成員不必是 hashable 或 unique 。 如果總體包含重復(fù),則每次出現(xiàn)都是樣本中可能的選擇。
要從一系列整數(shù)中選擇樣本,請(qǐng)使用
range()對(duì)象作為參數(shù)。 對(duì)于從大量人群中采樣,這種方法特別快速且節(jié)省空間:sample(range(10000000), k=60)。如果樣本大小大于總體大小,則引發(fā)
ValueError。
實(shí)值分布?
以下函數(shù)生成特定的實(shí)值分布。如常用數(shù)學(xué)實(shí)踐中所使用的那樣, 函數(shù)參數(shù)以分布方程中的相應(yīng)變量命名;大多數(shù)這些方程都可以在任何統(tǒng)計(jì)學(xué)教材中找到。
-
random.random()? 返回 [0.0, 1.0) 范圍內(nèi)的下一個(gè)隨機(jī)浮點(diǎn)數(shù)。
-
random.uniform(a, b)? 返回一個(gè)隨機(jī)浮點(diǎn)數(shù) N ,當(dāng)
a <= b時(shí)a <= N <= b,當(dāng)b < a時(shí)b <= N <= a。取決于等式
a + (b-a) * random()中的浮點(diǎn)舍入,終點(diǎn)b可以包括或不包括在該范圍內(nèi)。
-
random.triangular(low, high, mode)? 返回一個(gè)隨機(jī)浮點(diǎn)數(shù) N ,使得
low <= N <= high并在這些邊界之間使用指定的 mode 。 low 和 high 邊界默認(rèn)為零和一。 mode 參數(shù)默認(rèn)為邊界之間的中點(diǎn),給出對(duì)稱分布。
-
random.betavariate(alpha, beta)? Beta 分布。 參數(shù)的條件是
alpha > 0和beta > 0。 返回值的范圍介于 0 和 1 之間。
-
random.expovariate(lambd)? 指數(shù)分布。 lambd 是 1.0 除以所需的平均值,它應(yīng)該是非零的。 (該參數(shù)本應(yīng)命名為 “l(fā)ambda” ,但這是 Python 中的保留字。)如果 lambd 為正,則返回值的范圍為 0 到正無(wú)窮大;如果 lambd 為負(fù),則返回值從負(fù)無(wú)窮大到 0。
-
random.gammavariate(alpha, beta)? Gamma 分布。 ( 不是 gamma 函數(shù)! ) 參數(shù)的條件是
alpha > 0和beta > 0。概率分布函數(shù)是:
x ** (alpha - 1) * math.exp(-x / beta) pdf(x) = -------------------------------------- math.gamma(alpha) * beta ** alpha
-
random.gauss(mu, sigma)? 高斯分布。 mu 是平均值,sigma 是標(biāo)準(zhǔn)差。 這比下面定義的
normalvariate()函數(shù)略快。
-
random.lognormvariate(mu, sigma)? 對(duì)數(shù)正態(tài)分布。 如果你采用這個(gè)分布的自然對(duì)數(shù),你將得到一個(gè)正態(tài)分布,平均值為 mu 和標(biāo)準(zhǔn)差為 sigma 。 mu 可以是任何值,sigma 必須大于零。
-
random.normalvariate(mu, sigma)? 正態(tài)分布。 mu 是平均值,sigma 是標(biāo)準(zhǔn)差。
-
random.vonmisesvariate(mu, kappa)? 馮·米塞斯分布。 mu 是平均角度,以弧度表示,介于0和 2*pi 之間,kappa 是濃度參數(shù),必須大于或等于零。 如果 kappa 等于零,則該分布在 0 到 2*pi 的范圍內(nèi)減小到均勻的隨機(jī)角度。
-
random.paretovariate(alpha)? 帕累托分布。 alpha 是形狀參數(shù)。
-
random.weibullvariate(alpha, beta)? 威布爾分布。 alpha 是比例參數(shù),beta 是形狀參數(shù)。
替代生成器?
-
class
random.SystemRandom([seed])? 使用
os.urandom()函數(shù)的類,用從操作系統(tǒng)提供的源生成隨機(jī)數(shù)。 這并非適用于所有系統(tǒng)。 也不依賴于軟件狀態(tài),序列不可重現(xiàn)。 因此,seed()方法沒(méi)有效果而被忽略。getstate()和setstate()方法如果被調(diào)用則引發(fā)NotImplementedError。
關(guān)于再現(xiàn)性的說(shuō)明?
有時(shí)能夠重現(xiàn)偽隨機(jī)數(shù)生成器給出的序列是有用的。 通過(guò)重新使用種子值,只要多個(gè)線程沒(méi)有運(yùn)行,相同的序列就可以在兩次不同運(yùn)行之間重現(xiàn)。
大多數(shù)隨機(jī)模塊的算法和種子函數(shù)都會(huì)在 Python 版本中發(fā)生變化,但保證兩個(gè)方面不會(huì)改變:
如果添加了新的播種方法,則將提供向后兼容的播種機(jī)。
當(dāng)兼容的播種機(jī)被賦予相同的種子時(shí),生成器的
random()方法將繼續(xù)產(chǎn)生相同的序列。
例子和配方?
基本示例:
>>> 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
>>> # (a ten, jack, queen, or king).
>>> deck = collections.Counter(tens=16, low_cards=36)
>>> seen = sample(list(deck.elements()), k=20)
>>> seen.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(10000)) / 10000
0.4169
>>> # Probability of the median of 5 samples being in middle two quartiles
>>> def trial():
... return 2500 <= sorted(choices(range(10000), k=5))[2] < 7500
...
>>> sum(trial() for i in range(10000)) / 10000
0.7958
statistical bootstrapping 使用重采樣和替換來(lái)估計(jì)大小為五的樣本的均值的置信區(qū)間的示例:
# http://statistics.about.com/od/Applications/a/Example-Of-Bootstrapping.htm
from statistics import mean
from random import choices
data = 1, 2, 4, 4, 10
means = sorted(mean(choices(data, k=5)) for i in range(20))
print(f'The sample mean of {mean(data):.1f} has a 90% confidence '
f'interval from {means[1]:.1f} to {means[-2]:.1f}')
使用 重新采樣排列測(cè)試 來(lái)確定統(tǒng)計(jì)學(xué)顯著性或者使用 p-值 來(lái)觀察藥物與安慰劑的作用之間差異的示例:
# Example from "Statistics is Easy" by Dennis Shasha and Manda Wilson
from statistics import 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 = 10000
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.')
模擬單個(gè)服務(wù)器隊(duì)列中的到達(dá)時(shí)間和服務(wù)交付:
from random import expovariate, gauss
from statistics import mean, median, stdev
average_arrival_interval = 5.6
average_service_time = 5.0
stdev_service_time = 0.5
num_waiting = 0
arrivals = []
starts = []
arrival = service_end = 0.0
for i in range(20000):
if arrival <= service_end:
num_waiting += 1
arrival += expovariate(1.0 / average_arrival_interval)
arrivals.append(arrival)
else:
num_waiting -= 1
service_start = service_end if num_waiting else arrival
service_time = gauss(average_service_time, stdev_service_time)
service_end = service_start + service_time
starts.append(service_start)
waits = [start - arrival for arrival, start in zip(arrivals, starts)]
print(f'Mean wait: {mean(waits):.1f}. Stdev wait: {stdev(waits):.1f}.')
print(f'Median wait: {median(waits):.1f}. Max wait: {max(waits):.1f}.')
參見(jiàn)
Statistics for Hackers Jake Vanderplas 撰寫(xiě)的視頻教程,使用一些基本概念進(jìn)行統(tǒng)計(jì)分析,包括模擬、抽樣、改組和交叉驗(yàn)證。
Economics Simulation Peter Norvig 編寫(xiě)的市場(chǎng)模擬,顯示了該模塊提供的許多工具和分布的有效使用(高斯、均勻、樣本、beta變量、選擇、三角和隨機(jī)范圍等)。
A Concrete Introduction to Probability (using Python) Peter Norvig 撰寫(xiě)的教程,涵蓋了概率論基礎(chǔ)知識(shí),如何編寫(xiě)模擬,以及如何使用 Python 進(jìn)行數(shù)據(jù)分析。
