def _test_three_recurrent_children(self, gpu): # Test if https://github.com/chainer/chainer/issues/6053 is addressed in_size = 2 out_size = 6 rseq = StatelessRecurrentSequential( L.NStepLSTM(1, in_size, 3, 0), L.NStepGRU(2, 3, 4, 0), L.NStepRNNTanh(5, 4, out_size, 0), ) if gpu >= 0: chainer.cuda.get_device_from_id(gpu).use() rseq.to_gpu() xp = rseq.xp seqs_x = [ xp.random.uniform(-1, 1, size=(4, in_size)).astype(np.float32), xp.random.uniform(-1, 1, size=(1, in_size)).astype(np.float32), xp.random.uniform(-1, 1, size=(3, in_size)).astype(np.float32), ] # Make and load a recurrent state to check if the order is correct. _, rs = rseq.n_step_forward(seqs_x, None, output_mode='concat') _, _ = rseq.n_step_forward(seqs_x, rs, output_mode='concat') _, rs = rseq.n_step_forward(seqs_x, None, output_mode='split') _, _ = rseq.n_step_forward(seqs_x, rs, output_mode='split')
def make_q_func(self, env): n_hidden_channels = 10 return StatelessRecurrentSequential( L.Linear(env.observation_space.low.size, n_hidden_channels), F.elu, L.NStepRNNTanh(1, n_hidden_channels, n_hidden_channels, 0), L.Linear(n_hidden_channels, env.action_space.n), DiscreteActionValue, )
def _test_n_step_forward_with_tuple_output(self, gpu): in_size = 5 out_size = 6 def split_output(x): return tuple(F.split_axis(x, [2, 3], axis=1)) rseq = StatelessRecurrentSequential( L.NStepRNNTanh(1, in_size, out_size, 0), split_output, ) if gpu >= 0: chainer.cuda.get_device_from_id(gpu).use() rseq.to_gpu() xp = rseq.xp # Input is a list of two variables. seqs_x = [ xp.random.uniform(-1, 1, size=(3, in_size)).astype(np.float32), xp.random.uniform(-1, 1, size=(2, in_size)).astype(np.float32), ] # Concatenated output should be a tuple of three variables. concat_out, concat_state = rseq.n_step_forward(seqs_x, None, output_mode='concat') self.assertIsInstance(concat_out, tuple) self.assertEqual(len(concat_out), 3) self.assertEqual(concat_out[0].shape, (5, 2)) self.assertEqual(concat_out[1].shape, (5, 1)) self.assertEqual(concat_out[2].shape, (5, 3)) # Split output should be a list of two tuples, each of which is of # three variables. split_out, split_state = rseq.n_step_forward(seqs_x, None, output_mode='split') self.assertIsInstance(split_out, list) self.assertEqual(len(split_out), 2) self.assertIsInstance(split_out[0], tuple) self.assertIsInstance(split_out[1], tuple) for seq_x, seq_out in zip(seqs_x, split_out): self.assertEqual(len(seq_out), 3) self.assertEqual(seq_out[0].shape, (len(seq_x), 2)) self.assertEqual(seq_out[1].shape, (len(seq_x), 1)) self.assertEqual(seq_out[2].shape, (len(seq_x), 3)) # Check if output_mode='concat' and output_mode='split' are consistent xp.testing.assert_allclose( F.concat([F.concat(seq_out, axis=1) for seq_out in split_out], axis=0).array, F.concat(concat_out, axis=1).array, )
def test(self): # Check if it can properly detect recurrent child links link = stateless_recurrent.StatelessRecurrentChainList( L.Linear(3, 4), L.NStepLSTM(1, 3, 2, 0), L.Linear(4, 5), stateless_recurrent.StatelessRecurrentChainList( L.NStepRNNTanh(1, 2, 5, 0), ), ) self.assertEqual(len(link.recurrent_children), 2) self.assertIs(link.recurrent_children[0], link[1]) self.assertIs(link.recurrent_children[1], link[3]) self.assertEqual(len(link.recurrent_children[1].recurrent_children), 1) self.assertIs(link.recurrent_children[1].recurrent_children[0], link[3][0])
def make_q_func(self, env): obs_size = env.observation_space.low.size hidden_size = 64 return iqn.StatelessRecurrentImplicitQuantileQFunction( psi=chainerrl.links.StatelessRecurrentSequential( L.Linear(obs_size, hidden_size), F.relu, L.NStepRNNTanh(1, hidden_size, hidden_size, 0), ), phi=chainerrl.links.Sequence( chainerrl.agents.iqn.CosineBasisLinear(32, hidden_size), F.relu, ), f=L.Linear(hidden_size, env.action_space.n, initialW=chainer.initializers.LeCunNormal(1e-1)), )
def make_distrib_recurrent_q_func(env): n_atoms = 51 v_max = 10 v_min = -10 return chainerrl.links.StatelessRecurrentSequential( L.NStepRNNTanh(1, env.observation_space.low.size, 20, 0), chainerrl.q_functions. DistributionalFCStateQFunctionWithDiscreteAction( # NOQA 20, env.action_space.n, n_atoms=n_atoms, v_min=v_min, v_max=v_max, n_hidden_channels=None, n_hidden_layers=0, ), )
def _test_n_step_forward_with_tuple_input(self, gpu): in_size = 5 out_size = 3 def concat_input(*args): return F.concat(args, axis=1) rseq = StatelessRecurrentSequential( concat_input, L.NStepRNNTanh(1, in_size, out_size, 0), ) if gpu >= 0: chainer.cuda.get_device_from_id(gpu).use() rseq.to_gpu() xp = rseq.xp # Input is list of tuples. Each tuple has two variables. seqs_x = [ (xp.random.uniform(-1, 1, size=(3, 2)).astype(np.float32), xp.random.uniform(-1, 1, size=(3, 3)).astype(np.float32)), (xp.random.uniform(-1, 1, size=(1, 2)).astype(np.float32), xp.random.uniform(-1, 1, size=(1, 3)).astype(np.float32)), ] # Concatenated output should be a variable. concat_out, concat_state = rseq.n_step_forward(seqs_x, None, output_mode='concat') self.assertEqual(concat_out.shape, (4, out_size)) # Split output should be a list of variables. split_out, split_state = rseq.n_step_forward(seqs_x, None, output_mode='split') self.assertIsInstance(split_out, list) self.assertEqual(len(split_out), len(seqs_x)) for seq_x, seq_out in zip(seqs_x, split_out): self.assertEqual(seq_out.shape, (len(seq_x), out_size)) # Check if output_mode='concat' and output_mode='split' are consistent xp.testing.assert_allclose( F.concat(split_out, axis=0).array, concat_out.array, )
def construct_RNN(unit_type, bidirection, n_layers, n_input, n_units, dropout): rnn = None if unit_type == 'lstm': if bidirection: rnn = L.NStepBiLSTM(n_layers, n_input, n_units, dropout) else: rnn = L.NStepLSTM(n_layers, n_input, n_units, dropout) elif unit_type == 'gru': if bidirection: rnn = L.NStepBiGRU(n_layers, n_input, n_units, dropout) else: rnn = L.NStepGRU(n_layers, n_input, n_units, dropout) else: if bidirection: rnn = L.NStepBiRNNTanh(n_layers, n_input, n_units, dropout) else: rnn = L.NStepRNNTanh(n_layers, n_input, n_units, dropout) print('# RNN unit: {}, dropout={}'.format(rnn, rnn.__dict__['dropout']), file=sys.stderr) for i, c in enumerate(rnn._children): print('# {}-th param'.format(i), file=sys.stderr) print('# 0 - W={}, b={}'.format(c.w0.shape, c.b0.shape), file=sys.stderr) print('# 1 - W={}, b={}'.format(c.w1.shape, c.b1.shape), file=sys.stderr) if unit_type == 'gru' or unit_type == 'lstm': print('# 2 - W={}, b={}'.format(c.w2.shape, c.b2.shape), file=sys.stderr) print('# 3 - W={}, b={}'.format(c.w3.shape, c.b3.shape), file=sys.stderr) print('# 4 - W={}, b={}'.format(c.w4.shape, c.b4.shape), file=sys.stderr) print('# 5 - W={}, b={}'.format(c.w5.shape, c.b5.shape), file=sys.stderr) if unit_type == 'lstm': print('# 6 - W={}, b={}'.format(c.w6.shape, c.b6.shape), file=sys.stderr) print('# 7 - W={}, b={}'.format(c.w7.shape, c.b7.shape), file=sys.stderr) return rnn
def __init__(self, input_size, rnn_type, bidirectional, num_units, num_proj, num_layers, dropout_input, dropout_hidden, subsample_list=[], subsample_type='drop', use_cuda=False, merge_bidirectional=False, num_stack=1, splice=1, input_channel=1, conv_channels=[], conv_kernel_sizes=[], conv_strides=[], poolings=[], activation='relu', batch_norm=False, residual=False, dense_residual=False, num_layers_sub=0): super(RNNEncoder, self).__init__() if len(subsample_list) > 0 and len(subsample_list) != num_layers: raise ValueError( 'subsample_list must be the same size as num_layers.') if subsample_type not in ['drop', 'concat']: raise TypeError('subsample_type must be "drop" or "concat".') if num_layers_sub < 0 or (num_layers_sub > 1 and num_layers < num_layers_sub): raise ValueError('Set num_layers_sub between 1 to num_layers.') self.rnn_type = rnn_type self.bidirectional = bidirectional self.num_directions = 2 if bidirectional else 1 self.num_units = num_units self.num_proj = num_proj if num_proj is not None else 0 self.num_layers = num_layers self.dropout_input = dropout_input self.dropout_hidden = dropout_hidden self.merge_bidirectional = merge_bidirectional self.use_cuda = use_cuda # TODO: self.clip_activation = clip_activation # Setting for hierarchical encoder self.num_layers_sub = num_layers_sub # Setting for subsampling if len(subsample_list) == 0: self.subsample_list = [False] * num_layers else: self.subsample_list = subsample_list self.subsample_type = subsample_type # This implementation is bases on # https://arxiv.org/abs/1508.01211 # Chan, William, et al. "Listen, attend and spell." # arXiv preprint arXiv:1508.01211 (2015). # Setting for residual connection assert not (residual and dense_residual) self.residual = residual self.dense_residual = dense_residual subsample_last_layer = 0 for l_reverse, is_subsample in enumerate(subsample_list[::-1]): if is_subsample: subsample_last_layer = num_layers - l_reverse break self.residual_start_layer = subsample_last_layer + 1 # NOTE: residual connection starts from the last subsampling layer with self.init_scope(): # Setting for CNNs before RNNs# Setting for CNNs before RNNs if len(conv_channels) > 0 and len(conv_channels) == len( conv_kernel_sizes) and len(conv_kernel_sizes) == len( conv_strides): assert num_stack == 1 and splice == 1 self.conv = CNNEncoder(input_size, input_channel=input_channel, conv_channels=conv_channels, conv_kernel_sizes=conv_kernel_sizes, conv_strides=conv_strides, poolings=poolings, dropout_input=0, dropout_hidden=dropout_hidden, activation=activation, use_cuda=use_cuda, batch_norm=batch_norm) input_size = self.conv.output_size else: input_size = input_size * splice * num_stack self.conv = None self.rnns = [] self.projections = [] for l in range(num_layers): if l == 0: encoder_input_size = input_size elif self.num_proj > 0: encoder_input_size = num_proj if subsample_type == 'concat' and l > 0 and self.subsample_list[ l - 1]: encoder_input_size *= 2 else: encoder_input_size = num_units * self.num_directions if subsample_type == 'concat' and l > 0 and self.subsample_list[ l - 1]: encoder_input_size *= 2 if rnn_type == 'lstm': if bidirectional: rnn_i = L.NStepBiLSTM(n_layers=1, in_size=encoder_input_size, out_size=num_units, dropout=0) else: rnn_i = L.NStepLSTM(n_layers=1, in_size=encoder_input_size, out_size=num_units, dropout=0) elif rnn_type == 'gru': if bidirectional: rnn_i = L.NStepBiGRU(n_layers=1, in_size=encoder_input_size, out_size=num_units, dropout=0) else: rnn_i = L.NStepGRU(n_layers=1, in_size=encoder_input_size, out_size=num_units, dropout=0) elif rnn_type == 'rnn': if bidirectional: # rnn_i = L.NStepBiRNNReLU( rnn_i = L.NStepBiRNNTanh(n_layers=1, in_size=encoder_input_size, out_size=num_units, dropout=0) else: # rnn_i = L.NStepRNNReLU( rnn_i = L.NStepRNNTanh(n_layers=1, in_size=encoder_input_size, out_size=num_units, dropout=0) else: raise ValueError( 'rnn_type must be "lstm" or "gru" or "rnn".') if use_cuda: rnn_i.to_gpu() setattr(self, rnn_type + '_l' + str(l), rnn_i) if l != self.num_layers - 1 and self.num_proj > 0: proj_i = LinearND(num_units * self.num_directions, num_proj, dropout=dropout_hidden, use_cuda=use_cuda) if use_cuda: proj_i.to_gpu() setattr(self, 'proj_l' + str(l), proj_i)
def _test_n_step_forward(self, gpu): in_size = 2 out_size = 6 rseq = StatelessRecurrentSequential( L.Linear(in_size, 3), F.elu, L.NStepLSTM(1, 3, 4, 0), L.Linear(4, 5), L.NStepRNNTanh(1, 5, out_size, 0), F.tanh, ) if gpu >= 0: chainer.cuda.get_device_from_id(gpu).use() rseq.to_gpu() xp = rseq.xp linear1 = rseq._layers[0] lstm = rseq._layers[2] linear2 = rseq._layers[3] rnn = rseq._layers[4] seqs_x = [ xp.random.uniform(-1, 1, size=(4, in_size)).astype(np.float32), xp.random.uniform(-1, 1, size=(1, in_size)).astype(np.float32), xp.random.uniform(-1, 1, size=(3, in_size)).astype(np.float32), ] concat_out, concat_state = rseq.n_step_forward( seqs_x, None, output_mode='concat') self.assertEqual(concat_out.shape, (8, out_size)) split_out, split_state = rseq.n_step_forward( seqs_x, None, output_mode='split') self.assertIsInstance(split_out, list) self.assertEqual(len(split_out), len(seqs_x)) for seq_x, seq_out in zip(seqs_x, split_out): self.assertEqual(seq_out.shape, (len(seq_x), out_size)) # Check if output_mode='concat' and output_mode='split' are consistent xp.testing.assert_allclose( F.concat(split_out, axis=0).array, concat_out.array, ) (concat_lstm_h, concat_lstm_c), concat_rnn_h = concat_state (split_lstm_h, split_lstm_c), split_rnn_h = split_state xp.testing.assert_allclose(concat_lstm_h.array, split_lstm_h.array) xp.testing.assert_allclose(concat_lstm_c.array, split_lstm_c.array) xp.testing.assert_allclose(concat_rnn_h.array, split_rnn_h.array) # Check if the output matches that of step-by-step execution def manual_n_step_forward(seqs_x): sorted_seqs_x = sorted(seqs_x, key=len, reverse=True) transposed_x = F.transpose_sequence(sorted_seqs_x) lstm_h = None lstm_c = None rnn_h = None ys = [] for batch in transposed_x: if lstm_h is not None: lstm_h = lstm_h[:len(batch)] lstm_c = lstm_c[:len(batch)] rnn_h = rnn_h[:len(batch)] h = linear1(batch) h = F.elu(h) h, (lstm_h, lstm_c) = _step_lstm(lstm, h, (lstm_h, lstm_c)) h = linear2(h) h, rnn_h = _step_rnn_tanh(rnn, h, rnn_h) y = F.tanh(h) ys.append(y) sorted_seqs_y = F.transpose_sequence(ys) # Undo sort seqs_y = [sorted_seqs_y[0], sorted_seqs_y[2], sorted_seqs_y[1]] return seqs_y manual_split_out = manual_n_step_forward(seqs_x) for man_seq_out, seq_out in zip(manual_split_out, split_out): xp.testing.assert_allclose( man_seq_out.array, seq_out.array, rtol=1e-5) # Finally, check the gradient (wrt linear1.W) concat_grad, = chainer.grad([F.sum(concat_out)], [linear1.W]) split_grad, = chainer.grad( [F.sum(F.concat(split_out, axis=0))], [linear1.W]) manual_split_grad, = chainer.grad( [F.sum(F.concat(manual_split_out, axis=0))], [linear1.W]) xp.testing.assert_allclose( concat_grad.array, split_grad.array, rtol=1e-5) xp.testing.assert_allclose( concat_grad.array, manual_split_grad.array, rtol=1e-5)