Ayuda a proteger la Gran Barrera de Coral con TensorFlow en Kaggle Únete Challenge

Migración de feature_columns a las capas de preprocesamiento Keras de TF2

Ver en TensorFlow.org Ejecutar en Google Colab Ver fuente en GitHub Descargar cuaderno

El entrenamiento de un modelo generalmente vendrá con cierta cantidad de preprocesamiento de características, particularmente cuando se trata de datos estructurados. Cuando la formación de un tf.estimator.Estimator en TF1, este procesamiento previo característica se hace generalmente con la tf.feature_column API. En TF2, este procesamiento previo puede realizarse directamente con capas Keras, llamado pre-procesamiento capas.

En esta guía de migración, realizará algunas transformaciones de características comunes utilizando columnas de características y capas de preprocesamiento, y luego entrenará un modelo completo con ambas API.

Primero, comience con un par de importaciones necesarias,

import tensorflow as tf
import tensorflow.compat.v1 as tf1
import math

y agregue una utilidad para llamar a una columna de funciones para demostración:

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)

Manejo de entrada

Para usar columnas de características con un estimador, siempre se espera que las entradas del modelo sean un diccionario de tensores:

input_dict = {
  'foo': tf.constant([1]),
  'bar': tf.constant([0]),
  'baz': tf.constant([-1])
}

Cada columna de características debe crearse con una clave para indexar en los datos de origen. La salida de todas las columnas de características está concatenada y utilizada por el modelo de estimador.

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)>

En Keras, la entrada de modelos es mucho más flexible. Un tf.keras.Model puede manejar una sola entrada tensor, una lista de características de tensor, o un diccionario de tensor características. Puede manejar la entrada diccionario pasando un diccionario de tf.keras.Input en la creación del modelo. Las entradas no se concatenarán automáticamente, lo que permite que se utilicen de formas mucho más flexibles. Pueden ser concatenados con 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 de números enteros de codificación one-hot

Una transformación de característica común es la codificación one-hot de entradas enteras de un rango conocido. A continuación, se muestra un ejemplo que utiliza columnas de características:

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)>

Usando Keras preprocesamiento capas, estas columnas pueden ser reemplazados por un solo tf.keras.layers.CategoryEncoding capa con output_mode conjunto a '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)>

Normalización de características numéricas

Durante la manipulación continua, de punto flotante cuenta con columnas de características, es necesario utilizar un tf.feature_column.numeric_column . En el caso de que la entrada ya esté normalizada, convertir esto a Keras es trivial. Usted puede simplemente utilizar un tf.keras.Input directamente en su modelo, como se muestra arriba.

A numeric_column también se puede utilizar para la entrada Normalizar:

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)>

Por el contrario, la Keras, esta normalización se puede hacer con 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)>

Funciones numéricas de codificación en caliente y agrupación en segmentos

Otra transformación común de las entradas continuas de punto flotante es dividir en cubos a números enteros de un rango fijo.

En las columnas de funciones, esto se puede lograr con 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)>

En Keras, esto puede ser reemplazado por 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)>

Datos de cadena de codificación one-hot con un vocabulario

El manejo de características de cadenas a menudo requiere una búsqueda de vocabulario para traducir cadenas en índices. Aquí hay un ejemplo que usa columnas de características para buscar cadenas y luego codificar los índices de forma directa:

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)>

El uso de capas de preprocesamiento Keras, utilice el tf.keras.layers.StringLookup capa con output_mode conjunto a '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)>

Incrustar datos de cadenas con un vocabulario

Para vocabularios más amplios, a menudo se necesita una incorporación para un buen desempeño. A continuación, se muestra un ejemplo de incrustación de una característica de cadena utilizando columnas de características:

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)>

El uso de capas de preprocesamiento Keras, esto se puede lograr mediante la combinación de un tf.keras.layers.StringLookup capa y un tf.keras.layers.Embedding capa. La salida por defecto para el StringLookup será número entero índices que pueden ser alimentados directamente en una incrustación.

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)>

Suma de datos categóricos ponderados

En algunos casos, debe tratar con datos categóricos donde cada aparición de una categoría viene con un peso asociado. En las columnas de funciones, esto se maneja con tf.feature_column.weighted_categorical_column . Cuando se combina con un indicator_column , esto tiene el efecto de sumar pesos por categoría.

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)>

En Keras, esto puede hacerse pasando un count_weights de entrada a tf.keras.layers.CategoryEncoding con 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)>

Incorporación de datos categóricos ponderados

Alternativamente, es posible que desee incrustar entradas categóricas ponderadas. En las columnas de características, la embedding_column contiene un combiner argumento. Si cualquier muestra contiene varias entradas para una categoría, que se combinarán de acuerdo con el ajuste de argumento (por defecto '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)>

En Keras, no hay combiner opción de tf.keras.layers.Embedding , pero se puede acheive el mismo efecto con tf.keras.layers.Dense . El embedding_column arriba son simplemente combinando linealmente vectores de incrustación de acuerdo con la categoría de peso. Aunque no es evidente a primera, es exactamente equivalente a la representación de sus entradas categóricas como un vector de peso escasa de tamaño (num_tokens) , y mutiplying ellos por un Dense núcleo de la forma (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)>

Ejemplo de entrenamiento completo

Para mostrar un flujo de trabajo de entrenamiento completo, primero prepare algunos datos con tres características de diferentes tipos:

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]}

Defina algunas constantes comunes para los flujos de trabajo TF1 y TF2:

vocab = ['small', 'medium', 'large']
one_hot_dims = 3
embedding_dims = 4
weight_mean = 2.0
weight_variance = 1.0

Con columnas de características

Las columnas de características deben pasarse como una lista al estimador en el momento de la creación y se llamarán implícitamente durante el entrenamiento.

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>

Las columnas de características también se utilizarán para transformar los datos de entrada al ejecutar la inferencia en el modelo.

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)}

Con capas de preprocesamiento de Keras

Las capas de preprocesamiento de Keras son más flexibles en cuanto a dónde se pueden llamar. Una capa puede ser aplicada directamente a tensores, que se utiliza dentro de un tf.data tubería de entrada, o integrado directamente en un modelo Keras entrenable.

En este ejemplo, se aplicará el procesamiento previo capas dentro de un tf.data tubería de entrada. Para ello, se puede definir una separada tf.keras.Model preprocesasen sus características de entrada. Este modelo no se puede entrenar, pero es una forma conveniente de agrupar capas de preprocesamiento.

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)

Ahora puede aplicar este modelo dentro de una llamada a tf.data.Dataset.map . Tenga en cuenta que la función pasa al map se convertirá automáticamente en un tf.function y advertencias habituales para escribir tf.function código se aplican (sin efectos secundarios).

# 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))

A continuación, se puede definir una separada Model que contiene las capas entrenables. Observe cómo las entradas a este modelo ahora reflejan los tipos y formas de características preprocesados.

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)

Ahora puede entrenar al training_model con 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>

Finalmente, en el momento de la inferencia, puede ser útil combinar estas etapas separadas en un solo modelo que maneja entradas de características sin procesar.

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)

Este modelo compuesto puede ser guardado como un SavedModel para su uso posterior.

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)

Tabla de equivalencias de columnas de funciones

Como referencia, aquí hay una correspondencia aproximada entre las columnas de características y las capas de preprocesamiento:

Columna de funciones Capa de Keras
feature_column.bucketized_column layers.Discretization
feature_column.categorical_column_with_hash_bucket layers.Hashing
feature_column.categorical_column_with_identity layers.CategoryEncoding
feature_column.categorical_column_with_vocabulary_file layers.StringLookup o layers.IntegerLookup
feature_column.categorical_column_with_vocabulary_list layers.StringLookup o layers.IntegerLookup
feature_column.crossed_column No se ha implementado.
feature_column.embedding_column layers.Embedding
feature_column.indicator_column output_mode='one_hot' o output_mode='multi_hot' *
feature_column.numeric_column layers.Normalization
feature_column.sequence_categorical_column_with_hash_bucket layers.Hashing
feature_column.sequence_categorical_column_with_identity layers.CategoryEncoding
feature_column.sequence_categorical_column_with_vocabulary_file layers.StringLookup , layers.IntegerLookup , o layer.TextVectorization
feature_column.sequence_categorical_column_with_vocabulary_list layers.StringLookup , layers.IntegerLookup , o layer.TextVectorization
feature_column.sequence_numeric_column layers.Normalization
feature_column.weighted_categorical_column layers.CategoryEncoding

* output_mode se puede pasar a layers.CategoryEncoding , layers.StringLookup , layers.IntegerLookup y layers.TextVectorization .

layers.TextVectorization puede manejar la entrada de texto de forma libre directamente (por ejemplo, frases enteras o párrafos). Este no es un reemplazo uno a uno para el manejo de secuencias categóricas en TF1, pero puede ofrecer un reemplazo conveniente para el preprocesamiento de texto ad-hoc.

Próximos pasos