从图片相似度学习图片的表示
<p>很多时候带分类标注的图片样本是很难获得的,但是图片之间的相似度却不难获得。最简单的方式有几个:</p> <ul> <li>视频里相邻的帧是相似的。</li> <li>如果有用户日志数据,可以基于协同过滤计算图片之间的相似度。</li> </ul> <p>最早用来从相似图片数据集上学习图片表示的网络结构是siamese网络。</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/0688ed05a517bc554954d7f5eed1ccc1.png"></p> <p style="text-align: center;">siamese.png</p> <p>两幅图通过两个共享权重的CNN得到各自的表示。而各自表示的距离决定了他们是相似还是不相似。</p> <p>在siamese网络之后,又提出了用triplet loss来学习图片的表示,大概思路如下:</p> <ul> <li>拿到3张图片A, B, C。其中A,B相似,A,C不相似。</li> <li>学到A, B, C 的表示,使得A,B之间的距离尽量小,而A,C之间的距离尽量大。</li> </ul> <p>用mxnet实现triplet loss很简单,代码如下:</p> <pre> def get_net(batch_size): same = mx.sym.Variable('same') diff = mx.sym.Variable('diff') anchor = mx.sym.Variable('anchor') one = mx.sym.Variable('one') one = mx.sym.Reshape(data = one, shape = (-1, 1)) conv_weight = [] conv_bias = [] for i in range(3): conv_weight.append(mx.sym.Variable('conv' + str(i) + '_weight')) conv_bias.append(mx.sym.Variable('conv' + str(i) + '_bias')) fc_weight = mx.sym.Variable('fc_weight') fc_bias = mx.sym.Variable('fc_bias') fa = get_conv(anchor, conv_weight, conv_bias, fc_weight, fc_bias) fs = get_conv(same, conv_weight, conv_bias, fc_weight, fc_bias) fd = get_conv(diff, conv_weight, conv_bias, fc_weight, fc_bias) fs = fa - fs fd = fa - fd fs = fs * fs fd = fd * fd fs = mx.sym.sum(fs, axis = 1, keepdims = 1) fd = mx.sym.sum(fd, axis = 1, keepdims = 1) loss = fd - fs loss = one - loss loss = mx.sym.Activation(data = loss, act_type = 'relu') return mx.sym.MakeLoss(loss)</pre> <p>这里conv_weight[], fc_weight, conv_bias[], fc_bias是两个CNN网络共享的模型。理论上这里可以用任何的CNN网络(AlexNet, GoogleNet, ResNet)。我们用了一个特别简单的CNN,如下:</p> <pre> def get_conv(data, conv_weight, conv_bias, fc_weight, fc_bias): cdata = data ks = [5, 3, 3] for i in range(3): cdata = mx.sym.Convolution(data=cdata, kernel=(ks[i],ks[i]), num_filter=32, weight = conv_weight[i], bias = conv_bias[i], name = 'conv' + str(i)) cdata = mx.sym.Pooling(data=cdata, pool_type="avg", kernel=(2,2), stride=(1, 1)) cdata = mx.sym.Activation(data=cdata, act_type="relu") cdata = mx.sym.Flatten(data = cdata) cdata = mx.sym.FullyConnected(data = cdata, num_hidden = 1024, weight = fc_weight, bias = fc_bias, name='fc') cdata = mx.sym.L2Normalization(data = cdata) return cdata</pre> <p>Triple loss用的 Simultaneous Feature Learning and Hash Coding with Deep Neural Networks 里的定义:</p> <p><img src="https://simg.open-open.com/show/3c9ee72e5ffa966e45e271c2f95eb244.png"></p> <p>Triple Loss</p> <p>下面是在cifar10数据集上测试的结果。为了形象的表示,采用了图片检索的方式(因为不是论文,所以就不那么严谨了)。在训练集上学习图片的表示,然后对于测试集的一张随机图片,找到测试集上和他最相似的其他图片:</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/0383550c1c8f393a0879391569cbe638.png"></p> <p style="text-align: center;">cifar_triple.png</p> <p>在其他的论文中还有一些其它评测方式,比如学习到表示后,用一个SVM去学习分类,看看分类的准确度相比End-End的CNN如何。基本的结论都是精度会稍微低一些,但是没用明显区别。这说明学到的表示是靠谱的。</p> <p> </p> <p> </p> <p>来自:http://www.jianshu.com/p/70a66c8f73d3</p> <p> </p>
本文由用户 suiaing 自行上传分享,仅供网友学习交流。所有权归原作者,若您的权利被侵害,请联系管理员。
转载本站原创文章,请注明出处,并保留原始链接、图片水印。
本站是一个以用户分享为主的开源技术平台,欢迎各类分享!