【问题标题】:Extremely slow model load with keraskeras 的模型加载速度极慢
【发布时间】:2018-05-07 09:55:33
【问题描述】:

我有一组 Keras 模型 (30),我使用以下方法训练和保存:

 model.save('model{0}.h5'.format(n_model))

当我尝试使用load_model 加载它们时,每个模型所需的时间都非常大且递增。加载完成如下:

models = {}
for i in range(30):
    start = time.time()
    models[i] = load_model('model{0}.h5'.format(ix)) 
    end = time.time()
    print "Model {0}: seconds {1}".format(ix, end - start)

输出是:

...
Model 9: seconds 7.38966012001
Model 10: seconds 9.99283003807
Model 11: seconds 9.7262301445
Model 12: seconds 9.17000102997
Model 13: seconds 10.1657290459
Model 14: seconds 12.5914049149
Model 15: seconds 11.652477026
Model 16: seconds 12.0126030445
Model 17: seconds 14.3402299881
Model 18: seconds 14.3761711121
...

每个模型都非常简单:2 个隐藏层,每个隐藏层 10 个神经元(大小约为 50Kb)。为什么加载这么多,为什么时间增加?我是否遗漏了什么(例如模型的关闭功能?)

解决方案

我发现要加快模型的加载速度,最好将网络结构和权重存储到两个不同的文件中: 保存部分:

model.save_weights('model.h5')
model_json = model.to_json()
with open('model.json', "w") as json_file:
    json_file.write(model_json)
json_file.close()

加载部分:

from keras.models import model_from_json
json_file = open("model.json", 'r')
loaded_model_json = json_file.read()
json_file.close()
model = model_from_json(loaded_model_json)
model.load_weights("model.h5")

【问题讨论】:

  • 是theano吗?我对 theano 也有类似的问题...
  • 不,是 TensorFlow,
  • 你解决了吗?随着每个加载模型的时间增加,我遇到了完全相同的问题
  • 是的,我更新了答案
  • 如果使用with,则无需关闭文件;您可以从保存部分中删除json_file.close()

标签: python performance load keras


【解决方案1】:

我通过在每次加载之前清除 keras 会话来解决问题

from keras import backend as K
for i in range(...):
  K.clear_session()
  model = load_model(...)

【讨论】:

  • 非常感谢您。我有一个使用 1000 个模型进行预测的预测设置,这节省了我的培根。
  • 我试过这个,它似乎破坏了我在循环中早些时候加载的模型。不知何故,所有模型的输入都应该符合我加载的最后一个模型的形状。 (哦,我看到@Wentai Chen 上面提到过。)
  • @EricMcLachlan 嘿,你能解释一下如何解决多个模型损坏的问题吗?我面临同样的问题。我没有看到任何名叫文泰的人发表任何评论。我得到 InvalidArgumentError: Tensor dense_3/Sigmoid:0, specified in either feed_devices or fetch_devices was not found in the Graph error
  • @SahilShah:我最终恢复了对 clear_session 的使用,因为它似乎清除了所有以前加载的模型。因此,例如,我有模型 0..9,但所有 10 个模型都有模型 [9] 的实现。这就是当时的情况。
  • 正如其他人所提到的,这会大大加快速度,但会破坏所有模型。因此,这不是一个解决方案。我们只需要忍受极其缓慢的加载。
【解决方案2】:

我尝试使用K.clear_session(),它每次都会增加加载时间。
但是,由于以下错误,我以这种方式加载的模型无法使用model.predict 功能:
ValueError: Tensor Tensor("Sigmoid_2:0", shape=(?, 17), dtype=float32) is not an element of this graph.
Github #2397 对此提供了详细的讨论。目前最好的解决方案是在加载模型后立即预测数据,而不是同时加载几十个模型。每次预测后可以使用K.clear_session()释放GPU,这样下次加载不会花费更多时间。

【讨论】:

  • 我试过 clear_session() 但我得到“无法破坏 cudnn 句柄:CUDNN_STATUS_BAD_PARAM”
【解决方案3】:

我是这样做的

from keras.models import Sequential
from keras_contrib.losses import import crf_loss
from keras_contrib.metrics import crf_viterbi_accuracy

# To save model
model.save('my_model_01.hdf5')

# To load the model
custom_objects={'CRF': CRF,'crf_loss':  crf_loss,'crf_viterbi_accuracy':crf_viterbi_accuracy}

# To load a persisted model that uses the CRF layer 
model1 = load_model("/home/abc/my_model_01.hdf5", custom_objects = custom_objects)

【讨论】:

【解决方案4】:

我也有类似的问题。在训练期间,我将验证损失最低的模型保存到 xyz.h5 之类的文件中。训练完成后,我加载保存的模型而不使用K.clear_session(),因此加载需要一分钟多的时间。使用 K.clear_session() 大约需要 39 秒才能加载。 xyz.h5 文件大小约为 39 MB。似乎连 39 秒都太长了。

无论如何,我决定通过编写一个小的回调来“绕过”延迟,该回调可以保存模型权重以实现最低的验证损失。然后我将这些权重加载到模型中进行预测。只需在训练时将回调包含在回调列表中即可。即callbacks=[save_best_weights(), etc, etc]。然后在训练完成后设置模型权重:

model.set_weights(save_best_weights.best_weights)

如果您想根据另一个指标保存权重,只需更改行:

current_loss=logs.get(whatever metric you choose)

class save_best_weights(tf.keras.callbacks.Callback):
best_weights=model.get_weights()    
def __init__(self):
    super(save_best_weights, self).__init__()
    self.best = np.Inf
def on_epoch_end(self, epoch, logs=None):
    current_loss = logs.get('val_loss')
    accuracy=logs.get('val_accuracy')* 100
    if np.less(current_loss, self.best):
        self.best = current_loss            
        save_best_weights.best_weights=model.get_weights()
        print('\nSaving weights validation loss= {0:6.4f}  validation accuracy= {1:6.3f} %\n'.format(current_loss, accuracy))     

【讨论】:

    【解决方案5】:

    虽然回答这个问题可能为时已晚。我认为这可以解决问题。

    model = tf.keras.models.load_model(model_path, compile=False)

    加载模型时添加compile=False

    【讨论】:

      【解决方案6】:

      虽然来晚了,但在 Google 的 Facenet (89MB) 上,我得到了一些有趣的结果,如下所示,

      我尝试了上述答案中提到的所有选项,但发现 Tensorflow 中的 Keras 比 vanilla Keras 稍快,并且在更强的 CPU 上结果可能会更好。

      我的笔记本电脑很旧,配置为第四代 i5 (4120U)、8GB 1600MHz DDR3 和普通 SATA SSD,我使用的是 Tensorflow 1.15.2 CPU 版本。

      # Old method -- 16 to 17 seconds
      from keras import backend as K
      K.clear_session()
      model = load_model('models/facenet_v1.h5', compile=False)
      #------------------------------------------------------
      
      # Method 1 -- 16 to 18 seconds 
      from keras import backend as K
      K.clear_session()
      with open('models/facenet_v1.json', 'r') as j:
          json_model = j.read()
      
      model = model_from_json(json_model)
      model.load_weights('models/facenet_v1_weights.h5')
      #------------------------------------------------------
      
      # Method 2 -- 9 to 11 seconds -> Best
      tf.keras.backend.clear_session()
      model = tf.keras.models.load_model('models/facenet_v1.h5', compile=False)
      

      除此之外,如果你有 GPU,你会得到更好的结果。

      【讨论】:

        猜你喜欢
        • 2020-02-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多