卷积代码实现

卷积在pytorch中有两种方式,一种是torch.Conv2d(),一种是torch.nn.functional.conv2d(),这两种形式本质都是使用一个卷积操作,下面举例来说明一下这两种卷积方式

import numpy as np
import torch
from torch import nn
from torch.autograd import Variable
import torch.nn.functional as F
from PIL import Image
import matplotlib.pyplot as plt
%matplotlib inline
im=Image.open('./cat.png').convert('L') #读入一张灰度的图片
im=np.array(im,dtype='float32') #将其转换为一个矩阵

 

#将图片矩阵转化为 pytorch torch,并适配卷积输入的要求
im=torch.from_numpy(im.reshape((1,1,im.shape[0],im.shape[1])))

 下面我们定义一个算子对其进行轮廓检测

#使用nn.Conv2d
conv1 = nn.Conv2d(1,1,3,bias=False)#定义卷积
sobel_kernel=np.array([[-1,-1,-1],[-1,8,-1],[-1,-1,-1]],dtype ="float32")#定义轮廓检测算子
sobel_kernel=sobel_kernel.reshape((1,1,3,3))#适配卷积的驶入输出
conv1.weight.data=torch.from_numpy(sobel_kernel)#给卷积的kernel赋值

edge1=conv1(Variable(im))#作用在图片上
edge1=edge1.data.squeeze().numpy()#将输出转换为图片的格式

下面我们可视化边缘检测之后的结果

#使用F.conv2d
sobel_kernel = np.array([[-1,-1,-1],[-1,8,-1],[-1,-1,-1]],dtype='float32')#定义轮廓检测算子
sobel_kernel=sobel_kernel.reshape((1,1,3,3))#适配卷积的输入输出
weight = Variable(torch.from_numpy(sobel_kernel))

edge2=F.conv2d(Variable(im),weight)#作用在图片上
edge2=edge2.data.squeeze().numpy()#将输出转换为图片的格式
plt.imshow(edge2,cmap='gray')

 

可以看到两种形式能够得到相同的效果,不同的地方相信你也看到了,使用 `nn.Conv2d()` 相当于直接定义了一层卷积网络结构,而使用 `torch.nn.functional.conv2d()` 相当于定义了一个卷积的操作,所以使用后者需要再额外去定义一个 weight,而且这个 weight 也必须是一个 Variable,而使用 `nn.Conv2d()` 则会帮我们默认定义一个随机初始化的 weight,如果我们需要修改,那么取出其中的值对其修改,如果不想修改,那么可以直接使用这个默认初始化的值,非常方便

**实际使用中我们基本都使用 `nn.Conv2d()` 这种形式**

## 池化层
卷积网络中另外一个非常重要的结构就是池化,这是利用了图片的下采样不变性,即一张图片变小了还是能够看出了这张图片的内容,而使用池化层能够将图片大小降低,非常好地提高了计算效率,同时池化层也没有参数。池化的方式有很多种,比如最大值池化,均值池化等等,在卷积网络中一般使用最大值池化。

在 pytorch 中最大值池化的方式也有两种,一种是 `nn.MaxPool2d()`,一种是 `torch.nn.functional.max_pool2d()`,他们对于图片的输入要求跟卷积对于图片的输入要求是一样了,就不再赘述,下面我们也举例说明

# 使用 nn.MaxPool2d
pool1 = nn.MaxPool2d(2, 2)
print('before max pool, image shape: {} x {}'.format(im.shape[2], im.shape[3]))
small_im1 = pool1(Variable(im))
small_im1 = small_im1.data.squeeze().numpy()
print('after max pool, image shape: {} x {} '.format(small_im1.shape[0], small_im1.shape[1]))

before max pool, image shape: 224 x 224

after max pool, image shape: 112 x 112

可以看到图片的大小减小了一半,那么图片是不是变了呢?我们可以可视化一下

可以看到图片几乎没有变化,说明池化层只是减小了图片的尺寸,并不会影响图片的内容

# F.max_pool2d
print('before max pool, image shape: {} x {}'.format(im.shape[2], im.shape[3]))
small_im2 = F.max_pool2d(Variable(im), 2, 2)
small_im2 = small_im2.data.squeeze().numpy()
print('after max pool, image shape: {} x {} '.format(small_im1.shape[0], small_im1.shape[1]))
plt.imshow(small_im2, cmap='gray')

 before max pool, image shape: 224 x 224

after max pool, image shape: 112 x 1

12

**跟卷积层一样,实际使用中,我们一般使用 `nn.MaxPool2d()`** 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无咎.lsy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值