Заполнение пустой таблицы с помощью функции, рассчитанной по итерируемым - PullRequest
0 голосов
/ 27 августа 2018

Я искал компактный способ создания матрицы, рассчитанной с использованием одной и той же функции для элемента из разных итераций разного размера. Скажем, один размер m = 3, а другой размер n = 4

a = range(3)
b = range(4)

И это только самый простой пример, так как я мог бы свободно использовать numpy векторы, чтобы сделать то же самое.

И я хочу заполнить матрицу таким образом:

yawn = np.zeros((len(a), len(b)), dtype='float')

meh = lambda x, y: np.exp(x + y) / (1 + np.exp(x + y))
for i in a:
    for j in b:
       yawn[i,j] = meh(i,j)

И ожидаемые результаты действительно:

array([[ 0.5       ,  0.73105858,  0.88079708,  0.95257413],
       [ 0.73105858,  0.88079708,  0.95257413,  0.98201379],
       [ 0.88079708,  0.95257413,  0.98201379,  0.99330715]])

Я пытался использовать что-то вроде np.vectorize () или np.fromfunction () , и я уже близко:

meh_vec = np.vectorize(meh)
meh_vec(a, 3)

array([ 0.95257413,  0.98201379,  0.99330715])

Но я могу выяснить, есть ли способ сделать что-то вроде этого:

meh_vec(a, b) 

, что не приведет к ошибке ValueError:

ValueError: операнды не могут передаваться вместе с фигурами (3,) (4) * * тысяча двадцать пять

Более того, я прочитал это:

Функция векторизации предоставляется в первую очередь для удобства, а не для исполнения. Реализация по сути является циклом for.

Есть ли обходной путь, который может быть более компактным и быстрым, чем цикл for?

1 Ответ

0 голосов
/ 27 августа 2018

Преобразуйте их в open массивы, которые можно транслировать друг на друга для результирующего массива 2D с np.ix_ -

In [57]: x,y = np.ix_(a,b)

In [58]: np.exp(x + y) / (1 + np.exp(x + y))
Out[58]: 
array([[0.5       , 0.73105858, 0.88079708, 0.95257413],
       [0.73105858, 0.88079708, 0.95257413, 0.98201379],
       [0.88079708, 0.95257413, 0.98201379, 0.99330715]])

В качестве альтернативы, чтобы быть более точным, мы можем расширить размеры вручную с помощью None/np.newaxis в массиве версий входных данных -

In [64]: a = np.arange(3)
    ...: b = np.arange(4)

In [65]: np.exp(a[:,None] + b) / (1 + np.exp(a[:,None] + b))
Out[65]: 
array([[0.5       , 0.73105858, 0.88079708, 0.95257413],
       [0.73105858, 0.88079708, 0.95257413, 0.98201379],
       [0.88079708, 0.95257413, 0.98201379, 0.99330715]])

Для дальнейшей оптимизации мы можем захотеть сохранить np.exp(a[:,None] + b) и повторно использовать для деления. Кроме того, a[:,None] + b можно переписать как np.add.outer(a,b), так как это в основном внешнее дополнение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...