シナプスのシミュレーション
ヒトの脳のニューロンをシミュレーションできるBrain2というライブラリを知ったので試してみる.
(私もまだ勉強中であるが)これはシナプスの可塑性の変化を示した図である.
左側がスパイク(発火)を起こすタイミング,右側がそれによってシナプスの重みが変化する様子を表している.
# Brian2でSTDPを使ったLIFネットワークのシミュレーション
!pip install brian2
from brian2 import *
# シミュレーション設定
start_scope()
prefs.codegen.target = 'numpy' # GPU使わない設定(Colabで安定)
# 定数
tau = 20*ms
Vt = -50*mV
Vr = -60*mV
El = -49*mV
# ニューロン方程式
eqs = '''
dv/dt = (El - v) / tau : volt (unless refractory)
'
# ニューロングループ(入力2個、出力1個)
G1 = NeuronGroup(2, eqs, threshold='v > Vt', reset='v = Vr', refractory=5*ms, method='exact')
G2 = NeuronGroup(1, eqs, threshold='v > Vt', reset='v = Vr', refractory=5*ms, method='exact')
G1.v = Vr
G2.v = Vr
# 外部刺激
input_times = [10, 50, 90, 130, 170, 210]*ms
indices = [0, 1, 0, 1, 0, 1] # 入力ニューロン 0と1が交互に発火
P = SpikeGeneratorGroup(2, indices, input_times)
Sinput = Synapses(P, G1, on_pre='v_post += 2*mV') # 強制発火入力
Sinput.connect(j='i')
# STDP付きのシナプス結合
model = '''
w : 1
dApre/dt = -Apre / tau : 1 (event-driven)
dApost/dt = -Apost / tau : 1 (event-driven)
'
on_pre = '''
v_post += w * mV
Apre += 0.01
w = clip(w + Apost, 0, 1)
'
on_post = '''
Apost += -0.012
w = clip(w + Apre, 0, 1)
'
S = Synapses(G1, G2, model=model, on_pre=on_pre, on_post=on_post)
S.connect()
S.w = 0.5
# モニタ
mon_v = StateMonitor(G2, 'v', record=0)
mon_w = StateMonitor(S, 'w', record=True)
spike_mon = SpikeMonitor(G2)
# 実行
run(250*ms)
# 結果表示
figure(figsize=(10,4))
subplot(121)
plot(mon_v.t/ms, mon_v.v[0]/mV)
xlabel('Time (ms)')
ylabel('Output neuron voltage (mV)')
title('Output Neuron Membrane Potential')
subplot(122)
plot(mon_w.t/ms, mon_w.w[0], label='Synapse from G1[0]')
plot(mon_w.t/ms, mon_w.w[1], label='Synapse from G1[1]')
xlabel('Time (ms)')
ylabel('Synaptic weight')
title('STDP Synaptic Weight Changes')
legend()
show()
