如何向量化具有不同形状的ndarray作为参数的函数?

时间:2018-08-15 22:25:11

标签: python python-3.x numpy vectorization

我具有以下功能:

update(i: number) {
    const id = `shade${i}`;
    const slider = document.getElementById(id) as HTMLInputElement;
    console.log(slider.value);
}

输入:

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']])

它会引发ryuntime错误:

x = func(dump, pattern)

但是,如果我通过以下方式修改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)

我的问题是:

  1. 为什么该功能在第一种情况下不起作用,但在第二种情况下能正常工作?
  2. 如何克服这个问题?

1 个答案:

答案 0 :(得分:1)

您的第一个func接受2个输入,它们相互广播,并将元素元组传递到reshape_to_array

dump是(4,4),pattern是(2,2)。该错误表明它可以将2配对-如果您了解广播,这应该很明显。

如果将dump减小为(2,2)(或(2,1)或(1,2)),它应该可以工作。 pattern也就是(1,4)或(4,1)。


在第二种情况下,外部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)

对复杂类型进行向量化

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)