**
深度学习自学记录(1)——Tensor的维度理解(参数axis)
**
本人小白自学深度学习时,涉及到矩阵和数组的计算常常出现参数axis,一直搞不懂矩阵和数组中axis参数的含义,参考了大佬的博客以及这篇博客在这里记录一下自己的理解,毕竟好记性不如烂笔头。如果有错误的地方,希望大家指正,一起进步。
什么是张量(tensor)
首先了解一下什么是张量,它可以看作是向量和矩阵的自然推广。0维张量表示的是一个数(点),1维张量表示的是一个向量(线),2维张量是一个矩阵(面),3维张量则可以看成有2阶张量堆叠构成,可称之为一个立方体,图像处理中一张图片的tensor(224,224,3)就是3维张量。而多个三维张量堆叠在一起就是四维张量,以此类推。张量的维度又称阶数、轴,英文即axis。
如下代码中a为一维张量,b为二维张量,c为三维张量,d为四维张量
import tensorflow as tf
sess = tf.Session()
a = tf.ones(2)
b = tf.ones([2,2])
c = tf.ones([2,2,2])
d = tf.ones([2,2,2,2])
print( sess.run(a))
print( "#########")
print( sess.run(b))
print( "#########")
print( sess.run(c))
print( "#########")
print( sess.run(d))
[1. 1.]
#########
[[1. 1.]
[1. 1.]]
#########
[[[1. 1.]
[1. 1.]]
[[1. 1.]
[1. 1.]]]
#########
[[[[1. 1.]
[1. 1.]]
[[1. 1.]
[1. 1.]]]
[[[1. 1.]
[1. 1.]]
[[1. 1.]
[1. 1.]]]]
理解了什么是张量和不同维度的张量的形式,下面来看一下具体代码中参数axis的作用。
代码中的参数axis含义
设定axis=i,则表示计算沿着第i个下表变化的方向进行分组计算操作。也即是将矩阵进行分组,然后再操作
第一次看到这么一句话的时候,我依旧是一脸懵逼。。。。慢慢来
首先我们要了解张量的下标标注,其实和矩阵的下标标注一样的,三维张量只不过又加了一个维度。上面张量b、c、d的下标如下所示,b的下表再熟悉不过,为行和列;把矩阵看作一个模块,c的第一个下标i表示第i个模块;同理,把三维张量看作一个模块,d的第一个下标i表示位于哪一个模块。
b = [[A00,A01,A02]
[A10,A11,A12]]
c = [[[A000,A001,A002]
[A010,A011,A012]]
[[A100,A101,A102]
[A110,A111,A112]]]
d = [[[[A0000,A0001,A0002]
[A0010,A0011,A0012]]
[[A0100,A0101,A0102]
[A0110,A0111,A0112]]]
[[[A1000,A1001,A1002]
[A1010,A1011,A1012]]
[[A1100,A1101,A1102]
[A1110,A1111,A1112]]]]
如果参数axis=0,则表示计算是沿着最左边下标(第0个下标)的变化方向进行操作(也可以说按照张量的第0维计算),将除了第0个下标外,其他几个下标都相同的部分分成一组,然后再进行操作。以三维张量c为例,计算是用A000,A100和A001,A01等六组数据计算。
如果参数axis=1,则表示计算是沿着第1个下标(左边第二个)的变化方向进行操作(也可以说按照张量的第1维计算),以c为例,计算是用A000,A010和A001,A011等六组数据计算。
如果参数axis= -1,则表示按照倒数第一个坐标(最右边)的变化方向操作(也可以说按照张量的最后一维计算)。
原始矩阵的shape=[3,4,5],取axis=0再进行操作后,得到的矩阵shape=[4,5]。同样的,取axis=1再进行操作后,得到的矩阵shape=[3,5]。取axis=-1(axis=2)再操作后,shape=[3,4]。掌握这一点,能有利于你在神经网络中的变换或是数据操作中明确矩阵变换前后的形状,从而加快对模型的理解。
链接
具体例子
我们使用tf.reduce_mean函数来验证我们的理解,它是一个求均值函数。每计算一次打印张量的shape观察他们的变化。
sess = tf.Session()
x = tf.constant([[[1.,2.,3.], [4., 5.,6]], [[2., 3.,4], [5., 6.,7]], [[3., 4.,5], [6., 5.,4]]])
print(x.shape)
print(sess.run(tf.reduce_mean(x)))
print(tf.reduce_mean(x).shape)
print('##############')
print(sess.run(tf.reduce_mean(x, 0)))
print(tf.reduce_mean(x,0).shape)
print('##############')
print(sess.run(tf.reduce_mean(x, 1)))
print(tf.reduce_mean(x,1).shape)
print('##############')
print(sess.run(tf.reduce_mean(x, -2)))
print(tf.reduce_mean(x,-2).shape)
print('##############')
print(sess.run(tf.reduce_mean(x, -1)))
print(tf.reduce_mean(x,-1).shape)
参数axis=None时,是对x中所有的数据求均值,返回的是一个0维张量:
(3, 2, 3)
4.0
()
参数axis=0时,是对x取第0维(沿着第0个下标的变化方向)再进行操作后,返回的张量shape=[2,3],将第0维对应数据取出来,分组后进行均值操作,过程与结果如下:
[[(1+2+3)/3 (2+3+4)/3 (3+4+5)/3 ]
[(4+5+6)/3 (5+6+5)/3 (6+4+4)/3 ]]
##############
[[2. 3. 4. ]
[5. 5.3333335 4.6666665]]
(2, 3)
参数axis=1时,是对x取第1维(沿着第1个下标的变化方向)再进行操作后,返回的张量shape=[3,3],将第1维对应数据取出来,分组后进行均值操作,过程与结果如下:
[[(1+4)/2 (2+5)/2 (3+6)/2 ]
[(2+5)/2 (3+6)/2 (4+4)/2 ]
[(3+6)/2 (4+5)/2 (5+4)/2]]
##############
[[2.5 3.5 4.5]
[3.5 4.5 4. ]
[4.5 4.5 4.5]]
(3, 3)
参数axis=-2时,是对x取倒数第2维,对于x来说也就是第1维(沿着第1个下标的变化方向)再进行操作后,返回的张量shape=[3,3],将第1维对应数据取出来,分组后进行均值操作,过程与结果如下,结果与axis=1时一致。
##############
[[2.5 3.5 4.5]
[3.5 4.5 4. ]
[4.5 4.5 4.5]]
(3, 3)
参数axis=-1时,是对x取倒数第1维,对于x来说也就是第2维(沿着第1个下标的变化方向)再进行操作后,返回的张量shape=[3,2],将第2维对应数据取出来,直接付结果:
##############
[[2. 5.]
[3. 5.]
[4. 5.]]
(3, 2)
总结
(1)axis=i表示在操作在张量第i个维度上进行(也即是第i个下标变化的方向),对张量按维度方向分组在计算。
(2)最后返回的shape:始矩阵的shape=[3,2,3],取axis=0再进行操作后,得到的矩阵shape=[2,3]。同样的,取axis=1再进行操作后,得到的矩阵shape=[3,3]。取axis= -1(axis=2)再操作后,shape=[3,2]。