Чем заменить CSV, если у вас очень много данных
Одна из основных проблем формата CSV — размер файлов. В нем мы храним данные в виде строк, соответственно, число 0.0123456789 будет занимать 12 байт. В то же время, это float число, которое должно занимать 4 байта. Мы видим разницу в 3 раза для каждого числа. А их могут быть миллионы! Более того, большой размер файла еще и замедляет скорость его считывания с диска.
Давайте представим: у нас есть датасет размерности (100000000,10) и мы хотим обучить нейросетку. Загрузить в оперативную память такой датасет не получится. Следовательно, нам нужно будет считывать куски с диска. Если в батч мы захотим положить элемент с индексом 1000, то в CSV нам придется пройти все предыдущие 1000 строк (если вы не гуру
memory mapping’а). Это очень долго и неэффективно.
Одно из решений перечисленных проблем — хранение данных в формате
Hdf (Hierarchical Data Format). В этом посте мы расскажем вам только о нем, а если тема интересна, можно еще погуглить
parquet.
Данные в hdf5 хранятся в бинарном формате. Это значит, что 0.0123456789 будет занимать ровно 4 байта. В hdf5 для таблиц есть специальная сущность dataset. Данные в ней хранятся кусками — чанками. В то же время, индексы этих чанков хранятся в B - дереве. Таким образом, у нас получится очень быстро получить доступ к любому чанку. В нашем случае мы возьмем чанк размера (1,10) и сможем очень быстро читать строки.
Можем даже исхитриться и использовать чанк размера (k, 10) и в батч класть данные не по одному элементу, а по k. У нас не будет обычного уровня случайности. Но если k достаточно мало — этим можно пожертвовать в сторону скорости (особенно если bottlneck - чтение с диска)!
Пара интересных фичей hdf5:
1) Сжатие данных (на прикрепленной ниже картинке мы представили пример, во сколько раз может сжать hdf5).
2) Возможность хранения мета-информации. Например, в ней можно хранить описание данных.
3) Возможность хранения нескольких датасетов в одном файле. Например, можно train, test и val хранить в одном файле!
4) А главное, все это поддерживается в
pandas! Важно не забыть pip install pytables. Ну а если у вас действительно большие данные, то лучше напрямую работать с
h5py.
У читателей может возникнуть вопрос: почему бы не использовать sqlite? Там тоже самое B-дерево, также есть разные типы данных, но еще и доступ произвольный не к чанку, а к элементу… Главная причина — скорость. В большинстве случаев hdf5 просто быстрее. Подробнее можно почитать, например, в этом
исследовании.