pytouch画像におけるデータ前処理とバッチ標準化の例


現在のデータ前処理で最も一般的な方法は中心化と標準化です。
中心化は修正データの中心位置に相当し、実現方法は非常に簡単であり、各特徴次元から対応する平均値を引いて、最後に0平均の特徴を得る。
標準化も非常に簡単であり、データが0平均になった後、異なる特徴次元が同じ規模になるように、標準偏差近似で標準正規分布として割り算しても良いし、最大値と最小値に基づいて−1〜1の間に変換しても良い。
バッチ標準化:BN
データ前処理の際には,特性が相関しないように入力し,標準的な正規分布を満足させるようにしたが,このようなモデルの表現は一般的にも良好であった。しかし、深いネットワーク構造については、ネットワークの非線形層が出力の結果を相関させ、標準的なN(0,1)の分布を満たさなくなり、出力の中心がオフセットしてしまうこともあります。これはモデルの訓練、特に深層のモデルトレーニングにとって非常に困難です。
したがって、2015年の論文では、この方法を提出しました。バッチ標準化は、簡単に言えば、各階層のネットワークの出力に対して、正規化して標準的な正規分布に従わせます。このように、後者のネットワークの入力も標準的な正規分布です。
batch normalizationの実現はとても簡単です。これから対応するpythonコードを書きます。

import sys
sys.path.append('..')
 
import torch
 
def simple_batch_norm_1d(x, gamma, beta):
  eps = 1e-5
  x_mean = torch.mean(x, dim=0, keepdim=True) #        broadcast
  x_var = torch.mean((x - x_mean) ** 2, dim=0, keepdim=True)
  x_hat = (x - x_mean) / torch.sqrt(x_var + eps)
  return gamma.view_as(x_mean) * x_hat + beta.view_as(x_mean)
   
x = torch.arange(15).view(5, 3)
gamma = torch.ones(x.shape[1])
beta = torch.zeros(x.shape[1])
print('before bn: ')
print(x)
y = simple_batch_norm_1d(x, gamma, beta)
print('after bn: ')
print(y)
テストの時はバッチ標準化を使うべきですか?
答えは肯定的です。訓練の時に使いましたので、テストの時に使わないと結果が違ってきますが、テストの時にはデータセットが一つしかないなら、平均値はこの値ではなく、分散は0ですか?これは明らかにランダムですので、テストの時はテストのデータセットで平均値と分散を計算するのではなく、訓練の時に算出した移動平均値と分散を使って代用します。
以下のように訓練状態とテスト状態を区別できるバッチ標準化方法を実現します。

def batch_norm_1d(x, gamma, beta, is_training, moving_mean, moving_var, moving_momentum=0.1):
  eps = 1e-5
  x_mean = torch.mean(x, dim=0, keepdim=True) #        broadcast
  x_var = torch.mean((x - x_mean) ** 2, dim=0, keepdim=True)
  if is_training:
    x_hat = (x - x_mean) / torch.sqrt(x_var + eps)
    moving_mean[:] = moving_momentum * moving_mean + (1. - moving_momentum) * x_mean
    moving_var[:] = moving_momentum * moving_var + (1. - moving_momentum) * x_var
  else:
    x_hat = (x - moving_mean) / torch.sqrt(moving_var + eps)
  return gamma.view_as(x_mean) * x_hat + beta.view_as(x_mean)
以下、私達は畳み込みネットの下でバッチ標準化を試してみます。効果を見てみます。

def data_tf(x):
  x = np.array(x, dtype='float32') / 255
  x = (x - 0.5) / 0.5 #      ,   
  x = torch.from_numpy(x)
  x = x.unsqueeze(0)
  return x
 
train_set = mnist.MNIST('./data', train=True, transform=data_tf, download=True) #        ,         
test_set = mnist.MNIST('./data', train=False, transform=data_tf, download=True)
train_data = DataLoader(train_set, batch_size=64, shuffle=True)
test_data = DataLoader(test_set, batch_size=128, shuffle=False)
#       
class conv_bn_net(nn.Module):
  def __init__(self):
    super(conv_bn_net, self).__init__()
    self.stage1 = nn.Sequential(
      nn.Conv2d(1, 6, 3, padding=1),
      nn.BatchNorm2d(6),
      nn.ReLU(True),
      nn.MaxPool2d(2, 2),
      nn.Conv2d(6, 16, 5),
      nn.BatchNorm2d(16),
      nn.ReLU(True),
      nn.MaxPool2d(2, 2)
    )
    
    self.classfy = nn.Linear(400, 10)
  def forward(self, x):
    x = self.stage1(x)
    x = x.view(x.shape[0], -1)
    x = self.classfy(x)
    return x
 
net = conv_bn_net()
optimizer = torch.optim.SGD(net.parameters(), 1e-1) #         ,    0.1
 
 
train(net, train_data, test_data, 5, optimizer, criterion)
以上のpytouch画像のデータ前処理とバッチ標準化の例は小編集が皆さんに提供したすべての内容です。参考にしていただければ幸いです。よろしくお願いします。