Esta biblioteca permite leer y escribir archivos TFRecord de manera eficiente en Python. La biblioteca también proporciona un lector de IterableAtAset de archivos TFRecord para Pytorch. Actualmente, no se compresan y se admiten GZIP Tfrecords comprimidos.
pip3 install 'tfrecord[torch]'
Se recomienda crear un archivo de índice para cada archivo TFRecord. El archivo de índice debe proporcionarse al usar varios trabajadores, de lo contrario, el cargador puede devolver los registros duplicados. Puede crear un archivo de índice para un archivo TFRecord individual con este programa de utilidad:
python3 -m tfrecord.tools.tfrecord2idx <tfrecord path> <index path>
Para crear archivos ".tfidnex" para todos " .tfrecord" en un directorio ejecutivo:
tfrecord2idx <data dir>
Use TFRecordDataSet para leer archivos TFRecord en 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 MultITFrecordDataSet para leer múltiples archivos TFRecord. Esta clase muestras de archivos TFRecord dados con probabilidad dada.
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 defecto, MultiTFRecordDataset es infinito, lo que significa que muestra los datos para siempre. Puede hacerlo finito proporcionando la bandera apropiada
dataset = MultiTFRecordDataset(..., infinite=False)
Tanto TFRecordDataSet como MultITFrecordDataSet arrastran automáticamente los datos cuando proporciona un tamaño de cola.
dataset = TFRecordDataset(..., shuffle_queue_size=1024)
Opcionalmente, puede pasar un argumento transform para realizar el procesamiento posterior de las características antes de regresar. Esto se puede usar, por ejemplo, para decodificar imágenes o normalizar los colores a una secuencia de longitud variable de rango o PAD.
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" ]) SecuenceExmples se puede leer y escribir utilizando los mismos métodos que se muestran arriba con un argumento adicional ( sequence_description para leer y sequence_datum para escribir) que hacen que las funciones de lectura/escritura respectivas traten los datos como un ejemplo de secuence.
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 ()Lectura de una secuencia Ejemplo de una tupla que contiene dos 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" ]) Como se describe en la sección sobre Transforming Input , uno puede pasar una función como el argumento transform para realizar el procesamiento posterior de las características. Esto debe usarse especialmente para las características de secuencia, ya que son una secuencia de longitud variable y deben acolcharse antes de ser por lotes.
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 ) Alternativamente, puede optar por implementar un collate_fn personalizado para ensamblar el lote, por ejemplo, para realizar un relleno 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 )