Di chuyển feature_columns sang các Lớp tiền xử lý Keras của TF2

Xem trên TensorFlow.org Chạy trong Google Colab Xem nguồn trên GitHub Tải xuống sổ ghi chép

Đào tạo một mô hình thường sẽ đi kèm với một số tiền xử lý tính năng, đặc biệt là khi xử lý dữ liệu có cấu trúc. Khi đào tạo tf.estimator.Estimator trong TF1, việc xử lý trước tính năng này thường được thực hiện với API tf.feature_column . Trong TF2, quá trình tiền xử lý này có thể được thực hiện trực tiếp với các lớp Keras, được gọi là các lớp tiền xử lý .

Trong hướng dẫn di chuyển này, bạn sẽ thực hiện một số chuyển đổi tính năng phổ biến bằng cách sử dụng cả cột tính năng và lớp tiền xử lý, tiếp theo là đào tạo một mô hình hoàn chỉnh với cả hai API.

Trước tiên, hãy bắt đầu với một vài lần nhập khẩu cần thiết,

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

và thêm một tiện ích để gọi một cột tính năng để trình diễ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)

Xử lý đầu vào

Để sử dụng các cột tính năng với một công cụ ước tính, đầu vào của mô hình luôn được mong đợi là một từ điển của các tenxơ:

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

Mỗi cột tính năng cần được tạo với một khóa để lập chỉ mục vào dữ liệu nguồn. Đầu ra của tất cả các cột tính năng được ghép và sử dụng bởi mô hình ước lượng.

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

Trong Keras, đầu vào mô hình linh hoạt hơn nhiều. tf.keras.Model có thể xử lý một đầu vào tensor duy nhất, danh sách các tính năng tensor hoặc từ điển các tính năng tensor. Bạn có thể xử lý đầu vào từ điển bằng cách chuyển từ điển tf.keras.Input khi tạo mô hình. Các đầu vào sẽ không được nối tự động, điều này cho phép chúng được sử dụng theo những cách linh hoạt hơn nhiều. Chúng có thể được nối với 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 số nguyên mã hóa một lần

Một phép biến đổi tính năng phổ biến là các đầu vào số nguyên mã hóa một nóng của một dải ô đã biết. Đây là một ví dụ sử dụng các cột tính năng:

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

Sử dụng các lớp tiền xử lý của Keras, các cột này có thể được thay thế bằng một lớp tf.keras.layers.CategoryEncoding duy nhất với output_mode được đặt thành '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)>

Chuẩn hóa các tính năng số

Khi xử lý các đối tượng dấu chấm động, liên tục với các cột đối tượng, bạn cần sử dụng tf.feature_column.numeric_column . Trong trường hợp đầu vào đã được chuẩn hóa, việc chuyển đổi này thành Keras là điều không cần thiết. Bạn chỉ cần sử dụng tf.keras.Input trực tiếp vào mô hình của mình, như được hiển thị ở trên.

Một numeric_column cũng có thể được sử dụng để chuẩn hoá đầu vào:

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

Ngược lại, với Keras, quá trình chuẩn hóa này có thể được thực hiện với 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)>

Các tính năng mã hóa số một và mã hóa một cách đấu giá

Một phép biến đổi phổ biến khác của các đầu vào liên tục, dấu phẩy động là buckeised sau đó thành các số nguyên trong một phạm vi cố định.

Trong các cột tính năng, điều này có thể đạt được với 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)>

Trong Keras, điều này có thể được thay thế bằng 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)>

Dữ liệu chuỗi mã hóa một lần có từ vựng

Xử lý các tính năng chuỗi thường yêu cầu tra cứu từ vựng để dịch các chuỗi thành chỉ số. Dưới đây là một ví dụ sử dụng các cột tính năng để tra cứu chuỗi và sau đó mã hóa một lần các chỉ số:

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

Sử dụng các lớp tiền xử lý của Keras, hãy sử dụng lớp tf.keras.layers.StringLookup với output_mode được đặt thành '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)>

Nhúng dữ liệu chuỗi với từ vựng

Đối với các từ vựng lớn hơn, thường cần nhúng để có hiệu suất tốt. Dưới đây là một ví dụ nhúng một tính năng chuỗi bằng cách sử dụng các cột tính năng:

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

Sử dụng các lớp tiền xử lý của Keras, điều này có thể đạt được bằng cách kết hợp một lớp tf.keras.layers.StringLookup và một lớp tf.keras.layers.Embedding . Đầu ra mặc định cho StringLookup sẽ là các chỉ số nguyên có thể được đưa trực tiếp vào một nhúng.

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

Tổng hợp dữ liệu phân loại có trọng số

Trong một số trường hợp, bạn cần xử lý dữ liệu phân loại trong đó mỗi lần xuất hiện của một danh mục đi kèm với một trọng số liên quan. Trong các cột tính năng, điều này được xử lý bằng tf.feature_column.weighted_categorical_column . Khi được ghép nối với indicator_column , cột này có tác dụng tổng cộng các trọng số cho mỗi danh mục.

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

Trong Keras, điều này có thể được thực hiện bằng cách chuyển đầu vào count_weights tới tf.keras.layers.CategoryEncoding với 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)>

Nhúng dữ liệu phân loại có trọng số

Bạn có thể muốn nhúng các đầu vào phân loại có trọng số. Trong các cột tính năng, embedding_column chứa một đối số là combiner . Nếu bất kỳ mẫu nào chứa nhiều mục nhập cho một danh mục, chúng sẽ được kết hợp theo cài đặt đối số (theo mặc định '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)>

Trong Keras, không có tùy chọn combiner nào cho tf.keras.layers.Embedding , nhưng bạn có thể đạt được hiệu ứng tương tự với tf.keras.layers.Dense . embedding_column ở trên chỉ đơn giản là kết hợp tuyến tính các vectơ nhúng theo trọng lượng danh mục. Mặc dù ban đầu không rõ ràng, nhưng nó chính xác tương đương với việc biểu thị các đầu vào phân loại của bạn dưới dạng véc tơ trọng số thưa thớt có kích thước (num_tokens) và làm nhỏ chúng bằng một nhân Dense có hình dạng (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)>

Hoàn thành ví dụ đào tạo

Để hiển thị một quy trình đào tạo hoàn chỉnh, trước tiên hãy chuẩn bị một số dữ liệu với ba tính năng của các loại khác nhau:

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

Xác định một số hằng số chung cho cả hai dòng công việc TF1 và TF2:

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

Với các cột tính năng

Các cột tính năng phải được chuyển dưới dạng danh sách cho trình ước tính khi tạo và sẽ được gọi ngầm trong quá trình huấn luyện.

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>

Các cột tính năng cũng sẽ được sử dụng để biến đổi dữ liệu đầu vào khi chạy suy luận trên mô hình.

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

Với các lớp tiền xử lý của Keras

Các lớp tiền xử lý của Keras linh hoạt hơn ở nơi chúng có thể được gọi. Một lớp có thể được áp dụng trực tiếp vào tensor, được sử dụng bên trong đường dẫn đầu vào tf.data hoặc được xây dựng trực tiếp vào mô hình Keras có thể huấn luyện.

Trong ví dụ này, bạn sẽ áp dụng các lớp tiền xử lý bên trong đường dẫn đầu vào tf.data . Để làm điều này, bạn có thể xác định một tf.keras.Model riêng biệt để xử lý trước các tính năng đầu vào của bạn. Mô hình này không thể đào tạo, nhưng là một cách thuận tiện để nhóm các lớp tiền xử lý.

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)

Bây giờ bạn có thể áp dụng mô hình này bên trong một cuộc gọi tới tf.data.Dataset.map . Xin lưu ý rằng chức năng được chuyển đến map sẽ tự động được chuyển đổi thành chức năng tf.function . và các lưu ý thông thường khi viết mã tf.function . sẽ được áp dụng (không có tác dụng phụ).

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

Tiếp theo, bạn có thể xác định một Model riêng biệt chứa các lớp có thể đào tạo. Lưu ý cách các đầu vào cho mô hình này hiện phản ánh các loại và hình dạng tính năng được xử lý trước.

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)

Bây giờ bạn có thể đào training_model với 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>

Cuối cùng, tại thời điểm suy luận, có thể hữu ích nếu kết hợp các giai đoạn riêng biệt này thành một mô hình duy nhất xử lý các đầu vào tính năng thô.

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)

Mô hình đã soạn này có thể được lưu dưới dạng SavedModel để sử dụng sau này.

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)

Bảng tương đương cột tính năng

Để tham khảo, đây là sự tương ứng gần đúng giữa các cột tính năng và các lớp tiền xử lý:

Cột tính năng Lớp 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 hoặc layers.IntegerLookup
feature_column.categorical_column_with_vocabulary_list layers.StringLookup hoặc layers.IntegerLookup
feature_column.crossed_column Không được thực hiện.
feature_column.embedding_column layers.Embedding
feature_column.indicator_column output_mode='one_hot' hoặc 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 hoặc layer.TextVectorization
feature_column.sequence_categorical_column_with_vocabulary_list layers.StringLookup , layers.IntegerLookup hoặc layer.TextVectorization
feature_column.sequence_numeric_column layers.Normalization
feature_column.weighted_categorical_column layers.CategoryEncoding

* output_mode có thể được chuyển cho các layers.CategoryEncoding , các layers.StringLookup , các layers.IntegerLookuplayers.TextVectorization .

layers.TextVectorization có thể xử lý trực tiếp đầu vào văn bản dạng tự do (ví dụ: toàn bộ câu hoặc đoạn văn). Đây không phải là sự thay thế một-một cho xử lý trình tự phân loại trong TF1, nhưng có thể cung cấp một sự thay thế thuận lợi cho xử lý trước văn bản đặc biệt.

Bước tiếp theo