用numpy实现RNN

ytr*_*ewq 9 python numpy recurrent-neural-network rnn

我正试图用numpy实现递归神经网络.

我目前的输入和输出设计如下:

x 形状:(序列长度,批量大小,输入维度)

h :(层数,方向数,批量大小,隐藏大小)

initial weight:(方向数,2*隐藏大小,输入大小+隐藏大小)

weight:(层数-1,方向数,隐藏大小,方向*隐藏大小+隐藏大小)

bias:(层数,方向数,隐藏大小)

我已经查找了RNN的pytorch API作为参考(https://pytorch.org/docs/stable/nn.html?highlight=rnn#torch.nn.RNN),但略微改变它以包括初始权重作为输入.(输出形状与pytorch中的相同)

当它正在运行时,我无法确定它是否表现正常,因为我输入随机生成的数字作为输入.

特别是,我不确定我的输入形状是否设计正确.

有专家可以给我一个指导吗?

def rnn(xs, h, w0, w=None, b=None, num_layers=2, nonlinearity='tanh', dropout=0.0, bidirectional=False, training=True):
    num_directions = 2 if bidirectional else 1
    batch_size = xs.shape[1]
    input_size = xs.shape[2]
    hidden_size = h.shape[3]
    hn = []
    y = [None]*len(xs)

    for l in range(num_layers):
        for d in range(num_directions):
            if l==0 and d==0:
                wi = w0[d, :hidden_size,  :input_size].T
                wh = w0[d, hidden_size:,  input_size:].T
                wi = np.reshape(wi, (1,)+wi.shape)
                wh = np.reshape(wh, (1,)+wh.shape)
            else:
                wi = w[max(l-1,0), d, :,  :hidden_size].T
                wh = w[max(l-1,0), d, :,  hidden_size:].T
            for i,x in enumerate(xs):
                if l==0 and d==0:
                    ht = np.tanh(np.dot(x, wi) + np.dot(h[l, d], wh) + b[l, d][np.newaxis])
                    ht = np.reshape(ht,(batch_size, hidden_size)) #otherwise, shape is (bs,1,hs)
                else:
                    ht = np.tanh(np.dot(y[i], wi) + np.dot(h[l, d], wh) + b[l, d][np.newaxis])
                y[i] = ht
            hn.append(ht)
    y = np.asarray(y)
    y = np.reshape(y, y.shape+(1,))
    return np.asarray(y), np.asarray(hn)
Run Code Online (Sandbox Code Playgroud)

Dzj*_*jkb 2

关于形状,如果 PyTorch 就是这样做的,那么它可能是有意义的,但 Tensorflow 的方式更直观一些——(batch_size, seq_length, input_size)每个元素都有大小的长度batch_size序列。两种方法都可以工作,所以我想这只是一个偏好问题。seq_lengthinput_size

为了查看你的 rnn 行为是否正确,我只需打印每个时间步的隐藏状态,在一些小的随机数据(例如 5 个向量,每个向量 3 个元素)上运行它,并将结果与​​你的手动计算进行比较。

看看你的代码,我不确定它是否做了它应该做的事情,但我建议你阅读并尝试复制这个来自wildml 的很棒的教程(在第 2 部分中) ,而不是根据现有的 API 自己做这件事有一个纯 numpy 实现)。