【问题标题】:Keras custom generator when batch_size doesn't match with amount of data当 batch_size 与数据量不匹配时的 Keras 自定义生成器
【发布时间】:2019-03-13 16:51:41
【问题描述】:

我在 Python 2.7 中使用 Keras。我正在制作自己的数据生成器来计算火车的批次。我对基于这个模型的data_generator有一些疑问seen here

class DataGenerator(keras.utils.Sequence):

def __init__(self, list_IDs, ...):
    #init

def __len__(self):
    return int(np.floor(len(self.list_IDs) / self.batch_size))

def __getitem__(self, index):
    indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size]
    # Find list of IDs
    list_IDs_temp = [self.list_IDs[k] for k in indexes]
    # Generate data
    X, y = self.__data_generation(list_IDs_temp)
    return X, y

def on_epoch_end(self):
    'Updates indexes after each epoch'
    self.indexes = np.arange(len(self.list_IDs))
    if self.shuffle == True:
        np.random.shuffle(self.indexes)

def __data_generation(self, list_IDs_temp):
    #generate data
    return X, y

好的,下面是我的几个问题:

你能确认我对函数调用顺序的看法吗?这里是:

- __init__
- loop for each epoc :
    - loop for each batches :
        - __len_
        - __get_item__ (+data generation)
    - on_epoch_end

如果您知道调试生成器的方法,我想知道,断点和打印无法使用它..

还有,我的情况很糟糕,但我认为每个人都有问题:

例如,我有 200 个数据(和 200 个标签都可以),例如,我希望批量大小为 64。如果我想得很好,__len_ 将给出 200/64 = 3(而不是 3,125)。所以 1 个 epoch 将用 3 个批次完成?剩下的数据呢?我有一个错误,因为我的数据量不是批量大小的倍数...

第二个例子,我有 200 个数据,我想要一批 256?在这种情况下我必须做什么来调整我的发电机?我考虑过检查 batch_size 是否优于我的数据量,以便为 CNN 提供 1 个批次,但批次不会有预期的大小,所以我认为它会出错?

感谢您的阅读。我更喜欢使用伪代码,因为我的问题更多是关于理论而不是编码错误!

【问题讨论】:

    标签: python tensorflow machine-learning keras data-generation


    【解决方案1】:
    • __len__ : 返回批次数
    • __getitem__ : 返回第 i 个批次

    通常您不会在模型架构中提及批量大小,因为它是训练参数而不是模型参数。因此,在训练时使用不同的批量大小是OK

    示例

    from keras.models import Sequential
    from keras.layers import Dense, Conv2D, Flatten
    from keras.utils import to_categorical
    import keras
    
    #create model
    model = Sequential()
    #add model layers
    model.add(Conv2D(64, kernel_size=3, activation='relu', input_shape=(10,10,1)))
    model.add(Flatten())
    model.add(Dense(2, activation='softmax'))
    model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
    class DataGenerator(keras.utils.Sequence):
        def __init__(self, X, y, batch_size):
            self.X = X
            self.y = y
            self.batch_size = batch_size
    
        def __len__(self):
            l = int(len(self.X) / self.batch_size)
            if l*self.batch_size < len(self.X):
                l += 1
            return l
    
        def __getitem__(self, index):
            X = self.X[index*self.batch_size:(index+1)*self.batch_size]
            y = self.y[index*self.batch_size:(index+1)*self.batch_size]
            return X, y
    
    X = np.random.rand(200,10,10,1)
    y = to_categorical(np.random.randint(0,2,200))
    model.fit_generator(DataGenerator(X,y,13), epochs=10)
    

    输出:

    Epoch 1/10 16/16 [==============================] - 0s 2ms/step - loss: 0.6774 - acc: 0.6097

    如您所见,它在一个 epoch 中运行了 16 个批次,即 13*15+5=200

    【讨论】:

    • 感谢您的回答,很清楚。在您的示例中,如果 "(index+1)*self.batch_size" 是 X 数组中的索引,那么在 X=self.X[....] 行会发生什么? (如果在 len 函数中添加 l+=1,最后一批 5 的情况一定是这样吗?)
    • @Alexy 它将返回元素直到数组的末尾。它不会给出任何错误。检查np.arange(10)[5:20] 将返回[5, 6, 7, 8, 9]
    • 你成就了我的一天!我会尽量适应我的情况,谢谢
    【解决方案2】:

    这个问题的调试方面听起来像是我最近尝试发布但没有得到答案的同一个问题。我最终想通了,我认为这是一个简单的原则,初学者很容易错过。如果下面是 tensorflow-gpu,则不能在 keras 源代码级别进行中断/调试。该 keras 代码被“翻译”以在 gpu 上运行。我认为如果在 cpu 上运行 tensorflow 可能会中断,但也不可能。有一些方法可以在 tensorflow 级别上调试/中断 gpu,但这超出了高级 keras 的简单性。

    【讨论】:

      【解决方案3】:

      你的生成器被Keras用在你的python环境中,如果你不能调试它,原因在别处。

      cf : https://keras.io/utils/#sequence

      __len__:给你小批量的数量

      __getitem__ : 给出第 i 个小批量

      你不必知道他们何时何地被调用,但更像这样:

      - __init__
      - __len_
      - loop for each epoc :
          - loop for each batches :
              - __get_item__
          - on_epoch_end
      

      至于小批量大小,您有两个(经典)选择,要么截断,要么从集合中重新选择条目来填充。 如果您按照应有的方式在每个 epoch 随机化您的训练集,那么随着时间的推移,某些项目将不会出现过度曝光或曝光不足的情况

      【讨论】:

      • 因此,由于它是一个多处理任务,因此无法调试。好的,我喜欢有两种不同的场景,谢谢!
      【解决方案4】:

      如果您在 model.compile 函数中传递“run_eagerly=True”,您或许可以调试生成器。它说here

      热切运行意味着您的模型将逐步运行,就像 Python 代码一样。您的模型可能运行得较慢,但通过单步调用各个层调用,您应该可以更轻松地对其进行调试。

      【讨论】:

        猜你喜欢
        • 2019-09-28
        • 2020-12-10
        • 2019-03-16
        • 1970-01-01
        • 1970-01-01
        • 2019-03-17
        • 1970-01-01
        • 2018-10-23
        • 2019-01-29
        相关资源
        最近更新 更多