Как загрузить несколько матриц в модель Chainer, используя интерфейс итератора?
У меня есть вопрос, касающийся интерфейса итератора Chainer, и как он взаимодействует с Trainer, Updater и Model.
Мои данные представляют собой графики, и, следовательно, имеют различные формы матрицы. Я объединил матрицу признаков в одну большую плотную матрицу, матрицы смежности в одну большую разреженную матрицу COO и оператор суммирования в одну большую разреженную матрицу COO. Поскольку это сделано с молекулярными данными, у меня есть атомный граф и граф связей на образец. Следовательно, входные данные представляют собой шесть кортежей, которые для целей глубокого обучения я считаю одной большой гигантской точкой данных для обучения. (Пока я не буду работать с этой гигантской матрицей, я пока не планирую делать разделение на поезда / тесты, чтобы сохранить мой код простым.)
xs = (atom_Fs, atom_As, atom_Ss, bond_Fs, bond_As, bond_Ss)
ts = data['target'].values
dataset = [(xs, ts)]
Моя модель прямого прохода выглядит следующим образом:
# model boilerplate above this comment
def forward(self, data):
atom_feats, atom_adjs, atom_sums, bond_feats, bond_adjs, bond_sums = data
atom_feats = self.atom_mp1(atom_feats, atom_adjs)
atom_feats = self.atom_mp2(atom_feats, atom_adjs)
atom_feats = self.atom_gather(atom_feats, atom_sums)
bond_feats = self.atom_mp1(bond_feats, bond_adjs)
bond_feats = self.atom_mp2(bond_feats, bond_adjs)
bond_feats = self.atom_gather(bond_feats, bond_sums)
feats = F.hstack([atom_feats, bond_feats])
feats = F.tanh(self.dense1(feats))
feats = F.tanh(self.dense2(feats))
feats = self.dense3(feats)
return feats
Затем я передаю все в трейнер:
from chainer import iterators, training
from chainer.optimizers import SGD, Adam
iterator = iterators.SerialIterator(dataset, batch_size=1)
optimizer = Adam()
optimizer.setup(mpnn)
updater = training.updaters.StandardUpdater(iterator, optimizer)
max_epoch = 50
trainer = training.Trainer(updater, (max_epoch, 'epoch'))
trainer.run()
Однако, когда я запускаю трейнер, я получаю следующую ошибку:
Exception in main training loop: forward() takes 2 positional arguments but 3 were given
Traceback (most recent call last):
File "/home/ericmjl/anaconda/envs/mpnn/lib/python3.7/site-packages/chainer/training/trainer.py", line 315, in run
update()
File "/home/ericmjl/anaconda/envs/mpnn/lib/python3.7/site-packages/chainer/training/updaters/standard_updater.py", line 165, in update
self.update_core()
File "/home/ericmjl/anaconda/envs/mpnn/lib/python3.7/site-packages/chainer/training/updaters/standard_updater.py", line 177, in update_core
optimizer.update(loss_func, *in_arrays)
File "/home/ericmjl/anaconda/envs/mpnn/lib/python3.7/site-packages/chainer/optimizer.py", line 680, in update
loss = lossfun(*args, **kwds)
File "/home/ericmjl/anaconda/envs/mpnn/lib/python3.7/site-packages/chainer/link.py", line 242, in __call__
out = forward(*args, **kwargs)
Will finalize trainer extensions and updater before reraising the exception.
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-45-ea26cece43b3> in <module>
9 max_epoch = 50
10 trainer = training.Trainer(updater, (max_epoch, 'epoch'))
---> 11 trainer.run()
~/anaconda/envs/mpnn/lib/python3.7/site-packages/chainer/training/trainer.py in run(self, show_loop_exception_msg)
327 f.write('Will finalize trainer extensions and updater before '
328 'reraising the exception.\n')
--> 329 six.reraise(*sys.exc_info())
330 finally:
331 for _, entry in extensions:
~/anaconda/envs/mpnn/lib/python3.7/site-packages/six.py in reraise(tp, value, tb)
691 if value.__traceback__ is not tb:
692 raise value.with_traceback(tb)
--> 693 raise value
694 finally:
695 value = None
~/anaconda/envs/mpnn/lib/python3.7/site-packages/chainer/training/trainer.py in run(self, show_loop_exception_msg)
313 self.observation = {}
314 with reporter.scope(self.observation):
--> 315 update()
316 for name, entry in extensions:
317 if entry.trigger(self):
~/anaconda/envs/mpnn/lib/python3.7/site-packages/chainer/training/updaters/standard_updater.py in update(self)
163
164 """
--> 165 self.update_core()
166 self.iteration += 1
167
~/anaconda/envs/mpnn/lib/python3.7/site-packages/chainer/training/updaters/standard_updater.py in update_core(self)
175
176 if isinstance(in_arrays, tuple):
--> 177 optimizer.update(loss_func, *in_arrays)
178 elif isinstance(in_arrays, dict):
179 optimizer.update(loss_func, **in_arrays)
~/anaconda/envs/mpnn/lib/python3.7/site-packages/chainer/optimizer.py in update(self, lossfun, *args, **kwds)
678 if lossfun is not None:
679 use_cleargrads = getattr(self, '_use_cleargrads', True)
--> 680 loss = lossfun(*args, **kwds)
681 if use_cleargrads:
682 self.target.cleargrads()
~/anaconda/envs/mpnn/lib/python3.7/site-packages/chainer/link.py in __call__(self, *args, **kwargs)
240 if forward is None:
241 forward = self.forward
--> 242 out = forward(*args, **kwargs)
243
244 # Call forward_postprocess hook
TypeError: forward() takes 2 positional arguments but 3 were given
Это сбивает меня с толку, потому что я настроил набор данных так же, как пример mnist, в котором входные данные связаны с выходными данными в кортеже. Из-за слоев абстракций в Chainer, я не совсем уверен, как отладить эту проблему. У кого-нибудь есть понимание этого?
1 ответ
Ты используешь mpnn
модель, которая получает только xs
(или же data
) и выводы feats
? Я думаю, что проблема в модели, а не в итераторе или наборе данных.
Вам нужно подготовить модель, которая получает xs
а также ts
в качестве входного аргумента и рассчитать loss
в качестве вывода. Например,
class GraphNodeClassifier(chainer.Chain):
def __init__(self, mpnn):
with self.init_scope():
self.mpnn = mpnn
def forward(self, xs, ts):
feat = self.mpnn(xs)
loss = "calculate loss between `feat` and `ts` here..."
return loss
и использовать это GraphNodeClassifier
как оптимизатор setup
аргумент.
В приведенном выше примере MNIST он использует встроенный в цепочку L.Classifier
класс, который оборачивает модель MLP (которая только получает x
) получить x
а также t
рассчитать классификацию потерь.