NNDL 实验六 卷积神经网络(1)卷积

卷积神经网络(Convolutional Neural Network,CNN)

受生物学上感受野机制的启发而提出。
一般是由卷积层、汇聚层和全连接层交叉堆叠而成的前馈神经网络
有三个结构上的特性:局部连接、权重共享、汇聚。
具有一定程度上的平移、缩放和旋转不变性。
和前馈神经网络相比,卷积神经网络的参数更少。
主要应用在图像和视频分析的任务上,其准确率一般也远远超出了其他的神经网络模型。
近年来卷积神经网络也广泛地应用到自然语言处理、推荐系统等领域。
5.1 卷积
5.1.1 二维卷积运算

5.1.2 二维卷积算子

在本书后面的实现中,算子都继承torch.nn.Layer,并使用支持反向传播的进行实现,这样我们就可以不用手工写backword()的代码实现。

import torch
import torch.nn as nn
 
class Conv2D(nn.Module):
    def __init__(self, kernel_size,
                    weight_attr=torch.tensor([[0., 1.],[2., 3.]])):
        super(Conv2D, self).__init__()
        # 使用'paddle.create_parameter'创建卷积核
        # 使用'paddle.ParamAttr'进行参数初始化
        self.weight = nn.Parameter(weight_attr)
    def forward(self, X):
        """
        输入:
            - X:输入矩阵,shape=[B, M, N],B为样本数量
        输出:
            - output:输出矩阵
        """
        u, v = self.weight.shape
        output = torch.zeros([X.shape[0], X.shape[1] - u + 1, X.shape[2] - v + 1])
        for i in range(output.shape[1]):
            for j in range(output.shape[2]):
                output[:, i, j] = torch.sum(X[:, i:i+u, j:j+v]*self.weight, axis=[1,2])
        return output
 
# 随机构造一个二维输入矩阵
torch.seed()
inputs = torch.tensor([[[1.,2.,3.],[4.,5.,6.],[7.,8.,9.]]])
 
conv2d = Conv2D(kernel_size=2)
outputs = conv2d(inputs)
print("input: {}, \noutput: {}".format(inputs, outputs))
 

输出结果: 

 

 

5.1.3 二维卷积的参数量和计算量

随着隐藏层神经元数量的变多以及层数的加深,

使用全连接前馈网络处理图像数据时,参数量会急剧增加。

如果使用卷积进行图像处理,相较于全连接前馈网络,参数量少了非常多。

5.1.4 感受野

5.1.5 卷积的变种

5.1.5.1 步长(Stride)

 

 

 


5.1.6 带步长和零填充的二维卷积算子

从输出结果看出,使用3×3大小卷积,

padding为1,

stride=1时,模型的输出特征图与输入特征图保持一致;

stride=2时,模型的输出特征图的宽和高都缩小一倍。

【使用pytorch实现】

class Conv2D(nn.Module):
    def __init__(self, kernel_size,stride=1, padding=0,
                    weight_attr=torch.tensor([[0., 1.],[2., 3.]])):
        super(Conv2D, self).__init__()
        # 使用'paddle.create_parameter'创建卷积核
        # 使用'paddle.ParamAttr'进行参数初始化
        self.weight = nn.Parameter(weight_attr)
        # 步长
        self.stride = stride
        # 零填充
        self.padding = padding
 
    def forward(self, X):
        """
        输入:
            - X:输入矩阵,shape=[B, M, N],B为样本数量
        输出:
            - output:输出矩阵
        """
        u, v = self.weight.shape
        output = torch.zeros([X.shape[0], X.shape[1] - u + 1, X.shape[2] - v + 1])
        for i in range(output.shape[1]):
            for j in range(output.shape[2]):
                output[:, i, j] = torch.sum(X[:, i:i+u, j:j+v]*self.weight, axis=[1,2])
        return output
 
# 随机构造一个二维输入矩阵
torch.seed()
inputs = torch.tensor([[[1.,2.,3.],[4.,5.,6.],[7.,8.,9.]]])
 
conv2d = Conv2D(kernel_size=2)
outputs = conv2d(inputs)
print("input: {}, \noutput: {}".format(inputs, outputs))
 
inputs = torch.randn(size=[2, 8, 8])
conv2d_padding = Conv2D(kernel_size=3, padding=1)
outputs = conv2d_padding(inputs)
print("When kernel_size=3, padding=1 stride=1, input's shape: {}, output's shape: {}".format(inputs.shape, outputs.shape))
conv2d_stride = Conv2D(kernel_size=3, stride=2, padding=1)
outputs = conv2d_stride(inputs)
print("When kernel_size=3, padding=1 stride=2, input's shape: {}, output's shape: {}".format(inputs.shape, outputs.shape))

 输出结果:


 

5.1.7 使用卷积运算完成图像边缘检测任务

【使用pytorch实现】

# 可视化结果
plt.figure(figsize=(8, 4))
f = plt.subplot(121)
f.set_title('input image', fontsize=15)
plt.imshow(img)
f = plt.subplot(122)
f.set_title('output feature map', fontsize=15)
plt.imshow(outputs.detach().squeeze(), cmap='gray')
plt.savefig('conv-vis.pdf')
plt.show()

 

 

从结果可以看出边缘轮廓十分明显, 效果很好。


选做

实现一些传统边缘检测算子,如:Roberts、Prewitt、Sobel、Scharr、Kirsch、Robinson、Laplacian

Roberts:

 Prewitt:

 

 Sobel: 

 (我看了一下大神的csdn,都导入了cv2这个包)


总结:
这次实验我了解了卷积的基本流程以及是否需要填充等问题,是对上次作业的升华。动手处理了图片,充分了解了边缘检测的原理。收获很大。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值