L'API tfds.features.FeatureConnector
:
- Definisce la struttura, le forme, i dtype del
tf.data.Dataset
finale - Serializzazione astratta su/da disco.
- Esporre metadati aggiuntivi (ad esempio nomi di etichette, frequenza di campionamento audio,...)
Panoramica
tfds.features.FeatureConnector
definisce la struttura delle caratteristiche del set di dati (in tfds.core.DatasetInfo
):
tfds.core.DatasetInfo(
features=tfds.features.FeaturesDict({
'image': tfds.features.Image(shape=(28, 28, 1), doc='Grayscale image'),
'label': tfds.features.ClassLabel(
names=['no', 'yes'],
doc=tfds.features.Documentation(
desc='Whether this is a picture of a cat',
value_range='yes or no'
),
),
'metadata': {
'id': tf.int64,
'timestamp': tfds.features.Scalar(
tf.int64,
doc='Timestamp when this picture was taken as seconds since epoch'),
'language': tf.string,
},
}),
)
Le funzionalità possono essere documentate utilizzando solo una descrizione testuale ( doc='description'
) o utilizzando direttamente tfds.features.Documentation
per fornire una descrizione più dettagliata della funzionalità.
Le caratteristiche possono essere:
- Valori scalari:
tf.bool
,tf.string
,tf.float32
,... Quando si desidera documentare la funzionalità, è anche possibile utilizzaretfds.features.Scalar(tf.int64, doc='description')
. -
tfds.features.Audio
,tfds.features.Video
,... (vedi l'elenco delle funzionalità disponibili) -
dict
di funzionalità nidificate:{'metadata': {'image': Image(), 'description': tf.string} }
,... -
tfds.features.Sequence
nidificate :Sequence({'image': ..., 'id': ...})
,Sequence(Sequence(tf.int64))
,...
Durante la generazione, gli esempi verranno automaticamente serializzati da FeatureConnector.encode_example
in un formato adatto al disco (attualmente buffer del protocollo tf.train.Example
):
yield {
'image': '/path/to/img0.png', # `np.array`, file bytes,... also accepted
'label': 'yes', # int (0-num_classes) also accepted
'metadata': {
'id': 43,
'language': 'en',
},
}
Durante la lettura del set di dati (ad esempio con tfds.load
), i dati vengono decodificati automaticamente con FeatureConnector.decode_example
. Il tf.data.Dataset
restituito corrisponderà alla struttura dict
definita in tfds.core.DatasetInfo
:
ds = tfds.load(...)
ds.element_spec == {
'image': tf.TensorSpec(shape=(28, 28, 1), tf.uint8),
'label': tf.TensorSpec(shape=(), tf.int64),
'metadata': {
'id': tf.TensorSpec(shape=(), tf.int64),
'language': tf.TensorSpec(shape=(), tf.string),
},
}
Serializza/deserializza in proto
TFDS espone un'API di basso livello per serializzare/deserializzare gli esempi nel proto tf.train.Example
.
Per serializzare dict[np.ndarray | Path | str | ...]
in proto bytes
, utilizzare features.serialize_example
:
with tf.io.TFRecordWriter('path/to/file.tfrecord') as writer:
for ex in all_exs:
ex_bytes = features.serialize_example(data)
f.write(ex_bytes)
Per deserializzare in proto bytes
su tf.Tensor
, utilizzare features.deserialize_example
:
ds = tf.data.TFRecordDataset('path/to/file.tfrecord')
ds = ds.map(features.deserialize_example)
Accedi ai metadati
Consulta il documento introduttivo per accedere ai metadati delle funzionalità (nomi delle etichette, forma, dtype,...). Esempio:
ds, info = tfds.load(..., with_info=True)
info.features['label'].names # ['cat', 'dog', ...]
info.features['label'].str2int('cat') # 0
Crea il tuo tfds.features.FeatureConnector
Se ritieni che manchi una funzionalità tra quelle disponibili , apri un nuovo problema .
Per creare il tuo connettore di funzionalità, devi ereditare da tfds.features.FeatureConnector
e implementare i metodi astratti.
- Se la tua funzionalità è un singolo valore tensore, è meglio ereditare da
tfds.features.Tensor
e utilizzaresuper()
quando necessario. Vedi il codice sorgentetfds.features.BBoxFeature
per un esempio. - Se la tua funzionalità è un contenitore di più tensori, è meglio ereditare da
tfds.features.FeaturesDict
e utilizzaresuper()
per codificare automaticamente i sottoconnettori.
L'oggetto tfds.features.FeatureConnector
astrae il modo in cui la funzionalità è codificata sul disco da come viene presentata all'utente. Di seguito è riportato un diagramma che mostra i livelli di astrazione del set di dati e la trasformazione dai file del set di dati grezzi all'oggetto tf.data.Dataset
.
Per creare il tuo connettore di funzionalità, crea la sottoclasse tfds.features.FeatureConnector
e implementa i metodi astratti:
-
encode_example(data)
: Definisce come codificare i dati forniti nel generatore_generate_examples()
in dati compatibili contf.train.Example
. Può restituire un singolo valore o undict
di valori. -
decode_example(data)
: definisce come decodificare i dati dal tensore letto datf.train.Example
nel tensore utente restituito datf.data.Dataset
. -
get_tensor_info()
: indica la forma/dtype dei tensori restituiti datf.data.Dataset
. Può essere facoltativo se si eredita da un altrotfds.features
. - (facoltativo)
get_serialized_info()
: se le informazioni restituite daget_tensor_info()
sono diverse da come i dati vengono effettivamente scritti su disco, è necessario sovrascrivereget_serialized_info()
per corrispondere alle specifiche ditf.train.Example
-
to_json_content
/from_json_content
: è necessario per consentire il caricamento del set di dati senza il codice sorgente originale. Vedi la funzione Audio per un esempio.
Per ulteriori informazioni, dai un'occhiata alla documentazione di tfds.features.FeatureConnector
. È anche meglio guardare esempi reali .