# Can anyone explain how this output of cnn less than inp

Hi i got a code to study but when i look at the code it doesnt make sense special for out
this is code for the module

``````class Bottleneck(nn.Module):
def __init__(self, inp, oup, stride, expansion):
super(Bottleneck, self).__init__()
self.connect = stride == 1 and inp == oup
#
self.conv = nn.Sequential(
# pw
nn.Conv2d(inp, inp * expansion, 1, 1, 0, bias=False),
nn.BatchNorm2d(inp * expansion),
nn.PReLU(inp * expansion),
# nn.ReLU(inplace=True),

# dw
nn.Conv2d(inp * expansion, inp * expansion, 3, stride, 1, groups=inp * expansion, bias=False),
nn.BatchNorm2d(inp * expansion),
nn.PReLU(inp * expansion),
# nn.ReLU(inplace=True),

# pw-linear
nn.Conv2d(inp * expansion, oup, 1, 1, 0, bias=False),
nn.BatchNorm2d(oup),
)

def forward(self, x):
if self.connect:
return x + self.conv(x)
else:
return self.conv(x)
``````
``````MobiFace_bottleneck_setting = [
# t, c , n, s
[2, 64, 1, 2],
[2, 64, 2, 1],
[4, 128, 1, 2],
[2, 128, 3, 1],
[4, 256, 1, 2],
[2, 256, 6, 1]
]
``````

this is when i run this code

``````class MobiFace(nn.Module):
def __init__(self, bottleneck_setting=MobiFace_bottleneck_setting, final_linear=False):
super(MobiFace, self).__init__()
self.final_linear = final_linear

self.conv1 = ConvBlock(3, 64, 3, 2, 1)

self.dw_conv1 = ConvBlock(64, 64, 3, 1, 1, dw=True)

self.inplanes = 64
block = Bottleneck
#set_trace()

self.blocks = self._make_layer(block, bottleneck_setting)

self.conv2 = ConvBlock(256, 512, 1, 1, 0, linear=True)

self.linear1 = nn.Linear(7*7*512, 512)

self.prelu1 = nn.PReLU()

for m in self.modules():
if isinstance(m, nn.Conv2d):
n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
m.weight.data.normal_(0, math.sqrt(2. / n))
elif isinstance(m, nn.BatchNorm2d):
m.weight.data.fill_(1)
m.bias.data.zero_()

def _make_layer(self, block, setting):
layers = []
for t, c, n, s in setting:
for i in range(n):
if i == 0:
layers.append(block(self.inplanes, c, s, t))
else:
layers.append(block(self.inplanes, c, 1, t))
self.inplanes = c

return nn.Sequential(*layers)

def forward(self, x):
x = self.conv1(x)
x = self.dw_conv1(x)

x = self.blocks(x)
x = self.conv2(x)
x = x.view(x.size(0), -1)
x = self.linear1(x)
if self.final_linear is False:
x = self.prelu1(x)

return x
``````

so print the layer

``````if __name__ == "__main__":
input = Variable(torch.FloatTensor(2, 3, 112, 96))
net = MobiFace()
print(net)
``````
``````MobiFace(
(conv1): ConvBlock(
(conv): Conv2d(3, 64, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
(bn): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(prelu): PReLU(num_parameters=64)
)
(dw_conv1): ConvBlock(
(conv): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=64, bias=False)
(bn): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(prelu): PReLU(num_parameters=64)
)
(blocks): Sequential(
(0): Bottleneck(
(conv): Sequential(
(0): Conv2d(64, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
(1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(2): PReLU(num_parameters=128)
(3): Conv2d(128, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), groups=128, bias=False)
(4): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(5): PReLU(num_parameters=128)
(6): **Conv2d(128, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)**
(7): **BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)**
``````

can anyone explain to me how does the conv2d input is 128 in (6) it reduce to 64 at the end how is this happen?

Your `Bottleneck` layer defines:

``````# pw-linear
nn.Conv2d(inp * expansion, oup, 1, 1, 0, bias=False),
nn.BatchNorm2d(oup),
``````

where at the `oup` is set to 64, which creates the last conv and batchnorm layer in the first `Bottleneck` as:

``````(6): Conv2d(128, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
(7): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
``````

ok thank you that make sense now but just wonder how does oup be less than inp is this mean the layer deleter channel?

The number of output channels is defined by the number of filters in the layer.
In the default setup each filter will use all input channels and create a single output channel.
Multiple filters define the complete activation output.
CS231n - Convolution layer explains the logic pretty well.

thnk you so much will check it out

and can you explain what is the n value in # t, c , n, s been try to understand it but only that part im not quite sure what is it for

`n` is used in the loop:

``````for i in range(n):
``````

to create multiple layers.
As you can see in the final model `blocks` will contain 14 `Bottleneck` modules, which corresponds to the values of `n` in the setting (1+2+1+3+1+6=14).