PyTorch 1.5 レシピ : 基本 : 勾配をゼロで埋める

PyTorch 1.5 レシピ : 基本 : 勾配をゼロで埋める (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 05/13/2020 (1.5.0)

* 本ページは、PyTorch 1.5 Recipes の以下のページを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

無料セミナー開催中 クラスキャット主催 人工知能 & ビジネス Web セミナー

人工知能とビジネスをテーマにウェビナー (WEB セミナー) を定期的に開催しています。スケジュールは弊社 公式 Web サイト でご確認頂けます。
  • お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
  • Windows PC のブラウザからご参加が可能です。スマートデバイスもご利用可能です。

お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。

株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
E-Mail:sales-info@classcat.com ; WebSite: https://www.classcat.com/
Facebook: https://www.facebook.com/ClassCatJP/

 

基本 : 勾配をゼロで埋める

ニューラルネットワークを構築するとき勾配をゼロで埋めることは有益です。これはデフォルトでは、勾配は .backward() が呼び出されるときいつでもバッファで累積される (i.e. 上書きされない) からです。

 

イントロダクション

ニューラルネットワークを訓練するとき、モデルは勾配降下を通してそれらの精度を増大することが可能です。手短に言えば、勾配降下はモデルの重みとバイアスを微調整することにより損失 (or 誤差) を最小化するプロセスです。

torch.Tensor は PyTorch の中心的なクラスです。tensor を作成するとき、その属性 .requires_grad を True に設定する場合、パッケージはそれ上の総ての演算を追跡します。これは続く backward パスで発生します。この tensor に対する勾配は .grad 属性に累積されます。総ての勾配の累積 (or 総計) は loss tensor 上で .backward() が呼び出されるとき計算されます。

tensor の勾配を zero-out する必要があるかもしれないケースがあります。例えば: 訓練ループを開始するとき、この追跡を正しく遂行できるように勾配を zero out するべきです。このレシピでは、PyTorch ライブラリを使用して勾配をどのように zero out するかを学習します。CIFAR10 データセット上で (PyTorch に構築された) ニューラルネットワークを訓練することによりこれをどのように行なうかを実演します。

 

セットアップ

このレシピ内でデータを訓練していきますので、実行可能なノートブックに在る場合、ランタイムを GPU か TPU に切り替えることが最善です。始める前に、torch と torchvision をそれらがまだ利用可能でないのであればインストールする必要があります。

pip install torchvision

 

ステップ

ステップ 1 から 4 は訓練のためのデータとニューラルネットワークをセットアップします。勾配を zero out するプロセスはステップ 5 で発生します。構築されたデータとニューラルネットワークを既に持つ場合には、5 にスキップしてください。

  1. データをロードするために総ての必要なライブラリをインポートする。
  2. データセットをロードして正規化する。
  3. ニューラルネットワークを構築する。
  4. 損失関数を定義する。
  5. ネットワークを訓練する間、勾配をゼロにする。

 

1. データをロードするために必要なライブラリをインポートする

このレシピのため、データセットにアクセスするため torch と torchvision を単に使用していきます。

import torch

import torch.nn as nn
import torch.nn.functional as F

import torch.optim as optim

import torchvision
import torchvision.transforms as transforms

 

2. データセットをロードして正規化する

PyTorch は様々な組込みデータセットをフィーチャーします (より多くの情報については Loading Data レシピを見てください)。

transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
                                        download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4,
                                          shuffle=True, num_workers=2)

testset = torchvision.datasets.CIFAR10(root='./data', train=False,
                                       download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=4,
                                         shuffle=False, num_workers=2)

classes = ('plane', 'car', 'bird', 'cat',
           'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

 

3. ニューラルネットワークを構築する

畳込みニューラルネットワークを使用します。更に学習するためには ニューラルネットワークを定義する レシピを見てください。

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16 * 5 * 5)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

 

4. 損失関数と optimizer を定義する

分類 Cross-Entropy 損失と SGD with モメンタムを使用しましょう。

net = Net()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

 

5. ネットワークを訓練する間に勾配をゼロにする

これは物事が面白くなり始めるときです。私達は単純にデータ iterator に渡りループし、そして入力をネットワークに供給して最適化しなければなりません。データの各実在に対して、勾配をゼロにすることに注意してください。これは、ニューラルネットワークを訓練するときどのような不要な情報も追跡していないことを確実にします。

for epoch in range(2):  # loop over the dataset multiple times

    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        # get the inputs; data is a list of [inputs, labels]
        inputs, labels = data

        # zero the parameter gradients
        optimizer.zero_grad()

        # forward + backward + optimize
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        # print statistics
        running_loss += loss.item()
        if i % 2000 == 1999:    # print every 2000 mini-batches
            print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0

print('Finished Training')

mode.zero_grad() もまた使用できます。これはモデルパラメータの総てがその optimizer にある限りは optimizer.zero_grad() の使用と同じです。どちらの一つを使用するかを決めるために最善の判断をしてください。

Congratulations! PyTorch で勾配を成功的にゼロにしました。

 
以上