当前位置: 首页 > news >正文

一家专做灯的网站招聘大连有什么好玩的地方

一家专做灯的网站招聘,大连有什么好玩的地方,ps如何做网站导航图,保险公司网站开发李宏毅-卷积神经网络CNN 如果使用全连接层#xff1a;第一层的weight就有3*10^7个 观察 1#xff1a;检测模式不需要整张图像 很多重要的pattern只要看小范围即可 简化1#xff1a;感受野 根据观察1 可以做第1个简化#xff0c;卷积神经网络会设定一个区域#xff0c…李宏毅-卷积神经网络CNN 如果使用全连接层第一层的weight就有3*10^7个 观察 1检测模式不需要整张图像 很多重要的pattern只要看小范围即可 简化1感受野 根据观察1 可以做第1个简化卷积神经网络会设定一个区域即感受野receptive field每个神经元都只关心自己的感受野里面发生的事情 这个神经元会把3×3×3的数值“拉直”变成一个长度是3×3×327维的向量再把这27维的向量作为神经元的输入这个神经元会给27维的向量的每个维度一个权重所以这个神经元有3×3×327个权重再加上偏置bias得到输出。这个输出再送给下一层的神经元当作输入。 感受野彼此之间也可以是重叠的比如绿色的神经元的感受野跟蓝色的、黄色的神经元都有一些重叠的空间。我们没有办法检测所有的模式所以同个范围可以有多个不同的神经元即多个神经元可以去守备同一个感受野。 感受野可以有大有小因为模式有的比较小有的比较大。有的模式也许在3×3的范围内就可以被检测出来有的模式也许要11×11的范围才能被检测出来。此外感受野可以只考虑某些通道。目前感受野是RGB三个通道都考虑但也许有些模式只在红色或蓝色的通道会出现即有的神经元可以只考虑一个通道。之后在讲到网络压缩的时候会讲到这种网络的架构。感受野不仅可以是正方形的例如刚才举的例子里面3×3、11×11也可以是长方形的完全可以根据对问题的理解来设计感受野。虽然感受野可以任意设计但下面要跟大家讲一下最经典的感受野安排方式。 一般在做图像识别的时候可能不会觉得有些模式只出现在某一个通道里面所以会看全部的通道。既然会看全部的通道那么在描述一个感受野的时候只要讲它的高跟宽不用讲它的深度因为它的深度就等于通道数而高跟宽合起来叫做核大小。图4.8中的核大小就是3×3。在图像识别里面一般核大小不会设太大3×3的核大小就足够了7×7、9×9算是蛮大的核大小。如果核大小都是3×3意味着我们觉得在做图像识别的时候重要的模式都只在3×3这么小的范围内就可以被检测出来了。但有些模式也许很大也许3×3的范围没办法检测出来后面我们会再回答这个问题。常见的感受野设定方式就是核大小为3×3。 步幅是一个超参数需要人为调整。因为希望感受野跟感受野之间是有重叠的所以步幅往往不会设太大一般设为1或2。 Q:为什么希望感受野之间是有重叠的呢 A: 因为假设感受野完全没有重叠如果有一个模式正好出现在两个感受野的交界上面就没有任何神经元去检测它这个模式可能会丢失所以希望感受野彼此之间有高度的重叠。如令步幅2感受野就会重叠。 我们就按照这个方式扫过整张图像所以整张图像里面每一寸土地都是有被某一个感受野覆盖的。也就是图像里面每个位置都有一群神经元在检测那个地方有没有出现某些模式。这个是第1个简化 观察 2同样的模式可能会出现在图像的不同区域 第2个观察是同样的模式可能会出现在图像的不同区域。比如说模式鸟嘴它可能出现在图像的左上角也可能出现在图像的中间 如果不同的守备范围都要有一个检测鸟嘴的神经元参数量会太多了因此需要做出相应的简化。 简化 2共享参数 可以让不同感受野的神经元共享参数也就是做参数共享parametersharing如图4.13所示。所谓参数共享就是两个神经元的权重完全是一样的。 上面神经元跟下面神经元守备的感受野是不一样的但是它们的参数是相同的。虽然两个神经元的参数是一模一样但它们的输出不会永远都是一样的因为它们的输入是不一样的它们照顾的范围是不一样的。 因为输入不一样的关系所以就算是两个神经元共用参数它们的输出也不会是一样的。所以这是第2个简化让一些神经元可以共享参数共享的方式完全可以自己决定。接下来将介绍图像识别方面常见的共享方法是如何设定的。 每个感受野都有一组神经元在负责守备比如64个神经元它们彼此之间可以共享参数。图4.16中使用一样的颜色代表这两个神经元共享一样的参数所以每个感受野都只有一组参数就是上面感受野的第1个神经元会跟下面感受野的第1个神经元共用参数上面感受野的第2个神经元跟下面感受野的第2个神经元共用参数······ 所以每个感受野都只有一组参数而已这些参数称为滤波器filter。这是第2个简化的方法 观察 3下采样不影响模式检测 把一张比较大的图像做下采样downsampling把图像偶数的列都拿掉奇数的行都拿掉图像变成为原来的1/4但是不会影响里面是什么东西。 简化 3汇聚 根据第3个观察汇聚被用到了图像识别中。汇聚没有参数所以它不是一个层它里面没有权重它没有要学习的东西汇聚比较像Sigmoid、ReLU等激活函数。因为它里面是没有要学习的参数的它就是一个操作符operator其行为都是固定好的不需要根据数据学任何东西。 做完卷积以后往往后面还会搭配汇聚。汇聚就是把图像变小。做完卷积以后会得到一张图像这张图像里面有很多的通道。做完汇聚以后这张图像的通道不变。 一般架构就是卷积加汇聚汇聚是可有可无的很多人可能会选择不用汇聚。如图4.30所示如果做完几次卷积和汇聚以后把汇聚的输出做扁平化flatten再把这个向量丢进全连接层里面最终还要过个softmax 来得到图像识别的结果。这就是一个经典的图像识别的网络里面有卷积、汇聚和扁平化最后再通过几个全连接层或softmax 来得到图像识别的结果。 卷积神经网络的应用下围棋 除了图像识别以外卷积神经网络另外一个最常见的应用是用来下围棋以AlphaGo为例。下围棋其实是一个分类的问题网络的输入是棋盘上黑子跟白子的位置输出就是下一步应该要落子的位置。网络的输入是一个向量棋盘上有19×19 个位置可以把一个棋盘表示成一个19×19 维的向量。在这个向量里面如果某个位置有一个黑子这个位置就填1如果有白子就填-1如果没有子就填0。不一定要黑子是1白子是-1没有子就是0这只是一个可能的表示方式。通过把棋盘表示成向量网络就可以知道棋盘上的盘势。把这个向量输到一个网络里面下围棋就可以看成一个分类的问题通过网络去预测下一步应该落子的最佳位置所以下围棋就是一个有19×19个类别的分类问题网络会输出19×19个类别中的最好类别据此选择下一步落子的位置。这个问题可以用一个全连接网络来解决但用卷积神经网络的效果更好。 Q: 为什么卷积神经网络可以用在下围棋上 A: 首先一个棋盘可以看作是一个分辨率为19×19的图像。一般图像很大100×100的分辨率的图像都是很小的图像了。但是棋盘是一个更小的图像其分辨率只有19×19。这个图像里面每个像素代表棋盘上一个可以落子的位置。一般图像的通道就是RGB。而在AlphaGo 的原始论文里面每个棋盘的位置即每个棋盘上的像素是用48个通道来描述即棋盘上的每个位置都用48个数字来描述那个位置发生的事情[1]。48个数字是围棋高手设计出来的包括比如这个位置是不是要被叫吃了这个位置旁边有没有颜色不一样的等等。所以当我们用48个数字来描述棋盘上的一个位置时这个棋盘就是19×19 的分辨率的图像其通道就是48。卷积神经网络其实并不是随便用都会好的它是为图像设计的。如果一个问题跟图像没有共通的特性就不该用卷积神经网络。既然下围棋可以用卷积神经网络这意味着围棋跟图像有共同的特性。图像上的第 1 个观察是只需要看小范围就可以知道很多重要的模式。下围棋也是一样的图4.32 中的模式不用看整个棋盘的盘势就知道发生了什么事白子被黑子围住了。接下来黑子如果放在被围住的白子下面就可以把白子提走。白子如果放在白子下面被围住的白子才不会被提走。其实AlphaGo 的第1层的滤波器大小就是5×5所以显然设计这个网络的人觉得棋盘上很多重要的模式也许看5×5的范围就可以知道。此外图像上的第2个观察是同样的模式可能会出现在不同的位置在下围棋里面也是一样的。如图4.33 所示这个叫吃的模式它可以出现在棋盘上的任何位置它可以出现在左上角也可以出现在右下角所以从这个观点来看图像跟下围棋有很多共同之处。 在做图像的时候都会做汇聚一张图像做下采样以后并不会影响我们对图像中物体的判断。但汇聚对于下围棋这种精细的任务并不实用下围棋时随便拿掉一个列拿掉一个行整个棋局就不一样。AlphaGo 在 Nature 上的论文正文里面没有提它用的网络架构而是在附件中介绍了这个细节。AlphaGo 把一个棋盘看作19×19×48 大小的图像。接下来它有做零填充。它的滤波器的大小是5×5然后有k192个滤波器k的值是试出来的它也试了128、256发现 192 的效果最好。这是第1层步幅1使用了ReLU。在第2层到第12层都有做零填充。核大小都是3×3一样是k个滤波器也就是每一层都是192个滤波器步幅一样设1这样叠了很多层以后因为是一个分类的问题最后加上了一个softmax没有用汇聚所以这是一个很好的设计类神经网络的例子。在下围棋的时候不适合用汇聚。所以我们要想清楚在用一个网络架构的时候这个网络的架构到底代表什么意思它适不适合用在这个任务上。 其实卷积神经网络不能处理图像放大缩小或者是旋转的问题假设给卷积神经网络看的狗的图像大小都相同它可以识别这是一只狗。当把这个图像放大的时候它可能就不能识别这张图像是一只狗。卷积神经网络就是这么“笨”对它来说这是两张图像。虽然两张图像的形状是一模一样的但是如果把它们“拉直”成向量里面的数值就是不一样的。虽然人眼一看觉得两张图像的形状很像但对卷积神经网络来说它们是非常不一样的。所以事实上卷积神经网络并不能够处理图像放大缩小或者是旋转的问题。假设图像里面的物体都是比较小的当卷积神经网络在某种大小的图像上面学会做图像识别我们把物体放大它的性能就会降低不少卷积神经网络并没有想像的那么强。**因此在做图像识别的时候往往都要做数据增强。所谓数据增强就是把训练数据每张图像里面截一小块出来放大让卷积神经网络看过不同大小的模式把图像旋转让它看过某一个物体旋转以后长什么样子卷积神经网络才会做到好的结果。**卷积神经网络不能够处理缩放scaling跟旋转rotation的问题但Spatial Transformer Layer 网络架构可以处理这个问题。 6.1 从全连接层到卷积 此例以说明全连接层处理图片的时候会遇到参数过多 模型过大的问题 我们之前讨论的多层感知机十分适合处理表格数据其中行对应样本列对应特征。 对于表格数据我们寻找的模式可能涉及特征之间的交互但是我们不能预先假设任何与特征交互相关的先验结构。 此时多层感知机可能是最好的选择然而对于高维感知数据这种缺少结构的网络可能会变得不实用。 例如在之前猫狗分类的例子中假设我们有一个足够充分的照片数据集数据集中是拥有标注的照片每张照片具有百万级像素这意味着网络的每次输入都有一百万个维度。 即使将隐藏层维度降低到1000这个全连接层也将有10^6 * 10^3 10^9个参数。 想要训练这个模型将不可实现因为需要有大量的GPU、分布式优化训练的经验和超乎常人的耐心。 有些读者可能会反对这个观点认为要求百万像素的分辨率可能不是必要的。 然而即使分辨率减小为十万像素使用1000个隐藏单元的隐藏层也可能不足以学习到良好的图像特征在真实的系统中我们仍然需要数十亿个参数。 此外拟合如此多的参数还需要收集大量的数据。 然而如今人类和机器都能很好地区分猫和狗这是因为图像中本就拥有丰富的结构而这些结构可以被人类和机器学习模型使用。 卷积神经网络convolutional neural networksCNN是机器学习利用自然图像中一些已知结构的创造性方法。 所以说卷积是特殊的全连接层 6.2 图像卷积 总结 核矩阵和偏移是可学习的参数核矩阵的大小是超参数 互相关运算 严格来说卷积层是个错误的叫法因为它所表达的运算其实是互相关运算cross-correlation而不是卷积运算。 根据 6.1节中的描述在卷积层中输入张量和核张量通过互相关运算产生输出张量。 稍后我们将看到如何通过在图像边界周围填充零来保证有足够的空间移动卷积核从而保持输出大小不变。 接下来我们在corr2d函数中实现如上过程该函数接受输入张量X和卷积核张量K并返回输出张量Y。 import torch from torch import nn from d2l import torch as d2ldef corr2d(X, K): #save计算二维互相关运算h, w K.shapeY torch.zeros((X.shape[0] - h 1, X.shape[1] - w 1))for i in range(Y.shape[0]):for j in range(Y.shape[1]):Y[i, j] (X[i:i h, j:j w] * K).sum()return Y矩阵的哈达玛积对应位置元素的乘积然后对乘积求和 卷积层 卷积层对输入和卷积核权重进行互相关运算并在添加标量偏置之后产生输出。 所以卷积层中的两个被训练的参数是卷积核权重和标量偏置。 就像我们之前随机初始化全连接层一样在训练基于卷积层的模型时我们也随机初始化卷积核权重。 基于上面定义的corr2d函数实现二维卷积层。在__init__构造函数中将weight和bias声明为两个模型参数。前向传播函数调用corr2d函数并添加偏置。 class Conv2D(nn.Module):def __init__(self, kernel_size):super().__init__()self.weight nn.Parameter(torch.rand(kernel_size))self.bias nn.Parameter(torch.zeros(1))def forward(self, x):return corr2d(x, self.weight) self.bias高度和宽度分别为h和w的卷积核可以被称为h * w卷积或h * w卷积核。 我们也将带有h * w卷积核的卷积层称为h * w卷积层。 图像中目标的边缘检测 如下是卷积层的一个简单应用通过找到像素变化的位置来检测图像中不同颜色的边缘。 首先我们构造一个6*8像素的黑白图像。中间四列为黑色0其余像素为白色1 X torch.ones((6, 8)) X[:, 2:6] 0 X接下来我们构造一个高度为1、宽度为2的卷积核K。当进行互相关运算时如果水平相邻的两元素相同则输出为零否则输出为非零。 K torch.tensor([[1.0, -1.0]])现在我们对参数X输入和K卷积核执行互相关运算。 如下所示输出Y中的1代表从白色到黑色的边缘-1代表从黑色到白色的边缘其他情况的输出为0。 Y corr2d(X, K) Y现在我们将输入的二维图像转置再进行如上的互相关运算。 其输出如下之前检测到的垂直边缘消失了。 不出所料这个卷积核K只可以检测垂直边缘无法检测水平边缘。 corr2d(X.t(), K)学习卷积核 如果我们只需寻找黑白边缘那么以上[1, -1]的边缘检测器足以。然而当有了更复杂数值的卷积核或者连续的卷积层时我们不可能手动设计滤波器。那么我们是否可以学习由X生成Y的卷积核呢 现在让我们看看是否可以通过仅查看“输入-输出”对来学习由X生成Y的卷积核。 我们先构造一个卷积层并将其卷积核初始化为随机张量。接下来在每次迭代中我们比较Y与卷积层输出的平方误差然后计算梯度来更新卷积核。为了简单起见我们在此使用内置的二维卷积层并忽略偏置。 # 构造一个二维卷积层它具有1个输出通道和形状为12的卷积核 conv2d nn.Conv2d(1,1, kernel_size(1, 2), biasFalse)# 这个二维卷积层使用四维输入和输出格式批量大小、通道、高度、宽度 # 其中批量大小和通道数都为1 X X.reshape((1, 1, 6, 8)) Y Y.reshape((1, 1, 6, 7)) lr 3e-2 # 学习率for i in range(10):Y_hat conv2d(X)l (Y_hat - Y) ** 2conv2d.zero_grad()l.sum().backward()# 迭代卷积核conv2d.weight.data[:] - lr * conv2d.weight.gradif (i 1) % 2 0:print(fepoch {i1}, loss {l.sum():.3f})在10次迭代之后误差已经降到足够低。现在我们来看看我们所学的卷积核的权重张量。 conv2d.weight.data.reshape((1, 2))细心的读者一定会发现我们学习到的卷积核权重非常接近我们之前定义的卷积核K。 6.3 填充和步幅 卷积的输出形状取决于输入形状和卷积核的形状。 还有什么因素会影响输出的大小呢本节我们将介绍填充padding和步幅stride。假设以下情景 有时在应用了连续的卷积之后我们最终得到的输出远小于输入大小。这是由于卷积核的宽度和高度通常大于1所导致的。如此一来原始图像的边界丢失了许多有用信息。而填充是解决此问题最有效的方法 有时我们可能希望大幅降低图像的宽度和高度。例如如果我们发现原始的输入分辨率十分冗余。步幅则可以在这类情况下提供帮助。 填充 如上所述在应用多层卷积时我们常常丢失边缘像素。 由于我们通常使用小卷积核因此对于任何单个卷积我们可能只会丢失几个像素。 但随着我们应用许多连续卷积层累积丢失的像素数就多了。 解决这个问题的简单方法即为填充padding在输入图像的边界填充元素通常填充元素是0。 卷积神经网络中卷积核的高度和宽度通常为奇数例如1、3、5或7。 选择奇数的好处是保持空间维度的同时我们可以在顶部和底部填充相同数量的行在左侧和右侧填充相同数量的列。 此外使用奇数的核大小和填充大小也提供了书写上的便利。对于任何二维张量X当满足 1. 卷积核的大小是奇数 2. 所有边的填充行数和列数相同 3. 输出与输入具有相同高度和宽度 则可以得出输出Y[i, j]是通过以输入X[i, j]为中心与卷积核进行互相关计算得到的。 比如在下面的例子中我们创建一个高度和宽度为3的二维卷积层并在所有侧边填充1个像素。给定高度和宽度为8的输入则输出的高度和宽度也是8。 import torch from torch import nn# 为了方便起见我们定义了一个计算卷积层的函数。 # 此函数初始化卷积层权重并对输入和输出提高和缩减相应的维数 def comp_conv2d(conv2d, X):# 这里的11表示批量大小和通道数都是1X X.reshape((1, 1) X.shape) # 将输入张量 X 的形状从 (8, 8) 转换为 (1, 1, 8, 8)Y conv2d(X)# 省略前两个维度批量大小和通道return Y.reshape(Y.shape[2:]) # 卷积后的输出张量 Y 的形状为 (1, 1, H, W)其中 H 和 W 是输出的高度和宽度。这行代码移除了前两个维度批量大小和通道数只保留卷积输出的空间尺寸 (H, W)。# 请注意这里每边都填充了1行或1列因此总共添加了2行或2列 conv2d nn.Conv2d(1, 1, kernel_size3, padding1) X torch.rand(size(8, 8)) comp_conv2d(conv2d, X).shape卷积核kernel_size3卷积核的大小为3x3表示卷积操作会应用一个3x3的矩阵来处理输入数据。 填充padding1在进行卷积运算之前输入的每一边都填充1行和1列这样填充后输入数据的边界不会缩小。具体地输入大小从 (8, 8) 变为 (8 2, 8 2) (10, 10)。 通道数in_channels1 和 out_channels1卷积层输入和输出的通道数均为1这意味着输入和输出数据都是二维的单通道图像。 Y.shape[2:] 表示获取张量 Y 的形状shape中从第 2 维开始的所有维度。 假设 Y 的形状是 (1, 1, H, W) Y.shape[0] 是批量大小1Y.shape[1] 是通道数1Y.shape[2] 是高度HY.shape[3] 是宽度W Y.shape[2:] 就是从第 2 维开始的部分即 (H, W)。 在你的代码中Y.reshape(Y.shape[2:]) 是将 Y 的形状从 (1, 1, H, W) 变为 (H, W)从而省略掉批量大小和通道数的维度仅保留高度和宽度信息。 当卷积核的高度和宽度不同时我们可以填充不同的高度和宽度使输出和输入具有相同的高度和宽度。在如下示例中我们使用高度为5宽度为3的卷积核高度和宽度两边的填充分别为2和1。 conv2d nn.Conv2d(1, 1, kernel_size(5, 3), padding(2, 1)) comp_conv2d(conv2d, X).shape建议这么理解82-3-1) 卷积操作后输出的高度和宽度可以通过以下公式计算 步幅 在计算互相关时卷积窗口从输入张量的左上角开始向下、向右滑动。 在前面的例子中我们默认每次滑动一个元素。 但是有时候为了高效计算或是缩减采样次数卷积窗口可以跳过中间位置每次滑动多个元素。 下面我们将高度和宽度的步幅设置为2从而将输入的高度和宽度减半。 conv2d nn.Conv2d(1, 1, kernel_size3, padding1, stride2) comp_conv2d(conv2d, X).shape接下来看一个稍微复杂的例子。 conv2d nn.Conv2d(1, 1, kernel_size(3, 5), padding(0, 1), stride(3, 4)) comp_conv2d(conv2d, X).shape总结 填充和步幅是卷积层的超参数填充在输入周围添加额外的行/列来控制输出形状的减少量步幅是每次滑动核窗口时的行/列的步长可以成倍的减少输出形状 6.4 多输入多输出通道 多输入通道 当输入包含多个通道时需要构造一个与输入数据具有相同输入通道数的卷积核以便与输入数据进行互相关运算。 注意这里的输出是单通道的所以是结果相加 为了加深理解我们实现一下多输入通道互相关运算。 简而言之我们所做的就是对每个通道执行互相关操作然后将结果相加。 import torch from d2l import torch as d2ldef corr2d_multi_in(X, K):# 先遍历“X”和“K”的第0个维度通道维度再把它们加在一起return sum(d2l.corr2d(x, k) for x, k in zip(X, K))zip(X, K)X 和 K 都是多通道张量因此 zip(X, K) 会将输入张量 X 的每个通道 x 与卷积核 K 的每个通道 k 配对形成 (x, k) 的元组列表。 sum(d2l.corr2d(x, k) for x, k in zip(X, K)) 对于每一对 (x, k)执行 d2l.corr2d(x, k)即对输入通道 x 和对应的卷积核 k 进行二维互相关操作得到一个二维的输出矩阵。最后通过 sum(…) 将每个通道互相关的结果累加起来得到最终的输出。这相当于对所有通道的卷积结果求和生成一个单通道的输出。 假设输入 X 和卷积核 K 各有 3 个通道 X: (C3, H, W) K: (C3, h, w) 对应的操作为 X 的每个通道与 K 的每个通道执行 d2l.corr2d(x, k)生成 3 个二维矩阵。将这 3 个矩阵逐元素相加得到一个最终的单通道输出矩阵。 我们可以构造与 图6.4.1中的值相对应的输入张量X和核张量K以验证互相关运算的输出。 X torch.tensor([[[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]],[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]]) K torch.tensor([[[0.0, 1.0], [2.0, 3.0]], [[1.0, 2.0], [3.0, 4.0]]])corr2d_multi_in(X, K)多输出通道 到目前为止不论有多少输入通道我们还只有一个输出通道。然而正如我们在 6.1.4.1节中所讨论的每一层有多个输出通道是至关重要的。在最流行的神经网络架构中随着神经网络层数的加深我们常会增加输出通道的维数通过减少空间分辨率以获得更大的通道深度。直观地说我们可以将每个通道看作对不同特征的响应。而现实可能更为复杂一些因为每个通道不是独立学习的而是为了共同使用而优化的。因此多输出通道并不仅是学习多个单通道的检测器。 对于每一个输入把它对应的一个输出通道的核拿出来就会得到一个对应的输出通道 如下所示我们实现一个计算多个通道的输出的互相关函数。 def corr2d_multi_in_out(X, K):# 迭代“K”的第0个维度每次都对输入“X”执行互相关运算。# 最后将所有结果都叠加在一起return torch.stack([corr2d_multi_in(X, k) for k in K], 0)通过将核张量K与K1K中每个元素加1和K2连接起来构造了一个具有3个输出通道的卷积核。 K torch.stack((K, K 1, K 2), 0) K.shape下面我们对输入张量X与卷积核张量K执行互相关运算。现在的输出包含3个通道第一个通道的结果与先前输入张量X和多输入单输出通道的结果一致。 corr2d_multi_in_out(X, K)1*1卷积层 卷积的本质是有效提取相邻像素间的相关特征而11卷积显然没有此作用。 尽管如此11仍然十分流行经常包含在复杂深层网络的设计中。 因为使用了最小窗口11卷积失去了卷积层的特有能力——在高度和宽度维度上识别相邻元素间相互作用的能力。 **其实11卷积的唯一计算发生在通道上**。 图6.4.2展示了使用11卷积核与3个输入通道和2个输出通道的互相关计算。 这里输入和输出具有相同的高度和宽度输出中的每个元素都是从输入图像中同一位置的元素的线性组合。 我们可以将11卷积层看作在每个像素位置应用的全连接层以c_i个输入值转换为c_o个输出值。 因为这仍然是一个卷积层所以跨像素的权重是一致的。 同时1*1卷积层需要的权重维度为c_o * c_i再额外加上一个偏置。 下面我们使用全连接层实现1*1卷积。 请注意我们需要对输入和输出的数据形状进行调整。 def corr2d_multi_in_out_1x1(X, K):c_i, h, w X.shapec_o K.shape[0]X X.reshape((c_i, h * w))K K.reshape((c_o, c_i))# 全连接层中的矩阵乘法Y torch.matmul(K, X)return Y.reshape((c_o, h, w))当执行1*1卷积运算时上述函数相当于先前实现的互相关函数corr2d_multi_in_out。让我们用一些样本数据来验证这一点。 X torch.normal(0, 1, (3, 3, 3)) K torch.normal(0, 1, (2, 3, 1, 1))Y1 corr2d_multi_in_out_1x1(X, K) Y2 corr2d_multi_in_out(X, K) assert float(torch.abs(Y1 - Y2).sum()) 1e-6当以每像素为基础应用时1*1卷积层相当于全连接层。 1*1卷积层通常用于调整网络层的通道数量和控制模型复杂性。 6.5 汇聚层 本节将介绍汇聚pooling层它具有双重目的降低卷积层对位置的敏感性通常池化层作用在卷积层之后同时降低对空间降采样表示的敏感性。 最大汇聚层和平均汇聚层 在下面的代码中的pool2d函数我们实现汇聚层的前向传播。 这类似于 6.2节中的corr2d函数。 然而这里我们没有卷积核输出为输入中每个区域的最大值或平均值。 import torch from torch import nn from d2l import torch as d2ldef pool2d(X, pool_size, modemax):p_h, p_w pool_sizeY torch.zeros((X.shape[0] - p_h 1, X.shape[1] - p_w 1))for i in range(Y.shape[0]):for j in range(Y.shape[1]):if mode max:Y[i, j] X[i: i p_h, j: j p_w].max()elif mode avg:Y[i, j] X[i: i p_h, j: j p_w].mean()return Y我们可以构建 图6.5.1中的输入张量X验证二维最大汇聚层的输出。 X torch.tensor([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]]) pool2d(X, (2, 2))此外我们还可以验证平均汇聚层。 pool2d(X, (2, 2), avg)填充和步幅 与卷积层一样汇聚层也可以改变输出形状。和以前一样我们可以通过填充和步幅以获得所需的输出形状。 下面我们用深度学习框架中内置的二维最大汇聚层来演示汇聚层中填充和步幅的使用。 我们首先构造了一个输入张量X它有四个维度其中样本数和通道数都是1。 X torch.arange(16, dtypetorch.float32).reshape((1, 1, 4, 4)) X默认情况下深度学习框架中的步幅与汇聚窗口的大小相同。 因此如果我们使用形状为(3, 3)的汇聚窗口那么默认情况下我们得到的步幅形状为(3, 3)。 pool2d nn.MaxPool2d(3) pool2d(X)填充和步幅可以手动设定。 pool2d nn.MaxPool2d(3, padding1, stride2) pool2d(X)当然我们可以设定一个任意大小的矩形汇聚窗口并分别设定填充和步幅的高度和宽度。 pool2d nn.MaxPool2d((2, 3), stride(2, 3), padding(0, 1)) pool2d(X)多个通道 在处理多通道输入数据时汇聚层在每个输入通道上单独运算而不是像卷积层一样在通道上对输入进行汇总。 这意味着汇聚层的输出通道数与输入通道数相同。 下面我们将在通道维度上连结张量X和X 1以构建具有2个通道的输入。 X torch.cat((X, X 1), 1) X这行代码的目的是将张量 X 和 X 1 沿指定的维度拼接起来。 张量 X 假设 X 是一个形状为 (batch_size, channels, height, width) 的四维张量也就是说它是一个批量的多通道图像数据。X 1 X 1 表示对张量 X 中的每个元素加 1。假设 X 的形状是 (batch_size, channels, height, width)那么 X 1 也是相同形状的张量所有元素都增加了 1。torch.cat((X, X 1), 1) torch.cat 是 PyTorch 中用于沿指定维度拼接concat张量的函数。它的第一个参数是一个元组包含要拼接的张量第二个参数指定拼接的维度。 (X, X 1)将原始张量 X 和 X 1 拼接在一起。 1指定拼接操作在第 1 维即通道维度进行。假设 X 的形状是 (batch_size, channels, height, width)那么这个操作会在通道维度上拼接两个张量。示例 假设 X 的形状是 (batch_size1, channels3, height8, width8)即一张 8x8 大小、3 个通道的图像 X 1 也是形状为 (1, 3, 8, 8)但每个元素都比 X 的元素大 1。 torch.cat((X, X 1), 1) 会将这两个形状相同的张量在通道维度拼接生成一个形状为 (1, 6, 8, 8) 的新张量通道数变为 6。 如下所示汇聚后输出通道的数量仍然是2。 pool2d nn.MaxPool2d(3, padding1, stride2) pool2d(X)6.6 卷积神经网络LeNet 通过之前几节我们学习了构建一个完整卷积神经网络的所需组件。 回想一下之前我们将softmax回归模型 3.6节和多层感知机模型 4.2节应用于Fashion-MNIST数据集中的服装图片。 为了能够应用softmax回归和多层感知机我们首先将每个大小为28*28的图像展平为一个784维的固定长度的一维向量然后用全连接层对其进行处理。 而现在我们已经掌握了卷积层的处理方法我们可以在图像中保留空间结构。 同时用卷积层代替全连接层的另一个好处是模型更简洁、所需的参数更少。 本节将介绍LeNet它是最早发布的卷积神经网络之一因其在计算机视觉任务中的高效性能而受到广泛关注。 这个模型是由ATT贝尔实验室的研究员Yann LeCun在1989年提出的并以其命名目的是识别图像 (LeCun et al., 1998)中的手写数字。 当时Yann LeCun发表了第一篇通过反向传播成功训练卷积神经网络的研究这项工作代表了十多年来神经网络研究开发的成果。 当时LeNet取得了与支持向量机support vector machines性能相媲美的成果成为监督学习的主流方法。 LeNet被广泛用于自动取款机ATM机中帮助识别处理支票的数字。 时至今日一些自动取款机仍在运行Yann LeCun和他的同事Leon Bottou在上世纪90年代写的代码呢 LeNet 总体来看LeNetLeNet-5由两个部分组成 卷积编码器由两个卷积层组成;全连接层密集块由三个全连接层组成。 该架构如 图6.6.1所示。 先使用卷积层来学习图片空间信息然后使用全连接层来转换到类别空间 每个卷积块中的基本单元是一个卷积层、一个sigmoid激活函数和平均汇聚层。请注意虽然ReLU和最大汇聚层更有效但它们在20世纪90年代还没有出现。每个卷积层使用5*5卷积核和一个sigmoid激活函数。这些层将输入映射到多个二维特征输出通常同时增加通道的数量。第一卷积层有6个输出通道而第二个卷积层有16个输出通道。每个2*2池操作步幅2通过空间下采样将维数减少4倍。卷积的输出形状由批量大小、通道数、高度、宽度决定。 为了将卷积块的输出传递给稠密块我们必须在小批量中展平每个样本。换言之我们将这个四维输入转换成全连接层所期望的二维输入。这里的二维表示的第一个维度索引小批量中的样本第二个维度给出每个样本的平面向量表示。LeNet的稠密块有三个全连接层分别有120、84和10个输出。因为我们在执行分类任务所以输出层的10维对应于最后输出结果的数量。 通过下面的LeNet代码可以看出用深度学习框架实现此类模型非常简单。我们只需要实例化一个Sequential块并将需要的层连接在一起。 import torch from torch import nn from d2l import torch as d2lnet nn.Sequential(nn.Conv2d(1, 6, kernel_size5, padding2), nn.Sigmoid(),nn.AvgPool2d(kernel_size2, stride2),nn.Conv2d(6, 16, kernel_size5), nn.Sigmoid(),nn.AvgPool2d(kernel_size2, stride2),nn.Flatten(),nn.Linear(16 * 5 * 5, 120), nn.Sigmoid(),nn.Linear(120, 84), nn.Sigmoid(),nn.Linear(84, 10))nn.Flatten()是把 第0维的批量 保持住后面全部拉成一个向量 我们对原始模型做了一点小改动去掉了最后一层的高斯激活。除此之外这个网络与最初的LeNet-5一致。 下面我们将一个大小为28*28的单通道黑白图像通过LeNet。通过在每一层打印输出的形状我们可以检查模型以确保其操作与我们期望的 图6.6.2一致。 X torch.rand(size(1, 1, 28, 28), dtypetorch.float32) # 万一搭错了可以看到是自己哪一层输出错了 for layer in net:X layer(X)print(layer.__class__.__name__,output shape: \t,X.shape)如果有几百层的话pytorch的summary就不方便了 请注意在整个卷积块中与上一层相比每一层特征的高度和宽度都减小了。 第一个卷积层使用2个像素的填充来补偿5*5卷积核导致的特征减少。 相反第二个卷积层没有填充因此高度和宽度都减少了4个像素。 随着层叠的上升通道的数量从输入时的1个增加到第一个卷积层之后的6个再到第二个卷积层之后的16个。 同时每个汇聚层的高度和宽度都减半。最后每个全连接层减少维数最终输出一个维数与结果分类数相匹配的输出。 模型训练 现在我们已经实现了LeNet让我们看看LeNet在Fashion-MNIST数据集上的表现。 batch_size 256 train_iter, test_iter d2l.load_data_fashion_mnist(batch_sizebatch_size)虽然卷积神经网络的参数较少但与深度的多层感知机相比它们的计算成本仍然很高因为每个参数都参与更多的乘法。 通过使用GPU可以用它加快训练。 为了进行评估我们需要对 3.6节中描述的evaluate_accuracy函数进行轻微的修改。 由于完整的数据集位于内存中因此在模型使用GPU计算数据集之前我们需要将其复制到显存中。 内存RAMRandom Access Memory是计算机中用于临时存储数据的存储空间。它通常被称为主存或系统内存**。CPU 主要使用内存来存储和处理数据。当你运行程序时程序中的数据和指令会被加载到内存中以便 CPU 快速读取和处理**。“完整的数据集位于内存中” 意思是数据集暂时存储在主机计算机的 RAM 中。 显存VRAMVideo RAM是专门为 GPU图形处理单元设计的高速存储空间。显存用于存储 GPU 需要处理的数据比如神经网络模型的参数、输入数据、临时计算结果等。显存的容量一般比系统内存小通常 4GB 到 24GB 或更多但它的读写速度极快以便 GPU 高效处理图形或并行计算任务如深度学习。“我们需要将其到显存中” 指的是在进行模型的评估时我们需要将数据从主机的内存RAM转移到 GPU 的显存这样 GPU 才能直接访问数据并进行高效计算。 def evaluate_accuracy_gpu(net, data_iter, deviceNone): #save使用GPU计算模型在数据集上的精度if isinstance(net, nn.Module): # 检查 net 是否是 PyTorch 的 nn.Module 的子类net.eval() # 设置为评估模式# 如果没有提供 device 参数函数会自动获取模型参数的设备# 这样可以确保模型和数据在同一个设备上进行计算if not device:device next(iter(net.parameters())).device# 正确预测的数量总预测的数量metric d2l.Accumulator(2)with torch.no_grad(): # 在模型评估时禁用梯度计算因为我们不需要进行反向传播这样可以节省显存和计算资源for X, y in data_iter: # 遍历数据集data_iter 返回批量的输入 X 和标签 y# 数据迁移到指定设备if isinstance(X, list): # 如果 X 是一个列表# BERT微调所需的之后将介绍X [x.to(device) for x in X] # 则需要将列表中的每个元素迁移到设备上else: # 否则直接将 X 和 y 迁移到设备上X X.to(device)y y.to(device)metric.add(d2l.accuracy(net(X), y), y.numel())return metric[0] / metric[1]device next(iter(net.parameters())).device这行代码的作用是自动确定模型的设备device也就是模型参数所在的计算设备通常是 GPU 或 CPU。具体解释如下 net.parameters() net.parameters() 是 PyTorch 中的一个方法它返回一个迭代器包含模型 net 的所有参数例如权重和偏置。这些参数通常是 torch.Tensor 对象并且每个 Tensor 都存储在某个设备上如 GPU 或 CPU。iter(net.parameters()) iter() 将 net.parameters() 转换为一个迭代器。迭代器是一个对象可以用于逐个访问模型的参数。next(iter(net.parameters())) next() 函数从迭代器中获取第一个参数即模型的一个 torch.Tensor 对象。在这里它获取了模型中的第一个参数张量。.device device 是 torch.Tensor 的一个属性用于指示该张量所在的设备。设备可以是 cpu 或者 cuda:0表示 GPU。 如果模型的参数存储在 GPU 上device 会是类似 cuda:0 的值。 如果参数存储在 CPU 上device 则会是 cpu。总结 这行代码的作用是 获取模型 net 的第一个参数张量。 获取该张量所在的设备GPU 或 CPU。 将该设备存储在变量 device 中。 这允许后续代码知道模型已经加载到哪个设备如 GPU 或 CPU从而在执行操作时可以将数据加载到相同的设备上避免设备不一致导致的错误。 为了使用GPU我们还需要一点小改动。 与 3.6节中定义的train_epoch_ch3不同在进行正向和反向传播之前我们需要将每一小批量数据移动到我们指定的设备例如GPU上。 如下所示训练函数train_ch6也类似于 3.6节中定义的train_ch3。 由于我们将实现多层神经网络因此我们将主要使用高级API。 以下训练函数假定从高级API创建的模型作为输入并进行相应的优化。 我们使用在 4.8.2.2节中介绍的Xavier随机初始化模型参数。 与全连接层一样我们使用交叉熵损失函数和小批量随机梯度下降。 #save def train_ch6(net, train_iter, test_iter, num_epochs, lr, device):用GPU训练模型(在第六章定义)def init_weights(m):if type(m) nn.Linear or type(m) nn.Conv2d:nn.init.xavier_uniform_(m.weight)net.apply(init_weights)print(training on, device)net.to(device)optimizer torch.optim.SGD(net.parameters(), lrlr)loss nn.CrossEntropyLoss()animator d2l.Animator(xlabelepoch, xlim[1, num_epochs],legend[train loss, train acc, test acc])timer, num_batches d2l.Timer(), len(train_iter)for epoch in range(num_epochs):# 训练损失之和训练准确率之和样本数metric d2l.Accumulator(3)net.train()for i, (X, y) in enumerate(train_iter):timer.start()optimizer.zero_grad()X, y X.to(device), y.to(device)y_hat net(X)l loss(y_hat, y)l.backward()optimizer.step()with torch.no_grad():metric.add(l * X.shape[0], d2l.accuracy(y_hat, y), X.shape[0])timer.stop()train_l metric[0] / metric[2]train_acc metric[1] / metric[2]if (i 1) % (num_batches // 5) 0 or i num_batches - 1:animator.add(epoch (i 1) / num_batches,(train_l, train_acc, None))test_acc evaluate_accuracy_gpu(net, test_iter)animator.add(epoch 1, (None, None, test_acc))print(floss {train_l:.3f}, train acc {train_acc:.3f}, ftest acc {test_acc:.3f})print(f{metric[2] * num_epochs / timer.sum():.1f} examples/sec fon {str(device)})现在我们训练和评估LeNet-5模型。 lr, num_epochs 0.9, 10 train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())
http://www.dnsts.com.cn/news/8085.html

相关文章:

  • 兄弟网络(西安网站建设制作公司)成都推广团队
  • 北京国都建设集团网站网站搜索框怎么做
  • 模板免费下载网站ppt一键优化
  • 徐州做网站xlec小企业网站模板
  • 广州公司注册网站官网wordpress 会员下载
  • 全国建设部官方网站亚马逊雨林简介
  • 做网站链接怎么弄wordpress 充值
  • 建网站语言wordpress联系浮动
  • 九江市住房和城乡建设局网站自助建站管理平台
  • 响应式网站用什么做做游戏交易网站有哪些
  • 国内html5视频网站建设wordpress 坐标
  • jsp网站建设项目实践网站域名密码找回
  • wordpress 兼职seo推广分析关键词的第一个步骤
  • 网站优化就是seo线上做笔记的网站
  • 实验中心网站建设的调查问卷南沙网站建设wwiw
  • 网站数据库连接错误开发公司设计部工作建议
  • 藁城区建设局网站网页版微信app
  • 中国建设银行网站特色访问wap网站
  • tp框架可以做网站吗长沙网站建
  • 做网络主播网站违法吗宝塔部署wordpress
  • 免费情感网站哪个好企业为什么做网站 图片
  • 浙江网站建设企业免费下载应用软件
  • 宁波网站建设方案联系方式艺术品电商网站开发
  • 重庆响应式网站建设网络舆情案例
  • 建设行业网站大概需要都少钱网站代码制作
  • 外贸做零售的网站网站建设运营必备人员
  • 西宁市城乡规划和建设局网站无锡模板网站
  • 企业网站制作公司盈利做问卷不花钱的网站
  • 微信网站如何制作做网站网页版和手机版
  • psd转wordpress碉堡了seo博客