Было лето, и еще в марте нас выгнали из нашего кампуса. Не имея никаких перспектив на будущее и надежды на возвращение в кампус в ближайшее время, мы были прикованы к своим домам, и нам оставалось только одно интересное - наши летние проекты SnT.

Я был членом Модельного зоопарка при Клубе программирования IIT Канпура. Для первой реализации я взял 3D-GAN, синоним всем известной Generative Adversarial Networks, но только на этот раз в трехмерном пространстве. Но трехмерное пространство дало нам, «энтузиастам машинного обучения», еще одно большое ограничение: огромные наборы данных в гигабайтах!

Как бы вы управляли огромными наборами данных, учитывая, что вы работаете в Google Colab и должны предварительно обрабатывать данные? Бывают случаи, когда данные имеют не тот формат, который вы ожидаете. Сегодня я проиллюстрирую одну из своих методик, которая помогла мне успешно загрузить данные для моей модели 3D-GAN.

Статью можно найти здесь - http://3dgan.csail.mit.edu/

Используемый набор данных

В статье предлагается использовать набор данных IKEA, поскольку он выполняет 3D-реконструкцию объектов по 2D-изображениям. Я ограничиваю себя из-за вычислительных ограничений - я использую довольно популярный набор данных ModelNet-10 и пропускаю ту часть, где они используют вариационный автоэнкодер для генерации скрытого пространства, обучая просто обычную сеть GAN без обучения на основе классов. Вы можете посмотреть здесь.

Предварительная обработка

Набор данных ModelNet-10 поставляется в формате файла .off, который используется для хранения 2D и 3D объектов. Поскольку трехмерные свертки работают с вокселизированными данными, нам необходимо преобразовать их в окончательную форму трехмерного массива, который обозначает воксель, если значение равно 1 (нет вокселя для 0). Теперь, что такое воксель, вы можете спросить? Это трехмерный аналог пикселя. Позвольте мне показать вам пример, и вы легко расскажете.

Это пример того, как должна выглядеть наша конечная точка данных. Хотя это немного переоценка, она определенно служит цели поднять ваш энтузиазм по поводу этой статьи. Это тоже похоже на блочный мир Minecraft, не так ли? Это точно!

Я преобразовал файлы .off в формат binvox. Этот формат широко используется для хранения растеризованных файлов трехмерных моделей в двоичных трехмерных воксельных сетках. Патрик Мин написал прекрасную программу, которая делает это, ее можно найти здесь.

Следующий шаг

Как только вы получите файлы binvox с вокселизацией, вам необходимо преобразовать их в читаемый формат. Ваша модель PyTorch принимает тензоры в качестве входных данных. По крайней мере, вам нужен массив NumPy, который можно преобразовать в тензор на предварительном этапе.

Для этого я использую модуль binvox-rw-py. Это помогает мне читать файлы binvox как массивы NumPy, и я очень счастлив.

Я конвертирую их в воксельную сетку 32x32x32.

Самый большой вызов!

Теперь самая большая проблема - размер. Я выполнил весь процесс, упомянутый выше, на своем локальном компьютере. Первоначальный размер набора данных составлял около 2,2 гигабайта в необработанном виде.

Я преобразовал его в массив NumPy, используя упомянутый выше модуль. Я сохранил его с расширением файла .npy, родным для NumPy, и вот! Его размер составил 8,5 гигабайт!

Что теперь делать, если исходных данных было всего 2,2 ГБ? Я мог бы загрузить его по всему Colab и запустить сценарий для всего процесса онлайн. Но нет, я этого не делал. Я не хотел тратить время на этот процесс, поскольку он включал обработку (копирование-вставку и прочее) большого количества файлов, а виртуальная среда Colab в Интернете не настолько быстра, чтобы дать мне мотивацию для этого.

В сетках было большое количество пустых вокселей. Это означало, что в наших данных было много нулей, наши данные были буквально скудными. Методы сжатия очень хорошо работают с разреженными данными. Я использовал схему сжатия gzip, и она отлично сработала. Мой файл размером 8 ГБ был сжат в файл размером 32 МБ!

Последнее прикосновение

Давайте попробуем загрузить это в виртуальную среду Colab.

import gzip
import numpy as np
with gzip.open('modelnet10.npy.gz','rb') as f:
    arr=np.load(f)
    print(type(arr),arr.shape)

Это дает нам следующий вывод:

<class 'numpy.ndarray'> (3992, 1, 64, 64, 64)

Это было для сетки размером 64x64x64. Было 3992 выборки, распределенные по 10 классам с одним каналом данных. Что мы видим как наш результат выше.

Наш процесс определенно сработал!

Теперь мы должны проверить, как выглядят наши модели! Представим себе модель стула!

import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.gca(projection='3d')
# You might add edgecolor='k' attribute to make black edgelines.
ax.voxels(arr[78][0],facecolors='red') 
plt.show()

Левый - это стул без цвета краев. Правый, как мы видим, - это таблица с черным краем в сетке 32x32x32.

Забрать

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

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

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

Этот пост является частью серии блогов Клуба программирования IIT Kanpur.