Created
June 25, 2026 10:09
-
-
Save CosmosKey/e9acfbe80c43ca5dbbdc2f2b35fab955 to your computer and use it in GitHub Desktop.
Neuralt Nätverk (MLP) i PowerShell
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # ============================================================= | |
| # Ett enkelt feedforward neuralt nätverk (MLP - Multilayer Perceptron) | |
| # med ett dolt lager, tränat med backpropagation. | |
| # | |
| # Nätverksarkitektur: | |
| # | |
| # [Indatalager] [Dolt lager] [Utdatalager] | |
| # 4 neuroner --> 4 neuroner --> 1 neuron | |
| # (x) (a1) (a2) | |
| # | |
| # Varje neuron i det dolda lagret tar emot alla 4 inputvärden, | |
| # viktar dem, adderar en bias och aktiveras med sigmoid. | |
| # Utdata-neuronen gör samma sak mot det dolda lagrets output. | |
| # | |
| # Funktioner: | |
| # Get-RandomDouble - Slumpar ett tal mellan -scale och +scale | |
| # Get-Sigmoid - Aktiveringsfunktion sigmoid: f(x) = 1 / (1 + e^-x) | |
| # Get-SigmoidDerivative - Derivatan av sigmoid, används i backpropagation | |
| # Invoke-ForwardPass - Kör ett prov framåt genom nätverket | |
| # Invoke-NeuralNetworkTraining - Tränar nätverket och returnerar en modell | |
| # Invoke-NeuralNetworkPrediction - Kör prediktion med en tränad modell | |
| # ============================================================= | |
| # ------------------------------------------------------------- | |
| # Get-RandomDouble | |
| # | |
| # Genererar slumptal mellan -$scale och +$scale | |
| # Används för att slumpa vikter och bias innan träning. | |
| # | |
| # Varför slumpa vikter? | |
| # Om alla vikter startar på samma värde (t.ex. 0) lär sig alla | |
| # neuroner exakt samma sak och nätverket fungerar inte. | |
| # Slumpning bryter denna symmetri. | |
| # | |
| # Varför litet scale (0.5)? | |
| # Stora startvikter kan ge ett mycket högt eller lågt z-värde | |
| # som skickas in i sigmoid, vilket hamnar vid platåerna nära 0 och 1. | |
| # Då blir gradienten nära 0 och inlärningen går extremt långsamt - "vanishing gradient". | |
| # ------------------------------------------------------------- | |
| $rand = [System.Random]::new() | |
| function Get-RandomDouble { | |
| param( | |
| [double]$Scale = 0.5 | |
| ) | |
| return ($rand.NextDouble() * 2 - 1) * $Scale | |
| } | |
| # ------------------------------------------------------------- | |
| # Get-Sigmoid | |
| # | |
| # Sigmoidfunktionen: f(x) = 1 / (1 + e^-x) | |
| # | |
| # Varför sigmoid? | |
| # Den "krossar" vilket reellt tal som helst till intervallet (0, 1). | |
| # Det gör den perfekt för binär klassificering - outputen kan | |
| # tolkas som en sannolikhet: "hur sannolikt är det att detta är klass 1?" | |
| # | |
| # Visualisering: | |
| # x = -10 --> f(x) ≈ 0.00005 (säkert klass 0) | |
| # x = 0 --> f(x) = 0.5 (osäker) | |
| # x = +10 --> f(x) ≈ 0.99995 (säkert klass 1) | |
| # ------------------------------------------------------------- | |
| function Get-Sigmoid { | |
| param( | |
| [double]$Num | |
| ) | |
| return 1 / (1 + [math]::Exp(-$Num)) | |
| } | |
| # ------------------------------------------------------------- | |
| # Get-SigmoidDerivative | |
| # | |
| # Derivatan av sigmoid: f'(x) = sigmoid(x) * (1 - sigmoid(x)) | |
| # | |
| # OBS: Tar redan beräknad sigmoid som inparameter (inte rå x). | |
| # Det sparar beräkningar - vi har redan sigmoid-värdet från | |
| # framåtpasset och behöver inte räkna om det. | |
| # | |
| # Varför behövs derivatan? | |
| # Under backpropagation behöver vi veta hur känslig förlusten | |
| # är för förändringar i vikterna. Derivatan berättar hur brant | |
| # sigmoid-kurvan lutar vid ett visst värde - det är lutningen | |
| # vi följer när vi justerar vikterna. | |
| # | |
| # Derivatan är störst (≈ 0.25) när sigmoid = 0.5 (osäker prediktion) | |
| # och nära 0 när sigmoid är nära 0 eller 1 (säker prediktion). | |
| # Det innebär att nätverket lär sig snabbast när det är osäkert. | |
| # ------------------------------------------------------------- | |
| function Get-SigmoidDerivative { | |
| param( | |
| [double]$Sigmoid | |
| ) | |
| return $Sigmoid * (1 - $Sigmoid) | |
| } | |
| # ------------------------------------------------------------- | |
| # Invoke-ForwardPass | |
| # | |
| # Kör ett dataprov framåt genom hela nätverket och returnerar | |
| # aktiveringarna från det dolda lagret (a1) och utdataneuronen (a2). | |
| # | |
| # Steg 1 - Dolt lager (z1 och a1): | |
| # För varje dold neuron i (0..3): | |
| # z1[i] = W1[i][0]*x[0] + W1[i][1]*x[1] + W1[i][2]*x[2] + W1[i][3]*x[3] + b1[i] | |
| # a1[i] = sigmoid(z1[i]) | |
| # | |
| # z1 kallas "pre-activation" - den viktade summan innan sigmoid. | |
| # a1 kallas "activation" - värdet efter sigmoid. | |
| # | |
| # Steg 2 - Utdatalager (z2 och a2): | |
| # z2 = W2[0]*a1[0] + W2[1]*a1[1] + W2[2]*a1[2] + W2[3]*a1[3] + b2 | |
| # a2 = sigmoid(z2) | |
| # | |
| # a2 är nätverkets prediktion: ett tal mellan 0 och 1. | |
| # Tolkning: a2 >= 0.5 --> klass 1 (elakartad), annars klass 0 (godartad). | |
| # | |
| # Parametrar: | |
| # Features - array med 4 inputvärden för ett dataprov | |
| # W1 - viktmatris [4x4] mellan indata och dolt lager | |
| # b1 - biasvektor [4] för dolda lagret | |
| # W2 - viktvektorn [4] mellan dolt lager och utdata | |
| # b2 - bias [1] för utdataneuronen | |
| # | |
| # Returnerar: hashtable med a1 (array[4]) och a2 (double) | |
| # ------------------------------------------------------------- | |
| function Invoke-ForwardPass { | |
| param( | |
| [array]$Features, | |
| [double[][]]$W1, | |
| [double[]]$b1, | |
| [double[]]$W2, | |
| [double]$b2 | |
| ) | |
| # Steg 1: Beräkna pre-activation z1 för varje dold neuron | |
| $z1 = @() | |
| for ($i = 0; $i -lt 4; $i++) { | |
| $sum = 0 | |
| for ($j = 0; $j -lt 4; $j++) { | |
| # Multiplicera varje inputvärde med motsvarande vikt | |
| $sum += $W1[$i][$j] * $Features[$j] | |
| } | |
| # Addera bias för denna neuron | |
| $sum += $b1[$i] | |
| $z1 += $sum | |
| } | |
| # Steg 2: Aktivera det dolda lagret med sigmoid | |
| $a1 = @() | |
| foreach ($z in $z1) { | |
| $a1 += Get-Sigmoid $z | |
| } | |
| # Steg 3: Beräkna pre-activation z2 för utdataneuronen | |
| $z2 = $b2 | |
| for ($i = 0; $i -lt 4; $i++) { | |
| $z2 += $W2[$i] * $a1[$i] | |
| } | |
| # Steg 4: Aktivera utdataneuronen med sigmoid --> nätverkets prediktion | |
| $a2 = Get-Sigmoid $z2 | |
| return @{ a1 = $a1; a2 = $a2 } | |
| } | |
| # ------------------------------------------------------------- | |
| # Invoke-NeuralNetworkTraining | |
| # | |
| # Tränar nätverket på ett dataset med backpropagation och | |
| # stochastic gradient descent (SGD). | |
| # | |
| # Flöde: | |
| # 1. Initialisera vikter (slump eller fasta) | |
| # 2. Dela dataset 80% träning / 20% test | |
| # 3. Träningsloop: för varje epoch och varje träningsprov: | |
| # a. Framåtpass - beräkna prediktion | |
| # b. Beräkna fel - jämför prediktion med facit | |
| # c. Backprop - propagera felet bakåt och beräkna gradienter | |
| # d. Uppdatera - justera vikter och bias | |
| # 4. Utvärdera på testset | |
| # 5. Returnera modellobjekt med vikter och metadata | |
| # | |
| # Parametrar: | |
| # Dataset - array av hashtables med nycklarna Features och Label | |
| # LearningRate - hur stora steg vi tar när vi uppdaterar vikterna (default 0.1) | |
| # Högt värde = snabb men instabil inlärning | |
| # Lågt värde = långsam men stabil inlärning | |
| # Epochs - antal gånger hela träningssetet körs igenom (default 50) | |
| # W1, b1, W2, b2 - valfria fasta startvikter för reproducerbarhet | |
| # | |
| # Returnerar: ett modellobjekt (hashtable) med: | |
| # Id, StartTime, EndTime, DurationSeconds, | |
| # Epochs, LearningRate, UseStaticWeights, | |
| # TrainingSamples, TestSamples, Accuracy, | |
| # W1, b1, W2, b2 | |
| # ------------------------------------------------------------- | |
| function Invoke-NeuralNetworkTraining { | |
| param( | |
| [Parameter(Mandatory)] | |
| [array]$Dataset, | |
| # Learning rate styr stegstorleken vid viktuppdatering. | |
| # För högt --> vikterna "hoppar förbi" optimum och oscillerar. | |
| # För lågt --> träningen tar väldigt lång tid. | |
| [double]$LearningRate = 0.1, | |
| # Antal epoker - hur många gånger hela träningssetet körs igenom. | |
| # Fler epoker ger generellt bättre resultat men tar längre tid. | |
| # Risk för "overfitting" om man kör för många epoker på litet dataset. | |
| [int]$Epochs = 50, | |
| # Valfria fasta startvikter. Utelämnas dessa slumpas vikterna. | |
| # Fasta vikter är bra för att reproducera exakt samma träningskörning. | |
| [double[][]]$W1 = $null, | |
| [double[]]$b1 = $null, | |
| [double[]]$W2 = $null, | |
| [double]$b2 = [double]::NaN | |
| ) | |
| # Starta tidmätning och skapa ett unikt ID för denna träningskörning | |
| $startTime = Get-Date | |
| $modelId = [System.Guid]::NewGuid().ToString() | |
| # Avgör om fasta vikter ska användas - alla fyra måste anges | |
| $useStatic = ($null -ne $W1 -and $null -ne $b1 -and $null -ne $W2 -and -not [double]::IsNaN($b2)) | |
| if (-not $useStatic) { | |
| Write-Host "Inga fasta vikter angivna - initialiserar med slumpade värden." | |
| # W1: viktmatris [4x4] - en rad per dold neuron, en kolumn per inputneuron | |
| # Varje W1[i][j] representerar vikten från input j till dold neuron i | |
| $W1 = @(for ($i = 0; $i -lt 4; $i++) { | |
| ,@(for ($j = 0; $j -lt 4; $j++) { Get-RandomDouble }) | |
| }) | |
| # b1: biasvektor [4] - en bias per dold neuron | |
| # Bias låter neuronen aktiveras även när alla inputs är 0 | |
| $b1 = @(for ($i = 0; $i -lt 4; $i++) { Get-RandomDouble }) | |
| # W2: viktvektorn [4] - en vikt per dold neuron mot utdataneuronen | |
| $W2 = @(for ($i = 0; $i -lt 4; $i++) { Get-RandomDouble }) | |
| # b2: bias för utdataneuronen | |
| $b2 = Get-RandomDouble | |
| } | |
| else { | |
| Write-Host "Använder fasta startvikter och bias." | |
| } | |
| # --- Dela upp dataset i tränings- och testset (80/20) --- | |
| # Slumpa ordningen för att undvika att nätverket lär sig ordningen på datan | |
| $shuffled = $Dataset | Get-Random -Count $Dataset.Count | |
| $trainSize = [math]::Floor(0.8 * $shuffled.Count) | |
| $trainingSet = $shuffled[0..($trainSize - 1)] | |
| $testSet = $shuffled[$trainSize..($shuffled.Count - 1)] | |
| Write-Host "Dataset: $($Dataset.Count) prover | Träning: $($trainingSet.Count) | Test: $($testSet.Count)" | |
| Write-Host | |
| # ============================================================= | |
| # TRÄNINGSLOOP | |
| # | |
| # SGD (Stochastic Gradient Descent): vikterna uppdateras efter | |
| # varje enskilt träningsprov, inte efter hela epoket. | |
| # Det ger snabbare (men mer "brusig") konvergens jämfört med | |
| # batch gradient descent där man väntar på hela datasetet. | |
| # ============================================================= | |
| for ($epoch = 1; $epoch -le $Epochs; $epoch++) { | |
| foreach ($data in $trainingSet) { | |
| # --------------------------------------------------------- | |
| # STEG 1: FRAMÅTPASS | |
| # Skicka provet framåt genom nätverket och få en prediktion. | |
| # --------------------------------------------------------- | |
| $pass = Invoke-ForwardPass $data.Features $W1 $b1 $W2 $b2 | |
| $a1 = $pass.a1 # Aktiveringar i dolda lagret [array av 4 värden] | |
| $a2 = $pass.a2 # Nätverkets prediktion [0..1] | |
| # --------------------------------------------------------- | |
| # STEG 2: BERÄKNA FEL | |
| # Hur mycket och åt vilket håll hade prediktionen fel? | |
| # predictionError > 0 --> vi predikterade för lågt (borde vara högre) | |
| # predictionError < 0 --> vi predikterade för högt (borde vara lägre) | |
| # --------------------------------------------------------- | |
| $predictionError = $data.Label - $a2 | |
| # --------------------------------------------------------- | |
| # STEG 3: BACKPROPAGATION - UTDATALAGRET | |
| # | |
| # delta2 är gradienten för utdataneuronen. | |
| # Den berättar hur mycket utdataneuronens viktade summa (z2) | |
| # behöver förändras för att minska felet. | |
| # | |
| # delta2 = predictionError * sigmoid'(a2) | |
| # | |
| # Vi multiplicerar med sigmoid-derivatan för att ta hänsyn | |
| # till hur "responsiv" aktiveringssfunktionen är just nu. | |
| # Om a2 är nära 0 eller 1 är sigmoid-kurvan flack (derivatan ≈ 0) | |
| # och vi ändrar vikterna lite. Om a2 ≈ 0.5 är kurvan brant | |
| # och vi ändrar mer. | |
| # --------------------------------------------------------- | |
| $delta2 = $predictionError * (Get-SigmoidDerivative $a2) | |
| # --------------------------------------------------------- | |
| # STEG 4: BACKPROPAGATION - DOLDA LAGRET | |
| # | |
| # delta1[i] är gradienten för dold neuron i. | |
| # Felet "propageras bakåt" från utdataneuronen till varje | |
| # dold neuron, viktat med den vikt som kopplar dem (W2[i]). | |
| # | |
| # delta1[i] = delta2 * W2[i] * sigmoid'(a1[i]) | |
| # | |
| # Intuitionen: om W2[i] är stor betyder det att dold neuron i | |
| # hade stort inflytande på prediktionen och bär därmed mer | |
| # "ansvar" för felet - den får en större gradient. | |
| # --------------------------------------------------------- | |
| $delta1 = @(0, 0, 0, 0) | |
| for ($i = 0; $i -lt 4; $i++) { | |
| $delta1[$i] = $delta2 * $W2[$i] * (Get-SigmoidDerivative $a1[$i]) | |
| } | |
| # --------------------------------------------------------- | |
| # STEG 5: UPPDATERA VIKTER OCH BIAS - UTDATALAGRET | |
| # | |
| # W2[i] += LearningRate * delta2 * a1[i] | |
| # | |
| # Intuitionen: om a1[i] (aktiveringen från dold neuron i) var | |
| # stor och vi hade fel åt ett håll, ska vi justera W2[i] mer. | |
| # LearningRate styr hur stort steg vi tar i den riktningen. | |
| # | |
| # b2 += LearningRate * delta2 | |
| # Bias uppdateras utan att multipliceras med någon aktivering | |
| # eftersom den inte är kopplad till något inkommande värde. | |
| # --------------------------------------------------------- | |
| for ($i = 0; $i -lt 4; $i++) { | |
| $W2[$i] += $LearningRate * $delta2 * $a1[$i] | |
| } | |
| $b2 += $LearningRate * $delta2 | |
| # --------------------------------------------------------- | |
| # STEG 6: UPPDATERA VIKTER OCH BIAS - DOLDA LAGRET | |
| # | |
| # W1[i][j] += LearningRate * delta1[i] * Features[j] | |
| # | |
| # Samma logik som för utdatalagret men nu ett lager bakåt. | |
| # delta1[i] är gradienten för dold neuron i. | |
| # Features[j] är inputvärdet från indata-neuron j. | |
| # En stor input Features[j] betyder att vikten W1[i][j] | |
| # hade stort inflytande - den justeras mer. | |
| # --------------------------------------------------------- | |
| for ($i = 0; $i -lt 4; $i++) { | |
| for ($j = 0; $j -lt 4; $j++) { | |
| $W1[$i][$j] += $LearningRate * $delta1[$i] * $data.Features[$j] | |
| } | |
| $b1[$i] += $LearningRate * $delta1[$i] | |
| } | |
| } | |
| # Beräkna och visa genomsnittlig förlust var 10:e epoch | |
| # Förlusten (MSE - Mean Squared Error) mäter hur långt ifrån | |
| # facit nätverkets prediktioner är i snitt. | |
| # MSE = (1/n) * sum((y - a2)^2) | |
| # En sjunkande förlust indikerar att nätverket lär sig. | |
| if ($epoch % 10 -eq 0) { | |
| $loss = 0 | |
| foreach ($data in $trainingSet) { | |
| $a2 = (Invoke-ForwardPass $data.Features $W1 $b1 $W2 $b2).a2 | |
| $loss += [math]::Pow(($data.Label - $a2), 2) | |
| } | |
| $avgLoss = $loss / $trainingSet.Count | |
| Write-Host "Epoch $epoch / $Epochs - Loss (MSE): $([math]::Round($avgLoss, 4))" | |
| } | |
| } | |
| # --- Utvärdering på testset --- | |
| # Testdatan har nätverket INTE sett under träningen. | |
| # Det ger en rättvisare bild av hur bra modellen generaliserar. | |
| $correct = 0 | |
| Write-Host | |
| Write-Host "Prediktioner på testset:" | |
| foreach ($data in $testSet) { | |
| $a2 = (Invoke-ForwardPass $data.Features $W1 $b1 $W2 $b2).a2 | |
| # Klassificeringströskel = 0.5 | |
| # a2 >= 0.5 --> prediktion 1 (elakartad) | |
| # a2 < 0.5 --> prediktion 0 (godartad) | |
| $prediction = [int]($a2 -ge 0.5) | |
| if ($prediction -eq $data.Label) { $correct++ } | |
| Write-Host " Predicted: $prediction | Actual: $($data.Label) | Raw output: $([math]::Round($a2, 4))" | |
| } | |
| $accuracy = ($correct / $testSet.Count) * 100 | |
| $endTime = Get-Date | |
| Write-Host | |
| Write-Host "Accuracy: $([math]::Round($accuracy, 2))%" | |
| Write-Host "Träningstid: $([math]::Round(($endTime - $startTime).TotalSeconds, 2))s" | |
| # --- Returnera modellobjekt --- | |
| # Modellobjektet innehåller allt som behövs för att: | |
| # 1. Köra prediktion med Invoke-NeuralNetworkPrediction | |
| # 2. Reproducera eller jämföra träningskörningar | |
| # 3. Spara modellen (t.ex. ConvertTo-Json | Out-File eller Export-Clixml) | |
| return @{ | |
| # Metadata | |
| Id = $modelId | |
| StartTime = $startTime | |
| EndTime = $endTime | |
| DurationSeconds = [math]::Round(($endTime - $startTime).TotalSeconds, 2) | |
| Epochs = $Epochs | |
| LearningRate = $LearningRate | |
| UseStaticWeights = $useStatic | |
| TrainingSamples = $trainingSet.Count | |
| TestSamples = $testSet.Count | |
| Accuracy = [math]::Round($accuracy, 2) | |
| # Tränade vikter och bias - dessa är vad nätverket "lärt sig" | |
| W1 = $W1 | |
| b1 = $b1 | |
| W2 = $W2 | |
| b2 = $b2 | |
| } | |
| } | |
| # ------------------------------------------------------------- | |
| # Invoke-NeuralNetworkPrediction | |
| # | |
| # Kör prediktion på ett nytt dataset med en redan tränad modell. | |
| # Ingen träning sker här - vikterna är låsta. | |
| # | |
| # Det här är den funktion man använder i "produktion" - man har | |
| # redan tränat modellen en gång och vill nu klassificera nya prov. | |
| # | |
| # Parametrar: | |
| # Dataset - array av hashtables med nyckeln Features (och valfritt Label) | |
| # Om Label finns jämförs prediktionen och accuracy beräknas. | |
| # Model - modellobjektet returnerat av Invoke-NeuralNetworkTraining | |
| # | |
| # Returnerar: array av hashtables med: | |
| # Features, RawOutput, Prediction, och Label/Correct om Label gavs | |
| # ------------------------------------------------------------- | |
| function Invoke-NeuralNetworkPrediction { | |
| param( | |
| [Parameter(Mandatory)] | |
| [array]$Dataset, | |
| [Parameter(Mandatory)] | |
| [hashtable]$Model | |
| ) | |
| # Plocka ut vikter och bias från modellobjektet | |
| $W1 = $Model.W1 | |
| $b1 = $Model.b1 | |
| $W2 = $Model.W2 | |
| $b2 = $Model.b2 | |
| $hasLabels = $Dataset[0].ContainsKey('Label') | |
| $correct = 0 | |
| $results = @() | |
| Write-Host "Kör prediktion med modell: $($Model.Id)" | |
| Write-Host "Tränad med LearningRate=$($Model.LearningRate), Epochs=$($Model.Epochs), Accuracy=$($Model.Accuracy)%" | |
| Write-Host | |
| foreach ($data in $Dataset) { | |
| # Kör framåtpasset - exakt samma beräkning som under träning | |
| # men vi uppdaterar inga vikter efteråt | |
| $a2 = (Invoke-ForwardPass $data.Features $W1 $b1 $W2 $b2).a2 | |
| # Klassificera baserat på tröskel 0.5 | |
| $prediction = [int]($a2 -ge 0.5) | |
| $result = @{ | |
| Features = $data.Features | |
| RawOutput = [math]::Round($a2, 4) | |
| Prediction = $prediction | |
| } | |
| if ($hasLabels) { | |
| $result.Label = $data.Label | |
| $result.Correct = ($prediction -eq $data.Label) | |
| if ($result.Correct) { $correct++ } | |
| Write-Host " Features: $($data.Features) | Predicted: $prediction | Actual: $($data.Label) | Raw: $([math]::Round($a2, 4)) | $( if($result.Correct) {'OK'} else {'FEL'} )" | |
| } | |
| else { | |
| Write-Host " Features: $($data.Features) | Predicted: $prediction | Raw: $([math]::Round($a2, 4))" | |
| } | |
| $results += $result | |
| } | |
| if ($hasLabels) { | |
| $accuracy = ($correct / $Dataset.Count) * 100 | |
| Write-Host | |
| Write-Host "Accuracy: $([math]::Round($accuracy, 2))% ($correct / $($Dataset.Count) rätt)" | |
| } | |
| return $results | |
| } | |
| # ============================================================= | |
| # EXEMPELKÖRNING | |
| # ============================================================= | |
| $dataset = @( | |
| @{Features = @(5, 1, 1, 1); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(6, 4, 4, 5); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 2, 2, 2); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(7, 4, 4, 6); Label = 1}, | |
| @{Features = @(2, 1, 1, 1); Label = 0}, | |
| @{Features = @(4, 3, 3, 3); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 2, 2, 2); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(6, 4, 4, 5); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 2, 2, 2); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(7, 4, 4, 6); Label = 1}, | |
| @{Features = @(2, 1, 1, 1); Label = 0}, | |
| @{Features = @(4, 3, 3, 3); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 1, 1, 2); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(6, 5, 4, 5); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 2, 2, 2); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(7, 4, 4, 6); Label = 1}, | |
| @{Features = @(2, 1, 1, 1); Label = 0}, | |
| @{Features = @(4, 3, 3, 3); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 1, 1, 1); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(6, 4, 4, 5); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 2, 2, 2); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(7, 4, 4, 6); Label = 1}, | |
| @{Features = @(2, 1, 1, 1); Label = 0}, | |
| @{Features = @(4, 3, 3, 3); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 2, 2, 2); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(6, 4, 4, 5); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 2, 2, 2); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(7, 4, 4, 6); Label = 1}, | |
| @{Features = @(2, 1, 1, 1); Label = 0}, | |
| @{Features = @(4, 3, 3, 3); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 1, 1, 1); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(6, 4, 4, 5); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 2, 2, 2); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(7, 4, 4, 6); Label = 1}, | |
| @{Features = @(2, 1, 1, 1); Label = 0}, | |
| @{Features = @(4, 3, 3, 3); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 1, 1, 1); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(6, 4, 4, 5); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 2, 2, 2); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(7, 4, 4, 6); Label = 1}, | |
| @{Features = @(2, 1, 1, 1); Label = 0}, | |
| @{Features = @(4, 3, 3, 3); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 1, 1, 1); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(6, 4, 4, 5); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 2, 2, 2); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(7, 4, 4, 6); Label = 1}, | |
| @{Features = @(2, 1, 1, 1); Label = 0}, | |
| @{Features = @(4, 3, 3, 3); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 1, 1, 1); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(6, 4, 4, 5); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 2, 2, 2); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(7, 4, 4, 6); Label = 1}, | |
| @{Features = @(2, 1, 1, 1); Label = 0}, | |
| @{Features = @(4, 3, 3, 3); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 1, 1, 1); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(6, 4, 4, 5); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 2, 2, 2); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(7, 4, 4, 6); Label = 1}, | |
| @{Features = @(2, 1, 1, 1); Label = 0}, | |
| @{Features = @(4, 3, 3, 3); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 1, 1, 1); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(6, 4, 4, 5); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 2, 2, 2); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(7, 4, 4, 6); Label = 1}, | |
| @{Features = @(2, 1, 1, 1); Label = 0}, | |
| @{Features = @(4, 3, 3, 3); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 1, 1, 1); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(6, 4, 4, 5); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 2, 2, 2); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(7, 4, 4, 6); Label = 1}, | |
| @{Features = @(2, 1, 1, 1); Label = 0}, | |
| @{Features = @(4, 3, 3, 3); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 1, 1, 1); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(6, 4, 4, 5); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 2, 2, 2); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(7, 4, 4, 6); Label = 1}, | |
| @{Features = @(2, 1, 1, 1); Label = 0}, | |
| @{Features = @(4, 3, 3, 3); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 1, 1, 1); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(6, 4, 4, 5); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 2, 2, 2); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(7, 4, 4, 6); Label = 1}, | |
| @{Features = @(2, 1, 1, 1); Label = 0}, | |
| @{Features = @(4, 3, 3, 3); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 1, 1, 1); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(6, 4, 4, 5); Label = 1}, | |
| @{Features = @(4, 1, 1, 1); Label = 0}, | |
| @{Features = @(5, 2, 2, 2); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0}, | |
| @{Features = @(7, 4, 4, 6); Label = 1}, | |
| @{Features = @(2, 1, 1, 1); Label = 0}, | |
| @{Features = @(4, 3, 3, 3); Label = 1}, | |
| @{Features = @(3, 1, 1, 1); Label = 0} | |
| ) | |
| # --- Anrop 1: Träna med slumpade vikter --- | |
| Write-Host "=== TRÄNING MED SLUMPADE VIKTER ===" | |
| $model = Invoke-NeuralNetworkTraining -Dataset $dataset -LearningRate 0.1 -Epochs 50 | |
| # --- Anrop 2: Prediktion på nya okända prover (utan Label) --- | |
| Write-Host | |
| Write-Host "=== PREDIKTION PÅ NYA PROVER ===" | |
| $newSamples = @( | |
| @{Features = @(6, 3, 3, 4)}, # Okänt prov - ingen Label | |
| @{Features = @(2, 1, 1, 1)}, # Okänt prov | |
| @{Features = @(8, 5, 5, 7)} # Okänt prov | |
| ) | |
| $predictions = Invoke-NeuralNetworkPrediction -Dataset $newSamples -Model $model | |
| # --- Anrop 3: Träna med fasta vikter för reproducerbarhet --- | |
| Write-Host | |
| Write-Host "=== TRÄNING MED FASTA VIKTER ===" | |
| $fixedW1 = @( | |
| @(0.2, -0.5, 0.1, 2.0), | |
| @(1.5, 1.3, -1.2, 0.7), | |
| @(0.3, 0.8, -0.6, -0.1), | |
| @(-1.0, 2.0, 1.0, -0.5) | |
| ) | |
| $fixedB1 = @(0.5, -1.5, 2.0, 0.0) | |
| $fixedW2 = @(1.2, -0.7, 0.3, 0.8) | |
| $fixedB2 = 1.0 | |
| $modelFixed = Invoke-NeuralNetworkTraining -Dataset $dataset -LearningRate 0.1 -Epochs 50 ` | |
| -W1 $fixedW1 -b1 $fixedB1 -W2 $fixedW2 -b2 $fixedB2 | |
| # --- Visa modellmetadata --- | |
| Write-Host | |
| Write-Host "=== MODELLMETADATA ===" | |
| Write-Host "ID: $($modelFixed.Id)" | |
| Write-Host "Starttid: $($modelFixed.StartTime)" | |
| Write-Host "Sluttid: $($modelFixed.EndTime)" | |
| Write-Host "Träningstid: $($modelFixed.DurationSeconds)s" | |
| Write-Host "Epoker: $($modelFixed.Epochs)" | |
| Write-Host "Learning Rate: $($modelFixed.LearningRate)" | |
| Write-Host "Fasta vikter: $($modelFixed.UseStaticWeights)" | |
| Write-Host "Träningsprover: $($modelFixed.TrainingSamples)" | |
| Write-Host "Testprover: $($modelFixed.TestSamples)" | |
| Write-Host "Accuracy: $($modelFixed.Accuracy)%" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment