1.了解siamese
出发点:因项目需求,需要在不同的图中找到同一个物体,类似ReID
实际效果:效果挺好
使用框架:caffe
原理:这个网络叫做siamese,caffe自带demo,请自行谷歌相关资料
损失函数:
简单的讲,就是标签y=1(相同)时,相似度越大,损失函数越小,训练是最小化损失函数,标签y=0(不同)时采用惩罚机制,相似度越小,损失函数越小。其中d是欧式距离后面还会说一下欧式距离和余弦距离的优缺点,margin是一个惩罚值需要根据自己的数据集确定大小确定依据是玄学。
这里caffe的地址的exmples/siamese下可以看到demo工程,打开最重要的mnist_siamese_train_test.prototxt文件很让人失望,这个是针对于手写字体的识别,用的是单通道的图像而且使用了Slice层(切片层)。这个模型的长这个样子:
输入的是一个两个单通道的图像相叠加,和一个标签,然后在网络中使用Slice层进行切开,然后是两个权值共享的lenet最后提取特征后怼如对比损失函数。
2.修改网络
看到这里对于一个开发人员来讲就是放弃这个demo去网上找有没有人去修改这个网络使之适用于生产项目中,但是去搜的话会看见很多人把ContrastiveLoss转载了一遍又一遍。废话不多讲这个网络肯定不能使用,从这个网络中我们可以得到启发:Siamese的组成两个图像输入一个标签输入、权值共享网路、ContrastiveLoss于是经过很多次的尝试和各种资料大神坑的参考采用人类最直观的想法设计了这样一个网络:
比上面那个要直观简洁很多,该网络包括两个图像输入、两个标签、caffenet提取特征(去全连接层)、ContrastiveLoss直接解释可能会有的疑问:
1.输入的是3通道的图像
2.两个标签输入纯属为了迎合caffe的输入要求,实际使用会自行丢弃一个,因为不这么做就运行不起来
3.去全连接层,因为是为了提取图像特征不是为了分类,全连接会拖慢运行速度,最重要的是这是实际测试的结果。
4.可以考虑使用其他的提取特征的网络,比如resnet,mobilenet,vgg等等,本人经过测试使用的网络应包含权重和偏置,比如resnet和mobilenet没有偏置,会影响最终结果(虽然微乎其微)。最终使用caffenet的原因是感觉比较好。
3.训练
下面到了大家最喜欢的环节直接上代码https://github.com/l1uw3n/siamese-projict,好用的话给个star,其中当然运行这些代码需要基于caffe的环境,需要有caffe的基础,另外需要改动一些文件的路径我在上传过程中屏蔽了我的个人路径,在train_siamese.prototxt文件中使用到了5个文件两个训练、两个测试、一个mean,训练的文件的列表在data文件夹下,两个文件是对应的同目标的是1不同目标的是0,大家自行观察一下就明白训练原理了。这里需要注意的有1.数据大家自行去处理,可以使用lwf人类数据2.训练时一定不能打乱图像顺序。此外我还准备了lmdb制作和均值文件的制作代码,同样也需要修改自己的路径。还有训练的脚本,包括超参数也调好了。训练过程如下:
这个怎么评判呢 ,评判标准是在margin不是很大的情况下loss足够小并且收敛。
最终训练好了之后会得到一个权重文件,就可以预测了,直接上修改后的预测代码!在src中代码已经修改好了,感兴趣的自己去看吧,这里有一个比较巧妙的地方是对于deploy的修改最后一层的输出层我使用了EuclideanLoss代替,因为这个层就是欧式距离层省了自己计算了。
4.测试
看看最总效果吧:
Prediction = 0.478233
Prediction = 1.01193
Prediction = 8.54355
Prediction = 0.170693
Prediction = 7.08859
Prediction = 3.55699
Prediction = 3.58375
Prediction = 3.783
其中数据越小说明越相似!
5.余弦距离和欧式距离
其中余弦距离是指的方向距离,受物体的大小清晰度影响小,欧式距离是判断的像素距离,受物体的周围的环境,图像的清晰度影响大。
如果要转载的话请注明出处!如果有新的见解欢迎讨论。