Autores:
(1) Sasun Hambardzumyan, Activeloop, Mountain View, CA, EUA;
(2) Abhinav Tuli, Activeloop, Mountain View, CA, EUA;
(3) Levon Ghukasyan, Activeloop, Mountain View, CA, EUA;
(4) Fariz Rahman, Activeloop, Mountain View, CA, EUA;.
(5) Hrant Topchyan, Activeloop, Mountain View, CA, EUA;
(6) David Isayan, Activeloop, Mountain View, CA, EUA;
(7) Mark McQuade, Activeloop, Mountain View, CA, EUA;
(8) Mikayel Harutyunyan, Activeloop, Mountain View, CA, EUA;
(9) Tatevik Hakobyan, Activeloop, Mountain View, CA, EUA;
(10) Ivo Stranic, Activeloop, Mountain View, CA, EUA;
(11) Davit Buniatyan, Activeloop, Mountain View, CA, EUA.
Os conjuntos de dados Deep Lake seguem uma arquitetura de armazenamento colunar, com tensores como colunas, conforme mostrado na Fig. 3. Cada tensor é uma coleção de pedaços - blobs binários que contêm as amostras de dados. Um mapa de índice associado a cada tensor ajuda a encontrar o pedaço e o índice corretos da amostra dentro desse pedaço para um determinado índice de amostra.
Uma amostra em um conjunto de dados representa uma única linha indexada em tensores paralelos. Ao contrário de um formato de armazenamento de documentos, os elementos de amostra são logicamente independentes, o que permite acesso parcial a amostras para executar consultas de alto desempenho ou transmitir tensores selecionados pela rede para as instâncias de treinamento de GPU. Vários tensores podem ser agrupados. Os grupos implementam o aninhamento sintático e definem como os tensores estão relacionados entre si. O aninhamento sintático evita a complicação de formato para layout de memória hierárquica. As alterações no esquema do conjunto de dados também são rastreadas ao longo do tempo com controle de versão, semelhante às alterações no conteúdo do conjunto de dados.
Os tensores são digitados e podem ser anexados ou modificados no local. O acesso padrão a um índice ou conjunto de índices retorna os dados como matrizes NumPy [55]. Em vez de armazenar dados 1-D como visto em Parquet [79] ou séries em Arrow [13], os tensores podem acomodar dados n-dimensionais, onde normalmente a primeira dimensão corresponde ao índice ou dimensão do lote. Os tensores podem conter matrizes de formato dinâmico, também chamadas de tensores irregulares, em oposição a outros formatos de matriz estaticamente fragmentados, como Zarr [52].
Htype define as expectativas em amostras em um tensor, como tipo de dados (dtype conforme visto em NumPy [55]), forma, número de dimensões ou compactação. Tensores digitados simplificam a interação com estruturas de aprendizado profundo e permitem verificações de integridade e layout de memória eficiente. Herdando de um tipo de tensor genérico, podemos construir tipos como imagem, vídeo, áudio, bbox, dicom e outros. Por exemplo, um tensor com imagem htype esperaria que as amostras anexadas a ele tivessem dtype como uint8 e comprimento de forma 3 (ou seja, largura, altura e número de canais). Expandimos ainda mais a noção de htypes, permitindo metatipos que suportam o armazenamento de sequências de imagens em tensores (sequence[image]), fazendo referência a imagens armazenadas remotamente, enquanto mantêm o comportamento regular de um tensor de imagem (link[image]), ou mesmo possível suporte para vários formatos.
Um conjunto de dados Deep Lake contém um arquivo de origem em formato JSON e pastas por tensor. Um tensor contém pedaços, codificador de pedaços, codificador de blocos e metadados de tensor. Os tensores podem ser opcionalmente ocultos. Por exemplo, tensores ocultos podem ser usados para manter versões de imagens com amostragem reduzida ou preservar informações de forma para consultas rápidas.
Os tensores são armazenados em pedaços no nível de armazenamento. Embora o chunking de formato estaticamente (inferido) evite a manutenção de uma tabela de mapa de chunks, ele introduz uma sobrecarga significativa do usuário durante a especificação do tensor, limitações de uso de compactação personalizada, armazenamento subutilizado para tensores de formato dinâmico e ineficiências de pós-processamento. Os pedaços do Deep Lake são construídos com base nos limites inferior e superior do tamanho do pedaço para caber em um número limitado de amostras. Isso vem com a desvantagem de ter um mapa de índice compactado que preserva o índice de amostra para mapeamento de ID de bloco por tensor, ao mesmo tempo que permite tamanhos de bloco no intervalo ideal para streaming, ao mesmo tempo que acomoda amostras de formatos mistos. Pode-se considerar a abordagem adotada neste artigo como uma compensação otimizada entre o mapa de páginas do sistema de arquivos e o sistema de armazenamento de array sem mapa definido por computação. Por razões práticas, um codificador de bloco único pode ser dimensionado para bilhões de imagens, mantendo um codificador de bloco de 150 MB por dados de tensor de 1 PB. Escala adicional pode ser introduzida fragmentando o codificador de pedaços. Os pedaços contêm informações de cabeçalho, como intervalos de bytes, formatos das amostras e os próprios dados de amostra. Se uma amostra for maior que o tamanho do pedaço limite superior, o que é o caso de grandes imagens aéreas ou de microscopia, a amostra será dividida em pedaços em dimensões espaciais. A única exceção ao ladrilho são os vídeos. Os vídeos são preservados devido ao mapeamento eficiente de quadros para índices, descompressão somente de quadros-chave e solicitações baseadas em intervalo durante o streaming.
O formato de armazenamento tensor é otimizado para treinamento e inferência de aprendizado profundo, incluindo acesso sequencial e aleatório. O acesso sequencial é usado para executar consultas de varredura, transformar tensores em outros tensores ou executar inferência. Os casos de uso de acesso aleatório incluem vários anotadores escrevendo rótulos na mesma imagem ou modelos armazenando previsões anteriores junto com o conjunto de dados. Enquanto o modo estrito está desabilitado, índices fora dos limites de um tensor podem ser atribuídos, acomodando assim tensores esparsos. No entanto, a atribuição aleatória ao longo do tempo produzirá blocos de dados armazenados de forma ineficiente. Para corrigir o layout dos dados, implementamos um algoritmo de reagrupamento dinâmico para otimizar o layout dos dados. Um dos principais padrões de acesso do Deep Lake é o acesso de fluxo embaralhado para treinar modelos de aprendizado de máquina. Requer acesso de pedido aleatório ou personalizado durante a transmissão de partes no processo de treinamento. Isso é conseguido envolvendo solicitações baseadas em intervalo para acessar subelementos dentro de blocos, executando consultas complexas antes do treinamento para determinar a ordem e mantendo um cache de buffer de dados buscados e não utilizados. Isso evita ter um cluster de computação separado para executar o algoritmo de embaralhamento [50].
Cada tensor tem seus próprios pedaços e o tamanho padrão do pedaço é 8 MB. Um único bloco consiste em dados de vários índices quando os pontos de dados individuais (imagem, rótulo, anotação, etc.) são menores que o tamanho do bloco. Por outro lado, quando os pontos de dados individuais são maiores que o tamanho do bloco, os dados são divididos entre vários blocos (ladrilhos). As exceções à lógica de chunking são os dados de vídeo.
O formato Deep Lake é otimizado para maximizar o rendimento do processamento de GPU. Inclui pré-busca de CPU, descompactação ou decodificação, transformações e transferência de memória de GPU no layout esperado de uma estrutura de aprendizado profundo.
Deep Lake pode ser conectado a qualquer provedor de armazenamento, incluindo armazenamentos de objetos como AWS S3 [1], Google Cloud Storage (GCS) [3], sistemas de arquivos compatíveis com POSIX ou armazenamento local na memória. Além disso, ele constrói cache de memória encadeando vários provedores de armazenamento, por exemplo - o cache menos usado recentemente (LRU) de armazenamento S3 remoto com dados locais na memória.
Este artigo está disponível no arxiv sob licença CC 4.0.