pytorch入門チュートリアル:テンソル初期化と基本演算


pytorchを正式に開始する前に、まず以下のnumpyの基本的な操作を振り返ります.
まずnumpyパッケージをインポート
import numpy as np

numpyのndarray配列を作成する方法は主に以下の3つです.
  • listはnpに移行する.array
  • a1 = [[1, 2], [3, 4]]
    a1 = np.array(a1)
    
  • カスタムサイズのランダム配列を作成
  • a2 = np.random.rand(2, 3)
    
  • 特殊マトリクスの作成
  • a3_zero = np.zeros((2, 3), float)
    a3_one = np.ones((2, 3), int)
    a3_sequence = np.arange(6).reshape(2, 3)
    

    マトリクスの形状は,我々がプログラミングする際に関心を持つパラメータであり,例えば,ボリュームニューラルネットワークを構築する際に,ボリュームコアのchannel数と前層出力の特徴図のchannel数が等しいことを保証しなければならない.
    では、マトリクスのshapeをどのように取得しますか?
    print(a2.shape)
    

    出力:
     (2, 3)
    

    行列演算:行列乗算と要素乗算
    行列乗算:
    np.dot(a1, a2)
    

    出力:
    array([[0.73630149, 2.14174254, 2.88921558],
           [1.91645686, 5.21595794, 6.71389597]])
    

    要素の乗算:
    np.multiply(a1, a1)
    

    出力:
    array([[ 1,  4],
           [ 9, 16]])
    

    ここでは行列乗算の定義を用いる演算も行い,結果とnp.dotの計算結果は一致した.
    def calculate(a, b):
        [m, n] = a.shape
        [p, q] = b.shape
        c = np.zeros((m, q), float)
        if n == p:
            for i in range(m):
                for j in range(q):
                    for k in range(n):
                        c[i][j] += a[i][k] * b[k][j]
        else:
            print('col of a is not matched with row of b')
        return c
    
    res = calculate(a1, a2)
    

    出力:
    array([[0.73630149, 2.14174254, 2.88921558],
           [1.91645686, 5.21595794, 6.71389597]])
    

    ではpytorch入門チュートリアルに入り、numpyのndarrayに対応し、torchのマトリクスをtensorと呼びます.
    テンソル初期化
    import numpy as np
    import torch 
    

    tensor初期化には主に以下の6種類があります.
  • Null Matrix
  • a_1 = torch.empty(5, 3)
    print(a_1)
    
    tensor([[7.1118e-04, 1.7444e+28, 7.3909e+22],
            [4.5828e+30, 3.2483e+33, 1.9690e-19],
            [6.8589e+22, 1.3340e+31, 1.1708e-19],
            [7.2128e+22, 9.2216e+29, 7.5546e+31],
            [1.6932e+22, 3.0728e+32, 2.9514e+29]])
    
  • ランダム初期化
  • a_2 = torch.rand(5, 3)
    print(a_2)
    
    tensor([[0.0671, 0.2958, 0.4455],
            [0.6711, 0.1368, 0.8041],
            [0.3503, 0.2100, 0.2833],
            [0.7877, 0.4100, 0.3452],
            [0.8703, 0.5900, 0.4173]])
    
  • 特殊マトリクス
  • a_3 = torch.zeros(5, 3, dtype=torch.long)
    print(a_3)
    a_4 = torch.ones(5, 3, dtype=torch.long)
    print(a_4)
    
    tensor([[0, 0, 0],
            [0, 0, 0],
            [0, 0, 0],
            [0, 0, 0],
            [0, 0, 0]])
    tensor([[1, 1, 1],
            [1, 1, 1],
            [1, 1, 1],
            [1, 1, 1],
            [1, 1, 1]])
    
  • 直接データ構造tensor
  • a_5 = torch.tensor([[1, 2], [3, 4]])
    print(a_5)
    
    tensor([[1, 2],
            [3, 4]])
    
  • 既存のtensorに基づいて新しいtenor
  • を確立する
    a_6 = torch.randn_like(a_4, dtype=torch.float)
    print(a_6)
    
    tensor([[ 0.9866, -0.8028,  0.0766],
            [-0.2422,  0.2072,  0.6010],
            [ 1.3993,  0.3761, -0.3051],
            [ 0.9399, -1.5329,  1.3698],
            [-0.4801, -0.6285,  0.9697]])
    
  • numpy配列とtorchテンソルの変換
  • x = torch.ones(5)
    print(x)
    print(x.numpy())
    x = np.ones(5)
    x = torch.from_numpy(x)
    print(x)
    
    tensor([1., 1., 1., 1., 1.])
    [1. 1. 1. 1. 1.]
    tensor([1., 1., 1., 1., 1.], dtype=torch.float64)
    

    tensorのシェイプを取得するには
    torch.Sizeの本質はtupleであり,numpyはreshapeを用いて行列形状を変化させ,torchはtensorのshapeを用いてviewを変化させる.
    print(a_6.size())
    print(a_6.view(3, 5).size())
    print(a_6.view(-1, 5).size())
    a_6 = torch.randn(1)
    print(a_6)
    print(a_6.item())
    
    torch.Size([5, 3])
    torch.Size([3, 5])
    torch.Size([3, 5])
    tensor([1.1442])
    1.14415442943573
    

    tensor演算
  • 加算
  • #        
    print(a_3 + a_4)
    print(torch.add(a_3, a_4))
    #       
    a_7 = torch.add(a_3, a_4)
    res = torch.empty(5, 3)
    torch.add(a_3, a_4, out=res)
    print(res)
    #        x+=y
    a_3.add_(a_4)
    print(a_3)
    
    tensor([[1, 1, 1],
            [1, 1, 1],
            [1, 1, 1],
            [1, 1, 1],
            [1, 1, 1]])
    tensor([[1, 1, 1],
            [1, 1, 1],
            [1, 1, 1],
            [1, 1, 1],
            [1, 1, 1]])
    tensor([[1., 1., 1.],
            [1., 1., 1.],
            [1., 1., 1.],
            [1., 1., 1.],
            [1., 1., 1.]])
    tensor([[1, 1, 1],
            [1, 1, 1],
            [1, 1, 1],
            [1, 1, 1],
            [1, 1, 1]])
    
  • マトリクス乗算
  • x = torch.ones(2, 2, dtype=torch.long)
    y = torch.ones(2, 2, dtype=torch.long)
    print(torch.mul(x, y))
    print(x * y)
    print(torch.mm(x, y))
    print(torch.matmul(x, y))
    
    tensor([[1, 1],
            [1, 1]])
    tensor([[1, 1],
            [1, 1]])
    tensor([[2, 2],
            [2, 2]])
    tensor([[2, 2],
            [2, 2]])
    

    Cuda上のテンソル
    device = torch.device('cuda') if torch.cuda.is_available() else 'cpu'
    print(device)
    if torch.cuda.is_available():
        x = x.to(device)
        x = torch.ones_like(x, device=device)
        x = x.to('cpu', dtype=torch.float64)
    
    cpu