2017-01-25 2 views
-1

Я пытаюсь найти хороший способ выполнить следующую операцию добавления без использования np.repeat для создания большого размера. Если вы используете np.repeat и добавление - лучшее решение, дайте мне знать.Пример тиражирования в цифрах без повторения

Я также смущен тем, что делает вещание в этом случае. По существу, у меня есть 4d матрицу, и я хочу, чтобы добавить 2d матрицу в 1-й и 2-го индекса, в то время как и делают это по индексу 0 и индекс 3.

Это работает правильно

a = np.arange(64).reshape((2,4,4,2)).astype(float) 
b = np.ones((2,2)) 
a[:, 0:2, 0:2, : ] += b 

Это бросает ошибка. Каков хороший способ сделать это?

a[:, 0:3, 0:3, :] += np.ones((3,3)) 

Это работает, но это не то, что я ищу, чтобы сделать

c = np.arange(144).reshape(3,4,4,3).astype(float) 
c[:, 0:3, 0:3, :] += np.ones((3,3)) 
+0

Код «работает правильно» на самом деле не делает то, что вы считаете. Он выглядит только потому, что он работает, потому что все элементы 'b' равны. – user2357112

ответ

3

Вы можете включать пустую ось с самого начала:

a[:, 0:3, 0:3, :] += np.ones((3,3,1)) # 1 broadcasts against any axis 

Похожие вы должны были использовать:

a[:, 0:2, 0:2, : ] += np.ones((2,2,1)) 

, потому что вы (возможно непреднамеренно) транслировались эти против третьей и четвертой осей. Я думаю, вы хотели, чтобы он транслировал второй и третий, верно?


Кроме того, вы всегда можете добавить размеры с np.expand_dims и axis=-1:

>>> np.expand_dims(np.ones((2, 2)), axis=-1).shape 
(2, 2, 1) 

или нарезка с None или np.newaxis (они эквивалентны!):

>>> np.ones((2, 2))[None, :, :, np.newaxis].shape 
(1, 2, 2, 1) 

Первый None не является необходимым для правильного вещания, но последний из них!


В этом контексте важно упомянуть, что numpy-трансляции начинаются с последнего измерения. Поэтому, если у вас есть два массива, каждое измерение, начиная с последнего, должно иметь равную форму, или один из них должен быть 1 (если один из них равен 1, то он передает по этой оси!). Вот почему a[:, 0:2, 0:2, : ] работал:

>>> a[:, 0:2, 0:2, : ].shape 
(2, 2, 2, 2) 
>>> b.shape 
(2, 2) 

Так последняя размерность равна (как 2) и второй-последний равен (как 2). Тем не менее с:

>>> np.ones((2,2,1)).shape 
(2, 2, 1) 

Последних из них является 2 и 1 поэтому последняя ось np.ones((2,2,1)) транслируется в то время как второй и третий размер равен (все 2), поэтому NumPy использует операцию поэлементны там.

+2

Мне нравится '[None,:,:, None]', потому что он дает понять (er), что мы расширяем размеры на обоих концах (даже через первый Нет - автоматический). – hpaulj

2

Для выравнивания осей массива, которые будут добавлены, необходимо вставить новую ось в конце, как и -

a[:, 0:3, 0:3, :] += np.ones((3,3))[...,None] 

Давайте изучать формы здесь:

In [356]: a[:, 0:3, 0:3, :].shape 
Out[356]: (2, 3, 3, 2) 

In [357]: np.ones((3,3)).shape 
Out[357]: (3, 3) 

In [358]: np.ones((3,3))[...,None].shape 
Out[358]: (3, 3, 1) 


Input1 (a[:, 0:3, 0:3, :])  :  (2, 3, 3, 2) 
Input2 (np.ones((3,3))[...,None]) :  (3, 3, 1) 

Помните, что в правилах радиовещания указано, что размеры синглтона (размеры с lengths = 1) будут транслироваться в соответствие с длинами других измерений, отличных от одного синглтона. Кроме того, размеры, которые не указаны, фактически имеют длины 1 по умолчанию.

Итак, это доступно для трансляции и будет работать сейчас.


Часть 2: Почему следующие работы?

c = np.arange(144).reshape(3,4,4,3).astype(float) 
c[:, 0:3, 0:3, :] += np.ones((3,3)) 

Изучение формы снова -

In [363]: c[:, 0:3, 0:3, :].shape 
Out[363]: (3, 3, 3, 3) 

In [364]: np.ones((3,3)).shape 
Out[364]: (3, 3) 

Input1 (c[:, 0:3, 0:3, :]) :  (3, 3, 3, 3) 
Input2 (np.ones((3,3)))  :   (3, 3) 

Опять не происходит по broadcastable правилам это нормально, так что нет ошибки здесь, но результат не ожидаемый один.

+0

@MSeifert Добавлено. – Divakar

+0

Спасибо, я немного смутился. :) – MSeifert

Смежные вопросы