首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在tensorflow中实现stdp?

如何在tensorflow中实现stdp?
EN

Stack Overflow用户
提问于 2019-03-05 04:17:22
回答 1查看 432关注 0票数 2

我正在尝试在tensorflow中实现STDP (与时间相关的塑性)。有点复杂。有什么想法(完全在tensorflow图中运行)?

它的工作原理如下:假设我有2个输入神经元,它们通过这个矩阵连接到3个输出神经元:[[1.0, 1.0, 0.0], [0.0, 0.0, 1.0]] (输入神经元0连接输出神经元0和1.)。

假设我有这些输入神经元的尖峰(2个神经元,7个时间步骤):

代码语言:javascript
运行
复制
Input Spikes:
[[0, 0, 1, 1, 0, 1, 0],
 [1, 1, 0, 0, 0, 0, 1]]

输出神经元的这些尖峰(3个神经元,7个时间步骤):

代码语言:javascript
运行
复制
Output Spikes:
[[0, 0, 0, 1, 0, 0, 1],
 [1, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1]]

现在,对于每一个非零的重量,我想计算一个dw。例如,对于连接到输出神经元0的输入神经元0:

输入神经元0的尖峰时间戳为[2, 3, 5],输出神经元0的时间戳为[3, 6]。现在,我计算所有的增量时间:

代码语言:javascript
运行
复制
Delta Times = [ 2-3, 2-6, 3-3, 3-6, 5-3, 5-6 ] = [ -1, -4, 0, -3, 2, -1 ]

然后,我计算一些函数(实际的STDP函数,这对这个问题并不重要-一些指数型的东西)。

代码语言:javascript
运行
复制
 dw = SUM [ F(-1), F(-4), F(0), F(-3), F(2), F(-1) ]

这是连接输入神经元0到输出神经元0的权重dw。对所有非零权重重复。

所以我可以在numpy中完成所有这些,但是我希望能够完全在一个tensorflow图中完成。特别是,我被困在计算增量时间上。以及如何并行地对所有非零权重进行所有这些操作。

这是实际的stdp函数,顺便说一下(常量可以是参数):

代码语言:javascript
运行
复制
def stdp_f(x):
    return tf.where(
        x == 0, np.zeros(x.shape), tf.where(
            x > 0, 1.0 * tf.exp(-1.0 * x / 10.0), -1.0 * 1.0 * tf.exp(x / 10.0)))

关于性能的注意事项:下面@jdehesa给出的方法是正确的,也是聪明的。但结果也是缓慢的。特别地,对于一个由784个输入神经元组成的真实神经网络,超过500个时间步长,spike_match =步骤执行(784,1500,1)和(1,400,1,500)张量的乘法。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-03-05 10:29:43

我不熟悉STDP,所以我希望我能正确理解你的意思。我想这和你说的一样:

代码语言:javascript
运行
复制
import tensorflow as tf

def f(x):
    # STDP function
    return x * 1

def stdp(input_spikes, output_spikes):
    input_shape = tf.shape(input_spikes)
    t = input_shape[-1]
    # Compute STDP function for all possible time difference values
    stdp_values = f(tf.cast(tf.range(-t + 1, t), dtype=input_spikes.dtype))
    # Arrange in matrix such that position [i, j] contains f(i - j)
    matrix_idx = tf.expand_dims(tf.range(t - 1, 2 * t - 1), 1) + tf.range(0, -t, -1)
    stdp_matrix = tf.gather(stdp_values, matrix_idx)
    # Find spike matches
    spike_match = (input_spikes[:, tf.newaxis, :, tf.newaxis] *
                   output_spikes[tf.newaxis, :, tf.newaxis, :])
    # Sum values where there are spike matches
    return tf.reduce_sum(spike_match * stdp_matrix, axis=(2, 3))

# Test
input_spikes = [[0, 0, 1, 1, 0, 1, 0],
                [1, 1, 0, 0, 0, 0, 1]]
output_spikes = [[0, 0, 0, 1, 0, 0, 1],
                 [1, 0, 0, 0, 0, 0, 0],
                 [0, 0, 0, 0, 1, 1, 1]]
with tf.Graph().as_default(), tf.Session() as sess:
    ins = tf.placeholder(tf.float32, [None, None])
    outs = tf.placeholder(tf.float32, [None, None])
    res = stdp(ins, outs)
    res_val = sess.run(res, feed_dict={ins: input_spikes, outs: output_spikes})
    print(res_val)
    # [[ -7.  10. -15.]
    #  [-13.   7. -24.]]

在这里,我假设f可能很昂贵(而且它的值对每一对神经元都是相同的),所以我只对每一个可能的时间增量计算一次,然后在一个矩阵中重新分配计算出来的值,这样我就可以在输入和输出尖峰发生的坐标对处乘法。

我使用了f的identity函数作为占位符,因此结果值实际上只是本例中时间差的总和。

编辑:仅供参考,将f替换为包含的STDP函数:

代码语言:javascript
运行
复制
def f(x):
    return tf.where(x == 0,
                    tf.zeros_like(x),
                    tf.where(x > 0,
                             1.0 * tf.exp(-1.0 * x / 10.0),
                             -1.0 * 1.0 * tf.exp(x / 10.0)))

结果是:

代码语言:javascript
运行
复制
[[-3.4020822   2.1660795  -5.694256  ]
 [-2.974073    0.45364904 -3.1197631 ]]
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54995306

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档