Добавление массивов с разным количеством измерений - PullRequest
10 голосов
/ 20 января 2010

Допустим, у меня есть двумерный массив Numpy:

>>> a = np.random.random((4,6))

и я хочу добавить одномерный массив в каждую строку:

>>> c = np.random.random((6,))
>>> a + c

Это работает. Теперь, если я пытаюсь добавить одномерный массив к каждому столбцу, я получаю сообщение об ошибке:

>>> b = np.random.random((4,))
>>> a + b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: shape mismatch: objects cannot be broadcast to a single shape

Я могу исправить это, используя np.newaxis:

>>> a + b[:,np.newaxis]

, который работает как положено.

Каковы правила соответствия формы, чтобы не использовать np.newaxis? Неужели последний элемент кортежа numpy shape должен совпадать? Это правило также применимо к более высоким измерениям? Например, следующие работы:

>>> a = np.random.random((2,3,4,5))
>>> b = np.random.random((4,5))
>>> a + b

Так что мой вопрос в том, задокументировано ли это где-нибудь, и можно ли на это полагаться, или лучше всегда использовать np.newaxis?

Ответы [ 2 ]

12 голосов
/ 20 января 2010

Это отличительная черта numpy, которая называется broadcasting . Это делается с использованием четырех правил, которые немного сложны в формулировке, но довольно интуитивно понятны:

  1. Все входные массивы на ndim меньше, чем входной массив с наибольшим ndim, иметь 1, предварительно подгоненные к их формам.
  2. Размер в каждом измерении выходной формы является максимальным из всех входные размеры в этом измерении.
  3. Ввод может использоваться в расчете, если его размер в конкретное измерение либо совпадает выходной размер в этом измерении, или имеет значение ровно 1.
  4. Если вход имеет размерный размер 1 в форме, первый ввод данных в этом измерении будет использоваться для всех расчеты вдоль этого измерения. В другими словами, степперы ufunc просто не шагнет это измерение (шаг будет 0 для этого измерения).

Операция возможна (не приводит к упомянутой вами ошибке shape mismatch) в трех случаях:

  1. Все массивы имеют одинаковую форму.
  2. Все массивы имеют одинаковое количество измерений, а длина каждого измерения - либо общая длина, либо 1.
  3. Массивам, имеющим слишком мало измерений, можно придать своим формам размер 1, чтобы удовлетворить свойству 2.

Примеры можно найти по ссылке выше.

2 голосов
/ 21 января 2010

Дай мне посмотреть, получу ли я это ...

>>> from numpy import ones, newaxis
>>> A = ones((4,3))   # 4 rows x 3 cols
>>> A.shape
(4, 3)
>>> A
array([[ 1.,  1.,  1.],
       [ 1.,  1.,  1.],
       [ 1.,  1.,  1.],
       [ 1.,  1.,  1.]])
>>> 
>>> ones((4,1))      # 4 rows x 1 col
array([[ 1.],
       [ 1.],
       [ 1.],
       [ 1.]])
>>> A + ones((4,1))
array([[ 2.,  2.,  2.],
       [ 2.,  2.,  2.],
       [ 2.,  2.,  2.],
       [ 2.,  2.,  2.]])
>>> 
>>> ones((1,3))      # 1 row x 3 cols
array([[ 1.,  1.,  1.]])
>>> A + ones((1,3))  
array([[ 2.,  2.,  2.],
       [ 2.,  2.,  2.],
       [ 2.,  2.,  2.],
       [ 2.,  2.,  2.]])
>>> 
>>> B = ones((3,))   # a 1D array
>>> B
array([ 1.,  1.,  1.])
>>> B.shape
(3,)
>>> A + B
array([[ 2.,  2.,  2.],
       [ 2.,  2.,  2.],
       [ 2.,  2.,  2.],
       [ 2.,  2.,  2.]])
>>> 
>>> C = ones((4,))   # a 1D array
>>> C.shape
(4,)
>>> C
array([ 1.,  1.,  1.,  1.])
>>> A + C
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: shape mismatch: objects cannot be broadcast to a single shape
>>> 
>>> D = C[:,newaxis]
>>> D.shape
(4, 1)
>>> A + D
array([[ 2.,  2.,  2.],
       [ 2.,  2.,  2.],
       [ 2.,  2.,  2.],
       [ 2.,  2.,  2.]])

Успешное вещание, необходимое для создания вектора 4 x 3 плюс одномерный вектор с 3 элементами.

Передача, необходимая для создания вектора 4 x 3 плюс одномерный вектор с 4 элементами, завершается неудачей.

>>> D = C[:,newaxis]

преобразует C в двухмерный вектор совместимой формы.

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