0

I've written a very simple, toy, chainer model:

class Upscale(chainer.Chain):
def __init__(self):
    super(Upscale, self).__init__(
        d1=L.Deconvolution2D(3, 40, 4, stride=2),
        c1=L.Convolution2D(40, 3, 4)
        )


def __call__(self, x, test=False):
    h = self.c1(self.d1(x))
    return h

I can call it and it seems to work. However, I must call it with:

model = Upscale()
...
xp = cuda.cupy
...
image = xp.zeros((1, 3, 768, 1024), dtype=xp.float32)
image[0] = load_image("foo.jpg", xp)
...
y = model(image[0:1])

For reference, load_image is:

def load_image(path, xp):
image = Image.open(path).convert('RGB')
return xp.asarray(image, dtype=xp.float32).transpose(2, 0, 1)

My model will accept an array shaped (1, 3, 768, 1024) but not an array shaped (3, 768, 1024). I do not see why this is. Alternatively, how to write a chainer model that accepts single images would help. The error I get is:

Traceback (most recent call last):
  File "upscale.py", line 92, in <module>
    main()
  File "upscale.py", line 68, in main
    y0 = model(image, test=True)
  File "upscale.py", line 21, in __call__
    h = self.c1(self.d1(x))
  File "/usr/local/lib/python2.7/dist-packages/chainer/links/connection/deconvolution_2d.py", line 116, in __call__
    deterministic=self.deterministic)
  File "/usr/local/lib/python2.7/dist-packages/chainer/functions/connection/deconvolution_2d.py", line 332, in deconvolution_2d
    return func(x, W, b)
  File "/usr/local/lib/python2.7/dist-packages/chainer/function.py", line 189, in __call__
    self._check_data_type_forward(in_data)
  File "/usr/local/lib/python2.7/dist-packages/chainer/function.py", line 273, in _check_data_type_forward
    self.check_type_forward(in_type)
  File "/usr/local/lib/python2.7/dist-packages/chainer/functions/connection/deconvolution_2d.py", line 50, in check_type_forward
    x_type.shape[1] == w_type.shape[0]
  File "/usr/local/lib/python2.7/dist-packages/chainer/utils/type_check.py", line 487, in expect
    expr.expect()
  File "/usr/local/lib/python2.7/dist-packages/chainer/utils/type_check.py", line 449, in expect
    '{0} {1} {2}'.format(left, self.inv, right))
chainer.utils.type_check.InvalidType:
Invalid operation is performed in: Deconvolution2DFunction (Forward)

Expect: in_types[0].ndim == 4
Actual: 3 != 4
desertnaut
  • 57,590
  • 26
  • 140
  • 166
Jeffrey
  • 11,063
  • 1
  • 21
  • 42

1 Answers1

0

In my environment, I confirmed following code works correctly. Please tell me result of print(image.shape), print(image[0].shape) and print(image[0:].shape). Also I want to know your chainer version.

import cupy
from PIL import Image
import chainer.links as L
import chainer


def load_image(path):
    image = Image.open(path).convert('RGB')
    return cupy.asarray(image, dtype=cupy.float32).transpose(2, 0, 1)

image = cupy.zeros((1, 3, 768, 1024), dtype=cupy.float32)
image[0] = load_image("foo.png")
print(image[0].shape)  # (3, 768, 1024)
print(image.shape)  # (1, 3, 768, 1024)
print(image[0:1].shape)  # (1, 3, 768, 1024)

class Upscale(chainer.Chain):
    def __init__(self):
        super(Upscale, self).__init__(
            d1=L.Deconvolution2D(3, 40, 4, stride=2),
            c1=L.Convolution2D(40, 3, 4)
        )


    def __call__(self, x, test=False):
        h = self.c1(self.d1(x))
        return h

model = Upscale()
model.to_gpu()
y = model(image[0:1])  # work
desertnaut
  • 57,590
  • 26
  • 140
  • 166
fukatani
  • 190
  • 6
  • I probably wasn't precise enough. But my question is: with your sample, why doesn't y = model(image[0]) work ? Chainer seems to require an array where an image would do. – Jeffrey Mar 27 '17 at 14:04
  • Most of chainer function and layer, the first dimension of input array must be the dimension of the mini-batch. Shape of input array of deconvolution layer should be (N, c, h, w). N=mini-batch size, c=channel size, h=height of image, w=width of image. If you want to input 1 image, you should construct mini-batch including 1 image. – fukatani Mar 29 '17 at 13:56
  • Ok, convention is to receive mini-batches and the extra dimension is the mini-batch. Fair enough. – Jeffrey Mar 31 '17 at 16:04