Skip to main content
 首页 » 编程设计

python之如何在tensorflow中实现stdp

2024年09月03日26sxdcgaq8080

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

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

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

Input Spikes: 
[[0, 0, 1, 1, 0, 1, 0], 
 [1, 1, 0, 0, 0, 0, 1]] 

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

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]。现在,我计算所有增量时间:

Delta Times = [ 2-3, 2-6, 3-3, 3-6, 5-3, 5-6 ] = [ -1, -4, 0, -3, 2, -1 ] 

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

 dw = SUM [ F(-1), F(-4), F(0), F(-3), F(2), F(-1) ] 

这就是连接输入神经元 0 和输出神经元 0 的权重的 dw。对所有非零权重重复此操作。

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

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

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 个输入神经元馈送到 400 个神经元的真实神经网络,超过 500 个时间步长,spike_match = 步骤执行 (784, 1, 500, 1) 和 (1, 400) 的乘法, 1, 500) 张量。

请您参考如下方法:

我对 STDP 不熟悉,所以我希望我能正确理解你的意思。我认为这符合您的描述:

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 的恒等函数作为占位符,因此在这种情况下,结果值实际上只是时间差的总和。

编辑:仅供引用,将 f 替换为您包含的 STDP 函数:

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))) 

结果是:

[[-3.4020822   2.1660795  -5.694256  ] 
 [-2.974073    0.45364904 -3.1197631 ]]