Модель mxnet не выдает одинаковый вывод для одного и того же ввода без промежуточного градиента backprop - PullRequest
0 голосов
/ 07 декабря 2018

У меня есть некоторый опыт работы с Tensorflow, но только около недели с mxnet.Я пытаюсь понять поведение некоторого кода, когда я достигаю точки останова в функции ниже:

def train_and_eval(lr, end_date_str, pred):
    model.collect_params().initialize(mx.init.Xavier(), ctx=ctx, force_reinit=True)
    mgr      = ProcessMgr(2, end_date_str)

    for epoch in range(args_epochs):    
        for i in range(2):
            if i == TRAIN_MODE:
                mgr.switch_to_train()
            elif epoch == args_epochs - 1 and i == VALIDATE_MODE:
                mgr.switch_to_validate()
            else:
                break

            while True:
                try:
                    data, target, eval_target, date_str = mgr.get_batch()
                    data        = gluon.utils.split_and_load(data, ctx)
                    target      = gluon.utils.split_and_load(target, ctx)
                    eval_target = gluon.utils.split_and_load(eval_target, ctx)
                    data        = [mx.nd.swapaxes(d, 0, 1) for d in data]

                    with autograd.record():                    
                        losses = [loss(model(X)[-args_batch_size:], Y) for X, Y in zip(data, target)]
                        null_loss_vals = sum([Y.square().sum().asscalar() for Y in target])
                        model_loss_vals = sum([sum(l).asscalar() for l in losses])
                        null_loss[i] += null_loss_vals
                        model_loss[i] += model_loss_vals

                        **pdb.set_trace() ## BREAK POINT IS HERE**
                        if i == TRAIN_MODE:
                            for l in losses:
                                l.backward()
                            x = 18
                            grads = [i.grad(ctx) for i in model.collect_params().values() if i._grad is not None]
                            gluon.utils.clip_global_norm(grads, args_clip)
                            trainer.step(GPU_COUNT * args_batch_size)
                except:
                    print("completed an epoch")
                    break

Я получаю некоторые неожиданные значения для вычисляемых потерь, поэтому я ставлю точку останова вчтобы увидеть, что происходит.Проблема в том, что когда я запускаю одни и те же данные через модель, я каждый раз получаю разные результаты.Ниже я вставляю некоторые из выводов, которые имею, когда достигаю точки останова pdb и пытаюсь пропустить данные через model.

<NDArray 38400x1 @gpu(0)>
(Pdb) model(data[0])

[[ 2.9265028e-01]
 [ 9.3701184e-03]
 [ 4.3234527e-02]
 ...
 [-5.0668776e-09]
 [-2.7628975e-08]
 [-1.9340845e-08]]
<NDArray 38400x1 @gpu(0)>
(Pdb) model(data[0])

[[ 1.5275864e-01]
 [ 2.0615126e-01]
 [ 4.6957955e-02]
 ...
 [-2.6077061e-08]
 [-9.2040580e-09]
 [-3.2883932e-08]]
<NDArray 38400x1 @gpu(0)>
(Pdb) data[0]

[[[ 0. -4.]
  [ 0. -4.]
  [ 0. -4.]
  ...
  [ 0. -4.]
  [ 0. -4.]
  [ 0. -4.]]

 [[ 0. -4.]
  [ 0. -4.]
  [ 0. -4.]
  ...
  [ 0. -4.]
  [ 0. -4.]
  [ 0. -4.]]

 [[ 0. -4.]
  [ 0. -4.]
  [ 0. -4.]
  ...
  [ 0. -4.]
  [ 0. -4.]
  [ 0. -4.]]

 ...

 [[ 0.  0.]
  [ 0.  0.]
  [ 0.  0.]
  ...
  [ 0.  0.]
  [ 0.  0.]
  [ 0.  0.]]

 [[ 0.  0.]
  [ 0.  0.]
  [ 0.  0.]
  ...
  [ 0.  0.]
  [ 0.  0.]
  [ 0.  0.]]

 [[ 0.  0.]
  [ 0.  0.]
  [ 0.  0.]
  ...
  [ 0.  0.]
  [ 0.  0.]
  [ 0.  0.]]]
<NDArray 128x300x2 @gpu(0)>
(Pdb) data[0]

[[[ 0. -4.]
  [ 0. -4.]
  [ 0. -4.]
  ...
  [ 0. -4.]
  [ 0. -4.]
  [ 0. -4.]]

 [[ 0. -4.]
  [ 0. -4.]
  [ 0. -4.]
  ...
  [ 0. -4.]
  [ 0. -4.]
  [ 0. -4.]]

 [[ 0. -4.]
  [ 0. -4.]
  [ 0. -4.]
  ...
  [ 0. -4.]
  [ 0. -4.]
  [ 0. -4.]]

 ...

 [[ 0.  0.]
  [ 0.  0.]
  [ 0.  0.]
  ...
  [ 0.  0.]
  [ 0.  0.]
  [ 0.  0.]]

 [[ 0.  0.]
  [ 0.  0.]
  [ 0.  0.]
  ...
  [ 0.  0.]
  [ 0.  0.]
  [ 0.  0.]]

 [[ 0.  0.]
  [ 0.  0.]
  [ 0.  0.]
  ...
  [ 0.  0.]
  [ 0.  0.]
  [ 0.  0.]]]
<NDArray 128x300x2 @gpu(0)>
(Pdb) 

Я озадачен тем, что здесь происходит.Я действительно понимаю, что мой код может быть не совсем корректным в том смысле, что я ничего не выполняю в модели предсказания или вывода (планировал проверить / решить это позже), но Я не понимаю, как меняется сама моделькаждый раз, когда я запускаю ввод в модель, даже если я не запускаю backward() или trainer.step(). Любое понимание будет оценено.Почему это происходит?

Мое единственное предположение, что, возможно, скрытое состояние сохраняется между прогонами.Но я подумал, что не кодировал его, чтобы сделать это (я видел пример, где это было сделано, и скрытое состояние должно было быть явно сохранено и передано обратно в RNN).В частности, я не реализовал метод begin_state для моего gluon.Block.Я не уверен, как проверить или опровергнуть это предположение.

Вот мой глюон. Блок, реализованный на случай, если это уместно:

class RNNModel(gluon.Block):
    def __init__(self, mode, num_inputs, num_embed, num_hidden,
                 num_layers, dropout=0.5, tie_weights=False, **kwargs):
        super(RNNModel, self).__init__(**kwargs)
        with self.name_scope():
            self.drop = nn.Dropout(dropout)
            self.rnn = rnn.GRU(num_hidden, num_layers, dropout=dropout,
                               input_size=num_inputs)
            self.decoder = nn.Dense(1, in_units = num_hidden)
            self.num_hidden = num_hidden

    def forward(self, inputs):
        output = self.rnn(inputs)
        output = self.drop(output)
        decoded = self.decoder(output.reshape((-1, self.num_hidden)))
        return decoded

1 Ответ

0 голосов
/ 08 декабря 2018

Я определил, что в контексте с autograd.record() скрытое состояние должно продолжать развиваться, потому что я не видел это поведение вне этого контекста.Поскольку моя модель не предоставляет переменную, которая предоставляет скрытое состояние, я не смог проверить это явно, но это имеет смысл.Также я смог подтвердить, что выставленные веса (через trainer._params) не изменились, поэтому это должно было быть скрытое состояние.

...