Tensorflow 联合 | tff.learning.from_keras_model() 具有 DenseFeature 层和多个输入的模型
Tensorflow Federated | tff.learning.from_keras_model() with a model with DenseFeature layer and multiple inputs
我正在尝试联合具有多个输入的 keras 模型。
其中一些输入是分类输入,一些是数字输入,所以我有一些 DenseFeature 层来嵌入这些值。
问题是使用 tff.learning.from_keras_model()
期望 input_spec 一个只有 2 个元素 (x,y) 的字典,但我有多个输入,然后我必须在模型中进行区分才能执行使用 feature_columns 函数和 DenseFeature 层正确嵌入。
如果模型仅接受 'x' 作为输入而没有正确的列名称,我该如何处理单个特征列?
这是代码和错误:
def create_keras_model():
l = tf.keras.layers
# handling numerical columns
for header in numerical_column_names:
feature_columns.append(feature_column.numeric_column(header))
# handling the categorical feature
pickup = feature_column.categorical_column_with_vocabulary_list(
'pickup_location_id', [i for i in range(number_of_locations)])
#pickup_one_hot = feature_column.indicator_column(pickup)
#feature_columns.append(pickup_one_hot)
pickup_embedding = feature_column.embedding_column(pickup, dimension=64)
#feature_columns.append(pickup_embedding)
feature_inputs = {
'pickup_week_day_sin': tf.keras.Input((1,), name='pickup_week_day_sin'),
'pickup_week_day_cos': tf.keras.Input((1,), name='pickup_week_day_cos'),
'pickup_hour_sin': tf.keras.Input((1,), name='pickup_hour_sin'),
'pickup_hour_cos': tf.keras.Input((1,), name='pickup_hour_cos'),
'pickup_month_sin': tf.keras.Input((1,), name='pickup_month_sin'),
'pickup_month_cos': tf.keras.Input((1,), name='pickup_month_cos'),
}
numerical_features = l.DenseFeatures(feature_columns)(feature_inputs)#{'x': a}
location_input = {
'pickup_location_id': tf.keras.Input((1,), dtype=tf.dtypes.int32, name='pickup_location_id'),
}
categorical_features = l.DenseFeatures(pickup_embedding)(location_input)#{'x': a}
#i = l.Input(shape=(64+6,))
#embedded_lookup_feature = tf.feature_column.numeric_column('x', shape=(784))
conca = l.Concatenate()([categorical_features, numerical_features])
dense = l.Dense(128, activation='relu')(conca)
dense_1 = l.Dense(128, activation='relu')(dense)
dense_2 = layers.Dense(number_of_locations, kernel_initializer='zeros')(dense_1)
output = l.Softmax()(dense_2)
inputs = list(feature_inputs.values()) + list(location_input.values())
return tf.keras.Model(inputs=inputs, outputs=output)
input_spec = preprocessed_example_dataset.element_spec
def model_fn():
# We _must_ create a new model here, and _not_ capture it from an external
# scope. TFF will call this within different graph contexts.
keras_model = create_keras_model()
return tff.learning.from_keras_model(
keras_model,
input_spec=input_spec,
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=[tf.keras.metrics.SparseCategoricalAccuracy()]
)
调用时出错:
ValueError: The top-level structure in `dummy_batch` or `input_spec` must contain exactly two elements, as it must contain type information for both inputs to and predictions from the model.
preprocessed_example_dataset.element_spec:
OrderedDict([('pickup_location_id',
TensorSpec(shape=(None,), dtype=tf.int32, name=None)),
('pickup_hour_sin',
TensorSpec(shape=(None,), dtype=tf.float32, name=None)),
('pickup_hour_cos',
TensorSpec(shape=(None,), dtype=tf.float32, name=None)),
('pickup_week_day_sin',
TensorSpec(shape=(None,), dtype=tf.float32, name=None)),
('pickup_week_day_cos',
TensorSpec(shape=(None,), dtype=tf.float32, name=None)),
('pickup_month_sin',
TensorSpec(shape=(None,), dtype=tf.float32, name=None)),
('pickup_month_cos',
TensorSpec(shape=(None,), dtype=tf.float32, name=None)),
('y', TensorSpec(shape=(None,), dtype=tf.int32, name=None))])
我在 GitHub 上的联合学习存储库中找到了答案:
方法是使 orderedDict 的 'x' 值成为 orderedDict 本身,使用我们想要作为输入的列的名称作为键。
定义输入规范的地方:
input_spec = collections.OrderedDict(
x=collections.OrderedDict(
a=tf.TensorSpec(shape=[None, 1], dtype=tf.float32),
b=tf.TensorSpec(shape=[1, 1], dtype=tf.float32)),
y=tf.TensorSpec(shape=[None, 1], dtype=tf.float32))
model = model_examples.build_multiple_inputs_keras_model()
要在定义为的模型中使用:
def build_multiple_inputs_keras_model():
"""Builds a test model with two inputs."""
l = tf.keras.layers
a = l.Input((1,), name='a')
b = l.Input((1,), name='b')
# Each input has a single, independent dense layer, which are combined into
# a final dense layer.
output = l.Dense(1)(
l.concatenate([
l.Dense(1)(a),
l.Dense(1)(b),
]))
return tf.keras.Model(inputs={'a': a, 'b': b}, outputs=[output])
我正在尝试联合具有多个输入的 keras 模型。 其中一些输入是分类输入,一些是数字输入,所以我有一些 DenseFeature 层来嵌入这些值。
问题是使用 tff.learning.from_keras_model()
期望 input_spec 一个只有 2 个元素 (x,y) 的字典,但我有多个输入,然后我必须在模型中进行区分才能执行使用 feature_columns 函数和 DenseFeature 层正确嵌入。
如果模型仅接受 'x' 作为输入而没有正确的列名称,我该如何处理单个特征列?
这是代码和错误:
def create_keras_model():
l = tf.keras.layers
# handling numerical columns
for header in numerical_column_names:
feature_columns.append(feature_column.numeric_column(header))
# handling the categorical feature
pickup = feature_column.categorical_column_with_vocabulary_list(
'pickup_location_id', [i for i in range(number_of_locations)])
#pickup_one_hot = feature_column.indicator_column(pickup)
#feature_columns.append(pickup_one_hot)
pickup_embedding = feature_column.embedding_column(pickup, dimension=64)
#feature_columns.append(pickup_embedding)
feature_inputs = {
'pickup_week_day_sin': tf.keras.Input((1,), name='pickup_week_day_sin'),
'pickup_week_day_cos': tf.keras.Input((1,), name='pickup_week_day_cos'),
'pickup_hour_sin': tf.keras.Input((1,), name='pickup_hour_sin'),
'pickup_hour_cos': tf.keras.Input((1,), name='pickup_hour_cos'),
'pickup_month_sin': tf.keras.Input((1,), name='pickup_month_sin'),
'pickup_month_cos': tf.keras.Input((1,), name='pickup_month_cos'),
}
numerical_features = l.DenseFeatures(feature_columns)(feature_inputs)#{'x': a}
location_input = {
'pickup_location_id': tf.keras.Input((1,), dtype=tf.dtypes.int32, name='pickup_location_id'),
}
categorical_features = l.DenseFeatures(pickup_embedding)(location_input)#{'x': a}
#i = l.Input(shape=(64+6,))
#embedded_lookup_feature = tf.feature_column.numeric_column('x', shape=(784))
conca = l.Concatenate()([categorical_features, numerical_features])
dense = l.Dense(128, activation='relu')(conca)
dense_1 = l.Dense(128, activation='relu')(dense)
dense_2 = layers.Dense(number_of_locations, kernel_initializer='zeros')(dense_1)
output = l.Softmax()(dense_2)
inputs = list(feature_inputs.values()) + list(location_input.values())
return tf.keras.Model(inputs=inputs, outputs=output)
input_spec = preprocessed_example_dataset.element_spec
def model_fn():
# We _must_ create a new model here, and _not_ capture it from an external
# scope. TFF will call this within different graph contexts.
keras_model = create_keras_model()
return tff.learning.from_keras_model(
keras_model,
input_spec=input_spec,
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=[tf.keras.metrics.SparseCategoricalAccuracy()]
)
调用时出错:
ValueError: The top-level structure in `dummy_batch` or `input_spec` must contain exactly two elements, as it must contain type information for both inputs to and predictions from the model.
preprocessed_example_dataset.element_spec:
OrderedDict([('pickup_location_id',
TensorSpec(shape=(None,), dtype=tf.int32, name=None)),
('pickup_hour_sin',
TensorSpec(shape=(None,), dtype=tf.float32, name=None)),
('pickup_hour_cos',
TensorSpec(shape=(None,), dtype=tf.float32, name=None)),
('pickup_week_day_sin',
TensorSpec(shape=(None,), dtype=tf.float32, name=None)),
('pickup_week_day_cos',
TensorSpec(shape=(None,), dtype=tf.float32, name=None)),
('pickup_month_sin',
TensorSpec(shape=(None,), dtype=tf.float32, name=None)),
('pickup_month_cos',
TensorSpec(shape=(None,), dtype=tf.float32, name=None)),
('y', TensorSpec(shape=(None,), dtype=tf.int32, name=None))])
我在 GitHub 上的联合学习存储库中找到了答案:
方法是使 orderedDict 的 'x' 值成为 orderedDict 本身,使用我们想要作为输入的列的名称作为键。
定义输入规范的地方:
input_spec = collections.OrderedDict(
x=collections.OrderedDict(
a=tf.TensorSpec(shape=[None, 1], dtype=tf.float32),
b=tf.TensorSpec(shape=[1, 1], dtype=tf.float32)),
y=tf.TensorSpec(shape=[None, 1], dtype=tf.float32))
model = model_examples.build_multiple_inputs_keras_model()
要在定义为的模型中使用:
def build_multiple_inputs_keras_model():
"""Builds a test model with two inputs."""
l = tf.keras.layers
a = l.Input((1,), name='a')
b = l.Input((1,), name='b')
# Each input has a single, independent dense layer, which are combined into
# a final dense layer.
output = l.Dense(1)(
l.concatenate([
l.Dense(1)(a),
l.Dense(1)(b),
]))
return tf.keras.Model(inputs={'a': a, 'b': b}, outputs=[output])