水库计算机的雅可比式 - 符号形式

Jacobian of a Reservoir Computer - Symbolic Form

提问人:rmewest 提问时间:11/15/2023 更新时间:11/15/2023 访问量:15

问:

我有一个向量值函数:F(h) = (1-a)* h + a*tanh(Win * x + W * h )

https://reservoirpy.readthedocs.io/en/latest/user_guide/node.html

a是常数,x是外部输入,W是输入权重向量,W是向量元素之间耦合强度的矩阵,h表示网络内部(隐藏)状态的向量。

导数,如果这是一个变量,则为 dF/dh = a + W * sech2(Win * x + W * h)

我想计算雅可比。我目前正在用数值计算这个问题,但我想根据方程的符号解来检查我的工作。

使用数值解,我遍历每个向量元素,添加 + 和 - 扰动 (eps = 1e-8),取差值,然后除以 eps。

    def numerical_jacobian(x, res, h_t, j_eps):
        n = np.size(h_t,1)
        jac = np.zeros((n,n))
        for i in range(n):
            hf = h_t.copy()
            hb = h_t.copy()
            hf[0][i] = hf[0][i] + j_eps
            hb[0][i] = hb[0][i] - j_eps
            hf_state = res.call(x, from_state = hf, stateful = False)
            hb_state = res.call(x, from_state = hb, stateful = False)
            jaccol = (hf_state - hb_state)/(2*j_eps)
            jac[:,i] = np.transpose(jaccol[0])
        return jac

[顺便说一句 - 我知道 autograd 将是最好的解决方案,因为它会更有效率。但目前,我正在使用别人的代码,在开始走这条路之后,要重新设计它需要做很多工作。他们把所有东西都写成一个numpy数组(与Pytorch或tensorflow相比)。

我尝试重构导数的表达式,将除一个(每次通过循环)之外的所有 h 值视为常数。

以长度为 3 的向量为例。

宽 * h = W11 h1 + W12 h2 + W13 h3 + W21 h1 + W22 h2 +W23h3 + W31 h1 + W32h2 + W33*h3

D = W12 h2 + W13 h3 + W22 h2 + W23 h3 + W32h2 + W33 h3.# 除索引 1 外的所有常量

M = W11 + W21 + W31 # 索引 1 上的常数系数

C = Win * x # 向量,但是一个常数

b = (1-a)*(h2 + h3) # 常数

-- 回到原来的表达方式,但进行替换

F(h) = (1-a)* h + a*tanh(Win * x + W * h )

F(h 1) = b + (1-a) * h 1 + a * tanh(C + D + M * h1)

dF(h 1) = M * a * sech2(C + D + M * h 1) - a +1

def symbolic_jacobian(W_in, W, x, h_t):
    n = np.size(h_t,1)
    jac = np.zeros((n,n))
    h = np.ndarray.flatten(h_t)

    C = W_in * x  # vector, but a constant

    for i in range(n):
        M = 0.0
        D = 0.0

        # sum just the values in this column of W
        for j in range(n):
            M = M + W[j][i]     # single valued constant

        # sum W*h for all but this column
        for j in range(n):   
            for k in range(n):
                if k != i:
                    D = D + W[j][k] * h[k]  # single valued constant
    
        
        E = C * D                   # n x 1
        G = E + M * h[i]            # n x 1  
        H = np.tanh(G)              # n x 1

        # reminder that sech(Z) = 1 - tanh<sup>2</sup>(Z)
        h_deriv = (a * M * ((1 - (H * H))*(1 - (H * H)))) - a + 1 # n x 1

        jac[:,i] = np.transpose(h_deriv) # 1 x n
    return jac

The numerical and symbolic jacobians do not match. Here are the differences. 

[[-1.61322219e-02  3.08682911e+00  2.81308279e-04]

 [ 1.54216918e-04  3.10315716e+00  1.98080410e-04]

 [ 2.37444787e-04  3.10230650e+00 -1.61204694e-05]]

Thanks very much!
神经网络 导数

评论


答: 暂无答案