我正在尝试训练UNet,但由于某种原因,我得到以下错误:
Traceback (most recent call last):
File "<ipython-input-54-b56497e81356>", line 1, in <module>
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=opt.learning_rate), loss=dice_coef_loss, metrics=[dice_coef])
File "C:Users...Anaconda3envsgpucondalibsite-packagestensorflowpythonkerasenginetraining.py", line 537, in compile
with self.distribute_strategy.scope():
File "C:Users...Anaconda3envsgpucondalibsite-packagestensorflowpythonkerasenginetraining.py", line 682, in distribute_strategy
return self._distribution_strategy or ds_context.get_strategy()
AttributeError: 'UNet' object has no attribute '_distribution_strategy'
我已经寻找了多个答案,其中一个是将keras
替换为tf.keras
,但错误仍然出现。另一个答案是它与TensorBoard有关,所以我删除了TensorBoard回调,但这也没有修复它。
这是我的模型:
import tensorflow as tf
class UNet(tf.keras.Model):
def __init__(self, img_shape=(256,256,256), num_class=1):
print ('build UNet ...')
self.img_shape = img_shape+(1,)
self.num_class = num_class
def get_crop_shape(self, target, refer):
# depth, the 4th dimension
cd = (target.get_shape()[3] - refer.get_shape()[3])
assert (cd >= 0)
if cd % 2 != 0:
cd1, cd2 = int(cd//2), int(cd//2) + 1
else:
cd1, cd2 = int(cd//2), int(cd//2)
# width, the 3rd dimension
cw = (target.get_shape()[2] - refer.get_shape()[2])
assert (cw >= 0)
if cw % 2 != 0:
cw1, cw2 = int(cw//2), int(cw//2) + 1
else:
cw1, cw2 = int(cw//2), int(cw//2)
# height, the 2nd dimension
ch = (target.get_shape()[1] - refer.get_shape()[1])
assert (ch >= 0)
if ch % 2 != 0:
ch1, ch2 = int(ch//2), int(ch//2) + 1
else:
ch1, ch2 = int(ch//2), int(ch//2)
return (ch1, ch2), (cw1, cw2), (cd1, cd2)
def __call__(self, inputs):
concat_axis = 4
conv1 = tf.keras.layers.Conv3D(8, (3, 3, 3), activation='relu', padding='same', name='conv1_1')(inputs)
conv1 = tf.keras.layers.Conv3D(8, (3, 3, 3), activation='relu', padding='same')(conv1)
pool1 = tf.keras.layers.MaxPooling3D(pool_size=(2, 2, 2))(conv1)
conv2 = tf.keras.layers.Conv3D(16, (3, 3, 3), activation='relu', padding='same')(pool1)
conv2 = tf.keras.layers.Conv3D(16, (3, 3, 3), activation='relu', padding='same')(conv2)
up_conv1 = tf.keras.layers.UpSampling3D(size=(2, 2, 2))(conv2)
ch, cw, cd = self.get_crop_shape(conv1, up_conv1)
crop_conv1 = tf.keras.layers.Cropping3D(cropping=(ch,cw,cd))(conv1)
up1 = tf.keras.layers.concatenate([up_conv1, crop_conv1], axis=concat_axis)
conv3 = tf.keras.layers.Conv3D(8, (3, 3, 3), activation='relu', padding='same')(up1)
conv3 = tf.keras.layers.Conv3D(8, (3, 3, 3), activation='relu', padding='same')(conv3)
ch, cw, cd = self.get_crop_shape(inputs, conv3)
conv3 = tf.keras.layers.ZeroPadding3D(padding=((ch[0], ch[1]), (cw[0], cw[1]), (cd[0], cd[1])))(conv3)
conv4 = tf.keras.layers.Conv3D(self.num_class, (1, 1, 1), activation="sigmoid")(conv3)
return conv4
我是这样训练它的:
# Initialize the model
model = UNet(img_shape=opt.img_shape, num_class=opt.num_class)
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=opt.learning_rate), loss=dice_coef_loss, metrics=[dice_coef])
callbacks = [
tf.keras.callbacks.ModelCheckpoint(os.path.join(opt.checkpoint_path, "UNet.{epoch:02d}-{val_loss:.3f}.hdf5")),
tf.keras.callbacks.TensorBoard(log_dir=opt.log_dir, histogram_freq=1, write_graph=True, write_images=True, update_freq='epoch')
]
# Train the model, doing validation at the end of each epoch.
model.fit(trainDataset, epochs=opt.epoch, validation_data=testDataset, callbacks=callbacks)
我没有使用分销策略。我使用python 3.7.9版本和tensorflow 2.3.0版本。
有人能帮我一下吗?谢谢!
幸运的是,我找到了答案。我忘了把tensorflow的超类叫做keras模型;我只需要将
super(MyModel, self).__init__()
添加到__init__()
函数中。
所以我的模型现在是这样的:
class UNet(tf.keras.Model):
def __init__(self, img_shape=(256,256,256), num_class=1):
super(UNet, self).__init__()
print ('build UNet ...')
self.img_shape = img_shape
self.num_class = num_class
...
https://www.tensorflow.org/api_docs/python/tf/keras/Model
!pip install -q tensorflow==2.2
!pip install -q keras==2.3.1
绝对可以解决这个问题,享受吧;)