L'API tfds.features.FeatureConnector
:
- Définit la structure, les formes et les types du
tf.data.Dataset
final - Sérialisation abstraite vers/depuis le disque.
- Exposer des métadonnées supplémentaires (par exemple, noms d'étiquettes, fréquence d'échantillonnage audio,...)
Aperçu
tfds.features.FeatureConnector
définit la structure des fonctionnalités de l'ensemble de données (dans 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,
},
}),
)
Les fonctionnalités peuvent être documentées soit en utilisant simplement une description textuelle ( doc='description'
), soit en utilisant directement tfds.features.Documentation
pour fournir une description plus détaillée des fonctionnalités.
Les fonctionnalités peuvent être :
- Valeurs scalaires :
tf.bool
,tf.string
,tf.float32
,... Lorsque vous souhaitez documenter la fonctionnalité, vous pouvez également utilisertfds.features.Scalar(tf.int64, doc='description')
. -
tfds.features.Audio
,tfds.features.Video
,... (voir la liste des fonctionnalités disponibles) -
dict
imbriqué de fonctionnalités :{'metadata': {'image': Image(), 'description': tf.string} }
,... -
tfds.features.Sequence
imbriqué :Sequence({'image': ..., 'id': ...})
,Sequence(Sequence(tf.int64))
,...
Lors de la génération, les exemples seront automatiquement sérialisés par FeatureConnector.encode_example
dans un format adapté au disque (actuellement les tampons de protocole 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',
},
}
Lors de la lecture de l'ensemble de données (par exemple avec tfds.load
), les données sont automatiquement décodées avec FeatureConnector.decode_example
. Le tf.data.Dataset
renvoyé correspondra à la structure dict
définie dans 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),
},
}
Sérialiser/désérialiser en prototype
TFDS expose une API de bas niveau pour sérialiser/désérialiser les exemples dans le proto tf.train.Example
.
Pour sérialiser dict[np.ndarray | Path | str | ...]
en proto bytes
, utilisez 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)
Pour désérialiser en proto bytes
vers tf.Tensor
, utilisez features.deserialize_example
:
ds = tf.data.TFRecordDataset('path/to/file.tfrecord')
ds = ds.map(features.deserialize_example)
Accéder aux métadonnées
Voir la documentation d'introduction pour accéder aux métadonnées des fonctionnalités (noms d'étiquettes, forme, type,...). Exemple:
ds, info = tfds.load(..., with_info=True)
info.features['label'].names # ['cat', 'dog', ...]
info.features['label'].str2int('cat') # 0
Créez votre propre tfds.features.FeatureConnector
Si vous pensez qu'une fonctionnalité manque parmi les fonctionnalités disponibles , veuillez ouvrir un nouveau numéro .
Pour créer votre propre connecteur de fonctionnalités, vous devez hériter de tfds.features.FeatureConnector
et implémenter les méthodes abstraites.
- Si votre fonctionnalité est une valeur de tenseur unique, il est préférable d'hériter de
tfds.features.Tensor
et d'utilisersuper()
si nécessaire. Voir le code sourcetfds.features.BBoxFeature
pour un exemple. - Si votre fonctionnalité est un conteneur de plusieurs tenseurs, il est préférable d'hériter de
tfds.features.FeaturesDict
et d'utiliser lesuper()
pour encoder automatiquement les sous-connecteurs.
L'objet tfds.features.FeatureConnector
fait abstraction de la façon dont la fonctionnalité est codée sur le disque de la façon dont elle est présentée à l'utilisateur. Vous trouverez ci-dessous un diagramme montrant les couches d'abstraction de l'ensemble de données et la transformation des fichiers de l'ensemble de données bruts en l'objet tf.data.Dataset
.
Pour créer votre propre connecteur de fonctionnalités, sous-classez tfds.features.FeatureConnector
et implémentez les méthodes abstraites :
-
encode_example(data)
: Définit comment encoder les données fournies dans le générateur_generate_examples()
en données compatiblestf.train.Example
. Peut renvoyer une valeur unique ou undict
de valeurs. -
decode_example(data)
: Définit comment décoder les données du tenseur lu depuistf.train.Example
en tenseur utilisateur renvoyé partf.data.Dataset
. -
get_tensor_info()
: Indique la forme/le type du ou des tenseurs renvoyés partf.data.Dataset
. Peut être facultatif en cas d'héritage d'un autretfds.features
. - (facultatif)
get_serialized_info()
: Si les informations renvoyées parget_tensor_info()
sont différentes de la façon dont les données sont réellement écrites sur le disque, vous devez alors écraserget_serialized_info()
pour correspondre aux spécifications detf.train.Example
-
to_json_content
/from_json_content
: Ceci est requis pour permettre à votre ensemble de données d'être chargé sans le code source d'origine. Voir Fonctionnalité audio pour un exemple.
Pour plus d'informations, consultez la documentation tfds.features.FeatureConnector
. Il est également préférable de regarder des exemples réels .