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

ViT实战一:Patch_embedding

前言

本文是针对ViT这篇博文CV攻城狮入门VIT(vision transformer)之旅——VIT原理详解篇-CSDN博客中patch_embedding的笔记

我采用了比较简单的patch_embedding实现-------------利用卷积

原理第一种理解

既然要使用卷积,那么首先就是要解决的几个问题

  1. 卷积核的个数?也就是通道数
  2. 卷积核的大小,步长,是否需要填充
  3. 输出图片的大小,也就是子图的大小,

首先针对问题三,我们子图的大小是人为设定的,因此没有异议

对于卷积核的个数确定

例如我们有一张224*224的RGB三通道图像,要分成的子图大小为16*16三通道图,我们可以分出

\frac{224*224*3}{16*16*3}=14*14   

这么多的子图数量,那么我们最终能得到的像素点数量是

16*16*3*14*14

我们也可以这么写

16*16*(3*14*14)

这样表示的是什么意义呢?因为我们子图的大小为16,如果但从通道数来看,通道的大小也算16,但是通道的个数是3*14*14,为什么要研究通道数呢?因为我们卷积的通道数等于输出图片的通道数总和,至此我们解决了第一个问题,卷积核的个数

卷积核的大小,步长,是否需要填充

目前我们已经知道了:

输入图片的大小:224*224,3通道图像

输出图片的大小:16*16,3通道图像

输出图片的通道总数:14*14=196

我们可以询问AI,在这种情况下,我们要如何设计卷积核的大小,步长,是否需要填充

我们可以就源码进行实验设计

首先本次实验是在notebook上运行,调试,有关Notebook的调试过程可以参考以下教程

(29 封私信 / 83 条消息) VSCode Jupyter断点调试新方法 - 知乎

import torch
import torch.nn as nn
from torch.utils import data
import torchvision
import torchvision.transforms as T
import torch.nn.functional as F
from PIL import Image
import numpy as np
import os#导入数据
# 定义预处理函数
transform = T.Compose([T.Resize((224, 224)),T.ToTensor(),T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
# 加载数据集
img_dir=r"E:\DeepLearningProject\ViT_Transformer\convimg.png"
img = Image.open(img_dir).convert('RGB')
img = transform(img)
img = img.unsqueeze(0)  # 添加批次维度class PatchEmbed2(nn.Module):"""2D Image to Patch Embeddingpatch_size: 子图大小in_c: 输入图像通道数embed_dim: 输出嵌入维度norm_layer: 归一化层"""def __init__(self, img_size=224, patch_size=16, in_c=3, norm_layer=None):super().__init__()img_size = (img_size, img_size)#  img_size=(224,224)patch_size = (patch_size, patch_size)# patch_size=(16,16)self.img_size = img_sizeself.patch_size = patch_sizeself.grid_size = (img_size[0] // patch_size[0], img_size[1] // patch_size[1])  #输出(14,14)self.embed_dim=in_c* self.grid_size[0]**2  # 3*14*14=588print(self.grid_size)self.num_patches = self.grid_size[0]**2*in_cself.proj = nn.Conv2d(in_c, self.embed_dim, kernel_size=self.grid_size[0], stride=self.grid_size[0])#对源代码的改动2,将stride改为self.patch_size[0]self.norm = norm_layer(self.embed_dim) if norm_layer else nn.Identity()def forward(self, x):B, C, H, W = x.shapeassert H == self.img_size[0] and W == self.img_size[1], \f"Input image size ({H}*{W}) doesn't match model ({self.img_size[0]}*{self.img_size[1]})."# flatten: [B, C, H, W] -> [B, C, HW]# transpose: [B, C, HW] -> [B, HW, C]x = self.proj(x).flatten(2).transpose(1, 2)x = self.norm(x)return x

修改完源代码后,我们进行测试

为什么会是1,256,588呢,是因为我们后面对子图进行了展平的操作,16*16展平为256

原理第二种理解

卷积核个数的确定

由第一种理解,我们有这一个公式

16*16*3*14*14

我们进行第二种变化

(16*16*3)*14*14

这样怎么解释呢?16*16*3是输出子图的通道数总和,而14*14是输出子图的大小,那么卷积核的个数等于输出子图的通道数,也就是16*16*3=768个卷积核

卷积核大小,步长,是否需要填充

通过第二种理解,我们已有

输入图片是:224*224,3通道

输出图片是:14*14,3通道

输出图片的总数:16*16=256

同样,询问AI,这种情况下,我们该如何设计卷积核

这也就是源代码的方案,如下

import torch
import torch.nn as nn
from torch.utils import data
import torchvision
import torchvision.transforms as T
import torch.nn.functional as F
from PIL import Image
import numpy as np
import os#处理数据
#导入数据
# 定义预处理函数
transform = T.Compose([T.Resize((224, 224)),T.ToTensor(),T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
# 加载数据集
img_dir=r"E:\DeepLearningProject\ViT_Transformer\convimg.png"
img = Image.open(img_dir).convert('RGB')
img = transform(img)
img = img.unsqueeze(0)  # 添加批次维度class PatchEmbed(nn.Module):"""2D Image to Patch Embeddingpatch_size: 子图大小in_c: 输入图像通道数embed_dim: 输出嵌入维度norm_layer: 归一化层"""def __init__(self, img_size=224, patch_size=16, in_c=3, norm_layer=None):super().__init__()#以下有关img_size和patch_size的处理是为了适应输入为整数或元组的情况#具体读者可以自行调试进行理解img_size = (img_size, img_size)patch_size = (patch_size, patch_size)self.img_size = img_sizeself.patch_size = patch_sizeself.grid_size = (img_size[0] // patch_size[0], img_size[1] // patch_size[1])self.embed_dim = in_c * self.patch_size[0]**2  # 针对源代码的改动1#print(self.grid_size)self.num_patches = self.grid_size[0] * self.grid_size[1]self.proj = nn.Conv2d(in_c, self.embed_dim, kernel_size=patch_size, stride=self.patch_size[0])self.norm = norm_layer(self.embed_dim) if norm_layer else nn.Identity()def forward(self, x):B, C, H, W = x.shapeassert H == self.img_size[0] and W == self.img_size[1], \f"Input image size ({H}*{W}) doesn't match model ({self.img_size[0]}*{self.img_size[1]})."# flatten: [B, C, H, W] -> [B, C, HW]# transpose: [B, C, HW] -> [B, HW, C]x = self.proj(x).flatten(2).transpose(1, 2)x = self.norm(x)return x

测试结果

http://www.dtcms.com/a/442818.html

相关文章:

  • Java8+新特性
  • 网站的根目录怎么找境外网站不备案盈利
  • 【Linux】Linux 常用指令2
  • 买服务器做网站百度云搜索引擎入口手机版
  • 算法入门:专题攻克主题一---双指针(2)快乐数 呈最多水的容器
  • 中国建设银行移动门户网站广州市花
  • 手写MyBatis第92弹:SqlSource体系、SqlNode树与Trim标签实现原理全揭秘
  • Perl 简介
  • 【c++】set和map
  • LabVIEW脉冲信号中值滤波
  • 做网站北京公司网站做301对优化有影响
  • 【序列晋升】47 Spring Authorization Server授权码模式深度解构:OAuth2.1协议与PKCE扩展的实现细节
  • 深圳市手机网站建设企业网站模板 兼容
  • YOLO入门教程(番外):机器视觉一文通
  • 网站做cdn服务流量ps做网站字号大小
  • Cooperative ISAC-empowered Low-Altitude Economy
  • YOLO入门教程(番外):卷积神经网络—填充与步幅
  • 中国建设银行校园招聘网站注册个公司要多少钱费用
  • 商务网站建设的主流程网站作为医院形象建设
  • 旅游网站推广方案华为外包做的网站
  • 国际民用航空组织ICAO
  • 1.6 傅里叶变换7-拉氏变换、Z变换
  • h5响应式网站设计方案软件开发步骤流程
  • 网站建设所用的工具大丰网店制作
  • 网站建设及网站推广网站开发与建设课程
  • python计算化学(autode系列—xTB)Atoms类详解
  • 网站没有在工信部备案中山seo外包
  • 不通过网站可以做360全景吗网页设计与制作基础教程
  • Simulink模型转换为UPPAAL模型(2016)
  • 部署Spring Boot项目+mysql并允许前端本地访问的步骤