Как мне обрабатывать немаркированный класс базы данных pascal voc при обучении модели сегментации unet с набором данных pascal voc?
Я тренирую модель unet для семантической сегментации с набором данных pascal voc.
Насколько я понимаю, существует 21 помеченный класс (1 фон с индексом пикселя «0» и 20 объектов с индексами 1–20) и 1 пустой/непомеченный класс (индекс «255»). Меня смущает количество классов, которые я должен установить для последнего слоя свертки. Должен ли он установить его на 21 или 22?
Как ни странно, модель все еще может быть сохранена независимо от того, было ли установлено значение 21 или 22. Но в обоих случаях точность очень и очень низкая (менее 1%). Я использую sparse_categorical_crossentropy в качестве потери и активации softmax для последнего слоя. Я пробовал использовать другую функцию потерь, например кости, но результат тот же.
Ниже приведен снимок моего кода. Надеюсь, какая-нибудь добрая душа просветит меня.
def load_data(path, split=0.2):
images = sorted(glob(os.path.join(path, "voc_image_500/*")))
masks = sorted(glob(os.path.join(path, "voc_raw_mask_500/*")))
train_x, valid_x, train_y, valid_y = train_test_split(images, masks, test_size=split, random_state=42)
return (train_x, train_y), (valid_x, valid_y)
def read_image(path):
image = tf.io.read_file(path)
image = tf.image.decode_png(image,channels=3)
return image
def read_label(path):
image = tf.io.read_file(path)
image = tf.image.decode_png(image,channels=1)
return image
def normalize(image,mask):
image = tf.cast(image,tf.float32)
mask = tf.cast(mask,tf.int32)
return image,mask
def image_handler_train(image_path,label_path):
train_img = read_image(image_path)
label_img = read_label(label_path)
train_img = tf.image.resize(train_img,size=(256,256),method=tf.image.ResizeMethod.NEAREST_NEIGHBOR)
label_img = tf.image.resize(label_img,size=(256,256),method=tf.image.ResizeMethod.NEAREST_NEIGHBOR)
image,mask = normalize(train_img,label_img)
return image,mask
def image_handler_valid(image_path,label_path):
train_img = read_image(image_path)
label_img = read_label(label_path)
train_img = tf.image.resize(train_img,size=(256,256),method=tf.image.ResizeMethod.NEAREST_NEIGHBOR)
label_img = tf.image.resize(label_img,size=(256,256),method=tf.image.ResizeMethod.NEAREST_NEIGHBOR)
image,mask = normalize(train_img,label_img)
return image,mask
(train_x, train_y), (valid_x, valid_y) = load_data(PATH)
BUFFERSIZE = 100
BATCHSIZE = 8
AUTO = tf.data.experimental.AUTOTUNE
#Build training set
train_path_dataset = tf.data.Dataset.from_tensor_slices((train_x,train_y))
train_dataset = train_path_dataset.map(image_handler_train,num_parallel_calls=AUTO)
train_dataset = train_dataset.repeat().shuffle(BUFFERSIZE).batch(BATCHSIZE).prefetch(AUTO)
#Build valid set
valid_path_dataset = tf.data.Dataset.from_tensor_slices((valid_x,valid_y))
valid_dataset = valid_path_dataset.map(image_handler_valid,num_parallel_calls=AUTO)
valid_dataset = valid_dataset.batch(BATCHSIZE)
def make_unet_model():
input = keras.Input(shape=(256,256,3))
...
output = layers.Conv2D(21,1,padding='same',strides=1,activation='softmax')(x_)
return keras.Model(inputs=input,outputs=output)
model = make_unet_model()
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['acc'])
EPOCHS = 30
train_step = len(train_x) // BATCHSIZE
val_step = len(valid_x) // BATCHSIZE
history = model.fit(train_dataset,
epochs=EPOCHS,
steps_per_epoch= train_step,
validation_data=valid_dataset,
validation_steps=val_step)