A divisão de arquivos TFRecord em shards ajuda a embaralhar grandes conjuntos de dados que não cabem na memória.
Imagine que você tem milhões de exemplos de treinamento salvos no disco e deseja executá-los repetidamente em um processo de treinamento. Além disso, suponha que, para cada repetição dos dados de treinamento (ou seja, cada época), você queira carregar os dados em uma ordem completamente aleatória.
Uma abordagem é ter um arquivo por exemplo de treinamento e gerar uma lista de todos os nomes de arquivos. Em seguida, no início de cada época, você embaralha a lista de nomes de arquivos e carrega os arquivos individuais. O problema com essa abordagem é que você está carregando milhões de arquivos de locais aleatórios no seu disco. Isso pode ser lento, especialmente em uma unidade de disco rígido. Mesmo uma matriz RAID 0 não ajudará com velocidade se você estiver carregando milhões de arquivos pequenos de locais aleatórios. O problema fica ainda pior se você estiver acessando os arquivos por uma conexão de rede.
Outra abordagem é ler os exemplos de treinamento em sequência a partir de um arquivo TFRecord grande e embaralhar os exemplos na memória usando um buffer aleatório. No entanto, o buffer aleatório normalmente não pode ser maior que a memória DDR disponível para sua CPU. E se o buffer de reprodução aleatória for significativamente menor que o seu conjunto de dados, ele poderá não reproduzir adequadamente os dados. Os dados podem ser embaralhados "localmente", mas não embaralhados "globalmente". Ou seja, os exemplos do início do conjunto de dados não podem ser embaralhados com os exemplos do final do conjunto de dados.
Uma boa solução é usar uma combinação equilibrada das duas abordagens acima, dividindo seu conjunto de dados em vários arquivos TFRecord (chamados shards). Durante cada época, você pode embaralhar os nomes dos arquivos de fragmentos para obter a reprodução aleatória global e usar um buffer de reprodução aleatória para obter a reprodução local. Um bom equilíbrio tornará os shards grandes o suficiente para evitar problemas de velocidade do disco, mas os manterá pequenos o suficiente para permitir uma embaralhamento adequado por um buffer de embaralhamento.
Aqui estão as etapas exatas:
- Coloque todos os exemplos de treinamento aleatoriamente em vários arquivos TFRecord (shards).
- No início de cada época, embaralhe a lista de nomes de arquivos do shard.
- Leia exemplos de treinamento dos fragmentos e passe-os por um buffer aleatório. Normalmente, o buffer de reprodução aleatória deve ser maior que o tamanho do fragmento para garantir uma boa reprodução entre fragmentos.
- Passe os exemplos embaralhados para o seu processo de treinamento.
.shuffle()
O método não é uma solução ideal se você tiver um grande arquivo tfrecord. A saída aleatória está um pouco relacionada à ordem original se você não usar um tamanho de buffer grande. Acho que é necessário pré-embaralhar os dados antes de salvar em tfrecord ou dividir em shards quando você tiver um grande conjunto de dados.