拓展维度: tf.expand_dims()


tensorflow 上手不易,但是一旦上手就爱不释手了,也不知道为啥,做个笔记记录一些冷不丁想用就前列腺发炎的tf 函数吧



tf.expand_dims()

def expand_dims(input, axis=None, name=None, dim=None)
"""
input: 输入的tensor 或者 operation节点
axis: 要在输入的tensor的第几个维度增加1个维度
dim: 没有用的, 版本遗弃的东西
"""

这个函数其实就是给tensor增加维度的, 根据axis来确定在原本的tensor的哪个维度上增加1维

比如一个tensor的 shape 是[2, 3], 打印出来是这样:

array([[1., 1., 1.],
       [1., 1., 1.]])

若axis = 0, shape 从前面加1维, 就会变成[1,2,3]

array([[[1., 1., 1.],
        [1., 1., 1.]]])

若axis = -1, shape 从后面加1维[2,3,1]

array([[[1.],
        [1.],
        [1.]],

       [[1.],
        [1.],
        [1.]]])

如何看懂维度:

我这样来看维度的 ---- 数括号:

给定一个多维的向量, 确定一下它的各个维度上的维数shape:

>>> np.ones([1,2,3,4])
array([[[[1., 1., 1., 1.],
         [1., 1., 1., 1.],
         [1., 1., 1., 1.]],

        [[1., 1., 1., 1.],
         [1., 1., 1., 1.],
         [1., 1., 1., 1.]]]])

注意力放在这里array([[[[ 开始数有多少个中括号表示这个张量有多少维, 显然有4个维度, 对应维度的下标注意这里是0到3
然后从第一个中括号后面那个括号开始array([[[[ 往下找有多少个和它对齐的括号,发现只有它自己一个, 那么从左到右,我们说的高维到低维的第一个维度的维数是1, 然后再从这个中括号的后面一个中括号开始继续上面一样的操作,如下图

array([[这回说的就是这个括号了->[[1., 1., 1., 1.],
         					 [1., 1., 1., 1.],
         					 [1., 1., 1., 1.]],

        与它对齐的还有这个括号->[[1., 1., 1., 1.],
                             [1., 1., 1., 1.],
                             [1., 1., 1., 1.]]]])

说明从左到右第二个维度的维数为2
以此类推, 直到最后一个中括号这个中括号没有再包含任何中括号了, 那么开始数这个括号里有几个元素,就像array([[[数到这个中括号里已经没有子中括号在里面了那就数元素->[1., 1., 1., 1.], 显然有4个1, 那么最后一个维度的维数为4, 所以呢,上面的张量shape = (1,2,3,4)

给定一个多维向量的标签index, 确定是哪个元素或者说是哪个子张量

>>> a = np.random.randint(1,10,(1,3,3,4))
>>> a
array([[[[9, 4, 5, 6],
         [7, 1, 8, 5],
         [5, 3, 6, 9]],

        [[5, 8, 1, 6],
         [1, 8, 4, 4],
         [3, 1, 4, 4]],

        [[8, 2, 1, 2],
         [8, 9, 9, 9],
         [4, 1, 1, 5]]]])


比如看看 a[1,3,2,4] 是哪个元素, 这里数第一个中括号里面的第一个子中括号
然后再到再里面的第二个子中括号, 然后再到在里面发现没有子中括号了就找第一个元素 由此我们找到这个元素在这

>>> a = np.random.randint(1,10,(1,3,3,4))
>>> a
array([[[[9, 4, 5, 6],
         [7, 1, 8, 5],
         [5, 3, 6, 9]],

        [[5, 8, 1, 6],
         [1, 8, 4, 4],
         [3, 1, 4, 4]],

        [[8, 2, 1, 2],
         [8, 9, 9, 这里就是你要找的元素-->9],
         [4, 1, 1, 5]]]])

给定一个多维向量的, 看它axis =0, 1, 2, -1 时所影响的张量, 以及其切片slice

axis 和 shape 其实是一一对应的
比如

shape = (    1,    2,     3,     4     )
             |      |     |      |
axis  =      0,     1,    2,   3==-1
应的axis其实就是对应元素的下标

axis 其实就是对应第, 结合上面的找括号其实就是找 第 axis+2 个中括号有多少个
也等于第 axis+1 个中括号里面的平级中括号有多少个
来个栗子

>>> a = np.random.randint(1,10,(2,3,1))
>>> a
array([[[1],
        [9],
        [5]],

       [[5],
        [7],
        [1]]])

a[1] == a[1,:,:] 这是第0个axis, 那么找第1个括号里面次级的平级括号的第二个括号以及它的对应尾括号

		array([[[1],
		        [9],
		        [5]],
就是这个中括号-->[[5],
		        [7],
		        [1]]])

拿到的就是这玩意儿了

array([[5],
       [7],
       [1]])

a[:,:,2] axis=2 那么对应的就是第二个括号了, 找里面发现我的天没有第3(下标为2)个元素
所以其实这个不成立

>>> a[:,:,2]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: index 2 is out of bounds for axis 2 with size 1

如果有呢比如

array([[[2, 7],
        [9, 3],
        [9, 5]],

       [[1, 9],
        [2, 9],
        [5, 5]]])
看看a[:,:,1] 其实对应的就是axis = 2或者说-1, 一样的套路直到最后一个维度开始前面的中括号保留, 直到最后一个维数到元素位置本身了,抽第二个元素所以就是下面的array了
array([[7, 3, 5],
       [9, 9, 5]])
numpy里的机制是选取了一个维度只有1的话它就不keep demention了, shape = (2,3)
按规律来说是(2,3,1)只是切片有选取的意思就不保留选取后的维数为1的维度

现在来说在原来张量任意的维度位置上加一个维度,其实就是等于在这个维度上加中括号比如

>>> np.ones((2,3,2))
array([[[1., 1.],
        [1., 1.],
        [1., 1.]],

       [[1., 1.],
        [1., 1.],
        [1., 1.]]])

在axis = 0 上加维度, 那么就是最外面的中括号加一个中括号,如下

>>> np.ones((1,2,3,2))
array([[[[1., 1.],
         [1., 1.],
         [1., 1.]],

        [[1., 1.],
         [1., 1.],
         [1., 1.]]]])

在axis = 1 上加维度, 那么就是第二个中括号的每个中括号加中括号,如下

>>> np.ones((2,1,3,2))
array([[[[1., 1.],
         [1., 1.],
         [1., 1.]]],


       [[[1., 1.],
         [1., 1.],
         [1., 1.]]]])
其实和上面一样

在axis = -1 上加维度,那么就是每个元素加括号

>>> np.ones((2,3,2,1))
array([[[[1.],
         [1.]],

        [[1.],
         [1.]],

        [[1.],
         [1.]]],


       [[[1.],
         [1.]],

        [[1.],
         [1.]],

        [[1.],
         [1.]]]])

tf.expand_dims 使用例子

其实官方的例子是最好的:

  # 't' is a tensor of shape [2]
  tf.shape(tf.expand_dims(t, 0))  # [1, 2]
  tf.shape(tf.expand_dims(t, 1))  # [2, 1]
  tf.shape(tf.expand_dims(t, -1))  # [2, 1]
  # 't2' is a tensor of shape [2, 3, 5]
  tf.shape(tf.expand_dims(t2, 0))  # [1, 2, 3, 5]
  tf.shape(tf.expand_dims(t2, 2))  # [2, 3, 1, 5]
  tf.shape(tf.expand_dims(t2, 3))  # [2, 3, 5, 1]

它的源码

@tf_export("expand_dims")
def expand_dims(input, axis=None, name=None, dim=None):
  """
  Inserts a dimension of 1 into a tensor's shape.
  Given a tensor `input`, this operation inserts a dimension of 1 at the
  dimension index `axis` of `input`'s shape. The dimension index `axis` starts
  at zero; if you specify a negative number for `axis` it is counted backward
  from the end.
  This operation is useful if you want to add a batch dimension to a single
  element. For example, if you have a single image of shape `[height, width,
  channels]`, you can make it a batch of 1 image with `expand_dims(image, 0)`,
  which will make the shape `[1, height, width, channels]`.
  Other examples:

  # 't' is a tensor of shape [2]
  tf.shape(tf.expand_dims(t, 0))  # [1, 2]
  tf.shape(tf.expand_dims(t, 1))  # [2, 1]
  tf.shape(tf.expand_dims(t, -1))  # [2, 1]
  # 't2' is a tensor of shape [2, 3, 5]
  tf.shape(tf.expand_dims(t2, 0))  # [1, 2, 3, 5]
  tf.shape(tf.expand_dims(t2, 2))  # [2, 3, 1, 5]
  tf.shape(tf.expand_dims(t2, 3))  # [2, 3, 5, 1]

  This operation requires that:
  `-1-input.dims() <= dim <= input.dims()`
  This operation is related to `squeeze()`, which removes dimensions of
  size 1.
  Args:
    input: A `Tensor`.
    axis: 0-D (scalar). Specifies the dimension index at which to
      expand the shape of `input`. Must be in the range
      `[-rank(input) - 1, rank(input)]`.
    name: The name of the output `Tensor`.
    dim: 0-D (scalar). Equivalent to `axis`, to be deprecated.
  Returns:
    A `Tensor` with the same data as `input`, but its shape has an additional
    dimension of size 1 added.
  Raises:
    ValueError: if both `dim` and `axis` are specified.
  """
  
  # TODO(aselle): Remove argument dim
  if dim is not None:
    if axis is not None:
      raise ValueError("can't specify both 'dim' and 'axis'")
    axis = dim
  return gen_array_ops.expand_dims(input, axis, name)

硬要挖源码可以挖到c++, 哇水平有限这里只能放链接https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/ops/array_ops.cc

同样功能的函数在别的框架?

torch.unsqueeze(input, dim, out=None)

torch.unsqueeze(input, dim, out=None) → Tensor
在这里插入图片描述
Returns a new tensor with a dimension of size one inserted at the specified position.

The returned tensor shares the same underlying data with this tensor.

A dim value within the range [-input.dim() - 1, input.dim() + 1) can be used. Negative dimwill correspond to unsqueeze() applied at dim = dim + input.dim() + 1.

Example:

>>> x = torch.tensor([1, 2, 3, 4])
>>> torch.unsqueeze(x, 0)
tensor([[ 1,  2,  3,  4]])
>>> torch.unsqueeze(x, 1)
tensor([[ 1],
        [ 2],
        [ 3],
        [ 4]])

numpy.expand_dims(a, axis)

numpy.expand_dims(a, axis)

在这里插入图片描述

Expand the shape of an array.
Insert a new axis that will appear at the axis position in the expanded array shape.

Examples

>>> x = np.array([1,2])
>>> x.shape
(2,)
The following is equivalent to x[np.newaxis,:] or x[np.newaxis]:

>>> y = np.expand_dims(x, axis=0)
>>> y
array([[1, 2]])
>>> y.shape
(1, 2)
>>> y = np.expand_dims(x, axis=1)  # Equivalent to x[:,np.newaxis]
>>> y
array([[1],
       [2]])
>>> y.shape
(2, 1)
Note that some examples may use None instead of np.newaxis. These are the same objects:

>>> np.newaxis is None
True

参考文献:

https://www.cnblogs.com/qinduanyinghua/p/9333300.html

  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值