在回归模型中使用 Keras ImageDataGenerator

Posted

技术标签:

【中文标题】在回归模型中使用 Keras ImageDataGenerator【英文标题】:Using Keras ImageDataGenerator in a regression model 【发布时间】:2017-06-04 14:25:38 【问题描述】:

我想使用

flow_from_directory

方法

ImageDataGenerator

为回归模型生成训练数据,其中目标值可以是 1 到 -1 之间的任何浮点值。

flow_from_directory

有一个带有描述的“class_mode”参数

class_mode:“分类”、“二进制”、“稀疏”或无之一。默认: “分类”。确定返回的标签数组的类型: “categorical”将是 2D one-hot 编码标签,“binary”将是 1D 二进制标签,“稀疏”将是一维整数标签。

我应该采用哪些值?他们似乎都不适合......

【问题讨论】:

这些值存储在哪里? 最初,有一个包含图片的文件夹和一个将图片映射到其目标值的列表。我愿意接受建议 :-) 不幸的是,keras 文档并没有对回归模型进行太多扩展。 实际上 - 你需要一个非常整洁的才能获得你想要的行为。 抱歉,我没有完全得到你的答案——我需要什么? 【参考方案1】:

目前(2017 年 1 月 21 日最新版本的 Keras)flow_from_directory 只能以以下方式工作:

    您需要按以下方式构建目录:

    directory with images\
        1st label\
            1st picture from 1st label
            2nd picture from 1st label
            3rd picture from 1st label
            ...
        2nd label\
            1st picture from 2nd label
            2nd picture from 2nd label
            3rd picture from 2nd label
            ...
        ...
    
    flow_from_directory(picture, label) 的格式返回固定大小的批次。

如您所见,它只能用于分类案例,并且文档中提供的所有选项仅指定将类提供给分类器的方式。但是,有一个巧妙的技巧可以使 flow_from_directory 对回归任务有用:

    您需要按以下方式构建目录:

    directory with images\
        1st value (e.g. -0.95423)\
            1st picture from 1st value
            2nd picture from 1st value
            3rd picture from 1st value
            ...
        2nd value (e.g. - 0.9143242)\
            1st picture from 2nd value
            2nd picture from 2nd value
            3rd picture from 2nd value
            ...
       ...
    

    您还需要有一个列表list_of_values = [1st value, 2nd value, ...]。然后您的生成器以下列方式定义:

    def regression_flow_from_directory(flow_from_directory_gen, list_of_values):
        for x, y in flow_from_directory_gen:
            yield x, list_of_values[y]
    

对于flow_from_directory_gen 来说,拥有class_mode='sparse' 来完成这项工作至关重要。当然这有点麻烦,但它有效(我使用了这个解决方案:))

【讨论】:

谢谢。显然,flow_from_directory 并非旨在应用于回归问题,因为目标值是从文件夹结构中推断出来的。我会考虑使用你的 hack - 文件夹结构起初看起来很复杂,但它可以很容易地自动创建。【参考方案2】:

我认为以不同方式组织数据,使用 DataFrame(不必将图像移动到新位置)将允许您运行回归模型。简而言之,在 DataFrame 中创建包含每个图像的文件路径和目标值的列。这允许您的生成器保持回归值和图像正确同步,即使您在每个 epoch 打乱您的数据。

这是一个示例,展示了如何将图像与二项式目标、多项式目标和回归目标联系起来,只是为了表明“目标是目标是目标”,并且只有模型可能会改变:

df['path'] = df.object_id.apply(file_path_from_db_id)
df

       object_id   bi  multi                                    path     target
index                                                               
0         461756  dog  white    /path/to/imgs/756/61/blah_461756.png   0.166831
1        1161756  cat  black   /path/to/imgs/756/61/blah_1161756.png   0.058793
2        3303651  dog  white   /path/to/imgs/651/03/blah_3303651.png   0.582970
3        3367756  dog   grey   /path/to/imgs/756/67/blah_3367756.png  -0.421429
4        3767756  dog   grey   /path/to/imgs/756/67/blah_3767756.png  -0.706608
5        5467756  cat  black   /path/to/imgs/756/67/blah_5467756.png  -0.415115
6        5561756  dog  white   /path/to/imgs/756/61/blah_5561756.png  -0.631041
7       31255756  cat   grey  /path/to/imgs/756/55/blah_31255756.png  -0.148226
8       35903651  cat  black  /path/to/imgs/651/03/blah_35903651.png  -0.785671
9       44603651  dog  black  /path/to/imgs/651/03/blah_44603651.png  -0.538359
10      49557622  cat  black  /path/to/imgs/622/57/blah_49557622.png  -0.295279
11      58164756  dog   grey  /path/to/imgs/756/64/blah_58164756.png   0.407096
12      95403651  cat  white  /path/to/imgs/651/03/blah_95403651.png   0.790274
13      95555756  dog   grey  /path/to/imgs/756/55/blah_95555756.png   0.060669

我在这里通过示例详细描述了如何做到这一点:

https://techblog.appnexus.com/a-keras-multithreaded-dataframe-generator-for-millions-of-image-files-84d3027f6f43

【讨论】:

【参考方案3】:

在接受的答案中只有一个小问题我想指出。上面的代码失败并显示如下错误消息:

TypeError: only integer scalar arrays can be converted to a scalar index

这是因为 y 是一个数组。修复很简单:

def regression_flow_from_directory(flow_from_directory_gen,
            list_of_values):
    for x, y in flow_from_directory_gen:
        values = [list_of_values[y[i]] for i in range(len(y))]
        yield x, values

list_of_values的生成方法见https://***.com/a/47944082/4082092

【讨论】:

【参考方案4】:

使用 Keras 2.2.4,您可以使用“.flow_from_dataframe”来解决您想做的事情,让您可以从目录中流动图像以解决回归问题。您应该将所有图像存储在一个文件夹中,并加载一个数据框,其中一列包含图像 ID,另一列包含回归分数(标签),并在“.flow_from_dataframe”中设置“class_mode='other'”。

在这里您可以找到一个示例,其中图像位于“image_dir”中,带有图像 ID 和回归分数的数据框从“训练文件”中加载了 pandas

train_label_df = pd.read_csv(train_file, delimiter=' ', header=None, names=['id', 'score'])

train_datagen = ImageDataGenerator(rescale = 1./255, horizontal_flip = True,
                                   fill_mode = "nearest", zoom_range = 0.2,
                                   width_shift_range = 0.2, height_shift_range=0.2,
                                   rotation_range=30) 

train_generator = train_datagen.flow_from_dataframe(dataframe=train_label_df, directory=image_dir, 
                                              x_col="id", y_col="score", has_ext=True, 
                                              class_mode="other", target_size=(img_width, img_height), 
                                              batch_size=bs)

【讨论】:

以上是关于在回归模型中使用 Keras ImageDataGenerator的主要内容,如果未能解决你的问题,请参考以下文章

深度学习入门,keras实现回归模型

如何在 Keras 回归模型中包含特征的归一化?

深度学习高级,Keras多输入和混合数据实现回归模型

使用 Keras 的简单线性回归

如何使用 tensorflow 或 keras 重新训练具有新子集的线性回归模型?

如何保存 Keras 回归模型?