Esta biblioteca permite a leitura e a gravação de arquivos TFRCORD com eficiência no Python. A biblioteca também fornece um leitor de ITERABLEATATASET dos arquivos Tfrecord para Pytorch. Atualmente não compactada e compactada GZIP TfRecords é suportada.
pip3 install 'tfrecord[torch]'
É recomendável criar um arquivo de índice para cada arquivo tfrecord. O arquivo de índice deve ser fornecido ao usar vários trabalhadores, caso contrário, o carregador poderá retornar registros duplicados. Você pode criar um arquivo de índice para um arquivo Tfrecord individual com este programa de utilitário:
python3 -m tfrecord.tools.tfrecord2idx <tfrecord path> <index path>
Para criar arquivos ".tfidnex" para todos os arquivos .tfrecord "em uma execução de diretório:
tfrecord2idx <data dir>
Use o TfRecordDataSet para ler os arquivos TFRecord em Pytorch.
import torch
from tfrecord . torch . dataset import TFRecordDataset
tfrecord_path = "/tmp/data.tfrecord"
index_path = None
description = { "image" : "byte" , "label" : "float" }
dataset = TFRecordDataset ( tfrecord_path , index_path , description )
loader = torch . utils . data . DataLoader ( dataset , batch_size = 32 )
data = next ( iter ( loader ))
print ( data )Use o MultitFrecordDataSet para ler vários arquivos TFRecord. Esta classe amostras de arquivos tfrecord fornecidos com probabilidade determinada.
import torch
from tfrecord . torch . dataset import MultiTFRecordDataset
tfrecord_pattern = "/tmp/{}.tfrecord"
index_pattern = "/tmp/{}.index"
splits = {
"dataset1" : 0.8 ,
"dataset2" : 0.2 ,
}
description = { "image" : "byte" , "label" : "int" }
dataset = MultiTFRecordDataset ( tfrecord_pattern , index_pattern , splits , description )
loader = torch . utils . data . DataLoader ( dataset , batch_size = 32 )
data = next ( iter ( loader ))
print ( data ) Por padrão, MultiTFRecordDataset é infinito, o que significa que ele amostra os dados para sempre. Você pode torná -lo finito, fornecendo a bandeira apropriada
dataset = MultiTFRecordDataset(..., infinite=False)
TfRecordDataSet e multitfrecordataSet embaralham automaticamente os dados quando você fornece um tamanho de fila.
dataset = TFRecordDataset(..., shuffle_queue_size=1024)
Opcionalmente, você pode passar uma função como argumento transform para executar o pós -processamento dos recursos antes de retornar. Isso pode, por exemplo, ser usado para decodificar imagens ou normalizar as cores para um determinado intervalo ou sequência de comprimento variável do alcance.
import tfrecord
import cv2
def decode_image ( features ):
# get BGR image from bytes
features [ "image" ] = cv2 . imdecode ( features [ "image" ], - 1 )
return features
description = {
"image" : "bytes" ,
}
dataset = tfrecord . torch . TFRecordDataset ( "/tmp/data.tfrecord" ,
index_path = None ,
description = description ,
transform = decode_image )
data = next ( iter ( dataset ))
print ( data ) import tfrecord
writer = tfrecord . TFRecordWriter ( "/tmp/data.tfrecord" )
writer . write ({
"image" : ( image_bytes , "byte" ),
"label" : ( label , "float" ),
"index" : ( index , "int" )
})
writer . close () import tfrecord
loader = tfrecord . tfrecord_loader ( "/tmp/data.tfrecord" , None , {
"image" : "byte" ,
"label" : "float" ,
"index" : "int"
})
for record in loader :
print ( record [ "label" ]) Os exemplos de seqüencexames podem ser lidos e escritos usando os mesmos métodos mostrados acima com um argumento extra ( sequence_description for Reading e sequence_datum para escrever) que causam as respectivas funções de leitura/gravação para tratar os dados como uma sequência.
import tfrecord
writer = tfrecord . TFRecordWriter ( "/tmp/data.tfrecord" )
writer . write ({ 'length' : ( 3 , 'int' ), 'label' : ( 1 , 'int' )},
{ 'tokens' : ([[ 0 , 0 , 1 ], [ 0 , 1 , 0 ], [ 1 , 0 , 0 ]], 'int' ), 'seq_labels' : ([ 0 , 1 , 1 ], 'int' )})
writer . write ({ 'length' : ( 3 , 'int' ), 'label' : ( 1 , 'int' )},
{ 'tokens' : ([[ 0 , 0 , 1 ], [ 1 , 0 , 0 ]], 'int' ), 'seq_labels' : ([ 0 , 1 ], 'int' )})
writer . close ()Lendo a partir de uma sequência, por exemplo, uma tupla contendo dois elementos.
import tfrecord
context_description = { "length" : "int" , "label" : "int" }
sequence_description = { "tokens" : "int" , "seq_labels" : "int" }
loader = tfrecord . tfrecord_loader ( "/tmp/data.tfrecord" , None ,
context_description ,
sequence_description = sequence_description )
for context , sequence_feats in loader :
print ( context [ "label" ])
print ( sequence_feats [ "seq_labels" ]) Conforme descrito na seção sobre Transforming Input , pode -se aprovar uma função como o argumento transform para executar o pós -processamento dos recursos. Isso deve ser usado especialmente para os recursos de sequência, pois são sequência de comprimento variável e precisa ser acolchoada antes de serem lotados.
import torch
import numpy as np
from tfrecord . torch . dataset import TFRecordDataset
PAD_WIDTH = 5
def pad_sequence_feats ( data ):
context , features = data
for k , v in features . items ():
features [ k ] = np . pad ( v , (( 0 , PAD_WIDTH - len ( v )), ( 0 , 0 )), 'constant' )
return ( context , features )
context_description = { "length" : "int" , "label" : "int" }
sequence_description = { "tokens" : "int " , "seq_labels" : "int" }
dataset = TFRecordDataset ( "/tmp/data.tfrecord" ,
index_path = None ,
description = context_description ,
transform = pad_sequence_feats ,
sequence_description = sequence_description )
loader = torch . utils . data . DataLoader ( dataset , batch_size = 32 )
data = next ( iter ( loader ))
print ( data ) Como alternativa, você pode optar por implementar um collate_fn personalizado para montar o lote, por exemplo, para executar o preenchimento dinâmico.
import torch
import numpy as np
from tfrecord . torch . dataset import TFRecordDataset
def collate_fn ( batch ):
from torch . utils . data . _utils import collate
from torch . nn . utils import rnn
context , feats = zip ( * batch )
feats_ = { k : [ torch . Tensor ( d [ k ]) for d in feats ] for k in feats [ 0 ]}
return ( collate . default_collate ( context ),
{ k : rnn . pad_sequence ( f , True ) for ( k , f ) in feats_ . items ()})
context_description = { "length" : "int" , "label" : "int" }
sequence_description = { "tokens" : "int " , "seq_labels" : "int" }
dataset = TFRecordDataset ( "/tmp/data.tfrecord" ,
index_path = None ,
description = context_description ,
transform = pad_sequence_feats ,
sequence_description = sequence_description )
loader = torch . utils . data . DataLoader ( dataset , batch_size = 32 , collate_fn = collate_fn )
data = next ( iter ( loader ))
print ( data )