34.2 Kvantálás és hibatovábbterjedés

34.2.1 1. Cél, előismeret és induló kérdés

A 34.1. Mért késleltetés, throughput és memória egységben a késleltetést, az átbocsátóképességet és a memóriahasználatot mértük. Ott a tárolási méret csak az egyik erőforrás volt. Most a kvantálást vizsgáljuk: egy már betanított, float32 paraméterekkel és aktivációkkal számoló modellt kisebb bitszélességű, jellemzően int8 számábrázolásra képezünk le. A közvetlen motiváció a memória- és sávszélesség-igény csökkentése, de a leképzés numerikus hibát visz be. A kérdés az, hogy ezt a hibát hogyan tudjuk a skála és a kerekítés szintjén pontosan korlátozni, és hol szűnik meg a korlát.

Előismeret. A 33.2. Batch és kis szolgáltatás inference-szerződése rögzíti, hogy a bemeneti kép float32, [0,1][0,1] intenzitású és NCHW alakú. A kvantálás ezen a bejárati szerződésen nem változtat: a modell továbbra is float32 képet fogad, a kisebb bitszélesség a belső reprezentációban jelenik meg. A 30.2. Kontrasztív cél és temperature softmax-hőmérséklete azt mutatta, hogy ugyanakkora logitváltozás más predikciós érzékenységet okozhat; a 22.2. Címkemegőrző transzformációk figyelmeztetett, hogy a tanító- és a kiszolgálási eloszlás eltérése önmagában is hibát termel. A kvantálás kalibrációja ugyanezt a domaineltérést tesszi fel nagyító alá.

Induló kérdés. Ha egy float32 értéket egy közös ss skálával int8 egészre kerekítünk, majd visszaállítunk, legfeljebb mekkora lehet a visszaállítás abszolút hibája, amíg nem érjük el a int8 tartomány szélét?

34.2.2 2. Definíció: affin kvantálás, skála, zero-point, vágás, kalibráció

Legyen az eredeti valós érték r∈ℝr\in\mathbb R. Egy affin kvantáló egy (s,z)(s,z) pár, ahol

A kódolt egész szám

q=clamp(round(rs+z),qmin,qmax),q=\operatorname{clamp}\left(\operatorname{round}\!\left(\frac{r}{s}+z\right),\;q_{\min},\;q_{\max}\right),

a visszaállított, dekvantált érték pedig

r̂=s(q−z).\widehat r=s(q-z).

Itt qmin<qmaxq_{\min}<q_{\max} egészek, int8 esetén például qmin=−128q_{\min}=-128, qmax=127q_{\max}=127. A round\operatorname{round} a legközelebbi egészre kerekítés, az clamp(y,a,b)=min(max(y,a),b)\operatorname{clamp}(y,a,b)=\min(\max(y,a),b) a vágás (clipping). Ha qmin≤round(r/s+z)≤qmaxq_{\min}\le \operatorname{round}(r/s+z)\le q_{\max} nem teljesül, az érték telítődik: a kódolt érték a tartomány szélére esik, és a dekvantált érték nem követi tovább rr-et.

A definícióból közvetlenül látszik a két szabadsági fok szerepe. A skála határozza meg, hogy egy egész lépés mekkora valós lépésnek felel meg. A zero-point azt mondja meg, melyik qq egész kódolja a 00-t: ha r=0r=0, akkor a kerekítés előtt zz áll, tehát 00-hoz általában q≈zq\approx z tartozik. Aszimmetrikus tartomány, például r∈[0,2,5]r\in[0,2{,}5], esetén szükség van nemnulla zero-pointra.

Két elterjedt granularitás van. Per-tensor kvantálásnál egy teljes tenzor minden eleme ugyanazt az (s,z)(s,z) párt használja. Per-channel kvantálásnál a CC csatorna mentén s∈ℝCs\in\mathbb R^C skálavektort és z∈ℤCz\in\mathbb Z^C zero-point vektort használunk; például egy N×C×H×WN\times C\times H\times W aktivációban az n,c,i,jn,c,i,j elemhez az sc,zcs_c,z_c tartozik. E két fogalmat nem szabad felcserélni, mert a per-channel finomabb felbontás kisebb kerekítési hibát adhat, de több kalibrációs adatot és más kernel-támogatást igényelhet.

A kalibráció (calibration) a skála és zero-point megválasztása reprezentatív adaton. Egy egyszerű, gyakori szabály a min-max kalibráció:

s=rmax−rminqmax−qmin,z=qmin−round(rmins),s=\frac{r_{\max}-r_{\min}}{q_{\max}-q_{\min}},\qquad z=q_{\min}-\operatorname{round}\!\left(\frac{r_{\min}}{s}\right),

ahol rmin,rmaxr_{\min},r_{\max} a kalibrációs tenzor megfigyelt minimuma és maximuma. A kvantálásnál a reprezentálható valós tartomány tartalmazza a nullát is: a kalibrált szélsőértékeket ezért rmin←min(rmin,0)r_{\min}\leftarrow\min(r_{\min},0) és rmax←max(rmax,0)r_{\max}\leftarrow\max(r_{\max},0) szerint bővítjük; ezután zz a [qmin,qmax][q_{\min},q_{\max}] tartományra vágható. Ha a kibővített rmax=rmin=0r_{\max}=r_{\min}=0, a s=1,z=0s=1,z=0 konvenció használható. Egy nemnulla konstans tenzor esetén viszont a s=1,z=0s=1,z=0 általában nem biztosítja az érték torzításmentes reprezentálását. A kalibráció a tanítástól függetlenül, a legjobb modell kiválasztása után történik, és nem használhatja a tesztet; a teszt a végső, már kvantált modell független értékelésére szolgál.

34.2.3 3. Levezetett hibakorlát telítetlen tartományban

A tanulási célhoz tartozó kötelező állítás:

Állítás (abszolút kerekítési hibakorlát). Legyen s>0s>0 valós, z∈ℤz\in\mathbb Z, qmin<qmaxq_{\min}<q_{\max} egészek. Legyen r∈ℝr\in\mathbb R, qu=round(r/s+z)q_u=\operatorname{round}(r/s+z) a vágás előtti kerekített egész, és

r̂=s(clamp(qu,qmin,qmax)−z).\widehat r=s\left(\operatorname{clamp}(q_u,q_{\min},q_{\max})-z\right).

Ha a telítetlenségi feltétel

qmin≤qu≤qmaxq_{\min}\le q_u\le q_{\max}

teljesül, akkor

|r̂−r|≤s2.|\widehat r-r|\le \frac{s}{2}.

Bizonyítás. Vezessük be a kerekítés előtti értéket: y=rs+zy=\frac{r}{s}+z. A legközelebbi egészre kerekítés definíciójából minden y∈ℝy\in\mathbb R esetén

|round(y)−y|≤12.|\operatorname{round}(y)-y|\le\frac12.

A telítetlenségi feltétel miatt a vágás hatástalan, tehát q=qu=round(y)q=q_u=\operatorname{round}(y). Jelölje ε=round(y)−y\varepsilon=\operatorname{round}(y)-y; ekkor |ε|≤1/2|\varepsilon|\le 1/2. A dekvantált érték:

r̂=s(q−z)=s((y+ε)−z)=s(rs+z+ε−z)=r+sε.\widehat r=s(q-z)=s\bigl((y+\varepsilon)-z\bigr)=s\left(\frac{r}{s}+z+\varepsilon-z\right)=r+s\varepsilon.

Így

|r̂−r|=|sε|=s|ε|≤s2.|\widehat r-r|=|s\varepsilon|=s|\varepsilon|\le\frac{s}{2}.

Ezzel az állítást bebizonyítottuk. A bizonyítás semmilyen eloszlási feltevést nem használ; a korlát tetszőleges telítetlen rr-re érvényes, tetszőleges zz-vel. Ha a kerekítés döntetlennél nem a páros egész felé kerekít, hanem mindig felfelé, a |ε|≤1/2|\varepsilon|\le 1/2 tulajdonság akkor is fennáll, tehát a korlát érvényes marad; a döntetlen-szabály csak az ε\varepsilon konkrét értékét befolyásolja.

Miért nem érvényes a korlát telítéskor? Ha yy annyira nagy, hogy qu>qmaxq_u>q_{\max}, akkor a vágás qmaxq_{\max}-ra cseréli a kerekített értéket, és a r̂=s(qmax−z)\widehat r=s(q_{\max}-z) konstanssá válik. Ekkor yy további növelésével rr nő, r̂\widehat r viszont már nem, így |r−r̂||r-\widehat r| tetszőlegesen nagy lehet. Ugyanez igaz az alsó telítésre. A telítési hiba tehát nem a kerekítés, hanem a reprezentálható tartomány korlátosságának következménye.

34.2.4 4. Kézi számpélda

Legyen s=0,25s=0{,}25, z=0z=0, qmin=−128q_{\min}=-128, qmax=127q_{\max}=127. Négy értékre:

rr r̂\widehat r |r̂−r||\widehat r-r| telített?
1,371{,}37 1,251{,}25 0,120{,}12 nem
−0,12-0{,}12 00 0,120{,}12 nem
00 00 00 nem
32,032{,}0 31,7531{,}75 0,250{,}25 igen

A harmadik sor azt mutatja, hogy a zero-point itt éppen 00-ra kódolja a valós nullát. A negyedik sorban r/s=128r/s=128, a vágás előtti kerekítés 128128, ami meghaladja a 127127 felső határt; a vágás után r̂=0,25⋅(127−0)=31,75\widehat r=0{,}25\cdot(127-0)=31{,}75. A hiba 0,25>s/2=0,1250{,}25>s/2=0{,}125, mert a telítetlenségi feltétel sérült.

34.2.5 5. Labor: kis numerikus kvantálási példa

A labor célja egy önálló, Pythonban ellenőrizhető kvantáló és kalibráló függvény, amely nem backend-gyorsítást ígér, hanem a numerikus hibát méri. A kód tiszta NumPy, CPU, float32 bemenettel.

Munkahely: lab/q134_quant/.

# quant_example.py
import numpy as np

def affine_quantize(x, scale, zero_point, qmin=-128, qmax=127):
    # x: float32 tömb; scale: pozitív float32; zero_point: int
    if not float(scale) > 0.0:
        raise ValueError("scale > 0 szükséges")
    y = x / np.float64(scale) + float(zero_point)
    q_unclamped = np.rint(y)          # legközelebbi egész, feles döntetlennél páros
    saturated = (q_unclamped < qmin) | (q_unclamped > qmax)
    q = np.clip(q_unclamped, qmin, qmax).astype(np.int64)
    x_hat = (np.float32(scale) * (q - zero_point)).astype(np.float32)
    return q, x_hat, saturated

def per_tensor_minmax(x, qmin=-128, qmax=127):
    # A nulla is legyen reprezentálható; ez a konstans, nemnulla inputot is kezeli.
    rmin = min(0.0, float(np.min(x)))
    rmax = max(0.0, float(np.max(x)))
    if rmax == rmin:  # pontosan minden érték nulla
        return np.float32(1.0), 0
    scale = np.float32((rmax - rmin) / (qmax - qmin))
    zero_point = qmin - int(np.rint(rmin / np.float64(scale)))
    zero_point = int(np.clip(zero_point, qmin, qmax))
    return scale, zero_point

if __name__ == "__main__":
    rng = np.random.default_rng(20261020)
    x = rng.normal(0.2, 0.5, size=(4, 8)).astype(np.float32)

    scale, z = per_tensor_minmax(x)
    q, x_hat, sat = affine_quantize(x, scale, z)
    err = np.max(np.abs(x_hat - x))

    print("scale=", scale)
    print("zero_point=", z)
    print("max_abs_err=", err)
    print("saturated_cells=", int(sat.sum()))

    # Ellenőrzés: telítetlen esetben a levezetett korlátnak teljesülnie kell.
    if int(sat.sum()) == 0:
        assert err <= np.float64(scale) / 2.0 + 1e-6, "hibás kerekítési korlát"

    # Determinisztikus kézi kontroll a 4. szakasz táblázatára.
    x_ref = np.array([1.37, -0.12, 0.0, 32.0], dtype=np.float32)
    q_ref, x_hat_ref, sat_ref = affine_quantize(
        x_ref, np.float32(0.25), 0, qmin=-128, qmax=127
    )
    print("control_q=", q_ref)
    print("control_x_hat=", x_hat_ref)
    print("control_saturated=", sat_ref)
    assert np.allclose(x_hat_ref[:3], np.array([1.25, 0.0, 0.0], dtype=np.float32),
                       atol=1e-6)
    assert q_ref[3] == 127 and sat_ref[3]
    print("control_ok")

Futtatás:

cd lab/q134_quant
python quant_example.py

A determinisztikus kontroll várható kimenete control_q=[5 0 0 127], control_x_hat=[1.25 0. 0. 31.75], control_saturated=[False False False True]. A véletlen tenzorra a script kiírja a skálát, zero-pointot, maximális abszolút hibát és a telített elemek számát; ezt a hallgató a laborban futtatja. Az itteni szöveg nem állítja, hogy ezt a véletlen futtatást most végrehajtottuk; a kézi kontroll értékei a fenti képletekből közvetlenül számíthatók. Valódi backend-gyorsulást kizárólag tényleges mérés alapján szabad közölni, a 34.1. Mért késleltetés, throughput és memória mérési protokolljával.

34.2.6 6. Feladatok

34.2.6.1 F1 fogalmi feladat (nehézség 1)

Input: két (s,z)(s,z) pár: (0,25,0)(0{,}25,0) és (0,1,−10)(0{,}1,-10); egy rögzített q=0q=0 egész.

Előfeltétel: ismeri az affin kvantálás definícióját.

Átadandó eredmény: magyarázza el a skála és a zero-point különbségét, és adja meg mindkét párhoz a q=0q=0-hoz tartozó dekvantált értéket. Indokolja, miért nem elegendő a qq egész bitminta önmagában az eredeti valós érték rekonstruálásához.

34.2.6.2 F2 levezetési feladat (nehézség 2)

Input: s=0,25s=0{,}25, z=0z=0, qmin=−128q_{\min}=-128, qmax=127q_{\max}=127, r=32,0r=32{,}0.

Előfeltétel: ismeri a 3. szakasz állítását és bizonyítását.

Átadandó eredmény: lépésenként számolja ki r/s+zr/s+z értékét, a kerekített quq_u-t, a vágott qq-t és a dekvantált r̂\widehat r-et. Mutassa meg, hogy a hiba 0,250{,}25, ami nagyobb s/2s/2-nél, és nevezze meg pontosan, hogy a tétel mely feltétele nem teljesül.

34.2.6.3 F3 implementációs feladat (nehézség 2)

Input: X∈ℝ4×6X\in\mathbb R^{4\times 6}, per-channel skálák s∈ℝ6s\in\mathbb R^6, zero-pointok z∈{0,…,5}6z\in\{0,\ldots,5\}^6; a pontos numerikus értékeket a hallgató választja, de rögzítse seeddel: np.random.default_rng(20261020).

Előfeltétel: a labor kódjának működése; float32 dtype.

Átadandó eredmény: futtatható quantize_per_channel(x, scales, zero_points, qmin, qmax) függvény, amely minden cc oszlophoz külön (sc,zc)(s_c,z_c) párt használ. Ellenőrizze, hogy minden olyan oszlopra, ahol nincs telített elem, a maximális abszolút hiba legfeljebb sc/2s_c/2 legyen. A megoldásnak tartalmaznia kell a teljes kódot és a kontroll kimenetét.

34.2.6.4 F4 hibakeresési feladat (nehézség 2)

Input: az alábbi kalibrációs kódrészlet:

scale = (rmax - rmin) / 255.0
z = qmin - int(rmin / scale)      # hibaforrás

Előfeltétel: ismeri a min-max kalibráció képletét és a Python int szemantikáját.

Átadandó eredmény: mutasson egy konkrét rmin értéket, ahol a int(rmin / scale) nem a kívánt legközelebbi egész kerekítést adja. Magyarázza el a hiba okát, következményét a reprezentálható tartományra, adja meg a javítást, és írja le azt a numerikus ellenőrzést, amellyel a javítás helyességét visszaigazolja.

34.2.6.5 F5 kísérlettervezési/transzfer feladat (nehézség 3)

Input: egy GlyphLabon tanított kis CNN float32 súllyal; a metadata.csv scene-szintű splitje; korlátozott CPU-erőforrás.

Előfeltétel: a 33.2. Batch és kis szolgáltatás inference-szerződése, a 34.1. Mért késleltetés, throughput és memória mérési módszertana és a 34.2. Kvantálás és hibatovábbterjedés kvantálási hibamértéke.

Átadandó eredmény: egy írásbeli kísérleti terv post-training quantization (PTQ) és float32 baseline összehasonlítására. Azonosítsa a kalibrációs halmazt, a rögzített seedet, a mért numerikus hibát, a validációs metrikát és a kísérlet érvényességi korlátját. Tüntesse fel, mely állításokat nem szabad levonni valódi backend-futás nélkül.

34.2.7 7. Megoldások és indoklás

34.2.7.1 F1 megoldás

A dekvantálási képlet r̂=s(q−z)\widehat r=s(q-z).

Ugyanaz a q=0q=0 bitminta tehát az egyik kvantálóban 00-t, a másikban 1,01{,}0-t jelent. A skála adja egy egész lépés valós méretét, a zero-point pedig a nulla valós érték kódját; mindkettő ismerete szükséges, mert a tárolt qq önmagában csak egy egész, nem hordozza a mértékegységet és az origóeltolást.

34.2.7.2 F2 megoldás

  1. y=r/s+z=32,0/0,25+0=128y=r/s+z=32{,}0/0{,}25+0=128.
  2. qu=round(128)=128q_u=\operatorname{round}(128)=128.
  3. Mivel 128>qmax=127128>q_{\max}=127, a vágás: q=127q=127, telítés következik be.
  4. r̂=s(q−z)=0,25⋅127=31,75\widehat r=s(q-z)=0{,}25\cdot127=31{,}75.
  5. A hiba: |31,75−32,0|=0,25|31{,}75-32{,}0|=0{,}25, míg s/2=0,125s/2=0{,}125.

A 3. szakasz állítása felteszi, hogy qmin≤qu≤qmaxq_{\min}\le q_u\le q_{\max}. Itt qu=128>127q_u=128>127, tehát a feltétel nem teljesül; a kapott 0,250{,}25 hiba ezért nem mond ellent a tételnek. Alakellenőrzés: rr, r̂\widehat r és a hiba is dimenziótlan valós; qq egész.

34.2.7.3 F3 megoldás

# per_channel_quant.py
import numpy as np

def quantize_per_channel(x, scales, zero_points, qmin=-128, qmax=127):
    x = np.asarray(x, dtype=np.float32)
    scales = np.asarray(scales, dtype=np.float32)
    zero_points = np.asarray(zero_points, dtype=np.int64)
    y = x / scales.astype(np.float64) + zero_points.astype(np.float64)
    q_unclamped = np.rint(y)
    saturated = (q_unclamped < qmin) | (q_unclamped > qmax)
    q = np.clip(q_unclamped, qmin, qmax).astype(np.int64)
    x_hat = (scales * (q - zero_points)).astype(np.float32)
    return q, x_hat, saturated

if __name__ == "__main__":
    rng = np.random.default_rng(20261020)
    x = rng.normal(0.0, 1.0, size=(4, 6)).astype(np.float32)
    scales = rng.uniform(0.05, 0.15, size=(6,)).astype(np.float32)
    zero_points = rng.integers(-20, 21, size=(6,))
    q, x_hat, sat = quantize_per_channel(x, scales, zero_points)
    for c in range(6):
        col_sat = sat[:, c]
        err_c = np.max(np.abs(x_hat[:, c] - x[:, c]))
        if not np.any(col_sat):
            assert err_c <= np.float64(scales[c]) / 2.0 + 1e-6, (c, err_c)
        print(f"channel={c} scale={scales[c]:.6f} max_abs_err={err_c:.6f} "
              f"saturated={int(np.sum(col_sat))}")
    print("per_channel_control_ok")

A vektorizáció a scales és zero_points broadcastingjára épül: a N×CN\times C alakú x oszlopaihoz a CC hosszú vektorok rendelődnek. A tolerancia 1e-6, mert a kerekítési korlát felső határa analitikus, a lebegőpontos műveletek viszont 10−610^{-6}-nál kisebb numerikus eltérést adhatnak float32-ben. Szélsőeset: ha egy oszlop telített elemet tartalmaz, a korlátot nem követeljük meg, a konzol kimutatja a telített cellák számát.

34.2.7.4 F4 megoldás

A Python int(x) függvény nulla felé csonkít, nem a legközelebbi egészre kerekít. Példa: rmin=−1,37r_{\min}=-1{,}37, s=0,1s=0{,}1. Ekkor rmin/s=−13,7r_{\min}/s=-13{,}7. A int(-13.7) értéke −13-13, a legközelebbi egész viszont −14-14. A rossz zero-point ezért eggyel nagyobb lesz a helyesnél, és a reprezentálható legkisebb érték nem éri el a tényleges minimumot; a legkisebb bemenetek telítődnek, szisztematikus pozitív torzítást okozva.

Javítás:

z = qmin - int(np.rint(rmin / scale))

Ellenőrzés: a javított zz-vel számoljuk ki a kalibrációs minimum kvantálását. Azt várjuk, hogy r=rminr=r_{\min} esetén qu=qminq_u=q_{\min} (vagy a kerekítés miatt legfeljebb egy egész eltéréssel), és r̂\widehat r a hibatűrésen belül rminr_{\min} közelébe esik. Konkrétan rmin=−1,37r_{\min}=-1{,}37, s=0,1s=0{,}1 mellett a helyes z=qmin−(−14)=qmin+14z=q_{\min}-(-14)=q_{\min}+14; ezzel r/s+z=−13,7+14=0,3r/s+z=-13{,}7+14=0{,}3, kerekítve 00, nem −13,0-13{,}0-t csonkító érték. A fenti F3/F4 mintához hasonló, kis unit tesztben összehasonlítható a két változat maximális hibája telítetlen tartományon.

34.2.7.5 F5 megoldásminta

Egy lehetséges terv:

  1. Kérdés: egy már betanított GlyphLab-CNN per-tensor PTQ int8 szimulációja megőrzi-e a validációs pontosságot a float32 baseline-hoz képest, és mekkora a maximális logiteltérés?
  2. Adat és split: a meglévő scene-szintű train/val/test split rögzített; kalibrációra a train egy külön, rögzített seeddel kiválasztott 30% része használható, nem a val/test.
  3. Baseline: ugyanaz a checkpoint float32 súllyal; a val_loss alapján már kiválasztott, a tesztet a protokoll végéig nem használjuk.
  4. Kvantálás: csak a súlyok szimulált kvantálása a labor affine_quantize függvényével; aktivációkra nem állítunk backend-int8 futtatást.
  5. Metrikák: validációs accuracy, valamint a kvantálatlan és kvantált logitok maximális abszolút eltérése; a tárolási méret csökkenése int8 feltételezéssel.
  6. Korlátok: ez numerikus kompatibilitási vizsgálat, nem sebességmérés; semmilyen gyorsulást nem állítunk valódi, a 34.1. Mért késleltetés, throughput és memória protokoll szerinti latencia/throughput mérés nélkül. A corrupt tesztet csak a végleges kvantált modell kiválasztása után szabad futtatni, páros összehasonlításban.

34.2.8 8. Tipikus tévedés, önellenőrzés és visszahívás

Gyakori tévedés. „Az int8 reprezentáció automatikusan kisebb és gyorsabb modellt ad.” Az int8 tárolás valóban csökkentheti a paraméterek bájtjait, de a futás csak akkor gyorsul, ha az adott háttérben (CPU-utasításkészlet, GPU-kernel, runtime) az összes érintett operátornak létezik támogatott int8 implementációja. Ellenpélda: ha egy háló egyik operátorához nincs int8 kernel, a futtatórendszer dekvantálja a bemenetet, float32-ben számol, majd újra kvantál. Ekkor a memória csökkenhet, de a számítási idő akár nőhet is a többlet dequantize/quantize lépések miatt; a fenti labor tiszta NumPy szimulációja ugyancsak nem gyors kernel. Az int8 tehát egy reprezentáció, nem egy sebességígéretekre jogosító operátorszerződés.

Önellenőrzés. (1) Ha egy telítetlen tartományban a skálát megduplázzuk, mi történik az abszolút hibakorláttal? (2) Miért nem lehet a zero-point tetszőleges valós szám? (3) A kalibráció használhatja-e a validációt?

Válaszok: (1) A r̂−r=−sε\widehat r-r=-s\varepsilon alakból a korlát s/2s/2-ről 2s/2=s2s/2=s-re nő; a nagyobb lépésköz nagyobb maximális hibát enged. (2) Mert qq és zz különbsége lép be a s(q−z)s(q-z) képletbe; ha zz nem egész, a kerekített egész qq-val az r/s+zr/s+z értékhez való közelség nem fordítható le a kívánt rr-hez való közelséggé, és a kódolt értékek rácsát eltoló, nem egész origó nem őrizné meg az egész kódolás szerkezetét. A definíció emiatt z∈ℤz\in\mathbb Z-t köt ki. (3) Nem; a kalibráció a modell belső paramétereinek választása, ezért ugyanaz a logika tiltja, mint a hiperparaméter-választást a validáción: a kiértékelő halmazt érintetlenül kell hagyni.

Korábbi fogalom visszahívása. A 33.2. Batch és kis szolgáltatás szerint az inference bemenet float32 és [0,1][0,1]-beli; a kvantálás ezt a bemeneti szerződést nem írja felül, hanem a modell belsejében történik. A 30.2. Kontrasztív cél és temperature arról tanított, hogy a softmax hőmérséklete felnagyíthatja a logitok közötti kis különbségeket: egy |δ||\delta| logithiba predikciós hatása ezért nem pusztán a δ\delta-tól, hanem az érvényes hőmérséklettől és a szomszédos osztálypontszámoktól is függ. A 22.2. Címkemegőrző transzformációk címkemegőrző transzformációs érvelése analóg módon figyelmeztet: a kalibrációs eloszlásnak a kiszolgálási eloszlást kell reprezentálnia, különben a kvantálási hiba egy megjósolható domaineltérésre rakódik.

34.2.9 9. Rövid összefoglaló

Az affin kvantálás egy valós rr értéket a q=clamp(round(r/s+z),qmin,qmax)q=\operatorname{clamp}(\operatorname{round}(r/s+z),q_{\min},q_{\max}) egészre képez, a dekvantálás pedig r̂=s(q−z)\widehat r=s(q-z). A skála az egész lépés valós hossza, a zero-point a nulla kódja. Telítetlen tartományban a kerekítésből |r̂−r|≤s/2|\widehat r-r|\le s/2 következik, mert a legközelebbi egész hibája legfeljebb 1/21/2, és a skálával szorzás ezt s/2s/2-re skálázza. Telítéskor a vágás miatt a hiba tetszőlegesen nagy lehet. A kalibráció reprezentatív adaton választja meg az (s,z)(s,z) párt, de a tesztet nem érintheti. Az int8 tárolás önmagában nem bizonyít backend-támogatást vagy gyorsulást.

34.2.10 Következő alkalmazás

A 34.3. Pruning és struktúra egység a pruning és a strukturált ritkítás kérdését vizsgálja: ott azt elemezzük, hogyan távolíthatók el paraméterek vagy szerkezeti egységek a hibakorlát és a mért hatékonyság megőrzése mellett.

34.2.11 Források

A hibakorlát levezetése és a kód önálló példa. A kapcsolódó mérési módszereket a 34.1. Mért késleltetés, throughput és memória, a modell exportját a 33.3. torch.export és ONNX, a desztillációt a 34.4. Teacher–student desztilláció tárgyalja.