LoginSignup
0
0

More than 3 years have passed since last update.

神経細胞モデルを実装してみよう

Last updated at Posted at 2020-07-25

ここでいう神経細胞モデルとは、神経細胞の発火の時間変化を表現可能なモデリングのことを指します。このページは
[1] E.M.Izhikevich (2004) "Which Model to Use For COrtical Spiking Neurons?", IEEE transaction on neural networks,Vol.15, No.5,pp.1063-1070
[2] https://neuronaldynamics.epfl.ch/index.html
に基づきます.

以下のように文字を定めます。
$u,v,w$:微分方程式で表される変数,膜電位(参考にした文献によって微妙に文字が違います)
$I$:入力電流
$R$:抵抗値
$\tau$ :時定数

Hodgkin-Huxley model

神経細胞のモデルとして、最も精度が高くて複雑なものが、このHHモデルです。神経科学の世界では最も重要な内容の1つです。膜電位・やイオンチャンネルについての4つの微分方程式で表現されます。
式の詳細はこちらを参照。実装は長いので略。
https://bsd.neuroinf.jp/wiki/Hodgkin-Huxley%E6%96%B9%E7%A8%8B%E5%BC%8F

Fitzhugh-Nagumo Model

HHモデルは4つの微分方程式で構成されており複雑です。そこで,実際の細胞のダイナミクスに基づいて,無理のない範囲で近似することで,2変数に減らしました。その1例がFNモデルです。2変数になったことで,2次元平面での力学系として解析することが可能になりました。

\tau\frac{dv}{dt} = v-\frac{1}{3}v^3 - w + RI(t) \\
\tau_w\frac{dw}{dt} = a + bv - w 
import numpy as np
import matplotlib.pyplot as plt

def fitzhugh_nagumo(tau,tau_w,a,b,v_init,u_init,I):
    dt = 0.01
    v = np.zeros(np.size(I))
    u = np.zeros(np.size(I))
    R=1
    v[0] = v_init
    u[0] = u_init
    for i in range(np.size(I)-1):
        v[i+1] = v[i] + (v[i] - v[i]*v[i]*v[i]/3 -u[i]+R*I[i])*dt/tau
        u[i+1] = u[i] + (v[i] - b*u[i] +a)*dt/tau_w
    return v,u

v1,u1 = fitzhugh_nagumo(0.1,0.1,0.7,0.8,-5,-1,np.concatenate([np.ones(10)*2,np.zeros(490)])) #large pulse input
v2,u2 = fitzhugh_nagumo(0.1,0.2,0.7,0.8,-5,-1,np.ones(500)) #constant input

dt = 0.01
x = np.linspace(0,500,500)*dt
plt.subplot(2,1,1)
plt.plot(x,v1,label="large pulse input")
plt.plot(x,v2,label="constant input")
plt.legend()

plt.subplot(2,1,2)
plt.plot(v1,u1)
plt.plot(v2,u2)
plt.show()

上記コードは,定常入力時とパルス入力時の応答を示します。
u-v平面の図も表示でき,定常入力時はリミットサイクルが発生することがわかります。

Integrate-and-Fire model(積分発火モデル)

HNモデルよりも更に変数が減って1つしかないため,計算コストが非常に小さいというメリットがありますが,あまりちゃんとした発火パターンをモデリングすることができません。

\begin{align}
\tau \frac{dv}{dt} &= -(v-v_{rest}) + RI(t)\\
&if\quad v \geq v_{thres} \quad v=c
\end{align}
import numpy as np
import matplotlib.pyplot as plt

def IandF(tau,v_init,v_thresh,v_reset,I):
    dt = 0.001
    v = np.zeros(np.size(I))
    v[0] = v_init
    R=5
    for i in range(0,np.size(v)-1):
        v[i+1] = v[i] + ((-(v[i] -v_init) + R*I[i]) * dt)/tau
        if v[i+1]>= v_thresh:
            v[i+1] = v_reset
    return v

dt = 0.01
x = np.linspace(0,1000,1000)*dt
v = IandF(1,-70,-50,-65,np.ones(1000)*10);

plt.plot(x,v)
plt.legend()
plt.show()

Izhikevich model

比較的少ない計算量で,かつ高精度な結果を出すことができるのがこのモデルとされています。u,vに関わる2つの微分方程式で表現されます。

\begin{align}
\dot{v} &= 0.04v^2 + 5v + 140 -u + I \\
\dot{u} &= a(bv-u) \\
\\
if &\quad v \geq 30(mV) \\
 v &= c \\
 u &= u+ d \\
\end{align}
import numpy as np
import matplotlib.pyplot as plt

def izhikevich(u_init,v_init,I):
    dt = 0.01
    u = np.zeros(np.size(I))
    v = np.zeros(np.size(I))
    u[0]= u_init;
    v[0]= v_init;

    a = 0.02*10
    b = 0.2
    c = -65
    d = 2

    for i in range(0,np.size(I)-1):
        v[i+1] = v[i] + (0.04*v[i]*v[i] + 5*v[i] + 140 -u[i] +I[i])*dt*10
        u[i+1] = u[i] + a*(b*v[i]-u[i])*dt

        if v[i+1]>=30:
            v[i+1] = c
            u[i+1] = u[i+1]+d
    return u,v

u,v = izhikevich(30,-80,np.ones(1000)*10)

dt = 0.01
x = np.linspace(0,1000,1000)*dt
plt.plot(x,v)
plt.show()    
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0