2015-05-29 46 views
4

另一矢量我有以下數據陣列總和零和一通過在python

import numpy as np 
a = [[1],[0],[1],[0],[0]] 
b = [[1],[0],[1],[0],[0]] 
c = d = [[1],[0],[1],[0],[0]] 
m = np.hstack((a,b,c,d)) 
m 
array([[1, 0, 1, 1], 
     [0, 0, 0, 0], 
     [1, 1, 1, 1], 
     [0, 0, 0, 0], 
     [0, 1, 0, 0]]) 

我有以下矢量現有

prior = [0.1,0.2,0.3,0.4] 

我現在想要創建一個新長度爲5的矢量,其中每行m根據此方案求和

如果1再加入1 /現有

如果0然後添加0.1 * 1 /現有

所以對於在第一行我們將得到

(1/0.1)+(0.1*1/0.2)+(1/0.3)+(1/0.4) = 16.33 

第二行是

(0.1*1/0.1)+(0.1*1/0.2)+(0.1*1/0.3)+(0.1*1/0.4) = 2.083 

應該是基礎和numpy的可使用(可能的.sum(斧是= 1))?

UPDATE

我也有興趣在一個解決方案,可以採取兩種以上不同的整數。例如,我想爲m==2第三規則,既然你已經使用numpy添加這些值0.2 * 1 /前

回答

4

我會建議numpy.wherenumpy.sum。請注意,這僅適用於您製作prior a numpy.array

p = np.asarray(prior) 

np.sum(np.where(m,1./p,0.1/p),axis=1) 
# array([ 16.33333333, 2.08333333, 20.83333333, 2.08333333, 6.58333333]) 

np.where通常預計的bools陣列。但是,當你給的integers一個列表中的號碼0被解釋爲False和一切爲True

更新

如果你想在m我添加第三個規則的2發生將使用np.choose而不是np.where。如果你想擁有0.2/p2發生,你可以做

p = np.asarray(prior) 
p_vec = np.vstack((0.1/p,1./p,0.2/p)) 
np.choose(m,p_vec).sum(axis=1) 

的想法是先創建包含0.1/p1./p0.2/p列表p_vec。命令np.choose根據m從列表中挑選出相應的實體。

這可以很容易地擴展爲整數3,4,...只需將相應的數據添加到p_vec

+0

除非它會更好,如果一個是有點更明確在'where(m == 1,1./prior,0.1/prior)' – gabhijit

+0

那麼...一個人也可以做'm.astype(np.bool)'但最終都給出了相同的... – plonser

+0

謝謝,非常好。當我有三個不同的整數(0,1,2),並且想爲這些情況添加0.​​2/p時,您有簡單的numpy解決方案嗎? – spore234

3

方法1:boolean indexing矢量化的方法 -

# Calculate the reciprocal of prior as a numpy array 
prior_reci = 1/np.asarray(prior) 

# Mask of ones (1s) in array, m 
mask = m==1 

# Use the mask for m==1 and otherwise with proper scales: prior_reci 
# and 0.1*prior_reci respectively and sum them up along the rows 
out = (mask*prior_reci + ~mask*(0.1*prior_reci)).sum(1) 

採樣運行 -

In [58]: m 
Out[58]: 
array([[1, 0, 1, 1], 
     [0, 0, 0, 0], 
     [1, 1, 1, 1], 
     [0, 0, 0, 0], 
     [0, 1, 0, 0]]) 

In [59]: prior 
Out[59]: [0.1, 0.2, 0.3, 0.4] 

In [60]: prior_reci = 1/np.asarray(prior) 
    ...: mask = m==1 
    ...: 

In [61]: (mask*prior_reci + ~mask*(0.1*prior_reci)).sum(1) 
Out[61]: array([ 16.33333333, 2.08333333, 20.83333333, 2.08333333, 6.58333333]) 

方法2:使用matrix-multiplication with np.dot -

# Calculate the reciprocal of prior as a numpy array 
prior_reci = 1/np.asarray(prior) 

# Sum along rows for m==1 with scaling of prior_reci per row 
# would be equivalent to np.dot(m,prior_reci). 
# Similarly for m!=1, it would be np.dot(1-m,0.1*prior_reci) 
# i.e. with the new scaling 0.1*prior_reci. 
# Finally we need to combine them up with summation. 
out = np.dot(m,prior_reci) + np.dot(1-m,0.1*prior_reci) 

採樣運行 -

In [77]: m 
Out[77]: 
array([[1, 0, 1, 1], 
     [0, 0, 0, 0], 
     [1, 1, 1, 1], 
     [0, 0, 0, 0], 
     [0, 1, 0, 0]]) 

In [78]: prior 
Out[78]: [0.1, 0.2, 0.3, 0.4] 

In [79]: prior_reci = 1/np.asarray(prior) 

In [80]: np.dot(m,prior_reci) + np.dot(1-m,0.1*prior_reci) 
Out[80]: array([ 16.33333333, 2.08333333, 20.83333333, 2.08333333, 6.58333333]) 

運行測試早前上市的兩種方法比較 -

In [102]: # Parameters 
    ...: H = 1000 
    ...: W = 1000 
    ...: 
    ...: # Create inputs 
    ...: m = np.random.randint(0,2,(H,W)) 
    ...: prior = np.random.rand(W).tolist() 
    ...: 

In [103]: %%timeit 
    ...: prior_reci1 = 1/np.asarray(prior) 
    ...: mask = m==1 
    ...: out1 = (mask*prior_reci1 + ~mask*(0.1*prior_reci1)).sum(1) 
    ...: 
100 loops, best of 3: 11.1 ms per loop 

In [104]: %%timeit 
    ...: prior_reci2 = 1/np.asarray(prior) 
    ...: out2 = np.dot(m,prior_reci2) + np.dot(1-m,0.1*prior_reci2) 
    ...: 
100 loops, best of 3: 6 ms per loop 

通用的解決方案處理多個條件檢查可能解決了vec torized方式與np.einsum -

# Define scalars that are to be matched against input 2D array, m 
matches = [0,1,2,3,4] # Edit this to accomodate more matching conditions 

# Define multiplying factors for the reciprocal version of prior 
prior_multfactors = [0.1,1,0.2,0.3,0.4] # Edit this corresponding to matches 
            # for different multiplying factors 

# Thus, for the given matches and prior_multfactors, it means: 
# when m==0, then do: 0.1/prior 
# when m==1, then do: 1/prior 
# when m==2, then do: 0.2/prior 
# when m==3, then do: 0.3/prior 
# when m==4, then do: 0.4/prior 

# Define prior list 
prior = [0.1,0.2,0.3,0.4] 

# Calculate the reciprocal of prior as a numpy array 
prior_reci = 1/np.asarray(prior) 

# Mask for every element of m satisfying or not 
# all the matches to produce a 3D array mask 
mask = m==np.asarray(matches)[:,None,None] 

# Get scaling factors for each matches across each prior_reci value 
scales = np.asarray(prior_multfactors)[:,None]*prior_reci 

# Einsum-mation to give sum across rows corresponding to all matches 
out = np.einsum('ijk,ik->j',mask,scales) 

採樣運行 -

In [203]: m 
Out[203]: 
array([[1, 0, 1, 1], 
     [0, 0, 0, 0], 
     [4, 2, 3, 1], 
     [0, 0, 0, 0], 
     [0, 4, 2, 0]]) 

In [204]: matches, prior_multfactors 
Out[204]: ([0, 1, 2, 3, 4], [0.1, 1, 0.2, 0.3, 0.4]) 

In [205]: prior 
Out[205]: [0.1, 0.2, 0.3, 0.4] 

In [206]: prior_reci = 1/np.asarray(prior) 
    ...: mask = m==np.asarray(matches)[:,None,None] 
    ...: scales = np.asarray(prior_multfactors)[:,None]*prior_reci 
    ...: 

In [207]: np.einsum('ijk,ik->j',mask,scales) 
Out[207]: array([ 16.33333333, 2.08333333, 8.5  , 2.08333333, 3.91666667]) 
+0

非常有幫助,謝謝 – spore234

+0

@ spore234看來你想計算m == 2等情況嗎?也許用這些新的要求和相同的輸入輸出來編輯問題? – Divakar

+0

我將問題擴展爲 – spore234

1

不是說這比Divikar的更好,只是選擇:

prior_reci = 1/np.asarray(prior) 
(a * prior_reci + (1 - a)*prior_reci/10).sum(axis=1)