【问题标题】:Is it possible to automatically infer the class_weight from flow_from_directory in Keras?是否可以从 Keras 中的 flow_from_directory 自动推断 class_weight?
【发布时间】:2017-07-24 00:17:10
【问题描述】:

我有一个不平衡的多类数据集,我想使用来自fit_generatorclass_weight 参数根据每个类的图像数量为类赋予权重。我正在使用ImageDataGenerator.flow_from_directory 从目录加载数据集。

是否可以从ImageDataGenerator 对象中直接推断出class_weight 参数?

【问题讨论】:

  • 我认为这是不可能的。为什么不能只计算一次?

标签: keras deep-learning


【解决方案1】:

刚刚想出了实现这一目标的方法。

from collections import Counter
train_datagen = ImageDataGenerator()
train_generator = train_datagen.flow_from_directory(...)

counter = Counter(train_generator.classes)                          
max_val = float(max(counter.values()))       
class_weights = {class_id : max_val/num_images for class_id, num_images in counter.items()}                     

model.fit_generator(...,
                    class_weight=class_weights)

train_generator.classes 是每个图像的类列表。 Counter(train_generator.classes) 创建每个类中图像数量的计数器。

请注意,这些权重可能不利于收敛,但您可以将其用作其他类型权重的基础。

这个答案的灵感来自:https://github.com/fchollet/keras/issues/1875#issuecomment-273752868

【讨论】:

  • 但是 train_generator.classes 只返回一个类的列表,就像一个集合,不是吗?
  • 它返回每个图像的类列表。例如,如果我们有三张图片,前两张来自第 1 类,最后一张来自第 0 类,train_generator.classes 等于 [1, 1, 0]
  • 确实,刚去看了源码:)干得好
  • 嘿,谢谢。您能否详细说明“这些权重可能不利于收敛”是什么意思?
  • 但是如何在 numpy、pythor 或 tensorflow 中做到这一点(即当图像标签是 numpy 数组时)?
【解决方案2】:

或者,您可以简单地这样做:

from sklearn.utils import class_weight
import numpy as np

class_weights = class_weight.compute_class_weight(
               'balanced',
                np.unique(train_generator.classes), 
                train_generator.classes)

然后您可以设置(根据上面的评论):

model.fit_generator(..., class_weight=class_weights)

【讨论】:

    【解决方案3】:

    我尝试了两种解决方案和sklearn.utils.class_weight 一个给出了更好的准确性,但我不知道为什么。它们不会产生相同的类权重。

    【讨论】:

    • 如果看每种情况下类的权重比,是一样的。
    • 你得到了多大的改变? @大卫布朗
    【解决方案4】:

    正如文章here 中所建议的,分配类权重的一个好方法是使用:

    (1 / class_count) * (total_count/2)
    

    因此,稍微修改上面 Fábio Perez 建议的方法:

    counter = Counter(train_generator.classes)
    total = float(sum(counter.values()))
    class_weight = {class_id : (1/num_images)*(total)/2.0 for class_id, num_images in counter.items()}
    

    【讨论】:

      【解决方案5】:

      Pasha Dembo 建议的代码运行良好。但是,您应该在插入 model_fit 生成器之前将其转换为字典:

      from sklearn.utils import class_weight import numpy as np
      
      class_weights = class_weight.compute_class_weight(
                 'balanced',
                  np.unique(train_generator.classes), 
                  train_generator.classes)
      
      train_class_weights = dict(enumerate(class_weights))
      model.fit_generator(..., class_weight=train_class_weights)
      

      或者,您可以简单地这样做:

       from sklearn.utils import class_weight import numpy as np
       
       class_weights = class_weight.compute_class_weight(
                      'balanced',
                       np.unique(train_generator.classes), 
                       train_generator.classes) You can then set (as per comment above):
       
       model.fit_generator(..., class_weight=class_weights)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-31
        • 2021-05-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-13
        • 2016-03-16
        相关资源
        最近更新 更多