С этой целью 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.