微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 Keras Image Generator 中拆分验证数据以用于 U-Net 中的图像分割

如何解决在 Keras Image Generator 中拆分验证数据以用于 U-Net 中的图像分割

我正在尝试训练一个用于图像分割的 U-net 网络。

我克隆了这个存储库 (https://github.com/zhixuhao/unet),它具有 U-net 的 Keras 实现。

我的数据组织在 3 个文件夹中,就像在存储库中一样:

train/image : 包含原始图像

train/label : 包含原始图像的掩码

test/ :包含新的原始图像以查看训练后网络的表现。

我得到一个可以分段的网络,但它在训练期间不使用验证数据。

我想要一个验证损失,并在验证损失没有改善时有一个回调来停止训练。

model_checkpoint = ModelCheckpoint('unet_master.hdf5',monitor='val_loss',verbose=1,save_best_only=True)
#earlystopping
earlystopping = EarlyStopping(monitor='val_loss',patience=10,verbose=0,mode='min')

callbacks_list = [model_checkpoint,earlystopping]

#load unet function
model=unet()

model.fit_generator(my_generator,validation_data=validation_generator,steps_per_epoch=1000,epochs=5,callbacks=callbacks_list)

my_generator 是通过 data.py 文件中的 trainGenerator 和 adjustData 函数预先定义的(见最后)

现在我正在尝试生成validaton_generator,但没有成功。

我已阅读此问题:

https://github.com/keras-team/keras/issues/3900#issuecomment-420693239

和本教程:

https://keras.io/api/preprocessing/image/

但我不管理。 我遇到的问题是理解在我的情况下什么是“数据”的等价物。是火车文件夹吗?为什么我必须有一个 image_generator 和一个 mask_generator?

我尝试为图像和蒙版创建一个生成器,并为验证创建另一个生成器,如下所示:

#added 0.3 validation_split to aug_dict
aug_dict = dict(rotation_range=0.2,width_shift_range=0.05,height_shift_range=0.05,shear_range=0.05,zoom_range=0.05,horizontal_flip=True,vertical_flip=True,fill_mode='nearest',validation_split=0.3)


image_color_mode='grayscale'
target_size=(256,256)
batch_size=1
save_to_dir=None
seed=1
image_datagen = ImageDataGenerator(**aug_dict)
mask_datagen = ImageDataGenerator(**aug_dict)
validation_datagen = ImageDataGenerator(**aug_dict)


# i removed     class_mode = None,to have it running
image_generator = image_datagen.flow_from_directory(
    train_path,color_mode = image_color_mode,target_size = target_size,subset='training',batch_size = batch_size,save_to_dir = save_to_dir,seed = seed)

mask_generator = mask_datagen.flow_from_directory(
    mask_path,seed = seed)

train_generator=zip(image_generator,mask_generator)

#function to run the adjustData function
def return_adjusted_generator(train_generator):
    for (img,mask) in train_generator:
        img,mask = adjustData(img,mask,flag_multi_class=False,num_class=2)
        yield (img,mask)
        
my_new_generator=return_adjusted_generator(train_generator)
        
validation_generator = validation_datagen.flow_from_directory(
    train_path,class_mode = None,subset='validation',seed = seed)

输出

找到属于 2 个类别的 164 个图像。 找到属于 2 个类别的 164 个图像。 找到属于 2 个类别的 68 张图片

然后我跑:

model_checkpoint = ModelCheckpoint('unet_master.hdf5',save_best_only=True)
#added earlystopping
earlystopping = EarlyStopping(monitor='val_loss',earlystopping]

model=unet()

model.fit_generator(my_new_generator,steps_per_epoch=20,epochs=1,callbacks=callbacks_list)

我得到的错误是: ValueError: 无法将输入数组从形状 (256,256,1) 广播到形状 (1)

我知道 image_generator 和 mask_generator 是错误的,因为如果我循环遍历 image_generator,我会看到图像和掩码。但我不知道我做错了什么。

非常感谢有关如何拆分数据以进行验证的任何帮助。

谢谢

使用的函数

def adjustData(img,flag_multi_class,num_class):
    if(flag_multi_class):
        img = img / 255
        mask = mask[:,:,0] if(len(mask.shape) == 4) else mask[:,0]
        new_mask = np.zeros(mask.shape + (num_class,))
        for i in range(num_class):
            #for one pixel in the image,find the class in mask and convert it into one-hot vector
            #index = np.where(mask == i)
            #index_mask = (index[0],index[1],index[2],np.zeros(len(index[0]),dtype = np.int64) + i) if (len(mask.shape) == 4) else (index[0],dtype = np.int64) + i)
            #new_mask[index_mask] = 1
            new_mask[mask == i,i] = 1
        new_mask = np.reshape(new_mask,(new_mask.shape[0],new_mask.shape[1]*new_mask.shape[2],new_mask.shape[3])) if flag_multi_class else np.reshape(new_mask,(new_mask.shape[0]*new_mask.shape[1],new_mask.shape[2]))
        mask = new_mask
    elif(np.max(img) > 1):
        img = img / 255
        mask = mask /255
        mask[mask > 0.5] = 1
        mask[mask <= 0.5] = 0
    return (img,mask)



def trainGenerator(batch_size,train_path,image_folder,mask_folder,aug_dict,image_color_mode = "grayscale",mask_color_mode = "grayscale",image_save_prefix  = "image",mask_save_prefix  = "mask",flag_multi_class = False,num_class = 2,save_to_dir = None,target_size = (256,256),seed = 1):
    '''
    can generate image and mask at the same time
    use the same seed for image_datagen and mask_datagen to ensure the transformation for image and mask is the same
    if you want to visualize the results of generator,set save_to_dir = "your path"
    '''
    image_datagen = ImageDataGenerator(**aug_dict)
    mask_datagen = ImageDataGenerator(**aug_dict)
    image_generator = image_datagen.flow_from_directory(
        train_path,classes = [image_folder],save_prefix  = image_save_prefix,seed = seed)
    mask_generator = mask_datagen.flow_from_directory(
        train_path,classes = [mask_folder],color_mode = mask_color_mode,save_prefix  = mask_save_prefix,seed = seed)
    train_generator = zip(image_generator,mask_generator)
    for (img,num_class)
        yield (img,mask)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。