【问题标题】:Large trainable embedding layer slows down training大型可训练嵌入层减慢了训练速度
【发布时间】:2019-06-11 16:11:01
【问题描述】:

我正在训练一个网络以使用 LSTM 对文本进行分类。我为单词输入使用了一个随机初始化且可训练的嵌入层。网络使用 Adam Optimizer 进行训练,单词通过 one-hot-encoding 输入网络。

我注意到嵌入层中表示的单词数量会严重影响训练时间,但我不明白为什么。将网络中的单词数从 200'000 增加到 2'000'000 几乎使训练 epoch 的时间增加了一倍。

训练不应该只更新在当前数据点的预测过程中使用的权重吗?因此,如果我的输入序列始终具有相同的长度,则无论嵌入层的大小如何,都应该始终发生相同数量的更新。

【问题讨论】:

    标签: tensorflow optimization word-embedding


    【解决方案1】:

    所需的更新次数将反映在达到特定精度所需的 epoch 数中。

    如果您观察到收敛需要相同数量的 epoch,但每个 epoch 需要两倍的挂钟时间,那么这表明现在简单地执行嵌入查找(并写入嵌入表的更新)需要花费大量时间你训练时间的一部分。

    这很容易发生。 2'000'000 个字乘以每个浮点数 4 个字节 32 乘以嵌入向量的长度(它是什么?假设为 200)相当于 1.6 GB 的数据,每个小批量都需要处理。你也没有说你是如何训练这个(CPU、GPU、什么GPU)的,这对结果应该如何产生有意义的影响,因为例如缓存效果,对于 CPU 以稍微不那么缓存友好的方式(更稀疏)执行完全相同数量的读取/写入,可以轻松地将执行时间加倍。

    另外,你的前提有点不寻常。你有多少标记数据会有足够的#2000000th 稀有词的例子来直接计算有意义的嵌入?在几乎所有数据集中,包括非常大的数据集,这可能是可能的,但不寻常的是,第 2000000 个单词将是一个随机数,因此将其包含在可训练的嵌入中是有害的。通常的情况是将大型嵌入与大型未标记数据分开计算,并将其用作固定的不可训练层,并可能将它们与来自标记数据的小型可训练嵌入连接起来,以捕获特定领域的术语等内容。

    【讨论】:

    • 感谢您详尽的回答!我的训练集包含很大比例的产品名称。我正在使用 GPU 进行训练。如果它是 RAM,为什么在内存中查找很重要?无论表格大小,查找都不是 O(1) 吗?
    • @Jonas 除了 O() 之外,还有很多细节对“小的”速度差异很重要,比如执行时间加倍。表查找速度高度依赖于缓存命中率(至少对于 CPU,连续读取 100 个项目实际上比读取 100 个随机项目快 100 倍),对于 GPU 训练,将千兆字节 + 表从 CPU 复制到 GPU 并返回的时间是非常重要(对于您的表来说,半秒可能是合理的),所以突然之间考虑训练过程在 CPU 和 GPU 之间移动数据的频率等非常重要。
    【解决方案2】:

    如果我理解正确,您的网络将表示单词的 one-hot 向量转换为某种大小的 embedding_size。然后将嵌入作为输入馈送到 LSTM。网络的可训练变量既是嵌入层的变量,也是 LSTM 本身的变量。

    关于嵌入层中权重的更新,您是正确的。但是,一个 LSTM 单元中的权重数量取决于嵌入的大小。例如,如果您查看第 t 个单元的遗忘门的方程式, 您可以看到权重矩阵 W_f 与输入 x_t 相乘,这意味着 W_f 的维度之一必须恰好是 embedding_size。所以随着 embedding_size 的增长,网络规模也会增长,因此需要更长的时间来训练。

    【讨论】:

    • 对不起,我应该更详细地解释我的方法。我保持一个单词的维度相同,但增加了嵌入中存在的单词总数。我会更新我的问题!
    • 一种可能性是权重不再适合内存,因此您正在等待 tensorflow 从文件中读取它们。
    • 我也想过这个问题,但无法找到验证这一点的方法。你知道我怎么能看到这个内存问题吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-11
    • 1970-01-01
    • 2019-01-23
    • 2023-03-15
    • 2017-05-11
    • 2016-06-20
    • 1970-01-01
    相关资源
    最近更新 更多