【问题标题】:How to restore the function defined in the graph?如何恢复图中定义的函数?
【发布时间】:2017-12-27 13:57:11
【问题描述】:

我在tensorflow中定义了一个函数如下:

def generator(keep_prob, z, out_channel_dim, alphag1, is_train=True):
    """
    Create the generator network
    :param z: Input z
    :param out_channel_dim: The number of channels in the output image
    :param is_train: Boolean if generator is being used for training
    :return: The tensor output of the generator
    """
    # TODO: Implement Function
    # when it is training reuse=False
    # when it is not training reuse=True
    alpha=alphag1
    with tf.variable_scope('generator',reuse=not is_train):
        layer = tf.layers.dense(z, 3*3*512,activation=None,\
                                 kernel_initializer=tf.contrib.layers.xavier_initializer(uniform=False))
        layer = tf.reshape(layer, [-1, 3,3,512])
        layer = tf.layers.batch_normalization(layer, training=is_train)
        layer = tf.maximum(layer*alpha, layer)
        #layer = layer+tf.random_normal(shape=tf.shape(layer), mean=0.0, stddev=0.0001, dtype=tf.float32)
        #layer = tf.nn.dropout(layer,keep_prob)

        layer = tf.layers.conv2d_transpose(layer, 256, 4, strides=2, padding='same',\
                                 kernel_initializer=tf.contrib.layers.xavier_initializer_conv2d(uniform=False))
        layer = tf.layers.batch_normalization(layer, training=is_train)
        layer = tf.maximum(layer*alpha, layer)
        #layer = layer+tf.random_normal(shape=tf.shape(layer), mean=0.0, stddev=0.00001, dtype=tf.float32)
        #layer = tf.nn.dropout(layer,keep_prob)

        layer = tf.layers.conv2d_transpose(layer, 128, 4, strides=2, padding='same',\
                                 kernel_initializer=tf.contrib.layers.xavier_initializer_conv2d(uniform=False))
        layer = tf.layers.batch_normalization(layer, training=is_train)
        layer = tf.maximum(layer*alpha, layer)
        #layer = layer+tf.random_normal(shape=tf.shape(layer), mean=0.0, stddev=0.000001, dtype=tf.float32)
        #layer = tf.nn.dropout(layer,keep_prob)

        layer = tf.layers.conv2d_transpose(layer, 64, 4, strides=2, padding='same',\
                                 kernel_initializer=tf.contrib.layers.xavier_initializer_conv2d(uniform=False))
        layer = tf.layers.batch_normalization(layer, training=is_train)
        layer = tf.maximum(layer*alpha, layer)
        #layer = layer+tf.random_normal(shape=tf.shape(layer), mean=0.0, stddev=0.0000001, dtype=tf.float32)
        #layer = tf.nn.dropout(layer,keep_prob)

        layer = tf.layers.conv2d_transpose(layer, out_channel_dim, 4, strides=2, padding='same',\
                                 kernel_initializer=tf.contrib.layers.xavier_initializer_conv2d(uniform=False))
        #layer = layer+tf.random_normal(shape=tf.shape(layer), mean=0.0, stddev=0.00000001, dtype=tf.float32)

        layer = tf.tanh(layer)
    return layer

这很复杂,以至于很难跟踪每一层中的每个变量。 我后来使用 tf.train.Saver() 和 saver.save 来保存训练后的所有内容。

现在我想恢复这个函数,这样我就可以用它来做进一步的操作,同时保持每一层的训练权重不变。

我在网上发现大多数函数,如 tf.get_default_graph().get_tensor_by_name 或其他一些函数,仅限于恢复变量的值,而不是这个函数。

例如这个函数生成器的输入 z(keep_prob, z, out_channel_dim, alphag1, is_train=True) 是来自另一个函数的张量。 我想恢复这个函数,这样我就可以使用两个新的张量 z1 和 z2,它们的形状与 z 相同。

layer1 = generator(keep_prob, z1, out_channel_dim, alphag1, is_train=False) 
layer2 = generator(keep_prob, z2, out_channel_dim, alphag1, is_train=False) 
layer = layer1 - layer2

我可以把这个新的张量层放到另一个函数中。 这里 layer1 和 layer2 使用保存权重的函数。

难点在于,当我使用函数生成器时,我必须使用使用 Saver() 存储的经过优化的权重来指定它。我发现很难用它的权重来指定这个函数。因为,1. 太多层无法跟踪 2. 我不知道如何为 tf.layers.conv2() 指定权重。

那么有谁知道如何解决这个问题?

【问题讨论】:

    标签: python tensorflow


    【解决方案1】:

    这是一个普遍的问题: 我将整个模型保存到文件中,需要将部分模型恢复为新模型的一部分。

    这里的name_map是一个dict:key是graph中的新名字,value是ckpt文件中的name。

    def get_restore_saver(self, name_map, restore_optimise_var=True):
    
        var_grp = {_.op.name:_ for _ in tf.global_variables()}
        varm = {}
        for main_name in var_grp:
            if main_name in name_map:
                varm[name_map[main_name]] = var_grp[main_name]
            elif restore_optimise_var: # I use adam to optimise
                var_arr = main_name.split('/')
                tail = var_arr[-1]
                _ = '/'.join(var_arr[: -1])
                if tail in ['Adam', 'Adam_1', 'ExponentialMovingAverage'] and _ in name_map:
                    varm[name_map[_] + "/" + tail] = var_grp[main_name]
    
        return tf.train.Saver(varm)
    

    【讨论】:

      【解决方案2】:

      为什么需要恢复功能,这意味着什么?如果需要使用模型,则必须还原对应的图。您的函数所做的是定义图形的节点。您可以使用您的函数再次构建或重建该图表,然后使用 Saver() 加载存储在某处的权重,或者您可以从 protobuf 文件中恢复图表。

      为了重建图形,请尝试在某处调用您的函数 output_layer=generator(keep_prob, z, out_channel_dim, alphag1, is_train=True),然后像往常一样使用 Saver 类来恢复权重。您的函数不计算,它定义了图形的一部分或全部。所有计算都由图执行。

      在最后一种情况下,您会发现以下thread 很有用。通常,您需要知道输入和输出层的名称。可以通过the code获取:

      [n.name for n in tf.get_default_graph().as_graph_def().node]
      

      【讨论】:

      • 我可以恢复图形和权重,但是我需要使用这个功能来做操作。恢复图表只会给我会话,恢复权重只会给我值。当然,原则上,我可以重建我想使用的这个功能。但是为什么我不能简单地恢复这个功能呢?或者,如何用名字不清楚的权重准确地重建这个函数?
      • 为了重建,尝试在某个地方调用它output_layer=generator(keep_prob, z, out_channel_dim, alphag1, is_train=True),然后像往常一样使用'Saver()'类来恢复权重
      • 你打算如何重用你的函数?函数不计算,它定义了图形的一部分或全部。所有的计算都由图来执行
      • 假设我有 outlayer1=generator(keep_prob, z, out_channel_dim, alphag1, is_train=False)
      • 我将为 z 和 z_new 提供不同的值
      【解决方案3】:

      经过长时间的搜索,似乎以下是一个解决方案。

      提前定义好所有变量,即layer1 = generator(keep_prob, z1,

      out_channel_dim, alphag1, is_train=False) 
      layer2 = generator(keep_prob, z2, out_channel_dim, alphag1, is_train=False) 
      layer = layer1 - layer2.
      

      现在您可以使用 tf.get_collection 来查找运算符。

      似乎tensorflow不会给你预定义的功能。它只保留图形和值,而不是函数的形式。需要在图中设置未来所需的所有内容,或者应该跟踪每个权重,即使权重太多。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-10-06
        • 2021-02-24
        • 1970-01-01
        • 2021-05-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多