【问题标题】:ImageDataGenerator swapping image pathsImageDataGenerator 交换图像路径
【发布时间】:2021-11-21 18:56:38
【问题描述】:

我想为我使用 keras 的功能 api 构建的多输入 keras 模型实现我自己的自定义数据生成器。

我已经阅读了很多关于序列类以及如何以各种方式扩展它的功能。

我的数据集严重不平衡,包含 3 个类。

我想要实现的是构建一个使用 flowfromdataframe 的自定义数据生成器。此数据框包含图像的路径。通过限制来自过度表示的类目录的图像路径的数量,我可以成功地进行欠采样,从而平衡数据集。

数据框结构:

但是我遗漏的剩余图像仍然包含我希望我的模型学习的丰富信息。

是否可以使用类似回调“onepochend”之类的东西,它在我的 imagedatagenerator 中调用一个函数,该函数交换数据帧中的旧路径并用随机选择的新路径替换它?

回调 keras 文档: https://www.tensorflow.org/api_docs/python/tf/keras/callbacks/Callback

生成器类文档: https://www.tensorflow.org/api_docs/python/tf/keras/utils/Sequence

勾勒出我的想法:

或者 tensorflow/keras 有什么东西可以做到这一点吗?

【问题讨论】:

    标签: python tensorflow keras deep-learning


    【解决方案1】:

    如果有人正在寻找解决方案,我已经通过从 tensorflow 扩展序列来实现自定义生成器:

    class custom_generator(tf.keras.utils.Sequence):
        def __init__(self, ecg_path, eeg_path, batch_size, img_shape, shuffle=True, X_col='filename', Y_col='class'):
            self.batch_size = batch_size
            self.img_shape = img_shape
            self.shuffle = shuffle
            self.X_col = X_col
            self.Y_col = Y_col
            self.class_mapping = {"sz": 1, "non-sz": 0}
            self.ecg_path = ecg_path
            self.eeg_path = eeg_path
            self.eeg_df, self.ecg_df = self.__generate_data()
            self.len = len(self.eeg_df)
            self.n_name = self.ecg_df[self.Y_col].nunique()
    
        def __generate_data(self):
            eeg_class_dist = inspect_class_distribution(self.eeg_path)
            ecg_class_dist = inspect_class_distribution(self.ecg_path)
            max_n_images = get_lowest_distr(ecg_class_dist, eeg_class_dist)
            balanced_ecg_data = limit_data(self.ecg_path, max_n_images).sort_values(by=[self.Y_col]).reset_index(drop=True)
            balanced_eeg_data = limit_data(self.eeg_path, max_n_images).sort_values(by=[self.Y_col]).reset_index(drop=True)
            return shuffle_order_dataframes(balanced_eeg_data, balanced_ecg_data)
    
        def on_epoch_end(self):
            if shuffle:
                self.ecg_df, self.eeg_df = self.__generate_data()
                
    
        def __get_input(self, path, target_size):
            image = tf.keras.preprocessing.image.load_img(path)
            image_arr = tf.keras.preprocessing.image.img_to_array(image)
            image_arr = tf.image.resize(image_arr,(target_size[0], target_size[1])).numpy()
    
            return image_arr/255.
    
        def __get_output(self, label, num_classes):
            categoric_label = self.class_mapping[label]
            return tf.keras.utils.to_categorical(categoric_label, num_classes=num_classes)
    
        def __get_data(self, x1_batches):
            eeg_path_batch = x1_batches[self.X_col]
            ecg_path_batch = x1_batches[self.X_col]
    
            label_batch = x1_batches[self.Y_col]
    
            x1_batch = np.asarray([self.__get_input(x, self.img_shape) for x in eeg_path_batch])
            x2_batch = np.asarray([self.__get_input(x, self.img_shape) for x in ecg_path_batch])
            y_batch = np.asarray([self.__get_output(y, self.n_name) for y in label_batch])
    
            return tuple([x1_batch, x2_batch]), y_batch
    
        def __getitem__(self, index):
            n_batches = self.eeg_df[index * self.batch_size:(index + 1) * self.batch_size]
            X, y = self.__get_data(n_batches)        
            return X, y
    
        def __len__(self):
            return self.len // self.batch_size
    

    on_epoch_end 是这里的关键。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-14
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多