簡體   English   中英

如何矢量化具有不同形狀的ndarray作為參數的函數?

[英]How to vectorize a function having ndarray of different shape as an argument?

我有以下功能:

def reshape_to_array(in_dict, pattern):
    vec_func = np.frompyfunc(in_dict.get, 1, 1)
    return vec_func(pattern)
func = np.frompyfunc(reshape_to_array,2,1)

輸入:

dump = np.array([[{'HH': 'a00', 'HV': 'b00', 'VH': 'c00', 'VV': 'd00'},
        {'HH': 'a01', 'HV': 'b01', 'VH': 'c01', 'VV': 'd01'},
        {'HH': 'a02', 'HV': 'b02', 'VH': 'c02', 'VV': 'd02'},
        {'HH': 'a03', 'HV': 'b03', 'VH': 'c03', 'VV': 'd03'}],
       [{'HH': 'a10', 'HV': 'b10', 'VH': 'c10', 'VV': 'd10'},
        {'HH': 'a11', 'HV': 'b11', 'VH': 'c11', 'VV': 'd11'},
        {'HH': 'a02', 'HV': 'b02', 'VH': 'c02', 'VV': 'd02'},
        {'HH': 'a13', 'HV': 'b13', 'VH': 'c13', 'VV': 'd13'}],
       [{'HH': 'a20', 'HV': 'b20', 'VH': 'c20', 'VV': 'd20'},
        {'HH': 'a21', 'HV': 'b21', 'VH': 'c21', 'VV': 'd21'},
        {'HH': 'a22', 'HV': 'b22', 'VH': 'c22', 'VV': 'd22'},
        {'HH': 'a23', 'HV': 'b23', 'VH': 'c23', 'VV': 'd23'}],
       [{'HH': 'a30', 'HV': 'b30', 'VH': 'c30', 'VV': 'd30'},
        {'HH': 'a31', 'HV': 'b31', 'VH': 'c31', 'VV': 'd31'},
        {'HH': 'a32', 'HV': 'b32', 'VH': 'c32', 'VV': 'd32'},
        {'HH': 'a33', 'HV': 'b33', 'VH': 'c33', 'VV': 'd33'}]])

pattern = np.array([['HH', 'HV'], ['VH', 'VV']])

當我執行:

x = func(dump, pattern)

它拋出 ryuntime 錯誤:

ValueError: operands could not be broadcast together with shapes (4,4) (2,2)

但是,如果我按以下方式修改reshape_to_array函數:

# pattern is global
pattern = np.array([['HH', 'HV'], ['VH', 'VV']])
def reshape_to_array(in_dict):
    vec_func = np.frompyfunc(in_dict.get, 1, 1)
    return vec_func(pattern)
func = np.frompyfunc(reshape_to_array,1,1)

並執行func(dump)它成功執行並返回預期的(正確的)輸出。 這是:

x = np.array([[array([['a00', 'b00'],
       ['c00', 'd00']]),
        array([['a01', 'b01'],
       ['c01', 'd01']]),
        array([['a02', 'b02'],
       ['c02', 'd02']]),
        array([['a03', 'b03'],
       ['c03', 'd03']])],
       [array([['a10', 'b10'],
       ['c10', 'd10']]),
        array([['a11', 'b11'],
       ['c11', 'd11']]),
        array([['a02', 'b02'],
       ['c02', 'd02']]),
        array([['a13', 'b13'],
       ['c13', 'd13']])],
       [array([['a20', 'b20'],
       ['c20', 'd20']]),
        array([['a21', 'b21'],
       ['c21', 'd21']]),
        array([['a22', 'b22'],
       ['c22', 'd22']]),
        array([['a23', 'b23'],
       ['c23', 'd23']])],
       [array([['a30', 'b30'],
       ['c30', 'd30']]),
        array([['a31', 'b31'],
       ['c31', 'd31']]),
        array([['a32', 'b32'],
       ['c32', 'd32']]),
        array([['a33', 'b33'],
       ['c33', 'd33']])]])

我的問題是:

  1. 為什么函數在第一種情況下不起作用,但在第二種情況下工作正常?
  2. 如何克服這一點?

您的第一個func接受 2 個輸入,它們相互廣播,並且元素元組被傳遞給reshape_to_array

dump是 (4,4), pattern是 (2,2)。 錯誤說它可以配對 2 - 如果您了解廣播,這應該很明顯。

如果您將dump減少到 (2,2) (或 (2,1) 或 (1,2)) 它應該可以工作。 (1,4) 或 (4,1) 的pattern也是如此。


frompyfunc情況下,外部frompyfunc將每個 (4,4) dump元素傳遞給reshape_to_array (4,4)模式被評估。

我懷疑x = func(dump[:,:,np.newaxis, np.newaxis], pattern)會起作用,生成相同的值,但在 (4,4,2,2) 數組中。 使用不同的np.newaxis我們可以產生 (4,2,4,2) 等。

廣播字典和模式

In [291]: fn = lambda in_dict, pattern: in_dict.get(pattern)
In [299]: fn1 = np.frompyfunc(fn,2,1)

使用 (4,4) dump ,我可以使用 (1,4) pattern (或 (4,1)):

In [300]: fn1(dump, pattern.reshape(1,4))
Out[300]: 
array([['a00', 'b01', 'c02', 'd03'],
       ['a10', 'b11', 'c02', 'd13'],
       ['a20', 'b21', 'c22', 'd23'],
       ['a30', 'b31', 'c32', 'd33']], dtype=object)

如果我將newaxis添加到dump我可以獲得一個 (4,4,2,2) 數組:

In [302]: fn1(dump[:,:,None,None], pattern)
Out[302]: 
array([[[['a00', 'b00'],
         ['c00', 'd00']],

        [['a01', 'b01'],
         ['c01', 'd01']],

        [['a02', 'b02'],
         ['c02', 'd02']],

         ....

        [['a32', 'b32'],
         ['c32', 'd32']],

        [['a33', 'b33'],
         ['c33', 'd33']]]], dtype=object)
In [303]: _.shape
Out[303]: (4, 4, 2, 2)

這些與您的x相同,除了沒有 (4,4) (2,2) 嵌套。

如果我復制粘貼你的x ,它會產生一個 (4,4,2,2) 'U3' 數組(它不保留嵌套),然后比較:

In [309]: np.all(xx == Out[302].astype('U3'))
Out[309]: True

包裹圖案

您可以將上一個版本包裝在函數定義中:

def foo(pattern):
    def reshape_to_array(in_dict):
        vec_func = np.frompyfunc(in_dict.get, 1, 1)
        return vec_func(pattern)
    func = np.frompyfunc(reshape_to_array,1,1)
    return func

將用作:

In [313]: foo(pattern)
Out[313]: <ufunc '? (vectorized)'>
In [314]: foo(pattern)(dump)
# your x

外部矢量化

In [334]: def reshape_to_array(in_dict, pattern=None):
     ...:     vec_func = np.frompyfunc(in_dict.get, 1, 1)
     ...:     return vec_func(pattern)

In [335]: f = np.vectorize(reshape_to_array, excluded=['pattern'], otypes=['O'])
In [336]: f(dump, pattern=pattern)

使用復雜的 otype 進行向量化

In [380]: def reshape_to_array1(in_dict, pattern=None):
     ...:     vec_func = np.vectorize(in_dict.get, otypes=[complex])
     ...:     return vec_func(pattern)
     ...: 
     ...: 
In [381]: f = np.vectorize(reshape_to_array1, excluded=['pattern'], otypes=['O
     ...: '])
In [382]: dd = np.array([{'HH': 1+j, 'HV': 1j, 'VH':2j, 'VV': 1+2j}])
In [383]: f(dd, pattern=pattern)
Out[383]: 
array([array([[3.+0.j, 0.+1.j],
       [0.+2.j, 1.+2.j]])], dtype=object)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM