pytorch 數據維度變換


view、reshape

  1. 兩者功能一樣:將數據依次展開后,再變形
  2. 變形后的數據量與變形前數據量必須相等。即滿足維度:ab...f = xy...z
  3. reshape是pytorch根據numpy中的reshape來的
  4. -1表示,其他維度數據已給出情況下,
import torch
a = torch.rand(2, 3, 2, 3)
a
# 輸出:
    tensor([[[[0.4850, 0.0073, 0.8941],
              [0.0208, 0.4396, 0.7841]],

             [[0.0553, 0.3554, 0.0726],
              [0.9669, 0.3918, 0.9356]],

             [[0.6169, 0.2080, 0.1028],
              [0.5816, 0.3509, 0.6983]]],


            [[[0.7545, 0.8693, 0.4751],
              [0.2206, 0.3384, 0.2877]],

             [[0.9521, 0.6172, 0.5058],
              [0.6835, 0.0624, 0.6261]],

             [[0.7752, 0.3820, 0.5585],
              [0.1547, 0.1420, 0.6051]]]])

# 將數據依次展開后,再變形為對應維度。所以,數據的順序是一樣的。且總的數據維度是不變的。
a.view(4, 9)  
# 輸出:
    tensor([[0.4850, 0.0073, 0.8941, 0.0208, 0.4396, 0.7841, 0.0553, 0.3554, 0.0726],
            [0.9669, 0.3918, 0.9356, 0.6169, 0.2080, 0.1028, 0.5816, 0.3509, 0.6983],
            [0.7545, 0.8693, 0.4751, 0.2206, 0.3384, 0.2877, 0.9521, 0.6172, 0.5058],
            [0.6835, 0.0624, 0.6261, 0.7752, 0.3820, 0.5585, 0.1547, 0.1420, 0.6051]])

# reshape和view的效果一樣    
a.reshape(4, 9)  
# 輸出:
    tensor([[0.4850, 0.0073, 0.8941, 0.0208, 0.4396, 0.7841, 0.0553, 0.3554, 0.0726],
            [0.9669, 0.3918, 0.9356, 0.6169, 0.2080, 0.1028, 0.5816, 0.3509, 0.6983],
            [0.7545, 0.8693, 0.4751, 0.2206, 0.3384, 0.2877, 0.9521, 0.6172, 0.5058],
            [0.6835, 0.0624, 0.6261, 0.7752, 0.3820, 0.5585, 0.1547, 0.1420, 0.6051]])

# -1表示,除了其他維度以外的最大維度數據量
# 此處為2*3*2*3=36, 36/4=9
a.reshape(4, -1)
# 輸出:
    tensor([[0.4850, 0.0073, 0.8941, 0.0208, 0.4396, 0.7841, 0.0553, 0.3554, 0.0726],
            [0.9669, 0.3918, 0.9356, 0.6169, 0.2080, 0.1028, 0.5816, 0.3509, 0.6983],
            [0.7545, 0.8693, 0.4751, 0.2206, 0.3384, 0.2877, 0.9521, 0.6172, 0.5058],
            [0.6835, 0.0624, 0.6261, 0.7752, 0.3820, 0.5585, 0.1547, 0.1420, 0.6051]])

# 36/(2*3) = 6
# 所以此時-1表示6
a.reshape(2, 3, -1)
# 輸出:
    tensor([[[0.4850, 0.0073, 0.8941, 0.0208, 0.4396, 0.7841],
             [0.0553, 0.3554, 0.0726, 0.9669, 0.3918, 0.9356],
             [0.6169, 0.2080, 0.1028, 0.5816, 0.3509, 0.6983]],

            [[0.7545, 0.8693, 0.4751, 0.2206, 0.3384, 0.2877],
             [0.9521, 0.6172, 0.5058, 0.6835, 0.0624, 0.6261],
             [0.7752, 0.3820, 0.5585, 0.1547, 0.1420, 0.6051]]])


# 給定的-1以外的其他維度數據的乘積,必須能整除總的數據量
# 比如,此處的5不能整除36,所以會報錯
a.reshape(5, -1)
# 輸出:
    ---------------------------------------------------------------------------
    RuntimeError                              Traceback (most recent call last)
    <ipython-input-26-af98f63a60b8> in <module>
    ----> 1 a.reshape(5, -1)

    RuntimeError: shape '[5, -1]' is invalid for input of size 36


# 變成其他形狀后,如果記得原數據形狀,可以變形回去
a.view(4, 9).view(2, 3, 2, 3)
# 輸出:
tensor([[[[0.4850, 0.0073, 0.8941],
          [0.0208, 0.4396, 0.7841]],

         [[0.0553, 0.3554, 0.0726],
          [0.9669, 0.3918, 0.9356]],

         [[0.6169, 0.2080, 0.1028],
          [0.5816, 0.3509, 0.6983]]],


        [[[0.7545, 0.8693, 0.4751],
          [0.2206, 0.3384, 0.2877]],

         [[0.9521, 0.6172, 0.5058],
          [0.6835, 0.0624, 0.6261]],

         [[0.7752, 0.3820, 0.5585],
          [0.1547, 0.1420, 0.6051]]]])

unsqueeze

  1. 功能:指定維度,為其增加(插入)1個維度
  2. 必須給定維度數據,不然會報錯
a = torch.rand(2, 3)
a
# 輸出:
    tensor([[0.3074, 0.2152, 0.0082],
            [0.2831, 0.9236, 0.2705]])
    
# 在0維處,增加1個維度。
a.unsqueeze(0)
# 支持負數索引,等價於 a.unsqueeze(-3)
# 輸出:
    tensor([[[0.3074, 0.2152, 0.0082],
             [0.2831, 0.9236, 0.2705]]])

a.unsqueeze(1)
# 等價於a.unsqueeze(-2)
# 輸出:
    tensor([[[0.3074, 0.2152, 0.0082]],
            [[0.2831, 0.9236, 0.2705]]])

a.unsqueeze(2) 
# 等價於a.unsqueeze(-1)
# 輸出:
    tensor([[[0.3074],
             [0.2152],
             [0.0082]],

            [[0.2831],
             [0.9236],
             [0.2705]]])

a.unsqueeze(0).unsqueeze(-1)  # 分別在0和最后維度上面都增加了一個維度,相比上面的數據,外層多了一對[]括號
# 輸出:
    tensor([[[[0.3074],
              [0.2152],
              [0.0082]],

             [[0.2831],
              [0.9236],
              [0.2705]]]])

squeeze 刪除為1的維度

  1. 默認將刪除所有為1的維度
  2. 傳入指定維度,刪除指定維度為1的維度
a = torch.rand(2, 1, 3, 1, 2, 1)
a
# 輸出:
    tensor([[[[[[0.4492],
                [0.6223]]],

              [[[0.8522],
                [0.4971]]],

              [[[0.2585],
                [0.6034]]]]],


            [[[[[0.1904],
                [0.5564]]],

              [[[0.3120],
                [0.2698]]],

              [[[0.6620],
                [0.5963]]]]]])

a.squeeze()  # 默認刪除所有為1的維度,即(2, 1, 3, 1, 2, 1)刪除后得到(2, 3, 2)
a
# 輸出:
    tensor([[[0.4492, 0.6223],
             [0.8522, 0.4971],
             [0.2585, 0.6034]],

            [[0.1904, 0.5564],
             [0.3120, 0.2698],
             [0.6620, 0.5963]]])

a.squeeze(1).squeeze(2).squeeze(3)  # 通過指定維度刪除1,與上面效果相同
a
# 輸出:
    tensor([[[0.4492, 0.6223],
             [0.8522, 0.4971],
             [0.2585, 0.6034]],

            [[0.1904, 0.5564],
             [0.3120, 0.2698],
             [0.6620, 0.5963]]])

expand

  1. 功能:擴展維度到指定維度。擴展的數據是復制當前維度的數據。
  2. 只有只有維度大小為1的維度可以擴展
  3. -1表示保持原維度
a = torch.rand(2, 3, 1)
a
# 輸出:
    tensor([[[0.1162],
             [0.6026],
             [0.5674]],

            [[0.7272],
             [0.4351],
             [0.1708]]])

# 擴展數據,只有維度為1的地方可以被擴展
a.expand(2, -1, 3)
# 輸出:
    tensor([[[0.1162, 0.1162, 0.1162],
             [0.6026, 0.6026, 0.6026],
             [0.5674, 0.5674, 0.5674]],

            [[0.7272, 0.7272, 0.7272],
             [0.4351, 0.4351, 0.4351],
             [0.1708, 0.1708, 0.1708]]])

repeat

  1. 表示擴展數據到原維度的倍數。
  2. 1表示保持原維度。
  3. 不建議使用此方法,因為復制數據會重新申請內存空間,比較占內存
a
# 輸出:
    tensor([[[0.1162],
             [0.6026],
             [0.5674]],

            [[0.7272],
             [0.4351],
             [0.1708]]])

a.repeat(1, 1, 3)
# 輸出:
    tensor([[[0.1162, 0.1162, 0.1162],
         [0.6026, 0.6026, 0.6026],
         [0.5674, 0.5674, 0.5674]],

        [[0.7272, 0.7272, 0.7272],
         [0.4351, 0.4351, 0.4351],
         [0.1708, 0.1708, 0.1708]]])

矩陣轉置

  1. 行列互換
  2. .t()只支持2D的數據
a = torch.rand(5, 2)
a
# 輸出:
    tensor([[0.9841, 0.2180],
            [0.5082, 0.8553],
            [0.5250, 0.7228],
            [0.9064, 0.0074],
            [0.2752, 0.3939]])

a.t()
# 輸出:
    tensor([[0.9841, 0.5082, 0.5250, 0.9064, 0.2752],
            [0.2180, 0.8553, 0.7228, 0.0074, 0.3939]])

transpose維度交換

  1. 相當於被選擇的兩個維度數據進行轉置,即:行列互換
  2. 也可以理解為,每一行數據順時針旋轉90度為一列后,依次拼接在右邊(最后面)
a = torch.rand(2, 3, 4)
a
# 輸出:
    tensor([[[0.1696, 0.6733, 0.7269, 0.1066],
             [0.5433, 0.2820, 0.0214, 0.9471],
             [0.6922, 0.8220, 0.8422, 0.8682]],

            [[0.6121, 0.8133, 0.6502, 0.4529],
             [0.9810, 0.9233, 0.5279, 0.2193],
             [0.1775, 0.8487, 0.4938, 0.3994]]])

a.transpose(0, 2)  
# 輸出:
    tensor([[[0.1696, 0.6121],
             [0.5433, 0.9810],
             [0.6922, 0.1775]],

            [[0.6733, 0.8133],
             [0.2820, 0.9233],
             [0.8220, 0.8487]],

            [[0.7269, 0.6502],
             [0.0214, 0.5279],
             [0.8422, 0.4938]],

            [[0.1066, 0.4529],
             [0.9471, 0.2193],
             [0.8682, 0.3994]]])

a.transpose(0, 2).contiguous().view(4, 6)
# 輸出:
    tensor([[0.1696, 0.6121, 0.5433, 0.9810, 0.6922, 0.1775],
            [0.6733, 0.8133, 0.2820, 0.9233, 0.8220, 0.8487],
            [0.7269, 0.6502, 0.0214, 0.5279, 0.8422, 0.4938],
            [0.1066, 0.4529, 0.9471, 0.2193, 0.8682, 0.3994]])

permute

與transpose不同的是:

  1. transpose一次只能進行兩個維度之間的交換
  2. permute可以一次進行多個維度的交換。其實質就是實現多個transpose步驟。
  3. 給定維度索引。
a = torch.rand(2, 3, 4)
a
# 輸出:
    tensor([[[0.7855, 0.6239, 0.3785, 0.8138],
             [0.9595, 0.5210, 0.3816, 0.1612],
             [0.0152, 0.9714, 0.4245, 0.4754]],

            [[0.1475, 0.4961, 0.0812, 0.3769],
             [0.4279, 0.0595, 0.0717, 0.9871],
             [0.9480, 0.3525, 0.3076, 0.0367]]])

a.permute(1, 2, 0)
# 輸出:
    tensor([[[0.7855, 0.1475],
             [0.6239, 0.4961],
             [0.3785, 0.0812],
             [0.8138, 0.3769]],

            [[0.9595, 0.4279],
             [0.5210, 0.0595],
             [0.3816, 0.0717],
             [0.1612, 0.9871]],

            [[0.0152, 0.9480],
             [0.9714, 0.3525],
             [0.4245, 0.3076],
             [0.4754, 0.0367]]])    

# 通過2次transpose可以實現permute的效果    
a.transpose(0, 1).transpose(1, 2)  
# 輸出:
    tensor([[[0.7855, 0.1475],
             [0.6239, 0.4961],
             [0.3785, 0.0812],
             [0.8138, 0.3769]],

            [[0.9595, 0.4279],
             [0.5210, 0.0595],
             [0.3816, 0.0717],
             [0.1612, 0.9871]],

            [[0.0152, 0.9480],
             [0.9714, 0.3525],
             [0.4245, 0.3076],
             [0.4754, 0.0367]]])

broadcast廣播(自動擴展):

  1. 定義:兩個維度不同的數據相加,會自動將維度小的數據擴張到與大維度相同的維度
  2. 特點:自動擴展維度,並且不用復制數據,節省空間
  3. 前提:小維度的數據,要么不給定維度,要么給定1維,要么與原數據維度大小相同的維度,否則會報錯。
a = torch.rand(3, 4, 2)
a
# 輸出:
    tensor([[[0.7220, 0.7834],
             [0.4305, 0.6128],
             [0.6032, 0.5751],
             [0.2304, 0.3003]],

            [[0.1044, 0.1071],
             [0.1373, 0.4874],
             [0.3963, 0.5231],
             [0.1851, 0.8962]],

            [[0.0677, 0.0587],
             [0.7268, 0.8807],
             [0.5445, 0.2110],
             [0.8755, 0.8577]]])

b = torch.rand(1, 4, 2)  # b的第一維度為1,a的為3
b
# 輸出:
tensor([[[0.6676, 0.5702],
         [0.3334, 0.8553],
         [0.5392, 0.0754],
         [0.9488, 0.7814]]])

# 相加和,b被自動廣播為3,然后再與a相加,得到結果
a + b
# 輸出:
    tensor([[[1.0925, 1.1274],
             [0.7881, 1.6091],
             [0.6568, 0.8419],
             [1.8460, 1.7360]],

            [[0.9783, 0.9697],
             [1.0127, 1.3521],
             [0.7147, 0.3189],
             [1.3435, 1.3845]],

            [[0.8699, 1.0997],
             [0.5712, 1.8381],
             [0.6607, 1.0689],
             [0.9599, 1.7686]]])



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM