CUDA を備えた Tesla K80 GPU を備えた AWS P2 インスタンスで実行するように設定された Keras と Theano を使用して、さまざまなアーキテクチャとパラメーターを持つ一連の再帰型ニューラル ネットワークのモデル選択とパフォーマンス推定のためにネストされた交差検証を実行しています。 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
'nb_hidden_layers'
隠れ層の数がパラメーターin で指定され、各層param_grid
の隠れユニットの数が list からランダムにサンプリングされる RNN を構築します[50, 75, 100, 125, 150]
。最後に、この関数compile
はモデルを返します。
ネストされた相互検証 (CV) 中に、内側のループ (IN
時間を実行) は、ランダムに選択された 30 個のモデルのパフォーマンスを比較します。このステップの後、外側のループで最もパフォーマンスの高いモデルを選択し、ホールドアウト データセットでそのパフォーマンスを推定します。このスキームは何OUT
度も繰り返されます。したがって、私はcompile
RNN モデルをOUT
x IN
x30 回実行していますが、これには非常に長い時間がかかります。たとえば、いつOUT=4
との場合IN=3
、私のメソッドは完了するまでに 6 ~ 7 時間かかります。
GPU が散発的に使用されていることがわかります (ただし、GPU 使用率が 40% を超えることはありません)。ただし、ほとんどの場合、使用されているのは CPU です。私の (無知な) 推測では、これcompile
は CPU で何度も行われ、計算時間の大部分を占めますが、モデルのフィッティングと予測は GPU で行われ、短時間で済みます。
私の質問:
- この状況を改善する方法はありますか?
compile
実際にCPU上で行われますか?- ネストされた CV を使用して最適な RNN アーキテクチャを選択するにはどうすればよいでしょうか?
- 本番サーバーでこのスキームを実行することは合理的ですか? 最高のパフォーマンスを発揮するモデルを選択し、その後その 1 つのモデルを本番サーバーで使用するために、24 時間かかるかもしれない 1 つの大きなネストされた CV を実行することをお勧めしますか?
皆さん、ありがとうございました。