python - 在 numpy 中矢量化 VLAD 计算
问题描述
我想知道是否可以对 VLAD 计算的这种实现进行矢量化。
对于上下文:
feats
=形状的numpy数组(T, N, F)
kmeans
= 使用集群初始化的 scikit-learn 中的 KMeans 对象K
。
当前方法
k = kmeans.n_clusters # K
centers = kmeans.cluster_centers_ # (K, F)
vlad_feats = []
for feat in feats:
# feat shape - (N, F)
cluster_label = kmeans.predict(feat) #(N,)
vlad = np.zeros((k, feat.shape[1])) # (K, F)
# computing the differences for all the clusters (visual words)
for i in range(k):
# if there is at least one descriptor in that cluster
if np.sum(cluster_label == i) > 0:
# add the differences
vlad[i] = np.sum(feat[cluster_label == i, :] - centers[i], axis=0)
vlad = vlad.flatten() # (K*F,)
# L2 normalization
vlad = vlad / np.sqrt(np.dot(vlad, vlad))
vlad_feats.append(vlad)
vlad_feats = np.array(vlad_feats) # (T, K*F)
批量获取 kmeans 预测不是问题,我们可以执行以下操作:
feats2 = feats.reshape(-1, F) # (T*N, F)
labels = kmeans.predict(feats2) # (T*N, )
但我被困在计算集群距离上。
解决方案
您已经开始采用正确的方法。让我们尝试将所有行一一拉出循环。首先,预测:
cluster_label = kmeans.predict(feats.reshape(-1, F)).reshape(T, N) # T, N
您实际上并不需要 check np.sum(cluster_label == i) > 0
,因为无论如何总和都会变成零。您的目标是将每个和特征K
中的每个标签与中心的距离相加。T
您可以使用简单的广播来计算k
掩码。cluster_label == i
你会希望最后一个维度是K
:
mask = cluster_label[..., None] == np.arange(k) # T, N, K
您还可以使用更复杂的广播来计算k
差异:feats - centers[i]
delta = feats[..., None, :] - centers # T, N, K, F
您现在可以将差异乘以掩码并N
通过求和沿维度减少:
vlad = (delta * mask[..., None]).sum(axis=1).reshape(T, -1) # T, K * F
从这里开始,标准化应该是微不足道的:
vlad /= np.linalg.norm(vlad, axis=1, keepdims=True)
推荐阅读
- python - 从二维数组矢量化中获取值
- c# - How to use the C# g4 grammar with antlr in Python?
- angular - 如何在鼠标事件绑定中传递参数
- delphi - 过程调用中的 Tstringlist 与 Tstrings
- python - 列出的列表返回索引值
- r - 如何根据名称文本将多个变量与 R 中的特定模式合并?
- javascript - 在指针事件为 null 的元素上“单击”(或替代方法)
- mysql - ModuleNotFoundError:导入 mysql 时没有名为“_version”的模块
- c# - 在单击 Xamarin.Forms.Maps 时添加图钉
- r - 在 R 中使用 sapply 而不是循环