做网站工作内容阿里云服务器安装wordpress

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

做网站工作内容,阿里云服务器安装wordpress,如何减少网站建设中的错误,模拟建筑4本期内容是针对神经网络层结构的一个补充#xff0c;主要内容是#xff1a;转置卷积和全连接卷积网络 相关内容#xff1a; 由浅入深#xff0c;走进深度学习#xff08;2#xff09;_卷积层-CSDN博客 由浅入深#xff0c;走进深度学习#xff08;补充篇#xff1a…本期内容是针对神经网络层结构的一个补充主要内容是转置卷积和全连接卷积网络 相关内容 由浅入深走进深度学习2_卷积层-CSDN博客 由浅入深走进深度学习补充篇神经网络结构层基础-CSDN博客 由浅入深走进深度学习补充篇神经网络基础-CSDN博客 目录 转置卷积 填充、步幅和多通道 全连接卷积神经网络 正片开始 转置卷积 卷积不会增大输入的高宽  通常要么不变  要么减半 转置卷积则可以用来增大输入高宽 import torch from torch import nn from d2l import torch as d2l# 实现基本的转置卷积运算

定义转置卷积运算

def trans_conv(X, K):# 获取卷积核的宽度和高度h, w K.shape # 卷积核的宽、高# 创建一个新的张量Y 其尺寸为输入X的尺寸加上卷积核K的尺寸减去1 在常规卷积中 输出尺寸通常是输入尺寸减去卷积核尺寸加1Y torch.zeros((X.shape[0] h -1, X.shape[1] w - 1)) # 正常的卷积后尺寸为(X.shape[0] - h 1, X.shape[1] - w 1) # 遍历输入张量X的每一行for i in range(X.shape[0]):# 遍历输入张量X的每一列for j in range(X.shape[1]):# 对于输入X的每一个元素 我们将其与卷积核K进行元素级别的乘法 然后将结果加到输出张量Y的相应位置上Y[i:i h, j:j w] X[i, j] * K # 按元素乘法 加回到自己矩阵# 返回转置卷积的结果return Y# 验证上述实现输出

定义输入张量X 这是一个2x2的矩阵

X torch.tensor([[0.0, 1.0],[2.0, 3.0]])

定义卷积核K 也是一个2x2的矩阵

K torch.tensor([[0.0, 1.0],[2.0, 3.0]])

调用上面定义的trans_conv函数 对输入张量X和卷积核K进行转置卷积操作 并打印结果

trans_conv(X, K)# 使用高级API获得相同的结果

将输入张量X和卷积核K进行形状变换 原来是2x2的二维张量 现在变成了1x1x2x2的四维张量

第一个1表示批量大小 第二个1表示通道数 2x2是卷积核的高和宽

X, K X.reshape(1, 1, 2, 2), K.reshape(1, 1, 2, 2)

创建一个转置卷积层对象tconv 其中输入通道数为1 输出通道数为1 卷积核的大小为2 没有偏置项

tconv nn.ConvTranspose2d(1, 1, kernel_size 2, bias False) # 输入通道数为1 输出通道数为1

将创建的转置卷积层对象tconv的权重设置为我们的卷积核K

tconv.weight.data K

使用创建的转置卷积层tconv对输入张量X进行转置卷积操作 并返回结果

tconv(X) 填充、步幅和多通道 填充在输出上  padding1  之前输出3x3  现在上下左右都填充了1  那就剩下中心那个元素了 填充为1  就是把输出最外面的一圈当作填充 创建一个转置卷积层对象tconv  其中输入通道数为1  输出通道数为1  卷积核的大小为2  没有偏置项  同时设置填充大小为1   填充(padding)操作在输出上执行  原本输出为3x3  由于填充了大小为1的边框  结果就只剩下中心的元素    所以填充大小为1就相当于将输出矩阵最外面的一圈当作填充并剔除 tconv nn.ConvTranspose2d(1, 1, kernel_size 2, padding 1, bias False)

将创建的转置卷积层对象tconv的权重设置为我们的卷积核K

tconv.weight.data K

使用创建的转置卷积层tconv对输入张量X进行转置卷积操作 并返回结果

tconv(X)# 创建一个转置卷积层对象tconv 其中输入通道数为1 输出通道数为1 卷积核的大小为2 步幅(stride)为2 没有偏置项

步幅为2表示在进行卷积时 每次移动2个单位 相较于步幅为1 这样会使得输出尺寸增大

tconv nn.ConvTranspose2d(1, 1, kernel_size 2, stride 2, bias False)

将创建的转置卷积层对象tconv的权重设置为我们的卷积核K

tconv.weight.data K

使用创建的转置卷积层tconv对输入张量X进行转置卷积操作 并返回结果

tconv(X)# 多通道

创建一个四维张量X 批量大小为1 通道数为10 高和宽都为16

X torch.rand(size (1, 10, 16, 16))

创建一个二维卷积层对象conv 其中输入通道数为10 输出通道数为20 卷积核大小为5 填充为2 步幅为3

这会将输入的10个通道的图像转换为20个通道的特征图

conv nn.Conv2d(10, 20, kernel_size 5, padding 2, stride 3)

创建一个转置卷积层对象tconv 其中输入通道数为20 输出通道数为10 卷积核大小为5 填充为2 步幅为3

这会将输入的20个通道的特征图转换回10个通道的图像

tconv nn.ConvTranspose2d(20, 10, kernel_size 5, padding 2, stride 3)

首先对输入张量X进行卷积操作 然后再对卷积的结果进行转置卷积操作

然后检查这个结果的形状是否和原始输入张量X的形状相同

如果相同 说明转置卷积操作成功地还原了原始输入的形状

tconv(conv(X)).shape X.shape# 与矩阵变换的联系

创建一个一维张量 其中包含从0.0到8.0的连续数字

然后将这个一维张量重塑为3x3的二维张量

X torch.arange(9.0).reshape(3, 3)

创建一个2x2的卷积核K 其中包含四个元素1.02.03.04.0

K torch.tensor([[1.0, 2.0],[3.0, 4.0]])

使用自定义的二维卷积函数corr2d对输入张量X和卷积核K进行卷积操作

corr2d函数需要在引入d2l深度学习库之后才能使用

Y d2l.corr2d(X, K) # 卷积

打印卷积操作的结果

Y# 定义一个函数kernel2matrix 用于将给定的卷积核K转换为一个稀疏矩阵W def kernel2matrix(K):# 创建长度为5的零向量k和4x9的零矩阵Wk, W torch.zeros(5), torch.zeros((4,9))# 打印初始状态的kprint(k) # 打印初始状态的Wprint(W)# 打印输入的卷积核Kprint(K)# 将卷积核K的元素填充到向量k中的适当位置 形成一个稀疏向量k[:2], k[3:5] K[0, :], K[1,:]# 打印填充后的向量kprint(k)# 将稀疏向量k填充到矩阵W中的适当位置 形成一个稀疏矩阵W[0, :5], W[1, 1:6], W[2, 3:8], W[3, 4:] k, k, k, k# 返回转换后的稀疏矩阵Wreturn W# 每一行向量表示在一个位置的卷积操作 0填充表示卷积核未覆盖到的区域。

输入大小为 3 * 3 的图片 拉长一维向量后变成 1 * 9 的向量

输入大小为 3 * 3 的图片 卷积核为 2 * 2 则输出图片为 2 * 2 拉长后变为 4 * 1 的向量

kernel2matrix函数将卷积核改为稀疏矩阵C后矩阵情况# 使用kernel2matrix函数将卷积核K转换为一个稀疏矩阵W

这个矩阵的每一行表示在一个特定位置进行的卷积操作 其中的0表示卷积核没有覆盖的区域

如果输入是一个3x3的图像 并被拉平为一个1x9的向量

而卷积核是2x2的 那么输出图像的大小为2x2 拉平后变为一个4x1的向量

kernel2matrix函数实际上就是在构建这种转换关系

W kernel2matrix(K) W

打印输入张量X的内容

print(X)

使用reshape函数将输入张量X拉平为一个一维向量 并打印结果

这是为了将X与稀疏矩阵W进行矩阵乘法操作

print(X.reshape(-1))

判断卷积操作的结果Y是否等于稀疏矩阵W与拉平的输入张量X的矩阵乘法的结果 并将结果重塑为2x2的形状

这是一种检查卷积操作是否等价于某种矩阵变换的方式

Y torch.matmul(W, X.reshape(-1)).reshape(2, 2)# 使用自定义的转置卷积函数trans_conv对卷积操作的结果Y和卷积核K进行转置卷积操作 Z trans_conv(Y, K)

判断转置卷积操作的结果Z是否等于稀疏矩阵W的转置与拉平的卷积结果Y的矩阵乘法的结果 并将结果重塑为3x3的形状

这是一种检查转置卷积操作是否等价于某种特定的矩阵变换的方式

注意这里得到的结果并不是原图像 尽管它们的尺寸是一样的

Z torch.matmul(W.T, Y.reshape(-1)).reshape(3, 3) # 由卷积后的图像乘以转置卷积后 得到的并不是原图像 而是尺寸一样
全连接卷积神经网络 1 * 1 卷积层来降低维度 转置卷积层把图片扩大k是通道有多少类通道数为类别数则导致可以对每一个像素分类 FCN是用深度神经网络来做语义分割的奠基性工作 其用转置卷积层来替换CNN最后的全连接层  从而可以实现每个像素的预测

全连接卷积神经网络

import torch import torchvision from torch import nn from torch.nn import functional as F from d2l import torch as d2l# 使用在ImageNet数据集上预训练的ResNet18模型来提取图像特征 pretrained_net torchvision.models.resnet18(pretrainedTrue)

使用list函数和children方法列出预训练模型的所有子层这些子层通常是神经网络的层

然后使用Python的切片语法来取出最后三层

这可以帮助我们理解模型的结构 特别是在我们打算对模型进行微调或者使用模型的某些层来提取特征时

list(pretrained_net.children())[-3:] # 查看最后三层长什么样子# 创建一个全卷积网络实例net

使用预训练的ResNet18模型创建一个新的神经网络

其中 *list(pretrained_net.children())[:-2]这段代码将ResNet18模型的所有子层除了最后两层作为新网络的层

这样 新网络实际上是ResNet18模型去掉最后两层后的版本

这种方法常常用于迁移学习 即利用一个在大型数据集上训练过的模型的特征提取部分 来帮助我们处理新的任务

net nn.Sequential(*list(pretrained_net.children())[:-2]) # 去掉ResNet18最后两层

创建一个形状为(1, 3, 320, 480)的随机张量 这可以看作是一张形状为(320, 480) 有三个颜色通道的图片

这里的3代表图片的颜色通道数量红、绿、蓝 320和480分别代表图片的高度和宽度

随机张量的所有元素都是在[0, 1)之间随机生成的 可以看作是随机图片的像素值

X torch.rand(size(1,3,320,480)) # 卷积核与输入大小无关 全连接层与输入大小有关

将随机生成的图片输入到网络中 通过调用net(X) 进行前向传播

打印输出张量的形状 输出的形状通常可以用于检查网络的结构是否正确

对于全卷积网络 输出的宽度和高度通常会比输入的小 这是由于卷积和池化操作造成的

在这个例子中 输出的宽度和高度应该是输入的1/32 这是由ResNet18的结构决定的

net(X).shape # 缩小32倍# 使用1X1卷积层将输出通道数转换为Pascal VOC2012数据集的类数21类

将要素地图的高度和宽度增加32倍

定义目标数据集中的类别数量 这里的21表示Pascal VOC2012数据集中有21个类别 包括20个物体类别和一个背景类别

num_classes 21

在网络末尾添加一个新的卷积层 这是一个1x1的卷积层 输入通道数为512这是由前面的ResNet18模型决定的

输出通道数为我们定义的类别数量即21

1x1卷积层常用于改变通道数 即可以将前一层的特征图投影到一个新的空间 这个新的空间的维度即为卷积层的输出通道数

net.add_module(final_conv,nn.Conv2d(512,num_classes,kernel_size1))

图片放大32倍 所以stride为32

padding根据kernel要保证高宽不变的最小值 16 * 2 32 图片左右各padding

kernel为64 原本取图片32大小的一半 再加上padding的32 就相当于整个图片

再添加一个转置卷积层 转置卷积也被称为反卷积 通常用于将小尺寸的特征图放大到原来的大小

这里的输入和输出通道数都是num_classes 表示我们希望在放大的过程中保持通道数不变

kernel_size是64 stride是32 这意味着这一层将特征图的宽度和高度放大了32倍

padding是16 它用于在特征图的边缘添加额外的区域 使得输出的大小正好是输入的32倍

net.add_module(transpose_conv, nn.ConvTranspose2d(num_classes,num_classes,kernel_size64,padding16,stride32))

初始化转置卷积层# 双线性插值核的实现

定义一个函数 用于初始化双线性插值核

这个函数接受三个参数输入通道数、输出通道数和核大小

def bilinear_kernel(in_channels, out_channels, kernel_size):# 计算双线性插值核中心点位置# 计算双线性插值核的尺寸的一半 由于我们希望中心点位于核的中心 所以需要先计算核的一半大小# 我们使用 // 运算符进行整数除法 确保结果为整数factor (kernel_size 1) // 2# 根据核的大小是奇数还是偶数 确定中心点的位置# 如果核的大小是奇数 则中心点位于尺寸的一半减去1的位置 因为Python的索引从0开始 所以减去1# 例如 如果核的大小是3 那么中心点应该位于1的位置 (31)//2 - 1 1if kernel_size % 2 1:center factor - 1# 如果核的大小是偶数 则中心点位于尺寸的一半减去0.5的位置# 这是因为偶数大小的核没有明确的中心点 所以我们取中间两个元素的平均位置作为中心点# 例如 如果核的大小是4 那么中心点应该位于1.5的位置 (41)//2 - 0.5 1.5else:center factor - 0.5# 创建一个矩阵 其元素的值等于其与中心点的距离og (torch.arange(kernel_size).reshape(-1,1),torch.arange(kernel_size).reshape(1,-1))# 计算双线性插值核 其值由中心点出发 向外线性衰减filt (1 - torch.abs(og[0] - center) / factor) * (1 - torch.abs(og[1] - center) / factor) # 初始化一个权重矩阵 大小为 (输入通道数, 输出通道数, 核大小, 核大小)weight torch.zeros((in_channels, out_channels, kernel_size, kernel_size)) # 将双线性插值核的值赋给对应位置的权重weight[range(in_channels),range(out_channels),:,:] filt# 返回初始化的权重矩阵 这个权重矩阵可以直接用于初始化转置卷积层的权重return weight# 双线性插值的上采样实验

创建一个转置卷积层 输入和输出通道数都是3 这是因为我们处理的是RGB图片 每个颜色通道都需要进行处理

核大小是4 步长是2 这意味着这个层将输入的宽度和高度放大了2倍

设置bias为False 因为我们不需要偏置项

conv_trans nn.ConvTranspose2d(3,3,kernel_size4,padding1,stride2,biasFalse)

使用双线性插值核初始化转置卷积层的权重

这里我们使用了copy_方法 这是一种就地操作 直接修改了原始张量的值

convtrans.weight.data.copy(bilinear_kernel(3,3,4)) # 双线性核初始化权重

使用torchvision.transforms.ToTensor()将一张JPEG格式的图片转换为张量

img torchvision.transforms.ToTensor()(d2l.Image.open(01_Data/03_catdog.jpg))

增加一个批次维度

X img.unsqueeze(0)

将图片张量输入到转置卷积层中 得到上采样的结果

Y conv_trans(X)

将输出结果转换为可以展示的格式 即(高度, 宽度, 颜色通道)的格式 并从计算图中分离出来 这样就可以转换为NumPy数组

out_img Y[0].permute(1,2,0).detach()

设置展示图片的大小

d2l.set_figsize()

打印输入图片的形状

print(input image shape:, img.permute(1,2,0).shape)

展示图片

d2l.plt.imshow(img.permute(1,2,0))

打印输出图片的形状并展示图片

可以看到 输出图片的宽度和高度都是输入的2倍 这正是我们设置的步长

print(output image shape:,out_img.shape) # 输出被拉大了2倍

并展示图片

d2l.plt.imshow(out_img)# 用双线性插值的上采样初始化转置卷积层

对于1X1卷积层 我们使用Xavier初始化参数

使用双线性插值核初始化转置卷积层的权重

num_classes是目标数据集中的类别数量 这里使用双线性插值核的尺寸为64

W bilinear_kernel(num_classes, num_classes, 64)

将初始化的权重W复制给转置卷积层的权重

使用copy_方法进行就地操作 直接修改原始张量的值

net.transposeconv.weight.data.copy(W) 注上述内容参考b站up主“我是土堆”的视频参考吴恩达深度学习机器学习内容参考李沐动手学深度学习