美文网首页
TF2.0:tf.reshape与tf.transpose的区别

TF2.0:tf.reshape与tf.transpose的区别

作者: 胜负55开 | 来源:发表于2019-12-05 19:50 被阅读0次

    说明:这两个维度变换操作,对于张量的处理是非常重要的!但是二者其实有本质上的不同!一定不能混用。本文将详细说明两者对张量变换的区别。

    写在前面1:Tensorflow与Numpy其实从出发点来讲是一致的!都是“高维数组”的科学计算库,只不过TF把高维数组又起了一个名字叫“张量”而已。因此:高维数组与张量没有本质区别!只不过张量多了一个属性叫“张量的阶”(其实就是这个高维数组一共有几维而已)。因此:本文所阐明的Tensorflow中的tf.reshape与tf.transpose的不同,同理可用来区别Numpy中np.reshape与np.transpose。

    写在前面2:transpose就是“转置”的意思!当数据/张量为2维时,不论是reshape还是transpose都非常好理解。而本文讲解的“高维数组”下的情况:举一个3维数组的例子,理解之后即可理解更高维的情况。

    写在前面3:在深度学习中,tf.reshape改变的是“view(视图)”;tf.transpose改变的是“content(原图)”。其实二者都会改变原始图像的样貌,但个人认为:tf.transpose对原图的改变程度更大!—— 因为它改变的是轴的顺序

    本文举例中所用的数据:

    import numpy as np
    import tensorflow as tf
    
    c1 = [0, 1, 2, 3]
    c2 = [4, 5, 6, 7]
    c3 = [8, 9, 10, 11]
    c4 = [12, 13, 14, 15]
    c5 = [16, 17, 18, 19]
    c6 = [20, 21, 22, 23]
    
    c = np.array( [ [c1,c2], [c3,c4], [c5,c6] ] )
    c = tf.convert_to_tensor(c)
    
    # 所用数据为:
    <tf.Tensor: id=12, shape=(3, 2, 4), dtype=int32, numpy=
    array([[[ 0,  1,  2,  3],
            [ 4,  5,  6,  7]],
    
           [[ 8,  9, 10, 11],
            [12, 13, 14, 15]],
    
           [[16, 17, 18, 19],
            [20, 21, 22, 23]]])>
    

    一、tf.reshape( c, [] )

    使用方式:c1 = tf.reshape(c, [新的尺寸])
    参数1:c是原始图像;
    参数2:[新的尺寸] —— 给一个“符合逻辑(乘积和原数据点数相同)”的新尺寸。既然可以自定义尺寸,那么理论上就会有非常多种view视图;
    函数内部处理流程:

    • 把c所有数据点:按页一行一行展平;—— 一定且无法改变
    • 把展平的数据按新的尺寸组合起来。—— 自定义

    随便自定义一种view视图:

    c2 = tf.reshape(c, [2, 6, 2])
    c2
    
    # 结果:
    <tf.Tensor: id=22, shape=(2, 6, 2), dtype=int32, numpy=
    array([[[ 0,  1],
            [ 2,  3],
            [ 4,  5],
            [ 6,  7],
            [ 8,  9],
            [10, 11]],
    
           [[12, 13],
            [14, 15],
            [16, 17],
            [18, 19],
            [20, 21],
            [22, 23]]])>
    

    说明(很重要):如上面说明的函数内部处理流程,其中第一步“数据展平”操作一定会进行且展平规则不会被改变。—— 也就是说:只要原始数据不变,那么展平操作就不变,展平的效果就不变,即:各个“数据点之间的前后顺序”不会改变!—— 所以,不管在哪种view视图下,只要再次reshape到原图的的视图(3,2,4),就能回到原图!!!

    在c2视图的基础上,按照原图的视图(3,2,4)回到原图:

    c3 = tf.reshape(c2, [3,2,4])  # 在c2视图的基础上,回到原图的视图
    c3
    
    # 结果:
    <tf.Tensor: id=24, shape=(3, 2, 4), dtype=int32, numpy=
    array([[[ 0,  1,  2,  3],
            [ 4,  5,  6,  7]],
    
           [[ 8,  9, 10, 11],
            [12, 13, 14, 15]],
    
           [[16, 17, 18, 19],
            [20, 21, 22, 23]]])>
    

    总结:不管怎么reshape原图,只要原图不变,那么任何新的view视图只要通过“原图的view视图方式”,就一定能回到原图。 —— 即:reshape没有改变原图,因为它没有改变“展平后”的数据点前后、先后顺序!!! —— 即:reshape,仅仅是对原图“看法”的改变,原图还是原图。


    二、tf.transpose( c, perm = [新的轴顺序] )

    使用方式1:c1 = tf.transpose( c, perm = [新的轴顺序] )
    使用方式2:c1 = tf.tf.transpose( c, [新的轴顺序] ) # perm可以不写
    参数1:c还是原图数据;
    参数2:[新的轴顺序] —— 里面的数值是“索引值”。不需要给定义,举个例子就能明白:比如这里是[1, 0, 2],那么就表示:原来索引号为1的轴(原第二个),现在放第一位;原来索引号为0的轴(原第一个),现在放第二位;原来索引号为2的轴(原第三个),现在放第三位。 —— 即:原图尺寸是(3,2,4),现在按索引号重新调整后变为:(2,3,4)。

    它的效果可能不好直观理解,毕竟是“轴交换”。那么下面用是一个示意图来说明。看了示意图,会发现transpose的操作其实很好理解:

    图1:transpose之前

    看的角度永远是“顺着0轴正方向看”:可以看到3个2x4 —— (3,2,4)

    [0 1 2 3
     4 5 6 7]
    
    [8 9 10 11
     12 13 14 15]
    
    [16 17 18 19
     20 21 22 23]
    

    当perm = [1, 0, 2]时:0轴和1轴交换


    图2:transpose之后:0轴和1轴交换

    仍然是“顺着0轴正方向看”:现在是“从纸内向纸外”(不方便画箭头,就省略了)。那么现在看到就是2个3x4 —— (2, 3, 4)

    [0 1 2 3
     8 9 10 11
     16 17 18 19]
    
    [4 5 6 7
     12 13 14 15
     20 21 22 23]
    

    验证一下这种理解方法是否正确:

    c1 = tf.transpose(c, perm = [1, 0, 2])
    c1
    
    # 结果:
    <tf.Tensor: id=26, shape=(2, 3, 4), dtype=int32, numpy=
    array([[[ 0,  1,  2,  3],
            [ 8,  9, 10, 11],
            [16, 17, 18, 19]],
    
           [[ 4,  5,  6,  7],
            [12, 13, 14, 15],
            [20, 21, 22, 23]]])>   # 果然,理解没错!
    

    说明(很重要):tf.transpose改变是轴的顺序,也就是从不同的轴向来看待原数据!—— 这种轴的变换,虽然原数据点之间的相互顺序没用变,但换了一个轴的来看、来划分这些数据,其结果就是完全新的数据!—— 这些新的数据,不管怎么reshape是肯定回不到原图像的(因为reshape所根据的是“新数据”,由由上面关于reshape的说明可知:reshape不会改变所基于数据的数据点的相互排序顺序,因此不可能通过reshape把新数据恢复到原数据)。—— 因此:要想把tf.transpose创造的新数据,再转变回原数据,只能还利用tf.transpose按“相反的轴变换”再变回去。

    例如,把上面的c1再利用tf.transpose变回原图:在新图上再把0轴和1轴交换

    c11 = tf.transpose(c1, [1, 0, 2])
    c11
    
    # 结果:
    <tf.Tensor: id=20, shape=(3, 2, 4), dtype=int32, numpy=
    array([[[ 0,  1,  2,  3],
            [ 4,  5,  6,  7]],
    
           [[ 8,  9, 10, 11],
            [12, 13, 14, 15]],
    
           [[16, 17, 18, 19],
            [20, 21, 22, 23]]])>
    

    总结:以0轴的正方向来看,再每一个面上:先2轴正方向,再1轴正方向。
    总之:tf.transpose对于高维数组/张量的变换,是轴的交换,从得带来的是“观察方位”的改变。

    相关文章

      网友评论

          本文标题:TF2.0:tf.reshape与tf.transpose的区别

          本文链接:https://www.haomeiwen.com/subject/pjkjgctx.html