6.10. Транслювання¶
Коли бінарний оператор отримує два масиви, форми яких не збігаються точно, numpy не підіймає виняток – він транслює. Транслювання – це невелика множина правил, що визначає, чи сумісні дві форми, і якщо так, як менша з них віртуально розтягується, щоб відповідати більшій.
6.10.1. Правила¶
Коли два операнди мають форми A та B, numpy обробляє їх у два кроки.
Вирівняти ранги. Якщо один операнд має менше осей, ніж інший,
numpyвіртуально доповнює початок його форми осями розміру 1, поки обидві форми не матимуть однакову кількість осей. Одновимірний операнд форми(3,)у парі з двовимірним операндом форми(2, 3)стає(1, 3)проти(2, 3).Перевірити кожну вісь. Проходячи тепер однакові за довжиною форми вісь за віссю, кожна пара розмірів повинна задовольняти одну з двох умов: розміри рівні, або один з них дорівнює 1. Вісь розміру 1 віртуально розтягується до розміру іншої сторони для операції. Пара
(1, 3)проти(2, 3)є сумісною, оскільки перша вісь має 1 (розтягується до 2), а друга вісь збігається (3 == 3); результат має форму(2, 3).
Якщо будь-яка пара осей не задовольняє жодної умови, форми несумісні, і оператор підіймає ValueError.
6.10.2. Приклади¶
Скаляр проти будь-якого масиву. Скаляр діє як форма (1,) і розтягується до будь-чого:
a = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float)
a + 10 # (2, 3) + scalar -> (2, 3)
Одновимірний вектор через двовимірну матрицю. Правило 1 додає вісь розміру 1 на початок, перетворюючи (3,) у (1, 3); потім правило 2 розтягує цей рядок вниз по кожному стовпцю a
row = np.array([100, 200, 300], dtype=np.float)
a + row # (2, 3) + (3,) -> (2, 3)
Два одновимірних масиви однакової довжини додаються поелементно – транслювання не потрібне:
np.arange(4) + np.arange(4)
Стовпцевий вектор проти рядкового вектора дає двовимірну «зовнішню» форму: (4, 1) у парі з (3,) стає (4, 1) проти (1, 3) після доповнення рангу, і правило 2 розтягує кожен операнд вздовж його осі розміру 1:
x = np.array([1, 2, 3, 4]).reshape((4, 1)) # column
y = np.array([10, 20, 30]) # row
x + y # (4, 3) matrix
Ті самі правила форми застосовуються до будь-якого ufunc з двома аргументами, включно з arctan2()
np.arctan2(y, 1.0)
np.arctan2(y, x)
6.10.3. Що транслювання не виділяє¶
Розтягування є віртуальним. numpy проходить обидва операнди разом, повторно читаючи менший вздовж його осі транслювання замість копіювання. Дані коротшого масиву ніколи не дублюються в пам’яті.
Важливим для пам’яті є розмір вихідного масиву. a + row виділяє вихідний масив форми a, а не форми a плюс форма row. Довгі ланцюжки транслювання все одно можуть давати великі проміжні результати.
6.10.4. Коли транслювання йде не так¶
Класична помилка – дві форми, де жодна не має осі розміру 1 для розтягування, а розміри не збігаються – наприклад, (3, 4) проти (4, 3). Правило 2 не може порівняти 3 з 4, тому numpy підіймає ValueError.
Більш тонка проблема – транслювання, яке відбувається успішно, але не так, як задумав застосунок. (5,) проти (5, 1) – це канонічний випадок: доповнення рангу перетворює (5,) у (1, 5), яке транслюється проти (5, 1) і дає матрицю (5, 5) – зовнішню комбінацію двох векторів, а не поелементний результат довжиною 5, який, мабуть, мав на увазі застосунок. Якщо є сумніви, виведіть shape для обох сторін та пройдіть через правила перед використанням reshape() або transpose().