卷积运算:卷积核在输入信号(图像)上滑动,相应位置上进行乘加
卷积过程类似于用一个模板去图像上寻找与它相似的区域,与卷积核模式越相似,激活值越高,从而实现特征提取。
上图是AlexNet卷积核可视化图像,发现卷积核学习到的是边缘,条纹,色彩这一些细节模式。
# load img
path_img = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'lena.png')
img = Image.open(path_img).convert('RGB')
# convert to tensor
img_transform = transforms.Compose([transforms.ToTensor()])
img_tensor = img_transform(img)
img_tensor.unsqueeze_(dim=0) # C*H*W to B*C*H*W
# 创建卷积层
# 2d
flag = 1
# flag = 0
if flag:
conv_layer = nn.Conv2d(3, 1, 3) # input:(i, o, size)
nn.init.xavier_normal_(conv_layer.weight.data) # 正态分布初始化
# calculation
img_conv = conv_layer(img_tensor)
卷积前尺寸:torch.Size([1, 3, 512, 512])
卷积后尺寸:torch.Size([1, 1, 510, 510])
# transposed
flag = 1
# flag = 0
if flag:
conv_layer = nn.ConvTranspose2d(3, 1, 3, stride=2)
nn.init.xavier_normal_(conv_layer.weight.data)
# calculation
img_conv = conv_layer(img_tensor)
卷积前尺寸:torch.Size([1, 3, 512, 512])
卷积后尺寸:torch.Size([1, 1, 1025, 1025])
maxpool_layer = nn.MaxPool2d((2, 2), stride=(2, 2))
img_pool = maxpool_layer(img_tensor)
池化前尺寸:torch.Size([1, 3, 512, 512])
池化后尺寸:torch.Size([1, 3, 256, 256])
avgpool_layer = nn.AvgPool2d((2, 2), stride=(2, 2))
img_pool = avgpool_layer(img_tensor)
池化前尺寸:torch.Size([1, 3, 512, 512])
池化后尺寸:torch.Size([1, 3, 256, 256])
# pooling
img_tensor = torch.randint(high=5, size=(1, 1, 4, 4), dtype=torch.float)
maxpool_layer = nn.MaxPool2d((2, 2), stride=(2, 2), return_indices=True)
img_pool, indices = maxpool_layer(img_tensor) # indices为坐标信息
# unpooling
img_reconstruct = torch.randn_like(img_pool, dtype=torch.float)
maxunpool_layer = nn.MaxUnpool2d((2, 2), stride=(2, 2))
img_unpool = maxunpool_layer(img_reconstruct, indices)
执行结果:
raw_img:
tensor([[[[0., 4., 4., 3.],
[3., 3., 1., 1.],
[4., 2., 3., 4.],
[1., 3., 3., 0.]]]])
img_pool:
tensor([[[[4., 4.],
[4., 4.]]]])
img_reconstruct:
tensor([[[[-1.0276, -0.5631],
[-0.8923, -0.0583]]]])
img_unpool:
tensor([[[[ 0.0000, -1.0276, -0.5631, 0.0000],
[ 0.0000, 0.0000, 0.0000, 0.0000],
[-0.8923, 0.0000, 0.0000, -0.0583],
[ 0.0000, 0.0000, 0.0000, 0.0000]]]])
inputs = torch.tensor([[1., 2, 3]])
linear_layer = nn.Linear(3, 4)
linear_layer.weight.data = torch.tensor([[1., 1., 1.],
[2., 2., 2.],
[3., 3., 3.],
[4., 4., 4.]])
linear_layer.bias.data.fill_(0.5)
output = linear_layer(inputs)
print(inputs, inputs.shape)
print(linear_layer.weight.data, linear_layer.weight.data.shape)
print(output, output.shape)
结果为:
tensor([[1., 2., 3.]]) torch.Size([1, 3])
tensor([[1., 1., 1.],
[2., 2., 2.],
[3., 3., 3.],
[4., 4., 4.]]) torch.Size([4, 3])
tensor([[ 6.5000, 12.5000, 18.5000, 24.5000]], grad_fn=<AddmmBackward>) torch.Size([1, 4])