我正在尝试使用TensorFlow 1.12.0和Keras API训练神经网络。
设置如下。我有大量的数据点:每个点都包含一个上下文(称为24个浮点数)和一个标签(1个浮点数)。数据总量为O(10 ^ 7)点。测试网络各不相同,但相当简单的网络可能看起来像这样
v=[keras.layers.Input(shape=input_shape)]
v.append(keras.layers.Dense(4,use_bias=False,activation=tf.nn.tanh)(v[-1]))
v.append(keras.layers.Dense(1,use_bias=False)(v[-1]))
model=keras.models.Model(inputs=v[0],outputs=v[-1])
optimizer = tf.train.RMSPropOptimizer(0.001)
model.compile(loss='mse', optimizer=optimizer, metrics=['mae'])
(...)
history=model.fit(x=train_data,y=train_labels,epochs=EPOCHS,verbose=1,batch_size=10000, shuffle=True)
我一直在获得不错的结果,将数据保存在numpy数组中,并将它们按原样传递给model.fit()。但是,我对此表现不满意。它似乎是Python代码中的瓶颈(我什至试图对其进行概要分析,并且python / keras / utils / generic_utils.py中的Python方法slice_arrays成为主要的瓶颈,所有时间的花费多达一半。)GPU( GeForce 1080 Ti)正在使用中,但其利用率(据nvidia-smi报道)很少高于10-15%。
寻找一种加快速度的方法,我试图将数据转换为张量:
features=tf.convert_to_tensor(train_data)
labels=tf.convert_to_tensor(train_labels)
history=model.fit(x=features,y=labels,epochs=EPOCHS,verbose=1,steps_per_epoch=20, shuffle=True)
model.fit在传递numpy数组时需要参数batch_size,但在传递张量时需要steps_per_epoch。文档尚不清楚,但似乎我应该将steps_per_epoch设置为数据点数除以batch_size。这样,我可以获得可比的收敛速度。无论什么值,GPU利用率都是100%,这是很好的。
但是现在有一个问题。使用numpy数组时,每个时期的运行时间相对独立于批处理大小。我看到批量为10k时每个时期8秒,批量为100k时为5秒,批量为1M时每个纪元7秒。如果批处理量较小,那么收敛通常会更好。因此,我通常从100k以下的批量开始。另一方面,使用张量输入时,每个时期的运行时间与steps_per_epoch呈指数增长。批处理大小为1M(每个纪元10-20步)时,我的速度为2 s /纪元,但是收敛速度却很糟糕。批量大小为10k时,收敛速度很好,但是时间高达30 s / epoch(尽管GPU利用率为100%,实际上比numpy慢)。
基本上,张量输入实际上以更快的速度结束的唯一情况是我一开始并不在意使用它。
这是怎么回事,有什么办法可以解决这个问题?