团队:
我正在编写一个自定义的回调函数,以在Keras模型权重中存在NaN值时停止终止模型。
import numpy as np
class TerminateNaN(tf.keras.callbacks.Callback):
def on_epoch_end(self, epoch, logs={}):
mod_weights = np.asarray(model.get_weights())
if mod_weights is not None:
if np.isnan(mod_weights):
print("Invalid weight and terminated at epoch {}".format(epoch))
self.model.stop_training = True
# mod_weights = np.asarray(model.get_weights())
# print(f"Type of weights {type(mod_weights)}")
# # print(f"Type of weights {type(mod_weights)}")
# print(f"Weights:::: {mod_weights}")
模式:
%mkdir model_save
input_layer = Input(shape=(2))
layer1 = Dense(32,activation='tanh',kernel_initializer=tf.random_uniform_initializer(0,1,seed=30))(input_layer)
layer2 = Dense(28,activation='tanh',kernel_initializer=tf.random_uniform_initializer(0,1,seed=30))(layer1)
layer3 = Dense(16,activation='tanh',kernel_initializer=tf.random_uniform_initializer(0,1,seed=30))(layer2)
layer4 = Dense(8,activation='tanh',kernel_initializer=tf.random_uniform_initializer(0,1,seed=30))(layer3)
layer5 = Dense(4,activation='tanh',kernel_initializer=tf.random_uniform_initializer(0,1,seed=30))(layer4)
output = Dense(2,activation='softmax',kernel_initializer=tf.random_uniform_initializer(0,1,seed=30))(layer5)
model = Model(inputs=input_layer,outputs=output)
terminateNAN = TerminateNaN()
optimizer = tf.keras.optimizers.SGD(learning_rate=0.1,momentum=0.9)
model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(X_train,Y_train,epochs=3, validation_data=(X_test,Y_test), batch_size=16 ,callbacks=[terminateNAN])
我已经将get_weights()的输出拼写为numpy数组。但是我看到以下错误:
TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
进行了一些研究,发现isnan
仅适用于numpy本机浮点类型,不适用于对象类型。但就我而言,值确实是float32,如下所示:
Type of weights <class 'numpy.ndarray'>
Weights:::: [array([[-9.7659566e-03, 8.8743661e-03, ....]],dtype=float32)
答案 0 :(得分:1)
如果我对您的理解正确,则您正在尝试检查模型的权重是否为NaN。函数get_weights()返回numpy数组的列表。每个阵列可以具有不同的尺寸,具体取决于每层中输入和节点的数量。所以我不确定当您将此列表转换为numpy数组时会发生什么。我试图做同样的事情,并得到了相同的TypeError。
如果您仅想知道您的体重中是否存在NaN,我建议以下几点:
np.any([np.any(np.isnan(x)) for x in mdl.get_weights()])
如果重量为NaN,则返回True。否则它将返回False。
因此在您的代码中,它看起来像:
import numpy as np
class TerminateNaN(tf.keras.callbacks.Callback):
def on_epoch_end(self, epoch, logs={}):
mod_weights = model.get_weights()
if mod_weights is not None:
if np.any([np.any(np.isnan(x)) for x in mod_weights]):
print("Invalid weight and terminated at epoch {}".format(epoch))
self.model.stop_training = True