[英]Am i miss-using numpy random number generator for bootstrapping?
我試圖編寫一些代碼來創建引導分發,盡管它可以編譯,但我不確定它是否可以正常工作。 一些背景:我所教學校的一名學生一直在系統地找到計算機實驗室中筆記本電腦鎖的組合,以便與我們的計算機老師(很幸運,不是我)搞砸。 每個鎖具有三個條目,編號為0-9。 我計算出每個鎖有10 ^ 3種可能的組合。 他保留了已為每種鎖嘗試過的組合的詳細列表,因此,每次連續嘗試都會對一個組合進行采樣,而無需替換。 我正在嘗試對此進行模擬,以了解他為解鎖所有這些計算機(實驗室中有12台計算機)進行了多少次嘗試,方法是找到一次解鎖所需的期望值。 對我來說,這聽起來像是超幾何分布。 我寫的代碼是:
import numpy as np
def lock_hg(N):
final_counts = []
for i in range(N):
count = 1
combs = list(np.arange(1,1001,1))
guess = np.random.randint(1,1000)
for k in range(1000):
a = np.random.choice(combs, 1)
if a == guess:
final_counts.append(count)
break
else:
count = count + 1
combs.remove(a)
return(final_counts)
調用lock_hg(1000)時的直方圖plt.hist(final_counts)看起來相當均勻,嘗試40或50次與900或950次相同。我認為它看起來更像是以500為中心的正態分布。確定代碼是否有問題,或者我只是誤解了數學。 此代碼適合該問題嗎? 如果沒有,我該如何解決? 如果工作正常,是否有更有效的方法來完成此操作?
想象一下生成一個組合網格,其中每一行代表一個鎖,每一列值是該鎖的可能組合。 例如,假設有10個鎖,每個鎖只有5種可能的組合。 您可以按以下任意順序生成它們:
In [42]: np.random.seed(2018) # to make the example reproducible
In [43]: grid = np.random.random((10,5)).argsort(axis=1); grid
Out[43]:
array([[1, 3, 4, 0, 2],
[4, 0, 2, 3, 1],
[3, 4, 2, 0, 1],
[2, 1, 3, 4, 0],
[1, 3, 0, 4, 2],
[1, 0, 4, 3, 2],
[2, 0, 1, 3, 4],
[2, 0, 3, 4, 1],
[2, 3, 1, 0, 4],
[2, 4, 0, 3, 1]])
接下來,讓我們為10個鎖中的每個鎖選擇一個隨機組合:
In [48]: combo = np.random.choice(5, size=10, replace=True); combo
Out[48]: array([3, 2, 3, 3, 4, 4, 4, 3, 2, 3])
我們可以將grid
視為指示每個鎖嘗試組合的順序。 我們可以將combo
用作每個鎖的實際組合。
我們還可以使用以下方式可視化比賽的位置:
plt.imshow((grid == combo[:, None])[::-1], origin='upper')
我們可以使用argmax
找到每個成功匹配在網格中的argmax
:
In [73]: (grid == combo[:, None]).argmax(axis=1)
Out[73]: array([1, 2, 0, 2, 3, 2, 4, 2, 0, 3])
argmax
返回每一行的匹配項的索引(位置)。 這些索引號還指示找到每個匹配項所需的嘗試次數。 好吧,差不多。 由於Python是基於0索引的, argmax
如果首次嘗試匹配, argmax
將返回0。 因此,我們需要向(grid == combo[:, None]).argmax(axis=1)
加(grid == combo[:, None]).argmax(axis=1)
以獲得真實的嘗試次數。
因此,我們正在尋找(grid == combo[:, None]).argmax(axis=1) + 1
。 現在我們已經計算出10個鎖和5個組合的計算量,現在很容易將其增加到10000個鎖和1000個組合:
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(2018)
num_locks = 10000
num_combos = 1000
grid = np.random.random((num_locks, num_combos)).argsort(axis=1)
combo = np.random.choice(num_combos, size=num_locks, replace=True)
attempts = (grid == combo[:, None]).argmax(axis=1) + 1
plt.hist(attempts, density=True)
plt.show()
這種在網格中隨機選擇位置的方法清楚地表明了分布應該是均勻的-正確的組合很可能出現在開頭,結尾或中間的任何位置。
是的,期望分布均勻。 代碼很好。
一種可能的優化方法是,在刪除所選密鑰之前,將其與列表中的最后一個交換。 這樣可以避免碰到兩者之間的所有內容。
您可以進行兩項改進:
import random
for i in range(5):
print(random.randint(0, 100))
10
38
53
83
23
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.