PyTorch勾配の蓄積
PyTorchが蓄積勾配バッチの事実上の延長を実現使用
PyTorchなぜ勾配バックプロパゲーションの前に手動でクリアする必要がありますか?ほとんど知られている- -答えパスカル
https://www.zhihu.com/question/303070254/answer/573037166
このモードは、累積勾配(勾配蓄積)として、勾配がより多くのトリックを再生することができます
伝統的なトレーニング機能は、そのような訓練は、バッチです。
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()
- 損失を得る:入力画像とタグ、推測算出損失関数によって算出された予測値と、
optimizer.zero_grad()
クリア前の勾配;loss.backward()
バックプロパゲーション、現在の勾配を計算します。optimizer.step()
勾配に応じてネットワークパラメータを更新します
簡単に言えば、それは勾配を計算するために、データのバッチに来ている、更新されたネットワーク
勾配の蓄積を使用すると、そう書かれています:
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()
過去の勾配、次の波のために準備する累積勾配を空にする。
要約する:勾配は、データ取得のバッチは、二次の勾配を計算するたびに蓄積され、増加し続ける勾配が空でない勾配を累積更新されたネットワークパラメータに応じて、時間の特定の累積数の後、次いで、次のサイクルのために、空勾配。
場合は、一定の条件の下では、より良いバッチサイズのトレーニング効果も大きい、勾配蓄積は、バッチサイズの事実上の延長を達成することであるaccumulation_steps
8で、バッチサイズ「変装」は8倍に拡大、私たちの研究室では、この乞食を解決するための良いメモリに制約トリックは、学習率も適切な増幅を使用するときに注意を払う必要があります。
誰かがそう言う前に、かどうかにBNへの影響:1を更新します。
あなたがいない場合は私の知る限りでは、バッチノルム統計は、各往路ので、問題はないに更新されます
.backward()
たびに。
BNは、前方の段階で推定されているだけではなく、競合し、完了したaccumulation_steps=8
と8回に比べて拡大し、真のバッチサイズ、効果はいくつかの違いであり、結局、BNの8倍のバッチサイズは確かに、より正確な数を平均と分散推定。
アップデート2:によると、李Shaohuaのシェア、BNは、その勢いのパラメータを減らすために適切かもしれません。
彼はパラメータ:. x_new_running = BN勢いがある - あなたは、統計情報のより長い配列を得ることができるので、(1つのモメンタム)* x_running +勢い* x_new_observed勢い0に近いが、古い実行中の統計情報は、長く覚えています
私は単にPyTorch 1.0ソースを見て:https://github.com/pytorch/pytorch/blob/162ad945902e8fc9420cbd0ed432252bd7de673a/torch/nn/modules/batchnorm.py#L24、勢い0.1に、このプロパティのデフォルト値をBNクラス、あなたが試すことができます規制の下で。
蓄積による勾配、図を計算する複数の同時損失を計算する複数の記憶避けます
PyTorchなぜ勾配バックプロパゲーションの前に手動でクリアする必要がありますか?- Forever123答え-知っているほとんど
https://www.zhihu.com/question/303070254/answer/608153308
その理由はPyTorchに、算出した勾配値が増加しますということです。
そして、このような利点は、メモリの観点から消費することができます。
1. Edition1
、マルチタスクミッションスクラッチプロセスから標準電車の中PyTorchには:
for idx, data in enumerate(train_loader):
xs, ys = data
pred1 = model1(xs)
pred2 = model2(xs)
loss1 = loss_fn1(pred1, ys)
loss2 = loss_fn2(pred2, ys)
******
loss = loss1 + loss2
optmizer.zero_grad()
loss.backward()
++++++
optmizer.step()
PyTorchの設計原理から、各時刻におけるpredを計算する前に得られ、生成に必要な勾配バックホールのための算出マップ、中間結果逆伝播格納され、この図を、呼び出されたときに**.backward()**
、意志この図は、メモリから解放されます。
- コード上に
******
二つ計算グラフを含むメモリ、及び加算損失で、二つのマップを合わせ、そして変化の大きさは無視することができます。 - 実行するために
++++++
、対応する値は、卒業生とリリースメモリを得ました。このように、あなたはトレーニング2つの計算チャートを格納する必要があり、損失の発生源の組成は、より複雑な場合、メモリの消費量はさらに大きくなります。
2. Edition2
各メモリの消費量を削減するために、勾配の蓄積が意味がある以下の変異体は、。
for idx, data in enumerate(train_loader):
xs, ys = data
optmizer.zero_grad()
# 计算d(l1)/d(x)
pred1 = model1(xs) #生成graph1
loss = loss_fn1(pred1, ys)
loss.backward() #释放graph1
# 计算d(l2)/d(x)
pred2 = model2(xs)#生成graph2
loss2 = loss_fn2(pred2, ys)
loss.backward() #释放graph2
# 使用d(l1)/d(x)+d(l2)/d(x)进行优化
optmizer.step()
蓄積の勾配でコードから分かるように、図の計算ケースまでタスクストアにマルチタスクをトレーニングすることができます。
3.その他
もう一つの理由は、大規模なバッチグラ反復としてメモリ不足の場合のバッチサイズの複数の重ね合わせである得られた両方の勾配が同等であるからです。
要約すると、これは設計FAIRの出発で、素晴らしいアイデア勾配累積優しいメモリです。
関連リンク
- PyTorchなぜ勾配バックプロパゲーションの前に手動でクリアする必要がありますか?-ほとんど知られている:https://www.zhihu.com/question/303070254
- https://discuss.pytorch.org/t/why-do-we-need-to-set-the-gradients-manually-to-zero-in-pytorch/4903/9