Search code examples
python-3.ximage-processingdeep-learningchainer

Chainer CNN- TypeError: forward() missing 1 required positional argument: 'x'


I'm trying to run a classifier on Chainer, but failed due to the following error.

I have no idea about the error, because I confirmed that the iterator actually sent a batch to the trainer.

Is there a problem with the neural network model? Or, the way the data has been fed into the model is wrong?

Input.py

from chainer.datasets import split_dataset_random
from chainer.iterators import SerialIterator
from chainer.optimizers import Adam
from chainer.training import Trainer
from chainer.training.updaters import StandardUpdater
from chainer import functions as F, links as L
from chainer import Sequential

import numpy as np

batch_size = 3

X_train = np.ones((9957, 60, 80, 3), dtype=np.float32)
X_train, _ = split_dataset_random(X_train, 8000, seed=0)
train_iter = SerialIterator(X_train, batch_size)

model = Sequential(
    L.Convolution2D(None, 64, 3, 2),
    F.relu,
    L.Convolution2D(64, 32, 3, 2),
    F.relu,
    L.Linear(None, 16),
    F.dropout,
    L.Linear(16, 4)
)

model_loss = L.Classifier(model)
optimizer = Adam()
optimizer.setup(model_loss)
updater = StandardUpdater(train_iter, optimizer)
trainer = Trainer(updater, (25, 'epoch'))

trainer.run()

Stacktrace.py

Exception in main training loop: forward() missing 1 required positional argument: 'x'
Traceback (most recent call last):
  File "/home/user/miniconda3/lib/python3.7/site-packages/chainer/training/trainer.py", line 315, in run
    update()
  File "/home/user/miniconda3/lib/python3.7/site-packages/chainer/training/updaters/standard_updater.py", line 165, in update
    self.update_core()
  File "/home/user/miniconda3/lib/python3.7/site-packages/chainer/training/updaters/standard_updater.py", line 181, in update_core
    optimizer.update(loss_func, in_arrays)
  File "/home/user/miniconda3/lib/python3.7/site-packages/chainer/optimizer.py", line 680, in update
    loss = lossfun(*args, **kwds)
  File "/home/user/miniconda3/lib/python3.7/site-packages/chainer/link.py", line 242, in __call__
    out = forward(*args, **kwargs)
  File "/home/user/miniconda3/lib/python3.7/site-packages/chainer/links/model/classifier.py", line 143, in forward
    self.y = self.predictor(*args, **kwargs)
  File "/home/user/miniconda3/lib/python3.7/site-packages/chainer/link.py", line 242, in __call__
    out = forward(*args, **kwargs)
  File "/home/user/miniconda3/lib/python3.7/site-packages/chainer/sequential.py", line 210, in forward
    x = layer(*x)
  File "/home/user/miniconda3/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.
Traceback (most recent call last):
  File "/home/user/deploy/aaa.py", line 33, in <module>
    trainer.run()
  File "/home/user/miniconda3/lib/python3.7/site-packages/chainer/training/trainer.py", line 348, in run
    six.reraise(*exc_info)
  File "/home/user/miniconda3/lib/python3.7/site-packages/six.py", line 693, in reraise
    raise value
  File "/home/user/miniconda3/lib/python3.7/site-packages/chainer/training/trainer.py", line 315, in run
    update()
  File "/home/user/miniconda3/lib/python3.7/site-packages/chainer/training/updaters/standard_updater.py", line 165, in update
    self.update_core()
  File "/home/user/miniconda3/lib/python3.7/site-packages/chainer/training/updaters/standard_updater.py", line 181, in update_core
    optimizer.update(loss_func, in_arrays)
  File "/home/user/miniconda3/lib/python3.7/site-packages/chainer/optimizer.py", line 680, in update
    loss = lossfun(*args, **kwds)
  File "/home/user/miniconda3/lib/python3.7/site-packages/chainer/link.py", line 242, in __call__
    out = forward(*args, **kwargs)
  File "/home/user/miniconda3/lib/python3.7/site-packages/chainer/links/model/classifier.py", line 143, in forward
    self.y = self.predictor(*args, **kwargs)
  File "/home/user/miniconda3/lib/python3.7/site-packages/chainer/link.py", line 242, in __call__
    out = forward(*args, **kwargs)
  File "/home/user/miniconda3/lib/python3.7/site-packages/chainer/sequential.py", line 210, in forward
    x = layer(*x)
  File "/home/user/miniconda3/lib/python3.7/site-packages/chainer/link.py", line 242, in __call__
    out = forward(*args, **kwargs)
TypeError: forward() missing 1 required positional argument: 'x'

Is there a problem with the neural network model or the way the data has been fed into the model? Please let me know if you need to see the whole code


Solution

  • All you had to do is to give a tuple of ndarray and int to the model, because this is the specification of L.Classifier.

    Is there a problem with the neural network model? Or, the way the data has been fed into the model is wrong?

    Therefore, the absolute answer is "the way the data has been fed in to the model is wrong".

    In the following code, I defined a class inheriting DatasetMixin to feed a tuple of ndarray and int. (This is a conventional way how Chainer goes)

    It should be noted that the input argument of L.Convolution2D must be an ndarray whose shape is (batch, channel, width, height). So I transpose the array in the dataset.

    Solution.py

    from chainer.datasets import split_dataset_random
    from chainer.iterators import SerialIterator
    from chainer.optimizers import Adam
    from chainer.training import Trainer
    from chainer.training.updaters import StandardUpdater
    from chainer import functions as F, links as L
    from chainer import Sequential
    
    from chainer.dataset import DatasetMixin
    
    import numpy as np
    
    
    class MyDataset(DatasetMixin):
        def __init__(self, X, labels):
            super(MyDataset, self).__init__()
            self.X_ = X
            self.labels_ = labels
            self.size_ = X.shape[0]
    
        def __len__(self):
            return self.size_
    
        def get_example(self, i):
            return np.transpose(self.X_[i, ...], (2, 0, 1)), self.labels_[i]
    
    
    batch_size = 3
    
    X_train = np.ones((9957, 60, 80, 3), dtype=np.float32)
    label_train = np.random.randint(0, 4, (9957,), dtype=np.int32)
    dataset = MyDataset(X_train, label_train)
    dataset_train, _ = split_dataset_random(dataset, 8000, seed=0)
    train_iter = SerialIterator(dataset_train, batch_size)
    
    model = Sequential(
        L.Convolution2D(None, 64, 3, 2),
        F.relu,
        L.Convolution2D(64, 32, 3, 2),
        F.relu,
        L.Linear(None, 16),
        F.dropout,
        L.Linear(16, 4)
    )
    
    model_loss = L.Classifier(model)
    optimizer = Adam()
    optimizer.setup(model_loss)
    updater = StandardUpdater(train_iter, optimizer)
    trainer = Trainer(updater, (25, 'epoch'))
    
    trainer.run()