Numpy, python: автоматически расширяет размеры массивов при трансляции
Рассмотрим следующее упражнение в широковещательном массиве Numpy.
import numpy as np
v = np.array([[1.0, 2.0]]).T # column array
A2 = np.random.randn(2,10) # 2D array
A3 = np.random.randn(2,10,10) # 3D
v * A2 # works great
# causes error:
v * A3 # error
Я знаю правила Numpy для трансляции, и я знаком с функциональностью bsxfun
в Matlab. Я понимаю, почему попытка трансляции массива (2,1) в массив (2, N, N) завершается с ошибкой и что я должен преобразовать массив (2,1) в массив (2,1,1) до этого трансляция проходит.
Мой вопрос: есть ли способ сказать Python автоматически добавлять размерность массива при попытке трансляции, без необходимости конкретно указывать это необходимое измерение?
Я не хочу явно связывать вектор (2,1) с многомерным массивом, с которым он будет транслироваться. В противном случае я мог бы сделать что-то глупое и абсурдно уродливое, как mult_v_A = lambda v,A: v.reshape([v.size] + [1]*(A.ndim-1)) * A
. Я не знаю заранее, если массив "A" будет 2D или 3D или N-D.
Функция трансляции трансляций Matlab bsxfun
неявно заполняет размеры по мере необходимости, поэтому я надеюсь, что там что-то могу сделать на Python.
Ответы
Ответ 1
Это уродливо, но это будет работать:
(v.T * A3.T).T
Если вы не дадите никаких аргументов, транспонирование меняет порядок кортежа, поэтому теперь вы можете полагаться на правила вещания, чтобы сделать свою магию. Последняя транспозиция возвращает все в нужном порядке.
Ответ 2
Передача NumPy добавляет дополнительные оси слева.
Итак, если вы упорядочиваете свои массивы, чтобы общие оси были справа, а передаваемые оси - слева, вы можете без проблем использовать широковещательную рассылку:
import numpy as np
v = np.array([[1.0, 2.0]]) # shape (1, 2)
A2 = np.random.randn(10,2) # shape (10, 2)
A3 = np.random.randn(10,10,2) # shape (10, 10, 2)
v * A2 # shape (10, 2)
v * A3 # shape (10, 10, 2)