For each out_channel, you have a set of kernels for each in_channel.
Equivalently, each out_channel has an in_channel x height x width kernel:
for i in nn.Conv2d(in_channels=2, out_channels=3, kernel_size=(4, 5)).parameters():
print(i)
Output:
Parameter containing:
tensor([[[[-0.0012, 0.0848, -0.1301, -0.1164, -0.0609],
[ 0.0424, -0.0031, 0.1254, -0.0140, 0.0418],
[-0.0478, -0.0311, -0.1511, -0.1047, -0.0652],
[ 0.0059, 0.0625, 0.0949, -0.1072, -0.0689]],
[[ 0.0574, 0.1313, -0.0325, 0.1183, -0.0255],
[ 0.0167, 0.1432, -0.1467, -0.0995, -0.0400],
[-0.0616, 0.1366, -0.1025, -0.0728, -0.1105],
[-0.1481, -0.0923, 0.1359, 0.0706, 0.0766]]],
[[[ 0.0083, -0.0811, 0.0268, -0.1476, -0.1142],
[-0.0815, 0.0998, 0.0927, -0.0701, -0.0057],
[ 0.1011, 0.1572, 0.0628, 0.0214, 0.1060],
[-0.0931, 0.0295, -0.1226, -0.1096, -0.0817]],
[[ 0.0715, 0.0636, -0.0937, 0.0478, 0.0868],
[-0.0200, 0.0060, 0.0366, 0.0981, 0.1518],
[-0.1218, -0.0579, 0.0621, 0.1310, 0.1376],
[ 0.1395, 0.0315, -0.1375, 0.0145, -0.0989]]],
[[[-0.1474, 0.1405, 0.1202, -0.1577, 0.0296],
[-0.0266, -0.0260, -0.0724, 0.0608, -0.0937],
[ 0.0580, 0.0800, 0.1132, 0.0591, -0.1565],
[-0.1026, 0.0789, 0.0331, -0.1233, -0.0910]],
[[ 0.1487, 0.1065, -0.0689, -0.0398, -0.1506],
[-0.0028, -0.1191, -0.1220, -0.0087, 0.0237],
[-0.0648, 0.0938, -0.0962, 0.1435, 0.1084],
[-0.1333, -0.0394, 0.0071, 0.0231, 0.0375]]]], requires_grad=True)
Parameter containing:
tensor([ 0.0620, 0.0095, -0.0771], requires_grad=True)
A more detailed example going from 1 channel input, through 2 and 4 channel convolutions:
import torch
torch.manual_seed(0)
input0 = torch.randint(-1, 1, (1, 1, 8, 8)).type(torch.FloatTensor)
print('input0:', input0.size())
print(input0.data)
layer0 = nn.Conv2d(in_channels=1, out_channels=2, kernel_size=2, stride=2, padding=0, bias=False)
print('\nlayer1:')
for i in layer0.parameters():
print(i.size())
i.data = torch.randint(-1, 1, i.size()).type(torch.FloatTensor)
print(i.data)
output0 = layer0(input0)
print('\noutput0:', output0.size())
print(output0.data)
print('\nlayer1:')
layer1 = nn.Conv2d(in_channels=2, out_channels=4, kernel_size=2, stride=2, padding=0, bias=False)
for i in layer1.parameters():
print(i.size())
i.data = torch.randint(-1, 1, i.size()).type(torch.FloatTensor)
print(i.data)
output1 = layer1(output0)
print('\noutput1:', output1.size())
print(output1.data)
output:
input0: torch.Size([1, 1, 8, 8])
tensor([[[[-1., 0., 0., -1., 0., 0., 0., 0.],
[ 0., 0., 0., -1., -1., 0., -1., -1.],
[-1., -1., -1., 0., -1., 0., 0., -1.],
[-1., 0., 0., 0., 0., -1., 0., -1.],
[ 0., -1., 0., 0., -1., 0., 0., -1.],
[-1., 0., -1., 0., 0., 0., 0., 0.],
[-1., 0., -1., 0., 0., 0., 0., -1.],
[ 0., -1., -1., 0., 0., -1., 0., -1.]]]])
layer1:
torch.Size([2, 1, 2, 2])
tensor([[[[-1., -1.],
[-1., 0.]]],
[[[ 0., -1.],
[ 0., -1.]]]])
output0: torch.Size([1, 2, 4, 4])
tensor([[[[1., 1., 1., 1.],
[3., 1., 1., 1.],
[2., 1., 1., 1.],
[1., 2., 0., 1.]],
[[0., 2., 0., 1.],
[1., 0., 1., 2.],
[1., 0., 0., 1.],
[1., 0., 1., 2.]]]])
layer1:
torch.Size([4, 2, 2, 2])
tensor([[[[-1., -1.],
[-1., -1.]],
[[ 0., -1.],
[ 0., -1.]]],
[[[ 0., 0.],
[ 0., 0.]],
[[ 0., -1.],
[ 0., 0.]]],
[[[ 0., 0.],
[-1., 0.]],
[[ 0., -1.],
[-1., 0.]]],
[[[-1., -1.],
[-1., -1.]],
[[ 0., 0.],
[-1., -1.]]]])
output1: torch.Size([1, 4, 2, 2])
tensor([[[[-8., -7.],
[-6., -6.]],
[[-2., -1.],
[ 0., -1.]],
[[-6., -3.],
[-2., -2.]],
[[-7., -7.],
[-7., -6.]]]])
Breaking down the linear algebra:
np.sum(
# kernel for layer1, in_channel 0, out_channel 0
# multiplied by output0, channel 0, top left corner
(np.array([[-1., -1.],
[-1., -1.]]) * \
np.array([[1., 1.],
[3., 1.]])) + \
# kernel for layer1, in_channel 1, out_channel 0
# multiplied by output0, channel 1, top left corner
(np.array([[ 0., -1.],
[ 0., -1.]]) * \
np.array([[0., 2.],
[1., 0.]]))
)
This will be equal to output1, channel 0, top left corner:
-8.0
[Batch, 64,64,128]
and we again use64
kernals of size3x3
, How does this kernel transforms the feature maps? I mean with 1 channel , I can understand that 6 different kernels produces 6 different feature maps but with the shape as above, how do you intend to do that? – Nucleolus