Pytorch学習教程(三)----------ニューラルネットワーク


%matplotlib inline

ニューラルネットワーク
torchを使用できます.nn package構造はニューラルネットワークを構築する.
さっきautogradを簡単に紹介しましたが、nnはautogradに依存してモデルを定義し、それらを区別します.一つnn.Moduleには、あなたが定義したネットワーク層とforward(input)メソッドが含まれています.このメソッドはoutputを返します.
このデジタル画像分類のネットワークの例を見てみましょう.
簡単なフィードフォワードネットワークです.入力を受け入れ、各層の入力は上位層の出力であり、最後に出力が与えられます.
典型的なニューラルネットワークの訓練過程は以下の通りである.
  • は、学習パラメータ(または重み)を有するニューラルネットワーク
  • を定義する.
  • 反復入力データセット
  • ニューラルネットワークに基づいて入力データセットを演算する
  • .
  • 損失を計算します(実際の結果との距離を出力します.損失が小さいほどモデルが正確であることを示します).
  • は、勾配をニューラルネットワークのパラメータに逆方向に伝播する.
  • ネットワークの重み(またはパラメータ)を更新します.通常、単純な更新ルールが使用されます.ウェイト=ウェイト-学習率*勾配です.

  • ニューラルネットワークを定義する
    import torch
    import torch.nn as nn
    import torch.nn.functional as F
    
    
    class Net(nn.Module):
    
        def __init__(self):
            super(Net, self).__init__()
            #   2    
            # kernel
            self.conv1 = nn.Conv2d(1, 6, 3)
            self.conv2 = nn.Conv2d(6, 16, 3)
            #    3    , y=wx+b
            self.fc1 = nn.Linear(16 * 6 * 6, 120)  # 6*6 from image dimension 
            self.fc2 = nn.Linear(120, 84)
            self.fc3 = nn.Linear(84, 10)
    
        def forward(self, x):
            #                  relu        
            x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
            #                number  
            x = F.max_pool2d(F.relu(self.conv2(x)), 2)
            x = x.view(-1, self.num_flat_features(x))
            x = F.relu(self.fc1(x))
            x = F.relu(self.fc2(x))
            x = self.fc3(x)
            return x
    
        def num_flat_features(self, x):
            size = x.size()[1:]  #   0         batch number,      
            num_features = 1
            for s in size:
                num_features *= s
            return num_features
    
    
    net = Net()
    print(net)
    
    Net(
      (conv1): Conv2d(1, 6, kernel_size=(3, 3), stride=(1, 1))
      (conv2): Conv2d(6, 16, kernel_size=(3, 3), stride=(1, 1))
      (fc1): Linear(in_features=576, out_features=120, bias=True)
      (fc2): Linear(in_features=120, out_features=84, bias=True)
      (fc3): Linear(in_features=84, out_features=10, bias=True)
    )
    

    forwardメソッドを定義するだけで、後方関数(微分を自動的に計算する関数)が自動的に定義されます.もちろんautogradパラメータをTrueに設定する必要があります.forwardメソッドでは、テンソルの任意の演算を使用できます.
    モデルの学習パラメータはnet.parameters()が返されます.
    params = list(net.parameters())
    print(len(params))
    print(params[0].size())  # conv1's .weight
    
    10
    torch.Size([6, 1, 3, 3])
    

    このネットワークは3232のデータセットに適している(13232は1つのコアが5のボリューム層を経て、大きさは62828になる;1つのコアが2のプール化層を経て、大きさは61414になる;もう1つのコアが5のボリューム層を経て、大きさは160100になる;プール化層、165*5、ちょうど次の線形層の入力特徴数である).モデルを実行しましょう.
    input = torch.randn(1, 1, 32, 32)
    out = net(input)
    print(out)
    
    tensor([[ 0.0219,  0.0002,  0.0533, -0.0077, -0.0179, -0.0888, -0.0075,  0.0175,
              0.0084,  0.0613]], grad_fn=)
    

    勾配を0にクリアし、ランダム勾配を使用して逆方向に伝播します.
    net.zero_grad()
    out.backward(torch.randn(1, 10))
    

    注意:
    torch.nnはバッチデータの処理のみをサポートし、単一のサンプルはサポートしません.
    例えばnn.Conv 2 dは入力として4次元テンソルを必要とする:[nSamples,nChannels,Height,Width.]
    サンプルが1つしかない場合はinputを使用できます.unsqueeze(0)は、偽のbatch次元を追加します.
    継続する前に、学んだばかりのいくつかのクラスを振り返ってみましょう.
  • torch.Tensor:backward()などの自動微分(または勾配)操作をサポートする多次元配列.
  • nn.Module:ニューラルネットワークモデルは、パラメータのカプセル化、GPUへの移植、エクスポート、ロードなどの便利な方法を支援します.
  • nn.パラメータ:テンソル、Moduleにプロパティを定義すると、パラメータが自動的に生成されます.
  • autograd.Function:自動勾配演算の前後定義を実現します.各テンソル演算は、少なくとも1つのFunctionノードを生成し、テンソルを作成する関数に接続し、その履歴を符号化する.

  • その上で、私たちはすでにしました.
  • ニューラルネットワーク
  • を定義する
  • 入力および呼び出しbackwardメソッド
  • の処理
    残り:
  • 計算損失
  • 更新ネットワークの重み
  • そんしつかんすう
    損失関数には、2つの入力(予測値と実際の値)が含まれ、2つの値の距離が返されます.
    nn packageには異なる損失関数があります.簡単な損失関数はnn.MSELOssは、平均分散、すなわち、各成分が減算された二乗累計最終除算成分の個数を返す.
    output = net(input)
    target = torch.randn(10)  # a dummy target, for example
    target = target.view(1, -1)  # make it the same shape as output
    criterion = nn.MSELoss()
    
    loss = criterion(output, target)
    print(loss)
    
    tensor(1.1062, grad_fn=)
    

    だからlossを呼び出すとbackward()の場合、計算図全体で微分され、すべてのrequires_grad=Trueのテンソルの.gradプロパティは加算されます.
    それをよりよく理解するために、わずかなステップをリストします.
    print(loss.grad_fn)  # MSELoss
    print(loss.grad_fn.next_functions[0][0])  # Linear
    print(loss.grad_fn.next_functions[0][0].next_functions[0][0])  # ReLU
    
    
    
    
    

    ぎゃくほうこうでんぱ
    誤差を逆方向に伝播するために私たちがしなければならないのはlossを呼び出すだけです.backward().既存の勾配をクリアする必要があります.そうしないと、勾配は既存の勾配と累積されます.
    lossを呼び出します.backward()はconv 1’sのbiasの勾配の逆伝搬前後の変化を見た.
    net.zero_grad()     # zeroes the gradient buffers of all parameters
    
    print('conv1.bias.grad before backward')
    print(net.conv1.bias.grad)
    
    loss.backward()
    
    print('conv1.bias.grad after backward')
    print(net.conv1.bias.grad)
    
    conv1.bias.grad before backward
    tensor([0., 0., 0., 0., 0., 0.])
    conv1.bias.grad after backward
    tensor([ 0.0098,  0.0003, -0.0068,  0.0056, -0.0279, -0.0121])
    

    損失関数の使用方法を知っています.
    後で読む:
    nn packageは種々の深さニューラルネットワークのモジュールと損失関数を含む.ここには完全なリストがありますhttp://pytorch.org/docs/nn
    私たちがしなければならない最後のステップは、
    ネットワークモデルのウェイト値の更新(パラメータ)
    ウェイトの更新(Update Weights)
    実際によく使われる最も簡単な更新ルールは、Stochastic Gradient Descent(SGD)です.
    weight = weight - learning_rate * gradient
    上式はpythonコードで実現されます.
    learning_rate=0.01
    for f in net.parameters():
        f.data.sub_(learning_rate*f.grad.data)
    

    しかし、ニューラルネットワークを使用する場合、SGD(ランダム勾配降下法)、Nesterov-SGD、Adam、RMSProp(平均二乗伝播)など、さまざまな更新規則を使用したいと思っています.ライブラリtorchでこれらの方法をすべて実現しました.optim中です.使用も簡単です.
    import torch.optim as optim
    
    # create your optimizer
    optimizer = optim.SGD(net.parameters(), lr=0.01)
    
    # in your training loop:
    optimizer.zero_grad()   # zero the gradient buffers
    output = net(input)
    loss = criterion(output, target)
    loss.backward()
    optimizer.step()    # Does the update
    

    注意:
    勾配キャッシュを0、すなわちoptimizerに手動で設定する必要があることが観察された.zero_grad()は,逆伝搬の節でも述べたように勾配が積算されるためである.