I am using .npy
files, the masks are all 140MB with dimesions (240, 240, 160, 4) and the images are 70MB with dimesions (240. 240, 160, 1). I am using a data generator because the images are 3D and are quite large, but I can’t figure out why the RAM is consumed so quick.
Given my calculations (probably wrong) this is what every image consumes:
240 * 240 * 160 * 1 * 4 bytes = 29,491,200 bytes = ~28.125 MB
240 * 240 * 160 * 4 * 4 bytes = 117,964,800 bytes = ~112.5 MB
Here my model (3D Unet):
# Convolutional Block
def conv_block(inputs, num_filters):
x = Conv3D(num_filters, (3, 3, 3), padding = "same")(inputs)
x = BatchNormalization()(x)
x = Activation("relu")(x)
x = Conv3D(num_filters, (3, 3, 3), padding = "same")(x)
x = BatchNormalization()(x)
x = Activation("relu")(x)
return x
# Encoder Block
def encoder_block(inputs, num_filters):
x = conv_block(inputs, num_filters)
p = MaxPool3D((2, 2, 2), padding="same")(x)
return x, p
# Decoder Block
def decoder_block(inputs, skip, num_filters):
x = Conv3DTranspose(num_filters, (2, 2, 2), strides=2, padding="same")(inputs)
x = Concatenate()([x, skip])
x = conv_block(x, num_filters)
return x
# UNET
def unet(input_shape):
inputs = Input(input_shape)
"----ENCODER----"
s1, p1 = encoder_block(inputs, 16)
s2, p2 = encoder_block(p1, 32)
s3, p3 = encoder_block(p2, 64)
s4, p4 = encoder_block(p3, 128)
"----BRIDGE---"
b1 = conv_block(p4, 256)
"----DECODER----"
d1 = decoder_block(b1, s4, 128)
d2 = decoder_block(d1, s3, 64)
d3 = decoder_block(d2, s2, 32)
d4 = decoder_block(d3, s1, 16)
outputs = Conv3D(4, 1, padding="same", activation="softmax")(d4)
model = Model(inputs, outputs, name="UNET")
return model
# Input shape has to be divisible by 2**4 = 16
# Original input shape is (240, 240, 155) but an interpolation was done
# After the interpolation, we divided the images in patches
test_input_shape = (240, 240, 160, 1)
test_model = unet(test_input_shape)
test_optimizer = Adam(learning_rate=0.0001)
test_model.compile(optimizer=test_optimizer, loss=dice_loss, metrics=metrics)
And here is the data generator:
def data_generator(nifti_files, mask_files):
for nifti_file, mask_file in zip(nifti_files, mask_files):
nifti_image = np.load(nifti_file)
nifti_mask = np.load(mask_file)
yield (nifti_image, nifti_mask)
# Create datasets
dataset = tf.data.Dataset.from_generator(
lambda: data_generator(train_volumes, train_masks),
output_signature=(
tf.TensorSpec(shape=(240, 240, 160, 1), dtype=tf.float32),
tf.TensorSpec(shape=(240, 240, 160, 4), dtype=tf.float32)
)
)
dataset_val = tf.data.Dataset.from_generator(
lambda: data_generator(val_volumes, val_masks),
output_signature=(
tf.TensorSpec(shape=(240, 240, 160, 1), dtype=tf.float32),
tf.TensorSpec(shape=(240, 240, 160, 4), dtype=tf.float32)
)
)
# Batch and prefetch
dataset = dataset.batch(1).prefetch(tf.data.experimental.AUTOTUNE)
dataset_val = dataset_val.batch(1).prefetch(tf.data.experimental.AUTOTUNE)