Pytorch トレーニング モデルの損失 損失が Nan または Infinite (INF) である理由

目次

1、 Nan 和 INF

2. Nan と INF の一般的な原因の概要

3. 原因分析と解決策

3.1. 入力データが間違っている

3.2. 学習率が高すぎる --> 勾配爆発 --> ナン

3.3、損失関数が間違っています

3.4. プーリング層のストライドはカーネルのサイズより大きい 

3.5、batchNorm はトリックを行う可能性があります

3.6. シャッフル設定が乱れていませんか?

3.7. 長距離ラベルを設定すると NAN が得られます

4. 解決策: 本質は、モデル操作の過程で入力データの値の範囲を調整することです。

4.1. モデルの重みに正則化を追加してパラメータのサイズを制限する

4.2. BatchNormalization をモデルに追加してデータを正規化する

4.3. relu6 関数など、上限のある活性化関数を使用する

4.4. 損失関数の演算前に値の範囲補正を実行する

4.5. 勾配枝刈りの実行

4.6. ResNet または DenseNet 構造の使用

5. pytorch 半精度アンプトレーニング nan 問題

5.1、なぜ?

5.2、どうやって?

6. ニューラルネットワークが何も学習できない場合はどうすればよいですか?

参考記事:


サンプルコードを提供する別の記事を読む必要があります: 深層学習における nan と inf の解決策

1、 Nan 和 INF

NaN は数値ではありません。 

INFとはinfinityの略で無限を意味します。たとえば、log(x) は損失関数を見つけるために使用され、x が 0 に近い場合、結果は inf になります。

勾配消失:ガイド値が非常に小さいため、その乗算項目が無限小に近くなります。これは、入力データ範囲が小さすぎる (その結果、重み W の導関数が特に小さくなる) か、出力データが原因である可能性があります。活性化関数の飽和領域に該当するニューラル ネットワーク層 (活性化関数の特に小さな導関数が得られる)

Gradient Explosion:ガイド値が非常に大きいため、乗算項目が非常に大きくなり、更新後のWが値の範囲を超えてしまいます。入力データが正規化されていない可能性があります (データ次元が大きすぎて W の勾配値を増加できない)。乗算項目の導関数が常に 1 より大きい限り、W の更新範囲は入力層は特に大きくなります。乗算項は、連鎖導出ルールにおける各層の導関数を指し、明らかに、勾配消失と勾配爆発の両方が乗算項の影響を受けます (つまり、ネットワーク勾配の影響)。

概要:勾配の消失によってモデルが nan および inf に表示されるのではなく、モデルの損失が減少しないだけであり、トレーニング プロセス中に精度を向上させることはできません。勾配爆発により、トレーニング プロセス中にモデルが表示されなくなる可能性があります。

1.1. 理論的観点から見ると、トレーニングプロセスにナンが現れる本質的な理由は下溢出 和 上溢出 の現象

オーバーフロー:まず、モデル内の指数演算を疑ってください。モデル内の値が大きすぎるため、exp(x) 演算を実行するとオーバーフローが発生します。ここでの解決策は、演算を推奨し、パラメーターを正規化することですNrom 。 exp 演算を実行するときに、オーバーフロー現象を回避するのに非常に良いでしょう。これを行うことができますLayerNormBatchNorm 、モデルに微調整を追加するときのLayerNorm 損失の問題を解決するためにNAN 。[例えば、他の処理を行わないソフトマックスの分子と分母はexp(x)を計算する必要があります。値が大きすぎると、INF/INFになってNaNになる可能性があります。このとき、次のことを確認する必要があります。使用しているソフトマックスでexp(x)の計算を行っています。関連処理(最大値の減算など)]

オーバーフローの原因はx/0の場合もありますので、パラメータ値が大きすぎるのが原因ではなく、特定の演算が原因で、例えばソフトマックスの同様の演算に問題があることが考えられます。自分で定義します。以下はソフトマックスのソリューションです。オーバーフローとアンダーフローの回避策は次のとおりです。

アンダーフロー:一般に、これは log⁡(0) または exp(x) 操作に関する問題です。学習率の設定が大きすぎるため、学習率を下げる必要がある場合が考えられます。学習率が表示されなくなるまで下げることができます。たとえば、学習率 1e-4 を次のように設定すれば十分です。 1e-5。

学習率を下げることに加えて、オプティマイザに eps を追加して、分母が 0 にならないようにすることもできます。たとえば、batchnorm で eps の値を 1e-5 に設定し、パラメータをoptimizer epstorch.optim.adamデフォルトはeps です1e-8ただし、この値は実際には少し小さいので、eps たとえば に設定するなど、デフォルト値を増やすことができます1e-3

optimizer1 = optim.Adam(model.parameters(), lr=1e-3, eps=1e-4)
optimizer1 = optim.Adam(model.parameters(), lr=0.001, eps=1e-3)
optimizer2 = optim.RMSprop(model.parameters(), lr=0.001, eps=1e-2)

1.2. データの観点から見ると、トレーニングで生成される nan と inf は本質的に入力データ値の範囲の問題に分けることができます。

  • 入力データに欠陥がある場合、モデルの順伝播中に値の範囲が制限を超え、平均値を nan 値で埋める必要がありますが、これは通常画像データでは表示されません。
  • ほとんどの場合、値の範囲の問題であり、値が大きすぎるか小さすぎることが原因です。これはモデルの順伝播で発生し、クロスエントロピーの対数関数、対数(1e-10)の値が小さすぎるなど、モデル内の一連の演算によりデータが値の範囲を超えてしまいます。 、および mse loss ( x .2) の math.pow の二乗値が大きすぎます。活性化関数の relu 関数に上限がありません。モデルの重みが大きすぎます。

2. Nan と INF の一般的な原因の概要

一般に、NaN は次のような状況で発生します。
深いモデルをトレーニングするプロセスに遭遇したことがある人は多いと思いますが、損失が突然 NaN になります。問題の概要は次のとおりです。

  1. ダーティデータ: トレーニングデータ(ラベルを含む)に異常値(nan、infなど)があるかどうか。
  2. 0で割る問題。ここで実際には 2 つの可能性があり、1 つは被除数の値が無限、つまり Nan である場合、もう 1 つは除数として 0 が使用される場合 (分母は eps=1e-8 で加算可能) です。以前に生成された Nan または 0 が引き継がれ、すべての Nan が後に残る場合があります。ソフトマックス層など、ニューラルネットワーク内で分割が考えられる箇所をまず確認し、データを注意深く確認してください。いくつかのログを追加し、ニューラル ネットワークの中間結果を出力して、どのステップ Nan が表示され始めるかを確認してください。
  3. 0 または自然対数としての負の数、またはネットワーク内に根号 (torch.sqrt) が存在するかどうか、根号は >=0 であることが保証されている可能性があります。
  4. 初期パラメータ値が大きすぎる場合: Nan の問題も発生する可能性があります。入力値と出力値を正規化することが最善です。
  5. 学習率の設定が大きすぎる: 初期学習率が大きすぎることも、この問題を引き起こす可能性があります。100 ラウンドの反復以内に NaN が出現する場合、一般的な理由は学習率が高すぎるため、学習率を下げる必要があることです。学習率は、NaN が出現しなくなるまで継続的に低下させることができます。これは、通常、既存の学習率よりも 1 ~ 10 倍低くなります。学習率が理由であるかどうかを除外したい場合は、学習率を直接 0 に設定し、損失にナンが現れるかどうかを観察します。それでも出現する場合、それは学習率の理由ではありません。adam などの適応学習率アルゴリズムをトレーニングに使用した場合でも、過剰な学習率の問題が発生する可能性があり、この種のアルゴリズムには通常、変更可能な学習率のスーパー パラメーターがあることに注意してください。小さな値に。
  6. 勾配が大きすぎるため、更新された値が Nan になります。現在のネットワークが RNN に似た巡回ニューラル ネットワークである場合、シーケンスが比較的長い場合、NaN につながる勾配爆発の問題が発生しやすくなります。効果的な方法は、「勾配クリッピング」(勾配トランケーション) を増やすことです。解決するには) : グラデーションでグラデーション クリッピングを実行し、最大グラデーションを制限します。
  7. 損失を計算する必要がある配列が範囲外です (特に新しいネットワークがカスタマイズされている場合、これが発生する可能性があります)
  8. 指数を含む一部の計算では、最終計算値が INF (無限大) になることがあります (たとえば、他の処理を行わないソフトマックスの分子と分母は exp(x) を計算する必要があり、値が大きすぎるため、最終値は INF になる可能性があります) /INF を実行すると NaN が得られますが、このとき使用するソフトマックスが exp(x) の計算に関連する処理 (最大値の減算など) を行っていることを確認する必要があります。

3. 原因分析と解決策

3.1. 入力データが間違っている(ダーティデータ)

理由:入力データに NaN が含まれているか、使用されているラベルが空であるか、トレーニング サンプルにダーティ データが表示されています。ダーティデータの出現により、ロジットが 0 を計算し、INF が出現し、0 が除数、つまり nan として使用されます。

通常、入力データが正しいことを確認します。一般に、入力が間違っている場合は、すぐにそれを確認できます。検出するのがそれほど簡単ではない状況が 2 つあります。

現象:学習プロセス中にこの間違った入力に遭遇すると、必ず NaN になります。損失を観察していると、損失が徐々に減少していくのに、突然 NaN になるなど、異常が検出できない場合があります

1. トレーニングプロセス中の入力と出力が正しいかどうか、およびナンがあるかどうかに注意を払う必要があります。

デバッグを使用して間違った入力を見つける

2. ラベルが欠落していると、損失が常に nan になるため、ラベルをチェックする必要があります。

3.間違ったデータを徐々に見つけて、データのこの部分を削除します
。batch_size = 1、shuffle = False に設定すると、サンプルはすべてのダーティ データの可能性を段階的に見つけ出し、再編成されたデータ セットが削除されて確実にトレーニングセットと検証 セット内に写真の破損はありません。単純なネットワークを使用して入力を読み取ることができますが、データにエラーがある場合、このネットワークの損失値も表示されます。

4. ニューラル ネットワークでは、最初の数層の入力は正しい可能性が非常に高いですが、特定の層に到達すると、出力は or (負の無限大を表し、存在しない数を表します)naninfなり-infますnan。このとき、デバッグで一つ一つ確認する必要があります。

もちろん、独自のコードに検出関数を追加することもできます。たとえば、Pytorch フレームワークでは、torch.autograd.tect_anomaly クラスを使用して、トレーニングまたは予測中に発生する微妙な問題を監視できます。

>>> import torch
>>> from torch import autograd
>>> class MyFunc(autograd.Function):
...     @staticmethod
...     def forward(ctx, inp):
...         return inp.clone()
...     @staticmethod
...     def backward(ctx, gO):
...         # Error during the backward pass
...         raise RuntimeError("Some error in backward")
...         return gO.clone()
>>> def run_fn(a):
...     out = MyFunc.apply(a)
...     return out.sum()
>>> inp = torch.rand(10, 10, requires_grad=True)
>>> out = run_fn(inp)
>>> out.backward()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/your/pytorch/install/torch/tensor.py", line 93, in backward
        torch.autograd.backward(self, gradient, retain_graph, create_graph)
      File "/your/pytorch/install/torch/autograd/__init__.py", line 90, in backward
        allow_unreachable=True)  # allow_unreachable flag
      File "/your/pytorch/install/torch/autograd/function.py", line 76, in apply
        return self._forward_cls.backward(self, *args)
      File "<stdin>", line 8, in backward
    RuntimeError: Some error in backward
>>> with autograd.detect_anomaly():
...     inp = torch.rand(10, 10, requires_grad=True)
...     out = run_fn(inp)
...     out.backward()
    Traceback of forward call that caused the error:
      File "tmp.py", line 53, in <module>
        out = run_fn(inp)
      File "tmp.py", line 44, in run_fn
        out = MyFunc.apply(a)
    Traceback (most recent call last):
      File "<stdin>", line 4, in <module>
      File "/your/pytorch/install/torch/tensor.py", line 93, in backward
        torch.autograd.backward(self, gradient, retain_graph, create_graph)
      File "/your/pytorch/install/torch/autograd/__init__.py", line 90, in backward
        allow_unreachable=True)  # allow_unreachable flag
      File "/your/pytorch/install/torch/autograd/function.py", line 76, in apply
        return self._forward_cls.backward(self, *args)
      File "<stdin>", line 8, in backward
    RuntimeError: Some error in backward

3.2. 学習率が高すぎる --> 勾配爆発 --> ナン

理由:学習プロセス中に勾配が非常に大きくなり、学習プロセスが通常の軌道から逸脱し、学習プロセスを継続することが困難になります。

理由は簡単で、学習率が高いと毎回の新しい勾配の値に直接影響するため、歩く速度も速くなります。下図のように、学習率が大きすぎるとスムーズに最低点に到達できなくなり、注意しないと制御可能領域を飛び出してしまいます。損失は​​指数関数的に増加します (スパンレベル)。

 さらに、この状況は、ネットワーク層の数が比較的深い場合に発生しやすくなります。gluonからの一節を借用します。

 現象:各反復の損失値を観察すると、反復ごとに損失が大幅に増加し、どんどん大きくなり、最終的には損失値が大きすぎて浮動小数点表現の範囲を超えてしまい、Nan になってしまいます。 。
解決:

1.初期学習率を下げ、適切な学習率と学習率の減衰を少なくとも 1 桁低く設定します
2.勾配クリッピング、過剰な差分を制限するように勾配クリッピングを設定します
3.データの次元が一貫していない場合も勾配が発生しますExplosion 、データ正規化方法 (平均の減算、分散の除算、または BN、L2 ノルムなどの正規化の追加)

5. 各バッチの前に、optimizer.zero_grad() で勾配をゼロにクリアする必要があることに注意してください。
4. モデル内に複数の損失層がある場合は、勾配が爆発する層を見つけて、損失の重みを減らす必要があります。この層

3.3、損失関数が間違っています

理由:損失関数の計算は NaN の出現につながる可能性があります。特に損失関数を自分で設計する場合は、クロスエントロピー損失関数の計算で log(0) が出現する可能性があります。これは初期化の問題である可能性があります。データの問題正規化されていない値を入力により、損失が発生する状況が発生します

ネットワークのトレーニングが一定のレベルに達すると、分類に関するモデルの判断で 0 などの値が生成される場合があり、log(0) 自体は問題なく、-inf は (-inf * 0) を除くほとんどの操作に安全に参加できます。 、NaNが生成されます。NaN の場合、reduce 操作に参加すると結果が台無しになります

現象: トレーニングにより発生する損失を観察すると、最初は異常が見られず、徐々に損失が減少しているのに、突然ナンが出現する

1. 損失関数は、正常であるかどうかを考慮する必要がありますbackward

2. 次に、Tensor計算で同じ型が維持されるように入力型が変換されるかどうか。

3. 最後に、計算の安定性を確保するために、除数に小さな定数を追加することを検討します。

4. エラーを再現し、デバッグのために損失層に出力を追加してみます。エラーが発生する可能性のある場所を見つけてバイアスを追加する

# 源代码
# match wh / prior wh
g_wh = (matched[:, 2:] - matched[:, :2]) / priors[:, 2:]
g_wh = torch.log(g_wh) / variances[1]
# return target for smooth_l1_loss
return torch.cat([g_cxcy, g_wh], 1)  # [num_priors,4]


# 修改后
eps = 1e-5
# match wh / prior wh
g_wh = (matched[:, 2:] - matched[:, :2]) / priors[:, 2:]
g_wh = torch.log(g_wh + eps) / variances[1]
# return target for smooth_l1_loss
return torch.cat([g_cxcy, g_wh], 1)  # [num_priors,4]
y_truth * log(y_predict)      
# when y_truth[i] is 0, it is likely that y_predict[i] would be 0

# 这样的表达式,要考虑对log中的变量进行clip. 比如

safe_log = tf.clip_by_value(some_tensor, 1e-10, 1e100)
bin_tensor * tf.log(safe_log)

3.4. プーリング層のストライドはカーネルのサイズより大きい 

畳み込み層の畳み込みステップが畳み込みカーネルのサイズより大きい場合、次のものが生成される可能性がありますnan

以下の例に示すように、プーリング層で stride > kernel の場合、y に NaN が生成されます。

layer {
  name: "faulty_pooling"
  type: "Pooling"
  bottom: "x"
  top: "y"
  pooling_param {
    pool: AVE
    stride: 5
    kernel: 3
  }
}

3.5、batchNorm はトリックを行う可能性があります

ネットワークbatchNorm内に多数の層、より重要な役割を果たしている場合は、 TensorBatchnorm 層に入った後に変更可能かどうかを適切に確認できますnan。この場合、batchNorm 層の移動平均 (running_mean) と move_mean がvariance (running_var) も両方である可能性が非常に高くnan、予測段階でこれが発生する可能性が非常に高くなります。

この状況は、トレーニング セットと検証セットが 2 つの完全に異なる分布である場合に発生します。これは、トレーニング セットで学習された平均値と手法です。または、ニューラル ネットワークには異なる構造を持つ 2 つの陣営があります: Unet が一般的です。Unet をカスタマイズするときに、エンコード ネットワークとデコード ネットワークが構造に大きな違いがある 2 つのネットワークである場合、エンコード フェーズで学習されてしまいます。問題が発生します。デコード段階中。

実際の例を挙げると、Unet + resnet34 は 正常に動作しますが、Unet + resnext50を使用する と損失爆発が発生します (デコード段階のバッチノルム層が無効になった後は、パフォーマンスは正常になります)。

もちろん、上記の現象の原因のほとんどは、(Pytorch)を使用したmodel.eval()後に発生しました。予測フェーズ中にmodelモデルを次のように設定すると、model.train(True)問題は発生しない可能性があります。

 解決:

または、Batchnorm のパラメーターを設定して、track_running_stats=False移動平均と移動分散を無効にします。

関連問題:
`powx()` を置き換えてバッチノルム層の数値を修正する (pfollmann によるプル リクエスト #5136 BVLC/caffe) GitHub

3.6. シャッフル設定が乱れていませんか?

Suffle とはシャッフルを意味します。データの読み込みフェーズで Shuffle パラメーターを True に設定すると、ニューラル ネットワークがデータを読み取るときに、データはランダムな順序で読み取られます。データが揃ってます

一般に、トレーニング フェーズではシャッフルをオンにし、予測フェーズではシャッフルをオフにします。トレーニング フェーズの各エポックでシャッフルをオンにすると、データを一度完全にランダム化できます (魚のグリルと同様に、魚の向きを高くすることを選択します)頻繁にダウン(シャッフル)するか、一度だけひっくり返し、毎回長時間焼く)ため、トレーニングのロバスト性はシャッフルなしの場合よりわずかに高くなります。

しかし、batch_norm層を使用する場合、データの分布が非常に不規則である場合(shuflleを使用した場合と使用しない場合では、読み取られたデータの順番の情報分布がまったく異なります)、トレーニングフェーズ(shuffleを使用)でトレーニングされたモデルは、予測フェーズで使用する場合(シャッフルを使用しない場合)、データ分布の違いにより、batch_norm層にnanが出現し、異常な損失関数が発生する可能性もあります。

3.7. 長距離ラベルを設定すると NAN が得られます

このモデルはクロスエントロピー損失関数を使っていると理解しているのですが、ラベルが分散しすぎると、例えばラベルが8000のデータの場合、確率分布の値が比較的小さい値、つまり似たような値になってしまいます。 to log( 0) この場合、モデルの損失は Nan です。

4. 本質的な解決策: 本質は、モデル操作プロセス中に入力データの値の範囲を調整することです。

4.1. モデルの重みに正則化を追加してパラメータのサイズを制限する

        モデル重みの初期化方法 Xavier 初期化、Kaiming 初期化

4.2. BatchNormalization をモデルに追加してデータを正規化する

        例えば、入力画像データを255で割って0~1の間のデータに変換したり、平均減算や分散除算、BNやL2ノルムなどの正規化などがあります。

4.3. relu6 関数など、上限のある活性化関数を使用する

pytorch で torch .nn .ReLU6 を使用すると、関数のプロトタイプは min ( max (0, x ),6) になります。つまり、relu 関数の最大値は 6 に制限されます。つまり出力が制限される

4.4. 損失関数の演算前に値の範囲補正を実行する

tf は、clip_by_value 関数を使用して、損失関数の log および exp の前に y_pred の値の範囲を調整し、-logl(0) によって生成される無限大を回避できます。

 pytorch は範囲制限のために torch.clip ( input , min=None , max = None ) または torch.clamp ( input , min=None, max = None ) を使用できます。

import torch.nn as nn
 
outputs = model(data)
loss= loss_fn(outputs, target)
optimizer.zero_grad()
loss.backward()
#nn.utils.clip_grad_value(model.parameters(),clip_value=2)
nn.utils.clip_grad_norm_(model.parameters(), max_norm=20, norm_type=2)
optimizer.step()

4.5. 勾配枝刈りの実行

勾配が継続的に 1 より大きくなり、勾配爆発が発生するのを避けるために、値の範囲を超える勾配を制限します。(グラデーションの消失を回避する方法はありません)
 pytorch は nn.utils.clip_grad_value(parameters, Clip_value) を使用します。すべてのパラメータを [-clip_value,clip_value] にクリップします。たとえば、clip_value =1,[100,0.1]=>[1,0.1]、この操作はグラデーションの方向を変更します
。nn.utils.clip_grad_norm_ を使用して、ノルム サイズに従って正規化します。パラメーター Norm (norm_type) =2 ノルム数) が最大値より大きい場合は、最大値まで減らされます。この方法では、勾配の方向が完全に一貫していることを保証できるため、勾配値が特に小さい値 ([100,0.1]=>[1,0.0001] など) にスケーリングされる可能性があります。

4.6. ResNet または DenseNet 構造の使用

深いレイヤのサンプルスケール値は、スキップ接続を通じて浅いレイヤに渡されます。トレーニングの初期段階では、モデル パラメーターがあまり適切ではない可能性があり、特に lstm や rnn などのネットワークの場合、勾配の消失や爆発が発生します。Nan は数値ではなく、inf は無限大です。たとえば、log は損失関数を見つけるために使用され、入力が 0 に近い場合、結果は inf になります。

5. pytorch 半精度アンプトレーニング nan 問題

5.1、なぜ?

この問題を解決したい場合は、まずその理由を明らかにする必要があります。なぜ全精度トレーニングにはナンがなく、半精度トレーニングにはナンがあるのでしょうか。実際には次の 3 つのケースがあります。

  1. 損失を計算する場合、0で割る状況があります
  2. 損失が大きすぎるため半精度でinfと判定される
  3. ネットワークパラメータに nan がある場合、演算結果も nan を出力します。

ナンレポートのほとんどは 3 番目のケースです。ここでは3について見ていきましょう。状況 3 はどのような状況で発生しますか? このディスカッションは素晴らしい説明を提供します: Nan Loss with torch.cuda.amp および CrossEntropyLoss - #17 by bruceyo - 混合精度 - PyTorch フォーラム

翻訳すると、ce loss または bceloss を使用する場合、対数演算が行われます。半精度の場合、いくつかの非常に小さな値は直接 0 に丸められます。log(0) は何に等しいですか? ——ナンに等しい!したがって、ロジックは理にかなっています。返された勾配は nan になります -> ネットワーク パラメーター nan -> 対数により各ラウンドの出力は nan になります。

5.2、どうやって?

Focal Loss や Cross Entropy などの log() で損失関数を使用する場合、入力テンソルの一部の次元は非常に小さい数になる可能性があります。通常の状況では、float32 は非常に小さい数ですが 0 ではありませんが、If ampは半精度を使用するため、0 を直接取り込む可能性があるため、NAN の問題が発生します。問題が明確に特定されれば、解決策は非常に簡単です。したがって、log 演算に関しては float16 を float32 に変換できます。

x = x.float()
x = torch.sigmoid(x)

5.3. 原因(1)、(2)の分析と解決策

実際、(1) と (2) は解決でき、scaler.step(optimizer)オプティマイザとスケーラーは nan 例外を捕捉するのに役立ちます。しかし、(3) は機能しません。(3) は、一部またはすべてのネットワーク パラメータが nan になったことを意味します。これは、前の勾配を返すプロセスで 0 で除算したことが原因である可能性があります。まず [返された勾配は nan ではない]ため、スケーラーは例外をキャッチしません。次に、半精度の使用により、オプティマイザが [すでに精度の損失は nan の損失になります]、eps がどれだけ追加されても nan は nan のままであるため、オプティマイザは例外を処理できず、最終的にネットワーク パラメーターは nan になります。

したがって、3 はこの記事の冒頭で提案した解決策によってのみ解決できます。実際、ほとんどの分類問題は、半精度が使用される場合の 3 番目のケースで発生し、精度を float32 に変換し直すか、対数を計算するときに少量を追加することによってのみ回避できます (ただし、精度は失われます)。

6. ニューラルネットワークが何も学習できない場合はどうすればよいですか?

Nan やその他の問題が発生していない、または解決されていない可能性があります。ネットワークは正常にトレーニングされていますが、コストが削減できません。予測すると、結果が異常になります。

  1. トレーニング セットのコスト値とテスト セットのコスト値の変化傾向を出力してください。通常、トレーニング セットのコスト値は減少し続け、最終的に横ばいになるか、わずかに変動するはずです。テスト セットのコスト値が最初に低下し、その後ショックまたはゆっくりと上昇し始めます。トレーニングセットのコスト値が下がらない場合は、コードにバグがある可能性があります、データに問題がある可能性があります(データ自体の問題、データ処理の問題など)、ハイパーパラメータ(ネットワークサイズなど)がある可能性があります、層数、学習率など)設定が無理があります。手動でデータを10個構築して、ニューラルネットワークで繰り返し学習させてコストが下がるかどうかを確認し、下がらなければインターネットを使用することも可能です。ネットワークのコードにバグがあるため、注意深くチェックする必要があります。コスト値が低下した場合は、これら 10 個のデータに対して予測を行って、結果が期待どおりかどうかを確認します。その場合、ネットワーク自体は正常である可能性が非常に高いです。次に、ハイパーパラメータとデータに問題があるかどうかを確認してください。
  2. ニューラル ネットワーク コードをすべて自分で実装する場合は、勾配チェックを行うことを強くお勧めします。勾配計算にエラーがないことを確認してください。
  3. 最初に最も単純なネットワークで実験を開始します。コスト値だけを見るだけでなく、ニューラル ネットワークの予測出力がどのようなものかを調べて、期待どおりの結果が得られるかどうかも確認します。たとえば、言語モデルの実験を行う場合、最初は RNN の層を使用し、RNN の層が正常であれば、次に LSTM を試し、さらに多層 LSTM を試します。
  4. 可能であれば、指定されたデータを入力し、各ステップの正しい出力結果を自分で計算し、ニューラル ネットワークの各ステップの結果が同じであるかどうかを確認できます。

参考記事:

警告!ロスがナンか超大型の理由 - オルドパンの個人ブログ

Deep learning_dddeee のコラムの nan と inf の解決策 - CSDN blog_nan と inf

pytorch 半精度アンプトレーニングの nan 問題を解決する - プログラマーが求めた

モデル学習ロスがNANになる原因の解決策 - Knowledge

おすすめ

転載: blog.csdn.net/ytusdc/article/details/122321907