С этой целью PyTorch представляет фундаментальную структуру данных: тензор.

Проще говоря, тензор - это структура данных, в которой хранится набор чисел, которые доступны индивидуально по индексу и могут быть проиндексированы с помощью нескольких индексов. В контексте глубокого обучения тензоры относятся к обобщению векторов и матриц для произвольного числа измерений. Другое название той же концепции - многомерный массив.

Суть тензоров

В то время как списки или кортежи Python представляют собой коллекции объектов Python, которые индивидуально хранятся в памяти, тензоры PyTorch и массивы NumPy представляют собой представления над смежными блоками памяти, содержащими распакованный C числовые типы.

Почему числовые типы распакованные C?

  • Числа в Python - это объекты, которые означают, что 32-битное число с плавающей запятой, для представления которого требуется всего 32 бита, преобразуется в объект с подсчетом ссылок и так далее. (называется боксом) Это не проблема при работе с небольшим набором чисел. но распределение миллионов номеров становится неэффективным.
  • Список в Python представляет собой индексируемую коллекцию указателей на объекты Python любого типа и предназначен для их последовательных коллекций. Для списков нет эффективно реализованной операции. Более того, списки одномерные, и хотя вы можете создавать списки списков, это очень неэффективно.
  • С массивами и тензорами NumPy мы имеем дело с оптимизированным кодом на скомпилированном низкоуровневом языке, таком как C, что делает математические операции с числовыми данными намного быстрее, чем при использовании интерпретатора Python.

Создание тензора

Тензорные типы данных

Типы данных представляют возможные значения, которые тензор может содержать, и количество байтов, используемых для хранения каждого значения. Вы можете установить типы данных с помощью аргумента dtype в конструкторе тензора.

  • Вычисления в нейронных сетях обычно выполняются с 32-битной точностью с плавающей запятой. 64-разрядная версия не рекомендуется, поскольку она обычно не улучшает точность и требует больше памяти и вычислительного времени.
  • Использование тензоров для индексации других тензоров требовало, чтобы они имели 64-битный целочисленный тип данных.

Поэтому мы часто используем torch.float32 и torch.int64 как dtype.

Обратите внимание, что хотя числовой тип по умолчанию в PyTorch - это float32, в NumPy это float64.

Перенос тензоров на графический процессор

Любой тензор PyTorch может быть перенесен на графические процессоры, поддерживающие CUDA. Таким образом, все операции с тензором будут выполняться с использованием специальных процедур для графического процессора, которые поставляются с PyTorch и позволяют выполнять чрезвычайно быстрые и параллельные вычисления.

Чтобы указать, где размещается тензор (GPU или CPU), мы можем использовать аргумент device в его конструкторе или можем сделать копию уже созданного тензора в желаемом устройство с помощью метода в.

Мы также можем использовать сокращенные методы cpu и cuda вместо метода to для достижения той же цели:

Метод to возвращает тензор с теми же числовыми данными, но хранится в ОЗУ графического процессора, а не в обычной системной ОЗУ. Также стоит упомянуть, что с помощью метода to мы можем изменить размещение и тип данных одновременно, указав в качестве аргументов и устройство, и dtype.

NumPy Array против Tensor

Как вы, возможно, уже знаете, NumPy - еще одна библиотека для работы с многомерными массивами. Фактически, он настолько популярен, что теперь, возможно, стал lingua franca в науке о данных. Однако тензоры PyTorch имеют несколько сверхспособностей по сравнению с массивами NumPy. Тензоры могут выполнять очень быстрые операции на графических процессорах, выполнять распределенные операции на нескольких устройствах и машинах, а также отслеживать графы вычислений.

Чтобы получить массив NumPy из тензора или наоборот, мы можем использовать следующий код:

Интересно, что если тензор помещается в ЦП, возвращаемый массив NumPy из метода numpy использует тот же буфер, что и хранилище тензора. Это означает, что метод может быть выполнен бесплатно. Это также означает, что изменение массива
NumPy приведет к изменению первого тензора. Если тензор выделяется
на GPU, PyTorch скопирует содержимое тензора в массив NumPy, хранящийся в ЦП.

Сериализация тензоров

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

Теперь предположим, что данные внутри нашего тензора ценны, и вы хотите сохранить их в файл и иметь возможность загрузить обратно. Поэтому нам нужно сериализовать тензорный объект. PyTorch использует pickle под капотом плюс специальный код сериализации для хранилища. Вот пример кода с использованием методов save и load:

Проблема с приведенным выше кодом заключается в том, что, хотя он быстрый и удобный, его невозможно прочитать с помощью другого программного обеспечения, кроме PyTorch.

Чтобы сохранить тензоры и загрузить их обратно в системы, которые уже используют другие библиотеки, такие как tenorflow, мы можем использовать HDF5.

HDF5 - это переносимый, широко поддерживаемый формат для представления сериализованных многомерных массивов, организованных в словарь «ключ-значение». Чтобы использовать формат HDF5, вы должны сначала установить библиотеку h5py. в приведенном ниже коде показан процесс сохранения и загрузки тензоров в формате HDF5:

Большая часть приведенной выше статьи - это мои заметки из книги Глубокое обучение с помощью PyTorch, глава 3. Если вы хотите изучить PyTorch, я настоятельно рекомендую прочитать эту книгу. Я также использовал картинки из книги для лучшего понимания.

В следующей статье я продолжу писать о PyTorch.