在Keras模型weighta上执行np.isnan失败,并出现TypeError:输入类型不支持ufunc'isnan'

时间:2020-11-12 15:10:00

标签: python tensorflow keras

团队:

我正在编写一个自定义的回调函数,以在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)

1 个答案:

答案 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