batch_size 与数据量不匹配时的 Keras 自定义生成器

Keras custom generator when batch_size doesn't match with amount of data

我在 Python 2.7 中使用 Keras。我正在制作自己的数据生成器来计算火车的批次。我对基于此模型 :

的 data_generator 有一些疑问
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 个纪元将分 3 批完成?其余的数据呢?我有一个错误,因为我的数据量不是批量大小的倍数...

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

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

Keras 在您的 python 环境中使用了您的生成器,如果您无法调试它,则原因在别处。

比照:https://keras.io/utils/#sequence

__len__ :给你小批量的数量

__getitem__ :给出第 i 个小批量

您不必知道调用它们的时间或地点,但更像是这样:

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

至于小批量大小,您有两个(经典)选择,截断或通过从您的集合中再次挑选条目来填充。 如果你按照你应该的方式在每个时期随机化你的训练集,随着时间的推移,一些项目将不会过度曝光或曝光不足

  • __len__ : Returns 批次数
  • __getitem__ : Returns 第一批

通常你从不在模型架构中提及批量大小,因为它是训练参数而不是模型参数。因此,在训练时使用不同的批量大小是 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

如您所见,一个时期内有 运行 16 个批次,即 13*15+5=200

这个问题的调试方面听起来与我最近尝试发布但没有得到答案的问题相同。我最终弄明白了,我认为这是一个很容易被初学者忽略的简单原则。如果下面是 tensorflow-gpu,则不能在 keras 源代码级别 break/debug。该 keras 代码在 gpu 上得到 'translated' 到 运行。我认为如果在 cpu 上 运行ning tensorflow 可能会中断,但这也不可能。在 tensorflow 级别的 gpu 上有方法 debug/break,但这超出了高级 keras 的简单性。

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

运行 eagerly 意味着您的模型将 运行 一步一步,就像 Python 代码一样。您的模型可能 运行 速度较慢,但​​通过进入各个层调用,您应该可以更轻松地调试它。