Pytorchレコード

5174 ワード

  • detach
  • トレーニングデータトレーニング中にout of memoryが発生することはないが、テスト時にテストが行われるにつれてGPUのmemoryが増加し、最終的にout of memoryが発生する場合が
  • である.
  • torch.no_grad

  • テスト時out of memoryの問題について


    訓練の過程でloss.backward()は計算図の隠れた変数勾配をクリアし、テスト時に空間を解放するメカニズムがないため、テストが進むにつれて中間変数が多くなる可能性があり、out of memoryの発生注:テスト時にまずmodelを使用する.eval()です.そうしないと、テスト時のbatchNorm層とDropout層の結果に影響します.解決策を追加する必要があります.
  • pytorch 0.4.0より前にinput=Variable(input,volatile=True)にvolatileをTrueに設定し、入力がvolatileであれば出力もvolatileであり、中間状態
  • が存在しないことを保証することができる.
    regular_input = Variable(torch.randn(5, 5))
    >>> volatile_input = Variable(torch.randn(5, 5), volatile=True)
    >>> model = torchvision.models.resnet18(pretrained=True)
    >>> model(regular_input).requires_grad
    True
    >>> model(volatile_input).requires_grad
    False
    >>> model(volatile_input).volatile
    True
    
  • しかしpytorch 0.4.0以降にvolatileをキャンセルする機構はtorchに置き換えられる.no_grad(), torch.set_grad_enable(grad_mode)等関数
  •  x = torch.tensor([1], requires_grad=True)
    >>> with torch.no_grad():
    ...   y = x * 2
    >>> y.requires_grad
    False
    >>> @torch.no_grad()
    ... def doubler(x):
    ...     return x * 2
    >>> z = doubler(x)
    >>> z.requires_grad
    False
    

    ここにいるno_grad()はpytorchの逆伝播メカニズムに影響し、テスト時に逆伝播が使用されないと判断したため、このモードはメモリ領域の節約に役立ちます.同理対torch.set_grad_enable(grad_mode)もそうです
    x = torch.tensor([1], requires_grad=True)
    >>> is_train = False
    >>> with torch.set_grad_enabled(is_train):
    ...   y = x * 2
    >>> y.requires_grad
    False
    >>> torch.set_grad_enabled(True)
    >>> y = x * 2
    >>> y.requires_grad
    True
    >>> torch.set_grad_enabled(False)
    >>> y = x * 2
    >>> y.requires_grad
    False
    
  • ここで疑問なのは、ネットワーク構造のデータを入力する最初のrequire_です.gradがTrueかどうかすべてがrequire_に設定されている場合gradはfalseがまた中間の各種の変数を格納するかどうかこれはhock実験を通じて
  • require_の場合gradのデフォルト値はfalseです.追加の処理をしない場合は、これらのリーフノードに接続されている生成ノードrequire_gradはいずれもfalseである、例えばc=Variable((a**2)を増やさなければ.data,requires_grad=True)では、すべてのノードa,b,c,dはrequires_であるgrad=Falseですが、中間層の修正により、ある中間層から勾配の計算が必要になり、あるいはある層にノードを新たに追加するrequired_gradがtrueであれば、そのノードに関連する後続ノードはtrueになります.
    a= Variable(torch.tensor(np.array([1,2,3],dtype=np.float)),requires_grad=False)
    b=Variable(torch.tensor(np.array([4,5,6],dtype=np.float)),requires_grad=False)
    c=Variable((a**2).data,requires_grad=True)
    d=c+b
    d=sum(d)
    d.backward()
    # c.backward(torch.Tensor([1,1,1]))
    print(c.grad)
    
    features_blobs = []
    def hook_feature(module, input, output):
        features_blobs.append(output.data.cpu().numpy())
    net._modules.get(final_conv).register_forward_hook(hook_feature)
    

    レジスター経由forward_hookは中間結果を得て、所望の結果が得られるかどうかを見てみましょう.もしそうすれば、すべての入力がrequireに設定されます.gradはfalseとtorchである.no_grad()に違いがあるかどうか
  • CNNにとってPytorchにおけるautograd
  • class Autoencoder(nn.Module):
        def __init__(self):
            super(Autoencoder, self).__init__()
            self.encoder = nn.Sequential(
                _ConvLayer(3, 128),
                _ConvLayer(128, 256),
                _ConvLayer(256, 512),
                _ConvLayer(512, 1024),
                Flatten(),
                nn.Linear(1024 * 4 * 4,1024),
                nn.Linear(1024,1024 * 4 * 4),
                Reshape(),
                _UpScale(1024, 512),
            )
        ...
    #  net encoder requires_grad
    for param in model.encoder.parameters():
        print(param.requires_grad)
     :
    
    True
    True
    True
    True
    True
    True
    True
    True
    True
    True
    True
    True
    True
    True
     , net , loss.backward() net 。
    

    カスタム機能

  • callのpythonにおけるクラスのインスタンスは、関数として扱うことができ、入力として他の関数に渡して実行することができる.例えば、
  • class X(object):
        def __init__(self, a, b, range):
            self.a = a
            self.b = b
            self.range = range
        def __call__(self, a, b):
            self.a = a
            self.b = b
            print('__call__ with ({}, {})'.format(self.a, self.b))
        def __del__(self, a, b, range):
            del self.a
            del self.b
            del self.range
    
    X(1,2,3)(4,5)
      __init__  a 1,b 2,range 3  __call__  a 4,b 5    __call__ with (4,5)
    
    
  • torch.autograd.Functionが新しいFunctionを追加するにはtorchを継承する必要があります.autograd.Function init forwardとbackward関数
  • を書き換えます.

    pytorchダイナミック接続図


    ダイナミックグラフ
    余談:0.4.0では0次元テンソル(torch.tensor(3)がtensor(3)を直接生成する、0.4.0より前にtensor([3]))が生成されるため、tensorはnumpyと完全に見なすことができ、0次元ベクトルはnumpyでのnpに対応する.array(0)、戻り値はarray(0)、tensor([1,2])に対してarray([1,2])に対応するnumpyに対してもtensorに対してもitem()を使用して0次元データをPython Number余談2:lossに返すことができる.backward()lossがスカラーである、要素が含まれている場合はlossを必要としない.backward()は、lossに等価なパラメータを指定します.backward(torch.FloatTensor([1.0])) Autograd
    pytorchは動的計算図を採用し、各ノードは変数を表し、0.4.0後にVariableを廃棄し、Tensorは元のVariableの機能に直接代わるため、Tensorは現在、ノード(順方向伝播の活性化値と逆方向伝播の勾配を保存するために使用される)を代表し、Functionを表す.以前のVariableのrequired_がTensorに保持されています.gradおよびgrad_fn,leaf Variableと生成変数のrequired_についてgradとgrad_fnは違うleaf variableのrequire_gradは、trueが1つある場合に関連する生成変数がtrueであることを指定できます.

    テスト時pytroch処理

     with torch.no_grad():
     	for input,target in test_loader:
     		......
    
    model.eval()