NNDL 作业5:卷积

目录

作业1

编程实现

作业2

 一、概念

二、探究不同卷积核的作用

三、编程实现

1、实现灰度图的边缘检测、锐化、模糊。(必做)

2、调整卷积核参数,测试并总结。(必做) 

3、使用不同尺寸图片,测试并总结。(必做) 

4、探索更多类型卷积核。(选做)

5、尝试彩色图片边缘检测。(选做)

 总结:


 

卷积常用于特征提取 

实验过程中注意认真体会“特征提取”,弄清楚为什么卷积能够提取特征。

作业1

编程实现

NNDL 作业5:卷积_第1张图片

 NNDL 作业5:卷积_第2张图片

1. 图1使用卷积核\begin{pmatrix} 1 & -1 \end{pmatrix},输出特征图

import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F
import numpy as np
#生成图片
def create_pic():
    picture = torch.Tensor([[0,0,0,255,255,255],
                      [0,0,0,255,255,255],
                      [0,0,0,255,255,255],
                      [0,0,0,255,255,255],
                      [0,0,0,255,255,255]])
    return picture
#确定卷积网络
class MyNet(torch.nn.Module):
    def __init__(self,kernel,kshape):
        super(MyNet, self).__init__()
        kernel = torch.reshape(kernel,kshape)
        self.weight = torch.nn.Parameter(data=kernel, requires_grad=False)
    def forward(self, picture):
        picture = F.conv2d(picture,self.weight,stride=1,padding=0)
        return  picture
#确定卷积层
kernel = torch.tensor([-1.0,1.0])
#更改卷积层的形状适应卷积函数
kshape = (1,1,1,2)
#生成模型
model = MyNet(kernel=kernel,kshape=kshape)
#生成图片
picture = create_pic()
#更改图片的形状适应卷积层
picture = torch.reshape(picture,(1,1,5,6))
output = model(picture)
output = torch.reshape(output,(5,5))
plt.imshow(output,cmap='gray')
plt.show()

NNDL 作业5:卷积_第3张图片

2. 图1使用卷积核\begin{pmatrix} 1\\ -1\\ \end{pmatrix},输出特征图

import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F
import numpy as np
#生成图片
def create_pic():
    picture = torch.Tensor([[0,0,0,255,255,255],
                      [0,0,0,255,255,255],
                      [0,0,0,255,255,255],
                      [0,0,0,255,255,255],
                      [0,0,0,255,255,255]])
    return picture
#确定卷积网络
class MyNet(torch.nn.Module):
    def __init__(self,kernel,kshape):
        super(MyNet, self).__init__()
        kernel = torch.reshape(kernel,kshape)
        self.weight = torch.nn.Parameter(data=kernel, requires_grad=False)
    def forward(self, picture):
        picture = F.conv2d(picture,self.weight,stride=1,padding=0)
        return  picture
#确定卷积层
kernel = torch.tensor([-1.0,1.0])
#更改卷积和的形状为转置
kshape = (1,1,2,1)
model = MyNet(kernel=kernel,kshape=kshape)
picture = create_pic()
picture = torch.reshape(picture,(1,1,5,6))
output = model(picture)
output = torch.reshape(output,(6,4))
plt.imshow(output,cmap='gray')
plt.show()

NNDL 作业5:卷积_第4张图片

3. 图2使用卷积核\begin{pmatrix} 1 & -1 \end{pmatrix},输出特征图

import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F
import numpy as np

#生成图像
def create_pic():
    picture = torch.Tensor([[0,0,0,255,255,255],
                      [0,0,0,255,255,255],
                      [0,0,0,255,255,255],
                      [255,255,255,0,0,0],
                      [255,255,255,0,0,0],
                      [255,255,255,0,0,0]])
    return picture
class MyNet(torch.nn.Module):
    def __init__(self,kernel,kshape):
        super(MyNet, self).__init__()
        kernel = torch.reshape(kernel,kshape)
        self.weight = torch.nn.Parameter(data=kernel, requires_grad=False)
    def forward(self, picture):
        picture = F.conv2d(picture,self.weight,stride=1,padding=0)
        return  picture
#确定卷积核
kernel = torch.tensor([-1.0,1.0])
kshape = (1,1,1,2)
#生成模型
model = MyNet(kernel=kernel,kshape=kshape)
picture = create_pic()
picture = torch.reshape(picture,(1,1,6,6))
print(picture)
output = model(picture)
output = torch.reshape(output,(6,5))
print(output)
plt.imshow(output,cmap='gray')
plt.show()

NNDL 作业5:卷积_第5张图片

4. 图2使用卷积核\begin{pmatrix} 1\\ -1\\ \end{pmatrix},输出特征图 

import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F
import numpy as np

#生成图像
def create_pic():
    picture = torch.Tensor([[0,0,0,255,255,255],
                      [0,0,0,255,255,255],
                      [0,0,0,255,255,255],
                      [255,255,255,0,0,0],
                      [255,255,255,0,0,0],
                      [255,255,255,0,0,0]])
    return picture
class MyNet(torch.nn.Module):
    def __init__(self,kernel,kshape):
        super(MyNet, self).__init__()
        kernel = torch.reshape(kernel,kshape)
        self.weight = torch.nn.Parameter(data=kernel, requires_grad=False)
    def forward(self, picture):
        picture = F.conv2d(picture,self.weight,stride=1,padding=0)
        return  picture
#确定卷积核
kernel = torch.tensor([-1.0,1.0])
kshape = (1,1,2,1)
model = MyNet(kernel=kernel,kshape=kshape)
picture = create_pic()
picture = torch.reshape(picture,(1,1,6,6))
print(picture)
output = model(picture)
output = torch.reshape(output,(5,6))
print(output)
plt.imshow(output,cmap='gray')
plt.show()

NNDL 作业5:卷积_第6张图片

5. 图3使用卷积核\begin{pmatrix} 1 & -1 \end{pmatrix}\begin{pmatrix} 1\\ -1\\ \end{pmatrix}\begin{pmatrix} 1 &-1 \\ -1&1 \end{pmatrix} ,输出特征图 

import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F
import numpy as np

#生成图像
def create_pic():
    picture = torch.Tensor(
                     [[255,255,255,255,255,255,255,255,255],
                      [255,0  ,255,255,255,255,255,0  ,255],
                      [255,255,0  ,255,255,255,0  ,255,255],
                      [255,255,255,0  ,255,0  ,255,255,255],
                      [255,255,255,255,0  ,255,255,255,255],
                      [255,255,255,0  ,255,0  ,255,255,255],
                      [255,255,0  ,255,255,255,0  ,255,255],
                      [255,0  ,255,255,255,255,255,0  ,255],
                      [255,255,255,255,255,255,255,255,255],])
    return picture
class MyNet(torch.nn.Module):
    def __init__(self,kernel,kshape):
        super(MyNet, self).__init__()
        kernel = torch.reshape(kernel,kshape)
        self.weight = torch.nn.Parameter(data=kernel, requires_grad=False)
    def forward(self, picture):
        picture = F.conv2d(picture,self.weight,stride=1,padding=0)
        return  picture
#生成卷积核
kernel = torch.tensor([-1.0,1.0])
#更改卷积核的形状适应卷积函数
kshape = (1,1,1,2)
model = MyNet(kernel=kernel,kshape=kshape)
picture = create_pic()
picture = torch.reshape(picture,(1,1,9,9))
print(picture)
output = model(picture)
output = torch.reshape(output,(9,8))
print(output)
plt.imshow(output,cmap='gray')
plt.show()

 NNDL 作业5:卷积_第7张图片

import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F
import numpy as np

#生成图像
def create_pic():
    picture = torch.Tensor(
                     [[255,255,255,255,255,255,255,255,255],
                      [255,0  ,255,255,255,255,255,0  ,255],
                      [255,255,0  ,255,255,255,0  ,255,255],
                      [255,255,255,0  ,255,0  ,255,255,255],
                      [255,255,255,255,0  ,255,255,255,255],
                      [255,255,255,0  ,255,0  ,255,255,255],
                      [255,255,0  ,255,255,255,0  ,255,255],
                      [255,0  ,255,255,255,255,255,0  ,255],
                      [255,255,255,255,255,255,255,255,255],])
    return picture
class MyNet(torch.nn.Module):
    def __init__(self,kernel,kshape):
        super(MyNet, self).__init__()
        kernel = torch.reshape(kernel,kshape)
        self.weight = torch.nn.Parameter(data=kernel, requires_grad=False)
    def forward(self, picture):
        picture = F.conv2d(picture,self.weight,stride=1,padding=0)
        return  picture
#生成卷积核
kernel = torch.tensor([-1.0,1.0])
kshape = (1,1,2,1)
model = MyNet(kernel=kernel,kshape=kshape)
picture = create_pic()
picture = torch.reshape(picture,(1,1,9,9))
print(picture)
output = model(picture)
output = torch.reshape(output,(8,9))
print(output)
plt.imshow(output,cmap='gray')
plt.show()

 NNDL 作业5:卷积_第8张图片

import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F
import numpy as np

#生成图像
def create_pic():
    picture = torch.Tensor(
                     [[255,255,255,255,255,255,255,255,255],
                      [255,0  ,255,255,255,255,255,0  ,255],
                      [255,255,0  ,255,255,255,0  ,255,255],
                      [255,255,255,0  ,255,0  ,255,255,255],
                      [255,255,255,255,0  ,255,255,255,255],
                      [255,255,255,0  ,255,0  ,255,255,255],
                      [255,255,0  ,255,255,255,0  ,255,255],
                      [255,0  ,255,255,255,255,255,0  ,255],
                      [255,255,255,255,255,255,255,255,255],])
    return picture
class MyNet(torch.nn.Module):
    def __init__(self,kernel,kshape):
        super(MyNet, self).__init__()
        kernel = torch.reshape(kernel,kshape)
        self.weight = torch.nn.Parameter(data=kernel, requires_grad=False)
    def forward(self, picture):
        picture = F.conv2d(picture,self.weight,stride=1,padding=0)
        return  picture
#确定卷积核
kernel = torch.tensor([[1.0,-1.0],
                       [-1.0,1.0]])
#更改卷积核的大小适配卷积函数
kshape = (1,1,2,2)
#生成网络模型
model = MyNet(kernel=kernel,kshape=kshape)
picture = create_pic()
picture = torch.reshape(picture,(1,1,9,9))
print(picture)
output = model(picture)
output = torch.reshape(output,(8,8))
print(output)
plt.imshow(output,cmap='gray')
plt.show()

 NNDL 作业5:卷积_第9张图片

作业2

 一、概念

自己的语言描述“卷积、卷积核、特征图、特征选择、步长、填充、感受野”。

  • 卷积:所谓两个函数的卷积,本质上就是先将一个函数翻转,然后进行滑动叠加。卷积的“卷”,指的的函数的翻转,从 g(t) 变成 g(-t) 的这个过程;同时,“卷”还有滑动的意味在里面。卷积的“积”,指的是积分/加权求和。
  • 卷积核: 卷积核就是图像处理时,给定输入图像,输入图像中一个小区域中像素加权平均后成为输出图像中的每个对应像素,其中权值由一个函数定义,这个函数称为卷积核
  • 特征图:比如神经网络中,卷积(函数)的作用是找特征。而且经常有多个需要找的特征。多个找出的特征就是特征图。比如一个二维的像素图,每个特征是略小于原图的二维图,特征图就是n个特征叠加的一个三维的图。
  • 特征选择:特征选择也称特征子集选择或属性选择。是指从已有的M个特征中选择N个特征使得系统的特定指标最优化,是从原始特征中选择出一些最有效特征以降低数据集维度的过程,是提高学习算法性能的一个重要手段,也是模式识别中关键的数据预处理步骤。对于一个学习算法来说,好的学习样本是训练模型的关键。
  • 步长:让一个数值在每次运算中加上某个数(此即步长)重复执行此项运算。例如对参数N的某项运算,假设步长为M,对N做一次运算,然后将 N+M 赋值给N,再用新的N值(上一步运算中的N+M)进行一次运算,如此重复。
  • 填充:填充在输入周围添加额外的行或者列,来控制输出形状的减少量;使卷积后和卷积前的图像大小相同。
  • 感受野:感受野就是卷积神经网络每一层输出的特征图上的像素点在输入图片上映射的区域大小。即特征图上的一个点对应输入图上的区域

二、探究不同卷积核的作用

数值不同:

利用该网址进行探究 Image Kernels explained visually (setosa.io)

 模糊

NNDL 作业5:卷积_第10张图片

NNDL 作业5:卷积_第11张图片

浮雕效果

NNDL 作业5:卷积_第12张图片

 锐化

NNDL 作业5:卷积_第13张图片

 底部轮廓检测

NNDL 作业5:卷积_第14张图片

 边缘检测

NNDL 作业5:卷积_第15张图片

大小不同:卷积核的大小一般有1x1,3x3和5x5的尺寸(一般是奇数x奇数)

 小卷积核优势:

一:整合了一个以上个非线性激活层,代替单一非线性激活层,增加了非线性的拟合能力。

二:减少了网络参数。以3个3*3的级联卷积代替1个7*7的卷积为例:可以减少7*7-3*3*\3=22个参数,减少了45%的参数。以2个3*3的级联卷积代替1个5*5的卷积为例:可以减少5*5-2*3*3=7个参数,减少了28%的参数。

三:减少了计算量。以3个3*3的级联卷积代替1个7*7的卷积为例:可以减少7*7*L-3*3*3*L=22*L次计算,减少了45%的计算量。以2个3*3的级联卷积代替1个5*5的卷积为例:可以减少5*5*L-2*3*3*L=7*L次计算,减少了28%的计算量。

四:有感于1*1卷积核中还可以起到对通道数的升降进行控制的作用 (达到特征降维和升维的作用)。多个小卷积核的串联是否也可以在网络结构搜索中,给通道数设置增加更多的灵活性。

基于以上几个理解所以,一般都用3作为卷积核大小。

三、编程实现

1、实现灰度图边缘检测、锐化、模糊。(必做)

import numpy as np
import torch
from torch import nn
from torch.autograd import Variable
from PIL import Image
import matplotlib.pyplot as plt
import os

os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"

plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号 #有中文出现的情况,需要u'内容
file_path = '111.jpg'
im = Image.open(file_path).convert('L')  # 读入一张灰度图的图片
im = np.array(im, dtype='float32')  # 将其转换为一个矩阵
print(im.shape[0], im.shape[1])
plt.imshow(im.astype('uint8'), cmap='gray')  # 可视化图片
plt.title('原图')
plt.show()

im = torch.from_numpy(im.reshape((1, 1, im.shape[0], im.shape[1])))
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 = np.array([[0, -1, 0],
                         [-1, 5, -1],
                         [0, -1, 0]], dtype='float32')  # 定义轮廓检测算子
'''
# 模糊
sobel_kernel = np.array([[0.0625, 0.125, 0.0625],
                         [0.125, 0.25, 0.125],
                         [0.0625, 0.125, 0.0625]], dtype='float32')

# 定义轮廓检测算子
sobel_kernel = sobel_kernel.reshape((1, 1, 3, 3))  # 适配卷积的输入输出
conv1.weight.data = torch.from_numpy(sobel_kernel)  # 给卷积的 kernel 赋值

edge1 = conv1(Variable(im))  # 作用在图片上

x = edge1.data.squeeze().numpy()


print(x.shape)  # 输出大小
plt.imshow(x, cmap='gray')
plt.show()

 NNDL 作业5:卷积_第16张图片

 边缘检测

NNDL 作业5:卷积_第17张图片

 锐化

NNDL 作业5:卷积_第18张图片

模糊

NNDL 作业5:卷积_第19张图片

2、调整卷积核参数,测试并总结。(必做) 

修改步长stride=10

NNDL 作业5:卷积_第20张图片

步长增加,提取的特征和之前相比不全面。有可能错失一些有用的特征。使图像变得模糊但但计算量会减小

加入padding=5

NNDL 作业5:卷积_第21张图片

 加入padding后图像提取的特征会更全面 但同时可能造成计算量增大

3、使用不同尺寸图片,测试并总结。(必做) 

 上图尺寸为

1056 1080
(1064, 1088)

 修改图片为

1280 727
(1278, 725)
 

边缘检测

NNDL 作业5:卷积_第22张图片

 锐化

NNDL 作业5:卷积_第23张图片

 模糊

NNDL 作业5:卷积_第24张图片

 

stride=10

 NNDL 作业5:卷积_第25张图片

 

padding=5

NNDL 作业5:卷积_第26张图片 

4、探索更多类型卷积核。(选做)

. 均值滤波和高斯滤波

NNDL 作业5:卷积_第27张图片

 

均值卷积核

NNDL 作业5:卷积_第28张图片

高斯卷积核

 NNDL 作业5:卷积_第29张图片

锐化卷积核

NNDL 作业5:卷积_第30张图片 

 

NNDL 作业5:卷积_第31张图片 

 

 

5、尝试彩色图片边缘检测。(选做)

 

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

im = Image.open('333.jpg').convert('L') # 读入一张灰度图的图片
im = np.array(im, dtype='float32') # 将其转换为一个矩阵

#print(im.shape[0],im.shape[1])     448*448
# 可视化图片
plt.imshow(im.astype('uint8'), cmap='gray')
im = torch.from_numpy(im.reshape((1, 1, im.shape[0], im.shape[1])))
conv1 = nn.Conv2d(in_channels=1,out_channels=1, kernel_size=3, bias=False,stride=1,padding=1) # 定义卷积

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() # 将输出转换为图片的格式
plt.imshow(edge1, cmap='gray')

plt.show()

NNDL 作业5:卷积_第32张图片

NNDL 作业5:卷积_第33张图片

 

 

NNDL 作业5:卷积_第34张图片

 

 总结:

这次实验对图像进行卷积操作对图像特征进行提取,了解体会了不同的卷积核对图像的影响和作用,实验过程中通过调整卷积核参数进行实验研究,不同的图片不同的操作变化有的不明显有的效果很好,通过本次实验使我对卷积核的理解更加深刻,

ref:

如何通俗易懂地解释卷积? - 马同学的回答 - 知乎 https://www.zhihu.com/question/22298352/answer/228543288

https://blog.csdn.net/program_developer/article/details/80958716

 https://blog.csdn.net/qq_41554005/article/details/107369139

https://blog.csdn.net/mrliuzhao/article/details/106011640

 

你可能感兴趣的:(深度学习,python,人工智能)