Выполняя 3D U-net, я получаю совершенно разные показатели при каждом выполнении, иногда >99,99% по точности, полноте, DI ⇐ Python

Программы на Python
Anonymous
Выполняя 3D U-net, я получаю совершенно разные показатели при каждом выполнении, иногда >99,99% по точности, полноте, DI

Сообщение Anonymous »

Я создал специальную 3D-сеть U-Net для многоклассовой семантической сегментации. В настоящее время я использую его для классификации медицинских изображений, где присутствуют только два класса. У меня есть две взаимосвязанные проблемы: при каждом обучении я получаю совершенно разные оценки по метрикам, и иногда эти оценки составляют> 99,99%. Даже когда я выполняю один и тот же код с одними и теми же входными данными, мне не удается получить последовательные результаты.
Если точнее, я получаю три разных типа оценок каждый раз, когда запускаю обучение. :
  • Очень сильная первая эпоха, остальные быстро набрали >99,99% баллов.
  • Очень слабая первая эпоха эпоха (99,99% баллов.
  • Нормальная первая эпоха (от 60% до 80%, в зависимости от показателя), которая немного улучшается во время обучения .
Эти результаты появляются в обучающих, проверочных и тестовых наборах, поэтому я не думаю, что переоснащение является проблемой. Кроме того, когда я прогнозирую маски на основе исходных данных, я даже не близок к получению хороших результатов (как и следовало ожидать при показателе 99,99%). В заключение отметим, что большинство метрик, которые я использую, являются предопределенными метриками Keras/TensorFlow.
Я не уверен, какая дополнительная информация может потребоваться, чтобы понять, что здесь происходит, но если вы можете мне помочь, буду очень признателен. В частности, я хочу:
  • Понять, почему результаты так сильно различаются.
  • Понять, почему результаты достигают 99,99 %. когда производительность сегментации не так хороша.
Спасибо за любую помощь.
Весь код Unet можно найти в следующем блоке
''' 3D U-net for binary semantic segmentation'''

import numpy as np
from sklearn.model_selection import train_test_split
import os
import numpy as np
from tensorflow.keras.utils import to_categorical
import tensorflow as tf
from tensorflow.keras.layers import Input, Conv3D, MaxPooling3D, Conv3DTranspose, concatenate, BatchNormalization, ReLU, Dropout, UpSampling3D
from tensorflow.keras.metrics import IoU
from tensorflow.keras.models import Model
from tensorflow.keras import backend as K

# Custom Dice coefficient metric
def dice_coefficient(y_true, y_pred):
y_true_f = K.flatten(y_true)
y_pred_f = K.flatten(y_pred)
intersection = K.sum(y_true_f * y_pred_f)
return (2. * intersection + 1) / (K.sum(y_true_f) + K.sum(y_pred_f) + 1)

# Custom IoU metric
def iou_metric(y_true, y_pred):
y_true_f = K.flatten(y_true)
y_pred_f = K.flatten(y_pred)
intersection = K.sum(y_true_f * y_pred_f)
union = K.sum(y_true_f) + K.sum(y_pred_f) - intersection
return (intersection + 1) / (union + 1)

# U-net model for 64x64x64 images using the first custom architecture
def UNET_64x64x64_custom1(input_shape, n_classes):
inputs = Input(input_shape)

# Encoding path
c1 = Conv3D(32, (3, 3, 3), activation='relu', padding='same')(inputs)
c1 = Dropout(0.1)(c1)
c1 = Conv3D(32, (3, 3, 3), activation='relu', padding='same')(c1)
p1 = MaxPooling3D((2, 2, 2))(c1)

c2 = Conv3D(64, (3, 3, 3), activation='relu', padding='same')(p1)
c2 = Dropout(0.1)(c2)
c2 = Conv3D(64, (3, 3, 3), activation='relu', padding='same')(c2)
p2 = MaxPooling3D((2, 2, 2))(c2)

c3 = Conv3D(128, (3, 3, 3), activation='relu', padding='same')(p2)
c3 = Dropout(0.2)(c3)
c3 = Conv3D(128, (3, 3, 3), activation='relu', padding='same')(c3)
p3 = MaxPooling3D((2, 2, 2))(c3)

c4 = Conv3D(256, (3, 3, 3), activation='relu', padding='same')(p3)
c4 = Dropout(0.2)(c4)
c4 = Conv3D(256, (3, 3, 3), activation='relu', padding='same')(c4)
p4 = MaxPooling3D((2, 2, 2))(c4)

# Bottleneck
c5 = Conv3D(512, (3, 3, 3), activation='relu', padding='same')(p4)
c5 = Dropout(0.3)(c5)
c5 = Conv3D(512, (3, 3, 3), activation='relu', padding='same')(c5)

# Decoding path
u6 = UpSampling3D((2, 2, 2))(c5)
u6 = concatenate([u6, c4])
c6 = Conv3D(256, (3, 3, 3), activation='relu', padding='same')(u6)
c6 = Dropout(0.2)(c6)
c6 = Conv3D(256, (3, 3, 3), activation='relu', padding='same')(c6)

u7 = UpSampling3D((2, 2, 2))(c6)
u7 = concatenate([u7, c3])
c7 = Conv3D(128, (3, 3, 3), activation='relu', padding='same')(u7)
c7 = Dropout(0.2)(c7)
c7 = Conv3D(128, (3, 3, 3), activation='relu', padding='same')(c7)

u8 = UpSampling3D((2, 2, 2))(c7)
u8 = concatenate([u8, c2])
c8 = Conv3D(64, (3, 3, 3), activation='relu', padding='same')(u8)
c8 = Dropout(0.1)(c8)
c8 = Conv3D(64, (3, 3, 3), activation='relu', padding='same')(c8)

u9 = UpSampling3D((2, 2, 2))(c8)
u9 = concatenate([u9, c1])
c9 = Conv3D(32, (3, 3, 3), activation='relu', padding='same')(u9)
c9 = Dropout(0.1)(c9)
c9 = Conv3D(32, (3, 3, 3), activation='relu', padding='same')(c9)

outputs = Conv3D(n_classes, (1, 1, 1), activation='softmax')(c9)

model = Model(inputs=[inputs], outputs=[outputs])
return model

def custom_weighted_categorical_crossentropy(weights):
weights = K.variable(weights)

def loss(y_true, y_pred):
y_pred = K.clip(y_pred, K.epsilon(), 1 - K.epsilon())
y_pred /= K.sum(y_pred, axis=-1, keepdims=True)
cce = y_true * K.log(y_pred)
weighted_cce = cce * weights
return -K.sum(weighted_cce, axis=-1)

return loss

def main():
# Parameters model
input_shape = (64, 64, 64, 3)
architecture = UNET_64x64x64_custom1
epochs = 1
batch_size = 4
# Parameters input
input_dir = "data/Input"
img_file = "ADCs.npy"
mask_file = "Masks.npy"
# Parameters output
output_dir = 'output'
model_name = "output/model.h5"
# Binary classification
n_classes=2

# Read files
if not os.path.exists(output_dir):
os.makedirs(output_dir)
input_img = np.load(os.path.join(input_dir, img_file))
input_mask = np.load(os.path.join(input_dir, mask_file))

# Combine the first two dims to get N images
train_img = np.stack((input_img,)*3, axis=-1)
# Images to three channels.
train_mask = np.expand_dims(input_mask, axis=4)
# Binary masks to categorical.
train_mask = (train_mask > 0).astype(np.uint8)
train_mask_cat = to_categorical(train_mask, num_classes=n_classes)

# Divide training data between train and validation sets
X_train, X_val, y_train, y_val = train_test_split(train_img, train_mask_cat, test_size = 0.1, random_state = 0)

# Train
model = architecture(input_shape, n_classes)
model.compile(
optimizer='adam',
loss=custom_weighted_categorical_crossentropy([0.5005, 564.4044]),
metrics=[
'accuracy',
tf.keras.metrics.Recall(),
iou_metric,
dice_coefficient,
IoU(num_classes=2, target_class_ids=[0,1])
]
)
model.summary()
model.fit(X_train, y_train,
validation_data=(X_val, y_val),
epochs=epochs,
batch_size=batch_size
)
model.save(model_name, include_optimizer=True)

if __name__ == "__main__":
# We want to use the relative path of the file (instead of the project one).
current_dir = os.path.dirname(os.path.abspath(__file__))
os.chdir(current_dir)

main()


Подробнее здесь: https://stackoverflow.com/questions/790 ... -sometimes

Вернуться в «Python»