2.15 Select

seq2seqで使うために、時系列データの中から一つのタイムステップを選択するSelectレイヤを実装します。

from ivory.core.model import sequential

N, T, L, M = 2, 10, 4, 3

net = [("input", L), ("rnn", M, "select", "softmax_cross_entropy")]
model = sequential(net)
rnn, select = model.layers[:2]
rnn.dtype = "float64"
model.init()
model.layers

[1] 2019-06-21 08:32:18 (10.0ms) python3 (306ms)

[<RNN('RNN.2', (4, 3)) at 0x15ede34beb8>,
 <Select('Select.2', (3,)) at 0x15ee03690f0>,
 <SoftmaxCrossEntropy('SoftmaxCrossEntropy.2', (3,)) at 0x15ee0369198>]

Selectレイヤを通過することで時系列データの一つが選択されます。デフォルトは時系列データの最後のタイムステップです。

import numpy as np

x = np.random.randn(N, T, L)
t = np.random.randint(0, M, N)
model.set_data(x, t)
model.forward()
print(select.x.d[:, -1])
print(select.y.d)

[2] 2019-06-21 08:32:18 (9.01ms) python3 (315ms)

[[ 0.89512488  0.99522548  0.52110654]
 [-0.85422902  0.99547136 -0.81617407]]
[[ 0.89512488  0.99522548  0.52110654]
 [-0.85422902  0.99547136 -0.81617407]]

逆伝搬を検証するために、数値微分による勾配確認を行います。

model.forward()
model.backward()
for v in model.grad_variables:
    print(v.parameters[0].name, model.gradient_error(v))

[3] 2019-06-21 08:32:18 (67.0ms) python3 (382ms)

x 5.69606022570724e-05
W 0.00020918928862316438
U 0.0003342543827706396
b 0.0001633545912814812
h 7.316310336753588e-05

一致した結果が得られました。

実装は以下のとおりです。

Code 2.19 Selectクラス

class Select(Layer):
    input_ndim = 0

    def init(self):
        self.index = -1

    def forward(self):
        self.y.d = self.x.d[:, self.index]

    def backward(self):
        dx = np.zeros_like(self.x.d)
        dx[:, self.index] = self.y.g
        self.x.g = dx