32.1 Szekvenciamodell és változó hossz

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

A CNN-ekben a megosztott konvolúciós kernel a térbeli pozíciókra alkalmazza ugyanazt a lokális műveletet. A szekvenciamodellekben a hasonló induktív torzítás az időbeli tengelyre vonatkozik: egy szövegrészlet, hangjel vagy idősor egymást követő tokenjei között feltételezzük, hogy a feldolgozás szabálya időben nem változik. Ebben az alfejezetben az egyszerű rekurrens cella állapotegyenletét, paramétermegosztását, a változó hosszúságú bemenetek paddingjét és a kauzális információs határt vizsgáljuk.

Előismeret: a cross-correlation és az alakok 13.2. Konvolúció és cross-correlation alfejezetből, a hibaszeletek és az értékelési körülmények 23.4. Hibaszeletek és alkalmazási határ alfejezetből, a zárt/nyílt világú inputkezelés 25.4. Nyílt halmaz és ismeretlen input alfejezetből, az alkalmazási szerződés 28.4. VII. ellenőrző pont: CNN alkalmazási szerződés alfejezetből, a látens állapot és a likelihood 31.1. VAE és variációs alsó korlát alfejezetből, valamint az embedding mint reprezentáció 28.1. Embedding, távolság és normalizálás alfejezetből. A 20.1. Feature extractor és új fej alfejezetben látott befagyasztott paraméterek gondolatát itt annyiban használjuk, hogy a rekurrens cella megosztott súlyai egyetlen paramétercsoportot alkotnak.

Induló kérdés: egy batch három különböző hosszúságú szekvenciát tartalmaz. Hogyan ábrázoljuk ezt egyetlen, fix alakú tensorral úgy, hogy a mesterségesen hozzátett üres helyek ne adjanak hamis tanítójelet, és egy adott időpont kimenete ne lássa a jövőbeli tokeneket? Becslés: kell egy explicit hosszlista, egy padding maszk és szükség esetén egy kauzális maszk; a három közül egyik sem pótolja a másikat.

32.1.2 2. Szekvencia, változó hossz és a két maszk

Definíció (véges szekvencia). Egy TT hosszúságú szekvencia

x1:T=(x1,…,xT),xt∈ℝdin, x_{1:T} = (x_1,\dots,x_T), \qquad x_t \in \mathbb{R}^{d_{in}},

ahol tt a diszkrét időindex, xtx_t pedig a tt-edik token vektoros reprezentációja. Szöveges adatban a token lehet szó, részcímke vagy karakter beágyazása; hangban spektrális keret; a korábbi GlyphLab-képekhez hasonlóan a bemeneti objektumot a feladat szerint választott ábrázolás adja.

A gyakorlati minták hossza általában nem azonos. Legyen a batch elemszáma NN, az egyes minták valódi hossza LiL_i, és

T=maxi=1,…,NLi. T = \max_{i=1,\dots,N} L_i.

A batchelt reprezentáció

X∈ℝN×T×din, X \in \mathbb{R}^{N \times T \times d_{in}},

ahol az ii-edik mintánál a t>Lit > L_i pozíciók feltöltött, pad elemek. A pad értéke leggyakrabban a 00 vektor, de önmagában a nulla érték nem azonosítja a pad pozíciót, mivel valódi token is lehet nulla. Ezért a hosszlistát külön nyilvántartjuk.

Definíció (padding maszk). A padding maszk

P∈{0,1}N×T,Pit={1,ha t>Li (pad pozíció),0,különben. P \in \{0,1\}^{N \times T}, \qquad P_{it} = \begin{cases} 1, & \text{ha } t > L_i \text{ (pad pozíció)},\\ 0, & \text{különben}. \end{cases}

A veszteségszámításban a pad pozíciókhoz tartozó tagokat ki kell zárni. Ha a modell minden időlépésre ad egy yity_{it} kimenetet és a veszteség elemenkénti, akkor a maszkolt átlag például

L=∑i=1N∑t=1T(1−Pit)ℓit∑i=1NLi, L = \frac{\sum_{i=1}^{N}\sum_{t=1}^{T}(1-P_{it})\ell_{it}}{\sum_{i=1}^{N}L_i},

Itt a nevező az érvényes, nem pad pozíciók száma; ez fontos, mert a változó hosszúság miatt a mintánkénti átlagok egyszerű átlaga nem feltétlenül azonos a tokenenkénti átlaggal. A nevező ∑iLi=∑i,t(1−Pit)>0\sum_i L_i=\sum_{i,t}(1-P_{it})>0, és ez különbözik a padelt tokenek ∑i(T−Li)\sum_i(T-L_i) számától. Az átlagolási konvenciót a 7.3. Bináris, multilabel és regressziós cél veszteségfüggvényeknél is következetesen rögzítjük.

Definíció (kauzális maszk). Az autoregresszív vagy időben okszerű feldolgozásban az ii-edik időlépés kimenete csak a j≤ij \le i inputoktól függhet. A kauzális maszk

M∈{0,1}T×T,Mij={1,ha j>i (tiltott jövőbeli input),0,különben. M \in \{0,1\}^{T \times T}, \qquad M_{ij} = \begin{cases} 1, & \text{ha } j > i \text{ (tiltott jövőbeli input)},\\ 0, & \text{különben}. \end{cases}

A maszk tehát a T×TT \times T páronkénti függésmátrix felső háromszögét tiltja a főátló fölött. A padding maszk az üres pozíciókra vonatkozik, a kauzális maszk az időrendre; a kettő nem helyettesíti egymást. Egy pad pozíció lehet múltbeli időindex is, ezért általában szükség van mindkettőre.

Intuíció a CNN-hez képest. A 2D konvolúcióban a kernel minden térbeli ablakra ugyanazt a paramétert használja: ez a térbeli eltolási equivarianciához kapcsolódik 16.1. Eltolási equivariance és invariance. A szekvenciamodellben az időbeli súlymegosztás azt fejezi ki, hogy „ugyanaz a szabály dolgozza fel a mondat elejét és végét”. A fontos különbség a recepciós mező jellege: a konvolúció véges ablakot lát, a rekurrens cella állapota viszont az egész múlt összefoglalója lehet.

32.1.3 3. Rekurrens cella állapotegyenlete és paramétermegosztása

Definíció (egyszerű rekurrens cella, oszlopvektoros alak). Legyen dhd_h a rejtett dimenzió, h0∈ℝdhh_0 \in \mathbb{R}^{d_h} a kezdeti állapot (leggyakrabban h0=0h_0 = 0). A cella paraméterei

Wh∈ℝdh×dh,Wx∈ℝdh×din,b∈ℝdh. W_h \in \mathbb{R}^{d_h \times d_h}, \qquad W_x \in \mathbb{R}^{d_h \times d_{in}}, \qquad b \in \mathbb{R}^{d_h}.

Egy f:ℝ→ℝf: \mathbb{R} \to \mathbb{R} elemenként alkalmazott aktivációval az állapotfrissítés

ht=f(Whht−1+Wxxt+b),t=1,…,T. h_t = f\!\left(W_h h_{t-1} + W_x x_t + b\right), \qquad t = 1,\dots,T.

A zt=Whht−1+Wxxt+bz_t = W_h h_{t-1} + W_x x_t + b pre-aktivációt külön névvel jelöljük, mert a gradiensszámításban szerepel.

A batchelt, NN mintát tartalmazó alakban a PyTorch-szerű konvencióval

Ht=F(Ht−1Wh⊤+XtWx⊤+b),Ht∈ℝN×dh,Xt∈ℝN×din. H_t = F\!\left(H_{t-1} W_h^\top + X_t W_x^\top + b\right), \qquad H_t \in \mathbb{R}^{N \times d_h},\; X_t \in \mathbb{R}^{N \times d_{in}}.

A bias itt is soronként broadcastolódik, ahogy az affin rétegnél megszoktuk 3.2. Mátrixszorzás és affín réteg.

A definíció lényege, hogy a Wh,Wx,bW_h, W_x, b paraméterek minden tt időlépésben ugyanazok a változók. A rekurrencia tehát egy

ΦW(xt,ht−1)=f(Whht−1+Wxxt+b) \Phi_W(x_t, h_{t-1}) = f(W_h h_{t-1} + W_x x_t + b)

függvény ismételt alkalmazása, nem pedig TT darab független réteg.

Lemma (időbeli paramétermegosztás gradiense). Tegyük fel, hogy ff elemenkénti, komponensenként differenciálható, és legyen LL skalár veszteség, amely a rejtett állapotokon keresztül függ a cellától. Jelölje

Jt=diag(f′(zt,1),…,f′(zt,dh)) J_t = \operatorname{diag}\!\big(f'(z_{t,1}),\dots,f'(z_{t,d_h})\big)

az aktiváció Jacobi-mátrixát a tt-edik lépésben. Ekkor a teljes veszteség gradiense a megosztott paraméterekre

∇WhL=∑t=1T(Jtvt)ht−1⊤,∇WxL=∑t=1T(Jtvt)xt⊤,∇bL=∑t=1TJtvt, \nabla_{W_h} L = \sum_{t=1}^{T} (J_t v_t)\, h_{t-1}^\top, \qquad \nabla_{W_x} L = \sum_{t=1}^{T} (J_t v_t)\, x_t^\top, \qquad \nabla_b L = \sum_{t=1}^{T} J_t v_t,

ahol a veszteség L=∑t=1Tℓt(ht)L=\sum_{t=1}^T\ell_t(h_t) alakú (ha csak a végső állapottól függ, akkor ℓt≡0\ell_t\equiv0 minden t<Tt<T-re), és a vektorok a következők. A közvetlen tag gt=∂ℓt/∂ht∈ℝdhg_t=\partial\ell_t/\partial h_t\in\mathbb R^{d_h}, vagyis ℓt\ell_t deriváltja hth_t szerint úgy, hogy a későbbi állapotokon át ható függést nem számoljuk. A teljes visszaterjesztett vektor vt=∇htLv_t=\nabla_{h_t}L (a jövő lépéseken át érkező hatással együtt) az utolsó lépéstől visszafelé:

vT=gT,vt=gt+Wh⊤Jt+1vt+1(t=T−1,…,1), v_T=g_T,\qquad v_t=g_t+W_h^\top J_{t+1}v_{t+1}\quad(t=T-1,\dots,1),

és az előaktivációk gradiense δt=∇ztL=Jtvt\delta_t=\nabla_{z_t}L=J_tv_t. A fenti képletekben tehát Jtvt=δtJ_tv_t=\delta_t.

Bizonyítás (rövid, a láncszabályból). Rögzített tt-re a zt=Whht−1+Wxxt+bz_t = W_h h_{t-1} + W_x x_t + b kifejezésben a WhW_h lineárisan szerepel. A mátrix–vektor szorzat deriváltja a bemeneti vektorral vett külső szorzat, ezért a ztz_t-n keresztül vett parciális hozzájárulás (Jtvt)ht−1⊤(J_t v_t) h_{t-1}^\top. Mivel ht−1h_{t-1} maga is függ a korábbi lépések WhW_h-jától, de ugyanaz a WhW_h változó szerepel azokban a lépésekben is, a láncszabály szerint a teljes gradiens az egyes tt indexekre vonatkozó parciális hozzájárulások összege. Az összegzés indexhatára t=1,…,Tt=1,\dots,T; az xtx_t és bb esetén analóg módon járunk el. A vtv_t rekurziója a 4.3. Jacobi-mátrix, láncszabály és VJP alfejezetben bevezetett VJP láncszabály következménye: hth_t két úton hat LL-re, közvetlenül ℓt\ell_t-n át (gtg_t) és a zt+1=Whht+…z_{t+1}=W_hh_t+\dots következő előaktiváción át, amelynek VJP-je Wh⊤δt+1=Wh⊤Jt+1vt+1W_h^\top\delta_{t+1}=W_h^\top J_{t+1}v_{t+1}; a két hozzájárulás összeadódik. A függőségi gráf irányított, ezért az idő mentén visszafelé haladunk. Az alakellenőrzés: Jtvt∈ℝdhJ_t v_t \in \mathbb{R}^{d_h}, ht−1⊤∈ℝ1×dhh_{t-1}^\top \in \mathbb{R}^{1 \times d_h}, a külső szorzat WhW_h alakú; xt⊤x_t^\top esetén dh×dind_h \times d_{in} adódik. ∎

Kétlépéses kézi kontroll (nemnulla visszacsatolással). Legyen dh=din=1d_h=d_{in}=1, f=tanhf=\tanh, Wh=0,5W_h=0{,}5, Wx=1W_x=1, b=0b=0, h0=0,2h_0=0{,}2, x1=0,5x_1=0{,}5, x2=−0,3x_2=-0{,}3, és L=ℓ1+ℓ2=h1+2h2L=\ell_1+\ell_2=h_1+2h_2, tehát g1=1g_1=1, g2=2g_2=2. A forward: z1=0,5⋅0,2+0,5=0,6z_1=0{,}5\cdot0{,}2+0{,}5=0{,}6, h1=tanh0,6≈0,537050h_1=\tanh0{,}6\approx0{,}537050; z2=0,5⋅0,537050−0,3≈−0,031475z_2=0{,}5\cdot0{,}537050-0{,}3\approx-0{,}031475, h2≈−0,031465h_2\approx-0{,}031465. A Jacobi-tényezők Jt=1−ht2J_t=1-h_t^2: J1≈0,711578J_1\approx0{,}711578, J2≈0,999010J_2\approx0{,}999010. A rekurzió: v2=g2=2v_2=g_2=2, δ2=J2v2≈1,998020\delta_2=J_2v_2\approx1{,}998020; v1=g1+WhJ2v2=1+0,5⋅1,998020≈1,999010v_1=g_1+W_hJ_2v_2=1+0{,}5\cdot1{,}998020\approx1{,}999010, δ1=J1v1≈1,422451\delta_1=J_1v_1\approx1{,}422451. Így

∇WhL=δ2h1+δ1h0≈1,998020⋅0,537050+1,422451⋅0,2≈1,357526,∇WxL=δ2x2+δ1x1≈0,111820. \nabla_{W_h}L=\delta_2h_1+\delta_1h_0\approx1{,}998020\cdot0{,}537050+1{,}422451\cdot0{,}2\approx1{,}357526, \qquad \nabla_{W_x}L=\delta_2x_2+\delta_1x_1\approx0{,}111820.

Ha valaki a v1v_1-ben csak a közvetlen g1=1g_1=1 tagot venné (a jövőből érkező WhJ2v2W_hJ_2v_2 nélkül), ∇WhL\nabla_{W_h}L-re ≈1,215\approx1{,}215-öt kapna. A PyTorch autograd float64-ben ugyanezt a két értéket adja hat tizedesjegyre (1,3575261{,}357526 és 0,1118200{,}111820).

A lemma a backpropagation through time elnevezés mögötti pontos számítási szabályt adja. A megosztott paraméter fontos következménye, hogy a modell paraméterszáma nem függ a szekvencia hosszától, szemben egy olyan naiv rétegsorozattal, amely minden időlépésre külön affin réteget tanulna.

LSTM-áttekintés. Az egyszerű rekurrens cella gyakorlati problémája, hogy a hosszú időlépéseken át visszaterjedő gradiens szorzataiban a JtWhJ_tW_h mátrixok ismétlődnek, ami a gradiens eltűnését vagy felrobbanását okozhatja. Az LSTM ezt úgy kezeli, hogy külön sejtállapotot ctc_t tart fenn, és input-, felejtő- meg kimeneti kapukkal szabályozza, mennyi információ íródjon be, maradjon meg vagy kerüljön a rejtett kimenetbe. Az alábbiakban csak a fogalmi szerkezetet használjuk; a pontos kapuformulákat a későbbi szekvenciafejezetben, ellenőrzött forrás mellett vezetjük be.

32.1.4 4. Kézi számpélda

Legyen din=dh=2d_{in}=d_h=2, h0=(0,0)⊤h_0=(0,0)^\top,

Wh=(0,5000,5),Wx=I2,b=(0,0)⊤, W_h = \begin{pmatrix} 0{,}5 & 0 \\ 0 & 0{,}5 \end{pmatrix}, \qquad W_x = I_2, \qquad b = (0,0)^\top,

és f=tanhf = \tanh elemenként. A bemenetek:

x1=(0,5,0)⊤,x2=(0,0,5)⊤,x3=(0,0)⊤. x_1 = (0{,}5,0)^\top, \qquad x_2 = (0,\;0{,}5)^\top, \qquad x_3 = (0,0)^\top.

A rekurzív számolás négy tizedesjegyre kerekítve:

z1=x1,h1=tanh(x1)≈(0,4621,0)⊤, z_1 = x_1, \qquad h_1 = \tanh(x_1) \approx (0{,}4621,\;0)^\top,

z2=0,5h1+x2≈(0,2311,0,5000)⊤,h2≈(0,2271,0,4621)⊤, z_2 = 0{,}5h_1 + x_2 \approx (0{,}2311,\;0{,}5000)^\top, \qquad h_2 \approx (0{,}2271,\;0{,}4621)^\top,

z3=0,5h2≈(0,1135,0,2311)⊤,h3≈(0,1131,0,2271)⊤. z_3 = 0{,}5h_2 \approx (0{,}1135,\;0{,}2311)^\top, \qquad h_3 \approx (0{,}1131,\;0{,}2271)^\top.

Két tulajdonság látható: az x1x_1 hatása a h3h_3-ban már csak ≈0,1131\approx 0{,}1131 nagyságrendű, tehát a rekurrens állapot exponenciálisan halványíthatja a régi bemeneteket; másrészt a t=2t=2 lépésben a modell csak x1x_1 és x2x_2 ismeretében számolt, a t=3t=3 bemenetet nem látta. Az alábbi minikód ellenőrzi ugyanezt:

import torch

torch.manual_seed(0)
W_h = 0.5 * torch.eye(2, dtype=torch.float32)
W_x = torch.eye(2, dtype=torch.float32)
b = torch.zeros(2, dtype=torch.float32)
x = torch.tensor([[0.5, 0.0], [0.0, 0.5], [0.0, 0.0]],
                 dtype=torch.float32)
h = torch.zeros(2, dtype=torch.float32)
print(f"{'t':>2} {'h_t':>20}")
print(f"{0:>2} {h.tolist()}")
for t, x_t in enumerate(x, start=1):
    h = torch.tanh(h @ W_h.T + x_t @ W_x.T + b)
    print(f"{t:>2} {[round(float(v), 4) for v in h]}")

A kód a batchelt formát ugyanazzal a transzponált affin konvencióval használja; a fenti számokkal a kerekített egyezés várható, de a tanh implementációja miatt az utolsó tizedesjegyekben eltérés lehet, ezért 1e-3 abszolút tolerancia az ésszerű ellenőrzési határ.

32.1.5 5. Labor: padding és kauzális információs határ

A labor célja, hogy egyetlen minibatchben lássuk a padding maszk és a kauzális maszk különböző szerepét. A kód nem követeli meg a teljes tanítást, csak a két maszk konstrukcióját és egy ellenőrző mérést.

import torch

torch.manual_seed(0)

# Három változó hosszúságú minta, T=4, d_in=3.
# Az első 4, a második 3, a harmadik 1 érvényes token.
lengths = torch.tensor([4, 3, 1])
X = torch.randn(3, 4, 3, dtype=torch.float32)

# Padding maszk: P[i,t]=1, ha t >= lengths[i].
T = X.size(1)
pad_mask = torch.arange(T)[None, :] >= lengths[:, None]

# Kauzális maszk: M[i,j]=1, ha j > i (a jövő tiltása).
causal_mask = torch.triu(torch.ones(T, T, dtype=torch.bool), diagonal=1)

# Ellenőrzés: pad maszk érvényes elemszáma egyenlő a hosszlista összegével.
assert int((~pad_mask).sum()) == int(lengths.sum())

# Causal maszk: főátló és alsó háromszög engedélyezett.
allowed = ~causal_mask
assert torch.equal(allowed, torch.tril(torch.ones(T, T, dtype=torch.bool)))

print("pad_mask =")
print(pad_mask.int())
print("causal_mask (tiltott = 1) =")
print(causal_mask.int())

A várt kimenet (jelölt szemléltetés, nem mért futás):

pad_mask =
tensor([[0, 0, 0, 0],
        [0, 0, 0, 1],
        [0, 1, 1, 1]], dtype=torch.int32)
causal_mask (tiltott = 1) =
tensor([[0, 1, 1, 1],
        [0, 0, 1, 1],
        [0, 0, 0, 1],
        [0, 0, 0, 0]])

Az ellenőrzési pont: az első mintának nincs pad eleme, a harmadiknak a 2,3,42,3,4 időindexű elemei mind pad pozíciók. A kauzális maszk első sora a 2,3,42,3,4 pozíciót tiltja, mert az első időlépés kimenete csak az első inputtól függhet. Ha egy modell minden időlépésben ugyanazt az inputot kapná, a padding maszk önmagában nem tiltaná a jövőt; a kauzális maszkra akkor is szükség van, ha az összes pozíció érvényes, tehát a kettő nem ugyanazt a hibát védi ki.

Futtatási utasítás: a fenti kódot a lab/n125/pad_causal_demo.py fájlba téve a

python lab/n125/pad_causal_demo.py

parancs futtatja. A torch.manual_seed(0) miatt a véletlen bemenet reprodukálható CPU-n, de más PyTorch-verzió esetén a generált számok nem garantáltan bitazonosak; a két assert ekkor is ellenőrzi a maszkok szerkezetét.

32.1.6 6. Feladatok

F1 (fogalmi, nehézség 1). Adjon olyan konkrét N=2N=2, T=3T=3 példát, amelyben a padding maszk és a kauzális maszk különböző pozíciókat tilt, és magyarázza meg, miért nem elegendő önmagában a padding maszk egy autoregresszív modell tanításához.

F2 (levezetési, nehézség 2). Tekintsünk egy lineáris rekurrens cellát f(z)=zf(z)=z, Wx=IW_x=I, b=0b=0, h0=0h_0=0 és skalár paraméterrel Wh=αIW_h=\alpha I, ahol α∈ℝ\alpha \in \mathbb{R}. Vezesse le a hTh_T zárt alakját x1:Tx_{1:T} függvényében, és adja meg pontosan, mely α\alpha értékekre korlátos a T→∞T \to \infty limesz tetszőleges, egyenletesen korlátos bemeneti sorozatra. Ellenőrizze az eredményt a lemma gradienseinek speciális esetére.

F3 (implementációs, nehézség 2). Írjon olyan Python-függvényt, amely egy változó hosszúságú batch X és lengths tenorból kiszámítja a pad_mask-et, majd egy adott loss_per_step azonos alakú tensoron a maszkolt átlagot. A függvény térjen vissza az átlaggal és az érvényes elemszámmal is. Teszteset: X alakja (3,4,3), lengths = [4,3,1], loss_per_step legyen csupa egy; várt érvényes elemszám 4+3+1=84+3+1=8, várt átlag 11.

F4 (hibakeresési, nehézség 2). Egy fejlesztő a következőt írja: a paddingnek a veszteségben való kihagyásához a pad pozícióknál nullázza a rejtett állapotot a rekurrens lépés után, de a maszkot nem használja a veszteségátlagban. Lokalizálja a két hibát, indokolja a tanulási következményt, és adjon minimális javítást a fenti labor kódjához.

F5 (kísérlettervezési/transzfer, nehézség 3). Egy osztályozó modell bemenetként változó hosszúságú, legfeljebb T=64T=64 hosszú szekvenciákat kap. Tervezzen kísérletet annak eldöntésére, hogy a T=64T=64-re való padding vagy a T=32T=32-re való csonkolás ad-e jobb validációs pontosságot adott számítási keret mellett. Adja meg a protokollt: adatforrás, megfigyelési egység, split, baseline, változó tényező, metrika, validációs választás és a következtetés érvényességi határát. A feladat nyitott, egy lehetséges terv ismertetése elfogadható.

32.1.7 7. Megoldások és indoklás

F1. Legyen N=2N=2, L=(3,2)L=(3,2), így T=3T=3. A padding maszk csak a második minta harmadik pozícióját tiltja: P=(0,0,0;0,0,1)P=(0,0,0;0,0,1). A kauzális maszk ezzel szemben a (1,2),(1,3),(2,3)(1,2),(1,3),(2,3) (query-idő, key-idő) párokra 11: a kimenet t=2t=2 időpontban nem láthatja a t=3t=3 jövőbeli bemenetet, akkor sem, ha mindkét minta minden pozíciója érvényes. A padding maszk csak az üres pozíciókat kezeli; ha a modell például attentiont számol, akkor egy érvényes x2x_2 token jövőbeli x3x_3 tokenre is figyelhetne, ami tanításban magas pontosságot, de az autoregresszív használatban összeomlást ad. A két maszk együtt használandó: az engedélyezett pozícióhalmaz (1−Pit)∧(1−Mtj)(1-P_{it})\wedge(1-M_{tj}).

F2. A lineáris rekurzió ht=αht−1+xth_t = \alpha h_{t-1} + x_t. Teljes indukcióval:

hT=∑s=1TαT−sxs. h_T = \sum_{s=1}^{T} \alpha^{T-s} x_s.

Ez a konvolúciós forma is: egy geometriailag csillapodó, időben megosztott szűrő. Az alakellenőrzés: hT∈ℝdhh_T \in \mathbb{R}^{d_h}, minden tag ugyanakkora dimenziójú. Ha ∥xs∥2≤C\|x_s\|_2 \le C minden ss-re, akkor

∥hT∥2≤C∑s=1T|α|T−s. \|h_T\|_2 \le C \sum_{s=1}^{T} |\alpha|^{T-s}.

A sorozat korlátos minden TT-re pontosan akkor, ha |α|<1|\alpha|<1, ekkor a felső korlát C/(1−|α|)C/(1-|\alpha|). Ha |α|>1|\alpha|>1, választható konstans xs=x≠0x_s = x \ne 0 bemenet, amelyre ∥hT∥\|h_T\| divergál; ha |α|=1|\alpha|=1, az α=1\alpha=1 esetben hT=∑s≤Txsh_T=\sum_{s\le T}x_s, ami már konstans bemenet mellett is lineárisan nő, α=−1\alpha=-1 esetén pedig váltakozó módon nem konvergál. A lemma szerint a lineáris esetben Jt=IJ_t=I, így ∇WhL=∑tvtht−1⊤\nabla_{W_h}L = \sum_t v_t h_{t-1}^\top, ami a kimondott képlet speciális esete.

F3. Minimális, futtatható megoldás:

import torch

def masked_mean_loss(loss_per_step, lengths):
    """
    loss_per_step: float32 tensor, shape (N, T)
    lengths: int64 tensor, shape (N,), minden elem 1..T
    Visszaadja a nem pad elemek átlagát és az érvényes elemszámot.
    """
    N, T = loss_per_step.shape
    pos = torch.arange(T)[None, :]
    valid = pos < lengths[:, None]
    denom = int(valid.sum())
    if denom == 0:
        raise ValueError("üres batch: nincs érvényes pozíció")
    return float(loss_per_step[valid].sum() / denom), denom

# Teszt
loss = torch.ones(3, 4, dtype=torch.float32)
lengths = torch.tensor([4, 3, 1], dtype=torch.int64)
mean, count = masked_mean_loss(loss, lengths)
print(mean, count)  # 1.0, 8
assert mean == 1.0 and count == 8

Szélsőeset: ha egy minta hossza 00, a függvény azt a pozícióját kihagyja; ha minden hossz 00, az üres batch hibát dob, mert az átlag nem definiált. Az assert float egyenlőséget használ, ami itt a csupa egyes mátrixon pontos; más adatoknál toleranciát kell adni.

F4. Az első hiba: a rejtett állapot nullázása utólag nem szünteti meg, hogy a rekurrens lépésben a pad token már beírta a hatását a megelőző lépésekből; ráadásul ha a nullázás a következő lépés bemeneteként szolgál, az állapotdinamika torzul. A második hiba: a veszteségátlagban a pad pozíciók továbbra is szerepelnek, ezért a nevező N⋅TN \cdot T lesz az érvényes elemszám helyett, és a modell a pad tokenekre is illeszteni próbál. Következmény: a veszteség hamis jelzést ad, a gradiens felfelé torzul a hosszú minták irányába, a rövid mintákra rosszabbul általánosít. Javítás: a rekurrens lépés bemeneti pozíciójában a pad tokeneket ne etessük be, vagy ha az RNN implementáció minden lépést számol, akkor a veszteségben alkalmazzuk a pad_mask-et; a fenti labor masked_mean_loss-hez hasonlóan. Visszaellenőrzés: érvényes elemszámnak 88-nak kell lennie a tesztesetben, nem 1212-nek.

F5. Egy lehetséges terv: készítünk egy procedurális, 64-nél nem hosszabb szekvenciákat generáló adatforrást; minden adatpont egy független szekvencia, a generálási folyamat rögzített seeddel. A split train/val/test például 600/100/100, a testet csak a végén használjuk. A baseline legyen egy osztályonkénti prior-osztályozó, hogy a magas osztályarány ne adjon hamis képet. A változó tényező a bemenet-előkészítés: (A) pad T=64T=64-re; (B) csonkol T=32T=32-re. Ugyanazt a modellvázat (például egy rekurrens cella vagy kauzális konvolúció utolsó állapotára illesztett lineáris fej) mindkét beállítással tanítjuk, azonos loss, optimizer, seed és epochszám mellett. A kiválasztás metrikája a validációs accuracy; a seedek több ismétlésével (például 10) a különbségre adunk szórást is. Az érvényességi korlát: az eredmény csak a saját szekvencia-eloszlásra és hossztartományra vonatkozik; a T=32T=32-re csonkolásnál a hosszú minták elveszett farokinformációja miatt a pontosságromlás az adott tartalomtól függ, ezért a következtetést nem szabad általános csonkolási szabályként kimondani. A számítási költség mérésekor a futási időt is rögzíteni kell, mert a rövidebb bemenet nemcsak pontosabb vagy pontatlanabb, hanem gyorsabb is lehet.

32.1.8 8. Tipikus tévedés ellenpéldával, önellenőrzés, visszahívás

A leggyakoribb tévedés, hogy a tanításkor elérhető teljes szekvenciát automatikusan az inferenciahelyzettel azonosnak tekintjük. Ez nemcsak a padding mask hiányakor, hanem akkor is hibás, ha a modell a tt-edik kimenethez a tt utáni tokeneket is bemenetként kapja. Ellenpélda: legyen egy fordítói vagy következő token predikciós modell, amely tanításkor a x3x_3 inputot is felhasználja a t=2t=2 kimenet előállításához. A tanítási veszteség kicsi lehet, mert a cél token gyakran megegyezik a következő bemeneti tokennel. Az éles használatban azonban x3x_3 még nem áll rendelkezésre a t=2t=2 döntésnél, így a modellt olyan bemenetre kényszerítjük, amelyet soha nem látott. A megoldás a kauzális maszk: a tt-edik kimenetnek kizárólag j≤tj \le t bemeneteken szabad múlnia; a padding maszk önmagában ezt nem garantálja. A helyes kísérleti napló ezért külön rögzíti a tanítási és az autoregresszív kiértékelési módot 12.1. Tanítás, validáció és kiértékelési mód.

Önellenőrző kérdések: (1) Meg tudom-e mondani a PP és az MM maszk pontos alakját? (2) A lemma összegzésében miért t=1t=1-től TT-ig összegzünk, és miért nem ugyanaz, mint egyetlen hosszú affin lánc gradiense? (3) Mi a zero padding szerepe a CNN-ben 14.1. Stride, padding, dilation és outputméret, és miért nem azonos a szekvenciális padding maszkkal?

Visszahívás: a 31.1. VAE és variációs alsó korlát alfejezetben bevezetett qϕ(z|x)q_\phi(z|x) látens kódolóval szemben a rekurrens hth_t determinisztikus időbeli állapot, nem valószínűségi posterior. A 28.1. Embedding, távolság és normalizálás alfejezetben az embedding egyetlen input statikus reprezentációja volt; itt a rejtett állapot az inputok sorozatától függő, kontextusfüggő reprezentáció. A 20.1. Feature extractor és új fej alfejezetben a befagyasztott backbone paramétereihez hasonlóan a rekurrens cellában is egy paramétercsoportként kezeljük a megosztott Wh,Wx,bW_h, W_x, b hármast.

32.1.9 Rövid összefoglaló

A szekvenciamodell a változó hosszúságú token-sorozatokat közös időtengelyen ábrázolja. A padding maszk az érvénytelen pozíciókat, a kauzális maszk a jövőbeli információs csatornát zárja le; a kettő nem helyettesíthető. Az egyszerű rekurrens cella ugyanazt a Wh,Wx,bW_h, W_x, b paramétert használja minden időlépésben; a lemmában megmutattuk, hogy a gradiensük az időlépésenkénti külső szorzatok összege. Az LSTM kapukkal vezérli a hosszú távú állapotot; a temporális konvolúció ezzel szemben véges recepciós mezőjű, nem rekurrens művelet. A kézi és a kódos példa a maszkok szerkezetét és az időbeli súlymegosztás hatását ellenőrzi.

32.1.10 Következő alkalmazás

A 32.2. Scaled dot-product attention egységben a rekurrenciát elhagyjuk, és a scaled dot-product attention operátort vezetjük be. A most definiált kauzális és padding maszk ott közvetlenül a figyelmi súlymátrixra kerül; az időbeli súlymegosztás helyébe a pozíciófüggetlen, de pozíciókódolást igénylő attention lép.

32.1.11 Felhasznált források