feat(SNNBot): force learning on input change for fast re-acquisition
When enemy starts moving after stationary phase, the dead zone keeps error low and skips learning. Now learn when input pattern changes significantly (Hamming distance > 2 bits), forcing immediate re-adaptation regardless of error magnitude. Balances stability vs. responsiveness. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -214,6 +214,7 @@ type
|
||||
velSpeed: float64 # speed (units/tick) from last scan delta
|
||||
lastDecideGunDir: float # gun heading captured at DECIDE time for EVALUATE
|
||||
lastBinInput: BitVec80 # DECIDE-time binary input, reused in EVALUATE
|
||||
lastInput: BitVec80 # previous EVALUATE-time input (for change detection)
|
||||
|
||||
# ── aimTo helper ──────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -410,10 +411,14 @@ method run*(bot: SNNBot) =
|
||||
|
||||
when USE_RESERVOIR:
|
||||
let aimRaw = bot.res.forward(bot.lastBinInput)
|
||||
# Only learn if aim error exceeds adaptive dead zone
|
||||
# Detect significant input change via Hamming distance
|
||||
let hammingDist = popcount(bot.lastBinInput[0] xor bot.lastInput[0]) + popcount(bot.lastBinInput[1] xor bot.lastInput[1])
|
||||
let inputChanged = hammingDist > 2 # 3+ bits flipped = situation changed
|
||||
|
||||
# Learn if: error > dead zone OR input pattern changed significantly
|
||||
if aimRaw >= 0.0:
|
||||
let aimErr = abs(normalizeRelativeAngle(aimRaw - correctAngle))
|
||||
if aimErr > adaptiveDeadZone:
|
||||
if aimErr > adaptiveDeadZone or inputChanged:
|
||||
bot.res.learn(bot.lastBinInput, correctAngle)
|
||||
else:
|
||||
# Cold start: always learn
|
||||
@@ -423,6 +428,8 @@ method run*(bot: SNNBot) =
|
||||
" aim=" & (if aimRaw >= 0.0: formatFloat(aimRaw, ffDecimal, 1) else: "cold") &
|
||||
" correct=" & formatFloat(correctAngle, ffDecimal, 1) &
|
||||
" err=" & (if aimRaw >= 0.0: formatFloat(aimErr, ffDecimal, 1) else: "n/a") &
|
||||
" hammingDist=" & $hammingDist &
|
||||
" inputChanged=" & $inputChanged &
|
||||
" exemplars=" & $bot.res.count
|
||||
else:
|
||||
let targetRel = normalizeRelativeAngle(correctAngle - bot.lastDecideGunDir)
|
||||
@@ -445,6 +452,9 @@ method run*(bot: SNNBot) =
|
||||
meanWout += abs(w)
|
||||
meanWout /= float(2 * N_HID)
|
||||
echo "tick=" & $bot.tick & " err=" & formatFloat(err, ffDecimal, 1) & "° infer_spk=" & $spikeCount & "/" & $(N_INFER * N_HID) & " maxV=" & formatFloat(maxV, ffDecimal, 3) & " |wih|=" & formatFloat(meanWih, ffDecimal, 4) & " |wOut|=" & formatFloat(meanWout, ffDecimal, 4) & " sin=" & formatFloat(bot.snn.lastSinOut, ffDecimal, 3) & " cos=" & formatFloat(bot.snn.lastCosOut, ffDecimal, 3) & " snnAngle=" & formatFloat(bot.snn.lastSnnAngle, ffDecimal, 1)
|
||||
|
||||
# Update lastInput for next EVALUATE cycle's change detection
|
||||
bot.lastInput = bot.lastBinInput
|
||||
bot.phase = DECIDE
|
||||
|
||||
# Radar lock
|
||||
|
||||
Reference in New Issue
Block a user