2013-11-04 28 views
3

我想從二維Numpy數組的索引中取樣,因爲每個索引都由該數組內部的數字加權。我知道它的方式是numpy.random.choice,但是它不會返回索引而是數字本身。有沒有這樣做的有效方式?從Numpy數組的索引採樣的有效方法?

這裏是我的代碼:

import numpy as np 
A=np.arange(1,10).reshape(3,3) 
A_flat=A.flatten() 
d=np.random.choice(A_flat,size=10,p=A_flat/float(np.sum(A_flat))) 
print d 
+0

看到這個:http://stackoverflow.com/a/10803136/553404小修改 – YXD

+0

@MrE,但這意味着要製作一個額外的數組來存儲索引,對吧? – Cupitor

+1

是的。我會保存'np.indices(A)'的輸出,平坦化結果(包括元組)和你的權重數組,使用鏈接的方法,然後你的結果由'flattened_indices_x [idx],flattened_indices [ IDX]'。編輯:其實你可以使用http://docs.scipy.org/doc/numpy/reference/generated/numpy.unravel_index.html來避免創建索引數組,並直接從'idx'和你的權重數組得到2d索引形狀。 – YXD

回答

1

你可以這樣做:

import numpy as np 

def wc(weights): 
    cs = np.cumsum(weights) 
    idx = cs.searchsorted(np.random.random() * cs[-1], 'right') 
    return np.unravel_index(idx, weights.shape) 

請注意,cumsum是這個中最慢的部分,所以如果你需要爲同樣的a重複執行此操作我建議提前計算cumsum並重新使用它。

+0

不幸的是重量在變化,所以我不能那樣做。然而,你的搜索將是昂貴的權利?我認爲將索引保存在一個單獨的數組中會使計算更便宜,對嗎? – Cupitor

+1

搜索相當che,,特別是與'cusum'或'sum'相比。我沒有看到單獨數組中的索引如何幫助這裏,但也許我錯過了一些東西。 'cumsum'也不算太差,但對於需要從同一分佈中獲取多個樣本的人來說,提前完成'cumsum'是一個簡單的優化。 –

+2

@Naji,'cs'被排序並且'searchsorted()'利用它進行二分搜索 - 只需要'O(log(len(weights))'比較。非常便宜。 –

2

要擴大我的意見:適應加權選擇方法這裏介紹https://stackoverflow.com/a/10803136/553404

def weighted_choice_indices(weights): 
    cs = np.cumsum(weights.flatten())/np.sum(weights) 
    idx = np.sum(cs < np.random.rand()) 
    return np.unravel_index(idx, weights.shape)