【论文阅读12】Circle Loss:一统 Softmax 与 Triplet,从“线性”到“圆形”的优化视角

论文题目:《Circle Loss: A Unified Perspective of Pair Similarity Optimization》

目录

前言:两大门派的恩怨

派系一:基于分类的学习 (Classification-based)

派系二:基于度量的学习 (Metric Learning / Pairwise Learning)

为什么要提这个?(Circle Loss 的动机)

1. 万物归一 —— 统一视角 ()

1.1 统一 Loss 公式

1.2 计算量的“降维打击”

2. 证明 Softmax 和 Triplet 都是“特例”

2.1 退化为 Softmax ()

2.2 退化为 Triplet ()

3. 发现缺陷 —— 拒绝“死板”的优化

3.1 什么是“不够灵活”?

3.2 引入动态权重 ()

3.3 Circle Loss 最终形态

4. 几何解释 —— 为什么叫“Circle”?

4.1 决策边界的演变

4.2 圆形的意义

5. 梯度验证 —— 数学上的实锤


前言:两大门派的恩怨

派系一:基于分类的学习 (Classification-based)

  • 代表:Softmax, SphereFace, CosFace, ArcFace。
  • 原文描述:“优化样本和权重向量之间的相似性” (optimize the similarity between samples and weight vectors)。
  • 通俗解释(找老师)

公式特征

$x \cdot W$

训练目标:学生(样本

$x$

)必须尽可能靠近自己的班主任( 

$W_{y_i}$

 ),远离别人的班主任。

逻辑:模型预先设立了 10,000 个“教室”(类别),每个教室有一个“班主任”( 

$W$

 )。

权重

$W$

:被看作是类中心(Class Center)或者代理(Proxy)

派系二:基于度量的学习 (Metric Learning / Pairwise Learning)

  • 代表:Triplet Loss, Contrastive Loss。
  • 原文描述:“优化样本之间的相似性” (optimize the similarity between samples)。
  • 通俗解释(找朋友)
    • 逻辑:模型从数据堆里随便抓两个人。
    • 训练目标:如果这两个人是同一个人(Positive Pair),就拉近他们;如果是不同人(Negative Pair),就推开他们。

公式特征

$x_1 \cdot x_2$

没有

$W$

:这里没有固定的“教室”和“班主任”。

为什么要提这个?(Circle Loss 的动机)

在 Circle Loss 之前,大家觉得这是两套完全不同的逻辑:

  • 用 Softmax (ArcFace) 的人觉得 Triplet Loss 收敛太慢,采样太麻烦(组合爆炸)。
  • 用 Triplet Loss 的人觉得 Softmax 只能处理闭集(Closed-set),不灵活。

Circle Loss 的伟大之处在于它说了一句:

“别吵了,其实你们俩在数学本质上是一回事!”

Circle Loss 认为:

Triplet:其实就是把另一个样本

$x_j$

  当作临时的“中心”。

Softmax/ArcFace:其实就是把

$W$

当作一种特殊的“样本”(只有一个样本的类)。

它们的目标都是:最大化类内相似度 ( 

$s_p$

 ),最小化类间相似度 ( 

$s_n$

 )。


1. 万物归一 —— 统一视角 (

$L_{uni}$

)

        Circle Loss 的第一步贡献,是建立了一个统一的 Loss 框架。作者敏锐地发现,无论是分类还是配对,本质目标都是:最大化正样本分数

$s_p$

,最小化负样本分数

$s_n$

1.1 统一 Loss 公式

作者首先推导出了一个通用公式

$L_{uni}$

(Unified Loss):

$L_{uni} = \log \left[ 1 + \sum_{i=1}^K \sum_{j=1}^L \exp(\gamma(s_n^j - s_p^i + m)) \right]$
$m$

:间隔(Margin)。

$\gamma$

:缩放因子(Scale Factor)。

$s_n^j$

:第

$j$

个负样本对的相似度。

$s_p^i$

:第

$i$

个正样本对的相似度。

这个公式的直观含义很简单:要在

$Loss$

最小化过程中,迫使

$(s_n - s_p)$

越小越好。

1.2 计算量的“降维打击”

上面的公式有一个双重求和

$\sum \sum$

,这意味着要计算所有正负样本的配对,计算量是

$O(K \times L)$

利用指数运算法则

$e^{a-b} = e^a \cdot e^{-b}$

,作者做了一个精彩的数学变换:

$L_{uni} = \log \left[ 1 + \underbrace{\sum_{j=1}^L \exp(\gamma(s_n^j + m))}_{\text{}} \cdot \underbrace{\sum_{i=1}^K \exp(\gamma(-s_p^i))}_{\text{}} \right]$

                                   负样本集合                 正样本集合

这一步变换至关重要。它将复杂的 “成对比较” 解耦成了独立的  “正样本组”  和  “负样本组” 计算。这解释了为什么 Circle Loss 能够像 Softmax 一样高效训练,而不需要像 Triplet Loss 那样进行繁重的样本挖掘。


2. 证明 Softmax 和 Triplet 都是“特例”

为了证明

$L_{uni}$

是真正的大一统,我们看看它是如何退化成我们熟悉的 Loss 的。

2.1 退化为 Softmax (

$L_{am}$

)

如果我们设定只有一个正样本(

$K=1$

,即当前样本

$x$

和它的类中心

$W$

),忽略常数 1,公式就变成了:

$L_{am} = - \log \frac{\exp(\gamma(s_p - m))}{\exp(\gamma(s_p - m)) + \sum_{j=1}^{N-1} \exp(\gamma s_n^j)}$

解读: 这正是我们熟悉的 CosFace / AM-Softmax

这意味着:分类 Loss 只是 Circle Loss 在

$K=1$

时的特例。

2.2 退化为 Triplet (

$L_{tri}$

)

如果我们把

$\gamma$

设为无穷大(

$\gamma \to +\infty$

),根据 LogSumExp 的极限性质,公式变成了:

$L_{tri} = \lim_{\gamma \to +\infty} \frac{1}{\gamma} L_{uni} = \max [ s_n^j - s_p^i ]_+$

解读: 这正是 Triplet Loss 的核心逻辑(Hard Mining)!

这意味着:Triplet Loss 只是 Circle Loss 在

$\gamma$

趋于无穷大时的极限情况。


3. 发现缺陷 —— 拒绝“死板”的优化

既然统一了江湖,为什么还需要 Circle Loss?

因为作者发现,之前的 CosFace/ArcFace 存在一个致命的“不够灵活”的问题。

3.1 什么是“不够灵活”?

$L_{uni}$

中,我们是在优化

$(s_n - s_p)$

。当我们对它求导时,梯度是常数(或者说是 1)。

这意味着什么?

  • 困难样本(分错了):模型用 1 的力度去推它。
  • 简单样本(分对了):模型依然用 1 的力度去推它。

这就好比老师辅导学生,对考 30 分的学生和考 99 分的学生布置一样的作业。这显然浪费了算力,且效率低下。

3.2 引入动态权重 (

$L_{circle}$

)

为了让模型懂得“因材施教”,作者引入了动态权重

$\alpha$

$L_{circle} = \log \left[ 1 + \sum_{j=1}^L \exp(\gamma \alpha_n^j s_n^j) \cdot \sum_{i=1}^K \exp(-\gamma \alpha_p^i s_p^i) \right]$

其中,权重

$\alpha$

的定义是“自我配速”(Self-paced):

$\alpha_p^i = [O_p - s_p^i]_+, \quad \alpha_n^j = [s_n^j - O_n]_+$
  • 机制详解

如果样本简单(

$s_p$

接近目标

$O_p$

),

$\alpha_p$

 变小

$\rightarrow$

几乎不练。

如果样本很难(

$s_p$

远小于目标

$O_p$

),

$\alpha_p$

变大

$\rightarrow$

加权猛练!

3.3 Circle Loss 最终形态

将动态权重

$\alpha$

和 Margin 结合,我们就得到了最终公式:

$L_{circle} = \log \left[ 1 + \sum_{j=1}^L \exp(\gamma \alpha_n (s_n - \Delta_n)) \cdot \sum_{i=1}^K \exp(-\gamma \alpha_p (s_p - \Delta_p)) \right]$

4. 几何解释 —— 为什么叫“Circle”?

这是论文最精彩的几何视角。

4.1 决策边界的演变

Circle Loss: 由于引入了与

$s$

相关的权重 

$\alpha$

,优化项变成了关于

$s$

的二次项 (

$s^2$

)。其决策边界方程演变为:

Softmax/CosFace: 优化目标是

$s_p - s_n = m$

。在坐标系中,这是一条直线

$(s_n - \frac{O_n + \Delta_n}{2})^2 + (s_p - \frac{O_p + \Delta_p}{2})^2 = C$

在特定参数下,它简化为:

$(s_n - 0)^2 + (s_p - 1)^2 = 2m^2$

4.2 圆形的意义

直线变成圆弧,不仅仅是好看。

这意味着模型在优化

$s_p$

$s_n$

时,不再是僵硬的 1:1 兑换,而是根据它们各自离“完美状态”

$(0, 1)$

的距离来动态调整梯度方向。这就赋予了 Loss 更大的灵活性。


5. 梯度验证 —— 数学上的实锤

最后,为了证明“动态权重”真的有效,作者直接给出了梯度公式:

$\frac{\partial L}{\partial s_n} \propto \alpha_n = (s_n - O_n)$
$\frac{\partial L}{\partial s_p} \propto \alpha_p = (O_p - s_p)$

一句话总结:梯度的强弱,正比于样本的难度。

这彻底解决了传统 Loss 在简单样本上浪费梯度的问题,让模型能够全神贯注地攻克那些“死活分不开”的 Hard Cases。

Read more

前端防范 XSS(跨站脚本攻击)

目录 一、防范措施 1.layui util  核心转义的特殊字符 示例 2.js-xss.js库 安装 1. Node.js 环境(npm/yarn) 2. 浏览器环境 核心 API 基础使用 1. 基础过滤(默认规则) 2. 自定义过滤规则 (1)允许特定标签 (2)允许特定属性 (3)自定义标签处理 (4)自定义属性处理 (5)转义特定字符 常见场景示例 1. 过滤用户输入的评论内容 2. 允许特定富文本标签(如富文本编辑器内容) 注意事项 更多配置 XSS(跨站脚本攻击)是一种常见的网络攻击手段,它允许攻击者将恶意脚本注入到其他用户的浏览器中。

详细教程:如何从前端查看调用接口、传参及返回结果(附带图片案例)

详细教程:如何从前端查看调用接口、传参及返回结果(附带图片案例)

目录 1. 打开浏览器开发者工具 2. 使用 Network 面板 3. 查看具体的API请求 a. Headers b. Payload c. Response d. Preview e. Timing 4. 实际操作步骤 5. 常见问题及解决方法 a. 无法看到API请求 b. 请求失败 c. 跨域问题(CORS) 作为一名后端工程师,理解前端如何调用接口、传递参数以及接收返回值是非常重要的。下面将详细介绍如何通过浏览器开发者工具(F12)查看和分析这些信息,并附带图片案例帮助你更好地理解。 1. 打开浏览器开发者工具 按下 F12 或右键点击页面选择“检查”可以打开浏览器的开发者工具。常用的浏览器如Chrome、Firefox等都内置了开发者工具。下面是我选择我的一篇文章,打开开发者工具进行演示。 2. 使用

Cursor+Codex隐藏技巧:用截图秒修前端Bug的保姆级教程(React/Chakra UI案例)

Cursor+Codex隐藏技巧:用截图秒修前端Bug的保姆级教程(React/Chakra UI案例) 前端开发中最令人头疼的莫过于那些难以定位的UI问题——元素错位、样式冲突、响应式失效...传统调试方式往往需要反复修改代码、刷新页面、检查元素。现在,通过Cursor编辑器集成的Codex功能,你可以直接用截图交互快速定位和修复这些问题。本文将带你从零开始,掌握这套革命性的调试工作流。 1. 环境准备与基础配置 在开始之前,确保你已经具备以下环境: * Cursor编辑器最新版(v2.5+) * Node.js 18.x及以上版本 * React 18项目(本文以Chakra UI 2.x为例) 首先在Cursor中安装Codex插件: 1. 点击左侧扩展图标 2. 搜索"Codex"并安装 3. 登录你的OpenAI账户(需要ChatGPT Plus订阅) 关键配置项: // 在项目根目录创建.