PyTorchチュートリアル

41678 ワード

PyTorchチュートリアルノートの整理を煩わすな
文書ディレクトリ
  • 一、PyTorchニューラルネットワーク基盤
  • 1.TorchとNumpy
  • 2.変数
  • 2.励振関数
  • 二、簡単なニューラルネットワーク構築
  • 1.復帰
  • 2.分類
  • 3.ネットワーク構築の2つの方法
  • 4.モデルの保存と抽出
  • 5.バッチトレーニング
  • 一、PyTorchニューラルネットワーク基礎
    1.TorchとNumpy
    TorchにおけるtensorはNumpyにおける配列と非常に類似しており,両者の基本動作は類似しており,互いに変換可能である:Numpy配列をTorchに変換するtensortorch.from_numpy(numpy_array)TorchのtensorをNumpy配列に変換するtorch_tensor.numpy()コードの例
    import torch
    import numpy as np
    
    np_data = np.arange(6).reshape((2, 3))  # Numpy  
    torch_data = torch.from_numpy(np_data)  #  Numpy     Torch tensor
    tensor2array = torch_data.numpy()   #  Torch tensor   Numpy  
    

    Torchの数学演算もNumpyと似ています.
    # abs      
    data = [-1, -2, 1, 2]
    tensor = torch.FloatTensor(data)  #    32    tensor
    print(np.abs(data))          # [1 2 1 2]
    print(torch.abs(tensor)      # [1 2 1 2]
    
    # sin        sin
    print(np.sin(data))       # [-0.84147098 -0.90929743  0.84147098  0.90929743]
    print(torch.sin(tensor))  # [-0.8415 -0.9093  0.8415  0.9093]
    
    # mean    
    print(np.mean(data))          # 0.0
    print(torch.mean(tensor))     # 0.0
    

    注意:Torchでの行列点乗(.dot())はNumpyとは異なります.Torchでマトリクス点乗を実現するには、torch.mm(tensor1,tensor2)を利用し、その機能はnp.matmul(arr1,arr2)と同じである.Numpyでは行列点乗を計算し、arr1.dot(arr2)で実現することもできるが、Torchではtensor1.dot(tensor2)2つのtensorを1次元に伸ばして対応するビットを乗算して加算し、1つの値だけを返す.
    # matrix multiplication     
    data = [[1,2], [3,4]]
    tensor = torch.FloatTensor(data)  #    32    tensor
    # correct method
    print(
        '
    numpy: '
    , np.matmul(data, data), # [[7, 10], [15, 22]] '
    torch: '
    , torch.mm(tensor, tensor) # [[7, 10], [15, 22]] ) # !!!! !!!! data = np.array(data) print( '
    numpy: '
    , data.dot(data), # [[7, 10], [15, 22]] numpy '
    torch: '
    , tensor.dot(tensor) # torch [1,2,3,4].dot(1,2,3,4) = 30.0 )

    2.変数
    TorchにおけるVariableは、変化する値(tensor)を格納地理的位置である.
    変数の定義
    import torch
    from torch.autograd import Variable # torch   Variable   
    
    #     
    tensor = torch.FloatTensor([[1,2],[3,4]])
    #         , requires_grad           ,        
    variable = Variable(tensor, requires_grad=True)
    

    変数の計算と勾配を1つのVariableで計算すると、同じタイプのVariableが返される.Variableは計算する時、逐次計算図を構築して、逆方向の伝播に用います
    v_out = torch.mean(variable*variable)
    v_out.backward()    #    v_out        
    print(variable.grad)    #    Variable    
    '''
     0.5000  1.0000
     1.5000  2.0000
    '''
    

    Variable内のデータを取得してVariableに直接アクセスし、取得したのはVariable形式のデータで、多くの場合使えず、利用する必要があるvariable.dataそれをtensorに変換する
    2.励振関数
    PyTorchの励起関数はtorchにある.nn.functionalモジュールではrelu,sigmoid,tanh,softplusなどがよく用いられる.
    import torch
    import torch.nn.functional as F     #        
    from torch.autograd import Variable
    
    x = torch.linspace(-5, 5, 200)  # x data (tensor), shape=(100, 1)
    x = Variable(x)
    
    #          
    y_relu = F.relu(x)
    y_sigmoid = F.sigmoid(x)
    y_tanh = F.tanh(x)
    y_softplus = F.softplus(x)
    # y_softmax = F.softmax(x)  softmax    ,       ,          ,     
    

    二、簡単なニューラルネットワークを構築する
    1.回帰
    import torch
    import torch.nn.functional as F     #        
    
    #    
    x = torch.unsqueeze(torch.linspace(-1, 1, 100), dim=1)  # x data (tensor), shape=(100, 1)
    y = x.pow(2) + 0.2*torch.rand(x.size())                 # noisy y data (tensor), shape=(100, 1)
    
    #     
    class Net(torch.nn.Module):  #    torch   Module
        def __init__(self, n_feature, n_hidden, n_output):
            super(Net, self).__init__()     #    __init__   
            #            
            self.hidden = torch.nn.Linear(n_feature, n_hidden)   #        
            self.predict = torch.nn.Linear(n_hidden, n_output)   #        
    
        def forward(self, x):   #       Module    forward   
            #        ,           
            x = F.relu(self.hidden(x))      #     (       )
            x = self.predict(x)             #    
            return x
    
    net = Net(n_feature=1, n_hidden=10, n_output=1)
    
    print(net)  # net    
    """
    Net (
      (hidden): Linear (1 -> 10)
      (predict): Linear (10 -> 1)
    )
    """
    
    #   
    # optimizer       
    optimizer = torch.optim.SGD(net.parameters(), lr=0.2)  #    net      ,    
    loss_func = torch.nn.MSELoss()      #                (   )
    
    for t in range(100):
        prediction = net(x)     #    net      x,      
    
        loss = loss_func(prediction, y)     #        
    
        optimizer.zero_grad()   #              
        loss.backward()         #       ,        
        optimizer.step()        #           net   parameters  
    

    2.分類
    import torch
    import torch.nn.functional as F     #        
    
    #    
    n_data = torch.ones(100, 2)         #        
    x0 = torch.normal(2*n_data, 1)      #   0 x data (tensor), shape=(100, 2)
    y0 = torch.zeros(100)               #   0 y data (tensor), shape=(100, )
    x1 = torch.normal(-2*n_data, 1)     #   1 x data (tensor), shape=(100, 1)
    y1 = torch.ones(100)                #   1 y data (tensor), shape=(100, )
    
    #    x, y                  (torch.cat       )
    x = torch.cat((x0, x1), 0).type(torch.FloatTensor)  # FloatTensor = 32-bit floating
    y = torch.cat((y0, y1), ).type(torch.LongTensor)    # LongTensor = 64-bit integer
    
    #     
    class Net(torch.nn.Module):     #    torch   Module
        def __init__(self, n_feature, n_hidden, n_output):
            super(Net, self).__init__()     #    __init__   
            self.hidden = torch.nn.Linear(n_feature, n_hidden)   #        
            self.out = torch.nn.Linear(n_hidden, n_output)       #        
    
        def forward(self, x):
            #        ,           
            x = F.relu(self.hidden(x))      #     (       )
            x = self.out(x)                 #    ,          ,            
            return x
    
    net = Net(n_feature=2, n_hidden=10, n_output=2) #         output
    
    print(net)  # net    
    """
    Net (
      (hidden): Linear (2 -> 10)
      (out): Linear (10 -> 2)
    )
    """
    
    #   
    # optimizer       
    optimizer = torch.optim.SGD(net.parameters(), lr=0.02)  #    net      ,    
    #       ,      !  ! one-hot    ,   1D Tensor, (batch,)
    #       2D tensor (batch, n_classes)
    loss_func = torch.nn.CrossEntropyLoss()
    
    for t in range(100):
        out = net(x)     #    net      x,      
    
        loss = loss_func(out, y)     #        
    
        optimizer.zero_grad()   #              
        loss.backward()         #       ,        
        optimizer.step()        #           net   parameters  
    

    3.ネットワークを構築する二つの方法
    ネットワークを構築するためのClassの構築
    class Net(torch.nn.Module):
        def __init__(self, n_feature, n_hidden, n_output):
            super(Net, self).__init__()
            self.hidden = torch.nn.Linear(n_feature, n_hidden)   #    
            self.predict = torch.nn.Linear(n_hidden, n_output)   #    
    
        def forward(self, x):    #       
            x = F.relu(self.hidden(x))
            x = self.predict(x)
            return x
    
    net1 = Net(1, 10, 1)   #              net1
    

    利用するnnモジュール高速ネットワーク構築
    net2 = torch.nn.Sequential(
        torch.nn.Linear(1, 10),
        torch.nn.ReLU(),
        torch.nn.Linear(10, 1)
    )
    

    二つの方法を比較する
    print(net1)
    """
    Net (
      (hidden): Linear (1 -> 10)
      (predict): Linear (10 -> 1)
    )
    """
    print(net2)
    """
    Sequential (
      (0): Linear (1 -> 10)
      (1): ReLU ()
      (2): Linear (10 -> 1)
    )
    """
    

    Net 2にはいくつかの内容が多く表示され、励起関数も一緒に組み込まれていますが、net 1では、励起関数は実際にforward()機能で呼び出されます.これは、net 2よりもnet 1の利点が、個人のニーズに応じて順方向伝播プロセスをより個性化できることを示している.
    4.モデルの保存と抽出
    モデルの保存には,(1)ネットワーク全体およびパラメータを保存するtorch.save(net1, 'net.pkl');(2)ネットワークのパラメータのみを保存し,ネットワーク構造を保存せず,高速でメモリが少ないtorch.save(net1.state_dict(), 'net_params.pkl').したがって、モデルの抽出には、(1)ネットワーク全体およびパラメータを抽出するnet2 = torch.load('net.pkl')net.pklに保存されているのもネットワーク全体でなければなりません.(2)ネットワークのパラメータのみ抽出:ネットワークを確立してからパラメータを抽出する必要がある
    def restore_params():
        #    net3,            
        net3 = torch.nn.Sequential(
            torch.nn.Linear(1, 10),
            torch.nn.ReLU(),
            torch.nn.Linear(10, 1)
        )
    
        #           net3
        net3.load_state_dict(torch.load('net_params.pkl'))
    

    5.ロットトレーニング
    Torchで提供されたDataLoaderは、自分のデータを包装し、バッチトレーニングを行うことができます.自分の(numpy arrayまたは他の)データ形式をTensorに置き換え、このパッケージに入れます.DataLoaderデータを効率的に反復できます.
    import torch
    import torch.utils.data as Data
    
    BATCH_SIZE = 5      #         
    
    x = torch.linspace(1, 10, 10)       # x data (torch tensor)
    y = torch.linspace(10, 1, 10)       # y data (torch tensor)
    
    #      torch      Dataset
    torch_dataset = Data.TensorDataset(data_tensor=x, target_tensor=y)
    
    #   dataset    DataLoader
    loader = Data.DataLoader(
        dataset=torch_dataset,      # torch TensorDataset format
        batch_size=BATCH_SIZE,      # mini batch size
        shuffle=True,               #         (     )
        num_workers=2,              #        
    )
    
    for epoch in range(3):   #     !  !   3  
        for step, (batch_x, batch_y) in enumerate(loader):  #     loader            
            #             ...
    
            #        
            print('Epoch: ', epoch, '| Step: ', step, '| batch x: ',
                  batch_x.numpy(), '| batch y: ', batch_y.numpy())
    
    """
    Epoch:  0 | Step:  0 | batch x:  [ 6.  7.  2.  3.  1.] | batch y:  [  5.   4.   9.   8.  10.]
    Epoch:  0 | Step:  1 | batch x:  [  9.  10.   4.   8.   5.] | batch y:  [ 2.  1.  7.  3.  6.]
    Epoch:  1 | Step:  0 | batch x:  [  3.   4.   2.   9.  10.] | batch y:  [ 8.  7.  9.  2.  1.]
    Epoch:  1 | Step:  1 | batch x:  [ 1.  7.  8.  5.  6.] | batch y:  [ 10.   4.   3.   6.   5.]
    Epoch:  2 | Step:  0 | batch x:  [ 3.  9.  2.  6.  7.] | batch y:  [ 8.  2.  9.  5.  4.]
    Epoch:  2 | Step:  1 | batch x:  [ 10.   4.   8.   1.   5.] | batch y:  [  1.   7.   3.  10.   6.]
    """
    

    バッチ・トレーニングの場合、最後のロットに残ったデータの数がbatch_に満たない場合size、DataLoaderは残りのすべてのデータを返します.