- Je beschrijft welke oude tokens verdwijnen wanneer een contextvenster vol is.
- Je scheidt token-ID’s, zichtbare posities, attentionmaskers en loss-maskers.
Je gesprek wordt langer dan het modelvenster. Welke oude woorden verdwijnen, en weet het model nog welke posities echt tekst zijn? Een contextvenster (context window) begrenst één berekening; het is geen permanent geheugen.
Denk aan een leesstrook die over een zin schuift. Links verdwijnen woorden, en kortere zinnen krijgen lege plekken om samen in een rechthoekige batch te passen. Weglaten, nummeren en maskeren zijn daarbij afzonderlijke beslissingen.
1. Zeg wat je weglaat
Neem token-ID’s [7,8,9,10] en capaciteit drie. Je bewaart [8,9,10], rapporteert één weggelaten token en gebruikt lokale posities [0,1,2]. De functie verandert de originele reeks niet.
ids = np.array([7,8,9,10])
kept,pos,dropped = rolling_context(
ids,3)
print(kept) # [ 8 9 10]
print(pos) # [0 1 2]
print(dropped) # 1
Maak rolling_context met een niet-lege, gehele 1D-reeks en positieve exacte integercapaciteit. Ook wanneer niets verdwijnt, geef je een kopie terug. Dat voorkomt dat een latere wijziging in het venster stilzwijgend de oorspronkelijke invoer raakt.
Ons mini-GPT begint na afknippen opnieuw bij positie nul. De overgebleven tokens krijgen daardoor andere geleerde positie-embeddings en de vorige KV-cache is niet meer geldig. Een grotere positietabel toevoegen leert het model evenmin vanzelf langere context begrijpen.
Andere modellen kunnen andere positie- of venstermechanismen gebruiken. Deze opdracht beschrijft alleen ons lokale venstercontract. Het maakt verloren informatie zichtbaar, maar reconstrueert geen verdwenen tekst.
012. Scheid opvulplekken van echte tokens
Voor [[0,2,3],[4],[]] hebben we drie kolommen nodig. De opvulplekken krijgen ID 0, net als de eerste echte token in de eerste rij. De aparte valid-matrix bewaart welke posities echt zijn.
ids,valid,pos = left_pad(
[[0,2,3],[4],[]],0)
print(ids)
# [[0 2 3]
# [0 0 4]
# [0 0 0]]
print(valid.astype(int))
# [[1 1 1]
# [0 0 1]
# [0 0 0]]
Maak left_pad voor een niet-lege lijst van 1D-reeksen. IDs en posities zijn int64; valid is boolean. Een lege rij mag zolang ergens echte tekst staat; een geheel lege batch of alleen lege rijen geeft ValueError.
Posities tellen alleen echte tokens vanaf nul. In ons voorbeeld zijn ze [[0,1,2],[0,0,0],[0,0,0]]: de enige token in de tweede rij staat lokaal op nul. Padding krijgt eveneens nul als veilige placeholder, zonder daardoor geldig te worden.
023. Laat alleen geldige routes door
Een echte query mag eerdere echte keys en zichzelf bekijken. Ze mag geen toekomsttoken of paddingkey zien. Een paddingquery mag helemaal geen key zien.
A is de booleaanse toestemming, b de batchrij, i de querypositie en j de keypositie. v geeft aan of een positie echt is; ∧ betekent dat alle voorwaarden waar moeten zijn. De geretourneerde vorm (B,1,T,T) kan over attentionheads broadcasten.
mask = padded_causal_mask(valid)
print(mask.shape) # (3,1,3,3)
print(mask[1,0].astype(int))
# [[0 0 0]
# [0 0 0]
# [0 0 1]]
Maak padded_causal_mask met niet-lege 2D-booleans. Onze masked_softmax geeft voor een volledig verboden rij nulgewichten. Een latere bias of residual kan op padding toch niet-nul uitvoer maken; een attentionmasker vervangt daarom geen loss-masker.
losses = np.array([[1.,2.,3.],
[9.,9.,4.],
[9.,9.,9.]])
print(losses[valid].mean()) # 2.5
De vier echte doelen tellen hier mee; de kunstmatige negens op padding niet. De bestaande mini-GPT verwacht gelijklange vensters zonder padding. Je hebt een expliciete adapter voor posities, attention én loss nodig voordat deze batchhelpers daarin passen.
03Wat neem je mee?
- Afknippen verliest informatie en kan positie-embeddings veranderen.
- Een token-ID bepaalt niet of een positie padding is.
- Attention- en loss-maskers bewaken verschillende delen van de berekening.
Hierna onderzoek je wat er verandert als je gewichten met minder getallenprecisie opslaat.