Математика глубокого обучения

Тензоры

Многомерный массив, порядок осей — и почему математический тензор это другое

Шаг 74 из 117 · ~24 мин

Что называют тензором здесь

В глубоком обучении тензор — это многомерный массив чисел плюс его форма. Ничего больше.

TRn1×n2××nkT \in \mathbb{R}^{\htmlData{k=shape}{n_1 \times n_2 \times \dots \times n_k}}

Длина называется порядком (или, менее удачно, «размерностью»):

порядоккак называютпример
00скалярзначение лосса
11векторэмбеддинг токена
22матрицабатч эмбеддингов
33батч × позиция × канал
44батч × канал × высота × ширина

Слово «размерность» здесь перегружено, и путаница из-за него реальна: у тензора формы (8,512)(8, 512) порядок равен двум, а «размерность эмбеддинга» равна 512512. Первое — сколько осей, второе — длина одной из них. В коде это len(x.shape) против x.shape[-1].

Математический тензор — не это

Оговорка, которая экономит недоумение при чтении физики или дифференциальной геометрии.

Там тензор — это полилинейное отображение, определённое независимо от координат, с законом преобразования компонент при замене базиса. Массив чисел — лишь его представление в выбранном базисе, и требование состоит в том, что при смене базиса компоненты меняются согласованно.

тензор в MLтензор в математике
что этомассив с формойполилинейное отображение
зависит от базисавопрос не ставитсянет, компоненты — да
индексы верх/низнетразличаются (ко- и контравариантность)
«тензор ранга 2»форма из двух чиселранг как у линейного оператора

Слово «ранг» тоже расходится: в PyTorch rank иногда означает число осей, а в линейной алгебре (блок 1, урок 030) — размерность образа. У матрицы 3×33\times3 «ранг 2» в первом смысле и «ранг 2» во втором — совершенно разные утверждения.

Никакой практической беды в этом нет: в машинном обучении полилинейность и законы преобразования не используются. Знать различие нужно ровно затем, чтобы не искать в torch того, чего там нет.

Порядок осей — это соглашение

Одни и те же данные хранят по-разному, и это источник целого класса ошибок.

соглашениеформагде
NCHWбатч, канал, высота, ширинаPyTorch по умолчанию
NHWCбатч, высота, ширина, каналTensorFlow, часть ускорителей
batch-firstбатч, позиция, признактрансформеры обычно
seq-firstпозиция, батч, признакстарые RNN-API, nn.Transformer по умолчанию

Последняя строка стоит внимания: у torch.nn.Transformer параметр batch_first исторически по умолчанию равен False. Тензор формы (32,100,512)(32, 100, 512) будет прочитан как «3232 позиции, батч 100100» вместо ожидаемого. Ошибка не падает — формы сходятся, — и проявляется только качеством.

Отсюда практическое правило: ось — это не номер, а имя. Полезно записывать формы в комментариях или пользоваться einops, где оси называются:

# вместо x.permute(0, 2, 1, 3)
rearrange(x, 'b h n d -> b n h d')

Второе читается и, что важнее, проверяется глазами.

Форма против расположения в памяти

Тензор — это буфер плюс страйды, то есть шаги в элементах по каждой оси. Отсюда две вещи, которые обычно узнают на ошибке.

Транспонирование не копирует. x.T возвращает вид: тот же буфер, переставленные страйды. Дёшево, но результат становится нессмежным, и часть операций (например .view()) на нём не работает — отсюда RuntimeError про contiguous и привычка ставить .contiguous().

view против reshape. view требует совместимости со страйдами и падает, если её нет; reshape при необходимости копирует. То есть view — это обещание «копирования не будет», и падение здесь полезно: оно сообщает о неожиданном копировании, а не мешает.

Разница между (8,512)(8, 512) и (8,1,512)(8, 1, 512) тоже стоит понимания: данные те же, но вторая форма имеет ось длины 11, и это меняет поведение broadcasting — о чём следующий урок. Ось длины 11 не бесполезна: она и есть способ сказать «сюда можно растянуть».

Что стоит унести

  • порядок — сколько осей, размерность признаков — длина одной оси. Разные вещи;
  • математический тензор — другое понятие, и искать его в фреймворке не нужно;
  • порядок осей — соглашение, различающееся между библиотеками, и ошибки в нём не падают, а тихо портят результат;
  • форма и расположение в памяти — не одно и то же; view даёт вид, reshape может скопировать.

Источники

Проверки

0 из 2
  1. Что такое тензор здесь

    Отметьте все верные утверждения о тензорах в глубоком обучении.

  2. Порядок, элементы, страйды

    Дана форма тензора как список shape. Реализуйте tensor_facts(shape) — верните [order, elements, feature_dim, stride_of_axis_0]:

    • order — число осей (для скаляра, то есть пустого списка, это 00);
    • elements — произведение всех размеров (для скаляра — 11: пустое произведение);
    • feature_dim — размер последней оси, или -1.0 для скаляра;
    • stride_of_axis_0 — страйд нулевой оси при построчном (row-major) размещении, то есть произведение размеров всех последующих осей. Для скаляра верните -1.0.

    Страйд — это на сколько элементов нужно шагнуть в буфере, чтобы сдвинуться на единицу по данной оси. Для формы (8,100,512)(8, 100, 512) шаг по нулевой оси равен 100512=51200100 \cdot 512 = 51200.

    функция tensor_facts

    Загрузка редактора…

    Ctrl/⌘ + Enter