Tensorflow Keras 多输入模型

Posted

技术标签:

【中文标题】Tensorflow Keras 多输入模型【英文标题】:Tensorflow Keras multiple input model 【发布时间】:2021-12-26 01:00:20 【问题描述】:

我需要将此模型调整为两列文本输入(而不是一列)

tfhub_handle_encoder = \
    "https://tfhub.dev/tensorflow/small_bert/bert_en_uncased_L-4_H-512_A-8/1"
tfhub_handle_preprocess = \
"https://tfhub.dev/tensorflow/bert_en_uncased_preprocess/3"

def build_classifier_model():

text_input = tf.keras.layers.Input(
    shape=(), dtype=tf.string, name='text')

preprocessing_layer = hub.KerasLayer(
    tfhub_handle_preprocess, name='preprocessing')

encoder_inputs = preprocessing_layer(text_input)
encoder = hub.KerasLayer(
    tfhub_handle_encoder, trainable=True, name='BERT_encoder')

outputs = encoder(encoder_inputs)
net = outputs['pooled_output']
net = tf.keras.layers.Dropout(0.1)(net)
net = tf.keras.layers.Dense(
    6, activation='softmax', name='classifier')(net)
model = tf.keras.Model(text_input, net)

loss = tf.keras.losses.CategoricalCrossentropy(from_logits=False) # (from_logits=True)
metric = tf.metrics.CategoricalAccuracy('accuracy')
optimizer = Adam(
    learning_rate=5e-05, epsilon=1e-08, decay=0.01, clipnorm=1.0)
model.compile(
    optimizer=optimizer, loss=loss, metrics=metric)
model.summary()
return model

history = classifier_model.fit(
    x=X_train['f'].values,
    y=y_train_c,
    validation_data=(X_valid['f'].values, y_valid_c),
    epochs=15)

似乎这是教程中的模型:https://www.tensorflow.org/text/tutorials/classify_text_with_bert

我尝试修改两个输入层的代码,但由于连接后张量维度错误而出错:

def build_classifier_model():

input1 = tf.keras.layers.Input(
    shape=(), dtype=tf.string, name='text')

input2 = tf.keras.layers.Input(
    shape=(), dtype=tf.string, name='text1')
text_input = tf.keras.layers.concatenate([input1, input2], axis=-1)


preprocessing_layer = hub.KerasLayer(
    tfhub_handle_preprocess, name='preprocessing')

encoder_inputs = preprocessing_layer(text_input)
encoder = hub.KerasLayer(
    tfhub_handle_encoder, trainable=True, name='BERT_encoder')

outputs = encoder(encoder_inputs)
net = outputs['pooled_output']
net = tf.keras.layers.Dropout(0.1)(net)
net = tf.keras.layers.Dense(
    6, activation='softmax', name='classifier')(net)
model = tf.keras.Model([input1, input2], net)

loss = tf.keras.losses.CategoricalCrossentropy(from_logits=False) # (from_logits=True)
metric = tf.metrics.CategoricalAccuracy('accuracy')
optimizer = Adam(
    learning_rate=5e-05, epsilon=1e-08, decay=0.01, clipnorm=1.0)
model.compile(
    optimizer=optimizer, loss=loss, metrics=metric)
model.summary()
return model

错误:

InvalidArgumentError:  logits and labels must be broadcastable: logits_size=[64,6] labels_size=[32,6]
     [[node categorical_crossentropy/softmax_cross_entropy_with_logits (defined at tmp/ipykernel_39/1837193519.py:5) ]] [Op:__inference_train_function_271676]

如果使用与另一个维度连接,则模型不会编译

【问题讨论】:

警告消息表明标签问题而不是输入端问题。你检查过吗? 但是只有一个输入层,一切都很好。错误,因为我连接了两个输入层 这似乎是两个输入 (32 + 32) 样本的批量大小和一个输入的标签 - 32 个样本。您可以通过 colab 链接分享可重现的代码吗? 我做了colab notebook colab.research.google.com/drive/… 【参考方案1】:

奇怪的是,在你的模型中用tf.strings.join 替换你的Concatenation 层似乎有效:

def build_classifier_model():

  input1 = tf.keras.layers.Input(
      shape=(), dtype=tf.string, name='text')

  input2 = tf.keras.layers.Input(
      shape=(), dtype=tf.string, name='text1')
  text_input = tf.strings.join([input1, input2])

  preprocessing_layer = hub.KerasLayer(
      tfhub_handle_preprocess, name='preprocessing')

  encoder_inputs = preprocessing_layer(text_input)
  encoder = hub.KerasLayer(
      tfhub_handle_encoder, trainable=True, name='BERT_encoder')

  outputs = encoder(encoder_inputs)
  net = outputs['pooled_output']
  net = tf.keras.layers.Dropout(0.1)(net)
  output = tf.keras.layers.Dense(
      6, activation='softmax', name='classifier')(net)
  model = tf.keras.Model([input1, input2], output)

  loss = tf.keras.losses.CategoricalCrossentropy(from_logits=False) # (from_logits=True)
  metric = tf.metrics.CategoricalAccuracy('accuracy')
  optimizer = Adam(
      learning_rate=5e-05, epsilon=1e-08, decay=0.01, clipnorm=1.0)
  model.compile(
      optimizer=optimizer, loss=loss, metrics=metric)
  model.summary()
  return model
Epoch 1/5
 497/1094 [============>.................] - ETA: 2:14 - loss: 1.8664 - accuracy: 0.1641

您也可以考虑简单地做text_input = input1 + input2 ,因为Concatenation 层似乎搞乱了批处理维度。或者您可以将每个输入提供给您的encoder,然后将结果连接起来:

def build_classifier_model():

  input1 = tf.keras.layers.Input(
      shape=(), dtype=tf.string, name='text')

  input2 = tf.keras.layers.Input(
      shape=(), dtype=tf.string, name='text1')

  preprocessing_layer = hub.KerasLayer(
      tfhub_handle_preprocess, name='preprocessing')

  encoder_input1 = preprocessing_layer(input1)
  encoder_input2 = preprocessing_layer(input2)
  encoder = hub.KerasLayer(
      tfhub_handle_encoder, trainable=True, name='BERT_encoder')

  output1 = encoder(encoder_input1)
  output2 = encoder(encoder_input2)

  net = tf.keras.layers.Concatenate(axis=-1)([output1['pooled_output'], output2['pooled_output']])
  net = tf.keras.layers.Dropout(0.1)(net)
  output = tf.keras.layers.Dense(
      6, activation='softmax', name='classifier')(net)
  model = tf.keras.Model([input1, input2], output)

  loss = tf.keras.losses.CategoricalCrossentropy(from_logits=False) # (from_logits=True)
  metric = tf.metrics.CategoricalAccuracy('accuracy')
  optimizer = Adam(
      learning_rate=5e-05, epsilon=1e-08, decay=0.01, clipnorm=1.0)
  model.compile(
      optimizer=optimizer, loss=loss, metrics=metric)
  model.summary()
  return model

【讨论】:

我尝试将两个带有文本的 pandas 列合并为一个,但模型准确率下降 嗯,很有趣,因为 tf.strings.join 很简单地以元素方式连接字符串 这个型号应该没问题。因为我使用 catboost 模型,2 列得到 0.3,1 列得到 0.21。使用 keras bert 我有 0.27 一列和 0.21 两列。 谢谢,每个输入带有两个独立编码器的选项会更好 是的,我也这么认为。

以上是关于Tensorflow Keras 多输入模型的主要内容,如果未能解决你的问题,请参考以下文章

TensorFlow/Keras 多线程模型拟合

具有推理功能的 TensorFlow + Keras 多 GPU 模型

Keras + Tensorflow 和 Python 中的多处理

在 Tensorflow 中加载文本分类模型时出现 ValueError

当我在 Tensorflow 上使用 Keras API 连接两个模型时,模型的输入张量必须来自 `tf.layers.Input`

(已解决)Tensorflow 联合 | tff.learning.from_keras_model() 具有具有 DenseFeature 层和多个输入的模型