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
参考文献: