従来のトレーニング機能であるバッチは、次のようにトレーニングされます。
for i,(images,target) in enumerate(train_loader):
# 1. input output
images = images.cuda(non_blocking=True)
target = torch.from_numpy(np.array(target)).float().cuda(non_blocking=True)
outputs = model(images)
loss = criterion(outputs,target)
# 2. backward
optimizer.zero_grad() # reset gradient
loss.backward()
optimizer.step()
- 損失の取得:画像とラベルを入力し、推論によって予測値を計算し、損失関数を計算します。
- オプティマイザー.zero_grad()は過去の勾配をクリアします。
- loss.backward()逆伝播、現在の勾配を計算します。
- オプティマイザー.step()は、勾配に従ってネットワークパラメーターを更新します
簡単に言えば、データのバッチで提供され、勾配を1回計算し、ネットワークを1回更新します。
勾配累積の使用は次のように記述されます。
for i,(images,target) in enumerate(train_loader):
# 1. input output
images = images.cuda(non_blocking=True)
target = torch.from_numpy(np.array(target)).float().cuda(non_blocking=True)
outputs = model(images)
loss = criterion(outputs,target)
# 2.1 loss regularization
loss = loss/accumulation_steps
# 2.2 back propagation
loss.backward()
# 3. update parameters of net
if((i+1)%accumulation_steps)==0:
# optimizer the net
optimizer.step() # update parameters of net
optimizer.zero_grad() # reset gradient
- 損失の取得:画像とラベルを入力し、推論によって予測値を計算し、損失関数を計算します。
- loss.backward()逆伝播、現在の勾配を計算します。
- 勾配をクリアせずに、手順1〜2を複数回繰り返して、勾配が既存の勾配に累積されるようにします。
- 勾配が特定の回数蓄積された後、最初にoptimizer.step()は蓄積された勾配に従ってネットワークパラメータを更新し、次にoptimizer.zero_grad()は過去の勾配をクリアして次の勾配蓄積の波に備えます。
要約:勾配累積とは、1バッチのデータを取得するたびに、勾配を1回計算し、勾配がクリアされず、継続的に累積されることを意味します。一定の回数が経過すると、ネットワークパラメータが累積勾配に従って更新され、次に勾配がクリアされ、次のサイクル。
特定の条件下では、バッチサイズが大きいほど、トレーニング効果が高くなります。グラデーションの累積により、バッチサイズの偽装拡張が実現されます。accumulation_stepsが8の場合、バッチサイズ「偽装」は8倍に拡張されます。これは、ビデオメモリの制限を解決するための乞食ラボの1つです。良いトリックです。使用するときは注意が必要であり、学習率を適切に拡大する必要があります。