How can I pass multiple inputs to nn.Sequential(*layers)?

I’m trying to generate a network with sequential blocks and multiple inputs(images) using nn.Sequential(*layer). As I knew, nn.Sequential cannot handle multiple inputs.
In the post nn.Sequential(*layers) forward: with multiple inputs Error, they said that multiple inputs can be passed to nn.Sequential(*layer) using the dictionary, but it’s not working in my code below.

class BlkGenerator(nn.Module):
    def __init__(self, block, num_filter, num_blocks, growh_rate):
        super(BlkGenerator, self).__init__()
        self.block = self.BlockGenerator(block, num_filter, num_blocks, growh_rate)

    def BlockGenerator(self, block, num_filter, num_blocks, growh_rate):
        blocks = []

        for i in range(num_blocks):
            dblk = block(num_filter * growh_rate, kernel_size=8, stride=4, padding=2)
            blocks.append(dblk) 

        return nn.Sequential(*blocks)

    def forward(self, x1, x2):
        return self.block(x1, x2)

I passed two input images to a network using the dictionary

output = model_4ch({0:input2, 1:input2})

but, it gives an error below

File "C:\Users\shyu\Anaconda3\envs\pytorch\lib\site-packages\torch\nn\modules\module.py", line 477, in __call__
    result = self.forward(*input, **kwargs)
TypeError: forward() missing 1 required positional argument: 'x2'

How can I solve this problem?

Thanks in advance.

2 Likes

Hi there.
The error you get has nothing to do with your nn.Sequential code but is strictly Python based. Your code line output = model_4ch({0:input2, 1:input2}) sends one dict as an input to the forward function whilst you’ve defined two (both x1 and x2) inputs to the Python function.

Change your lineoutput = model_4ch({0:input2, 1:input2}) into output = model_4ch(input2, input2) (or maybe input1 input2?)

I’m pretty sure that your model can only handle one input so you’d have to combine your x1 & x2 before feeding that input to the model or feed the inputs separately. This could be done by the following code


def forward(self, x1, x2):
        inputs = torch.cat((x1, x2))
        return self.block(inputs)

or

def forward(self, x1, x2):
        output1 = self.block(x1)
        output2 = self.block(x2)
        return output1, output2

If this is not what you’re looking for, give us some more backbone to what you want to do. Gl :slight_smile:

Thanks for your reply.

I read the link again in my post and understood that he passed multiple inputs using the dictionary to two basic networks, which were defined by nn.Sequential.

I tried to feed (input1, input2) without using the dictionary and got the same error message.

In my case, I have two images having different size and want to simultaneously feed these images to a denseblock of the densenet as an input.

I searched for the solution, but there is no satisfying answer.

I found a solution to my problem.
Please check Why nn.Sequential can’t handle multiple input? and allow nn.Sequential to take multiple inputs.

I defined mySequential class and changed nn.Sequential to mySequential.
Although I don’t know exactly how it works, it makes nn.Sequential feed the multiple inputs to a network if the type of inputs is a tuple.

2 Likes

Put your multiple inputs into a tuple. (x1, x2, x3).
nn.Squential will work exactly the way you know, as it will look like you gave it one input.

In your custom layers simply unpack the tuple and if you need
multiple outputs return out1, out2, out3 as this will again become tuple.

If you want to be more pythonic about the unpacking you can surely go for creating your
custom subclass of nn.Sequential and use module(*tuple)

1 Like

It would be interesting to know if the custom mySequential supports Pipe model parallelism. Any info on that?

This is a general solution to the thread title;

class sequentialMultiInput(nn.Sequential):
	def forward(self, *inputs):
		for module in self._modules.values():
			if type(inputs) == tuple:
				inputs = module(*inputs)
			else:
				inputs = module(inputs)
		return inputs

class SubModel(nn.Module):
	def __init__(self):
		#define layers
	def forward(self, x1, x2):
		x1 = ...
		x2 = ...
		return x1, x2
		
class Model(nn.Module):
	def __init__(self):
		layers = []
		layers.append(SubModel())
		layers.append(SubModel())
		layers.append(SubModel())
		self.sequential = sequentialMultiInput(layers)
	def forward(self, x1, x2):
		x1, x2 = self.sequential(x1, x2)