我正在尝试对使用 GPU 扩展的 Tensorflow 2.0 编写的卷积神经网络进行一些超参数调整。
我的系统设置是:
- Windows 10 64 位
- GeForce RTX2070,8GB
- 张量流 2.0-测试版
- CUDA 10.0正确安装(我希望deviceQuery.exe和bandwidthTest.exe顺利通过)
我的神经网络有 75.572.574 个参数,我正在 3777 个样本上对其进行训练。在一次运行中,我训练 CNN 没有任何问题。
下一步,我想调整 CNN 的两个超参数。为此,我创建了一个 for 循环(迭代 20 个步骤),在其中每次创建新模型时都会构建和编译,并在每次循环迭代时更改超参数。
代码的要点(这是notMWE)如下
import tensorflow as tf
from tensorflow import keras
def build_model(input_shape, output_shape, lr=0.01, dropout=0, summary=True):
model = keras.models.Sequential(name="CNN")
model.add(keras.layers.Conv2D(32, (7, 7), activation='relu', input_shape=input_shape, padding="same"))
model.add(keras.layers.BatchNormalization())
model.add(keras.layers.MaxPooling2D((2, 2)))
model.add(keras.layers.Dropout(dropout))
model.add(keras.layers.Conv2D(128, (3, 3), activation='relu', padding="same"))
model.add(keras.layers.BatchNormalization())
model.add(keras.layers.MaxPooling2D((2, 2)))
model.add(keras.layers.Dropout(dropout))
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(1024, activation='relu'))
model.add(keras.layers.BatchNormalization())
model.add(keras.layers.Dense(output_shape, activation='linear'))
model.build()
model.compile(optimizer=keras.optimizers.Adam(learning_rate=lr),
loss="mse",
metrics=[RMSE])
if summary:
print(model.summary())
return model
...
for run_id in range(25):
lr = learning_rate.max_value + (learning_rate.min_value - learning_rate.max_value) * np.random.rand(1)
dropout = dropout.min_value + (dropout.max_value -
dropout.min_value) * np.random.rand(1)
print("%=== Run #{0}".format(run_id))
run_dir = hparamdir + "\\run{0}".format(run_id)
model0 = build_model(IMG_SHAPE, Ytrain.shape[1], lr=lr, dropout=dropout)
model0_history = model0.fit(Xtrain,
Ytrain,
validation_split=0.3,
epochs=2,
verbose=2)
我遇到的问题是,经过几(6)次循环后,程序停止返回错误
tensorflow.python.framework.errors_impl.ResourceExhaustedError: OOM when allocating tensor with shape[73728,1024] and type float on /job:localhost/replica:0/task:0/device:GPU:0 by allocator GPU_0_bfc [Op:Add] name: dense_12/kernel/Initializer/random_uniform/
Process finished with exit code 1.
我认为问题在于 GPU 不会在 for 循环的每次迭代之间释放内存,一段时间后,它会饱和并崩溃。
我已经深入研究并尝试了类似帖子中建议的不同解决方案(post1 https://stackoverflow.com/questions/51005147/keras-release-memory-after-finish-training-process, post2 https://stackoverflow.com/questions/55793768/gpu-oom-hyperparameter-tuning-loop-with-varying-models)
- 尝试在 for 循环的每次迭代结束时使用 Keras 后端释放内存
from keras import backend as K
K.clear_session()
- 尝试使用 Numba 和 CUDA 清除 GPU
from numba import cuda
cuda.select_device(0)
cuda.close()
我尝试使用删除图表del model0
但这也不起作用。
我无法尝试使用tf.reset_default_graph()
因为 TF2.0 的编程风格不再有默认图(据我所知),因此我还没有找到在运行时杀死/删除图的方法。
解决方案 1. 和 3. 返回相同的内存不足错误,而解决方案 2. 在 for 循环的第二次迭代期间返回以下错误,同时在build_model()
call:
2019-07-24 19:51:31.909377: F .\tensorflow/core/kernels/random_op_gpu.h:227] Non-OK-status: GpuLaunchKernel(FillPhiloxRandomKernelLaunch<Distribution>, num_blocks, block_size, 0, d.stream(), gen, data, size, dist) status: Internal: invalid resource handle
Process finished with exit code -1073740791 (0xC0000409)
我试着环顾四周,但我不太明白最后一个错误,我猜想 GPU 没有正确关闭/被占用/Python 再也看不到了。
无论如何,除了对每个要测试的超参数手动运行训练之外,我找不到任何解决此问题的方法。
有人知道如何解决这个问题吗?
或者超参数调整的解决方法?
我是否应该在 TF2.0 Github 问题跟踪器中提出问题(它本身似乎不是 TensorFlow 问题,因为他们声明不想释放 GPU 以避免分段问题)?