使用 Keras 和 Theano 进行模型选择需要很长时间
Posted
技术标签:
【中文标题】使用 Keras 和 Theano 进行模型选择需要很长时间【英文标题】:model selection with Keras and Theano takes a very long time 【发布时间】:2017-05-27 21:52:41 【问题描述】:我正在使用 Keras 和 Theano 对一组具有不同架构和参数的循环神经网络进行模型选择和性能估计的嵌套交叉验证,这些网络设置为在具有 Tesla K80 GPU 的 AWS P2 实例上运行安装/启用 CUDA 和 cuDNN。
为了进行模型选择,我比较了从参数空间采样的 30 个模型,使用
param_grid =
'nb_hidden_layers': [1, 2, 3],
'dropout_frac': [0.15, 0.20],
'output_activation': ['sigmoid', 'softmax'],
'optimization': ['Adedelta', 'RMSprop', 'Adam'],
'learning_rate': [0.001, 0.005, 0.010],
'batch_size': [64, 100, 150, 200],
'nb_epoch': [10, 15, 20],
'perform_batchnormalization': [True, False]
params_list = list(ParameterSampler(param_grid, n_iter = 30))
然后我使用下面定义的函数NeuralNetworkClassifier()
构建一个 RNN 模型
def NeuralNetworkClassifier(params, units_in_hidden_layer = [50, 75, 100, 125, 150]):
nb_units_in_hidden_layers = np.random.choice(units_in_hidden_layer, size = params['nb_hidden_layers'], replace = False)
layers = [8] # number of features in every week
layers.extend(nb_units_in_hidden_layers)
layers.extend([1]) # node identifying quit/stay
model = Sequential()
# constructing all layers up to, but not including, the penultimate one
layer_idx = -1 # this ensures proper generalization nb_hidden_layers = 1 (for which the loop below will never run)
for layer_idx in range(len(layers) - 3):
model.add(LSTM(input_dim = layers[layer_idx], output_dim = layers[layer_idx + 1], init = 'he_uniform', return_sequences = True)) # all LSTM layers, up to and including the penultimate one, need return_sequences = True
if params['perform_batchnormalization'] == True:
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Dropout(params['dropout_frac']))
# constructing the penultimate layer
model.add(LSTM(input_dim = layers[layer_idx + 1], output_dim = layers[(layer_idx + 1) + 1], init = 'he_uniform', return_sequences = False)) # the last LSTM layer needs return_sequences = False
if params['perform_batchnormalization'] == True:
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Dropout(params['dropout_frac']))
# constructing the final layer
model.add(Dense(output_dim = layers[-1], init = 'he_normal'))
model.add(Activation(params['output_activation']))
if params['optimization'] == 'SGD':
optim = SGD()
optim.lr.set_value(params['learning_rate'])
elif params['optimization'] == 'RMSprop':
optim = RMSprop()
optim.lr.set_value(params['learning_rate'])
elif params['optimization'] == 'Adam':
optim = Adam()
elif params['optimization'] == 'Adedelta':
optim = Adadelta()
model.compile(loss = 'binary_crossentropy', optimizer = optim, metrics = ['precision'])
return model
它构造了一个RNN,其隐藏层数由param_grid
中的参数'nb_hidden_layers'
给出,每层隐藏单元的数量从[50, 75, 100, 125, 150]
列表中随机采样。最后这个函数compile
s 模型并返回它。
在嵌套交叉验证 (CV) 期间,内部循环(运行 IN
次)比较随机选择的 30 个模型的性能。在这一步之后,我在外循环中选择性能最好的模型,并在一个保留数据集上估计它的性能;该方案重复OUT
次。因此,我compile
一个RNN模型OUT
xIN
x30次,这需要非常长的时间;例如,当OUT=4
和IN=3
时,我的方法需要6 到7 个小时才能完成。
我看到 GPU 偶尔被使用(但 GPU 使用率从未超过 40%);但是,大多数时候,正在使用的是 CPU。我的(未受过教育的)猜测是,compile
在 CPU 上执行了很多次并且占用了大部分计算时间,而模型拟合和预测是在 GPU 上完成的并且需要很短的时间。
我的问题:
-
有没有办法补救这种情况?
compile
真的在 CPU 上完成了吗?
人们如何通过嵌套 CV 来选择最佳 RNN 架构?
我在生产服务器上执行这个方案是否合理?您是否建议我做一个可能需要 24 小时的大型嵌套 CV,以选择性能最佳的模型,然后在生产服务器上使用该模型?
谢谢大家。
【问题讨论】:
nikicc here 的评论建议.compile()
ing 在第一次折叠中使用一次,并在交叉验证中对剩余折叠重复使用初始权重。尝试这个给了我很大的速度提升。
【参考方案1】:
我无法回答你所有的问题,仍然希望它有所帮助。
编译是在 CPU 中完成的,因为它主要由符号图操作和代码生成组成。更糟糕的是,theano 图优化使用纯 Python 代码,与 C/C++ 实现相比,这可能是一种开销。
为了提高 theano 编译时间(以运行时性能为代价):
使用不那么激进的优化
在/home/ec2-user/.theanorc
添加一行:
optimizer = fast_compile
或完全禁用优化:
optimizer = None
预编译一些块
如果您的模型之间有共享的公共块,您可以使用 theano.OpFromGraph
预编译它们
不过,您不能仅在 Keras 中做到这一点。
切换框架
Keras 确实支持 tensorflow 后端。与 theano 相比,tensorflow 更像是一个虚拟机而不是编译器。通常,TF 运行速度比 theano 慢,但编译速度要快得多。
【讨论】:
感谢您的帮助。我会尝试第一个建议。我无法从 Theano 切换(我被要求使用 Theano)。以上是关于使用 Keras 和 Theano 进行模型选择需要很长时间的主要内容,如果未能解决你的问题,请参考以下文章
从 Keras.layers.core 在创建模型时使用 theano 作为后端导入 Dense