原创文章,转载请注明出处:https://blog.csdn.net/weixin_37864449/article/details/126772830?spm=1001.2014.3001.5502

如上动态图所示,脉冲网络由脉冲神经元连接而成,脉冲神经元输入为脉冲,输出也是脉冲,脉冲神经元内部有电动势v,v在没有接收到任何输入时会随着时间指数衰减到某个稳定的电动势(平衡电压),而某一时刻接收到输入脉冲时电动势会增加某个值,当电动势增加的速度快过衰减的速度时(如频繁有脉冲输入),神经元内部的电动势会越来越大,直到达到某个发放阈值后该脉冲神经元会发放脉冲,此后脉冲神经元电动势迅速置为静息电动势,电动势变化过程如下图二所示。电动势变化的规律又称为神经电位动力学。

图二 神经元膜电压变化

一、脉冲神经元模型

脉冲神经元电位动力学数学模型最简单常用的是漏电积分-放电(leaky integrate-and-fire ( LIF ))模型,这个模型工作过程与生物神经元充电、漏电、放电过程类似,更精确的描述生物神经动力学模型是Hodgkin-huxley模型,但该模型微分方程复杂难以直观理解,虽然Hodgkin-huxley模型更精确描述了生物神经元电位动力学变化过程,但有观点认为该模型对数据拟合能力没有LIF模型好(https://www.youtube.com/watch?v=GTXTQ_sOxak 25:24),总而言之,LIF是基于生物神经元动力学特性简化后的数学模型,简单好用,下面详细讨论LIF模型。

我们知道,每个脉冲神经元内部有电压v,当没有接收到任何脉冲输入时,电压v会随着时间指数稳定到平衡电压,这个过程用LIF模型描述为:

求解这个微分方程,可以得到:

这里是任意常数, 控制指数下降速率, 越小 越快指数变化到,分析这个方程可以看到,初始时t=0时刻v=,其中取恰当的值就可以使等于脉冲神经元初始时刻电压,当t=∞时v=,该方程控制了电压v随时间指数稳定到平衡电压

上面是连续电压的变化方程,然而计算机只能模拟离散过程,取离散时间间隔为时,则:

故微分方程的离散形式为:

另外,当某个时刻神经元接收到一个脉冲输入时,则要累积该脉冲到电压中,最简单的方式是让当前的电压加上某个值,通常这个值跟连接该输入脉冲的突触权重有关,电压更新过程为:

神经元内部有一个发放阈值,当神经元电压v>时,神经元会发放一个脉冲,此后神经元电压会立刻置为静息电位

为更好的理解LIF模型控制的神经元膜电压变化,下面附上由for循环实现的python代码:

import numpy as np
import matplotlib.pyplot as pltfig = plt.figure(figsize=(5, 4))
ax = plt.subplot(111)# Function that runs the simulation
# tau: time constant (in ms)
# t0, t1, t2: time of three input spikes
# w: input synapse weight
# threshold: threshold value to produce a spike
# reset: reset value after a spike
def LIF(tau=10, t0=20, t1=30, t2=35, w=0.8, threshold=1.0, reset=0.0):# Spike times, keep sorted because it's more efficient to pop the last value off the listtimes = [t0, t1, t2]times.sort(reverse=True)# set some default parametersduration = 100  # total time in msdt = 0.1  # timestep in msalpha = np.exp(-dt / tau)  # this is the factor by which V decays each time stepV_rec = []  # list to record membrane potentialsV = 0.0  # initial membrane potentialT = np.arange(np.round(duration / dt)) * dt  # array of timesspikes = []  # list to store spike times# run the simulation# plot everything (T is repeated because we record V twice per loop)ax.clear()for t in times:ax.axvline(t, ls=':', c='b')for t in T:V_rec.append(V)  # recordV *= alpha  # integrate equationsif times and t > times[-1]:  # if there has been an input spikeV +=wtimes.pop()  # remove that spike from listV_rec.append(V)  # record V before the reset so we can see the spikeif V > threshold:  # if there should be an output spikeV = resetspikes.append(t)ax.plot(np.repeat(T, 2), V_rec, '-k', lw=2)for t in spikes:ax.axvline(t, ls='--', c='r')ax.axhline(threshold, ls='--', c='g')ax.set_xlim(0, duration)ax.set_ylim(-1, 2)ax.set_xlabel('Time (ms)')ax.set_ylabel('Voltage')plt.tight_layout()plt.show()LIF()

运行结果为:

绿色虚线表示发放阈值,黑色为神经元电压,蓝色虚线表示神经元接收到输入脉冲的时刻,红色虚线表示神经发放了一个脉冲。代码里设置神经元平衡电压为0,静息电位为0,发放阈值为1。

更复杂一些,我们可以让发放阈值也能发生变化,下面代码演示了当神经元发放脉冲时,发放阈值会增加某个值,且发放阈值动力学模型也是LIF模型。

import numpy as np
import matplotlib.pyplot as pltfig = plt.figure(figsize=(5, 4))
ax = plt.subplot(111)# Function that runs the simulation
# tau: time constant (in ms)
# t0, t1, t2: time of three input spikes
# w: input synapse weight
# threshold: threshold value to produce a spike
# reset: reset value after a spike
def LIF2(tau=10, taut=20, t0=20, t1=30, t2=35, w=0.8, threshold=1.0, dthreshold=0.5, reset=0.0):# Spike times, keep sorted because it's more efficient to pop the last value off the listtimes = [t0, t1, t2]times.sort(reverse=True)# set some default parametersduration = 100 # total time in msdt = 0.1 # timestep in msalpha = np.exp(-dt/tau) # this is the factor by which V decays each time stepbeta = np.exp(-dt/taut) # this is the factor by which Vt decays each time stepV_rec = [] # list to record membrane potentialsVt_rec = [] # list to record threshold valuesV = 0.0 # initial membrane potentialVt = thresholdT = np.arange(np.round(duration/dt))*dt # array of timesspikes = [] # list to store spike times# clear the axis and plot the spike timesax.clear()for t in times:ax.axvline(t, ls=':', c='b')# run the simulationfor t in T:V_rec.append(V) # recordVt_rec.append(Vt)V *= alpha # integrate equationsVt = (Vt-threshold)*beta+thresholdif times and t>times[-1]: # if there has been an input spikeV += wtimes.pop() # remove that spike from listV_rec.append(V) # record V before the reset so we can see the spikeVt_rec.append(Vt)if V>Vt: # if there should be an output spikeV = resetVt += dthresholdspikes.append(t)# plot everything (T is repeated because we record V twice per loop)ax.plot(np.repeat(T, 2), V_rec, '-k', lw=2)ax.plot(np.repeat(T, 2), Vt_rec, '--g', lw=2)for t in spikes:ax.axvline(t, ls='--', c='r')ax.set_xlim(0, duration)ax.set_ylim(-1, 2)ax.set_xlabel('Time (ms)')ax.set_ylabel('Voltage')plt.tight_layout()plt.show()#display(fig)LIF2()

运行结果为:

二、脉冲神经网络前向传播过程

有了上面的知识后,我们来简单模拟一下脉冲神经网络前向传播的过程:

三、脉冲神经网络突触权重学习方法(STDP)

前面我们知道了脉冲神经元内部的电动力学特性及其方程,接下来我们来学习如何更新脉冲神经网络的连接权重,区别于传统的梯度下降方法,脉冲神经网络通常使用的是更具生物学特性的STDP(spike timing dependent plasticity)学习策略。在解释STDP之前,我们先来看看一些概念:

如上图所示,脉冲神经元连接有前突触和后突触之分,索引j 神经元称为前突触,若神经元j产生了一个脉冲,则称神经元j产生了一个突触前脉冲,索引i 神经元称为后突触,同理神经元i产生的脉冲称为突触后脉冲。j与i的连接权重为 ,神经元i接收到来自神经元j的一个脉冲后,神经元i要累积该脉冲到电压中,即神经元i当前的电压加上某个值,该值的大小与有关,那么该如何更新 呢?

的更新在脉冲神经网络中最常用的方法是STDP方法,STDP更新突触权重的方式是:若突触前脉冲比突触后脉冲到达时间早,会导致Long-Term Potentiation(LTP)效应,即 权重会增加。反之,若突触前脉冲比突触后脉冲到达时间晚,会引起LTD,即 权重会减小。在神经科学实验中,人们多次发现和验证了STDP是大脑突触权重更新的方式,突触权重更新意味着学习和信息的存储,也意味着大脑发育过程中神经元回路的发展和完善。

根据上面的定义,STDP更新权重的公式可写成:

也就是说,突触权重 的变化是某个函数 W的所有突触前尖峰时间 和突触后尖峰时间 差的总和。一个常用的函数 W 是:

举个例子:

然而使用该定义需要事先知道前突触脉冲和后突触脉冲一段时间内各自发放脉冲的时间表,因此直接使用这个方程更新权重将非常低效,因为我们必须对每个神经元先记录好它的脉冲发放时间表,然后对所有尖峰对时间差求和。这在生物学上也是不现实的,因为神经元无法记住之前的所有尖峰时间。事实证明,有一种更有效、生理上更合理的方法可以达到同样的效果,该方法可以在突触前脉冲发放或突触后脉冲发放就立刻更新权重。

我们先定义两个新变量 ,它们分别为突触前脉冲发放后的活动“痕迹”变量和突触后脉冲发放后的活动“痕迹”变量(如下图所示):

痕迹变化由LIF模型控制:

当发放突触前脉冲时,会更新突触前活动痕迹变量并根据规则修改权重w:

同理当突触后脉冲发放时:

这个更新公式可以理解为:当突触前脉冲到达了,突触后脉冲痕迹还未衰减到0,说明突触后脉冲是比突触前脉冲早到达的,所以权重应该削弱,削弱量为, 需要说明的是通常 为负数(为负数的原因是在更新痕迹时,初始=0,突触后脉冲发放时,会加 ,通常是某个较小的负数常数);同理当突触后脉冲发生时,突触前脉冲痕迹还未衰减到0时,说明突触前脉冲是比突触后脉冲早到达的,所以权重应该增强,增强量为,这里通常 为正数。

四、泊松脉冲编码

最后,我们看一下泊松脉冲编码。由于脉冲神经网络接收的是脉冲信号,所以需要对初始输入数据进行脉冲编码,其中输入数据脉冲编码一个比较常用的方式是泊松脉冲编码,更详细的泊松脉冲编码讲解可参考:https://www.youtube.com/watch?v=4r_gc4vf8eE 。

泊松脉冲编码首先需要设置脉冲速率ρ0ρ0 可以是常数,也可以是时间函数。编码过程可描述为:取时间间隔为Δt ,则每个时间间隔脉冲发放的概率为pF=ρ0*Δt ,电脑在每个时间间隔生成一个(0,1)范围内均匀分布的随机数,随机数小于ρ0*Δt 则在该时间间隔内产生一个脉冲。

泊松脉冲编码可以这样应用:把输入时间序列值看成脉冲速率ρ0 ,如t1时刻输入为a, t2时刻输入为b,t3时刻输入为c,若t1时刻0-1随机数大于或等于a*Δt ,则t1时刻神经元不发放脉冲,t2时刻0-1随机数小于b*Δt ,则t2时刻神经元发放脉冲,t3时刻0-1随机数大于或等于c*Δt ,则t3时刻神经元不发放脉冲,所以a,b,c编码后的脉冲序列为无脉冲,脉冲,无脉冲。

最后,推荐一个可以用来学习脉冲神经网络特性的编程工具包:brian2

python安装方式:pip install brian2

教程:Introduction to Brian part 1: Neurons — Brian 2 2.5.1 documentation

一文通俗入门·脉冲神经网络(SNN)·第三代神经网络相关推荐

  1. 如何看待第三代神经网络SNN?详解脉冲神经网络的架构原理、数据集和训练方法 原创

    作者丨科技猛兽 编辑丨极市平台 本文首发于极市平台公众号,转载请获得授权并标明出处. 本文目录 1 脉冲神经网络简介 2 脉冲神经网络原理 3 脉冲神经网络数据集 4 脉冲神经网络训练方法 5 脉冲神 ...

  2. 第三十二课.脉冲神经网络SNN

    目录 时间驱动与事件驱动 时间驱动 事件驱动 基于时间驱动的脉冲神经元 spikingjelly:LIF神经元 实验仿真 时间驱动与事件驱动 时间驱动 为了便于理解时间驱动,我们可以将SNN(spik ...

  3. Pytorch入门练习-kaggle手写字识别神经网络(SNN)实现

    采用pytorch搭建神经网络,解决kaggle平台手写字识别问题. 数据来源:https://www.kaggle.com/competitions/digit-recognizer/data 参考 ...

  4. 【深度学习】翻译:60分钟入门PyTorch(三)——神经网络

    前言 原文翻译自:Deep Learning with PyTorch: A 60 Minute Blitz 翻译:林不清(https://www.zhihu.com/people/lu-guo-92 ...

  5. NLP入门概览(3)—— 神经网络语言模型、词向量

      在这一部分中,我们将在此基础上介绍神经网络语言模型以及词向量的相关知识.在介绍这些知识之前,我们首先对自然语言处理领域的整体架构进行一些简单的介绍. 1. 自然语言处理架构   首先,我们来看这样 ...

  6. 神经网络入门书籍推荐,神经网络入门经典书籍

    有什么适合深度学习的书单吗? . 12本最好的深度学习书籍:1.用Scikit-Learn和TensorFlow进行机器学习2.深度学习(DeepLearning)3.DeepLearningfort ...

  7. pytorch深度学习和入门实战(四)神经网络的构建和训练

    目录 1.前言 2.神经网络概述 2.1 核心组件包括: 2.2 核心过程 3.构建神经网络模型 3.1构建网络层(Layer ➨ Model) 3.2 torch.nn.Sequential的3大使 ...

  8. 期货股票量化软件:第三代神经网络深度网络

    简介 本文将要讨论这一课题的主要概念,诸如深度学习以及无复杂layman形式运算的深度网络. 真实数据的实验,赫兹量化软件通过定量和比较(无法定量和比较),证实(或证伪)深度神经网络的理论优势.当前的 ...

  9. 一文快速入门分库分表中间件 Sharding-JDBC (必修课)

    书接上文 <一文快速入门分库分表(必修课)>,这篇拖了好长的时间,本来计划在一周前就该写完的,结果家庭内部突然人事调整,领导层进行权利交接,随之宣布我正式当爹,紧接着家庭地位滑落至第三名, ...

  10. 零基础入门深度学习(5) - 循环神经网络

    往期回顾 在前面的文章系列文章中,我们介绍了全连接神经网络和卷积神经网络,以及它们的训练和使用.他们都只能单独的取处理一个个的输入,前一个输入和后一个输入是完全没有关系的.但是,某些任务需要能够更好的 ...

最新文章

  1. 数据结构与算法实验祝恩_《数据结构与算法》实验教学大纲
  2. 浏览器兼容问题IE兼容模式下 SCRIPT1028: 缺少标识符、字符串或数字
  3. MySQL会回收使用中的连接吗_Node.js实现mysql连接池使用事务自动回收连接的方法示例...
  4. 小技巧——让光驱符号定位在硬盘分区之后
  5. ejb 2.0 3.0_定义EJB 3.1视图(本地,远程,无接口)
  6. java实现k-means算法(用的鸢尾花iris的数据集,从mysq数据库中读取数据)
  7. vue实现网络图片瀑布流 + 下拉刷新 + 上拉加载更多
  8. Java并发编程之CountDownLatch闭锁
  9. 乐观锁-version的使用
  10. Unity3D之UGUI基础1:UGUI插件介绍
  11. 邵阳市计算机学校2021,邵阳市计算机中等专业学校在2021年邵阳市中等职业学校班主任基本功比赛中荣获市一等奖...
  12. matplotlib—plt.pie绘制饼状图及参数详解
  13. putty秘钥转换成xhell支持的格式
  14. 杭电多校第一场补题-1002 Balanced Sequence
  15. Linux下网络测试工具tcpping、tcptraceroute的使用
  16. 常用的第三方ui框架
  17. 传奇服务器M2道士毒文件,传奇版本M2里面【Envir】文件功能说明
  18. 《嵌入式系统原理与应用》 | 嵌入式系统 重点知识梳理
  19. 第1章 Dev C++的使用
  20. 机器学习实战-手写识别系统

热门文章

  1. 今日学习在线编程题:小码哥的手下
  2. 13、Jupyter notebook制作幻灯片PPT
  3. PAT_1078 Hashing
  4. LOJ #2155. 「POI2011 R1」同谋者 Conspiracy(深入性质分析)
  5. zanti html恶搞,Html.AntiForgeryToken 突然报这个错误 太奇怪了
  6. 高频leetcode数学部分:679. 24 点游戏
  7. fast虚拟服务器ip地址设置,迅捷路由器静态ip怎么设置_迅捷固定IP地址怎么设置?-192路由网...
  8. 1449异常 mysql_连接MySQL时出现1449与1045异常解决办法
  9. mysql 临时表 会话级_会话级的临时表和事务级的临时表
  10. Window 时间同步 地址