Question
为什么在 Keras 的 TensorFlow 后端设置线程数,intra_op_parallelism_threads
and inter_op_parallelism_threads
, 到 1 对模型的准确性和损失产生负面影响?
背景
我正在使用 Keras (2.1.6) 训练 MNIST CNN,并以 TensorFlow (1.7.0) 作为后端。我在 AWS EC2 实例中运行一些训练,发现从 t2.medium 实例切换到 t2.small 后,我的准确性大大下降。发生这种情况时根本没有更改两种实例类型之间的代码。
鉴于 CPU 核心数量从 t2.medium(2 核心)变为 t2.small(1 核心),我假设精度的下降与线程有关。为了测试这一点,我强制 TensorFlow 使用单线程并在本地运行训练。
from keras import backend as K
config = tf.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1)
sess = tf.Session(graph=tf.get_default_graph(),config=config)
K.set_session(sess)
在我的本地计算机上,使用单线程运行比运行多线程产生的结果要差得多。
一次单线程训练运行的结果是:
train_loss: 2.303228187561035 train_accuracy: 10.75%
而多线程训练运行的结果是:
train_loss: 0.3670464503765106 train_accuracy: 88.00%
这些结果对我来说没有意义,因为在我看来,无论使用多少线程,运行一定数量的训练周期都应该导致相同数量的计算工作。我的测试结果似乎表明,更多的线程会进行更多的训练,而不仅仅是使用并行性来提高速度。
我浏览了 GitHub 中的 Keras 存储库,但没有找到任何代码让我明白为什么结果会如此不同。
我正在给 Keras 打电话model.fit()
训练模型并model.evaluate()
以获得损失和准确性。
以下是我的一些超参数:
loss_function: categorical_crossentropy
optimizer: Adadelta
epochs: 12
mini_batch_size: 128
train_size: 600
validate_size: 400
更新 2018 年 6 月 26 日
我想独立于我自己的代码来测试更多线程的准确性的提高,所以我运行了Keras MNIST CNN https://github.com/keras-team/keras/blob/master/examples/mnist_cnn.py并在此基础上做了一些改变喀拉斯常见问题解答 https://keras.io/getting-started/faq/#how-can-i-obtain-reproducible-results-using-keras-during-development关于可重复开发。我的测试代码可以在这里看到gist https://gist.github.com/mistersdevelopment/0b30e4b82bc91f7c1bba5a8bc6e0ba52。要点中两个 Python 文件之间的唯一区别是第 80、90 和 91 行。取消注释这些行会强制 TensorFlow 后端在单个线程上运行。
I ran mnist_cnn_single_threaded.py
三次并且mnist_cnn_multi_threaded.py
三次。结果可以在同一个中看到gist https://gist.github.com/mistersdevelopment/0b30e4b82bc91f7c1bba5a8bc6e0ba52#file-testing_results-txt。它们与我昨天在本地和 EC2 中运行我自己的模型时发现的结果相符。
测试结果
以下是我根据 NPE 评论的测试结果。使用显式设置但默认运行tf.ConfigProto()
产生与根本不设置线程值类似的结果。在下面的图表和表格中,“线程”等于设置两者intra_op_parallelism_threads
and inter_op_parallelism_threads
到指定值。
Threads Test Loss Test Accuracy
1 2.300546171 0.1141
2 0.060040779 0.9806
4 0.060651763 0.9805
6 0.06015457 0.9808
8 0.057530957 0.9819
唯一在准确性和损失方面产生显着差异的情况是将线程显式设置为 1。
更新 2018 年 6 月 27 日
这似乎只是 Keras 的 TensorFlow 后端的问题。我尝试使用 Theano 后端进行测试,使用以下选项强制使用单线程,但我没有注意到准确性/丢失问题。
os.environ['OMP_NUM_THREADS'] = '1'
os.environ['THEANO_FLAGS'] = "device=cpu,force_device=True,openmp=False"