《Semantic Structure-based Unsupervised Deep Hashing》相似矩阵构造方法

Notes

SSDH[1]做的是 hashing 式的图像检索,用图像的 VGG-F fc-7 layer feature 计算各样本间的距离,并基于此距离构造相似矩阵指导 hash code 的学习。
其构造相似矩阵的思路是:两个样本之间,距离分成三类,

  • 特别近,认为它们相似, S i j = 1 S_{ij}=1 Sij=1
  • 特别远,认为不相似, S i j = − 1 S_{ij}=-1 Sij=1
  • 不远不近,不确定, S i j = 0 S_{ij}=0 Sij=0

作者先将样本间的距离(文中用了 cosine 距离)算出来,观察这些距离值的分布的概率密度函数(文中 Figure 1(b)),发现有点像两个半边的正态分布(文中 Figure 1 (c)、(d))拼在一起的样子。
于是在最高点处劈开两边(即将数据分成两部分),一边各是一个半边的正态分布,分别拟合这两个正态分布,得到它们的均值和标准差: m l , σ l m_l, \sigma_l ml,σl m r , σ r m_r, \sigma_r mr,σr,再利用这两组 m , σ m,\sigma m,σ 构造两个距离阈值: d s = m l − α σ l d_s=m_l-\alpha\sigma_l ds=mlασl d d = m r + β σ r d_d=m_r+\beta\sigma_r dd=mr+βσr其中 α , β \alpha,\beta α,β 是超参)。然后定义相似矩阵:
S i j = { 1 , d ( i , j ) ≤ d s 0 , d s < d ( i , j ) < d d − 1 , d ( i , j ) ≥ d d S_{ij}=\begin{cases} 1, & d(i,j)\le d_s \\ 0, & d_s<d(i,j)<d_d \\ -1, & d(i,j)\ge d_d \end{cases} Sij=1,0,1,d(i,j)dsds<d(i,j)<ddd(i,j)dd
其中 d(i,j) 表示样本 i 和样本 j 之间的距离。
拟合正态分布获得均值和标准差的过程可以直接调 scipy.stats.norm.fit()[3] 完成,不用自己写。

Code

这是作者释出代码中构造相似矩阵的部分,详见 [2]。

# 数据距离
euc_ = pdist(train_features, 'cosine')
euc_dis = squareform(euc_)
orig_euc_dis = euc_dis

# 试探分界点:距离分布密度的最高点所在
start = -0.00000001
margin = 1.0/100  # 组距(dx)
num = np.zeros(100)
max_num = 0.0
max_value = 0.0
for i in range(100):
	# (start, end) 定义了一个组距
    end = start + margin
    # 统计直方图中这个组距对应的那条柱
    temp_matrix = (euc_dis > start) & (euc_dis < end)
    num[i] = np.sum(temp_matrix)  # 频数
    if num[i] > max_num:
        max_num = num[i]  # 最大频数 -> 对应最大密度
        max_value = start
    start = end

# 数据分界:left-Gaussian & right-Gaussian
euc_dis = euc_dis.reshape(-1, 1)
left = []
right = []
for i in range(euc_dis.shape[0]):
    if euc_dis[i] <= max_value:
        left.append(euc_dis[i])
    else:
        right.append(euc_dis[i])
left = np.array(left)
right = np.array(right)

# 补全为完整的 Gaussian 分布数据(补上另一半)
fake_right = 2 * max_value - left
fake_left = 2 * max_value - right
left_all = np.concatenate([left, fake_right])
right_all = np.concatenate([fake_left, right])

# 拟合高斯分布 <- 直接掉 scipy 的包
l_mean, l_std = norm.fit(left_all)
r_mean, r_std = norm.fit(right_all)

# 得相似矩阵
S1 = ((orig_euc_dis < l_mean-2*l_std))*1.0  # 明显小的为 similar
S2 = ((orig_euc_dis > r_mean+2*r_std))*(-1.0)  # 明显大的为 disimilar
S = S1 + S2

References

  1. Semantic Structure-based Unsupervised Deep Hashing(paper)
  2. yangerkun/IJCAI2018_SSDH(code)
  3. scipy.stats.norm
  4. Markdown编辑分段函数

你可能感兴趣的:(机器学习)