通过时间的反向传播是什么?把循环网络沿时间展开再求梯度
通过时间的反向传播(Backpropagation Through Time,BPTT),也叫随时间反向传播,是训练循环神经网络的标准算法。它的核心思想是:把循环神经网络沿着时间展开,变成一个很深的普通前馈网络,然后用标准的反向传播算法来计算梯度。这一方法由 Paul Werbos 在 1990 年发表的论文中做了系统的阐述。
为什么需要特殊处理
循环神经网络是专门用来处理序列数据的,比如一句话、一段语音、一串股价。它逐个地读入序列中的元素,每一个时间步,网络都会结合当前的输入和上一个时间步留下来的隐藏状态,计算出新的隐藏状态,这个隐藏状态相当于网络的“记忆”。关键在于,在所有的时间步上,网络使用的都是同一组权重。这与普通的前馈网络不同:在前馈网络中,每一层都有自己独立的权重,反向传播可以逐层地计算每一层的梯度;而在循环神经网络中,同一组权重在每个时间步都会被使用,它对最终误差的影响分散在所有的时间步上,需要专门的方法来计算它的梯度。
沿时间展开
通过时间的反向传播的做法是:把循环神经网络在时间上“摊开”。假设序列有 T 个时间步,就把网络复制 T 份,第一份处理第一个时间步,它的隐藏状态传给第二份,第二份处理第二个时间步,以此类推。这样,一个循环的网络就变成了一个有 T 层的深层前馈网络,只不过每一层使用的都是同一组权重。
然后进行两个步骤。前向传播:按照时间的顺序,从第一个时间步计算到最后一个时间步,得到每个时间步的隐藏状态和输出,计算出每个时间步的损失,并把它们加起来得到总的损失。反向传播:从最后一个时间步开始,按照时间的反方向,逐步地把误差往前传。每个时间步的隐藏状态,既影响当前时间步的输出,也通过传给下一个时间步而影响后续所有的输出,因此它的梯度要综合这两方面的来源。由于所有时间步共享同一组权重,最后要把每个时间步上计算出的、对权重的梯度全部加起来,得到权重的总梯度,再用它来更新权重。
长序列带来的问题
当序列很长时,通过时间的反向传播会遇到几个严重的问题。梯度消失和梯度爆炸:误差从后往前传递时,每经过一个时间步,都要乘以一次与权重矩阵有关的因子。经过很多个时间步之后,如果这些因子小于 1,梯度会以指数的速度衰减到接近零,网络就无法学到序列中相隔很远的元素之间的关系,也就是长期依赖;如果大于 1,梯度又会以指数的速度增大,导致训练崩溃。Yoshua Bengio 等人在 1994 年对这一问题进行了深入的分析。计算和内存的开销:需要保存所有时间步的中间结果,序列越长,占用的内存越多,计算也越慢。
应对的方法
截断的通过时间反向传播:不把误差一直传回到序列的开头,而是只往回传固定的若干个时间步,比如 50 步,这样大大减少了计算量和内存占用,代价是无法学习超过这个长度的依赖关系。这是实践中最常用的做法,比如训练语言模型时,把很长的文本切成一段一段来处理,隐藏状态在段与段之间传递,但梯度只在段内传播。梯度裁剪:当梯度的大小超过某个阈值时,把它按比例缩小,防止梯度爆炸。改进网络的结构:长短期记忆网络(LSTM)和门控循环单元(GRU)通过门控机制,让信息和梯度能够在很长的时间跨度上较为稳定地传递,有效地缓解了梯度消失的问题。如今,在很多序列任务中,Transformer 已经取代了循环神经网络:它不需要按时间顺序逐步地处理,可以并行地计算,任意两个位置之间都能直接建立联系,从根本上避开了通过时间反向传播的这些困难。