文章目录
https://zhuanlan.zhihu.com/p/363900943
上方链接有两个论文:
- 解决NMT的单词遗漏[acl2019]
- 常识推理的对比性自我监督学习
对比学习+聚类(Contrastive Clustering)
1 对比学习有多火?文本聚类都被刷爆了…
上方链接是 聚类+对比学习
来更好的对文本聚类。
聚类关注高层级的语义概念,对比学习增强的语句对更关注句子级别的。
2 我的另一篇博客Contrastive Clustering
分布对特征矩阵的行和列进行聚类和对比学习
Dropout来实现对比学习的数据增强(SimCSE)
说了:对比表示学习有用,主要是因为它优化了两个目标:
- 正例之间表示保持较近距离
- 机样例的表示应分散在超球面上。
提出这两个目标分别可以用指标alignment和uniformity来衡量:
alignment计算正例对之间的向量距离的期望:
越相似的样例之间的alignment程度越高。因为alignment使用距离来衡量,所以距离越小,表示alignment的程度越高。
uniformity评估所有数据的向量均匀分布的程度,越均匀,保留的信息越多
可以想象任意从表示空间中采样两个数据 和 , 希望他们的距离比较远。他们的距离越远,证明空间分布越uniform。所以uniformity的值也是越低越好。
SimCSE也采用这两个指标来衡量生成的句子向量,并证明了文本的语义空间也满足:alignment值越低且uniformity值越低,向量表示的质量越高,在STS任务上的Spearman相关系数越高。
多模态运用对比学习
博客、论文:吊打BERT、GPT、DALL·E,跨模态榜单新霸主诞生!
构建图片文字pairs,针对pairs做数据增强,再运用对比学习。
用对比学习来优化句子向量的表示
论文、博客:美团在ACL2021上提出基于对比学习的文本表示模型,效果提升8%
论文发现:直接从BERT导出的句向量表示往往被约束在一个很小的区域内,表现出很高的相似度,因而难以直接用于文本语义匹配。Bert导出的句向量(不经过Fine-tune,对所有词向量求平均)质量较低,甚至比不上Glove的结果。
该论文用数据增强的方式为:对Embedding层做数据增强。
并得出结论:Token Shuffle > Token Cutoff >> Feature Cutoff ≈ Dropout >> None
Contrastive Loss Layer为进行对比学习的层。
小batch_size
的对比学习损失函数
论文:Simpler, Faster, Stronger: Breaking The log-K Curse On Contrastive Learners With FlatNCE
由于对比学习希望拉大正负样本对的得分差,通常直接用交叉熵作为损失:
−
log
e
s
t
∑
i
e
s
i
=
log
(
∑
i
e
s
i
)
−
s
t
-\log \frac{e^{s_{t}}}{\sum_{i} e^{s_{i}}}=\log \left(\sum_{i} e^{s_{i}}\right)-s_{t}
−log∑iesiest=log(i∑esi)−st
−
log
e
s
t
∑
i
e
s
i
=
log
∑
i
e
s
i
e
s
t
=
log
(
1
+
∑
i
≠
t
e
s
i
e
s
t
)
=
log
(
1
+
∑
i
≠
t
e
s
i
−
s
t
)
-\log \frac{e^{s_{t}}}{\sum_{i} e^{s_{i}}}=\log \frac{\sum_i e^{s_i}}{e^{s_t}}=\log(1 + \frac{\sum_{i \neq t}e^{s_i}}{e^{s_t}})=\log \left(1+\sum_{i \neq t} e^{s_{i}-s_{t}}\right)
−log∑iesiest=logest∑iesi=log(1+est∑i=tesi)=log⎝⎛1+i=t∑esi−st⎠⎞
其中,
e
s
t
e^{s_t}
est为正样本对的得分,
e
s
i
e^{s_i}
esi为所有样本对的得分,当然,除了一个正样本,其他都是负样本。
令
ξ
=
∑
i
≠
t
e
s
i
−
s
t
\xi=\sum_{i \neq t} e^{s_{i}-s_{t}}
ξ=∑i=tesi−st,即使是一开始,
e
s
t
e^{s_t}
est一般也较大于
e
s
i
e^{s_i}
esi,则
e
s
i
−
s
t
≈
0
e^{s_{i}-s_{t}} \approx 0
esi−st≈0, 又因为batch_size
较小,所以
i
i
i也较少,则
ξ
≈
0
\xi\approx0
ξ≈0。
ξ \xi ξ接近0,损失函数也接近0,对应的的梯度也接近0,但梯度更新量不接近0,因为 梯度 梯度 ⊗ 梯度 × 学 习 率 \frac{\text { 梯度 }}{\sqrt{\text { 梯度 } \otimes \text { 梯度 }}} \times 学习率 梯度 ⊗ 梯度 梯度 ×学习率,更新量就会保持着 学 习 率 学习率 学习率 的数量级。
对比学习希望 e s t e^{s_t} est与 e s i e^{s_i} esi相差大,即 e s i − s t → 0 e^{s_{i}-s_{t}} \rightarrow 0 esi−st→0,即 s i − s t → − ∞ s_{i}-s_{t} \rightarrow-\infty si−st→−∞,但对比学习的打分( s i {s_i} si)通常是余弦值除以温度参数,所以它是有界的, s i − s t → − ∞ s_{i}-s_{t} \rightarrow-\infty si−st→−∞是无法实现的。然而, ξ \xi ξ的计算本身就存在浮点误差,当 ξ \xi ξ很接近于 0 时,浮点误差可能比精确值还要大,然后 log ( 1 + ξ ) \log(1+\xi) log(1+ξ)的计算也会存在浮点误差,再然后梯度的计算也会存在浮点误差,这一系列误差累积下来,很可能导致最后算出来的梯度都接近于随机噪声了,而不能提供有效的更新指引。
解决方法:
对函数做一阶展开: log ( 1 + ∑ i ≠ t e s i − s t ) ≈ ∑ i ≠ t e s i − s t \log \left(1+\sum_{i \neq t} e^{s_{i}-s_{t}}\right) \approx \sum_{i \neq t} e^{s_{i}-s_{t}} log⎝⎛1+i=t∑esi−st⎠⎞≈i=t∑esi−st, ξ \xi ξ就相当于损失函数, ξ \xi ξ乘以一个常数,其梯度不变,则梯度更新量不变,这样, ξ \xi ξ就变大了。
我们使其乘以
ξ
\xi
ξ的倒数,
s
g
(
ξ
)
sg(\xi)
sg(ξ)是stop_gradient,不计算导数的意思。
∇
θ
(
ξ
sg
(
ξ
)
)
=
∇
θ
ξ
ξ
=
∇
θ
log
ξ
\nabla_{\theta}\left(\frac{\xi}{\operatorname{sg}(\xi)}\right)=\frac{\nabla_{\theta} \xi}{\xi}=\nabla_{\theta} \log \xi
∇θ(sg(ξ)ξ)=ξ∇θξ=∇θlogξ
推导上式的时候,注意分母的
ξ
\xi
ξ为常数。
我们把损失函数变为:
log
(
∑
i
≠
t
e
s
i
−
s
t
)
=
log
(
∑
i
≠
t
e
s
i
)
−
s
t
\log \left(\sum_{i \neq t} e^{s_{i}-s_{t}}\right)=\log \left(\sum_{i \neq t} e^{s_{i}}\right)-s_{t}
log⎝⎛i=t∑esi−st⎠⎞=log⎝⎛i=t∑esi⎠⎞−st
,
l
o
g
∘
s
u
m
∘
e
x
p
log\circ sum \circ exp
log∘sum∘exp通常可以有效地计算,浮点误差不会占主导。
实验结果:
作者提出的FlatNCE
在小batch_size上效果比较好,在大batch_size上收敛的也比较快。