《Vision Transformer (ViT)》论文精度,并解析ViT模型结构以及代码实现

2023-11-15

《AN IMAGE IS WORTH 16X16 WORDS:

TRANSFORMERS FOR IMAGE RECOGNITION AT SCALE》

论文共有22页,表格和图像很多,网络模型结构解释的很清楚,并且用四个公式展示了模型的计算过程;本文章对其进行精度,并对源码进行剖析,希望读者可以耐心读下去。

论文地址:https://arxiv.org/abs/2010.11929

源码地址(pytorch):https://github.com/lucidrains/vit-pytorch


目录

一、引言

二、结论

三、ViT模型结构

四、代码构建ViT模型(注释基本都在代码中)

(1)标准的Transformer编码器

(2)ViT模型

五、论文中的图像和表格分析

(1)ViT的模型变体

(2)分类精度结果对比

(3)数据集的大小对ViT的影响

(3)BiT、ViT、Hybrids模型集的比较

(4)ATTENTION DISTANCE

(5)学习率的影响

(6)位置嵌入的比较

(7)注意力权重可视化


一、引言

虽然Transformer架构已经成为自然语言处理任务的事实上的标准,但它在计算机视觉中的应用仍然有限。在视觉上,注意力要么与卷积网络结合使用,要么用于替换卷积网络的某些组成部分,同时保持其整体结构的到位。我们表明,这种对CNN的依赖是不必要的,直接应用于图像块序列的Transformer可以很好地执行图像分类任务。当对大量数据进行预训练并转移到多个中小规模的图像识别基准时(ImageNet、CIFAR-100、VTAB等),Vision Transformer ( ViT ) 相对于先进的卷积网络获得了优异的结果,同时训练所需的计算资源也大大减少。

二、结论

我们探索了Transformer在图像识别中的直接应用不同于以往在计算机视觉中使用自注意力的工作,我们除了初始的patches提取步骤外,并没有引入图像特定的诱导偏差。相反,我们将图像理解为一个patches序列,并通过标准的 Transformer 编码器对其进行处理,如同在NLP中使用一样。这种简单而又可扩展的策略在结合大规模数据集的预训练时表现出惊人的效果。因此,Vision Transformer 在许多图像分类数据集上匹配或超过了艺术状态,同时相对于训练前来说相对便宜。

虽然这些初步成果令人鼓舞,但仍存在许多挑战。一是将ViT应用到其他计算机视觉任务中,如检测和分割。我们的结果,再加上 《End-to-end object detection with transformers》(2020) 的结果,表明这一方法的前景。另一个挑战是继续探索自监督的预训练方法。我们的初始实验从自监督预训练方面表现出了改进,但自监督与大规模监督预训练相比仍有较大差距。最后,ViT 的进一步缩放很可能导致性能的提高。

三、ViT模型结构

原文:我们将图像分割成固定大小的块,线性嵌入其中的每个块,加入位置嵌入,并将得到的向量序列反馈给标准的Transformer编码器。为了执行分类,我们采用在序列中添加额外可学习的“classification token”的标准方法。

结合原文,把模型的结构解析成以下三个步骤:

(1)把大小为256*256的图像切割成16*16的patches,每一个patch的像素大小是14*14

 ​​​​​​(2)对一张图像进行切割、位置嵌入、分类嵌入的操作,返回一个大小为197*768的矩阵,准备送入到标准的Transformer编码器中。

 (3)本文章举例处理了一张图像,即batch_size=1。[1, 197, 768]经标准的Transformer编码器输出[1, 197, 768],然后经过分类头,输出分类结果。

 以上三个步骤的计算公式,可以由下面的四个公式概括:

如下图所示,右侧是ViT模型的结构图,左边是对各个公式的参数解释,其对应右侧的各个模型块 

 四、代码构建ViT模型(注释基本都在代码中)

构建ViT模型的结构前,需要搭建一个标准的Transformer编码器结构。

一个标准的Transformer编码器结构包括:多头注意力机制、层规范化和残差连接和多层感知机(简单的神经网络)。

******如果对Transformer的结构不是很熟悉,可以参考我的 “变形金刚 Transformer” 专栏******

(1)标准的Transformer编码器

层规范化:

class PreNorm(nn.Module):
    """层规范化"""
    def __init__(self, dim, fn):
        super().__init__()
        self.norm = nn.LayerNorm(dim)
        self.fn = fn

    def forward(self, x, **kwargs):
        return self.fn(self.norm(x), **kwargs)

多层感知机:

class FeedForward(nn.Module):
    """前馈神经网络(MLP)"""
    def __init__(self, dim, hidden_dim, dropout = 0.):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(dim, hidden_dim),
            nn.GELU(),
            nn.Dropout(dropout),
            nn.Linear(hidden_dim, dim),
            nn.Dropout(dropout)
        )

    def forward(self, x):
        return self.net(x)

多头注意力机制:

class Attention(nn.Module):
    """多头注意力机制"""
    def __init__(self, dim, heads = 8, dim_head = 64, dropout = 0.):
        super().__init__()
        inner_dim = dim_head *  heads
        project_out = not (heads == 1 and dim_head == dim)

        self.heads = heads
        self.scale = dim_head ** -0.5

        self.attend = nn.Softmax(dim = -1)
        self.dropout = nn.Dropout(dropout)

        self.to_qkv = nn.Linear(dim, inner_dim * 3, bias = False)

        self.to_out = nn.Sequential(
            nn.Linear(inner_dim, dim),
            nn.Dropout(dropout)
        ) if project_out else nn.Identity()

    def forward(self, x):
        qkv = self.to_qkv(x).chunk(3, dim = -1)
        q, k, v = map(lambda t: rearrange(t, 'b n (h d) -> b h n d', h = self.heads), qkv)

        dots = torch.matmul(q, k.transpose(-1, -2)) * self.scale

        attn = self.attend(dots)
        attn = self.dropout(attn)

        out = torch.matmul(attn, v)
        out = rearrange(out, 'b h n d -> b n (h d)')
        return self.to_out(out)

Transformer编码器:

class Transformer(nn.Module):
    """标准的Transformer编码器"""
    def __init__(self, dim, depth, heads, dim_head, mlp_dim, dropout = 0.):
        super().__init__()
        self.layers = nn.ModuleList([])
        for _ in range(depth):
            self.layers.append(nn.ModuleList([
                PreNorm(dim, Attention(dim, heads = heads, dim_head = dim_head, dropout = dropout)),
                PreNorm(dim, FeedForward(dim, mlp_dim, dropout = dropout))
            ]))

    def forward(self, x):
        # 实现残差网络的相加
        for attn, ff in self.layers:
            x = attn(x) + x
            x = ff(x) + x
        return x

(2)ViT模型

ViT模型结构可以分成三个部分:

  • 首先对图像进行预处理,分成固定大小的patches后,平坦化并进行位置和分类嵌入;
  • 然后经过标准的Transformer编码器输出自注意权重矩阵;
  • 最后经过LN和MLP进行图像分类。
class ViT(nn.Module):
    def __init__(self, *,
                 image_size,
                 patch_size,
                 num_classes,
                 dim,
                 depth,
                 heads,
                 mlp_dim,
                 pool='cls',
                 channels=3,
                 dim_head=64,
                 dropout=0.,
                 emb_dropout=0.
                 ):
        super().__init__()
        # 图像尺寸
        image_height, image_width = pair(image_size)
        # patch尺寸
        patch_height, patch_width = pair(patch_size)

        assert image_height % patch_height == 0 and image_width % patch_width == 0,  'Image dimensions must be divisible by the patch size.'
        # patches数量
        num_patches = (image_height // patch_height) * (image_width // patch_width)
        # 一个patch的维度
        patch_dim = channels * patch_height * patch_width
        assert pool in {'cls', 'mean'}, 'pool type must be either cls (cls token) or mean (mean pooling)'

        # 处理原始图像
        # Rearrange:按照字符串的含义对目标进行重新排列的操作
        # img = torch.randn(1, 3, 256, 256)  '1 3 (256 32) (256 32) -> 1 (256 256) (32 32 3)'
        # 分成32*32个patch,并平铺成1024个patch,每一个patch的大小为8*8
        # 然后经过一个全连接层(3072, 1024)输出处理后的图像(三维:32*32*3=3072)
        self.to_patch_embedding = nn.Sequential(
            Rearrange('b c (h p1) (w p2) -> b (h w) (p1 p2 c)', p1=patch_height, p2=patch_width),
            nn.Linear(patch_dim, dim),
        )
        # Sequential(
        #   (0): Rearrange('b c (h p1) (w p2) -> b (h w) (p1 p2 c)', p1=32, p2=32)
        #   (1): Linear(in_features=3072, out_features=1024, bias=True)
        # )
        # print(self.to_patch_embedding)

        # 位置嵌入(patches+cls的位置信息)
        self.pos_embedding = nn.Parameter(torch.randn(1, num_patches + 1, dim))
        # class token
        self.cls_token = nn.Parameter(torch.randn(1, 1, dim))
        self.dropout = nn.Dropout(emb_dropout)

        # 定义标准Transformer模型结构
        self.transformer = Transformer(dim, depth, heads, dim_head, mlp_dim, dropout)

        self.pool = pool

        # 不区分参数的占位符标识运算符。
        # identity模块不改变输入,直接return input
        # 一种编码技巧吧,比如我们要加深网络,有些层是不改变输入数据的维度的,这时就可以使用此函数
        # 这个网络层的设计是仅用于占位的,即不干活,只是有这么一个层,放到残差网络里就是在跳过连接的地方用这个层,显得没有那么空虚!
        self.to_latent = nn.Identity()

        # 定义MLP分类头的模型结构
        # 首先经过LN,然后经过一个全连接层(1024, 1000),输出分类结果
        self.mlp_head = nn.Sequential(
            nn.LayerNorm(dim),
            nn.Linear(dim, num_classes)
        )

    def forward(self, img):
        # img = torch.randn(1, 3, 256, 256)
        # 即往网络中送入一张256*256的三维图像(batch_size=1)
        x = self.to_patch_embedding(img)
        # 平铺后,共有8*8个patch,其大小为32*32
        print('平铺:', x.size())  # torch.Size([1, 64, 1024])
        b, n, _ = x.shape
        # print(b, n)  # 1 64

        # class tokens
        cls_tokens = repeat(self.cls_token, '1 n d -> b n d', b=b)
        # print(cls_tokens.size())  # torch.Size([1, 1, 1024])

        x = torch.cat((cls_tokens, x), dim=1)  # 沿着dim=1方向对cls_token和x进行拼接
        x += self.pos_embedding[:, :(n + 1)]  # 拼接后的x与嵌入未知信息
        x = self.dropout(x)
        print(x.size())  # torch.Size([1, 65, 1024])

        # 把预处理的图像送入Transformer模型中
        x = self.transformer(x)
        print(x.size())  # torch.Size([1, 65, 1024])

        # 如果pool=='mean',返回dim=1方向上的元素平均值
        # 否则,直接返回dim=0方向上的第一行的所有元素,即class tokens
        x = x.mean(dim=1) if self.pool == 'mean' else x[:, 0]
        print(x.size())  # torch.Size([1, 1024])

        # 不区分参数的占位符标识运算符。
        x = self.to_latent(x)

        # 返回分类头的分类结果
        return self.mlp_head(x)

测试代码:输入指定参数,调用ViT模型,输出分类矩阵:

输入参数含义:

  • image_size=256,       # 图像尺寸
  • patch_size=32,          # patches大小
  • num_classes=1000,  # 标签数量
  • dim=1024,                 # patch的维度
  • depth=6,                    # 模型深度(编码器的数量)
  • heads=16,                 # 注意力头的数量
  • mlp_dim=2048,         # Transformer中MLP的输出维度
  • dropout=0.1,              # Transformer中MLP的舍弃率
  • emb_dropout=0.1      # 嵌入舍弃率
import torch
from vit_pytorch import ViT


def test():
    v = ViT(
        image_size=256,  # 图像尺寸
        patch_size=32,   # patches数量
        num_classes=1000,# 标签数量
        dim=1024,        # patch的维度
        depth=6,         # 模型深度(编码器的数量)
        heads=16,        # 注意力头的数量
        mlp_dim=2048,    # Transformer中MLP的输出维度
        dropout=0.1,     # Transformer中MLP的舍弃率
        emb_dropout=0.1  # 嵌入舍弃率
    )

    img = torch.randn(1, 3, 256, 256)
    preds = v(img)

    # 如果preds.shape != (1, 1000),自行中断程序,并报错:'correct logits outputted'
    assert preds.shape == (1, 1000), 'correct logits outputted'

    return preds.shape


VIT_result = test()
print(VIT_result)  # torch.Size([1, 1000])

五、论文中的图像和表格分析

(1)ViT的模型变体

下面的表格表示的是ViT的模型变体,分别是ViT-B、ViT-L、ViT-H。

我们基于用于BERT《BERT: Pre-training of deepbidirectional transformers for language understanding》的ViT配置,如下表所示。“Base”和“Large”模型直接采用BERT,我们加入了较大的“Huge”模型。

下面我们使用简要说明来表示模型大小和输入patch大小:例如,ViT-L / 16表示输入patch大小为16×16的 “Large” 变体。注意,Transformer的序列长度与patch大小的平方成反比,因此具有较小patch大小的模型计算代价更高。

(2)分类精度结果对比

我们发现,大规模的训练会克服归纳性偏差。我们的视觉变形金刚( ViT )在足够规模的预训练后转移到数据量较少的任务时取得了很好的效果。在公共ImageNet-21k数据集或内部 JFT-300M 数据集上进行预训练时,ViT接近器在多个图像识别基准上击败了艺术状态。特别是最佳模型在ImageNet上达到了88.55%的准确率,在ImageNet-ReaL上达到了90.72%,在CIFAR-100上达到了94.55%。

在JFT - 300M上预训练的较小的 ViT - L / 16 模型在所有任务上都优于 BiT - L ( 在同一数据集上进行预训练 )模型,同时训练所需的计算资源大大减少。更大的模型 ViT-H / 14 进一步提高了性能,特别是在更具挑战性的数据集- ImageNet、CIFAR-100和VTAB套件上。有趣的是,该模型对预训练的计算量仍然大大低于现有的技术状态。但是,我们注意到,预训练效率不仅可能受到体系结构选择的影响,还可能受到其他参数的影响,如训练计划、优化器、权值衰减等。最后,在公开的ImageNet-21k数据集上预训练的 ViT-L / 16 模型在大多数数据集上也表现良好,同时占用了很少的资源进行预训练:它需要使用8个核心的标准云TPUv3训练大约30天。

下面的表格表示微调不同ResNet中Adam、SGD的消融实验:

(3)数据集的大小对ViT的影响

  • 左侧的图像表示:在小数据集上进行预训练时,大型ViT模型的表现要比BiTResNets 差,但在较大数据集上进行预训练时,ViT会发光。随着数据集的增长,较大的ViT变体会取代较小的ViT变体。
  • 右侧的图像表示:ResNets在较小的预训练数据集上表现更好,但ViT在较大的预训练数据集上表现更好。

(3)BiT、ViT、Hybrids模型集的比较

预训练的模型集:

  • BiT:7 ResNets, R50x1,R50x2 R101x1, R152x1, R152x2, pre-trained for 7 epochs, plus R152x2 and R200x3 pre-trainedfor 14 epochs;
  • ViT: 6 Vision Transformers, ViT-B/32, B/16, L/32, L/16, pre-trained for 7 epochs, plusL/16 and H/14 pre-trained for 14 epochs;
  • Hybrids:5 hybrids, R50+ViT-B/32, B/16, L/32, L/16 pre-trained for 7 epochs, plus R50+ViT-L/16 pre-trained for 14 epochs 

如下图所示:比较不同架构的性能与预训练计算:ViT,ResNets和混合Transformer的比较。在相同的计算开销下,ViT的性能一般优于ResNet。对于较小的模型尺寸,混合Transformer比纯Transformer有所改善,而对于较大的模型尺寸,纯Transformer比混合Transformer有所改善。

启发:这个结果有些令人惊讶,因为人们可能期望卷积局部特征处理能够在任何大小上辅助ViT。其次,ViT似乎没有在所尝试的范围内饱和,从而激励了未来的缩放努力(主要的缩放策略便是对模型的宽度(w)、深度(d)和分辨率(r)进行调整)。

(4)ATTENTION DISTANCE

为了了解ViT如何使用自注意来整合图像中的信息,我们分析了不同层次的注意权重所跨越的平均距离。这种 “注意力距离” 类似于CNN的感受野大小。平均注意距离在较低层的头之间是高度可变的,有的头会关注图像的大部分,有的头会关注查询位置处或附近的小区域。随着深度的增加,所有注意力头的注意距离增加。在网络的后半部分,大多数的heads通过tokens广泛参加。

如下图所示,按heads和网络深度划分参加区域的规模。通过平均查询像素与所有其他像素之间的距离,加权得到的注意力权重,对128幅样本图像计算了注意距离。每一个点显示了16个heads中的1个head在1层Transformer中的平均注意距离。图像宽度为224像素。

 (5)学习率的影响

分类头:这个设计继承了Transformer模型的文本,我们在整个主论文中使用它。最初尝试只使用图像块嵌入,全局平均池( GAP )它们,随后使用线性分类器(就像ResNet的最终特征映射一样)的性能很差。但是,我们发现性能差既不是由于额外的token,也不是GAP操作造成的。相反,他在表现上的差异完全由不同的学习率影响。

 (6)位置嵌入的比较

下表总结了本消融研究在 ViT-B / 16 模型上的结果。正如我们所看到的,虽然没有位置嵌入的模型和有位置嵌入的模型的性能有很大的差距,但是不同的位置信息编码方式之间几乎没有差别。我们推测,由于我们的Transformer编码器工作在 patch-level 的输入上,相对于像素级,在如何编码空间信息方面的差异并不重要。更确切地说,在 patch-level 输入中,空间维度远小于原始的像素级输入,如14 × 14而不是224 × 224,对于这些不同的位置编码策略,学习表示空间关系同样容易。

即便如此,网络学习到的位置嵌入相似度的具体模式取决于训练超参数。 

 (7)注意力权重可视化

认真阅读完毕,定会有所收获!

>>>如有疑问,欢迎评论区一起探讨!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

《Vision Transformer (ViT)》论文精度,并解析ViT模型结构以及代码实现 的相关文章

  • 红帽认证-RHCSA

    目录 RHCSA认证考的是 Server A 题目 一 按要求配置网络 二 配置系统使用默认存储库 三 调试SELinux 四 创建用户账户 五 配置cron 作业 六 创建协作目录 七 配置NTP 八 配置 autofs 九 配置 var
  • 牛客网-华为机考-HJ30 字符串合并处里--详细解题思路,并有详细解题代码和注解

    注意 代码和解题思路在后面 HJ30 字符串合并处理 描述 按照指定规则对输入的字符串进行处理 详细描述 第一步 将输入的两个字符串str1和str2进行前后合并 如给定字符串 dec 和字符串 fab 合并后生成的字符串为 decfab
  • 排序之sort排序

    C 的STL里面有个sort函数 可以直接对数组排序 复杂度为n log2 n 使用这个函数 需要包含头文件
  • 【计算机毕业设计】228图书商城网站

    一 系统截图 需要演示视频可以私聊 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术 让传统数据信息的管理升级为软件存储 归纳 集中处理数据信息的管理方式 本图书商城网站就是在这样的大环境下诞生 其可以帮助管理者在短时间内处理完毕庞大
  • ModuleNotFoundError: No module named 'cv2' (安装cv2)

    1 问题 ModuleNotFoundError No module named cv2 Pycharm 中 import cv2 出现错误 2 解决 安装cv2 pip install opencv python 如果只用主模块 使用这个
  • vulnhub靶机Looz

    下载地址 Looz 1 VulnHub 主机发现 arp scan l 端口扫描 nmap min rate 10000 p 192 168 21 155 扫描端口信息 nmap sV sT O p22 80 139 3306 8081 1
  • flask中文学习教程

    2019独角兽企业重金招聘Python工程师标准 gt gt gt http flask123 sinaapp com 转载于 https my oschina net 935572630 blog 371473
  • vue中 关于 同一个 页面 使用搜索功能 数据不更新

    注意 我这里的搜索是在 公共的头部里面如图 我这里点击搜索是跳到搜索页面 并且传参 代码如下 div class search div

随机推荐

  • mipi协议_学习共享——MIPI

    点击上方蓝字 记得关注我们 MIPI名词解释 MIPI Mobile Industry Processor Interface 移动行业处理器接口 是2003年由ARM Nokia ST TI等公司成立的一个联盟发起的为移动应用处理器定制的
  • 3D纹理,立体纹理,三维纹理示例配置

    1 下载freeglut并使用cmake配置 编译安装 https github com FreeGLUTProject freeglut git clone https github com FreeGLUTProject freeglu
  • c++学习——构造函数和析构函数

    构造函数和析构函数 简要概述 构造函数和析构函数的简单调用 构造函数和析构函数能够函数重载 默认的构造函数和析构函数 拷贝构造 构造函数的分类和调用 匿名对象 拷贝构造函数的调用时机 构造函数的调用规则 多个对象的构造函数和析构函数 深浅拷
  • 数组越界访问会发生什么错误?怎样避免该错误?_后缀数组跳坑笔记

    记点写题的时候遇到的坑 可能会更新 多组数据相关 1 h数组需要清空 别的一般不需要 除了倍增算法中为简化代码把上一迭代的rk数组开成两倍的情况 那个场合会有因为字符串长度不同而导致访问到以前填写的不知道什么鬼东西的情况导致rk算错 大概就
  • [790]win环境Maven安装配置

    文章目录 什么是Maven Maven是一个项目管理和整合的工具 Maven为开发者提供了一套完整的构建生命周期框架 开发团队基本不用花多少时间就能自动完成工程的基础构建配置 因为Maven使用了一个标准的目录结构和一个默认的构建生命周期
  • 【UE4】多视角相机捕获图像如何同屏拼接在一起

    前段时间有个Demo移植的需求 需要把实时裸眼3D多视角立体显示的Unity版本移植到UE4 主要包含后处理Shader 相机矩阵变换 多视角画面平铺拼接三大部分 10 10 多视角相机捕获图拼接效果 对现有的多窗口显示方法进行查阅后 发现
  • 不一样的视角,不一样的Kinect for Windows 2.0

    随着科技的发展 智能硬件已经越来越多的出现在我们的生活当中 侦探片中的无线内耳耳机已经变成了蓝牙耳机 而 少数派报告 中手势操作的荧幕界面也已变成现实 对人机交互有很高要求的开发者来讲 于7月正式发售的Kinect for Windows
  • pytorch 线性回归拟合sin函数

    目录 1 库文件 2 定义超参数 3 获取数据集 4 加载训练集 测试集 5 搭建线性网络 6 实例化网络和优化器 7 训练网络 8 可视化 9 结果展示 10 完整代码 1 库文件 os 文件是为了消除matplotlib 绘图的错误 T
  • Yolox_s可视化网络结构图

    Yolox共有七种网络结构 包含2种轻量级网络 和5种标准网络 轻量级网络 1 Yolox Nano可视化网络结构图 点击查看 2 Yolox Tiniy可视化网络结构图 点击查看 标准网络 1 Yolox s可视化网络结构图 点击查看 2
  • Java中对象实例化过程中的多态特性

    通过上述代码 始终明确调用的方法必须是实例化子类中重写的方法 首先 在main函数中 new B new了一个B类的实例化对象 在实例化对象时 调用了B类中的构造函数 执行 super 5 也就是public A int v gt setV
  • 14.应用层HTTP协议

    目录 一 OSI七层协议 vs TCP IP五层协议 二 HTTP协议 URL 1 1URL 中的可省略部分 2 请求消息Request 2 1请求行 2 2请求头 2 3空行 2 4请求数据 2 5HTTP 请求方法 3 响应消息Resp
  • sql developer默认是不自动提交事务的,如何查询未被提交的事务

    select SQL TEXT status from v sql v transaction where LAST ACTIVE TIME START DATE 上面的语句可以查询未被提交的事务 如果你查询或更新时很长时间没反应 一般是另
  • 二分查找BinarySearch

    二分查找 在包含size个元素 从小到大排序的int数组array里查找元素p 如果找到返回下标 如果未找到返回 1 int BinarySearch int array int size int p int left 0 查找区间的左端点
  • 5.7及以上版本的MySQL下载、安装及配置教程

    对版本的说明 之所以说是MySQL5 7及以上版本 是因为从MySQL5 7版本之后 其安全机制有所改变 在安装完成后 登陆MySQL时 需要输入一个密码 这个密码其实是在配置MySQL的过程中生成的一个随机密码 而我们必须找到这个随机密码
  • Eclipse中启动Tomcat无任何反应

    推动了软件业不断发展的可以说有3个方面的东西 过程 方法 技术 方法附会到哲学上应该就是方法论了 做很多事情都是需要方法的 比如写一篇案例 随心随意写也可以写出来 但是别人能否理解 如何检测自己描述清晰都是没有参考的 如果有个模板的 这样按
  • 韩顺平_java 学习路线

    链接 目录 阶段一 Java基础 阶段二 Java高级 阶段三 Java Web 阶段四 主流框架 项目管理相关的技术 阶段五 分布式 微服务 并行架构 阶段六 DevOps 开发运维一体化 自动部署项目管理 解决 CI CD 阶段七 大数
  • 【目标检测】单阶段算法--YOLOv3详解

    论文题目 YOLOv3 An Incremental Improvement 论文地址 https pjreddie com media files papers YOLOv3 pdf 一文读懂YOLOv1 YOLOv1 一文读懂YOLOv
  • 链表(详解)

    一 链表 1 1 什么是链表 1 链表是物理存储单元上非连续的 非顺序的存储结构 数据元素的逻辑顺序是通过链表的指针地址实现 有一系列结点 地址 组成 结点可动态的生成 2 结点包括两个部分 1 存储数据元素的数据域 内存空间 2 存储指向
  • gitee最详细使用教程,汇总了全网,看这一篇就够了

    1 gitee是什么 基于git的代码托管协助平台 2 git网站上的注册登录 打开gitee官网Gitee 基于 Git 的代码托管和研发协作平台打开注册登录即可 邮箱注册最好 非邮箱在个人 设置里添加自己的邮箱 新手请公开自己的邮箱 如
  • 《Vision Transformer (ViT)》论文精度,并解析ViT模型结构以及代码实现

    AN IMAGE IS WORTH 16X16 WORDS TRANSFORMERS FOR IMAGE RECOGNITION AT SCALE 论文共有22页 表格和图像很多 网络模型结构解释的很清楚 并且用四个公式展示了模型的计算过程