File size: 5,290 Bytes
e4cdd5f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | """Custom Learning Rule Benchmark
==================================
Demonstrates P19 microcode learning engine with custom learning rules.
Compares default STDP, anti-STDP, and a custom reward-modulated rule
assembled from microcode text mnemonics.
Features demonstrated: P19 microcode ISA, assembler, LearningRule, custom rules.
"""
import sys, os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
import neurocore as nc
from neurocore.microcode import LearningRule
def build_network():
"""Create a simple pre->post network for learning experiments."""
net = nc.Network()
pre = net.population(1, params={"threshold": 100, "leak": 0, "refrac": 0}, label="pre")
post = net.population(1, params={"threshold": 100, "leak": 0, "refrac": 0}, label="post")
net.connect(pre, post, topology="all_to_all", weight=500)
return net, pre, post
def get_final_weight(sim):
"""Extract the weight from the simulator's adjacency table."""
for targets in sim._adjacency.values():
for entry in targets:
return entry[1]
return None
def run_stdp(rule, rule_name, three_factor=False):
"""Run a learning trial with the given rule."""
net, pre, post = build_network()
net.set_learning_rule(rule)
sim = nc.Simulator()
sim.deploy(net)
sim.set_learning(learn=True, three_factor=three_factor)
# Generate pre-before-post spike pattern (normally LTP)
for _ in range(5):
sim.inject(pre, current=200)
sim.run(1) # pre spikes
sim.run(1) # post receives input, spikes -> LTP correlation
if three_factor:
sim.reward(500)
sim.run(1)
final_w = get_final_weight(sim)
print(f" {rule_name}: initial=500, final={final_w}")
return final_w
def main():
print("=" * 60)
print(" Custom Learning Rule Benchmark (P19 Microcode)")
print("=" * 60)
# 1. Default STDP (weight directly modified)
print("\n1. Default STDP (pre-before-post = LTP):")
rule_stdp = LearningRule.stdp()
w_stdp = run_stdp(rule_stdp, "Default STDP")
assert w_stdp > 500, "STDP LTP should increase weight"
# 2. Anti-STDP (inverted: pre-before-post = LTD)
print("\n2. Anti-STDP (inverted correlation):")
rule_anti = LearningRule()
rule_anti.assemble_ltd("""
SHR R5, R0, 3 ; delta = trace >> 3
SKIP_Z R5 ; skip if zero
ADD R2, R2, R5 ; weight += delta (anti-LTD = potentiate)
STORE_W R2
HALT
""")
rule_anti.assemble_ltp("""
SHR R5, R0, 3 ; delta = trace >> 3
SKIP_Z R5 ; skip if zero
SUB R2, R2, R5 ; weight -= delta (anti-LTP = depress)
STORE_W R2
HALT
""")
w_anti = run_stdp(rule_anti, "Anti-STDP")
assert w_anti < 500, "Anti-STDP should decrease weight for pre-before-post"
# 3. Scaled STDP (2x learning rate via SHL)
print("\n3. Scaled STDP (2x learning rate):")
rule_fast = LearningRule()
rule_fast.assemble_ltd("""
SHR R5, R0, 3 ; delta = trace >> 3
SHL R5, R5, 1 ; delta *= 2 (double rate)
SKIP_Z R5
SUB R2, R2, R5
STORE_W R2
HALT
""")
rule_fast.assemble_ltp("""
SHR R5, R0, 3 ; delta = trace >> 3
SHL R5, R5, 1 ; delta *= 2
SKIP_Z R5
ADD R2, R2, R5
STORE_W R2
HALT
""")
w_fast = run_stdp(rule_fast, "2x STDP")
assert w_fast > w_stdp, f"2x STDP ({w_fast}) should be > default ({w_stdp})"
# 4. 3-factor eligibility learning (default program)
print("\n4. 3-factor eligibility + reward:")
rule_3f = LearningRule.three_factor()
w_3f = run_stdp(rule_3f, "3-factor STDP", three_factor=True)
print(f" (Reward applied: weight change reflects eligibility * reward)")
# 5. Custom capped rule (weight bounded to [400, 600])
print("\n5. Capped STDP (weight bounded [400, 600]):")
rule_capped = LearningRule()
rule_capped.assemble_ltp("""
SHR R5, R0, 3 ; delta = trace >> 3
SKIP_Z R5
ADD R2, R2, R5 ; weight += delta
LOADI R4, 600 ; max weight
MIN R2, R2, R4 ; clamp to max
STORE_W R2
HALT
""")
rule_capped.assemble_ltd("""
SHR R5, R0, 3
SKIP_Z R5
SUB R2, R2, R5 ; weight -= delta
LOADI R4, 400 ; min weight
MAX R2, R2, R4 ; clamp to min
STORE_W R2
HALT
""")
w_capped = run_stdp(rule_capped, "Capped STDP")
assert 400 <= w_capped <= 600, f"Capped weight should be in [400,600], got {w_capped}"
# Summary
print("\n--- Summary ---")
print(f"Default STDP: {w_stdp:>6d} (LTP: weight increased)")
print(f"Anti-STDP: {w_anti:>6d} (inverted: weight decreased)")
print(f"2x STDP: {w_fast:>6d} (double learning rate)")
print(f"3-Factor: {w_3f:>6d} (eligibility + reward)")
print(f"Capped [400,600]: {w_capped:>4d} (bounded)")
print("\nAll custom learning rules verified!")
print("Done!")
if __name__ == "__main__":
main()
|