Динамически транслировать массив numpy

В настоящее время у меня есть массив 1D numpy, epsilons, который должен выполнять поэлементное умножение на массив x. Однако размерность x является динамической и меняется с каждой итерацией следующего цикла for:

for x in grads:
  x = x * epsilons
  print(grad)

epsilons всегда имеет форму (M,). Однако для первой итерации x принимает форму (M,4,2), а для второй итерации принимает форму (M,4) (форма x меняется по мере того, как код повторяет grads). Есть ли способ, которым я могу автоматически транслировать epsilons в форму x, чтобы я мог выполнять это поэлементное умножение для любой формы x?


person Caleb Sanders    schedule 12.04.2021    source источник
comment
Во-первых, я предполагаю, что вы имеете в виду град = x * эпсилон, нет? Во-вторых, вы уверены, что ваши выпускники (М, 4), а не (4, М)? Если они первые, я получаю ошибку значения: операнды не могут быть переданы вместе с формами (M, 4) (M,). Если они последние, то можно выполнить x * epsilon и получить ожидаемый результат, если x.shape равен (4, M) или (2, 4, M) или любому (..., M).   -  person Malcolm    schedule 12.04.2021
comment
Можете ли вы изменить форму x на (4,2,M) или (4,M)? Помните, что последнее измерение является самым внутренним, поэтому в numpy имеет смысл добавлять (или удалять) ведущие измерения.   -  person hpaulj    schedule 12.04.2021
comment
Возможно, вы захотите сделать размеры x более согласованными. Увеличение или уменьшение массивов в цикле может быть дорогостоящим и способствовать возникновению ошибок.   -  person hpaulj    schedule 12.04.2021
comment
Да, верно. К сожалению, характер моего проекта требует, чтобы я перебирал атрибуты parameter.grad нейронной сети pytorch и модифицировал их. Эти атрибуты parameter.grad различаются по форме и размеру, что объясняет характер моего вопроса.   -  person Caleb Sanders    schedule 13.04.2021


Ответы (1)


Вы можете просто изменить форму epsilons до правильной формы. Действительно, Numpy автоматически транслирует векторную форму (например, вызов broadcast_to), если она имеет совместимую форму: одно и то же число измерений должно быть как минимум одинаковым, а форма должна быть либо 1, либо полной для каждого измерение. Спасибо @hpaulj за улучшенное решение.

# Reshape epsilons so that the vector value are along the first dimension (the least contiguous one)
reshapedEpsilons = epsilons.reshape((M,)+(1,)*(x.ndim-1))

# Broadcast automatically the vector values in the other dimensions so the result have the same shape than x
# Actual element-wise multiplication
x *= reshapedEpsilons

PS: обратите внимание, что a = a * b должен создать новую матрицу и менее эффективен, чем a *= b, который изменяет значения на месте.

person Jérôme Richard    schedule 12.04.2021
comment
Я не думаю, что вам нужен шаг broadcast_to. - person hpaulj; 13.04.2021
comment
reshapedEpsilons = epsilons.reshape((M,)+(1,)*(x.ndim-1)) является альтернативой - person hpaulj; 13.04.2021
comment
@hpaulj Действительно. Спасибо. Я отредактировал пост, чтобы улучшить его. - person Jérôme Richard; 13.04.2021
comment
Спасибо, ребята, это решило это! Мне нужно было изменить форму новых эпсилонов, просто я не был уверен, что нужно передать в .reshape(), чтобы сделать это правильно! - person Caleb Sanders; 13.04.2021