【问题标题】:How can I change the shape of a variable in TensorFlow?如何在 TensorFlow 中更改变量的形状?
【发布时间】:2016-02-12 19:00:53
【问题描述】:

TensorFlow tutorial 表示在创建时我们需要指定张量的形状。该形状自动成为张量的形状。它还说 TensorFlow 提供了重塑变量的高级机制。我怎样才能做到这一点?有代码示例吗?

【问题讨论】:

  • 行为已经改变,如果shape 被指定为参数,形状不会自动变成变量的形状。请参阅下面的答案

标签: matrix reshape tensorflow


【解决方案1】:

查看 TensorFlow 文档中的 shapes-and-shaping。它描述了可用的不同形状转换。

最常见的函数可能是tf.reshape,它类似于它的numpy等价物。只要元素的数量保持不变,它就允许您指定所需的任何形状。文档中提供了一些示例。

【讨论】:

  • 这不会重塑变量,而是返回一个具有变量值但新形状的张量。
【解决方案2】:

Documentation shows 整形方法。它们是:

  • 重塑
  • squeeze(从张量的形状中删除大小为 1 的维度)
  • expand_dims(添加尺寸为 1 的尺寸)

以及获取张量的shapesizerank 的一系列方法。最常用的可能是reshape,这是一个带有几个边缘情况(-1)的代码示例:

import tensorflow as tf

v1 = tf.Variable([
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12]
])
v2 = tf.reshape(v1, [2, 6])
v3 = tf.reshape(v1, [2, 2, -1])
v4 = tf.reshape(v1, [-1])
# v5 = tf.reshape(v1, [2, 4, -1]) will fail, because you can not find such an integer for -1
v6 = tf.reshape(v1, [1, 4, 1, 3, 1])
v6_shape = tf.shape(v6)
v6_squeezed = tf.squeeze(v6)
v6_squeezed_shape = tf.shape(v6_squeezed)

init = tf.initialize_all_variables()

sess = tf.Session()
sess.run(init)
a, b, c, d, e, f, g = sess.run([v2, v3, v4, v6, v6_shape, v6_squeezed, v6_squeezed_shape])
# print all variables to see what is there
print e # shape of v6
print g # shape of v6_squeezed

【讨论】:

    【解决方案3】:

    tf.Variable 类是创建变量的推荐方法,但它限制了您在创建变量后更改其形状的能力。

    如果您需要更改变量的形状,可以执行以下操作(例如,对于 32 位浮点张量):

    var = tf.Variable(tf.placeholder(tf.float32))
    # ...
    new_value = ...  # Tensor or numpy array.
    change_shape_op = tf.assign(var, new_value, validate_shape=False)
    # ...
    sess.run(change_shape_op)  # Changes the shape of `var` to new_value's shape.
    

    请注意,此功能不在记录的公共 API 中,因此可能会发生变化。如果您确实发现自己需要使用此功能,请告诉我们,我们可以研究一种方法来支持它向前发展。

    【讨论】:

    • 这种方法的问题是var.shape没有相应地更新。这在存储检查点时会持续存在,因此会阻止再次加载检查点,因为变量形状与权重形状不匹配。有没有办法强制var.shape 更新?我应该创建一个 GitHub 问题吗?
    • 我找到了这个帖子,讨论这个问题:github.com/tensorflow/tensorflow/issues/… 不过,我想知道是否有办法扩展现有网络的权重
    【解决方案4】:
    tf.Variable(tf.placeholder(tf.float32))
    

    在 tensorflow 1.2.1 中无效

    在 python 外壳中:

    import tensorflow as tf
    tf.Variable(tf.placeholder(tf.float32))
    

    你会得到:

    ValueError: initial_value must have a shape specified: Tensor("Placeholder:0", dtype=float32)
    

    更新:如果添加validate_shape=False,就不会报错了。

    tf.Variable(tf.placeholder(tf.float32), validate_shape=False)
    

    如果tf.py_func 符合您的要求:

    def init():
        return numpy.random.rand(2,3)
    a = tf.pyfun(init, [], tf.float32)
    

    您可以通过传递您自己的 init 函数来创建具有任何形状的变量。

    另一种方式:

    var = tf.get_varible('my-name', initializer=init, shape=(1,1))
    

    您可以传递 tf.constant 或任何返回 numpy 数组的 init 函数。提供的形状将不会被验证。输出形状是您的真实数据形状。

    【讨论】:

      【解决方案5】:

      tf.Variable:将shape 参数与None 一起使用

      1.14 中的feature was added 允许指定未知形状。

      如果shapeNone,则使用初始形状值。

      如果指定了shape,则将其用作形状并允许拥有None

      例子:

      var = tf.Variable(array, shape=(None, 10))
      

      这允许稍后分配具有与上述形状匹配的形状的值(例如,轴 0 中的任意形状)

      var.assign(new_value)

      【讨论】:

        【解决方案6】:

        正如 Mayou36 所说,您现在可以在变量第一次声明后更改它的形状。这是一个工作示例:

        v = tf.Variable([1], shape=tf.TensorShape(None), dtype=tf.int32) 
        tf.print(v)
        v.assign([1, 1, 1])
        tf.print(v)
        

        这个输出:

        [1]
        [1 1 1]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-07-19
          • 2018-11-06
          • 1970-01-01
          • 2017-02-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-10-22
          相关资源
          最近更新 更多