最近在自学深度学习,由于之前有一些不采用机器学习的图像处理经验,现在说说自己对深度学习的一点理解。
池化层
池化层分为平均池化和最大池化,意为当输入数据做出少量平移时,经过池化函数后的大多数输出还能保持不变。
个人认为所谓平均池化很类似图像处理中的均值滤波。都是取卷积核内部的平均值作为特征图的输出。而最大池化个人感觉类似中值滤波,只不过将滤波器的中值部分换为了最大值部分。
现在有疑问,如果我的上述感觉是正确的那为什么要区分卷积层与池化层呢?感觉池化层就是一个已经确定好权重的卷积操作。
自定义卷积核
在pytorch搭建起网络时,大家通常都使用已有的框架进行训练,在网络中使用最多就是卷积操作,最熟悉不过的就是:torch.nn.conv2Dpytorch封装在torch.nn里的Conv2d非常好用,然而其卷积核的权重都是需要学习的参数,如果想要自定义一个卷积核(比如高斯核)来提取图像特征,conv2d就不适用了。
而解决方案如下:
pytorch自带的卷积操作:torch.nn.functional.conv2d()
这个卷积核与nn.Conv2d不同,它的weight可以自己设定。好处是,你既可以把各项参数写死在里面,不让它求导,也可以当成可学习参数,反向传播有pytorch来自动实现;并且,由于这是pytorch自带的,在训练中也不需要我们去考虑batch维度,数据格式采用torch tensor,方便得很。还有一个好处是,它可以像普通cnn的卷积核一样操作,有4个维度,分别是输出通道,输入通道,卷积核高,卷积核宽,这样可以很方便地把自定义的卷积核写成一个卷积层。具体操作为:
nn.functinoal.conv2d(inputs, weight, bias, padding=1)
具体例:
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.conv_1_weight = nn.Parameter(torch.randn(16, 1, 5, 5))
self.bias_1_weight = nn.Parameter(torch.randn(16))
self.conv_2_weight = nn.Parameter(torch.randn(32, 16, 5, 5))
self.bias_2_weight = nn.Parameter(torch.randn(32))
self.linear_weight = nn.Parameter(torch.randn(4 * 4 * 32, 10))
self.bias_weight = nn.Parameter(torch.randn(10))
def forward(self, x):
x = x.view(x.size(0), -1)
out = F.conv2d(x, self.conv_1_weight, self.bias_1_weight)
out = F.conv2d(out, self.conv_2_weight, self.bias_2_weight)
out = F.linear(out.view(x.size(0), -1), self.linear_weight, self.bias_weight
以上为自定义卷积核操作