赞
踩
卷积就是输入和卷积核之间的内积运算,如下图:
容易发现,卷积神经网络中通过输入卷积核来进行卷积操作,使输入单元(图像或特征映射)和输出单元(特征映射)之间的连接时稀疏的,能够减少需要的训练参数的数量,从而加快网络计算速度。
卷积的分类如下所示,大体分为一维卷积、二维卷积、三位卷积以及转置卷积(简单理解为卷积操作的逆操作)
层对应的类 | 功能作用 |
---|---|
torch.nn.Conv1d() | 针对输入信号上应用1D卷积 |
torch.nn.Conv2d() | 针对输入信号上应用2D卷积 |
torch.nn.Conv3d() | 针对输入信号上应用3D卷积 |
torch.nn.ConvTranspose1d() | 在输入信号上应用1D转置卷积 |
torch.nn.ConvTranspose2d() | 在输入信号上应用2D转置卷积 |
torch.nn.ConvTranspose3d() | 在输入信号上应用3D转置卷积 |
以torch.nn.Conv2d()为例,介绍卷积在图像上的使用方法,其调用方式为:
torch.nn.Conv2d(in_channels,outchannels,kernel_size,
stride=1,
padding=0,
dilation=1,
groups=1,
bias=True)
直接说前面三个参数吧,这三个是必选的参数,其他的参数作用可以看下面的这个文章:
torch.nn.Conv2d() 用法讲解
必选参数:
in_channels:输入的通道数目
out_channels:输出的通道数目
kernel_size:卷积核的大小,类型为int或元组,当卷积为方形时,只需要一个整形边长即可,否则要输入一个元组表示高和宽
现在我们针对一个二维图像来做卷积并观察结果:
import torch import torch.nn as nn import matplotlib.pyplot as plt import numpy as np from PIL import Image # 使用PIL包读取图像数据,使用matplotlib包来可视化图像和卷积后的结果 # 读取图像->转化为灰度图像->转化为Numpy数组 myim = Image.open("data/chap2/yier.jpg") myimgray = np.array(myim.convert("L"), dtype=np.float32) # 可视化图片 plt.figure(figsize=(6, 6)) plt.imshow(myimgray, cmap=plt.cm.gray) plt.axis("off") # plt.show() # 上述操作得到一个512×512的数组,在卷积前,需要转化为1×1×512×512的张量 imh, imw = myimgray.shape myimgray_t = torch.from_numpy(myimgray.reshape(1, 1, imh, imw)) # print(myimgray_t.shape) # 卷积时需将图像转化为四维来表示[batch,channel,h,w],卷积后得到两个特征映射: # 第一个特征映射使用图像轮廓提取卷积核获取,第二个特征映射使用的卷积核为随机数 # 卷积核大小为5×5,且不使用0填充,则卷积后输出特征映射的尺寸为508×508 # 下面进行卷积,且对卷积后的两个特征映射进行可视化 kersize = 5 # 定义边缘检测卷积核,并将维度处理为1*1*5*5 ker = torch.ones(kersize, kersize, dtype=torch.float32) * -1 ker[2, 2] = 24 ker = ker.reshape((1, 1, kersize, kersize)) # 此时ker矩阵为: # tensor([[[[-1., -1., -1., -1., -1.], # [-1., -1., -1., -1., -1.], # [-1., -1., 24., -1., -1.], # [-1., -1., -1., -1., -1.], # [-1., -1., -1., -1., -1.]]]]) # 用意还是很好理解的,如果不再边缘上,那么乘积之和就是0,否则看结果正负也容易知道边缘所在的大概位置 # 进行卷积操作 conv2d = nn.Conv2d(1, 2, (kersize, kersize), bias=False) # 设置卷积时使用的核,第一个核使用边缘检测核 conv2d.weight.data[0] = ker # 对灰度图像进行卷积操作 imconv2dout = conv2d(myimgray_t) # 对卷积后的输出进行维度压缩 imconv2dout_im = imconv2dout.data.squeeze() # print(imconv2dout_im.shape) # 可视化卷积后的图像 plt.figure(figsize=(12, 12)) plt.subplot(2, 2, 1) plt.imshow(myim) plt.axis("off") plt.subplot(2, 2, 2) plt.imshow(myimgray, cmap=plt.cm.gray) plt.axis("off") plt.subplot(2, 2, 3) plt.imshow(imconv2dout_im[0], cmap=plt.cm.gray) plt.axis("off") plt.subplot(2, 2, 4) plt.imshow(imconv2dout_im[1], cmap=plt.cm.gray) plt.axis("off") plt.show()
结果:
可以看出,使用的边缘特征提取卷积核很好地提取出了图像的边缘信息。而使用随机数的卷积核得到的卷积结果与原始图像很相似。
池化的一个重要目的是对卷积后得到的特征进行进一步处理(主要是降维),池化层可以对数据进一步浓缩,从而缓解内存压力。
池化会选取一定大小区域,将该区域内的像素值用一个代表元素表示,如下图表示滑动窗口2×2,且步长为2时的最大值池化和平均值池化:
在pytorch中有多种池化的类,分别是最大值池化(MaxPool)、最大值池化的逆过程(MaxUnPool)、平均值池化(AvgPool)与自适应池化(AdaptiveMaxPool、AdaptiveAvgPool)等,且都提供了一二三维的池化操作。
如果对上一个卷积后的图像进行池化,并且使用步长为2的最大值池化或平均值池化以后,所得到的尺寸将会变为254×254。
如果使用nn.AdaptiveAvgPool2d()函数,构造时可以指定其池化后的大小。
池化后,特征映射的尺寸变小,图像变得更模糊。
下面的一些函数感觉也都是很基础的,一些关于双曲正余弦函数、双曲正切函数、梯度的概念给搞懂了就没什么问题。
层对应的类 | 功能 |
---|---|
torch.nn.Sigmoid | Sigmoid激活函数 |
torch.nn.Tanh | Tanh激活函数 |
torch.nn.ReLU | ReLU激活函数 |
torch.nn.Softplus | ReLU激活函数的平滑近似 |
torch.nn.Sigmoid()
其对应的Sigmoid激活函数,又叫logistic激活函数:
f
(
x
)
=
1
1
+
e
−
x
f(x)=\frac{1}{1+e^{-x}}
f(x)=1+e−x1
其输出在(0,1)这个开区间内,该函数在神经网络早期也是很常用的激活函数之一,但是当输入远离坐标源点时,函数的梯度就会变得很小,几乎为0,因此会影响参数的更新速度
torch.nn.Tanh()
对应双曲正切函数:
f
(
x
)
=
e
x
−
e
−
x
e
x
+
e
−
x
f(x)=\frac{e^x-e^{-x}}{e^x+e^{-x}}
f(x)=ex+e−xex−e−x
其输出区间在(-1,1)之间,整个函数以0为中心,虽然与Sigmoid一样,当输入很大或很小时,梯度很小,不利于权重的更新,但毕竟是以0为对称,使用效果会比Sigmoid好很多
torch.nn.ReLU()
其对应的ReLU函数又叫修正线性单元,计算方式为:
f
(
x
)
=
m
a
x
(
0
,
x
)
f(x)=max(0,x)
f(x)=max(0,x)
其只保留大于0的输出。而在输入正数时,不会存在梯度饱和的问题,计算速度会更快,而且因为ReLU函数只有线性关系,所以不管是前向传播还是反向传播都很快。
torch.nn.Softplus()
对应的平滑近似ReLU的激活函数,计算公式:
f
(
x
)
=
1
β
l
o
g
(
1
+
e
β
x
)
f(x)=\frac{1}{β}log(1+e^{βx})
f(x)=β1log(1+eβx)
β默认为1。这个函数可以在任何位置求导数,且尽可能保留了ReLU函数的优点。
pytorch提供三种循环层实现:
层对应的类 | 功能 |
---|---|
torch.nn.RNN() | 多层RNN单元 |
torch.nn.LSTM() | 多层长短期记忆LSTM单元 |
torch.nn.GRU() | 多层门限循环GRU单元 |
torch.nn.RNNCell() | 一个RNN循环层单元 |
torch.nn.LSTMCell() | 一个长短期记忆LSTM单元 |
torch.nn.GRUCell() | 一个门限循环GRU单元 |
几个循环层函数的原理将在之后更新。
指一个由多个神经元所组成的层,其所有的输出和该层的所有输入都有连接,即每个输入都会影响所有神经元的输出。
在pytorch中,nn.Linear()表示线性变换,全连接层可以看作是nn.Linear()表示线性变层再加上一个激活函数层所构成的结构。
nn.Linear()全连接操作及相关参数:
torch.nn.Linear(in_features,out_features,bias=True)
参数说明如下:
in_feature:每个输入样本的特征数量
out_feature:每个输出样本的特征数量
bias:若设置为False,则该层不会设置偏置,默认为True
torch.nn.Linear()的输入为(N,in_feature)的张量,输出为(N,out_feature)的张量。
全连接层的应用广泛,只有全连接层组成的网络是全连接神经网络,可用于数据的分类或回归预测,卷积神经网络和循环神经网络的末端,通常多个连接层组成。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。