这是算法找到的实际副本
第1步:获取激活
我们通常使用CNN对图像进行分类,只对网络末端的softmax输出感兴趣,它告诉我们网络认为图像标签是什么。在这种情况下,我们将比较网络的内层,希望网络学到的一些功能对于查找类似的图像很有用。为了实现这一点,我利用了fastai库中的强大callbacks 功能(代码页:https://docs.fast.ai/callbacks.hooks.html),它允许我们保存网络中任何子层的激活。
hook = hook_output(learn.model[0][7][2])
我使用的激活是Resnet架构的最后一个卷积块的输出,因为我注意到它们在经验上更好地工作。
第2步:合并
您可能知道,CNN中的隐藏层有四个维度:批量大小、高度、宽度和要素数量。假设我们正在谈论一个特定的图像,或者bs = 1。例如,在Resnet 50的情况下,最后一层的输出将具有尺寸(1,7,7,248 )。由于这里的维度非常高,计算相似性会非常耗时,这对用户来说是一种痛苦。这个问题的答案是使用Pooling(网址:http://deeplearning.stanford.edu/tutorial/supervised/Pooling/) 。我们将汇集每个7x7矩阵,以便得到一个维度张量(1,pool_dim,pool_dim,2048)。
我使用的池函数是AdaptiveConcatPooling(自适应平均池和自适应最大池连接在一起),使用的池维数是4,因为我发现它是速度和性能的良好组合。
第3步:展平
我们以四个维度的张量结束了最后一步。然而,为了计算不同示例之间的相似性,我们需要一维张量(向量)。我们将展平每个图像的激活以获得大小为pool_dim x pool_dim x 512的向量,并且我们将每个图像的向量连接成具有维度(n_exs,vector_dim)的矩阵。现在我们为每个n_exs图像都有一个特征向量。是时候计算相似之处了
def get_actns(learn:Learner, dl:DataLoader, hook:Hook, pool=AdaptiveConcatPool2d, pool_dim:int=4, train:bool=True): """Gets the activations at the layer specified by `hook`, applies `pool` of dim `pool_dim` and concatenates."""
pool = pool(pool_dim) actns = [] learn.model.eval() with torch.no_grad(): for i,(xb,yb) in enumerate(dl): learn.model(xb) actns.append((hook.stored).cpu()) return pool(torch.cat(actns)).view(len(dl.x), -1)
第4步:计算相似之处
为了计算每个特征向量之间的相似性,我们将使用余弦相似度函数。请注意,如果我们将每个向量与每个其他向量组合在一起,则所有相似度将被计算两次。还要注意,如果我们计算矢量与其自身的相似性,相似性的度量显然将是最高的。因此,对于我们的相似性矩阵,我们将用零替换对角线和右上角部分。
def comb_similarity(t1: torch.Tensor, t2: torch.Tensor, sim_func=nn.CosineSimilarity(dim=0)): """Computes the similarity function `sim_func` between each embedding of `t1` and `t2` matrices. t1` and `t2` should have dimensions [n_embeddings, n_features].""" self_sim = False if torch.equal(t1, t2): self_sim = True sims = np.zeros((t1.shape[0], t2.shape[0])) for idx1 in range(t1.shape[0]): for idx2 in range(t2.shape[0]): if not self_sim or idx1>idx2: ex1 = t1[idx1,:] ex2 = t2[idx2,:] sims[idx1][idx2] = sim_func(ex1,ex2) return sims
第五步:结果
让我们看看我们的方法是否有效!我用来测试算法的数据集是Oxford-IIIT Pet Dataset(http://www.robots.ox.ac.uk/~vgg/data/pets/),有37只狗和猫品种。
我还用计算机视觉中众所周知的数据集CIFAR10测试了算法,看看我是否能找到一些重复数据。这些是我发现的一些例子:
我还运行了relabeler小部件,这是一个额外有趣的发现:
一旦我们有网络的重复建议,我们应该怎么做?好吧,我们应该选择那些实际上是重复的并从我们的数据集中删除它们,因为重复会导致网络过于重视这些图像。我们如何轻松删除重复项?使用fastai的交互式小部件(https://github.com/fpingham/dataset-cleaner)非常容易!你可以通过运行来试试:
来自fastai.widgets进口*
ds,fns_idxs = DatasetFormatter.from_similars('learner') ImageCleaner(ds,fns_idxs,duplicates = True)
课程中所提到的网址整理如下:
fastai库:
https://github.com/fastai/fastai
callbacks 功能:
https://docs.fast.ai/callbacks.hooks.html
Pooling:
http://deeplearning.stanford.edu/tutorial/supervised/Pooling/
Oxford-IIIT Pet Dataset:
http://www.robots.ox.ac.uk/~vgg/data/pets/
fastai的交互式小部件:
https://github.com/fpingham/dataset-cleaner
信息来源:https://towardsdatascience.com/how-to-build-an-image-duplicate-finder-f8714ddca9d2