Brian2_脉冲神经网络_神经元学习记录

2023-10-11 14:40

本文主要是介绍Brian2_脉冲神经网络_神经元学习记录,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

脉冲神经网络被称作是第三代神经网络,生物可信度更高,在近年来兴起的类脑科学研究中,SNN也一直占据着核心地位。并且在性能相近的情况下,基于脉冲神经网络制成的芯片相较于人工神经网络功耗更低,稳定性、鲁棒性等也更为优异。
通过pip方式安装了Brian2,并运行了一些官网上提供的程序,也附了一些自己的学习心得。

from brian2 import *
start_scope()
#start_scope()函数确保在调用该函数之前创建的任何 
#Brian对象都不会包含在下一次模拟运行中。
tau = 10*ms
eqs ='dv/dt = (1-v)/tau : 1'
G = NeuronGroup(1, eqs,method='exact')
print('Before v = %s' % G.v[0])
run(100*ms)
print('After v = %s' % G.v[0])
start_scope()
G = NeuronGroup(1, eqs, method='exact')
M = StateMonitor(G, 'v', record=0)
run(30*ms)
plot(M.t/ms, M.v[0], 'C0', label='Brian')
plot(M.t/ms, 1-exp(-M.t/tau), 'C1--',label='Analytic')
xlabel('Time (ms)')
ylabel('v')
legend()
show()

请添加图片描述

程序中要注意量纲,如将不同单位的量进行相加、等式左右量纲不一致程序都会报错。如在eqs ='dv/dt = (1-v)/tau : 1'中去掉/tau就会出现量纲不一致而报错。

该程序中,创建神经元组函数NeuronGroup()创建了一个以微分方程dv/dt = (1-v)/tau : 1定义好模型的神经元,我们使用了 StateMonitor函数来监测神经元状态。前两个参数是要记录的组和要记录的变量。我们还指定record=0. 这意味着我们记录神经元 0 的所有值。我们必须指定我们想要记录哪些神经元,因为在具有许多神经元的大型模拟中,它通常会占用太多 RAM 来记录所有神经元的值。

蓝色实线即为该神经元v的变化,橙色虚线为微分方程dv/dt = (1-v)/tau : 1的解析解1-exp(-t/tau)的函数曲线,二者是重合的。

start_scope()
tau = 10*ms
eqs = '''
dv/dt = (1-v)/tau : 1
'''
G = NeuronGroup(1, eqs, threshold='v>0.8', reset='v = 0', method='exact')
M = StateMonitor(G, 'v', record=0)
run(50*ms)
plot(M.t/ms, M.v[0])
xlabel('Time (ms)')
ylabel('v')
show()

请添加图片描述

我们在NeuronGroup声明中添加了两个新关键字: threshold='v>0.8'reset='v = 0'。这意味着当我们发射尖峰时,并在尖峰后立即重置。

from brian2 import *
start_scope()
tau = 10*ms
eqs ='dv/dt = (1-v)/tau : 1'
G = NeuronGroup(1, eqs, threshold='v>0.8', reset='v = 0', method='exact')
statemon = StateMonitor(G, 'v', record=0)
spikemon = SpikeMonitor(G)
run(50*ms)
print('Spike times: %s' % spikemon.t[:])
plot(statemon.t/ms, statemon.v[0])
for t in spikemon.t:axvline(t/ms, ls='--', c='C1', lw=3)
xlabel('Time (ms)')
ylabel('v')
show()

请添加图片描述

脉冲时间:Spike times: [16. 32.1 48.2] ms

神经元模型的一个共同特征是不应期。这意味着在神经元发射一个尖峰之后,它会在一段时间内变得顽固,并且在这段时间结束之前不能再发射另一个尖峰。以下是我们在 Brian 中的做法。

from brian2 import *
start_scope()
tau = 10*ms
eqs ='dv/dt = (1-v)/tau : 1'
start_scope()
tau = 10*ms
eqs = '''
dv/dt = (1-v)/tau : 1 (unless refractory)
'''
G = NeuronGroup(1, eqs, threshold='v>0.8', reset='v = 0', refractory=5*ms, method='exact')
statemon = StateMonitor(G, 'v', record=0)
spikemon = SpikeMonitor(G)
run(50*ms)
plot(statemon.t/ms, statemon.v[0])
for t in spikemon.t:axvline(t/ms, ls='--', c='C1', lw=3)
xlabel('Time (ms)')
ylabel('v')
show()

请添加图片描述

虽然我们在NeuronGroup函数中添加了参数refractory=5*ms,但是在微分方程中还是要添加(unless refractory),否则神经元的行为不会产生不应期。

from brian2 import *
start_scope()
tau = 5*ms
eqs = '''
dv/dt = (1-v)/tau : 1
'''
G = NeuronGroup(1, eqs, threshold='v>0.8', reset='v = 0', refractory=15*ms, method='exact')
statemon = StateMonitor(G, 'v', record=0)
spikemon = SpikeMonitor(G)
run(50*ms)
plot(statemon.t/ms, statemon.v[0])
for t in spikemon.t:axvline(t/ms, ls='--', c='C1', lw=3)
axhline(0.8, ls=':', c='C2', lw=3)
xlabel('Time (ms)')
ylabel('v')
print("Spike times: %s" % spikemon.t[:])
show()

请添加图片描述

那么这里发生了什么?第一个尖峰的行为是相同的: v上升到 0.8,然后神经元在0到8 毫秒的时间内触发尖峰,然后立即重置为 0。由于不应期现在是 15 毫秒,这意味着神经元将无法尖峰再次直到时间 8 + 15 = 23 毫秒。在第一个尖峰之后,v的值立即开始上升,因为我们没有在NeuronGroup的定义中指定(unless refractory),此时虽然它可以在大约 8 毫秒的时间达到值 0.8(绿色虚线),但因为神经元现在正处于不应期,故到达阈值后不会重置反而继续上升,直到不应期结束电位才会被复位。

下面演示多个神经元。

from brian2 import *
start_scope()
N = 100
tau = 10*ms
eqs = '''
dv/dt = (2-v)/tau : 1
'''
G = NeuronGroup(N, eqs, threshold='v>1', reset='v=0', method='exact')
G.v = 'rand()'
spikemon = SpikeMonitor(G)
run(50*ms)
plot(spikemon.t/ms, spikemon.i, '.k')
xlabel('Time (ms)')
ylabel('Neuron index')
show()

请添加图片描述

变量N 来确定神经元的数量,G.v = 'rand()'是用 0 到 1 之间不同的随机值初始化每个神经元,这样做只是为了让每个神经元做一些不同的事情。spikemon.t表示神经元尖峰时间,spikemon.i为每个尖峰提供相应的神经元索引值。这是神经科学中使用的标准“光栅图”。

from brian2 import *
start_scope()
N = 100
tau = 10*ms
v0_max = 3.
duration = 1000*ms
eqs = '''
dv/dt = (v0-v)/tau : 1 (unless refractory)
v0 : 1
'''
G = NeuronGroup(N, eqs, threshold='v>1', reset='v=0', refractory=5*ms, method='exact')
M = SpikeMonitor(G)
G.v0 = 'i*v0_max/(N-1)'
run(duration)
figure(figsize=(12,4))
subplot(121)
plot(M.t/ms, M.i, '.k')
xlabel('Time (ms)')
ylabel('Neuron index')
subplot(122)
plot(G.v0, M.count/duration)
xlabel('v0')
ylabel('Firing rate (sp/s)')
show()

请添加图片描述

在这个例子中,我们将神经元以v0 指数方式驱动到该值,但是当v>1时,它会触发一个尖峰并重置。结果是它发射尖峰的速率将与v0的值相关。因为v0<1它永远不会发射尖峰,而且随着v0变大它会以更高的速率发射尖峰。右图显示了v0的函数的点火率 。这是这个神经元模型的 If 曲线。

请注意,在图中我们使用了SpikeMonitor中的变量count: 这是组中每个神经元被激发的尖峰数量的数组。将其除以运行的持续时间得出点火率。

from brian2 import *
start_scope()
N = 100
tau = 10*ms
v0_max = 3.
duration = 1000*ms
sigma = 0.2
eqs = '''
dv/dt = (v0-v)/tau+sigma*xi*tau**-0.5 : 1 (unless refractory)
v0 : 1
'''
G = NeuronGroup(N, eqs, threshold='v>1', reset='v=0', refractory=5*ms, method='euler')
M = SpikeMonitor(G)
G.v0 = 'i*v0_max/(N-1)'
run(duration)
figure(figsize=(12,4))
subplot(121)
plot(M.t/ms, M.i, '.k')
xlabel('Time (ms)')
ylabel('Neuron index')
subplot(122)
plot(G.v0, M.count/duration)
xlabel('v0')
ylabel('Firing rate (sp/s)')
show()

Often when making models of neurons, we include a random element to model the effect of various forms of neural noise. In Brian, we can do this by using the symbol xi in differential equations. Strictly speaking, this symbol is a “stochastic differential(随机微分)” but you can sort of thinking of it as just a Gaussian random variable with mean 0 and standard deviation 1. We do have to take into account the way stochastic differentials scale with time, which is why we multiply it by tau**-0.5 in the equations below (see a textbook on stochastic differential equations for more details). Note that we also changed the method keyword argument to use 'euler' (which stands for the Euler-Maruyama method); the 'exact' method that we used earlier is not applicable to stochastic differential equations(随机微分方程).

这一段程序我没有看懂,故把原文也附了上来,看些文献后研究,相比于上一块代码,神经网络中增加了一些噪音,使得点火率以S形方式上升,以下为运行结果。

请添加图片描述

这篇关于Brian2_脉冲神经网络_神经元学习记录的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/188767

相关文章

MySQL 中查询 VARCHAR 类型 JSON 数据的问题记录

《MySQL中查询VARCHAR类型JSON数据的问题记录》在数据库设计中,有时我们会将JSON数据存储在VARCHAR或TEXT类型字段中,本文将详细介绍如何在MySQL中有效查询存储为V... 目录一、问题背景二、mysql jsON 函数2.1 常用 JSON 函数三、查询示例3.1 基本查询3.2

Python获取中国节假日数据记录入JSON文件

《Python获取中国节假日数据记录入JSON文件》项目系统内置的日历应用为了提升用户体验,特别设置了在调休日期显示“休”的UI图标功能,那么问题是这些调休数据从哪里来呢?我尝试一种更为智能的方法:P... 目录节假日数据获取存入jsON文件节假日数据读取封装完整代码项目系统内置的日历应用为了提升用户体验,

Spring Boot 配置文件之类型、加载顺序与最佳实践记录

《SpringBoot配置文件之类型、加载顺序与最佳实践记录》SpringBoot的配置文件是灵活且强大的工具,通过合理的配置管理,可以让应用开发和部署更加高效,无论是简单的属性配置,还是复杂... 目录Spring Boot 配置文件详解一、Spring Boot 配置文件类型1.1 applicatio

MySQL INSERT语句实现当记录不存在时插入的几种方法

《MySQLINSERT语句实现当记录不存在时插入的几种方法》MySQL的INSERT语句是用于向数据库表中插入新记录的关键命令,下面:本文主要介绍MySQLINSERT语句实现当记录不存在时... 目录使用 INSERT IGNORE使用 ON DUPLICATE KEY UPDATE使用 REPLACE

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步

Python Dash框架在数据可视化仪表板中的应用与实践记录

《PythonDash框架在数据可视化仪表板中的应用与实践记录》Python的PlotlyDash库提供了一种简便且强大的方式来构建和展示互动式数据仪表板,本篇文章将深入探讨如何使用Dash设计一... 目录python Dash框架在数据可视化仪表板中的应用与实践1. 什么是Plotly Dash?1.1

Spring Boot中定时任务Cron表达式的终极指南最佳实践记录

《SpringBoot中定时任务Cron表达式的终极指南最佳实践记录》本文详细介绍了SpringBoot中定时任务的实现方法,特别是Cron表达式的使用技巧和高级用法,从基础语法到复杂场景,从快速启... 目录一、Cron表达式基础1.1 Cron表达式结构1.2 核心语法规则二、Spring Boot中定

Java进阶学习之如何开启远程调式

《Java进阶学习之如何开启远程调式》Java开发中的远程调试是一项至关重要的技能,特别是在处理生产环境的问题或者协作开发时,:本文主要介绍Java进阶学习之如何开启远程调式的相关资料,需要的朋友... 目录概述Java远程调试的开启与底层原理开启Java远程调试底层原理JVM参数总结&nbsMbKKXJx

国内环境搭建私有知识问答库踩坑记录(ollama+deepseek+ragflow)

《国内环境搭建私有知识问答库踩坑记录(ollama+deepseek+ragflow)》本文给大家利用deepseek模型搭建私有知识问答库的详细步骤和遇到的问题及解决办法,感兴趣的朋友一起看看吧... 目录1. 第1步大家在安装完ollama后,需要到系统环境变量中添加两个变量2. 第3步 “在cmd中

Spring Retry 实现乐观锁重试实践记录

《SpringRetry实现乐观锁重试实践记录》本文介绍了在秒杀商品SKU表中使用乐观锁和MybatisPlus配置乐观锁的方法,并分析了测试环境和生产环境的隔离级别对乐观锁的影响,通过简单验证,... 目录一、场景分析 二、简单验证 2.1、可重复读 2.2、读已提交 三、最佳实践 3.1、配置重试模板