- Je maakt begrensde tijdkenmerken en voorspelt twee ruiscoördinaten met een MLP.
- Je berekent het gemiddelde kwadratische ruisverlies en alle vier parametergradiënten.
Hetzelfde verstoorde punt kan op verschillende tijdstappen een andere betekenis hebben. Vroeg in het proces lijkt het nog sterk op een schoon voorbeeld; laat in het proces bevat het vooral ruis. Een ruisvoorspeller moet daarom weten naar welke stap hij kijkt.
Denk aan een restaurateur die zowel de beschadigde tekening als de ernst van de beschadiging ziet. Ons kleine netwerk krijgt twee puntcoördinaten en twee tijdkenmerken. Het schone punt en de werkelijk toegevoegde ruis blijven buiten zijn invoer; die ruis is alleen het trainingsdoel.
We hergebruiken de MLP en backprop uit de eerdere track. Het netwerk heeft één tanh-laag en voorspelt twee getallen: de ruis in beide coördinaten. Dit kleine model is bedoeld om de leerregel te begrijpen, niet om de beeldkwaliteit van grote diffusiemodellen na te bootsen.
1. Maak de tijd zichtbaar
Onze arrays gebruiken index j van nul tot en met T−1, voor T ruistappen. Zet die om naar hoek φ met de volgende formule en voeg sin(φ) en cos(φ) toe aan het punt. Zo blijven de tijdwaarden begrensd en heeft iedere toegestane stap een eigen positie op een halve cirkel.
features = diffusion_features(
[[2.,-1.]],[0],2)
print(features.round(3).tolist())
# [[2.0, -1.0, 1.0, 0.0]]
Bij T=2 hoort index nul bij hoek π/2: sinus één en cosinus nul. De laatste stap ligt bij hoek π: sinus nul en cosinus min één. Het zijn gekozen tijdkenmerken, geen geleerde informatie over het schone punt.
Maak diffusion_features met één floatrij per punt: eerst beide coördinaten, daarna sinus en cosinus. Gebruik de gegeven validators voor stappen, gehele indices en matrices. Een verkeerde index moet een fout opleveren; stilzwijgend afronden of de laatste stap afknippen verbergt een programmeerfout.
012. Voorspel ruis met gewone netwerkgewichten
Noem de featurematrix F, de verborgen activaties H en de voorspelde ruis E. De eerste matrix W₁ heeft vier invoerrijen; de tweede matrix W₂ heeft twee uitvoerkolommen. Biasvectoren b₁ en b₂ worden per voorbeeld opgeteld.
Voor een handvoorbeeld kiezen we één verborgen eenheid met nulgewichten in W₁ en bias nul. Dan is H overal nul. Met W₂=[1,2] en uitvoerbias nul voorspelt het netwerk dus [0,0], ongeacht het punt.
parameters = {
'w1':np.zeros((4,1)),
'b1':np.zeros(1),
'w2':np.array([[1.,2.]]),
'b2':np.zeros(2)}
prediction = predict_noise(
parameters,[[2.,-1.]],[0],2)
print(prediction.tolist())
# [[0.0, 0.0]]
Maak predict_noise met deze twee lineaire stappen en tanh ertussen. Een nulvoorspelling betekent niet dat er geen ruis in het voorbeeld zit: het betekent alleen dat deze gewichten nul voorspellen. Het latere bouwproject gebruikt willekeurige initialisatie voor echte training; dit speciaal gekozen handvoorbeeld dient alleen om na te rekenen.
Vergelijk dezelfde onafhankelijke validatiepunten vóór en na training. Het netwerk krijgt het verstoorde punt en twee tijdkenmerken.
| x | y | sin φ | cos φ |
|---|---|---|---|
| 1,013 | 1,164 | 0,707 | 0,707 |
- Werkelijke doelruis ε
- Voorspelde ruis E
| Vector | Coord. 1 | Coord. 2 |
|---|---|---|
| Doel ε | -1,241 | -1,088 |
| Model E | -0,262 | 0,106 |
- MSE over alle 8 punten
- 0,858
- Menselijke stap / index
- 16 / 15
Verlies over acht voorbeelden kan per stap schommelen. Een betere gemiddelde score garandeert geen perfecte voorspelling voor ieder afzonderlijk punt.
Voorberekende uitkomsten van 2000 echte updates met één vaste seed. Het doel ε staat alleen naast de voorspelling ter vergelijking; het is geen netwerkinvoer. In het bouwproject train je zelf.
3. Reken het verschil terug naar de parameters
Vergelijk E met de werkelijk toegevoegde ruis ε. Bij B punten en twee coördinaten is het verlies L het gemiddelde van 2B gekwadrateerde verschillen. E_i en ε_i zijn de twee ruiscoördinaten van punt i; de gekwadrateerde L2-norm telt beide kwadraten op.
De afgeleide G per uitvoerwaarde is twee maal het verschil gedeeld door 2B. Dat vereenvoudigt tot het verschil gedeeld door B. Vergeet de feature-as niet bij het middelen.
Neem voor hetzelfde voorbeeld doelruis [1,−1]. De voorspelling [0,0] heeft verschillen [−1,1], dus gemiddeld kwadraatverlies één. De gradiënt van b₂ is eveneens [−1,1].
loss,gradients = noise_loss_and_grad(
parameters,[[2.,-1.]],[0],
[[1.,-1.]],2)
print(loss)
print(gradients['b2'].tolist())
# 1.0
# [-1.0, 1.0]
Voor de verborgen eenheid is de terugkomende gradiënt −1×1+1×2=1. Omdat tanh bij nul afgeleide één heeft, is de W₁-gradiënt gelijk aan de featurevector als kolom. Dit controleert tegelijk de rol van de tijdkenmerken.
print(gradients['w1'].round(3).tolist())
# [[2.0], [-1.0], [1.0], [0.0]]
Maak noise_loss_and_grad met uitvoer (verlies, gradiëntdictionary) voor alle vier parameterarrays. Behoud de invoer; deze functie berekent de leerinformatie maar voert nog geen update uit. Het bouwproject past later Adam toe en bewaart het werkelijk gemeten minibatchverlies.
03Wat neem je mee?
- De voorspeller krijgt alleen het verstoorde punt en zijn tijdkenmerken.
- Een gewone MLP kan de ruisvector als regressiedoel leren.
- Het verlies middelt over punten én coördinaten; backprop levert vier parametergradiënten.