如何加载 CNN 保存的具有(无)输入形状的模型

问题描述 投票:0回答:1

我正在使用 CNN 和 TensorFlow 开展 3D 图像分类和检测项目。该模型在 3D 图像上进行训练,每个图像的大小为 (31,31,31,1),但我使模型输入形状具有可变大小,在输入形状中指定为

None
,因为我想要模型在滑动窗口期间接受任何形状。这对于分类来说效果很好,但是当我在滑动窗口方法中应用经过训练的模型来检测较大图像时遇到了一个问题。

培训代码(摘要):


model = Sequential([
    layers.Conv3D(filters=16, kernel_size=3, padding='same'),
    layers.LeakyReLU(),
    layers.BatchNormalization(),
    layers.Conv3D(filters=16, kernel_size=3, padding='same'),
    layers.LeakyReLU(),
    layers.BatchNormalization(),
    layers.MaxPool3D(pool_size=2),
    layers.BatchNormalization(),

    layers.Conv3D(filters=32, kernel_size=3, padding='same'),
    layers.LeakyReLU(),
    layers.BatchNormalization(),
    layers.Conv3D(filters=32, kernel_size=3, padding='same'),
    layers.LeakyReLU(),
    layers.BatchNormalization(),
    layers.MaxPool3D(pool_size=2),
    layers.BatchNormalization(),

    layers.Conv3D(filters=64, kernel_size=3, padding='same'),
    layers.LeakyReLU(),
    layers.BatchNormalization(),
    layers.Conv3D(filters=64, kernel_size=3, padding='same'),
    layers.LeakyReLU(),
    layers.BatchNormalization(),
    layers.MaxPool3D(pool_size=2),
    layers.BatchNormalization(),

    layers.Conv3D(filters=128, kernel_size=3, padding='same'),
    layers.LeakyReLU(),
    layers.BatchNormalization(),
    layers.Conv3D(filters=128, kernel_size=3, padding='same'),
    layers.LeakyReLU(),
    layers.BatchNormalization(),
    layers.MaxPool3D(pool_size=2),
    layers.BatchNormalization(),

    layers.GlobalAveragePooling3D(),
    layers.Dense(units=256),
    layers.LeakyReLU(),
    layers.BatchNormalization(),
    layers.Dropout(0.4),
    layers.Dense(units=1, activation="sigmoid"),
])

train_gen = DataGenerator(train_data, train_labels, base_dir, (31, 31, 31), batch_size=batch_size, shuffle=False)
test_gen = DataGenerator(val_data, val_labels, base_dir, (31, 31, 31), batch_size=batch_size, shuffle=False)

cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_path,
                                                 verbose=1)


log_dir="/project/checkpoints/cleancode/"+ datetime.now().strftime("%Y%m%d-%H%M%S")
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)
csv_logger = tf.keras.callbacks.CSVLogger('/project/checkpoints/cleancode/cleancode.csv')

model.compile(optimizer=opt,
              loss = tf.keras.losses.BinaryFocalCrossentropy(gamma=5, apply_class_balancing=True),
              metrics=['accuracy', BalancedAccuracy(), 'AUC',tf.keras.metrics.AUC(curve='PR',name='AUC_PR'), tfa.metrics.F1Score(num_classes=1, threshold=0.5), tf.keras.metrics.SpecificityAtSensitivity(0.5), 'Precision', 'Recall',
                        'TruePositives', 'FalsePositives', 'TrueNegatives','FalseNegatives'])
model.build(input_shape= (128,None,None,None,1))
model.summary()

history = model.fit(train_gen, validation_data = test_gen, epochs=epochs, shuffle = False , verbose = 1 ,
                    callbacks = [csv_logger, tensorboard_callback, cp_callback],
use_multiprocessing = True, workers=10)

model.save("cleancode.keras")

滑动窗口代码(总结):

model = tf.keras.models.load_model('/project/cleancode.keras',compile=False,custom_objects={"BalancedAccuracy": BalancedAccuracy(), "F1Score": tfa.metrics.F1Score(num_classes=1, threshold=0.5)})

错误信息:

Traceback (most recent call last):
  File "/home/mustafa/.local/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 3553, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-2-9c04782baac6>", line 1, in <cell line: 1>
    runfile('/home/mustafa/project/sliding_single_novoxel.py', wdir='/home/mustafa/project/')
  File "/home/mustafa/.pycharm_helpers/pydev/_pydev_bundle/pydev_umd.py", line 197, in runfile
    pydev_imports.execfile(filename, global_vars, local_vars)  # execute the script
  File "/home/mustafa/.pycharm_helpers/pydev/_pydev_imps/_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "/home/mustafa/project/sliding_single_novoxel.py", line 103, in <module>
    model = tf.keras.models.load_model('/home/mustafa/project/cleancode.keras',compile=False,custom_objects={"BalancedAccuracy": BalancedAccuracy(), "F1Score": tfa.metrics.F1Score(num_classes=1, threshold=0.5)})
  File "/home/mustafa/.local/lib/python3.9/site-packages/keras/utils/traceback_utils.py", line 70, in error_handler
    raise e.with_traceback(filtered_tb) from None
  File "/home/mustafa/.local/lib/python3.9/site-packages/keras/layers/convolutional/base_conv.py", line 409, in _get_input_channel
    raise ValueError(
ValueError: The channel dimension of the inputs should be defined. The input_shape received is (None, None, None, None, None), where axis -1 (0-based) is the channel dimension, which found to be `None`.

尽管在训练期间将输入形状设置为接受可变大小的图像,但滑动窗口检测脚本在加载和使用模型时会失败,因为通道尺寸未定义。

如何修改滑动窗口检测代码中的加载来解决此问题,确保模型在检测期间接受可变大小的子体积?

tensorflow deep-learning conv-neural-network
1个回答
0
投票

问题已通过使用解决了

model.load_weights('path to model')

首先我重新创建模型并构建它,然后将权重加载到其中。

我认为这是因为我使用 TensorFlow 检查点来保存模型

cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_path,
                                                 verbose=1)

但是我不知道为什么当我用

保存模型时会出现同样的问题
model.save("cleancode.keras")

另外,我可以使用 .load_weights 加载它

© www.soinside.com 2019 - 2024. All rights reserved.