Handboek · hoofdstuk 43Neurale netwerken
Een netwerk leert door de kettingregel door iedere laag terug te rekenen
Een vermogensmodel kan een krom verband tussen instraling en temperatuur bevatten. Een klein neuraal netwerk leert zulke samenhang, maar vraagt controle van iedere afgeleide en een eerlijke toets. Je bouwt het zonder verborgen trainingsfunctie in NumPy.

- Je kan perceptron, activaties en niet-lineariteit uitleggen.
- Je kan voorwaartse propagatie met matrixvormen uitvoeren.
- Je kan gradiëntafdaling aan e02 verbinden.
- Je kan backpropagation afleiden en numeriek controleren.
- Je kan een klein NumPy-netwerk trainen en convolutionele gewichtsdeling berekenen.
Het perceptron maakt één scheidingsvlak
Een klassiek perceptron vormt en geeft label 1 bij z≥0. Bij een fout wordt w met een stap in de richting van de gelabelde sample aangepast. Met alleen één lineair vlak kun je niet iedere verdeling scheiden. XOR is het bekende tegenvoorbeeld: twee gelijke bits hebben label nul en twee verschillende bits label één.
Een modern netwerk vervangt de harde stap tijdens training meestal door differentieerbare activaties. Het neuron is een rekenmodel, geen complete biologische zenuwcel. Zonder niet-lineariteit tussen lagen blijft iedere opeenvolging van affine lagen één affine functie: meer lagen alleen geven dan geen kromme grens.
Activatie verandert ook het leerpad
Sigmoid past bij een binaire uitvoerkans; tanh is symmetrisch tussen −1 en 1; ReLU is . De keuze hoort bij taak en verliesfunctie. Voor regressie kan de laatste laag lineair zijn, zodat de uitvoer niet tot [0,1] wordt beperkt.
tanh heeft afgeleide en raakt bij grote |z| verzadigd: de gradiënt wordt klein. ReLU heeft afgeleide één voor positieve z en nul voor negatieve z; een neuron dat altijd negatief blijft kan niet meer leren via dat pad. Schaal invoer en kies een passende initialisatie. Een activatie is dus een beslissing over modelvorm én optimalisatie.
Waarom XOR twee stappen vraagt
- één lineaire score z=b+w1x1+w2x2
- toon de tegenspraak; bouw twee verborgen regio's
- 1Voor (0,0) negatief moet b<0. Voor de twee enkelvoudige enen moeten b+w1≥0 en b+w2≥0. Dan b+w1+w2≥−b>0, terwijl (1,1) negatief zou moeten zijn.
- 2Twee verborgen drempelneuronen kunnen OR en AND vormen: h1=stap(x1+x2−0,5), h2=stap(x1+x2−1,5). Output=stap(h1−2h2−0,5). Controleer de vier combinaties; dit is XOR.
- 3De constructie toont representatie. Een harde stap is niet geschikt voor de gewone differentieerbare backprop-code; gebruik voor training gladde of stukgewijs differentieerbare activaties.
Voorwaartse propagatie bewaart de batchvorm
Voor n waarnemingen en twee features is X een n×2-matrix. Met twaalf verborgen neuronen is W1 2×12 en b1 lengte 12. NumPy broadcast de bias langs de sample-as. H=tanh(XW1+b1) heeft vorm n×12. W2 is 12×1; b2 lengte 1. De regressie-uitvoer heeft vorm n×1.
Een matrixvorm voorkomt twaalf los geschreven neuronlussen, maar vraagt controle van assen. Een uitvoer (n,1) aftrekken van een doelvector (n,) kan onbedoeld een n×n-matrix maken. De code maakt beide tot één doelvector voordat de fout wordt berekend. Bewaar de tussenactivaties: backprop gebruikt precies het forwardpad dat de voorspelling gaf.
Een neuron volledig vooruitrekenen
- één tanh-neuron
- doel y=0,8
- voorspelling en half-kwadratisch verlies
- 1z1=0,8×0,5+0,1=0,5; h=tanh(0,5)=0,462117.
- 2ŷ=0,7×0,462117+0,2=0,523482.
- 3L=(ŷ−y)²/2=0,038231. De fout e=−0,276518 heeft hier uitvoereenheid; de parameters in dit handvoorbeeld zijn dimensieloos.
Gradiëntafdaling verbindt aan e02
De lokale gradiënt geeft de richting van sterkste stijging. De update is . Een kleine η kan traag leren; een te grote η kan oscillatie of divergentie veroorzaken. Een niet-convex netwerkverlies heeft geen algemene garantie op het globale minimum.
Full-batch gebruikt alle trainingssamples per update. Mini-batches geven vaker een update met een ruisachtige gradiënt; dat kan rekenwerk efficiënter maken. Schud alleen binnen de toegestane trainingsgrens. Vergelijk trainings- en validatieverlies en sla een model op volgens een vooraf gekozen validatieregel. De eindtest kiest geen leersnelheid of epoch.
Backpropagation is de kettingregel
Voor een lineaire regressie-uitvoer en gemiddelde half-kwadratische fout geldt . Dan en de biasgradiënt is de som over samples. De verborgen fout is voor tanh. Daaruit volgen en de bias-som.
Het Hadamardproduct ⊙ is elementgewijs; matrixproducten dragen foutinvloed naar eerdere lagen. Bereken alle gradiënten met dezelfde oude parameters en voer daarna updates uit. Als W2 al verandert voordat D1 wordt berekend, past de kettingregel niet meer bij de forwardpass. Een L2-straf λ||W||²/2 voegt λW toe aan de gewichtgradiënt.
Het handneuron terugrekenen
- L=e²/2
- η=0,1
- alle vier gradiënten en updates
- 1dL/dw2=e·h=−0,127784; dL/db2=e=−0,276518.
- 2δ1=e·w2·(1−h²)=−0,152227. Dus dL/dw1=δ1×x=−0,076113 en dL/db1=−0,152227.
- 3Nieuwe waarden: w1≈0,807611; b1≈0,115223; w2≈0,712778; b2≈0,227652. Alle updates gebruiken de oude forwardwaarden.
Een onafhankelijke afgeleidecontrole
Voor één parameter θj is een centrale-differentieschatting . Vergelijk deze met backprop vóór training, op een kleine batch en meerdere parameters. Zij gebruikt opnieuw de forwardfunctie en controleert zo een onafhankelijk rekenpad.
Neem ε niet zo klein dat floating-pointaftrekking domineert, en niet zo groot dat kromming de afgeleide vervormt. Bij ReLU kan een verschil de knik kruisen; dat is geen glad afgeleidepunt. Een geslaagde gradiëntcontrole bewijst de update-algebra, geen goede dataset of geschikte toepassing.
Het PV-netwerk leert in echte NumPy
De module heeft 1,40 kWp als systeemgrens. Deze demonstratie schat ongeclipt beschikbaar DC-vermogen uit gerealiseerde instraling en celtemperatuur. Zij levert geen dag-vooruitfout of jaaropbrengst. Alleen training bepaalt de scaler; validatie kiest de opgeslagen epoch. De code vergelijkt op dezelfde honderd testomstandigheden met lineaire regressie en de ruisvloer van het bekende synthetische proces.
import numpy as nprng=np.random.default_rng(43)# Onafhankelijke synthetische omstandigheden; geen dag-vooruitprognoses.G=rng.uniform(0,1000,500)Tcel=rng.uniform(-5,55,500)+15*G/1000X=np.column_stack((G,Tcel))waar=1.40*(G/1000)*(1-.004*(Tcel-25))y=waar+rng.normal(0,.015,len(G))ids=rng.permutation(len(G)); tr,va,te=np.split(ids,[300,400])gem=X[tr].mean(axis=0); sd=X[tr].std(axis=0)Z=(X-gem)/sdpar=[rng.normal(0,.25,(2,12)),np.zeros(12), rng.normal(0,.25,(12,1)),np.zeros(1)]lam=1e-4def vooruit(z,p): W1,b1,W2,b2=p h=np.tanh(z@W1+b1) return (h@W2+b2).ravel(),hdef verlies(z,y,p): pred,h=vooruit(z,p) return np.mean((pred-y)**2)/2+lam*(np.sum(p[0]**2)+np.sum(p[2]**2))/2def gradient(z,y,p): pred,h=vooruit(z,p) d2=(pred-y)[:,None]/len(y) d1=(d2@p[2].T)*(1-h*h) return [z.T@d1+lam*p[0],d1.sum(axis=0), h.T@d2+lam*p[2],d2.sum(axis=0)]# Onafhankelijke centrale-differentiecontrole vóór training.g=gradient(Z[tr],y[tr],par)[0][0,0]eps=1e-6; oud=par[0][0,0]par[0][0,0]=oud+eps; plus=verlies(Z[tr],y[tr],par)par[0][0,0]=oud-eps; min_=verlies(Z[tr],y[tr],par)par[0][0,0]=oudfd=(plus-min_)/(2*eps)print("gradient analytisch/numeriek",round(g,9),round(fd,9),"verschil",abs(g-fd))assert abs(g-fd)<1e-7# Adam: lopende eerste/tweede momenten, met biascorrectie.m=[np.zeros_like(a) for a in par]; v=[np.zeros_like(a) for a in par]best=np.inf; historie=[]; beste=Nonefor epoch in range(1,2001): gg=gradient(Z[tr],y[tr],par) for j in range(4): m[j]=.9*m[j]+.1*gg[j]; v[j]=.999*v[j]+.001*gg[j]**2 par[j]-=.01*(m[j]/(1-.9**epoch))/(np.sqrt(v[j]/(1-.999**epoch))+1e-8) pt=vooruit(Z[tr],par)[0]; pv=vooruit(Z[va],par)[0] tv=np.mean((pv-y[va])**2) if tv<best: best=tv; beste=[a.copy() for a in par]; beste_epoch=epoch if epoch%50==0: historie.append((epoch,np.mean((pt-y[tr])**2),tv))pred,h=vooruit(Z,beste)lineair=np.column_stack((np.ones(len(Z)),Z))coef=np.linalg.lstsq(lineair[tr],y[tr],rcond=None)[0]rmse=lambda a,b: np.sqrt(np.mean((a-b)**2))print("gekozen epoch",beste_epoch,"parameters",sum(a.size for a in par))print("test RMSE netwerk",round(rmse(y[te],pred[te]),5),"kW")print("test RMSE lineair",round(rmse(y[te],lineair[te]@coef),5),"kW")print("model-noise RMSE",round(rmse(y[te],waar[te]),5),"kW")assert np.all(np.isfinite(pred))gradient analytisch/numeriek -0.109852295 -0.109852295 verschil 2.3535340343272537e-13 gekozen epoch 2000 parameters 49 test RMSE netwerk 0.01535 kW test RMSE lineair 0.03027 kW model-noise RMSE 0.01386 kW
De optimizer en de leercurve uitleggen
De code gebruikt Adam voor de updates: een lopend gemiddelde m van gradiënten en v van hun kwadraten. Biascorrectie deelt door en omdat beide momenten bij nul starten. De update deelt de gecorrigeerde eerste momentwaarde door de wortel van het tweede moment plus een kleine stabilisatieterm.
Deze optimizer verandert de parameterstap, niet de backprop-afleiding. De leswaarden β1=0,9, β2=0,999 en η=0,01 zijn keuzes voor deze demonstratie. Een dalend trainingsverlies met stijgend validatieverlies wijst op overfitting of selectieproblemen. Bewaar de beste validatie-epoch en voer de eindtest eenmaal uit. Bij gelijkwaardige prestaties kan het kleinere fysische of lineaire model beter uitlegbaar en goedkoper zijn.
Convolutionele netwerken delen een lokaal filter
Een dense laag verbindt ieder inputelement met ieder outputelement. Een convolutionele laag schuift hetzelfde kleine filter over lokale beeldvakken. Daardoor leert één gewichtenreeks een patroon op meerdere posities, bijvoorbeeld een rand. Meerdere filters leveren meerdere featurekaarten; volgende lagen combineren lokale patronen.
De gebruikelijke implementatie voert kruiscorrelatie uit: het kernelvak wordt niet omgedraaid zoals bij de wiskundige convolutie. Stride bepaalt de stap, padding de behandeling van randen. Pooling vat regio's samen en kan gevoeligheid voor exacte positie verlagen, maar verliest informatie. Gewichtsdeling geeft geen automatische robuustheid tegen belichting, sensorverschuiving of nieuwe cultivars.
Een beeldfilter zonder bibliotheekmysterie
Een 4×4-modelbeeld heeft twee donkere en twee lichte kolommen. Een 3×3-kernel detecteert de verticale overgang. Stride 1 en geen padding geven 2×2-uitvoer. De code toont kruiscorrelatie, ReLU, maxpool en de parameterbesparing tegen een dense laag met dezelfde vier uitvoerplaatsen.
import numpy as npbeeld=np.tile([0.,0.,1.,1.],(4,1))kernel=np.tile([-1.,0.,1.],(3,1))uit=np.empty((2,2))for i in range(2): for j in range(2): uit[i,j]=np.sum(beeld[i:i+3,j:j+3]*kernel)relu=np.maximum(0,uit)print("kruiscorrelatie",uit)print("ReLU",relu,"2x2 maxpool",relu.max())print("parameters conv",kernel.size+1,"densezelfdeoutput",16*4+4)kruiscorrelatie [[3. 3.] [3. 3.]] ReLU [[3. 3.] [3. 3.]] 2x2 maxpool 3.0 parameters conv 10 densezelfdeoutput 68
Parameters en uitvoermaat van een CNN
- één bias per filter
- parameter- en activatieaantal
- 1Per filter zijn 3×3×3=27 gewichten en één bias. Acht filters geven (27+1)×8=224 parameters.
- 2Ruimtelijke maat: (32+2−3)/1+1=32. Uitvoer 32×32×8 heeft 8192 activaties.
- 3Parameters worden over alle locaties gedeeld; activaties zijn sample-afhankelijke tussenwaarden. Die twee aantallen zijn dus niet hetzelfde geheugenbegrip.
Backpropagation werd een praktische leerroute
Rumelhart, Hinton en Williams beschreven in 1986 het leren van interne representaties door fouten terug te propageren. Het belang voor deze les is dat verborgen features niet allemaal met de hand gekozen hoeven te worden. De kettingregel verdeelt de uiteindelijke fout over eerdere gewichten.
Convolutionele netwerken werden onder meer concreet toegepast op documentherkenning door LeCun, Bottou, Bengio en Haffner. Primaire bronnen: Learning representations by back-propagating errors (1986) en Gradient Based Learning Applied to Document Recognition (1998), geraadpleegd 30-09-2026. Historisch succes op cijfers bewijst geen betrouwbaarheid op plantbeelden of stationweer; daarvoor zijn eigen data en toetsen nodig.
Rekenpad en toetsing
| symbool | betekenis | eenheid |
|---|---|---|
| verborgen activaties | — | |
| uitvoerfout met verliesafgeleide | — |
| controle | doel |
|---|---|
| batchvormen | broadcastfouten voorkomen |
| numerieke gradiënt | kettingregel controleren |
| validatiecurve | epoch en complexiteit kiezen |
| basislijn | meerwaarde aantonen |
| domein | invoer buiten training herkennen |
Een zonnevoorspeller houdt fysische grenzen
Een netwerk kan een niet-lineaire relatie leren, maar kent de systeemgrens alleen als data en contract haar vastleggen. Een vermogensschatting wordt pas opbrengst na integratie met correcte tijdstappen.
Afgeleiden en gradiënt.
Vermogen naar energie.
Basislijn en gescheiden toetsing.
Bevoegdheid en bewijs.
Modelmanifest en acceptatie.
Habitat houdt beschikbaar PV-vermogen apart van afgeknepen werkelijk geleverd vermogen. De voorbeeld-COP noch het netwerk verandert PV-dimensionering. Dag-vooruitgebruik vraagt een aparte proef met gearchiveerde weerprognoses en een begrensde planner.
In het kort
- Niet-lineariteit maakt meerdere lagen expressiever dan één affine functie.
- Batchvormen en activaties bepalen het forwardpad.
- Backpropagation rekent de kettingregel naar alle parameters.
- Gradiëntcontrole toetst algebra; een onafhankelijke test toetst generalisatie.
- Convolutie deelt filters over plaatsen en vraagt eigen domeinvalidatie.
Wat je nu kent
- neuron
- Een gewogen som met bias en gekozen activatiefunctie.
- epoch
- Eén verwerking van het afgesproken trainingsbestand.
- backpropagation
- Efficiënte toepassing van de kettingregel van verlies terug naar parameters.
- gewichtsdeling
- Dezelfde leerbare parameters op meerdere posities gebruiken.
- leersnelheid
- De schaal van een parameterupdate volgens de gradiënt.