在python中模拟神经元尖峰列车

时间:2016-03-17 01:32:32

标签: python numpy matplotlib scipy neural-network

我正在研究的模型有一个神经元(由霍奇金 - 赫胥黎方程建模),神经元本身接收来自其他神经元的一串突触输入,因为它在网络中。对输入进行建模的标准方法是使用尖峰序列,该峰值序列由一组以指定速率到达的delta函数脉冲组成,作为泊松过程。一些脉冲对神经元提供兴奋反应,一些提供抑制脉冲。因此突触电流应如下所示:

enter image description here

这里,Ne是兴奋性神经元的数量,Ni是抑制性的,h是0或1(1,概率为p)表示是否成功传输了尖峰,而delta是$ t_k ^ l $ function是第k个神经元第l个尖峰的放电时间(对于$ t_m ^ n $也是如此)。因此,我们尝试编码的基本思想是假设首先我有100个神经元向我的HH神经元提供脉冲(其中80个是兴奋性的,其中20个是抑制性的)。然后我们形成了一个阵列,其中一列列举了神经元(因此神经元#0-79是兴奋性的,#80-99是抑制性的)。然后我们检查是否在某个时间间隔内有一个尖峰,如果有,请选择0-1之间的随机数,如果它低于我指定的概率p,则为其分配数字1,否则将其设为0。然后将电压绘制为时间的函数,以查看神经元何时出现峰值。

我认为代码有效,但问题是,只要我在网络中添加更多神经元(一篇论文声称他们使用了5000个总神经元),就需要永远运行,这对于进行数值模拟来说是不可行的。我的问题是:有没有更好的方法来模拟尖峰列车脉冲进入神经元,以便网络中的大量神经元的计算速度更快?这是我们尝试的代码:(它有点长,因为HH方程非常详细):

import scipy as sp
import numpy as np
import pylab as plt

#Constants
C_m  =   1.0 #membrane capacitance, in uF/cm^2"""
g_Na = 120.0 #Sodium (Na) maximum conductances, in mS/cm^2""
g_K  =  36.0 #Postassium (K) maximum conductances, in mS/cm^2"""
g_L  =   0.3 #Leak maximum conductances, in mS/cm^2"""
E_Na =  50.0 #Sodium (Na) Nernst reversal potentials, in mV"""
E_K  = -77.0 #Postassium (K) Nernst reversal potentials, in mV"""
E_L  = -54.387 #Leak Nernst reversal potentials, in mV"""

def poisson_spikes(t, N=100, rate=1.0 ):
    spks = []
    dt = t[1] - t[0]
    for n in range(N):
        spkt = t[np.random.rand(len(t)) < rate*dt/1000.] #Determine list of times of spikes
        idx = [n]*len(spkt) #Create vector for neuron ID number the same length as time
        spkn = np.concatenate([[idx], [spkt]], axis=0).T #Combine tw lists
        if len(spkn)>0:        
            spks.append(spkn)
    spks = np.concatenate(spks, axis=0)
    return spks

N = 100
N_ex = 80 #(0..79)
N_in = 20 #(80..99)
G_ex = 1.0
K = 4

dt = 0.01
t = sp.arange(0.0, 300.0, dt) #The time to integrate over """
ic = [-65, 0.05, 0.6, 0.32]

spks =  poisson_spikes(t, N, rate=10.)

def alpha_m(V):
        return 0.1*(V+40.0)/(1.0 - sp.exp(-(V+40.0) / 10.0))

def beta_m(V):
        return 4.0*sp.exp(-(V+65.0) / 18.0)

def alpha_h(V):
        return 0.07*sp.exp(-(V+65.0) / 20.0)

def beta_h(V):
        return 1.0/(1.0 + sp.exp(-(V+35.0) / 10.0))

def alpha_n(V):
        return 0.01*(V+55.0)/(1.0 - sp.exp(-(V+55.0) / 10.0))

def beta_n(V):
        return 0.125*sp.exp(-(V+65) / 80.0)

def I_Na(V, m, h):
        return g_Na * m**3 * h * (V - E_Na)

def I_K(V, n):
        return g_K  * n**4 * (V - E_K)

def I_L(V):
        return g_L * (V - E_L)

def I_app(t):
        return 3

def I_syn(spks, t):
    """
    Synaptic current
    spks = [[synid, t],]
    """
    exspk = spks[spks[:,0]<N_ex] # Check for all excitatory spikes
    delta_k = exspk[:,1] == t # Delta function
    if sum(delta_k) > 0:
        h_k = np.random.rand(len(delta_k)) < 0.5 # p = 0.5
    else:
        h_k = 0

    inspk = spks[spks[:,0] >= N_ex] #Check remaining neurons for inhibitory spikes
    delta_m = inspk[:,1] == t #Delta function for inhibitory neurons
    if sum(delta_m) > 0:
        h_m = np.random.rand(len(delta_m)) < 0.5 #p =0.5
    else:
        h_m = 0

    isyn = C_m*G_ex*(np.sum(h_k*delta_k) - K*np.sum(h_m*delta_m))

    return  isyn


def dALLdt(X, t):
        V, m, h, n = X
        dVdt = (I_app(t)+I_syn(spks,t)-I_Na(V, m, h) - I_K(V, n) - I_L(V)) / C_m
        dmdt = alpha_m(V)*(1.0-m) - beta_m(V)*m
        dhdt = alpha_h(V)*(1.0-h) - beta_h(V)*h
        dndt = alpha_n(V)*(1.0-n) - beta_n(V)*n
        return np.array([dVdt, dmdt, dhdt, dndt])

X = [ic]
for i in t[1:]:
    dx = (dALLdt(X[-1],i))
    x = X[-1]+dt*dx
    X.append(x)

X = np.array(X)    
V = X[:,0]        
m = X[:,1]
h = X[:,2]
n = X[:,3]
ina = I_Na(V, m, h)
ik = I_K(V, n)
il = I_L(V)

plt.figure()
plt.subplot(3,1,1)
plt.title('Hodgkin-Huxley Neuron')
plt.plot(t, V, 'k')
plt.ylabel('V (mV)')

plt.subplot(3,1,2)
plt.plot(t, ina, 'c', label='$I_{Na}$')
plt.plot(t, ik, 'y', label='$I_{K}$')
plt.plot(t, il, 'm', label='$I_{L}$')
plt.ylabel('Current')
plt.legend()

plt.subplot(3,1,3)
plt.plot(t, m, 'r', label='m')
plt.plot(t, h, 'g', label='h')
plt.plot(t, n, 'b', label='n')
plt.ylabel('Gating Value')
plt.legend()

plt.show()

我不熟悉专门为神经网络设计的其他软件包,但我想自己编写,主要是因为我打算进行随机分析,这需要相当多的数学细节,我不知道那些包提供了这样的细节。

3 个答案:

答案 0 :(得分:1)

分析表明,大部分时间都用在这两行中:

    if sum(delta_k) > 0:

    if sum(delta_m) > 0:

将其中的每一项更改为:

    if np.any(...)

将所有内容提高10倍。如果您想要进行更多的逐行分析,请查看kernprof: https://github.com/rkern/line_profiler

答案 1 :(得分:1)

作为对welch的回答的补充,您可以使用scipy.integrate.odeint来加速集成:替换

X = [ic]
for i in t[1:]:
    dx = (dALLdt(X[-1],i))
    x = X[-1]+dt*dx
    X.append(x)

通过

from scipy.integrate import odeint
X=odeint(dALLdt,ic,t)

在我的电脑上将计算速度提高了10倍以上。

答案 2 :(得分:0)

如果您有NVidia grpahics板,则可以使用numba / numbapro来加速python代码,并达到每个具有128个突触前神经元的实时4K神经元。