阅读Learning towards Minimum Hyperspherical Energy笔记
对于一些特征和权重,我们希望其结果不要都粘连到一起去,使得结果最后塌陷。那么有什么办法可以解决呢?
下面的NIPS2018的文章可以(https://arxiv.org/pdf/1805.09298.pdf)。
首先,我们定义一下这里的内积计算。首先向量先归一化
w
^
i
=
w
i
∣
∣
w
i
∣
∣
\hat{\bm{w}}_i = \frac{\bm{w}_i}{||\bm{w}_i||}
w^i=∣∣wi∣∣wi
此时内积的取值范围是
[
−
1
,
1
]
[-1,1]
[−1,1]。然后定义一个骚操作
δ
i
j
=
2
−
2
<
w
^
i
,
w
^
j
>
\delta_{ij} = 2 - 2<\hat{\bm{w}}_i,\hat{\bm{w}}_j>
δij=2−2<w^i,w^j>
这个数值
δ
i
j
∈
[
0
,
4
]
\delta_{ij} \in [0,4]
δij∈[0,4].
我们有一个核心任务,就是把对应的
w
\bm{w}
w尽可能地都分开,那么一个简单的想法就是.
min
E
=
1
δ
i
j
2
\min \bm{E} = \frac{1}{\delta_{ij}^2}
minE=δij21
泛化之
min
E
=
1
δ
i
j
s
(
s
>
0
)
\min \bm{E} = \frac{1}{\delta_{ij}^s}(s > 0)
minE=δijs1(s>0)
或者开一个对数损失
min
E
=
−
log
δ
i
j
\min \bm{E} = -\log \delta_{ij}
minE=−logδij
(这里和他论文中的写法有一点点小小的差异)。
来看看源代码是什么样子的。
def _add_thomson_constraint_final(self, filt, n_filt, power):
filt = tf.reshape(filt, [-1, n_filt])
filt_norm = tf.sqrt(tf.reduce_sum(filt*filt, [0], keep_dims=True) + 1e-4)
norm_mat = tf.matmul(tf.transpose(filt_norm), filt_norm)
inner_pro = tf.matmul(tf.transpose(filt), filt)
inner_pro /= norm_mat
if power =='0':
cross_terms = 2.0 - 2.0 * inner_pro
final = -tf.log(cross_terms + tf.diag([1.0] * n_filt))
final -= tf.matrix_band_part(final, -1, 0)
cnt = n_filt * (n_filt - 1) / 2.0
loss = 10 * tf.reduce_sum(final) / cnt
elif power =='2':
cross_terms = (2.0 - 2.0 * inner_pro + tf.diag([1.0] * n_filt))
final = tf.pow(cross_terms, tf.ones_like(cross_terms) * (-1))
final -= tf.matrix_band_part(final, -1, 0)
cnt = n_filt * (n_filt - 1) / 2.0
loss = 10 * tf.reduce_sum(final) / cnt
看看函数图像
图上越往4函数数值越小,而
4
=
2
−
(
−
2
)
4 = 2 - (-2)
4=2−(−2)。除此之外,该问题还可以泛化到球面上,也就是
min
E
=
−
log
(
1
π
arccos
<
w
^
i
,
w
^
j
>
)
\min \bm{E} = -\log \left(\frac{1}{\pi}\arccos <\hat{\bm{w}}_i,\hat{\bm{w}}_j>\right)
minE=−log(π1arccos<w^i,w^j>)
或者泛化一下
min
E
=
1
(
1
π
arccos
<
w
^
i
,
w
^
j
>
)
s
(
s
>
0
)
\min \bm{E} = \frac{1}{\left(\frac{1}{\pi}\arccos <\hat{\bm{w}}_i,\hat{\bm{w}}_j>\right)^s} (s>0)
minE=(π1arccos<w^i,w^j>)s1(s>0)
看看代码吧
def _add_thomson_constraint_final(self, filt, n_filt, power):
filt = tf.reshape(filt, [-1, n_filt])
filt_norm = tf.sqrt(tf.reduce_sum(filt*filt, [0], keep_dims=True) + 1e-4)
norm_mat = tf.matmul(tf.transpose(filt_norm), filt_norm)
inner_pro = tf.matmul(tf.transpose(filt), filt)
inner_pro /= norm_mat
if power == 'a0':
acos = tf.acos(inner_pro)/math.pi
acos += 1e-4
final = -tf.log(acos)
final -= tf.matrix_band_part(final, -1, 0)
cnt = n_filt * (n_filt - 1) / 2.0
loss = 10 * tf.reduce_sum(final) / cnt
elif power =='a1':
acos = tf.acos(inner_pro)/math.pi
acos += 1e-4
final = tf.pow(acos, tf.ones_like(acos) * (-1))
final -= tf.matrix_band_part(final, -1, 0)
cnt = n_filt * (n_filt - 1) / 2.0
loss = 1 * tf.reduce_sum(final) / cnt
藉由这个函数图像,可以帮助看官更好地理解之。
最后解决最重要的历史遗留问题,就是可能的反向共线性问题。看图就知道了。
在原始的问题假设中,两个向量被拉开的。但是,拉开的最差的情况,就是内积为
−
1
-1
−1。
−
1
-1
−1就是比较糟糕了,向量虽然反向,但是共线,这显然是非常扯的事情了。
那么该怎么办呢?我简单翻译一下作者要表达的意图,就是
min
E
=
1
δ
i
j
s
+
1
δ
−
i
j
s
(
s
>
0
)
\min \bm{E} = \frac{1}{\delta_{ij}^s} + \frac{1}{\delta_{-ij}^s} (s > 0)
minE=δijs1+δ−ijs1(s>0)
其中
δ
−
i
j
=
2
−
2
<
−
w
^
i
,
w
^
j
>
\delta_{-ij} = 2 - 2<\hat{-\bm{w}}_i,\hat{\bm{w}}_j>
δ−ij=2−2<−w^i,w^j>
或者说
min
E
=
−
log
δ
i
j
−
log
δ
−
i
j
\min \bm{E} = -\log \delta_{ij} -\log \delta_{-ij}
minE=−logδij−logδ−ij