Помещение лямбды в NumPy `np.fromfunction ()` вызывает TypeError - PullRequest
1 голос
/ 01 мая 2019

Я пытаюсь понять NumPy np.fromfunction().

следующий фрагмент кода извлечен из этого сообщения .

dist = np.array([ 1, -1])
f = lambda x: np.linalg.norm(x, 1)
f(dist)

вывода

2.0

, как и ожидалось.

, когда я собрал их вместе, чтобы использовать np.linalg.norm () внутри np.fromfunction ()

ds = np.array([[1, 2, 1],
       [1, 1, 0],
       [0, 1, 1]])
np.fromfunction(f, ds.shape)

появляется ошибка.

> TypeError                                 Traceback (most recent call
last) <ipython-input-6-f5d65a6d95c4> in <module>()
      2        [1, 1, 0],
      3        [0, 1, 1]])
----> 4 np.fromfunction(f, ds.shape)

~/anaconda3/envs/tf11/lib/python3.6/site-packages/numpy/core/numeric.py
in fromfunction(function, shape, **kwargs)    
2026     dtype = kwargs.pop('dtype', float)    
2027     args = indices(shape, dtype=dtype)
-> 2028     return function(*args, **kwargs)    
2029     
2030 
TypeError: <lambda>() takes 1 positional argument but 2 were given

возможно ли поместить лямбда-функцию (может быть, другую лямбда-функцию) в np.fromfunction () для выполнения этой работы (получить массив расстояний)?

Ответы [ 2 ]

4 голосов
/ 01 мая 2019

Посмотрите на ошибку:

In [171]: np.fromfunction(f, ds.shape)                                               
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-171-1a3ed1ade41a> in <module>
----> 1 np.fromfunction(f, ds.shape)

/usr/local/lib/python3.6/dist-packages/numpy/core/numeric.py in fromfunction(function, shape, **kwargs)
   2026     dtype = kwargs.pop('dtype', float)
   2027     args = indices(shape, dtype=dtype)
-> 2028     return function(*args, **kwargs)
   2029 
   2030 

TypeError: <lambda>() takes 1 positional argument but 2 were given

fromfunction - маленькая функция Python; нет скомпилированной магии.

На основе заданной вами формы он генерирует indices.

In [172]: np.indices(ds.shape)                                                       
Out[172]: 
array([[[0, 0, 0],
        [1, 1, 1],
        [2, 2, 2]],

       [[0, 1, 2],
        [0, 1, 2],
        [0, 1, 2]]])

Это массив (2,3,3). 2 из формы 2 элемента, и (3,3) из самой формы. Это похоже на то, что производят np.meshgrid и np.mgrid. Просто индексация массивов.

Затем он передает этот массив в вашу функцию с распаковкой *args.

function(*args, **kwargs)

In [174]: f(Out[172][0], Out[172][1])                                                
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-174-40469f1ab449> in <module>
----> 1 f(Out[172][0], Out[172][1])

TypeError: <lambda>() takes 1 positional argument but 2 were given

Это все, что он делает - генерирует сетку n-d и передает ее в качестве n аргументов вашей функции.

===

Обратите внимание, что вы передали ds.shape в fromfunction, но не ds. Вы могли бы так же хорошо написать np.fromfunction(f,(3,3)).

Что вы хотите, чтобы ваш lambda делал с ds? Очевидно, что fromfunction не делает это для вас.

===

С этим f единственное, что может сделать fromfunction, это дать ему arange:

In [176]: np.fromfunction(f, (10,))                                                  
Out[176]: 45.0
In [177]: f(np.arange(10))                                                           
Out[177]: 45.0

===

В связанном SO лямбда принимает 2 аргумента, lambda x,y:

np.fromfunction(lambda x,y: np.abs(target[0]-x) + np.abs(target[1]-y), ds.shape)   

В этом SO, как вопросе, так и ответе, массив ds является просто источником формы, Target - (0,1), самый большой элемент ds.

Фактически, fromfunction в связанном ответе просто делает:

In [180]: f1 = lambda x,y: np.abs(0-x) + np.abs(1-y)                                 
In [181]: f1(Out[172][0], Out[172][1])                                               
Out[181]: 
array([[1, 0, 1],
       [2, 1, 2],
       [3, 2, 3]])

In [182]: np.abs(0-Out[172][0]) + np.abs(1-Out[172][1])                              
Out[182]: 
array([[1, 0, 1],
       [2, 1, 2],
       [3, 2, 3]])

In [183]: np.abs(np.array([0,1])[:,None,None]-Out[172]).sum(axis=0)                  
Out[183]: 
array([[1, 0, 1],
       [2, 1, 2],
       [3, 2, 3]])

In [184]: np.abs(0-np.arange(3))[:,None] + np.abs(1-np.arange(3))                    
Out[184]: 
array([[1, 0, 1],
       [2, 1, 2],
       [3, 2, 3]])
0 голосов
/ 01 мая 2019

Поскольку вы используете двумерный массив, ваша функция должна принимать 2 входа.

Документы np.fromfunction() https://docs.scipy.org/doc/numpy/reference/generated/numpy.fromfunction.html говорят "Построить массив, выполнив функцию для каждой координаты."

Таким образом, он будет передавать координаты каждого элемента массива ((0,0), затем (0,1) ... и т. Д.) Для создания массива. Это действительно то, что вы пытаетесь сделать?

Вы можете изменить лямбду на что-то вроде этого, но это действительно зависит от того, что вы пытаетесь сделать!

f = lambda x, y: np.linalg.norm([x,y],1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...