Python 单线程影响TensorFlow Keras后端的模型精度和损失

Python 单线程影响TensorFlow Keras后端的模型精度和损失,python,tensorflow,keras,Python,Tensorflow,Keras,问题 为什么将Keras的TensorFlow后端、内部并行线程和内部并行线程的线程数设置为1会对模型的准确性和损失产生负面影响 背景 我正在使用Keras(2.1.6)培训一个以TensorFlow(1.7.0)为后端的MNIST CNN。我在一个AWS EC2实例中进行了一些训练,发现在从t2.medium实例切换到t2.small实例后,我的准确度大大降低。这在两个实例类型之间根本没有更改代码 假设CPU内核的数量从t2.medium(2个内核)变为t2.small(1个内核),我假设精度

问题

为什么将Keras的TensorFlow后端、内部并行线程和内部并行线程的线程数设置为1会对模型的准确性和损失产生负面影响

背景

我正在使用Keras(2.1.6)培训一个以TensorFlow(1.7.0)为后端的MNIST CNN。我在一个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%
鉴于多线程训练运行导致:

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日更新

我想用更多的线程独立于我自己的代码来测试准确性的提高,所以我在基于可复制开发的基础上进行了一些更改。我的测试代码可以在这里看到。gist中两个Python文件之间的唯一区别是第80、90和91行。取消对这些行的注释将强制TensorFlow后端在单个线程上运行

我运行了三次mnist_cnn_single_threaded.py和三次mnist_cnn_multi_threaded.py。结果可以在相同的例子中看到。它们与我昨天在本地和EC2中运行自己的模型时发现的结果相符

测试结果

以下是我根据NPE的评论得出的测试结果。使用显式设置(但为默认设置)运行tf.ConfigProto()会产生与根本不设置线程值类似的结果。在下表和图表中,“线程”等同于将内部线程和内部线程设置为指定值

唯一在精度和损失方面产生显著差异的情况是显式地将线程设置为1

2018年6月27日更新

这似乎只是Keras的TensorFlow后端的问题。我尝试使用Theano后端进行测试,使用下面的选项强制执行单个线程,但我没有注意到准确性/丢失问题

os.environ['OMP_NUM_THREADS'] = '1'
os.environ['THEANO_FLAGS'] = "device=cpu,force_device=True,openmp=False"

偶尔,我会看到MNIST CNN由于不幸的初始化而陷入低精度。您确定低精度与单线程相关,而不仅仅是虚假结果(侥幸)吗?试着重复这个实验几次……谢谢@desertnaut。我遵循了Keras关于再现性的常见问题,通过重复测试,我能够看到类似的结果。我更新了原始帖子以反映这一点。就我个人而言,我将进行两个实验来收集更多数据:(1)使用显式构造但默认的配置(
config=tf.ConfigProto()
)进行测试;(2) 运行1、2、4、8个etc线程,查看每种情况下测试和val准确性的变化情况。@NPE这是个好主意。我将尝试并报告结果。非常感谢。