Определение векторизованной подписи Numpy - ValueError - PullRequest
1 голос
/ 05 марта 2019

Я пытаюсь использовать векторизованные функции Python / Numpy для сокращения циклов.

Мой вызов функции выглядит следующим образом

out_vectors = v_calculation(
                            in_vectors,
                            p
)

Определение векторизованной функции:

v_calculation = np.vectorize(
                     my_calculation,
                     signature='(j,i),(i)->()'
)

in_vectors - это массив формы

(3,6,200,3)

Но первые 2 измерения (3,6) могут быть любыми.Это размеры цикла.

p - это массив формы

(3,)

Мой расчет такой:

def my_calculation(in_vector, p):
    """
    total magnetic field from Biot-Savart's law
    """
    out_vector = np.zeros((3,))

    l_vector = in_vector[1:, :] - in_vector[:-1, :]
    r_vector = (in_vector[:-1, :] + l_vector / 2) - p

    out_vector = np.sum(np.cross(l_vector, r_vector) / \
                        np.linalg.norm(r_vector) ** 3,
                        axis=0
    )

    return out_vector

В этой функции in_vector является массивом формы(200, 3) и р такой же формы (3,).Форма out_vector - (3,).Это правильно.

out_vectors, результат векторизованной функции должен быть (6,3).Это должны быть результаты my_calculation, суммированные по первому измерению input_vectors (3 в данном случае) для каждого второго измерения input_vectors (6 в данном случае).Второе измерение результата - 3 (x, y, z компоненты для вектора), такое же, как измерение p и четвертое измерение input_vectors.Я надеюсь, что это все ясно.

Мой код не работает в векторизованном вызове функции

Stacktrace

~/path/to/my/code.py in calculate_vectors(mgr)
    588         out_vectors = v_calculation(
    589                                 in_vectors,
--> 590                                 p
    591         )

~/miniconda/lib/python3.7/site-packages/numpy/lib/function_base.py in __call__(self, *args, **kwargs)
   1970             vargs.extend([kwargs[_n] for _n in names])
   1971 
-> 1972         return self._vectorize_call(func=func, args=vargs)
   1973 
   1974     def _get_ufunc_and_otypes(self, func, args):

~/miniconda/lib/python3.7/site-packages/numpy/lib/function_base.py in _vectorize_call(self, func, args)
   2036         """Vectorized call to `func` over positional `args`."""
   2037         if self.signature is not None:
-> 2038             res = self._vectorize_call_with_signature(func, args)
   2039         elif not args:
   2040             res = func()

~/miniconda/lib/python3.7/site-packages/numpy/lib/function_base.py in _vectorize_call_with_signature(self, func, args)
   2100 
   2101             for output, result in zip(outputs, results):
-> 2102                 output[index] = result
   2103 
   2104         if outputs is None:

ValueError: setting an array element with a sequence.

1 Ответ

0 голосов
/ 06 марта 2019

Это работает для меня.Примечание. Я изменил подпись возврата, чтобы она соответствовала общему итоговому измерению обоих входов.

In [54]: A = np.arange(12).reshape(4,3); b = np.arange(3)                       
In [55]: my_calculation(A,b)                                                    
Out[55]: array([0., 0., 0.])
In [56]: f = np.vectorize(my_calculation, signature='(j,i),(i)->(i)')           
In [57]: f(A,b)                                                                 
Out[57]: array([0., 0., 0.])
In [58]: f([A,A,A],b)                                                           
Out[58]: 
array([[0., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.]])
...