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)