心法利器
本栏目主要和大家一起讨论近期自己学习的心得和体会,与大家一起成长。具体介绍:仓颉专项:飞机大炮我都会,利器心法我还有。
近期,我再次总结了我的历史文章,累积起来有50w字,百余篇文章了,有兴趣可以拿来看看,获取方式:七夕清流,百余篇累计50w字文章合集发布。
往期回顾
做NLP的可能很多都不清楚这玩意,然而CV中的ResNet应该大家已有所耳闻,而如果说完全没见过,那说明你对BERT还不算熟悉哈哈哈(我也在反思...),今天我单独把这东西拿出来聊聊,这绝对是一个非常有利于效果优化的技术。
懒人笔记:
提出背景
什么是残差网络
代码实现
功能效用
深入阅读
小结
参考资料
提出的背景
这并不是NLP产生的新玩意,早在2015年(这个年份的东西已经被叫早在了...),微软的几位大佬提出了残差网络,换个熟悉的名字,就是ResNet,在CV中,网络能在残差网络的加持下模型能持续增加深度,效果还能持续提升,从而达到更快实现更高的效果。神奇的就在此,残差网络是怎么让模型在深度增加的过程中效果持续提升,而为什么在没有残差网络的情况下,效果就不能持续增加了,除了“过拟合”外,是不是还有别的原因。
残差网络是什么
残差网络说的牛,但原理其实非常简单,其实就是这个公式:
很简单对吧,换个图来解释更加清楚:
一般地,我们都是用比较粗暴的方式来堆叠每一层,逐步向前转播,而残差网络的操作,除了有单向的传播,还会有一条绕过层直接到下游的线,在这里和过了层的结果进行求和,这就是残差网络。
假设是一个层的输入,这个是层的参数,所以经过就是了,然后再加上绕过的于是就有了这个
代码实现
说到代码,我想举的例子就来自BERT,最近我再BERT的源码阅读就发现了这东西,这应该也是BERT有效的根本原因之一,源码里很多地方都塞了残差网络。上代码:
class BertOutput(nn.Module):
def __init__(self, config):
super().__init__()
self.dense = nn.Linear(config.intermediate_size, config.hidden_size)
self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
self.dropout = nn.Dropout(config.hidden_dropout_prob)
def forward(self, hidden_states, input_tensor):
hidden_states = self.dense(hidden_states)
hidden_states = self.dropout(hidden_states)
# 此处用了残差网络,隐含层输出和输入层求和,当然外面包了层LayerNorm
hidden_states = self.LayerNorm(hidden_states + input_tensor)
return hidden_states
来自huggingface的BertOutput内使用了残差网络,这里的就是一个dense+dropout。可以看到非常简单,就是在过完这一层之后再加一个输入即可。
功能和效用
我这里并不只是想介绍残差网络那么简单,而是想探究,为什么这一个简单的操作能够产生这么好的效果,在论文“Attention is not all you need”中其实就有提到了残差网络的重要性。纵观很多文献和大佬博客分享,残差网络之所以能对效果产生影响,按照原论文的观点,其实就是解决了网络退化的问题,说的有些玄乎,来看看具体是什么样的。
众所周知,反向传播的其实就是一个通过链式法则将误差以梯度的方式从模型输出端向输入端传播的过程(这句话居然把几个要素都给涵盖了),对于某一层的反向传播,可以用这个表示:
这里可以看到,反向传播到后层,是需要以乘的形式回传的,这里,如果这个回乘的算子非常小或者非常大,那就梯度消失和梯度爆炸就会出现,而另外如果涉及到多个参数的回传,那越偏向输入端的参数,得到的回传误差就会越小,这时候更新的量就会非常小(w2v一定程度就有这个问题),这就是梯度弥散导致的靠近输入端的参数更新缓慢,最后就有了类似煲饭上不熟中间熟下层焦的效果。
而残差网络则可以一定程度解决这个问题,首先看前向传播的推导:
可以明显发现,每一次传播都能留下一个输入端的常数项,当然,要是想保留的话,每一层都能整成类似的格式:
这个的核心优点就在于反向传播的时候,有这样的形式:
由这一项可以看到,反向传播的时候损失信息稳定能直达每一个特定层的,而并非只要通过累乘的才能得到,大大降低了梯度弥散的程度,提升了反向传播的效率,也很大程度降低了梯度消失和梯度爆炸带来的影响。
这个理解算是比较直观的,所谓的润物细无声,就是一个这样的简单操作,能很大程度缓解训练过程梯度消失、爆炸和梯度弥散。
深入阅读
然而要是只局限在这个理解其实还不够,在Transformer和Bert出来以后,紧随其后的论文“attention is not all you need”中把残差网络提升到新的高度,文章指出如果没有残差网络(还有MLP),那么自注意力网络的输出出现“rank collapse”(我翻译为秩坍缩)的现象,最终会以指数的方式收敛到秩为1的矩阵,具体原理在论文里有详细的论证和实验(没错,就是有完整的证明和严格的实验),此处不展开说了,可以说是我最近看ptm里面数学味最浓的文章了。
论文:attention is not all you need。
解读:https://zhuanlan.zhihu.com/p/356956903
小结
之所以说残差网络是润物细无声,是因为在NLP领域可能提到的并不多,但其实在bert中起到了至关重要的作用,这个细节可以被吸收为一个trick,让我们能更加大胆的在效果调优过程中增加深度,进一步优化拟合效果。
参考资料
我的水平有限,部分内容可能讲的不太清楚或者有错误,这里参考了很多大佬的材料和文章,大家有兴趣可以深入阅读。
残差网络解决了什么,为什么有效?:https://zhuanlan.zhihu.com/p/80226180
一文读懂残差网络ResNet:https://zhuanlan.zhihu.com/p/91385516
BERT源码详解(一)——HuggingFace Transformers最新版本源码解读:https://zhuanlan.zhihu.com/p/360988428
论文:attention is not all you need。
解读:https://zhuanlan.zhihu.com/p/356956903