#python #numpy #array-broadcasting #in-place
#python #numpy #трансляция массива #на месте
Вопрос:
Когда я пытаюсь передать на месте из shape (1,) в shape () , возникает numpy ValueError: non-broadcastable output operand with shape () doesn't match the broadcast shape (1,)
. Я понимаю, что операторы inplace предназначены для работы с тем же фрагментом памяти, что и входные данные, поэтому вы не могли, скажем, транслировать на месте из shape (5,) в shape (1,) . Но в случае shape (1,) (или любого массива размером 1) размер совпадает со скаляром с shape () . Тогда почему я не могу не выполнять операцию на месте a = b
, где a
имеет форму ()
и b
имеет форму (1,)
? Работает обратное.
Код:
a = np.array(0)
b = np.array([0])
a b # valid
b = a # valid
a = b # ValueError
Результат:
ValueError: non-broadcastable output operand with shape () doesn't match the broadcast shape (1,)
Комментарии:
1. При работе с массивом с shape не учитывается особый случай
(1,)
, когда вы просто не можете преобразовать одномерный массив в нулевой размерный. Однако в этом случае вы могли бы использоватьa = b.squeeze()
, что, вероятно, более уместно. Противоположное работает, потому что вы можете преобразовать нулевой размерный ndarray в любую форму.2.
a[()]
является единственным допустимым индексом дляa
.
Ответ №1:
Хотя мы можем получить некоторые идеи из тестирования, это может сводиться к деталям реализации (в скомпилированном коде).
In [81]: a = np.array(0); b = np.array([0])
In [82]: a,b
Out[82]: (array(0), array([0]))
Сумма двух создает массив (1,) . Это согласуется с правилами трансляции. a
передается в (1,), а затем суммируется.
In [83]: a b
Out[83]: array([0])
Мы можем добавить () или скалярный:
In [84]: a = a
но ваш случай ошибки, по-видимому, пытается поместить эту (1,) сумму в () цель:
In [85]: a = b
Traceback (most recent call last):
File "<ipython-input-85-294cacd62d6f>", line 1, in <module>
a = b
ValueError: non-broadcastable output operand with shape () doesn't match the broadcast shape (1,)
С правильным индексом можно присвоить значение a
:
In [86]: a[:] = 1
Traceback (most recent call last):
File "<ipython-input-86-aa15caba710a>", line 1, in <module>
a[:] = 1
IndexError: too many indices for array: array is 0-dimensional, but 1 were indexed
In [87]: a[()] =2
In [88]: a
Out[88]: array(2)
In [89]: a[...] = a b
In [90]: a
Out[90]: array(2)
Но, по-видимому =
, тип присваивания использует этот более обобщенный подход к присвоению.
Мы также не можем =
преобразовать (1,1) в (1,):
In [92]: b = np.array([[1]])
Traceback (most recent call last):
File "<ipython-input-92-15b525996e5d>", line 1, in <module>
b = np.array([[1]])
ValueError: non-broadcastable output operand with shape (1,) doesn't match the broadcast shape (1,1)
Очевидно =
, что такое назначение не может уменьшить числовые размеры.
В качестве примечания, можно передать массив (1,) в массив (0,)
In [100]: c = np.zeros((0,))
In [101]: c = b
In [102]: c
Out[102]: array([], dtype=float64)
То есть на 2-м этапе трансляции (после сопоставления количества измерений) он может уменьшить размер 1 измерения до 0. Но это отличается от изменения количества измерений с n 1
на n
.