Простое вычитание вызывает проблему трансляции для различных форм массива

Я попытался решить мою проблему, используя эту ссылку, описывающую беспорядочную трансляцию, но безрезультатно. Как вычесть следующие числовые массивы:

X = np.array([[[1,2,3,4],[1,2,3,4],[1,2,3,4]],
              [[4,3,2,1],[4,3,2,1],[4,3,2,1]]])
X_mean = np.average(X_, axis=1)

Когда я делаю X - X_mean Говорится:

ValueError: operands could not be broadcast together with shapes (2,3,4) (2,4) 

Но делать X[0] - X_mean[0] дает правильный вывод:

array([[ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.]])

2 ответа

Решение

Вы должны держать размеры выровненными для broadcasting иметь место. У тебя есть -

In [4]: whos
Variable   Type       Data/Info
-------------------------------
X          ndarray    2x3x4: 24 elems, type `int64`, 192 bytes
X_mean     ndarray    2x4: 8 elems, type `float64`, 64 bytes
  1. Axis-0 из X_mean уже выровнен с axis-0 из X так что все хорошо там.

  2. Axis-1 из X_mean должен быть выровнен с axis-2 из X вставьте новую ось для X_mean там с None/np.newaxis чтобы axis-1 может быть отодвинут axis-2,

Давайте проверим выравнивание формы -

In [7]: X_mean3D = X_mean[:,None,:]

In [8]: whos
Variable   Type       Data/Info
-------------------------------
X          ndarray    2x3x4: 24 elems, type `int64`, 192 bytes
X_mean     ndarray    2x4: 8 elems, type `float64`, 64 bytes
X_mean3D   ndarray    2x1x4: 8 elems, type `float64`, 64 bytes

Затем выполните вычитание, которое приведет к трансляции -

In [5]: X - X_mean[:,None,:]
Out[5]: 
array([[[ 0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.]],

       [[ 0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.]]])

Как дополнение: в соответствии с правилами вещания Numpy,

При работе с двумя массивами NumPy сравнивает их формы поэлементно. Он начинается с задних размеров и движется вперед. Два измерения совместимы, когда

  • они равны
  • один из них 1

поэтому лучшая идея состоит в том, чтобы формировать данные таким образом, чтобы среднее значение создавалось по оси 0.

В твоем случае:

Y=np.rollaxis(X,1) # reshape (3,2,4)

Y-Y.mean(0) сейчас напрямую

array([[[ 0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.]],

       [[ 0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.]],

       [[ 0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.]]])
Другие вопросы по тегам