← 返回首页
Pytorch与nn库
发表时间:2024-01-30 15:57:00
Pytorch与nn库

PyTorch中的torch.nn模块有许多自带的函数,如全连接层,卷积层,归一化层等,都已经被封装在该模块下,可以直接使用,在编写代码的过程中十分简便。

nn是Neural Network的简称,帮助程序员方便执行如下的与神经网络相关的行为:

  1. 创建神经网络
  2. 训练神经网络
  3. 保存神经网络
  4. 恢复神经网络

1.卷积层

卷积运算:卷积核在输入信号(图像)上滑动,相应位置上进行乘加。 卷积核:又称滤波器,过滤器,可认为是某种模式,某种特征。 卷积过程:类似于用一个模板去图像上寻找与它相似的区域,与卷积核模式越相似,激活值越高,从而实现特征提取。

1).1d卷积示意

2).2d卷积示意

3).3d卷积示意

以二维卷积为例具体计算过程如下图所示:

我们发现卷积神经网络中通过输入卷积核来进行卷积操作,使输入单元(图像或特征映射)和输出单元(特征映射)之间的连接时稀疏的,能够减少需要的训练参数的数量,从而加快网络计算速度。

卷积的分类如下所示,大体分为一维卷积、二维卷积、三位卷积以及转置卷积(简单理解为卷积操作的逆操作)

以torch.nn.Conv2d()为例,我们针对一个二维图像来做卷积并观察结果:

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("carton.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,且步长为2时的最大值池化和平均值池化:

在pytorch中有多种池化的类,分别是最大值池化(MaxPool)、最大值池化的逆过程(MaxUnPool)、平均值池化(AvgPool)与自适应池化(AdaptiveMaxPool、AdaptiveAvgPool)等,且都提供了一二三维的池化操作。 如果对上一个卷积后的图像进行池化,并且使用步长为2的最大值池化或平均值池化以后,所得到的尺寸将会变为254×254。如果使用nn.AdaptiveAvgPool2d()函数,构造时可以指定其池化后的大小。池化后,特征映射的尺寸变小,图像变得更模糊。

3.torch.nn模块简介

1).nn.Parameter概述 Parameter实际上也是Tensor,也就是说是一个多维矩阵,是Variable类中的一个特殊类。 当我们创建一个model时,nn会自动创建相应的参数parameter,并会自动累加到模型的Parameter 成员列表中。

2).nn.Linear用于创建一个多输入、多输出的全连接层。其每个神经元与上一层所有神经元相连实现对前一层的线性组合,线性变换。

3).nn.functional定义了创建神经网络所需要的一些常见的处理函数。如没有激活函数的神经元,各种激活函数等。nn.functional包括神经网络前向和后向处理所需要到的常见函数。 - 神经元处理函数 - 激活函数

4).torch.nn.Module是nn中十分重要的类,包含网络各层的定义及forward方法,可以借助torch.nn.Module构建深度学习模型的类class,当面对复杂的模型,比如:多输入多输出、多分支模型、带有自定义层的模型时,需要自己来定义一个模型。

5).nn.Sequential是一个有序的容器,该类将按照传入构造器的顺序,依次创建相应的函数,并记录在Sequential类对象的数据结构中,同时以神经网络模块为元素的有序字典也可以作为传入参数。因此,Sequential可以看成是有多个函数运算对象,串联成的神经网络,其返回的是Module类型的神经网络对象。