MAE论文阅读《Masked Autoencoders Are Scalable Vision Learners》

文章介绍了MAE(MaskedAutoencoder),这是一种针对视觉Transformer的无监督预训练方法,类似于NLP中的BERT。MAE通过高比例的patch遮挡和轻量级解码器设计,解决图像信息冗余问题,促进更高级特征的学习。实验表明,MAE在无监督预训练中表现优秀,尤其是在高遮挡率下,且其计算效率较高。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


Paper: https://arxiv.org/pdf/2111.06377.pdf


动机

首先简要介绍下BERT,NLP领域的BERT是基于Transformer架构,并采取无监督预训练的方式去训练模型。它提出的预训练方法在本质上是一种masked autoencoding,也就是MLM(masked language modeling):去除数据的一部分然后学习恢复。
在这里插入图片描述
自从ViT火了之后,Transformer架构也可以应用于CV领域中了,一些研究者就开始尝试研究ViT的无监督学习,比如Mocov3用对比学习的方法无监督训练ViT,此外也有一些研究开始借鉴BERT中的MLM方法,比如BEiT提出了用于图像的无监督学习方法: MIM(masked image modeling)。但尽管如此,NLP领域已经在BERT的这种masked autoencoding方法下取得了巨大的进展,而CV领域中在无监督预训练这一块远远落后,主流的无监督训练还是对比学习。其中这种masked autoencoding方法并不是没在图像领域应用过,很早便就出现了,比如Denoising Autoencoders。但是至今却未取得像在NLP领域中的巨大发展。MAE论文对这个问题做了以下分析(参考:视觉无监督学习新范式:MAE):

  • 图像的主流模型是CNN,而NLP的主流模型是transformer,CNN和transformer的架构不同导致NLP的BERT很难直接迁移到CV。但是vision transformer的出现已经解决这个问题;
  • 图像和文本的信息密度不同,文本是高语义的人工创造的符号,而图像是一种自然信号,两者采用masked autoencoding建模任务难度就不一样,从句子中预测丢失的词本身就是一种复杂的语言理解任务,但是图像存在很大的信息冗余,一个丢失的图像块很容易利用周边的图像区域进行恢复。也就是说:丢失一个单词去恢复句子很难,用MLM这样的方式去学习这样一个难的任务可以学到一些有意义的信息;但是丢失一个patch去恢复图像却很简单,这只用线性插值就可以实现了,用MIM这样的方式去学习这么简单的任务,几乎学不到什么有价值的信息
  • 用于重建的decoder在图像和文本任务发挥的角色有区别,从句子中预测单词属于高语义任务,encoder和decoder的gap小,所以BERT的decoder部分微不足道(只需要一个MLP),而对图像重建像素属于低语义任务(相比图像分类),decoder需要发挥更大作用:将高语义的中间表征恢复成低语义的像素值。

因此,本文提出了一种简单有效的用于ViT无监督预训练的方法,称为MAE(masked autoencoder)。MAE也属于MIM的范畴,可以将MAE看作是BERT的CV版本:
在这里插入图片描述

方法

MAE方法很简单,整体架构如下。针对以上的分析,MAE采用了MIM的思想,随机mask掉部分patchs然后进行重建,并有两个核心的设计: 1)设计了一个非对称的encoder-decoder结构,这个非对称体现在两方面:一方面decoder采用比encoder更轻量级设计,encoder首先使用linear将patch映射为embedding,然后采用的是ViT模型,decoder是一个包含几个transformer blocks轻量级模块,最后一层是一个linear层采用的是一个;另外一方面encoder只处理visible patchs,而decoder处理所有的patchs(插入masked patchs)。2)MAE采用很高的masking ratio(比如75%甚至更高),这样构建的学习任务大大降低了信息冗余,或者说增加了学习难度,使得encoder能学习到更高级的特征。此外,由于encoder只处理visible patchs,所以很高的masking ratio可以大大降低计算量。 ​
在这里插入图片描述
MAE采用随机mask策略,对于mask ratio的选择如下:
在这里插入图片描述
其中的linear probing和Fine tune的区别是:linear probing把encoder冻结只加一个linear分类器训练,Fine tune是不冻结encoder完全放开训练。注意,decoder部分只是辅助无监督预训练的,具体到下游任务时就不需要它了。

不同mask ratio的效果:
在这里插入图片描述

在ImageNet-1K上与其他自监督方法对比:
在这里插入图片描述

最后的loss只计算masked patchs。

写作方面参考

论文名《Masked Autoencoders Are Scalable Vision Learners》也是一个常用的强有力的句式:xxx are xxx。并且这样的表达会给人一种很客观,站在读者角度上的感觉。

当你做的模型比较大时,用scalable;当你做的模型比较快时,用efficient。

画图的一些细节: MAE的计算量主要出现在encoder部分,所以作者将encoder部分画的比decoder部分大。论文图中的每一个小细节,体现的都是文章的思想。

### 关于Masked Autoencoders Are Scalable Vision Learners论文的代码实现 #### PyTorch 实现 针对《Masked Autoencoders Are Scalable Vision Learners》这篇论文,存在多个开源项目提供了基于PyTorch框架下的实现方案。其中一个较为知名的非官方版本可以在GitHub仓库找到[^3]。 以下是使用PyTorch构建MAE模型的核心组件之一——编码器的部分示例代码: ```python import torch.nn as nn from functools import partial from timm.models.vision_transformer import Block, _cfg class Encoder(nn.Module): """Encoder for MAE""" def __init__(self, img_size=224, patch_size=16, embed_dim=768, depth=12, num_heads=12, mlp_ratio=4., norm_layer=partial(nn.LayerNorm, eps=1e-6), **kwargs): super().__init__() self.patch_embed = PatchEmbed(img_size=img_size, patch_size=patch_size, in_chans=3, embed_dim=embed_dim) num_patches = self.patch_embed.num_patches self.cls_token = nn.Parameter(torch.zeros(1, 1, embed_dim)) self.pos_embed = nn.Parameter(torch.zeros(1, num_patches + 1, embed_dim), requires_grad=False) self.blocks = nn.ModuleList([ Block(dim=embed_dim, num_heads=num_heads, mlp_ratio=mlp_ratio, qkv_bias=True, norm_layer=norm_layer) for i in range(depth)]) self.norm = norm_layer(embed_dim) def forward(self, x, mask=None): B, C, H, W = x.shape x = self.patch_embed(x) # (B, L, D) cls_tokens = self.cls_token.expand(B, -1, -1) x = torch.cat((cls_tokens, x), dim=1) pos_embed = self.interpolate_pos_encoding(x.size(-1)-1, H//self.patch_embed.patch_size[0]) x += pos_embed[:, :x.size(1)] if mask is not None: keep_indices = ~mask.bool() x = x * keep_indices.unsqueeze(-1).float() for blk in self.blocks: x = blk(x) x = self.norm(x) return x @staticmethod def interpolate_pos_encoding(N, h): # Implementation details omitted here. pass ``` 此段代码展示了如何定义一个用于自监督学习任务中的视觉Transformer编码器结构。值得注意的是,在前向传播过程中引入了一个`mask`参数来指示哪些位置应该被遮挡掉不参与计算[^4]。 #### TensorFlow/Keras 实现 虽然原始论文主要采用PyTorch作为实验平台,但在TensorFlow社区也有开发者贡献了相应的Keras风格实现方式。下面给出了一种简化版的解码器模块示意代码片段: ```python import tensorflow as tf from tensorflow.keras.layers import Dense, LayerNormalization, Dropout def decoder_block(input_tensor, hidden_units, dropout_rate=.1): """ A single block within the decoder stack. Args: input_tensor: Input tensor from previous layer or embedding output. hidden_units: Number of units in feedforward network inside this block. dropout_rate: Rate at which to drop activations during training. Returns: Output tensor after applying one transformer decoder block operation. """ attention_output = tf.keras.layers.MultiHeadAttention( key_dim=input_tensor.shape[-1], value_dim=input_tensor.shape[-1], num_heads=8)(input_tensor, input_tensor) attention_output = Dropout(dropout_rate)(attention_output) add_attention = tf.keras.layers.Add()([input_tensor, attention_output]) normalized_addition = LayerNormalization()(add_attention) ffn_output = Dense(hidden_units*4, activation="gelu")(normalized_addition) ffn_output = Dropout(dropout_rate)(ffn_output) ffn_output = Dense(hidden_units)(ffn_output) final_output = tf.keras.layers.Add()([normalized_addition, ffn_output]) final_output = LayerNormalization()(final_output) return final_output decoder_input = tf.random.uniform(shape=(batch_size, sequence_length, feature_dimension)) for _ in range(num_decoder_layers): # Repeat according to desired number of layers decoder_input = decoder_block(decoder_input, feature_dimension) ``` 上述代码实现了单层Decoder Block的功能,并可通过循环堆叠多层形成完整的解码网络。需要注意的是实际应用时还需要考虑与特定数据集适配的具体细节以及优化策略等问题[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值