Voir sur TensorFlow.org | Exécuter dans Google Colab | Voir la source sur GitHub | Télécharger le cahier |
La formation d'un modèle s'accompagne généralement d'un certain prétraitement des fonctionnalités, en particulier lorsqu'il s'agit de données structurées. Lors de la formation d'un tf.estimator.Estimator
dans TF1, ce prétraitement de fonctionnalité est généralement effectué avec l'API tf.feature_column
. Dans TF2, ce prétraitement peut se faire directement avec les couches Keras, appelées couches de prétraitement .
Dans ce guide de migration, vous effectuerez certaines transformations de fonctionnalités courantes en utilisant à la fois des colonnes de fonctionnalités et des couches de prétraitement, puis vous entraînerez un modèle complet avec les deux API.
Tout d'abord, commencez par quelques importations nécessaires,
import tensorflow as tf
import tensorflow.compat.v1 as tf1
import math
et ajoutez un utilitaire pour appeler une colonne de fonctionnalités à des fins de démonstration :
def call_feature_columns(feature_columns, inputs):
# This is a convenient way to call a `feature_column` outside of an estimator
# to display its output.
feature_layer = tf1.keras.layers.DenseFeatures(feature_columns)
return feature_layer(inputs)
Gestion des entrées
Pour utiliser des colonnes de caractéristiques avec un estimateur, les entrées du modèle doivent toujours être un dictionnaire de tenseurs :
input_dict = {
'foo': tf.constant([1]),
'bar': tf.constant([0]),
'baz': tf.constant([-1])
}
Chaque colonne de caractéristiques doit être créée avec une clé à indexer dans les données source. La sortie de toutes les colonnes de caractéristiques est concaténée et utilisée par le modèle d'estimateur.
columns = [
tf1.feature_column.numeric_column('foo'),
tf1.feature_column.numeric_column('bar'),
tf1.feature_column.numeric_column('baz'),
]
call_feature_columns(columns, input_dict)
<tf.Tensor: shape=(1, 3), dtype=float32, numpy=array([[ 0., -1., 1.]], dtype=float32)>
Dans Keras, la saisie du modèle est beaucoup plus flexible. Un tf.keras.Model
peut gérer une seule entrée de tenseur, une liste de caractéristiques de tenseur ou un dictionnaire de caractéristiques de tenseur. Vous pouvez gérer l'entrée du dictionnaire en transmettant un dictionnaire de tf.keras.Input
lors de la création du modèle. Les entrées ne seront pas concaténées automatiquement, ce qui permet de les utiliser de manière beaucoup plus flexible. Ils peuvent être concaténés avec tf.keras.layers.Concatenate
.
inputs = {
'foo': tf.keras.Input(shape=()),
'bar': tf.keras.Input(shape=()),
'baz': tf.keras.Input(shape=()),
}
# Inputs are typically transformed by preprocessing layers before concatenation.
outputs = tf.keras.layers.Concatenate()(inputs.values())
model = tf.keras.Model(inputs=inputs, outputs=outputs)
model(input_dict)
<tf.Tensor: shape=(3,), dtype=float32, numpy=array([ 1., 0., -1.], dtype=float32)>
ID entiers d'encodage à chaud
Une transformation de caractéristique courante consiste à encoder à chaud des entrées entières d'une plage connue. Voici un exemple utilisant des colonnes de caractéristiques :
categorical_col = tf1.feature_column.categorical_column_with_identity(
'type', num_buckets=3)
indicator_col = tf1.feature_column.indicator_column(categorical_col)
call_feature_columns(indicator_col, {'type': [0, 1, 2]})
<tf.Tensor: shape=(3, 3), dtype=float32, numpy= array([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]], dtype=float32)>
En utilisant les couches de prétraitement Keras, ces colonnes peuvent être remplacées par une seule couche tf.keras.layers.CategoryEncoding
avec output_mode
défini sur 'one_hot'
:
one_hot_layer = tf.keras.layers.CategoryEncoding(
num_tokens=3, output_mode='one_hot')
one_hot_layer([0, 1, 2])
<tf.Tensor: shape=(3, 3), dtype=float32, numpy= array([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]], dtype=float32)>
Normalisation des caractéristiques numériques
Lors de la gestion d'entités continues à virgule flottante avec des colonnes d'entités, vous devez utiliser un tf.feature_column.numeric_column
. Dans le cas où l'entrée est déjà normalisée, la convertir en Keras est trivial. Vous pouvez simplement utiliser un tf.keras.Input
directement dans votre modèle, comme indiqué ci-dessus.
Une numeric_column
peut également être utilisée pour normaliser l'entrée :
def normalize(x):
mean, variance = (2.0, 1.0)
return (x - mean) / math.sqrt(variance)
numeric_col = tf1.feature_column.numeric_column('col', normalizer_fn=normalize)
call_feature_columns(numeric_col, {'col': tf.constant([[0.], [1.], [2.]])})
<tf.Tensor: shape=(3, 1), dtype=float32, numpy= array([[-2.], [-1.], [ 0.]], dtype=float32)>
En revanche, avec Keras, cette normalisation peut être effectuée avec tf.keras.layers.Normalization
.
normalization_layer = tf.keras.layers.Normalization(mean=2.0, variance=1.0)
normalization_layer(tf.constant([[0.], [1.], [2.]]))
<tf.Tensor: shape=(3, 1), dtype=float32, numpy= array([[-2.], [-1.], [ 0.]], dtype=float32)>
Fonctions numériques de regroupement et d'encodage à chaud
Une autre transformation courante des entrées continues à virgule flottante consiste à les compartimenter ensuite en nombres entiers d'une plage fixe.
Dans les colonnes de fonctionnalités, cela peut être réalisé avec un tf.feature_column.bucketized_column
:
numeric_col = tf1.feature_column.numeric_column('col')
bucketized_col = tf1.feature_column.bucketized_column(numeric_col, [1, 4, 5])
call_feature_columns(bucketized_col, {'col': tf.constant([1., 2., 3., 4., 5.])})
<tf.Tensor: shape=(5, 4), dtype=float32, numpy= array([[0., 1., 0., 0.], [0., 1., 0., 0.], [0., 1., 0., 0.], [0., 0., 1., 0.], [0., 0., 0., 1.]], dtype=float32)>
Dans Keras, cela peut être remplacé par tf.keras.layers.Discretization
:
discretization_layer = tf.keras.layers.Discretization(bin_boundaries=[1, 4, 5])
one_hot_layer = tf.keras.layers.CategoryEncoding(
num_tokens=4, output_mode='one_hot')
one_hot_layer(discretization_layer([1., 2., 3., 4., 5.]))
<tf.Tensor: shape=(5, 4), dtype=float32, numpy= array([[0., 1., 0., 0.], [0., 1., 0., 0.], [0., 1., 0., 0.], [0., 0., 1., 0.], [0., 0., 0., 1.]], dtype=float32)>
Encodage à chaud des données de chaîne avec un vocabulaire
La gestion des fonctionnalités de chaîne nécessite souvent une recherche de vocabulaire pour traduire les chaînes en index. Voici un exemple utilisant des colonnes de caractéristiques pour rechercher des chaînes, puis encoder à chaud les index :
vocab_col = tf1.feature_column.categorical_column_with_vocabulary_list(
'sizes',
vocabulary_list=['small', 'medium', 'large'],
num_oov_buckets=0)
indicator_col = tf1.feature_column.indicator_column(vocab_col)
call_feature_columns(indicator_col, {'sizes': ['small', 'medium', 'large']})
<tf.Tensor: shape=(3, 3), dtype=float32, numpy= array([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]], dtype=float32)>
À l'aide des couches de prétraitement Keras, utilisez la couche tf.keras.layers.StringLookup
avec output_mode
défini sur 'one_hot'
:
string_lookup_layer = tf.keras.layers.StringLookup(
vocabulary=['small', 'medium', 'large'],
num_oov_indices=0,
output_mode='one_hot')
string_lookup_layer(['small', 'medium', 'large'])
<tf.Tensor: shape=(3, 3), dtype=float32, numpy= array([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]], dtype=float32)>
Intégrer des données de chaîne avec un vocabulaire
Pour les vocabulaires plus volumineux, une incorporation est souvent nécessaire pour de bonnes performances. Voici un exemple d'intégration d'une fonctionnalité de chaîne à l'aide de colonnes de fonctionnalités :
vocab_col = tf1.feature_column.categorical_column_with_vocabulary_list(
'col',
vocabulary_list=['small', 'medium', 'large'],
num_oov_buckets=0)
embedding_col = tf1.feature_column.embedding_column(vocab_col, 4)
call_feature_columns(embedding_col, {'col': ['small', 'medium', 'large']})
<tf.Tensor: shape=(3, 4), dtype=float32, numpy= array([[-0.01798586, -0.2808677 , 0.27639154, 0.06081508], [ 0.05771849, 0.02464074, 0.20080602, 0.50164527], [-0.9208247 , -0.40816694, -0.49132794, 0.9203153 ]], dtype=float32)>
En utilisant les couches de prétraitement Keras, cela peut être réalisé en combinant une couche tf.keras.layers.StringLookup
et une couche tf.keras.layers.Embedding
. La sortie par défaut pour le StringLookup
sera des indices entiers qui peuvent être introduits directement dans une intégration.
string_lookup_layer = tf.keras.layers.StringLookup(
vocabulary=['small', 'medium', 'large'], num_oov_indices=0)
embedding = tf.keras.layers.Embedding(3, 4)
embedding(string_lookup_layer(['small', 'medium', 'large']))
<tf.Tensor: shape=(3, 4), dtype=float32, numpy= array([[ 0.04838837, -0.04014301, 0.02001903, -0.01150769], [-0.04580117, -0.04319514, 0.03725603, -0.00572466], [-0.0401094 , 0.00997342, 0.00111955, 0.00132702]], dtype=float32)>
Sommation de données catégorielles pondérées
Dans certains cas, vous devez traiter des données catégorielles où chaque occurrence d'une catégorie est associée à un poids. Dans les colonnes de caractéristiques, cela est géré avec tf.feature_column.weighted_categorical_column
. Lorsqu'il est associé à un indicator_column
, cela a pour effet d'additionner les poids par catégorie.
ids = tf.constant([[5, 11, 5, 17, 17]])
weights = tf.constant([[0.5, 1.5, 0.7, 1.8, 0.2]])
categorical_col = tf1.feature_column.categorical_column_with_identity(
'ids', num_buckets=20)
weighted_categorical_col = tf1.feature_column.weighted_categorical_column(
categorical_col, 'weights')
indicator_col = tf1.feature_column.indicator_column(weighted_categorical_col)
call_feature_columns(indicator_col, {'ids': ids, 'weights': weights})
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/feature_column/feature_column_v2.py:4203: sparse_merge (from tensorflow.python.ops.sparse_ops) is deprecated and will be removed in a future version. Instructions for updating: No similar op available at this time. <tf.Tensor: shape=(1, 20), dtype=float32, numpy= array([[0. , 0. , 0. , 0. , 0. , 1.2, 0. , 0. , 0. , 0. , 0. , 1.5, 0. , 0. , 0. , 0. , 0. , 2. , 0. , 0. ]], dtype=float32)>
Dans Keras, cela peut être fait en passant une entrée count_weights
à tf.keras.layers.CategoryEncoding
avec output_mode='count'
.
ids = tf.constant([[5, 11, 5, 17, 17]])
weights = tf.constant([[0.5, 1.5, 0.7, 1.8, 0.2]])
# Using sparse output is more efficient when `num_tokens` is large.
count_layer = tf.keras.layers.CategoryEncoding(
num_tokens=20, output_mode='count', sparse=True)
tf.sparse.to_dense(count_layer(ids, count_weights=weights))
<tf.Tensor: shape=(1, 20), dtype=float32, numpy= array([[0. , 0. , 0. , 0. , 0. , 1.2, 0. , 0. , 0. , 0. , 0. , 1.5, 0. , 0. , 0. , 0. , 0. , 2. , 0. , 0. ]], dtype=float32)>
Intégration de données catégorielles pondérées
Vous pouvez également intégrer des entrées catégorielles pondérées. Dans les colonnes de caractéristiques, embedding_column
contient un argument combiner
. Si un échantillon contient plusieurs entrées pour une catégorie, elles seront combinées en fonction du paramètre d'argument (par défaut 'mean'
).
ids = tf.constant([[5, 11, 5, 17, 17]])
weights = tf.constant([[0.5, 1.5, 0.7, 1.8, 0.2]])
categorical_col = tf1.feature_column.categorical_column_with_identity(
'ids', num_buckets=20)
weighted_categorical_col = tf1.feature_column.weighted_categorical_column(
categorical_col, 'weights')
embedding_col = tf1.feature_column.embedding_column(
weighted_categorical_col, 4, combiner='mean')
call_feature_columns(embedding_col, {'ids': ids, 'weights': weights})
<tf.Tensor: shape=(1, 4), dtype=float32, numpy= array([[ 0.02666993, 0.289671 , 0.18065728, -0.21045178]], dtype=float32)>
Dans Keras, il n'y a pas d'option de tf.keras.layers.Embedding
combiner
mais vous pouvez obtenir le même effet avec tf.keras.layers.Dense
. La embedding_column
ci-dessus combine simplement de manière linéaire les vecteurs d'intégration en fonction du poids de la catégorie. Bien que cela ne soit pas évident au début, cela revient exactement à représenter vos entrées catégorielles sous la forme d'un vecteur de poids clairsemé de size (num_tokens)
et de les multiplier par un noyau Dense
de forme (embedding_size, num_tokens)
.
ids = tf.constant([[5, 11, 5, 17, 17]])
weights = tf.constant([[0.5, 1.5, 0.7, 1.8, 0.2]])
# For `combiner='mean'`, normalize your weights to sum to 1. Removing this line
# would be eqivalent to an `embedding_column` with `combiner='sum'`.
weights = weights / tf.reduce_sum(weights, axis=-1, keepdims=True)
count_layer = tf.keras.layers.CategoryEncoding(
num_tokens=20, output_mode='count', sparse=True)
embedding_layer = tf.keras.layers.Dense(4, use_bias=False)
embedding_layer(count_layer(ids, count_weights=weights))
<tf.Tensor: shape=(1, 4), dtype=float32, numpy= array([[-0.03897291, -0.27131438, 0.09332469, 0.04333957]], dtype=float32)>
Exemple de formation complet
Pour afficher un flux de travail de formation complet, préparez d'abord des données avec trois fonctionnalités de types différents :
features = {
'type': [0, 1, 1],
'size': ['small', 'small', 'medium'],
'weight': [2.7, 1.8, 1.6],
}
labels = [1, 1, 0]
predict_features = {'type': [0], 'size': ['foo'], 'weight': [-0.7]}
Définissez des constantes communes aux workflows TF1 et TF2 :
vocab = ['small', 'medium', 'large']
one_hot_dims = 3
embedding_dims = 4
weight_mean = 2.0
weight_variance = 1.0
Avec des colonnes de fonctionnalités
Les colonnes de caractéristiques doivent être transmises sous forme de liste à l'estimateur lors de la création et seront appelées implicitement lors de la formation.
categorical_col = tf1.feature_column.categorical_column_with_identity(
'type', num_buckets=one_hot_dims)
# Convert index to one-hot; e.g. [2] -> [0,0,1].
indicator_col = tf1.feature_column.indicator_column(categorical_col)
# Convert strings to indices; e.g. ['small'] -> [1].
vocab_col = tf1.feature_column.categorical_column_with_vocabulary_list(
'size', vocabulary_list=vocab, num_oov_buckets=1)
# Embed the indices.
embedding_col = tf1.feature_column.embedding_column(vocab_col, embedding_dims)
normalizer_fn = lambda x: (x - weight_mean) / math.sqrt(weight_variance)
# Normalize the numeric inputs; e.g. [2.0] -> [0.0].
numeric_col = tf1.feature_column.numeric_column(
'weight', normalizer_fn=normalizer_fn)
estimator = tf1.estimator.DNNClassifier(
feature_columns=[indicator_col, embedding_col, numeric_col],
hidden_units=[1])
def _input_fn():
return tf1.data.Dataset.from_tensor_slices((features, labels)).batch(1)
estimator.train(_input_fn)
INFO:tensorflow:Using default config. WARNING:tensorflow:Using temporary folder as model directory: /tmp/tmp8lwbuor2 INFO:tensorflow:Using config: {'_model_dir': '/tmp/tmp8lwbuor2', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': allow_soft_placement: true graph_options { rewrite_options { meta_optimizer_iterations: ONE } } , '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_device_fn': None, '_protocol': None, '_eval_distribute': None, '_experimental_distribute': None, '_experimental_max_worker_delay_secs': None, '_session_creation_timeout_secs': 7200, '_checkpoint_save_graph_def': True, '_service': None, '_cluster_spec': ClusterSpec({}), '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1} WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/training/training_util.py:236: Variable.initialized_value (from tensorflow.python.ops.variables) is deprecated and will be removed in a future version. Instructions for updating: Use Variable.read_value. Variables in 2.X are initialized automatically both in eager and graph (inside tf.defun) contexts. INFO:tensorflow:Calling model_fn. WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/training/adagrad.py:77: calling Constant.__init__ (from tensorflow.python.ops.init_ops) with dtype is deprecated and will be removed in a future version. Instructions for updating: Call initializer instance with the dtype argument instead of passing it to the constructor INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Create CheckpointSaverHook. INFO:tensorflow:Graph was finalized. INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 0... INFO:tensorflow:Saving checkpoints for 0 into /tmp/tmp8lwbuor2/model.ckpt. INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 0... INFO:tensorflow:loss = 0.54634213, step = 0 INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 3... INFO:tensorflow:Saving checkpoints for 3 into /tmp/tmp8lwbuor2/model.ckpt. INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 3... INFO:tensorflow:Loss for final step: 0.7308526. <tensorflow_estimator.python.estimator.canned.dnn.DNNClassifier at 0x7f90685d53d0>
Les colonnes de caractéristiques seront également utilisées pour transformer les données d'entrée lors de l'exécution de l'inférence sur le modèle.
def _predict_fn():
return tf1.data.Dataset.from_tensor_slices(predict_features).batch(1)
next(estimator.predict(_predict_fn))
INFO:tensorflow:Calling model_fn. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Graph was finalized. INFO:tensorflow:Restoring parameters from /tmp/tmp8lwbuor2/model.ckpt-3 INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. {'logits': array([0.5172372], dtype=float32), 'logistic': array([0.6265015], dtype=float32), 'probabilities': array([0.37349847, 0.6265015 ], dtype=float32), 'class_ids': array([1]), 'classes': array([b'1'], dtype=object), 'all_class_ids': array([0, 1], dtype=int32), 'all_classes': array([b'0', b'1'], dtype=object)}
Avec les couches de prétraitement Keras
Les couches de prétraitement Keras sont plus flexibles quant à l'endroit où elles peuvent être appelées. Une couche peut être appliquée directement aux tenseurs, utilisée dans un pipeline d'entrée tf.data
ou intégrée directement dans un modèle Keras entraînable.
Dans cet exemple, vous appliquerez des couches de prétraitement dans un pipeline d'entrée tf.data
. Pour ce faire, vous pouvez définir un tf.keras.Model
distinct pour prétraiter vos entités d'entrée. Ce modèle ne peut pas être entraîné, mais constitue un moyen pratique de regrouper les couches de prétraitement.
inputs = {
'type': tf.keras.Input(shape=(), dtype='int64'),
'size': tf.keras.Input(shape=(), dtype='string'),
'weight': tf.keras.Input(shape=(), dtype='float32'),
}
# Convert index to one-hot; e.g. [2] -> [0,0,1].
type_output = tf.keras.layers.CategoryEncoding(
one_hot_dims, output_mode='one_hot')(inputs['type'])
# Convert size strings to indices; e.g. ['small'] -> [1].
size_output = tf.keras.layers.StringLookup(vocabulary=vocab)(inputs['size'])
# Normalize the numeric inputs; e.g. [2.0] -> [0.0].
weight_output = tf.keras.layers.Normalization(
axis=None, mean=weight_mean, variance=weight_variance)(inputs['weight'])
outputs = {
'type': type_output,
'size': size_output,
'weight': weight_output,
}
preprocessing_model = tf.keras.Model(inputs, outputs)
Vous pouvez maintenant appliquer ce modèle dans un appel à tf.data.Dataset.map
. Veuillez noter que la fonction transmise à map
sera automatiquement convertie en tf.function
, et les mises en garde habituelles pour l'écriture du code tf.function
s'appliquent (pas d'effets secondaires).
# Apply the preprocessing in tf.data.Dataset.map.
dataset = tf.data.Dataset.from_tensor_slices((features, labels)).batch(1)
dataset = dataset.map(lambda x, y: (preprocessing_model(x), y),
num_parallel_calls=tf.data.AUTOTUNE)
# Display a preprocessed input sample.
next(dataset.take(1).as_numpy_iterator())
({'type': array([[1., 0., 0.]], dtype=float32), 'size': array([1]), 'weight': array([0.70000005], dtype=float32)}, array([1], dtype=int32))
Ensuite, vous pouvez définir un Model
séparé contenant les couches entraînables. Notez comment les entrées de ce modèle reflètent désormais les types et formes d'entités prétraités.
inputs = {
'type': tf.keras.Input(shape=(one_hot_dims,), dtype='float32'),
'size': tf.keras.Input(shape=(), dtype='int64'),
'weight': tf.keras.Input(shape=(), dtype='float32'),
}
# Since the embedding is trainable, it needs to be part of the training model.
embedding = tf.keras.layers.Embedding(len(vocab), embedding_dims)
outputs = tf.keras.layers.Concatenate()([
inputs['type'],
embedding(inputs['size']),
tf.expand_dims(inputs['weight'], -1),
])
outputs = tf.keras.layers.Dense(1)(outputs)
training_model = tf.keras.Model(inputs, outputs)
Vous pouvez maintenant former le training_model
avec tf.keras.Model.fit
.
# Train on the preprocessed data.
training_model.compile(
loss=tf.keras.losses.BinaryCrossentropy(from_logits=True))
training_model.fit(dataset)
3/3 [==============================] - 0s 3ms/step - loss: 0.7248 <keras.callbacks.History at 0x7f9041a294d0>
Enfin, au moment de l'inférence, il peut être utile de combiner ces étapes distinctes en un seul modèle qui gère les entrées d'entités brutes.
inputs = preprocessing_model.input
outpus = training_model(preprocessing_model(inputs))
inference_model = tf.keras.Model(inputs, outpus)
predict_dataset = tf.data.Dataset.from_tensor_slices(predict_features).batch(1)
inference_model.predict(predict_dataset)
array([[0.936637]], dtype=float32)
Ce modèle composé peut être enregistré en tant que SavedModel pour une utilisation ultérieure.
inference_model.save('model')
restored_model = tf.keras.models.load_model('model')
restored_model.predict(predict_dataset)
WARNING:tensorflow:Compiled the loaded model, but the compiled metrics have yet to be built. `model.compile_metrics` will be empty until you train or evaluate the model. 2021-10-27 01:23:25.649967: W tensorflow/python/util/util.cc:348] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them. INFO:tensorflow:Assets written to: model/assets WARNING:tensorflow:No training configuration found in save file, so the model was *not* compiled. Compile it manually. array([[0.936637]], dtype=float32)
Tableau d'équivalence des colonnes de fonctions
Pour référence, voici une correspondance approximative entre les colonnes de caractéristiques et les couches de prétraitement :
* output_mode
peut être transmis à layers.CategoryEncoding
, layers.StringLookup
, layers.IntegerLookup
et layers.TextVectorization
.
† layers.TextVectorization
peut gérer directement la saisie de texte libre (par exemple, des phrases entières ou des paragraphes). Il ne s'agit pas d'un remplacement un à un pour la gestion des séquences catégorielles dans TF1, mais peut offrir un remplacement pratique pour le prétraitement de texte ad hoc.
Prochaines étapes
- Pour plus d'informations sur les couches de prétraitement keras, consultez le guide de prétraitement des couches .
- Pour un exemple plus approfondi d'application de couches de prétraitement à des données structurées, consultez le didacticiel sur les données structurées .