在处理RAM中不能容纳的数据时,KERAS FIT_GENERATOR是不是最好的选择?
问题描述
我正在构建一个可以对Knots进行分类的分类器。目前我有一个数据集,其中包含100,000张"解结"、100,000张"加三叶"和100,000张"负三叶"的图像。
在过去的40多天里,我一直在尝试让分类器处理这么大的数据集。到目前为止,我遇到的问题有:
1)数据集不适合CPU主内存:通过使用PyTables和Hdf5创建一些EArrays
并将其追加到磁盘上,修复了此问题。现在我有一个1.2 GB的文件,它是数据集。
2)模型编译后,即使是Kera中一个非常简单的神经网络也达到了100%GPU(NVIDIA K80)内存使用率.甚至还没有符合模型。我读到这是因为Kera后端在编译时自动分配几乎100%的可用资源:我也修复了这个问题。
3)一旦修复了错误1和2,我仍然可以从Kera获得奇怪的精确度fit_generator()
。
问题:
1)我所描述的使用PyTables将小数目的数组合并为一个大的EArray
的方法是制作非常大(300,000张图像128x128,总大小=1.2 GB)数据集的好方法吗?
train_on_batch
?它们返回的最终丢失/准确度分数是否会有显著差异?
3)如果我想从hdf5文件中批量训练神经网络,并且在每个训练周期之后,将网络刚刚训练过的图像从主内存中删除,那么我的生成器方法有什么问题?
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)
以下是拟合模型的输出:
很抱歉,如果这里不是发布帖子的正确位置。 我的研究顾问不在城里,我花了相当多的时间试图解决这个问题,我只是需要一些意见,因为我在互联网上找不到足够的解决方案,或者似乎不能很好地理解我找到的足够好的东西来以一种好的方式实施它。我不是一个新程序员,但对python的经验相对较少。
解决方案
我认为您定义生成器的方式很好。它似乎没有什么问题。不过,目前推荐使用Sequence class,特别是因为它在执行多处理时要安全得多。但是,使用生成器是可以的,并且仍然大量使用。
关于奇怪的准确率数字,您提到3000步的准确率是100%,然后下降到33%。我有以下建议来诊断此问题:
1)将学习速率降低到例如3e-3
或1e-3
或1-e4
。我建议使用Adagrad
或RMSprop
或Adam
这样的自适应优化器。我建议RMSprop
使用默认参数;先不要更改任何参数,而是尝试一下,并根据您得到的反馈进行更改(如果损失减少得非常慢,则稍微提高学习率;如果增加或稳定,则降低学习率,尽管这些不是明确的规则。您必须进行实验并考虑验证损失)。使用自适应优化器可以减少使用ReduceLearningRateOnPlateu
这样的回调的需要(至少在您有充分的理由使用它之前是不需要的)。
2)如果可能,将整个数据分成训练/验证/测试集(或至少训练/验证)。最常用的比例是60/20/20或70/15/15。但要确保这三个集合中的每一个类都是相等的(即,每个集合中的"解结"、"加三叶"和"减三叶"的数量大致相同)。请注意,它们的分布也应该大致相同。例如,您不应该为验证和测试集选择容易的。通常,在对整个数据进行混洗之后进行选择(即确保它们没有任何特定的顺序)是可行的。创建验证集可帮助您确保在培训过程中看到的进度是真实的,并且模型不会与培训数据过度匹配。
您需要为验证定义一个新的生成器,并以与处理训练数据相同的方式传递验证数据(即加载包含验证数据的文件)。然后为fit_generator
方法的validation_data
和validation_steps
参数设置适当的值。
3)在激活之前或之后使用批归一化是still debatable。不过,some people claim如果你把它放在激活之后或者正好放在下一层之前,效果会更好。您也可以试用此功能。
4)如果您没有将GPU用于任何其他用途,请使用其全部容量(即不限制其RAM使用)。并且使用是2的幂的批次大小(即64、128、256等)。因为它有助于GPU内存分配,并且可能会加快它的速度。考虑到您拥有的样本数量,128或256似乎是不错的选择。5)如果一个纪元的培训需要很长时间,请考虑使用ModelCheckpoint
和EarlyStopping
回调。
相关文章