【问题标题】:How to use multi-gpu in Keras with shared weights applications model如何在 Keras 中使用多 GPU 与共享权重应用程序模型
【发布时间】:2019-10-22 00:13:22
【问题描述】:

我想将多 GPU 中的 keras 与应用程序(例如 VGG16)一起使用。但是有一些错误。

我尝试使用单 GPU 是正确的。但是多GPU是错误的。 代码如下:

import keras
    with tf.device('/cpu:0'):
        input1 = keras.layers.Input(config.input_shape)
        input2 = keras.layers.Input(config.input_shape)
        sub_model = keras.applications.VGG16(include_top=False, weights=config.VGG_MODEL_PATH,
                                             input_shape=config.input_shape)
        output1 = sub_model(input1)
        output2 = sub_model(input1)
        model = keras.Model(inputs=[input1, input2], outputs=[output1, output2])
    parallel_model = keras.utils.multi_gpu_model(model, gpus=3)
    parallel_model.compile('sgd', loss=['mse', 'mse'])
    parallel_model.fit((np.random.random([10, 128, 128, 3]), np.random.random([10, 128, 128, 3])),
                       (np.random.random([10, 4, 4, 512]), np.random.random([10, 4, 4, 512])))

错误信息是

Traceback (most recent call last):
  File "/data00/home/liangdong.tony/PycharmProject/RetrievalCCWebVideo/AE/demo.py", line 145, in <module>
    parallel_model = keras.utils.multi_gpu_model(model, gpus=3)
  File "/data00/home/liangdong.tony/.local/lib/python2.7/site-packages/keras/utils/training_utils.py", line 177, in multi_gpu_model
    return Model(model.inputs, merged)
  File "/data00/home/liangdong.tony/.local/lib/python2.7/site-packages/keras/legacy/interfaces.py", line 87, in wrapper
    return func(*args, **kwargs)
  File "/data00/home/liangdong.tony/.local/lib/python2.7/site-packages/keras/engine/topology.py", line 1811, in __init__
    'Layer names: ', all_names)
RuntimeError: ('The name "vgg16" is used 2 times in the model. All layer names should be unique. Layer names: ', ['input_1', 'input_2', 'lambda_1', 'lambda_2', 'lambda_3', 'lambda_4', 'lambda_5', 'lambda_6', 'model_1', 'vgg16', 'vgg16'])

【问题讨论】:

  • 您必须在问题中包含完整的错误消息。
  • 对不起,我忘记了,已经更新了。你以前遇到过这个问题吗?

标签: python keras


【解决方案1】:

我发现有一个不明智的解决方案。 有解决方法代码:

import tensorflow as tf
from tensorflow.keras import backend as K


def slice_batch(x, n_gpus, part):
    sh = K.shape(x)
    L = sh[0] // n_gpus
    if part == n_gpus - 1:
        return x[part * L:]
    return x[part * L:(part + 1) * L]


def multi_gpu_wrapper(single_model, num_gpu):
    inputs = single_model.inputs
    towers = []
    splited_layer = tf.keras.layers.Lambda(lambda x: slice_batch(x, num_gpu, gpu_id))
    concate_layer = tf.keras.layers.Concatenate(axis=0)
    with tf.device('/cpu:0'):
        for gpu_id in range(num_gpu):
            cur_inputs = []
            for input in inputs:
                cur_inputs.append(
                    splited_layer(input)
                )
            towers.append(single_model(cur_inputs))
            print towers[-1]
    outputs = []
    num_output = len(towers[-1])
    with tf.device('/cpu:0'):
        for i in range(num_output):
            tmp_outputs = []
            for j in range(num_gpu):
                tmp_outputs.append(towers[j][i])
            outputs.append(concate_layer(tmp_outputs))
    multi_gpu_model = tf.keras.models.Model(inputs=inputs, outputs=outputs)
    return multi_gpu_model


if __name__ == '__main__':
    import config
    import os
    import numpy as np
    gpu_ids = "0,1,3"
    os.environ["CUDA_VISIBLE_DEVICES"] = gpu_ids
    with tf.device('/cpu:0'):
        input1 = tf.keras.layers.Input(config.input_shape)
        input2 = tf.keras.layers.Input(config.input_shape)
        sub_model = tf.keras.applications.VGG16(include_top=False, weights=config.VGG_MODEL_PATH,
                                                input_shape=config.input_shape)
        output1 = sub_model(input1)
        output2 = sub_model(input2)
        model = tf.keras.Model(inputs=[input1, input2], outputs=[output1, output2])
    multi_gpu_model = multi_gpu_wrapper(model, 3)
    multi_gpu_model.compile('sgd', loss=['mse', 'mse'])
    multi_gpu_model.fit([np.random.random([1000, 128, 128, 3]), np.random.random([1000, 128, 128, 3])],
                        [np.random.random([1000, 4, 4, 512]), np.random.random([1000, 4, 4, 512])], batch_size=128)

但是,我发现这个解决方案中 GPU 的使用率很低。

【讨论】:

    【解决方案2】:

    我只是在猜测,但它在您的错误日志中显示“名称“vgg16”在模型中使用了 2 次”。

    我猜如果你用

    创建 output1 和 output2
        output1 = sub_model(input1)
    
        output2 = sub_model(input1)
    

    并将其添加到您的模型中,您将创建 VGG16 模型的重复层名称。 也许您可以使用另一个输入 (input2)?

    您也可以尝试重命名模型:

    output1 = sub_model(input1)
    sub_model.name="VGG16_2"
    
    output2 = sub_model(input1) 
    

    如果你能提供更多代码,我可能会测试你的代码并尝试解决问题:)

    This 似乎也有类似的问题。

    希望这会有所帮助。

    【讨论】:

    • 我替换为 output2 = sub_model(input2),同样的错误。代码只是案例的演示,它使用了多输入。每个输入都由 VGG 16(共享权重)预处理。
    • 另一个猜测可能是你需要第二个 sub_model?但我现在真的只是在猜测:/ 我回家后会试试看的 :)
    • 好的,非常感谢!我想使用具有共享权重的模型。如果我定义第二个模型,我想他们可能不会相互分享。
    • 您可以在 output1 和 output2 之间重命名模型。我将在我的答案中更新代码。我保证最后一次猜测尝试;)
    • 伤心。它重写为: sub_model.name = 'vgg16_1' output1 = sub_model(input1) sub_model.name = 'vgg16_2' output2 = sub_model(input2) model = keras.Model(inputs=[input1, input2], outputs=[output1, output2 ]) 同样的错误。
    猜你喜欢
    • 2021-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-12
    • 2018-03-31
    • 1970-01-01
    • 2020-03-24
    • 1970-01-01
    相关资源
    最近更新 更多