28.2 Sziámi és triplet cél

28.2.1 Cél, előismeret és induló kérdés

A 28.1. Embedding, távolság és normalizálás egységben definiáltuk az embeddinget mint fθ(x)=z∈ℝdf_\theta(x)=z\in\mathbb R^d leképezést, az L2-normalizálást és a koszinusz-hasonlóságot. Most azt vizsgáljuk, milyen veszteségfüggvények tanítanak be olyan teret, amelyben a hasonlósági kérdések közvetlenül, euklideszi vagy koszinusz-távolsággal megválaszolhatók. Induló kérdés: ha egy minibatchben három kép van, honnan tudjuk, melyik kettőt kell közelíteni, és mi történik, ha a „negatív” címke téves?

28.2.2 Sziámi hálózat, pár és triplet: definíciók

1. definíció (sziámi, siamese). Legyen fθ:𝒳→ℝdf_\theta:\mathcal X\to\mathbb R^d egy megosztott paraméterű hálózat, ahol θ\theta közös. Két vagy több xi,xjx_i,x_j bemenetre a reprezentációk zi=fθ(xi)z_i=f_\theta(x_i), zj=fθ(xj)z_j=f_\theta(x_j) ugyanazzal a θ\theta-val készülnek. A sziámi elnevezés tehát a súlymegosztási és tanítási mintára vonatkozik, nem egy külön rétegtípusra. A 28.1. Embedding, távolság és normalizálás jelölését követve a képbemenet alakja x∈ℝC×H×Wx\in\mathbb R^{C\times H\times W}, a batchelt embedding Z∈ℝN×dZ\in\mathbb R^{N\times d}, ahol egy megfigyelés egy sor. A közös θ\theta következménye, hogy a három ág hibájának gradiense a láncszabály szerint ugyanabban a paramétertérben adódik össze.

2. definíció (pár). Egy pár (i,j,yij)(i,j,y_{ij}), ahol yij=1y_{ij}=1 pozitív pár, ha xix_i és xjx_j azonos osztályú; yij=0y_{ij}=0 negatív pár, ha eltérő. A pozitív/negatív fogalmát a rendelkezésre álló felügyelt címke definiálja, nem a pillanatnyi beágyazási távolság.

3. definíció (triplet). Egy triplet (a,p,n)(a,p,n) rendezett hármas, ahol aa anchor, pp pozitív: ya=ypy_a=y_p; nn negatív: ya≠yny_a\neq y_n. A triplet három, batchbeli sorra hivatkozik: za,zp,zn∈ℝdz_a,z_p,z_n\in\mathbb R^d.

28.2.3 Kontrasztív és triplet margin veszteség

Jelölje D(zi,zj)=∥zi−zj∥2D(z_i,z_j)=\lVert z_i-z_j\rVert_2 az euklideszi távolságot. A squared forma, amellyel dolgozunk, D2=∥zi−zj∥22D^2=\lVert z_i-z_j\rVert_2^2.

4. definíció (kontrasztív cél, contrastive loss). Legyen a párra d2=∥zi−zj∥2d^2=\lVert z_i-z_j\rVert^2 és m>0m>0 margin a távolságnégyzet egységében:

Lpair(zi,zj,yij)=yijd2+(1−yij)[m−d2]+, L_{\mathrm{pair}}(z_i,z_j,y_{ij})=y_{ij}\,d^2+(1-y_{ij})\,[m-d^2]_+,

ahol [t]+=max(0,t)[t]_+=\max(0,t). A batchveszteség a párok átlaga. A pozitív tag a közelséget, a negatív tag azt bünteti, ha d2<md^2<m.

5. definíció (triplet margin loss, squared változat). Legyen α>0\alpha>0 margin a távolságnégyzet egységében:

Ltrip(za,zp,zn)=[∥za−zp∥2−∥za−zn∥2+α]+. L_{\mathrm{trip}}(z_a,z_p,z_n)=\bigl[\lVert z_a-z_p\rVert^2-\lVert z_a-z_n\rVert^2+\alpha\bigr]_+ .

Ez a [P16] absztraktjában ellenőrzött állítás szerint ahhoz az elvhez illeszkedik, hogy a beágyazást közvetlenül triplet-megkötésekkel tanítsuk; a képlet pontos FaceNet-változatához a teljes cikk releváns szakasza olvasandó. A népszerű keretrendszerek beépített triplet loss implementációi eltérhetnek abban, hogy a távolságot vagy annak négyzetét használják, ezért beépített osztály használata előtt a helyi API-referenciát ellenőrizni kell.

28.2.4 A triplet loss zérus és nemzérus tartománya

1. lemma (a squared triplet loss zérus halmaza). Legyen za,zp,zn∈ℝdz_a,z_p,z_n\in\mathbb R^d és α>0\alpha>0. Ekkor

Ltrip=0⇔∥za−zn∥2≥∥za−zp∥2+α. L_{\mathrm{trip}}=0 \;\Longleftrightarrow\; \lVert z_a-z_n\rVert^2 \ge \lVert z_a-z_p\rVert^2+\alpha .

Ha a feltétel nem teljesül, azaz ∥za−zn∥2<∥za−zp∥2+α\lVert z_a-z_n\rVert^2<\lVert z_a-z_p\rVert^2+\alpha, akkor

Ltrip=∥za−zp∥2−∥za−zn∥2+α>0. L_{\mathrm{trip}}=\lVert z_a-z_p\rVert^2-\lVert z_a-z_n\rVert^2+\alpha>0 .

Bizonyítás (saját levezetés). Legyen t=∥za−zp∥2−∥za−zn∥2+αt=\lVert z_a-z_p\rVert^2-\lVert z_a-z_n\rVert^2+\alpha. A [⋅]+[\cdot]_+ definíciója szerint [t]+=0[t]_+=0, ha t≤0t\le0, és [t]+=t[t]_+=t, ha t>0t>0. A t≤0t\le0 feltétel átrendezve ∥za−zn∥2≥∥za−zp∥2+α\lVert z_a-z_n\rVert^2\ge\lVert z_a-z_p\rVert^2+\alpha; a t>0t>0 feltétel a fordított szigorú egyenlőtlenség, és ekkor α>0\alpha>0 miatt az érték is pozitív. Az egyenlőségi határon t=0t=0, tehát a veszteség zérus, de a marginpont nem sima pont.

Következmény (kapcsolat a koszinusszal). Ha za,zp,znz_a,z_p,z_n mind egységnormájú, a 28.1. Embedding, távolság és normalizálás alfejezetben levezetett ∥u−v∥2=2(1−cos(u,v))\lVert u-v\rVert^2=2(1-\cos(u,v)) alapján a zérus feltétel:

cos(za,zn)≤cos(za,zp)−α2. \cos(z_a,z_n)\le \cos(z_a,z_p)-\frac{\alpha}{2}.

A margin tehát normalizált beágyazásban a pozitív koszinusz-hasonlóság felett α/2\alpha/2 előnyt követel meg.

Kézi számpélda. Legyen d=2d=2, α=0.2\alpha=0.2.

  1. za=(0,0)⊤z_a=(0,0)^\top, zp=(1,0)⊤z_p=(1,0)^\top, zn=(2,0)⊤z_n=(2,0)^\top. Ekkor dp2=1d_p^2=1, dn2=4d_n^2=4, t=1−4+0.2=−2.8t=1-4+0.2=-2.8, tehát L=0L=0.
  2. za=(0,0)⊤z_a=(0,0)^\top, zp=(2,0)⊤z_p=(2,0)^\top, zn=(0,1)⊤z_n=(0,1)^\top. Ekkor dp2=4d_p^2=4, dn2=1d_n^2=1, t=4−1+0.2=3.2t=4-1+0.2=3.2, tehát L=3.2>0L=3.2>0.
  3. Határeset: dp2=1d_p^2=1, dn2=1.2d_n^2=1.2 mellett t=1−1.2+0.2=0t=1-1.2+0.2=0, így L=0L=0.

Az 1. példa mutatja, hogy a negatívnak nem kell messzinek lennie, csak az α\alpha margót teljesítenie kell; a 2. példa aktív, kemény tripletet mutat.

28.2.5 Gradiens és hard negative

Ha a triplet aktív, L=∥za−zp∥2−∥za−zn∥2+αL=\lVert z_a-z_p\rVert^2-\lVert z_a-z_n\rVert^2+\alpha sima. A négyzetes norma deriváltjából t>0t>0 esetén:

∇zaL=2(za−zp)−2(za−zn)=2(zn−zp), \nabla_{z_a}L=2(z_a-z_p)-2(z_a-z_n)=2(z_n-z_p),

∇zpL=−2(za−zp)=2(zp−za),∇znL=2(za−zn). \nabla_{z_p}L=-2(z_a-z_p)=2(z_p-z_a),\qquad \nabla_{z_n}L=2(z_a-z_n).

Minden gradiens ℝd\mathbb R^d-beli vektor, alakja megegyezik a megfelelő bemenet alakjával. A t=0t=0 pontban a [⋅]+[\cdot]_+ nem klasszikusan differenciálható, ugyanúgy, ahogy a ReLU nullpontja a 10.3. Gradiensellenőrzés és numerikus hibamérce gradient checkben; a fenti képletek csak az aktív tartományra érvényesek.

6. definíció (aktív és kemény negatív). A triplet aktív, ha a marginfeltétel sérül: ∥za−zn∥2<∥za−zp∥2+α\lVert z_a-z_n\rVert^2<\lVert z_a-z_p\rVert^2+\alpha, azaz L>0L>0. Ezen belül szokás kemény negatívnak nevezni a d(a,n)<d(a,p)d(a,n)<d(a,p) esetet; a d(a,p)≤d(a,n)<d(a,p)2+αd(a,p)\le d(a,n)<\sqrt{d(a,p)^2+\alpha} tartomány a négyzetes távolságú veszteség szokásos semi-hard (félig kemény) megfelelője. A terminológia a konkrét mining-eljárás szerint változhat. A mining-stratégiák közül a batch-all minden lehetséges tripletet képez a batchben és átlagol, a batch-hard csak a legkeményebbeket tartja meg; ez utóbbi kisebb számítású, de nagyobb gradiensvarianciájú heurisztika. Az egyes szakirodalmi és szoftveres megoldások a semi-hard és hard eseteket eltérő mining-konvenció szerint definiálhatják, ezért a használt kritériumot a kísérleti protokollban rögzíteni kell.

28.2.6 Collapse és a margin nélküli ellenpélda

7. definíció (collapse, összeomlás). Azt mondjuk, hogy a beágyazás collapse-olt, ha létezik c∈ℝdc\in\mathbb R^d, amelyre minden vizsgált xx bemenetre fθ(x)=cf_\theta(x)=c.

Állítás. α>0\alpha>0 mellett a triplet loss nem lehet zérus egy teljes mértékben collapse-olt beágyazásra, mert dp=dn=0d_p= d_n=0, így L=[0−0+α]+=α>0L=[0-0+\alpha]_+=\alpha>0. Ezzel szemben α=0\alpha=0 esetén a konstans leképezésre L=[0]+=0L=[0]_+=0; tehát egy margin nélküli squared triplet cél elfogadná a haszontalan, teljesen egybeeső reprezentációt. Ez a margin szükségességének formális indoka a squared változatra; az állítás saját levezetés a lemma következményeként. A margin nem elégséges garancia: ha a mintavételezés csak távoli negatívokat ad, a hálózat alacsony rangú, finom szerkezet nélküli megoldást is találhat.

28.2.7 Labor: szintetikus triplet veszteség és megosztott backbone gradiens

A labor célja a squared triplet veszteség numerikus kontrollja és annak igazolása, hogy a három ágon átfolyó közös paraméter gradiense a három ág gradiensének összege. A PyTorch-kód a könyv lab munkakönyvtárából futtatható. A kimenetet nem ebben a kéziratban futtattuk; a numerikus értékek a képletekből számolt várható szemléltetések.

# lab/n110_triplet_lab.py
# Futtatás a labor könyvtárból: cd lab && python n110_triplet_lab.py
import torch

torch.manual_seed(20261020)
dtype = torch.float32
device = torch.device("cpu")


def triplet_squared_loss(z_a, z_p, z_n, margin):
    # z_a, z_p, z_n: (N, d); margin: float >= 0; reduction: atlag
    d_ap = ((z_a - z_p) ** 2).sum(dim=1)
    d_an = ((z_a - z_n) ** 2).sum(dim=1)
    return torch.clamp(d_ap - d_an + margin, min=0.0).mean()


# 1. Kezi kontroll a ket numerikus peldara
z_a = torch.tensor([[0.0, 0.0]], dtype=dtype, device=device)
z_p = torch.tensor([[1.0, 0.0]], dtype=dtype, device=device)
z_n = torch.tensor([[2.0, 0.0]], dtype=dtype, device=device)
loss_zero = triplet_squared_loss(z_a, z_p, z_n, 0.2)
print("loss_zero =", loss_zero.item(), "(varhato 0.0)")

z_a2 = torch.tensor([[0.0, 0.0]], dtype=dtype, device=device)
z_p2 = torch.tensor([[2.0, 0.0]], dtype=dtype, device=device)
z_n2 = torch.tensor([[0.0, 1.0]], dtype=dtype, device=device)
loss_pos = triplet_squared_loss(z_a2, z_p2, z_n2, 0.2)
print("loss_pos =", loss_pos.item(), "(varhato 3.2)")


class Backbone(torch.nn.Module):
    def __init__(self):
        super().__init__()
        self.fc = torch.nn.Linear(3, 2, bias=False)

    def forward(self, x):
        # x: (N, 3), kimenet: (N, 2)
        return self.fc(x)


# Rogzitett, kezzel beallitott suly; az x bemenetek leaf tenzorok,
# ezert a gradiens csak a sulyra folyik.
W_data = torch.tensor([[0.5, -0.2, 0.1],
                       [0.3, 0.4, -0.1]], dtype=dtype, device=device)
x_a = torch.tensor([[1.0, 0.0, 0.0]], dtype=dtype, device=device)
x_p = torch.tensor([[0.0, 1.0, 0.0]], dtype=dtype, device=device)
x_n = torch.tensor([[0.0, 0.0, 1.0]], dtype=dtype, device=device)

net = Backbone().to(device)
with torch.no_grad():
    net.fc.weight.copy_(W_data)

z_a = net(x_a)
z_p = net(x_p)
z_n = net(x_n)
loss = triplet_squared_loss(z_a, z_p, z_n, 0.2)
loss.backward()
grad_shared = {name: p.grad.detach().clone()
               for name, p in net.named_parameters() if p.grad is not None}

# Harom fuggetlen masolat ugyanazzal a sulyvektorral;
# az agankent szamitott gradiensek osszeget hasonlitjuk a megosztotthoz.
nets = [Backbone().to(device) for _ in range(3)]
for net_i in nets:
    with torch.no_grad():
        net_i.fc.weight.copy_(W_data)

z_list = [nets[0](x_a), nets[1](x_p), nets[2](x_n)]
loss_split = triplet_squared_loss(*z_list, 0.2)
loss_split.backward()

grad_sum = {}
for net_i in nets:
    for name, p in net_i.named_parameters():
        if p.grad is None:
            continue
        g = p.grad.detach()
        grad_sum[name] = grad_sum.get(name, torch.zeros_like(g)) + g

max_diff = max((grad_shared[name] - grad_sum[name]).abs().max().item()
               for name in grad_shared)
print("loss =", loss.item())
print("max gradiens diff =", max_diff)
print("megosztott gradiens egyezik:", max_diff < 1e-6)

A várt loss érték a három, lineárisan kivetített bemenettől függ; a döntő kontroll a max_diff. Ha max_diff < 1e-6, akkor az autograd valóban a három ág VJP-jének összegét rendeli a közös súlyhoz; ez a PyTorch gráfbeli súlymegosztás következménye, és a labor ezt numerikusan, független referenciaként ellenőrzi.

28.2.8 Feladatok

F1 (fogalmi, nehézség 1). Magyarázza el, mi a különbség a sziámi súlymegosztás és két független hálózat között a triplet cél szempontjából. Miért nem elegendő két külön paraméterezésű háló az anchor–pozitív és anchor–negatív pár feldolgozásához? Átadandó: legfeljebb öt mondatos indoklás a gradiensösszegzés következményével.

F2 (levezetési, nehézség 2). Vezesse le a squared triplet loss aktív esetének gradiensét a za,zp,znz_a,z_p,z_n változókra. Ellenőrizze, hogy minden gradiens ℝd\mathbb R^d-beli, és hogy ∇zaL=2(zn−zp)\nabla_{z_a}L=2(z_n-z_p). Átadandó: minden lépés a négyzetes norma deriváltjából.

F3 (implementációs, nehézség 2). Írjon pair_squared_loss(z_i, z_j, y, m) függvényt a kontrasztív célra NumPy vagy PyTorch használatával. Ellenőrizze az y=1y=1, zi=(0,0)z_i=(0,0), zj=(1,0)z_j=(1,0), m=0.5m=0.5 párra, hogy a kimenet 1.01.0; az y=0y=0, ugyanezen vektorokra a kimenet [0.5−1]+=0[0.5-1]_+=0. Átadandó: kód és a két kimenet.

F4 (hibakeresési, nehézség 2). Az alábbi kód a triplet veszteséget akarja kiszámítani, de egy olyan tripletre is nullát ad, ahol a negatív közelebb van az anchorhoz, mint a pozitív. Keresse meg a hibát, írja le a következményt, és javítsa:

d_ap = ((z_a - z_p) ** 2).sum(dim=1)
d_an = ((z_a - z_n) ** 2).sum(dim=1)
loss = torch.relu(d_an - d_ap + margin).mean()   # hiba itt

Átadandó: a hiba oka, a hibás viselkedés egy konkrét numerikus példán, és a javított sor.

F5 (kísérleti/transzfer, nehézség 3). Tervezzen a GlyphLab train/val/test felosztásán triplet-alapú reprezentációtanulást, amelynek célja, hogy a test képre a train-képek közül az azonos orientációjúak legyenek a legközelebb. Adja meg a triplet-képzés szabályát a scene_id figyelembevételével, egy baseline-t, egy retrieval-metrikát és két érvényességi korlátot. Átadandó: protokollterv, nem szükséges kód.

28.2.9 Megoldások és indoklás

F1. A sziámi hálózatban mindhárom ág ugyanazt a θ\theta paramétert használja, ezért a triplet veszteség egyetlen közös térben értelmezi a pozitív közelséget és a negatív távolságot. Két független hálózat esetén az anchor–pozitív út és az anchor–negatív út külön transzformációt tanulhatna; a hasonlósági döntéshez nem lenne közös metrika. A közös θ\theta gradiensére a három ág hibájának VJP-je összegződik: ha az autograd gráfban ugyanaz a súly három lineáris úton szerepel, a láncszabály összeadja az ágakat.

F2. Legyen t>0t>0, tehát L=∥za−zp∥2−∥za−zn∥2+αL=\lVert z_a-z_p\rVert^2-\lVert z_a-z_n\rVert^2+\alpha. A ∥u∥2\lVert u\rVert^2 gradiensére ∇u∥u∥2=2u\nabla_u\lVert u\rVert^2=2u. Az első tag zaz_a szerinti gradiense 2(za−zp)2(z_a-z_p), a másodiké −2(za−zn)-2(z_a-z_n). Összegük:

∇zaL=2(za−zp)−2(za−zn)=2(zn−zp). \nabla_{z_a}L=2(z_a-z_p)-2(z_a-z_n)=2(z_n-z_p).

A zpz_p szerinti derivált csak az első tagból származik: ∇zpL=−2(za−zp)=2(zp−za)\nabla_{z_p}L=-2(z_a-z_p)=2(z_p-z_a). A znz_n szerinti derivált csak a második tagból: ∇znL=2(za−zn)\nabla_{z_n}L=2(z_a-z_n). Alakellenőrzés: mindhárom kifejezés ℝd\mathbb R^d-beli, mert zn−zp∈ℝdz_n-z_p\in\mathbb R^d; a veszteség skalár. A α\alpha konstans deriváltja nulla.

F3. Egy lehetséges megoldás:

import torch

def pair_squared_loss(z_i, z_j, y, m):
    d2 = ((z_i - z_j) ** 2).sum()
    return y * d2 + (1 - y) * torch.clamp(m - d2, min=0.0)

z_i = torch.tensor([0.0, 0.0])
z_j = torch.tensor([1.0, 0.0])
print(pair_squared_loss(z_i, z_j, 1.0, 0.5).item())  # 1.0
print(pair_squared_loss(z_i, z_j, 0.0, 0.5).item())  # 0.0

d2=1d^2=1, ezért y=1y=1 esetén L=1L=1; y=0y=0 esetén m−d2=−0.5m-d^2=-0.5, tehát a clamp nulla.

F4. A hibás kód a két távolságnégyzetet felcseréli: relu(d_an - d_ap + margin) akkor büntet, ha a negatív túl távol van. Konkrét példa: dp2=4d_p^2=4, dn2=1d_n^2=1, α=0.2\alpha=0.2 mellett a helyes loss 3.23.2, a hibás kód viszont [1−4+0.2]+=0[1-4+0.2]_+=0-t ad, tehát a legkeményebb tripletet figyelmen kívül hagyja. Következmény: a modell nem kap nyomást a negatív eltávolítására. Javítás:

loss = torch.relu(d_ap - d_an + margin).mean()

F5. Egy lehetséges terv. Kérdés: ad-e a triplet beágyazás jobb retrieval-t, mint a nyers intenzitásvektor? Megfigyelési egység: jelenet (scene_id), nem kép. Split: a rögzített GlyphLab train/val/test; triplet csak trainből, a val a mining-margin kiválasztására, a test csak a záróértékelésre. Triplet-képzés: batch-all, az anchorhoz minden azonos osztályú elem pozitív, minden eltérő osztályú negatív; a két view ugyanazon osztályba tartozik, ezért pozitív párként is szerepelhet. Baseline: 24×24-es, L2-normalizált nyers intenzitásvektor, euklideszi távolsággal. Keresett tényező: margin az {0.1,0.2,0.5}\{0.1,0.2,0.5\} halmazból. Metrika: query = test, gallery = train; recall@1 és mAP@5 a scene-független felosztás miatt. A [D15] metrika-averaging protokollja az implementáció előtt ellenőrizendő. Korlátok: három osztály, 24×2424\times24 méret és 360360 kép; az eredmény nem általánosítható természetes képre, a triplet tanulás pedig nem garantál cluster-tisztaságot.

28.2.10 Tipikus tévedés és ellenpélda

A rossz negatívdefiníció hamis negatívokat hoz létre, és hibás reprezentációs nyomást ad. Legyen za=(0,0)⊤z_a=(0,0)^\top, zp=(1,0)⊤z_p=(1,0)^\top, zn=(0,0.5)⊤z_n=(0,0.5)^\top, α=0.2\alpha=0.2. A párkonstrukció hibásan nn-t negatívnak címkézi, pedig xnx_n valójában az anchor osztályába tartozik. Ekkor dp2=1d_p^2=1, dn2=0.25d_n^2=0.25, a triplet loss 1−0.25+0.2=0.95>01-0.25+0.2=0.95>0, és a gradiens ∇znL=2(za−zn)=(0,−1)⊤\nabla_{z_n}L=2(z_a-z_n)=(0,-1)^\top a znz_n-t lefelé tolja, növelve az azonos osztályú pontok távolságát. A hálózat tehát megtanulja szétválasztani azokat a pontokat, amelyeket a valódi szemantika szerint közelíteni kellene. A következmény nem csupán nagyobb veszteség: a downstream osztályozási vagy keresési pontosság is romolhat. A helyes gyakorlat a pár- és triplet-generálást a megbízható osztálycímkére, nem a jelenlegi beágyazási távolságra alapozni.

28.2.11 Önellenőrzés és visszahívás

A margin dimenzióját mindig tisztázni kell: a squared triplet α\alpha és a fenti kontrasztív mm egyaránt távolságnégyzet egységű. A t=0t=0 pont nem sima; a gradiensképletek csak t>0t>0 esetén érvényesek, ugyanúgy, mint a ReLU nullpontjánál. Visszahívás a 28.1. Embedding, távolság és normalizálás alfejezetből: egységnormájú vektorokra ∥zi−zj∥2=2(1−cos(zi,zj))\lVert z_i-z_j\rVert^2=2(1-\cos(z_i,z_j)), ezért a triplet margin normalizált térben a pozitív feletti α/2\alpha/2 koszinusz-előnyt ír elő. A 16.2. Pooling, downsampling és aliasing tanulsága szerint a pooling és downsampling a finom térbeli pozíciót eltüntetheti; a triplet feladathoz használt embedding ezért a backbone kimenetén, nem a global average pooling utáni túl alacsony dimenziós vektoron értelmezendő.

28.2.12 Rövid összefoglaló

A sziámi szerkezet két vagy több bemenetet ugyanazon a paramétervektoron futtat, ezért a triplet cél közös beágyazási teret kényszerít. A kontrasztív párveszteség a pozitív párokat közelíti, a negatívakat mm margón túl nyomja. A squared triplet veszteség [∥a−p∥2−∥a−n∥2+α]+[\lVert a-p\rVert^2-\lVert a-n\rVert^2+\alpha]_+; a lemma szerint zérus akkor és csak akkor, ha ∥a−n∥2≥∥a−p∥2+α\lVert a-n\rVert^2\ge\lVert a-p\rVert^2+\alpha. A α=0\alpha=0 ellenpélda megmutatja, hogy margin nélkül a konstans embedding nulla veszteségű collapse. A hard negative a margót sértő negatív; a rossz negatívdefiníció hamis negatívval hibás nyomást ad. A labor a megosztott súly ágonkénti gradiensösszegzését numerikusan ellenőrzi.

28.2.13 Következő alkalmazás

A 28.3. Retrieval-értékelés és adatfelosztás egységben a megtanult beágyazás retrieval-értékelését építjük fel: a galéria és query definícióját, a recall@k, mAP és csoportszintű aggregálás helyes használatát, valamint a [D15] forrásban ellenőrizendő averaging-protokollt.

28.2.14 Felhasznált források