Re-ID with Triplet Loss

2023-12-13 11:18
文章标签 id re loss triplet

本文主要是介绍Re-ID with Triplet Loss,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一篇讲Person Re-ID的论文,与人脸识别(认证)有很多相通的地方。

文章链接: 《In Defense of the Triplet Loss for Person Re-Identification》

Github链接:https://github.com/VisualComputingInstitute/triplet-reid 目前还没有放出代码,作者说等论文录用了就放出来。

    • Introduction
    • Triplet Loss
        • Large Margin Nearest Neighbor loss
        • FaceNet Triplet Loss
        • Batch All Triplet Loss
        • Batch Hard Triplet Loss
        • Lifted Embedding Loss
        • Distance Measure
        • Soft-margin
    • Experiments
        • 多种Triplet Loss性能对比
        • To Pretrain or not to Pretrain
        • Trick
    • 参考文献

Introduction

Re-ID和图像检索有点类似。这样来看,Google的FaceNet利用Triplet Loss训练的高度嵌入的特征,似乎很适合做这样大范围的快速比对。 但是,很多的研究文献表明常见的classification或者结合verification Loss比Triplet Loss似乎更适合这个任务。 他们通常将CNN作为特征提取器,后面再接专门的测度模型。但是这两种Loss有着明显的缺点:

Classification Loss: 当目标很大时,会严重增加网络参数,而训练结束后很多参数都会被摒弃。

Verification Loss: 只能成对的判断两张图片的相似度,因此很难应用到目标聚类和检索上去。因为一对一对比太慢。

但是 Triplet Loss还是很吸引人啊: 端到端,简单直接; 自带聚类属性; 特征高度嵌入。

为什么Triplet训不好呢或者说不好训呢?

首先需要了解,hard mining在Triplet训练中是一个很重要的步骤。 没有hard mining会导致训练阻塞收敛结果不佳,选择过难的hard又会导致训练不稳定收敛变难。此外,hard mining也比较耗时而且也没有清楚的定义什么是 “Good Hard”。

文章的贡献主要有两个方面:

(1) 设计了新的Triplet Loss,并和其它变种进行了对比。

(2) 对于是否需要 pre-trained模型,进行了实验对比分析。

Triplet Loss

这一小节主要介绍几种Triplet 变种。

Large Margin Nearest Neighbor loss

比较早的Triplet形式(参考文献[1])。 \(L_{pull}\) 表示拉近属于同一目标的样本; \(L_{push}\) 表示拉远不同目标的样本。

float

由于是最近邻分类,所以同一类当中可能有多个cluster,而且固定的cluster中心也比较难以确定。

FaceNet Triplet Loss

Google的人脸认证模型FaceNet(参考文献[2]), 不要求同类目标都靠近某个点,只要同类距离大于不同类间距离就行。完美的契合人脸认证的思想。

float

Batch All Triplet Loss

FaceNet Triplet Loss训练时数据是按顺序排好的3个一组3个一组。假如batch_size=3B,那么实际上有多达 \(6B^2-4B\)种三元组组合,仅仅利用B组就很浪费。

所以我们可以首先改变一下数据的组织方式:\(batch\ size = K\times B\),即随机地选出K个人,每个人随机地选B张图片。 这样总共会有 \(PK(PK-K)(K-1)\)种组合,计算loss时就按照下式统计所有可能。

float

Batch Hard Triplet Loss

Batch All Triplet Loss看起来一次可以处理非常多的三元组,但是有一点很尴尬:数据集非常大时训练将会非常耗时,同时随着训练深入很多三元组因为很容易被分对而变成了“无用的”三元组。

怎么办? Hard Mining. 但是,过难得三元组又会导致训练不稳定,怎么办? Mining Moderate Hard.

作者定义了下面的“较难”的Triplet Loss,之所以是“较难”,是因为只是在一个小的Batch里面选的最难的。

float

其中 \(x_j^i\) 表示第 \(i\) 个人的第 \(j\)张图片。

Lifted Embedding Loss

文献[3]针对3个一组3个一组排列的batch,提出了一种新的Loss:将anchor-positive pair之外的所有样本作为negative,然后优化Loss的平滑边界。

float

文章针对 \(batch\ size = K\times B\)的形式对上式稍作改进:

float

Distance Measure

很多相关工作中,都使用平方欧式距离 \(D(a,b) = |a-b|_2^2\) 作为度量函数。 作者虽然没有系统对比过其它度量函数,但是在实验中发现非平方欧氏距离 \(D(a,b) = |a-b|_2\) 表现的更为稳定。 同时,使用非平方欧氏距离使得margin 这个参数更具有可读性。

Soft-margin

之前的很多Triplet Loss都采用了截断处理,即如果Triplet三元组关系正确则Loss直接为0。 作者发现,对于Re-ID来说,有必要不断地拉近同类目标的距离。因此,作者设计了下面的soft-margin函数:

\(s(x) = ln(1+e^x)\)

Experiments

多种Triplet Loss性能对比

float

(1) 没有Hard Mining的 \(L_{tri}\)往往模型效果不好,如果加上简单的offline hard-mining(OHM),则效果很不稳定,有时候很好有时候完全崩掉。

(2) Batch Hard形式的 \(L_{BH}\)整体表现好于 Batch All形式的 \(L_{BA}\)。作者猜测,训练后期很多三元组loss都是0,然后平均处理时会把仅剩的有用的信息给稀释掉。为了证明该猜想,作者计算平均loss时只考虑那些不为0的,用 \(L_{BA\neq 0}\)表示,发现效果确实会变好。

(3) 在作者的Re-ID实验中,Batch Hard + soft-margin的效果最好,但是不能保证在其他任务中这种组合依然是最好的,这需要更多的实验验证。

To Pretrain or not to Pretrain?

TriNet表示来自pre-trained model,LuNet是作者自己设计的一个普通网络。

float

从上面的表格来看,利用pre-trained model确实可以获得更好一点的效果,但是从头开始训练的网络也不会太差。

特别的,pre-trained model往往体积较大模式固定,不如自己设计网络来的灵活。同时,pre-trained model往往有其自己的固定输入,我们如果修改其输入很可能会得到相反的效果。如下表:

float

Trick

(1) 没有必要对输出特征进行归一化;

(2) 如果使用了hard mining, 单纯的看loss变化往往不能正确把握训练的进程。作者推荐观察一个batch中的有效三元组个数,或者所有pair间的距离。

(3) 初始margin不宜过大;

参考文献

[1] K. Q. Weinberger and L. K. Saul. Distance Metric Learning for Large Margin Nearest Neighbor Classification. JMLR,10:207–244, 2009

[2] F. Schroff, D. Kalenichenko, and J. Philbin. FaceNet: A Unified Embedding for Face Recognition and Clustering. In CVPR, 2015

[3] H. O. Song, Y. Xiang, S. Jegelka, and S. Savarese. Deep Metric Learning via Lifted Structured Feature Embedding. In CVPR, 2016

这篇关于Re-ID with Triplet Loss的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/488269

相关文章

4-4.Andorid Camera 之简化编码模板(获取摄像头 ID、选择最优预览尺寸)

一、Camera 简化思路 在 Camera 的开发中,其实我们通常只关注打开相机、图像预览和关闭相机,其他的步骤我们不应该花费太多的精力 为此,应该提供一个工具类,它有处理相机的一些基本工具方法,包括获取摄像头 ID、选择最优预览尺寸以及打印相机参数信息 二、Camera 工具类 CameraIdResult.java public class CameraIdResult {

集群环境下为雪花算法生成全局唯一机器ID策略

雪花算法是生成数据id非常好的一种方式,机器id是雪花算法不可分割的一部分。但是对于集群应用,让不同的机器自动产生不同的机器id传统做法就是针对每一个机器进行单独配置,但这样做不利于集群水平扩展,且操作过程非常复杂,所以每一个机器在集群环境下是一个头疼的问题。现在借助spring+redis,给出一种策略,支持随意水平扩展,肥肠好用。 大致策略分为4步: 1.对机器ip进行hash,对某一个(大于

在实现回显功能模块的时候,把ID设置成全局变量了

在hsapprove.jsp中: <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><script type="text/javascript">function edittodayhs(hsid){//alert(hsid);//

PL/SQL工具创建Oracle数据库表,实现id字段的自动递增

通过PL/SQL工具,创建Oracle数据库表,如何实现字段ID自动递增; Oracle的自增需要依靠序列和触发器共同实现 比如:先创建一个表 create table test (id int primary key, name varchar2(10)); 创建一个序列 create sequence test_seq increment by 1 start with 1  min

分布式项目中使用雪花算法提前获取对象主键ID

hello,大家好,我是灰小猿! 在做分布式项目开发进行数据表结构设计时,有时候为了提高查询性能,在进行数据库表设计时,会使用自增ID来代替UUID作为数据的主键ID,但是这样就会有一个问题,数据的自增ID应该如何获取到下一个ID并且插入到库中呢? 如果你使用的是mybatisPlus,可以使用自带的自增注解加在id字段上即可,这样在数据入库时就可以自动给数据赋值自增的主键ID, 但是对于不

013.Python爬虫系列_re正则解析

我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈 入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈 虚 拟 环 境 搭 建 :👉👉 Python项目虚拟环境(超详细讲解) 👈👈 PyQt5 系 列 教 程:👉👉 Python GUI(PyQt5)文章合集 👈👈 Oracle数据库教程:👉👉 Oracle数据库文章合集 👈👈 优

《长得太长也是错?——后端 Long 型 ID 精度丢失的“奇妙”修复之旅》

引言 在前后端分离的时代,我们的生活充满了无数的机遇与挑战——包括那些突然冒出来的让人抓狂的 Bug。今天我们要聊的,就是一个让无数开发者哭笑不得的经典问题:后端 Long 类型 ID 过长导致前端精度丢失。说到这个问题,那可真是“万恶之源”啊,谁让 JavaScript 只能安全地处理 Number.MAX_SAFE_INTEGER(也就是 9007199254740991)以内的数值呢?

练习实践-git工具-id:1-git 工具的基础命令

参考来源: csdn技能树-git https://fishc.com.cn/forum-334-1.html fishc论坛的扩展阅读 git能做什么? 进行版本控制,版本记录、版本回退; 需求场景:一个新的开发项目,随着功能的增加,代码量、相关文件数量也在逐渐增多…… 这样开发就会遇到一个问题:当需要修改一些代码的时候,不得已要删除另外一些代码。第二天脑袋突然被门框给夹了一下,又想恢复回

练习实践-git工具-id:2-git 仓库部分的基础命令

参考来源: csdn技能树-git https://fishc.com.cn/forum-334-1.html fishc论坛扩展阅读-git实用教程 git分支的实现原理理解–三棵树-工作、缓存、仓库 1.创建一个新文件license,修改readme.txt文件内容,之后查看git状态信息 F:\tmp\learning-git>echo "This is a license." >

update 返回更新的行的 id

应用软件开发过程中, 经常碰到 用 SQL 语句 更新表后, 希望 获取 更新的行 的 id ,  可以通过 以下方法 获取   update [user] set userPwd = '123' output inserted.id , inserted.userName where userName like 'mk%' 更新到多行时,这个方法仍然可用