ネットワークをトレーニングするとき、時々警告が出ます:
_W0722 11:47:35.101842 140641577297728 optimizer_v2.py:928] Gradients does not exist for variables ['model/conv1d_x/Variable:0'] when minimizing the loss.
_
これは、まれに(20回の成功ステップごとに1回)散発的に発生します。私のモデルには基本的に、ネットワークのさまざまな位置で連結によって結合する2つのパスがあります。これを説明するために、ここに私が意味することの簡単な例を示します。
_class myModel(tf.keras.Model):
def __init__(self):
self.conv1 = Conv2D(32)
self.conv2 = Conv2D(32)
self.conv3 = Conv2D(16)
def call(self, inputs):
net1 = self.conv1(inputs)
net2 = self.conv2(inputs)
net = tf.concat([net1, net2], axis=2)
net = self.conv3(net)
end_points = tf.nn.softmax(net)
model = myModel()
with tf.GradientTape() as tape:
predicition = model(image)
loss = myloss(labels, prediction)
gradients = tape.gradient(loss, model.trainable_variables)
optimizer.apply_gradients(Zip(gradients, model.trainable_variables))
_
実際には、私のネットワークははるかに大きくなりますが、一般的に勾配を持たない変数は、ネットワークの一番上にあるものになる傾向があります。各_Conv2D
_レイヤーの前に、カスタムグラデーションもあります。エラーが発生したときに、そのレイヤーのグラデーション関数が呼び出されていないことに気付く場合があります。
私の質問は、ネットワークを逆方向に伝播するときに、グラデーションテープが異なるパスのように見えることがあるのですが、どうすればよいのでしょうか。私の2番目の質問は、これは私のネットワークを介して2つの別々のルート(つまり、conv1とconv2)を持っていることが原因です。このネットワークアーキテクチャに根本的な欠陥はありますか?
理想的には、GradientTape()
に対して、最上位の各レイヤーのグラデーションを見つける必要があると定義できますか?
同じような問題がありました。ネットワークが実際にどのように見えるかによっては役立つかわからない場合がありますが、基本的にはマルチ出力ネットワークがあり、出力に対応する勾配を個別に適用しているので、個別の損失ごとに、勾配がゼロであるネットワークの分岐がありましたが、これは完全に有効であり、毎回非ターゲット出力の直前のターミナルレイヤーに対応していました。このため、Noneグラデーションをtf.zeros_likeに置き換えることになり、トレーニングを続行することができました。常にグラフの上部にある場合、ネットワークへの複数の入力ヘッドで同じ問題がありますか?
(以下のNguyễnThuによるETAソリューションは、上記で説明しているもののコードバージョンです-私がそれを扱ったのとまったく同じ方法です)
テンソルはデフォルトで監視されていないため、勾配が計算されなかった他の回答を見ました。それらを追加する必要がありますが、model.trainable_variablesまたはおそらくmyLoss関数のみを処理する必要があるため、問題ではないようです散発的な性質を説明するNaN結果を取得するか、時々numpy配列にキャストします。これは散発的な性質を説明します(たとえば、データが非常に不均衡な場合、少数派クラスのインスタンスを持たないバッチにある可能性があります)。
私も同じ問題を抱えていました。グラデーションをカスタマイズしたソリューションを見つけました
def _compute_gradients(tensor, var_list):
grads = tf.gradients(tensor, var_list)
return [grad if grad is not None else tf.zeros_like(var)
for var, grad in Zip(var_list, grads)]