Skip to content

Instantly share code, notes, and snippets.

@CosmosKey
Created June 25, 2026 10:09
Show Gist options
  • Select an option

  • Save CosmosKey/e9acfbe80c43ca5dbbdc2f2b35fab955 to your computer and use it in GitHub Desktop.

Select an option

Save CosmosKey/e9acfbe80c43ca5dbbdc2f2b35fab955 to your computer and use it in GitHub Desktop.
Neuralt Nätverk (MLP) i PowerShell
# =============================================================
# 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