Keras:TPU 模型的所有操作必须具有恒定的形状

Posted

技术标签:

【中文标题】Keras:TPU 模型的所有操作必须具有恒定的形状【英文标题】:Keras: TPU models must have constant shapes for all operations 【发布时间】:2020-02-25 04:08:12 【问题描述】:

我正在使用预训练的 keras 模型,我想在 Google Colaboratory 的 TPU 上运行它,但我收到以下错误:

值错误: 层在非批量维度上具有可变形状。 TPU 型号必须 所有操作的形状都保持不变。

您可能必须为 RNN/TimeDistributed 层指定“input_length”。

层: 输入形状:[(None, 128, 768), (None, 1)] 输出形状:(无,无,768)

我正在与keras-xlnet 合作。据我了解,按照here 和here 的说明编译模型时,TPU 需要具有固定的批量大小。

模型从检查点加载:

from keras_xlnet import Tokenizer, load_trained_model_from_checkpoint, 
      ATTENTION_TYPE_BI

checkpoint_path = 'xlnet_cased_L-12_H-768_A-12'

tokenizer = Tokenizer(os.path.join(checkpoint_path, 'spiece.model'))
model = load_trained_model_from_checkpoint(
    config_path=os.path.join(checkpoint_path, 'xlnet_config.json'),
    checkpoint_path=os.path.join(checkpoint_path, 'xlnet_model.ckpt'),
    batch_size=BATCH_SIZE,
    memory_len=512,
    target_len=SEQ_LEN,
    in_train_phase=False,
    attention_type=ATTENTION_TYPE_BI,
    )
 model.summary()

然后编译模型(经过一些更改):

from keras_bert import AdamWarmup, calc_train_steps

decay_steps, warmup_steps = calc_train_steps(
    y_train.shape[0],
    batch_size=BATCH_SIZE,
    epochs=EPOCHS,
    )


model.compile(
    AdamWarmup(decay_steps=decay_steps, warmup_steps=warmup_steps, lr=LR),
    loss='binary_crossentropy',
    )

然后,模型被加载到 TPU,出现错误:

tpu_address = 'grpc://' + os.environ['COLAB_TPU_ADDR']
    strategy = tf.contrib.tpu.TPUDistributionStrategy(
    tf.contrib.cluster_resolver.TPUClusterResolver(tpu=tpu_address)
    )

with tf.keras.utils.custom_object_scope(get_custom_objects()):
    tpu_model = tf.contrib.tpu.keras_to_tpu_model(model, strategy=strategy)

有没有办法可以在编译时修复批量大小以消除上述错误?还是问题完全不同?

【问题讨论】:

请注意,在 TPU 上运行可能很难解决所有各种错误,主要是 TensorFlow 自己过时的模块;即使你解决了这个问题,很可能还会有另一个问题。此外,功能主要限于核心 TF 模块(而不是例如自定义优化器)。最后,TPU 的速度非常快,但除非你的 input data pipeline 非常高效,否则你不会看到太大的收益;数据加载时间很容易成为瓶颈。 感谢您的评论。我认为我的输入管道等运行良好,因为它主要与我在keras-bert 中使用的设置相同。 GPU 在我的训练集(使用 BERT)上要慢很多,所以在整个数据集上运行它没有意义。 还好,TPU应该值得调试 恐怕你需要自己重写模型,固定形状并复制权重。但是像在这个问题中添加model.summary() 的信息(包括子模型,如果有的话)肯定会有助于检测更明显的东西。 模型摘要已找到here,因为它太大,无法在此处有用地上传。 【参考方案1】:

我同意 cmets - 要使其正常工作,您需要将各种可变输出形状(例如无、无、768)调整为固定大小(第一批尺寸除外)。也许你可以用简单的填充来做到这一点。如果您可以遍历保存的模型层并将权重加载到您使用填充尺寸编写的新模型中,它甚至可以工作。我想说这比考虑 TPU 就绪版本更麻烦。

我建议从 Keras 中移除这个模型。官方的 TensorFlow XLNet 实现无需修改即可与 TPU 一起使用。它还带有预训练的检查点。 https://github.com/zihangdai/xlnet

它使用标准的 TPUEstimator 类将模型函数发送给 TPU 工作器,因此您无需搞砸tf.contrib.tpu.keras_to_tpu_model

存储库中给出的示例可以在 colab 中运行,其中 $TPU_NAME$COLAB_TPU_ADDR 并且您将预训练的检查点和 imdb 数据上传到 colab 可以访问的存储桶。

python run_classifier.py \
  --use_tpu=True \
  --tpu=$TPU_NAME \
  --do_train=True \
  --do_eval=True \
  --eval_all_ckpt=True \
  --task_name=imdb \
  --data_dir=$IMDB_DIR \
  --output_dir=$GS_ROOT/proc_data/imdb \
  --model_dir=$GS_ROOT/exp/imdb \
  --uncased=False \
  --spiece_model_file=$LARGE_DIR/spiece.model \
  --model_config_path=$GS_ROOT/$LARGE_DIR/model_config.json \
  --init_checkpoint=$GS_ROOT/$LARGE_DIR/xlnet_model.ckpt \
  --max_seq_length=512 \
  --train_batch_size=32 \
  --eval_batch_size=8 \
  --num_hosts=1 \
  --num_core_per_host=8 \
  --learning_rate=2e-5 \
  --train_steps=4000 \
  --warmup_steps=500 \
  --save_steps=500 \
  --iterations=500

【讨论】:

以上是关于Keras:TPU 模型的所有操作必须具有恒定的形状的主要内容,如果未能解决你的问题,请参考以下文章

使用大数据集在 Google Colab TPU 上训练 seq2seq 模型 - Keras

使用 TPU 运行时在 Google Colab 上训练 Keras 模型时出错

无法将 tf.keras 模型正确转换为珊瑚 TPU 的量化格式

kaggle竞赛 使用TPU对104种花朵进行分类 第二十一次尝试 99.9%准确率 中文注释深度学习TPU+Keras+Tensorflow+EfficientNetB7

在谷歌 colab 中使用带有 TPU 的 Keras 调谐器搜索方法时如何解决“从空列表中弹出”错误?

为啥keras模型编译后预测速度变慢?