Keras 中的 CuDNNLSTM 和 LSTM 有啥区别?
Posted
技术标签:
【中文标题】Keras 中的 CuDNNLSTM 和 LSTM 有啥区别?【英文标题】:What is the difference between CuDNNLSTM and LSTM in Keras?Keras 中的 CuDNNLSTM 和 LSTM 有什么区别? 【发布时间】:2018-10-03 20:43:59 【问题描述】:在高级深度学习库Keras
中,有多种循环层;这些包括LSTM
(长期短期记忆)和CuDNNLSTM
。根据Keras documentation,CuDNNLSTM
是:
由 CuDNN 支持的快速 LSTM 实现。 只能在 GPU 上运行,带有 TensorFlow 后端。
我相信 Keras 会尽可能自动使用 GPU。根据TensorFlow build instructions,要拥有一个正常工作的 TensorFlow GPU 后端,您将需要 CuDNN:
您的系统上必须安装以下 NVIDIA 软件:
NVIDIA 的 Cuda 工具包 (>= 7.0)。我们推荐版本 9.0。有关详细信息,请参阅 NVIDIA 的文档。确保将相关的 Cuda 路径名附加到 LD_LIBRARY_PATH 环境变量中,如 NVIDIA 文档中所述。 与 NVIDIA 的 Cuda Toolkit 关联的 NVIDIA 驱动程序。 cuDNN (>= v3)。我们推荐版本 6.0。有关详细信息,请参阅 NVIDIA 的文档,尤其是关于将适当的路径名附加到 LD_LIBRARY_PATH 环境变量的说明。
因此,CuDNNLSTM
与使用 TensorFlow GPU 后端的普通 LSTM
有何不同?当找到可用的 TensorFlow GPU 后端时,CuDNNLSTM
是否会被自动选择并替换正常的 LSTM
?
【问题讨论】:
我猜他们是一样的?它可能只在没有 GPU 的情况下运行时有所不同。 LSTM 的选择 如果要将模型部署到生产中,CuDNNLSTM 很重要。例如,到目前为止,Google Cloud Platform 允许您在其“AI Platform”中仅使用 CPU 机器。因此,如果您使用 CuDNNLSTM 训练模型,您将无法部署它。 【参考方案1】:你为什么不自己试试看呢?
在我的例子中,使用LSTM
训练一个模型需要 10 分 30 秒。
只需将电话从 LSTM()
切换到 CuDNNLSTM()
不到一分钟。
我还注意到切换到CuDNNLSTM()
也大大加快了model.evaluate()
和model.predict()
。
【讨论】:
为什么我才发现这个,太神奇了!过去在大型数据集上评估模型需要 3 小时,现在只需 20 分钟左右。 CuDNNLSTM 更快(它使用 GPU 支持)但它的选项比 LSTM 少(例如 dropout) 更多信息请参见此主题:reddit.com/r/learnmachinelearning/comments/9jv0gx/… 只是重新执行所说的话。运行具有 10 个 LSTM 层、3 个密集层和每层 200 个神经元的模型,使用硬 sigmoid 激活函数强制使用通用 GPU - 每个 epoch 超过 40 分钟。将其更改回普通的 sigmoid 允许 cuDNN - 每个 epoch 54 秒。有很大的不同。 我刚刚在 Python 3.9.9 和 Tensorflow 2.7.0 上尝试过。我用 tf.compat.v1.keras.layers.CuDNNLSTM(128, return_sequences=True) 替换了 tf.keras.layers.LSTM(128, return_sequences=True),我得到了超过 3 倍的速度提升,从每步 110ms 到38 毫秒。在 RTX 3080Ti 上运行,低端显卡可能会看到更大的性能提升。因此,官方文档中关于 tensorflow 2.x 已经使用 CuDNN 内核的说法是不正确的,至少它对我不起作用。【参考方案2】:GPU 适合大规模并行计算,大多数线性代数运算可以并行化以提高性能,矩阵乘法和梯度下降等向量运算可以应用于在 GPU 支持下并行执行的大型矩阵。 CUDA - Compute Unified Device Architecture 提供了一个接口,允许向量运算利用 GPU 并行性。 CuDNN 使用 CUDA 在 GPU 上实现用于大型矩阵运算的内核。
这里,CuDNNLSTM 是为 CUDA 并行处理而设计的,如果没有 GPU,则无法运行。但是 LSTM 是为普通 CPU 设计的。更快的执行时间是因为并行性。
【讨论】:
【参考方案3】:TL;DR;区别在于模型训练时间提高了 15 倍!
Setup Steps
Dependencies
性能基准测试:标准测试机器的比较。在 612235 个样本上训练 1 次迭代。
keras.layers.LSTM
Intel i5-4690 CPU only:
612235/612235 [==============================] - 3755s 6ms/step - loss: 2.7339 - acc: 0.5067 - val_loss: 2.1149 - val_acc: 0.6175
GTX:950 & Intel i5-4690:
612235/612235 [==============================] - 1417s 2ms/step - loss: 2.7007 - acc: 0.5137 - val_loss: 2.0983 - val_acc: 0.6199
GPU 增益为 2.5 倍。
GTX:970 & Intel i5-4690:
612235/612235 [==============================] - 1322s 2ms/step - loss: 1.9214 - acc: 0.6442 - val_loss: 1.8808 - val_acc: 0.6461
强大的 GPU 带来的收益可忽略不计。
RTX 2070 & Intel i7-9700K:
612235/612235 [==============================] - 1012s 2ms/step - loss: 2.7268 - acc: 0.5111 - val_loss: 2.1162 - val_acc: 0.6234
即使有很棒的硬件升级,收益也很小!!!
keras.layers.CuDNNLSTM
RTX 2070 & Intel i7-9700K:
612235/612235 [==============================] - 69s 112us/step - loss: 1.9139 - acc: 0.6437 - val_loss: 1.8668 - val_acc: 0.6469
54 倍的 CPU 增益! 比传统(非 Cuda)LSTM 实现提高 15 倍!
【讨论】:
似乎只需要显示最后两个案例,因为它们是一个公平的测试 - 相同的组件,只有 CuDNNLSTM 与 LSTM 不同。前几个例子只会让你的帖子混乱。跨度> 【参考方案4】:在 TensorFlow 2.0 中,内置的 LSTM 和 GRU 层已更新为利用 CuDNN 内核默认情况下,当 GPU 可用时。进行此更改后,之前的 keras.layers.CuDNNLSTM/CuDNNGRU 层已被弃用,您可以构建模型而无需担心运行它的硬件。
由于 CuDNN 内核 是在某些假设下构建的,这意味着如果您更改内置的默认值,该层将无法使用 CuDNN 内核 LSTM 或 GRU 层。
查看 tensorflow RNN 文档:https://www.tensorflow.org/guide/keras/rnn
【讨论】:
这不是真的。我刚刚在 Python 3.9.9 和 Tensorflow 2.7.0 上尝试过。我用 tf.compat.v1.keras.layers.CuDNNLSTM(128, return_sequences=True) 替换了 tf.keras.layers.LSTM(128, return_sequences=True),我得到了超过 3 倍的速度提升,从每步 110ms 到38 毫秒。在 RTX 3080Ti 上运行,低端显卡可能会看到更大的性能提升。因此,你所说的关于 tensorflow 2.x 已经使用 CuDNN 内核的说法是不正确的,至少它对我不起作用。 使用 RTX 2060 Super 与 Keras 2.4/TF 2.3 确认 - 使用 CuDNNLSTM(通过 tf.compat.v1.keras.layers)与 LSTM 没有观察到加速。就我而言,无论哪种方式都是 24 毫秒/步。以上是关于Keras 中的 CuDNNLSTM 和 LSTM 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章
CuDNNLSTM:调用 ThenRnnForward 失败
tensorflow.keras.layers:ImportError:无法导入名称“CuDNNLSTM”
Keras - ImportError:无法导入名称'CuDNNLSTM'