Could anyone explain how a specific layer works in my model?

Could you explain how following layers in my model works? and are these substitutable in PyTorch?

Lambda(lambda x: x.view(x.size(0),-1)), # Reshape,
nn.Sequential(Lambda(lambda x: x.view(1,-1) if 1==len(x.size()) else x ),nn.Linear(3072,128)), # Linear,

Details:

I have torch7 model which have following architecture:

model: StyleNet

layers

I converted ‘stylenet.t7’ to ‘stylenet.pth’ by convert_torch_to_pytorch(GitHub),

then I got following python file:


import torch
import torch.nn as nn
import torch.legacy.nn as lnn

from functools import reduce
from torch.autograd import Variable

class LambdaBase(nn.Sequential):
    def __init__(self, fn, *args):
        super(LambdaBase, self).__init__(*args)
        self.lambda_func = fn

    def forward_prepare(self, input):
        output = []
        for module in self._modules.values():
            output.append(module(input))
        return output if output else input

class Lambda(LambdaBase):
    def forward(self, input):
        return self.lambda_func(self.forward_prepare(input))

class LambdaMap(LambdaBase):
    def forward(self, input):
        return list(map(self.lambda_func,self.forward_prepare(input)))

class LambdaReduce(LambdaBase):
    def forward(self, input):
        return reduce(self.lambda_func,self.forward_prepare(input))


stylenet = nn.Sequential( # Sequential,
	nn.Conv2d(3,64,(3, 3),(1, 1),(1, 1)),
	nn.ReLU(),
	nn.Conv2d(64,64,(3, 3),(1, 1),(1, 1)),
	nn.ReLU(),
	nn.Dropout(0.25),
	nn.MaxPool2d((4, 4),(4, 4)),
	nn.BatchNorm2d(64,0.001,0.9,True),
	nn.Conv2d(64,128,(3, 3),(1, 1),(1, 1)),
	nn.ReLU(),
	nn.Conv2d(128,128,(3, 3),(1, 1),(1, 1)),
	nn.ReLU(),
	nn.Dropout(0.25),
	nn.MaxPool2d((4, 4),(4, 4)),
	nn.BatchNorm2d(128,0.001,0.9,True),
	nn.Conv2d(128,256,(3, 3),(1, 1),(1, 1)),
	nn.ReLU(),
	nn.Conv2d(256,256,(3, 3),(1, 1),(1, 1)),
	nn.ReLU(),
	nn.Dropout(0.25),
	nn.MaxPool2d((4, 4),(4, 4)),
	nn.BatchNorm2d(256,0.001,0.9,True),
	nn.Conv2d(256,128,(1, 1)),
	nn.ReLU(),
	Lambda(lambda x: x.view(x.size(0),-1)), # Reshape,
	nn.Sequential(Lambda(lambda x: x.view(1,-1) if 1==len(x.size()) else x ),nn.Linear(3072,128)), # Linear,
)

I’m referring to last two layers.

Thank you for dealing with it.

If I am reading this right, the shape of the output of the last convolution layer will be (batch_size, 128, 6, 4).

The first lambda layer

Lambda(lambda x: x.view(x.size(0),-1)),

reshapes the output to shape (batch_size, 12864).

The second lambda layer is a no-op given that the preceding lambda reshapes the output to 2 dimensions. This lambda seems to want to create the batch dimension with size 1 if it doesn’t already exist. This seems pointless given that the preceding convolution layers require a batch dimension.

Finally the model applies the linear layer.

I think you could replace

Lambda(lambda x: x.view(x.size(0),-1)), # Reshape,
nn.Sequential(Lambda(lambda x: x.view(1,-1) if 1==len(x.size()) else x),nn.Linear(3072,128)), # Linear,

with

Lambda(lambda x: x.view(x.size(0),-1)), # Reshape,
nn.Linear(3072,128), # Linear,

and get a model that functions identically.

Thank you for explanation. Still I have two questions.

[1]

In this context, “2 dimensions” corresponds to batch_size = 2?

[2]
In my model includes lambda layers as described. Can I correctly save them by:

torch.save(model.state_dict(), "model.pth")

?

Two dimensions means that the size is a tuple containing two values, in this case the first value is the batch size and the second value is 3072.

The batch size is determined by your data loader.

Those Lambda layers have no parameters. There is nothing to save.