Keras ニューラル ネットワークをクラス オブジェクトにラップしようとしています。以下をクラス設定の外で実装しましたが、これをよりオブジェクトフレンドリーにしたいと考えています。
要約すると、私のモデルはシーケンシャル モデルを作成する関数 sequence_model を呼び出します。コンパイル ステップ内で、逐次モデルに実装する独自の損失関数 Weighted_categorical_crossentropy を定義しました。
ただし、以下のコードを実行すると、次のエラーが発生します: ValueError: No gradients provided for any variable:
シーケンシャルで使用するために Weighted_categorical_crossentropy 関数を定義する方法に問題があるのではないかと思われます。
繰り返しになりますが、私は非オブジェクト指向の方法でこの作業を行うことができました。ご協力をよろしくお願いいたします。
from tensorflow.keras import Sequential, backend as K
class MyNetwork():
def __init__(self, file, n_output=4, n_hidden=20, epochs=3,
dropout=0.10, batch_size=64, metrics = ['categorical_accuracy'],
optimizer = 'rmsprop', activation = 'softmax'):
[...] //Other Class attributes
def model(self):
self.model = self.sequential_model(False)
self.model.summary()
def sequential_model(self, val):
K.clear_session()
if val == False:
self.epochs = 3
regressor = Sequential()
#regressor.run_eagerly = True
regressor.add(LSTM(units = self.n_hidden, dropout=self.dropout, return_sequences = True, input_shape = (self.X.shape[1], self.X.shape[2])))
regressor.add(LSTM(units = self.n_hidden, dropout=self.dropout, return_sequences = True))
regressor.add(Dense(units = self.n_output, activation=self.activation))
self.weights = np.array([0.025,0.225,0.78,0.020])
regressor.compile(optimizer = self.optimizer, loss = self.weighted_categorical_crossentropy(self.weights), metrics = [self.metrics])
regressor.fit(self.X, self.Y*1.0,batch_size=self.batch_size, epochs=self.epochs, verbose=1, validation_data=(self.Xval, self.Yval*1.0))
return regressor
def weighted_categorical_crossentropy(self, weights):
weights = K.variable(weights)
def loss(y_true, y_pred):
y_pred /= K.sum(y_pred, axis=-1, keepdims=True)
y_pred = K.clip(y_pred, K.epsilon(), 1 - K.epsilon())
loss = y_true * K.log(y_pred) * weights
loss = -K.sum(loss, -1)
return loss
------------------------
上記のコードにはいくつかの問題がありますが、最も注目すべき問題は、weighted_categorical_crossentropy からの損失を返さないことです。次のようになります。
def weighted_categorical_crossentropy(self, weights):
weights = K.variable(weights)
def loss(y_true, y_pred):
y_pred /= K.sum(y_pred, axis=-1, keepdims=True)
y_pred = K.clip(y_pred, K.epsilon(), 1 - K.epsilon())
loss = y_true * K.log(y_pred) * weights
loss = -K.sum(loss, -1)
return loss
return loss # Return the callable function!
エラーは「ValueError: No gradients provided for any variable」です。これは、損失メソッドが何も返さず、None を返すためです。 loss=None を指定してメソッドを近似しようとすると、モデルには勾配を計算する方法がないため、まったく同じエラーがスローされます。
次は、非反復レイヤーの直前のレイヤーで return_sequences = True を使用していることです。これにより、形状が正しくないデータに対して Dense レイヤーが呼び出される原因になります。■ 反復レイヤーにのみ適しています。そのように使用しないでください。
return_sequences = True を使用する正当な理由がある場合は、次のような Dense レイヤーを追加する必要があります。
model.add(keras.layers.TimeDistributed(keras.layers.Dense(...)))
これにより、Dense レイヤーはタイム ステップごとに出力シーケンスに個別に作用します。これは、y_true が適切な形状でなければならないことも意味します。
定義したカスタム損失関数には他にも問題がある可能性がありますが、入出力の形状を推定できないため、それを実行して機能するかどうかを確認する必要があります。おそらく行列乗算の形状の不一致が存在する可能性があります。
最後に、サブクラス化 API の使用について考えてみましょう。操作を書きやすくすることはできますか?
読んでいただきありがとうございます。情報が入手でき次第、この回答を更新します。乾杯。
8
1
明らかな論理エラーをご指摘いただきありがとうございます。また、徹底的なご回答に感謝いたします。 2 番目の点に関して、y_true の出力は n X 時間 X クラス行列 (この場合: n X 20 X 4) です。したがって、n_hidden のサイズが 20 であり、n_output が 4 つの異なるクラスである理由です。 20 の非表示サイズは、20 の連続モデリング期間 (n ごとの順序) を意味するため、上記の点から、あなたが述べたように密なレイヤーを定義する必要があるように見えます。 3 番目の点については、サブクラスを調べる必要がありますNG API。もう一度感謝します。可能であれば、おいしいキンカリをご馳走したいと思います。
– ジョシュ
2020 年 9 月 7 日 13:41
1
よろしくお願いします@ジョシュ。お役に立ててうれしいです。また、そのクニカリについては、もしあなたがいつかジョージアを訪れることに決めたら、喜んで地元のサクヒンクル (サキンクルが提供される場所の名前) にご招待します。乾杯。 :)
– トルニケオ
2020 年 9 月 7 日 14:59
1
それは時間の問題です。妻はポティ出身で、できるだけ早くバフマロを訪れるように指示されています :D
– ジョシュ
2020 年 9 月 7 日 15:28
@tornikeo さん、元気でいてね。あなたはこの分野で私が知っている専門家のような人です。私の ANN の質問のもう 1 つを見ていただければ幸いです: stackoverflow.com/questions/65067446/…
– ジョシュ
2020 年 11 月 30 日 2:39
1
こんにちは @Josh 元気です。元気ですか?今日はいくつか用事があるので、時間ができたらすぐにあなたの質問に答えたいと思います。すでにブックマークしました。
– トルニケオ
2020 年 11 月 30 日 11:40