python - 在处理不适合 RAM 的数据时,Keras fit_generator 是最好的选择吗?

标签 python keras deep-learning conv-neural-network hdf5

我正在努力构建一个可以对 Knots 进行分类的分类器.目前我有一个数据集,其中包含 100,000 张“无节”图像、100,000 张“加三叶草”图像和 100,000 张“减三叶草”图像。

在过去的 4 天里,我一直在尝试让一个分类器处理这个大型数据集。到目前为止我遇到的问题列表是:

1) 数据集不适合 CPU 主内存:通过使用 PyTables 和 Hdf5 制作多个 EArrays 并将它们附加到磁盘上来解决此问题。所以现在我有一个 1.2Gb 的文件,它是数据集。

2) 在模型编译之后,即使是 Keras 中一个非常简单的神经网络也会达到 100% 的 GPU (nvidia k80) 内存使用率......甚至还没有适合该模型。我读到这是由于 Keras 后端在编译时自动分配了接近 100% 的可用资源:我也修复了这个问题。

3) 修复错误 1 ​​和 2 后,我仍然从 Keras fit_generator() 获得奇怪的准确性。

问题:

1) 我所描述的使用 PyTables 将小型 numpy 数组合并为一个大型 EArray 的方法是否是制作非常大(300,000 张图像 128x128,总大小 = 1.2Gb)数据集的好方法?

2) 在 Keras 中是否应该在 train_on_batch 上使用拟合生成器?他们会返回明显不同的最终损失/准确度分数吗?

3) 如果我想用 hdf5 文件中的 50 张图像批量训练神经网络,并且在每个训练时期之后,从主内存中删除网络刚刚训练的图像,我的生成器方法有什么问题?

import tables
hdf5_path = "300K_Knot_data.hdf5"
extendable_hdf5_file = tables.open_file(hdf5_path, mode='r')

def imageLoader(files, batch_size):

    L = len(files.root.train_data)

    #this line is just to make the generator infinite, keras needs that    
    while True:

        batch_start = 0
        batch_end = batch_size

        while batch_start < L:
            limit = min(batch_end, L)
            X = files.root.train_data[batch_start:limit]
            X = np.reshape(X, (X.shape[0],128,128,3))
            X = X/255
            Y = files.root.train_label[batch_start:limit]

            yield (X,Y) #a tuple with two numpy arrays with batch_size samples     

            batch_start += batch_size   
            batch_end += batch_size

img_rows, img_cols = 128,128
###################################
# TensorFlow wizardry
config = tf.ConfigProto()

# Don't pre-allocate memory; allocate as-needed
config.gpu_options.allow_growth = True

# Only allow a total of half the GPU memory to be allocated
config.gpu_options.per_process_gpu_memory_fraction = 0.5

# Create a session with the above options specified.
K.tensorflow_backend.set_session(tf.Session(config=config))
###################################

model = Sequential()
model.add(Conv2D(64, (3,3), input_shape=(img_rows,img_cols,3)))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Conv2D(96, (3,3), padding='same'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Conv2D(128, (3,3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2)))


model.add(Flatten())
model.add(Dense(128))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(3))
model.add(Activation('softmax', name='preds'))


#lr was originally 0.01

model.compile(loss='categorical_crossentropy',
optimizer=keras.optimizers.Adagrad(lr=0.01, epsilon=None, decay=0.0),metrics= 
['accuracy'])

# fits the model on batches with real-time data augmentation:

model.fit_generator(imageLoader(extendable_hdf5_file, 50),
                steps_per_epoch=240000 / 50, epochs=50)

这是拟合模型的输出:

Output of fitting the model.

抱歉,如果这不是发帖的正确位置。 我的研究顾问不在城里,我花了相当多的时间试图解决这个问题,我只需要一些意见,因为我在互联网上找不到合适的解决方案,或者似乎无法全神贯注于我的想法确实找到足够好的方式以很好的方式实现它。我不是一个新的程序员,但在 python 方面相对缺乏经验。

最佳答案

我认为您定义生成器的方式很好。它似乎没有任何问题。虽然,目前正在使用 Sequence class是推荐的方式,特别是因为它在进行多处理时更安全。然而,使用生成器很好,而且它仍然被大量使用。

至于奇怪的准确率数字,你提到它在 3000 步时为 100%,然后下降到 33%。我有以下诊断建议:

1) 将学习率降低到例如 3e-31e-31-e4。我建议使用自适应优化器,例如 AdagradRMSpropAdam。我推荐使用默认参数的RMSprop;不要先改变任何参数,而是试验它并根据你得到的反馈做出改变(如果损失减少非常缓慢然后增加学习率一点;如果它增加或稳定然后降低学习率,虽然这些不是明确的规则。您必须进行试验并同时考虑验证损失)。使用自适应优化器可以减少使用像 ReduceLearningRateOnPlateu 这样的回调的需要(至少在你有充分的理由使用它之前是这样)。

2) 如果可能的话,将您的整个数据分成训练/验证/测试集(或至少训练/验证)。 60/20/20 或 70/15/15 的比率是最常用的比率。但要确保这三组中的每一组中的类都具有相同的代表性(即每组中“未知节点”、“加三叶草”、“减三叶草”的数量大致相同)。请注意,它们的分布也应该大致相同。例如,您不应该为验证和测试集挑选简单的。通常在打乱整个数据后进行选择(即确保它们没有按任何特定顺序排列)会起作用。创建验证集可帮助您确保您在训练过程中看到的进展是真实的,并且模型不会过度拟合训练数据。

您需要为验证定义一个新的生成器并传递验证数据(即加载包含验证数据的文件),就像您对训练数据所做的那样。然后将 fit_generator 方法的 validation_datavalidation_steps 参数设置为合适的值。

3) 在激活之前或之后使用批量归一化是still debatable .虽然,some people claim如果你把它放在激活之后或恰好在下一层之前,效果会更好。您也可以对此进行试验。

4) 如果您没有将 GPU 用于其他用途,请使用其全部容量(即不要限制其 RAM 使用)。并使用 2 的幂(即 64、128、256 等)的批处理大小,因为它有助于 GPU 内存分配并可能加快速度。考虑到您拥有的样本数量,128 或 256 似乎是不错的选择。

5) 如果一个时期的训练需要很多时间,那么考虑使用 ModelCheckpointEarlyStopping回调。

关于python - 在处理不适合 RAM 的数据时,Keras fit_generator 是最好的选择吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51343169/

相关文章:

python-3.x - Jupyter 没有名为 'imagenet_utils' 的模块,但在 Spyder 上存在

python - 使用 SQL 索引时 SQLAlchemy 自定义排序算法

python - 退出失败的脚本运行(python)

python - 在 MPII 人体姿势数据集上训练 Keras 分类器

python - 如何准备我自己的数据集并使用 pytorch 或 tensorflow 对其进行转换?

deep-learning - 减少 fasttext bin 文件的大小

tensorflow - 如何自动选择批量大小以适合 GPU?

python - 在 python 中-如何将多个 HTML 源代码保存到一个文本文件中

python + windows 自动化 - windows 有时会出现故障

python - 以预训练方式使用机器学习模型 Keras、Tensorflow