最近看了很多的STDP的工作原理,比如
SNN系列|学习算法篇(6)脉冲时序依赖可塑性STDP_脉冲时间依赖可塑性-CSDN博客
Spike-Timing Dependent Plasticity - Scholarpedia
这两篇的介绍的代码非常的详细,我就不再赘述了
我设计的STDP的是基于最邻近匹配的:
#include<iostream>
#include<vector>
#include <math.h>
using namespace std;
class Neuron
{
private:
vector<int> spikeList; //脉冲的序列
public:
double last_fired; //神经元的上次发放脉冲的时间
void update(int i , vector<int>* e)
{
if (spikeList[i] == 1)
{
last_fired = (i + 1) * 0.1; //仿真的精度为0.1ms
e->push_back(i);
}
}
Neuron(vector<int> spikeList_) :last_fired(-1.0),spikeList(spikeList_)
{
}
};
class STDP
{
private:
const double A_pos = 0.1; // 正向权重更新速率
const double A_neg = 0.1; // 负向权重更新速率
const double tau = 20.0; // 时间常数
double weight; //突触的权重
public:
Neuron* post;
Neuron* pre;
void update()
{
if (pre->last_fired != -1.0 && post->last_fired != -1.0)
{
// 根据时间差计算权重更新
double Delta_t = pre->last_fired - post->last_fired;
double Delta_w;
if (Delta_t > 0)
{
//促进作用
Delta_w = A_pos * exp(-Delta_t / tau);
}
else if(Delta_t < 0)
{
//抑制作用
Delta_w = - A_neg * exp(-Delta_t / tau);
}
else
{
Delta_w = 0;
}
weight += Delta_w;
cout <<"突触更新后权重变为" << weight << endl;
}
}
STDP(Neuron* pre_, Neuron* post_) :pre(pre_), post(post_),weight(2.0)
{
}
};
int main()
{
// 初始化两个神经元的脉冲序列
vector<int> spike1 = { 0,1,0,0,0,1,0,0,1,0 };
vector<int> spike2 = { 0,0,0,1,0,0,1,0,0,1 };
// 初始化神经元
vector<Neuron> group;
Neuron n1(spike1);
Neuron n2(spike2);
group.push_back(n1);
group.push_back(n2);
// 初始化突触
STDP s(&group[0], &group[1]);
vector<int> event(0);//脉冲事件
// 模拟STDP
for (int i = 0; i < 10; i++)
{
for (auto& neuron : group)
{
neuron.update(i,&event);
}
//只有神经元发射脉冲才更新
if (event.size() > 0)
{
s.update();
}
event.clear();
}
return 0;
}
仿真的结果为:
缺点:
- 没有考虑突触的延迟机制
- 这种算法仅仅适合事件驱动的方式,但是不符合我设计的SNN的混合驱动的模式
回来我会写出符合我之前设计的代码。