[ピトーチ研究ノート(3)]:NN関連

ニューラルネットワーク

torch.nnパッケージを使用してニューラルネットワークを構築できます。

前回の記事autograd学習したようにnnパッケージはautogradパッケージを使用してモデルを定義し、派生させます。1つにはnn.Module、出力を返すためのさまざまなレイヤーとメソッドが含まれますforward(input)

たとえば、デジタル画像認識に使用されるネットワークを見ることができます:
[pic]

これは単純なフィードフォワードネットワークです。ネットワークは最初に入力を受け入れ、それを次の層に送信し、層ごとに送信し、最後に出力します。

ニューラルネットワークの一般的なトレーニングプロセスは次のとおりです。

  • 学習可能なパラメーター(または重み)を含むニューラルネットワークを定義する
  • 入力データセットを反復する
  • ネットワーク経由で入力を処理する
  • 損失(出力と正解の間の距離)を計算する
  • 勾配をネットワークのパラメーターに逆伝播する
  • 一般的に使用される単純なルールであるネットワークの重みを更新します。weight= weight-learning_rate * gradient

ネットワークを定義する

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

class Net(nn.Module):

    def __init__(self):
        super(Net, self).__init__()
        # 1 input image channel, 6 output channels, 3x3 square convolution
        # kernel
        self.conv1 = nn.Conv2d(1, 6, 3)
        self.conv2 = nn.Conv2d(6, 16, 3)
        # an affine operation: 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):
        # Max pooling over a (2, 2) window
        x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
        # If the size is a square you can only specify a single 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:]  # all dimensions except the batch dimension
        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で関数backward定義し、autogradで自動的に定義されました。forward関数では任意のテンソル演算を使用できます。

モデルのトレーニング可能なパラメーターは、次net.parameters()によって検索されます。

params = list(net.parameters())
print(len(params))
print(params[0].size())  # conv1's .weight

# output:
# 10
# torch.Size([6, 1, 3, 3])

これで32x32入力を最初に試すことができます。このネットワーク(LeNet)の予想される入力は32x32 だからです。MNISTデータセットをトレーニングに使用する場合は、画像サイズを32x32に調整するよう注意する必要があります。

input = torch.randn(1, 1, 32, 32)
out = net(input)
print(out)

# output:
# tensor([[ 0.0399, -0.0856,  0.0668,  0.0915,  0.0453, -0.0680, -0.1024,  # 0.0493, -0.1043, -0.1267]], grad_fn=<AddmmBackward>)

すべてのパラメーターのグラデーションキャッシュをクリアしてから、ランダムグラデーションの逆伝播を実行します。

net.zero_grad()
out.backward(torch.randn(1, 10))

ヒント:torch.nnはミニバッチのみをサポートします。torch.nnパッケージ全体は、単一のサンプルではなく、少量のバッチサンプルの入力のみをサポートします。

たとえば、nn.Conv2dは4次元テンソル、つまりnSamples x nChannels x高さx幅を受け入れます

別のサンプルの場合は、input.unsqueeze(0)を使用して、「偽の」バッチサイズディメンションを追加します。

要約:

  • torch.Tensor- backward()テンソルの勾配を保存しながら、などの自動導出操作をサポートする多次元配列
  • nn.Module-ニューラルネットワークモジュール。これは、GPUへのパラメーターの移動、エクスポート、ロードなどの機能を使用して、パラメーターをカプセル化する便利な方法です。
  • nn.Parameter -テンソルの一種で、属性としてモジュールに割り当てられると、自動的にパラメーターとして登録されます。
  • autograd.Function -順方向および逆方向の伝播の自動導出の定義を実現し、各Tensorは少なくとも1つの関数ノードを作成します。これは、Tensorを作成した関数に接続され、その履歴をエンコードします

これまでに、次のことを学びました。

  • ネットワークを定義する方法
  • 入力を処理して逆方向に呼び出す

まだ学ぶ必要があるもの:

  • 損失を計算する
  • ネットワークの重みを更新する

損失関数

損失関数は、(出力、ターゲット)のペアを入力として受け入れ、ネットワークの出力がターゲット値とどれだけ異なるかを推定する値を計算します。

nnパッケージには多くの異なる損失関数があります。nn.MSELossは比較的単純なもので、出力とターゲットの平均二乗誤差を計算します。

output = net(input)
target = torch.randn(10)  # 本例子中使用模拟数据
target = target.view(1, -1)  # 使目标值与数据值形状一致
criterion = nn.MSELoss()

loss = criterion(output, target)
print(loss)

# tensor(1.0263, grad_fn=<MseLossBackward>)

これで、loss.grad_fn属性を使用して逆伝播プロセスを追跡すると、次のような計算図が表示されます。

input -> conv2d -> relu -> maxpool2d -> conv2d -> relu -> maxpool2d
      -> view -> linear -> relu -> linear -> relu -> linear
      -> MSELoss
      -> loss

呼び出されるとloss.backward()、グラフ全体が損失について区別されます。このグラフのrequires_grad真であるすべてのテンソルは、それらの.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

# output:
# <MseLossBackward object at 0x7f8dac1b4550>
# <AddmmBackward object at 0x7f8dac1b4a90>
# <AccumulateGrad object at 0x7f8dac1b4a90>

バックプロップ

loss.backward()重みをバックプロパゲートするために呼び出す必要があるだけです最初に、既存の勾配をクリアする必要があります。そうしないと、勾配は既存の勾配で累積されます。

デモ時間:以下は、loss.backward()逆伝播の前後のconv1レイヤーバイアスの勾配変化を表示するための呼び出しです

net.zero_grad()     # 清零所有参数(parameter)的梯度缓存

print('conv1.bias.grad before backward')
print(net.conv1.bias.grad)

loss.backward()

print('conv1.bias.grad after backward')
print(net.conv1.bias.grad)

# output:
# conv1.bias.grad before backward
# tensor([0., 0., 0., 0., 0., 0.])
# conv1.bias.grad after backward
# tensor([ 0.0084,  0.0019, -0.0179, -0.0212,  0.0067, -0.0096])

重みを更新する

最も単純な更新規則は、確率的勾配降下法(SGD)です。

weight = weight - learning_rate * gradient

簡単な実装:

learning_rate = 0.01
for f in net.parameters():
    f.data.sub_(f.grad.data * learning_rate)

同時に、ニューラルネットワークを使用する場合は、SGD、Nesterov-SGD、Adam、RMSPropなどのさまざまな更新ルールを使用することもできます。これには、torch.optimこれらすべてのメソッドを実装するを使用できます使い方も非常に簡単です。

import torch.optim as optim

# 创建优化器(optimizer)
optimizer = optim.SGD(net.parameters(), lr=0.01)

# 在训练的迭代中:
optimizer.zero_grad()   # 清零梯度缓存
output = net(input)
loss = criterion(output, target)
loss.backward()
optimizer.step()    # 更新参数

REF

https://pytorch.apachecn.org/docs/1.4/blitz/neural_networks_tutorial.html
https://pytorch.org/tutorials/beginner/blitz/neural_networks_tutorial.html

50件の元の記事を公開 賞賛された51件 1968年の訪問

おすすめ

転載: blog.csdn.net/Chen_2018k/article/details/105642109