标题转载自AI Studio

标题项目链接https://aistudio.baidu.com/aistudio/projectdetail/3476364

项目简介

本项目提供了ConvNeXt的飞桨版本的预训练权重以及模型文件。权重由PyTorch转换而来。并且通过在ImageNet 1K测试集进行精度校验。模型文件请见ConvNeXt.py。本项目旨在提供飞桨版本的模型权重、模型文件和验证精度,对于模型的理解并没有描述,如果想深入了解模型,请见:
ConvNeXt:探索CNN网络的极限潜力

ConvNeXt

模型文件请见ConvNeXt.py, 下面说一下PyTorch模型转换PaddlePaddle模型的注意事项。

  • 线性层PyTorch与PaddlePaddle的权重转换需要转置一下
  • DropPath层需要自定义。我是参考了这篇文章 PiT:结合池化层的视觉 Transformer 网络
  • PaddlePaddle在涉及维度的参数时,多用axis,PyTorch则是dim
  • 有时需要自定义参数,PaddlePaddle的API在这里
  • PaddlePaddle无permute,而是采用了transpose
  • 其他简单的API映射请见这里

在这个py文件的第134和135行,给weight和bias乘了一个1,也就是没有做什么处理,这个是PyTorch的写法,PaddlePaddle的写法我还不会,麻烦知道的大佬回复一下。

权重

这里介绍一下本次精度验证的权重文件,总共有5个,分别代表了不同大小和版本的ConvNeXt。
首先来总览一下。

nameresolutionacc@1#paramsFLOPs
ConvNeXt-T224x22482.128M4.5G
ConvNeXt-S224x22483.150M8.7G
ConvNeXt-B224x22483.889M15.4G
ConvNeXt-L224x22484.3198M34.4G
ConvNeXt-XL384x38487.8350M179.0G

由于文件数量限制,这里只展示这5个不同版本,以及做精度验证。22K上的权重将放在其他数据集里在这里。这个项目用的数据集在ConvNeXt预训练模型PaddlePaddle版本里,欢迎大家下载使用。下面来做精度验证8!

精度验证

以下精度验证代码参考寂寞你快进去大佬的写法。

# 解压ImageNet 1K数据集
!mkdir data/ILSVRC2012
!tar -xf ~/data/data68594/ILSVRC2012_img_val.tar -C ~/data/ILSVRC2012
import os
import cv2
import numpy as np
import warnings
import paddle
import paddle.vision.transforms as T
from PIL import Image
warnings.filterwarnings('ignore')

# 构建数据集
class ILSVRC2012(paddle.io.Dataset):
    def __init__(self, root, label_list, transform, backend='pil'):
        self.transform = transform
        self.root = root
        self.label_list = label_list
        self.backend = backend
        self.load_datas()

    def load_datas(self):
        self.imgs = []
        self.labels = []
        with open(self.label_list, 'r') as f:
            for line in f:
                img, label = line[:-1].split(' ')
                self.imgs.append(os.path.join(self.root, img))
                self.labels.append(int(label))

    def __getitem__(self, idx):
        label = self.labels[idx]
        image = self.imgs[idx]
        if self.backend=='cv2':
            image = cv2.imread(image)
        else:
            image = Image.open(image).convert('RGB')
        image = self.transform(image)
        return image.astype('float32'), np.array(label).astype('int64')

    def __len__(self):
        return len(self.imgs)


val_transforms = T.Compose([
    T.Resize(int(224 / 0.96), interpolation='bicubic'),
    T.CenterCrop(224),
    T.ToTensor(),
    T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])

# 配置模型
from ConvNeXt import convnext_tiny, convnext_small, convnext_base, convnext_large, convnext_xlarge

cvt_t = convnext_tiny()
cvt_s = convnext_small()
cvt_b = convnext_base()
cvt_l = convnext_large()
cvt_x = convnext_xlarge()

W0211 21:12:49.976547   686 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 10.1, Runtime API Version: 10.1
W0211 21:12:49.982038   686 device_context.cc:465] device: 0, cuDNN Version: 7.6.

cvt_t.load_dict(paddle.load('data/data127804/convnext_tiny_1k_224_ema.pdparams'))
cvt_t = paddle.Model(cvt_t)
cvt_t.prepare(metrics=paddle.metric.Accuracy(topk=(1, 5)))

cvt_s.load_dict(paddle.load('data/data127804/convnext_small_1k_224_ema.pdparams'))
cvt_s = paddle.Model(cvt_s)
cvt_s.prepare(metrics=paddle.metric.Accuracy(topk=(1, 5)))

cvt_b.load_dict(paddle.load('data/data127804/convnext_base_1k_224_ema.pdparams'))
cvt_b = paddle.Model(cvt_b)
cvt_b.prepare(metrics=paddle.metric.Accuracy(topk=(1, 5)))

cvt_l.load_dict(paddle.load('data/data127804/convnext_large_1k_224_ema.pdparams'))
cvt_l = paddle.Model(cvt_l)
cvt_l.prepare(metrics=paddle.metric.Accuracy(topk=(1, 5)))

cvt_x.load_dict(paddle.load('data/data127804/convnext_xlarge_22k_1k_384_ema.pdparams'))
cvt_x = paddle.Model(cvt_x)
cvt_x.prepare(metrics=paddle.metric.Accuracy(topk=(1, 5)))
val_dataset = ILSVRC2012('data/ILSVRC2012', transform=val_transforms, label_list='data/data68594/val_list.txt', backend='pil')
# 模型验证
acc = cvt_t.evaluate(val_dataset, batch_size=128, num_workers=0, verbose=1)
print(acc)
Eval begin...
step 391/391 [==============================] - acc_top1: 0.8199 - acc_top5: 0.9588 - 1s/step          
Eval samples: 50000
{'acc_top1': 0.81992, 'acc_top5': 0.9588}
val_dataset = ILSVRC2012('data/ILSVRC2012', transform=val_transforms, label_list='data/data68594/val_list.txt', backend='pil')
# 模型验证
acc = cvt_s.evaluate(val_dataset, batch_size=128, num_workers=0, verbose=1)
print(acc)
Eval begin...
step 391/391 [==============================] - acc_top1: 0.8308 - acc_top5: 0.9652 - 1s/step          
Eval samples: 50000
{'acc_top1': 0.83078, 'acc_top5': 0.96516}
val_dataset = ILSVRC2012('data/ILSVRC2012', transform=val_transforms, label_list='data/data68594/val_list.txt', backend='pil')
# 模型验证
acc = cvt_b.evaluate(val_dataset, batch_size=128, num_workers=0, verbose=1)
print(acc)
Eval begin...
step 391/391 [==============================] - acc_top1: 0.8384 - acc_top5: 0.9683 - 2s/step          
Eval samples: 50000
{'acc_top1': 0.8384, 'acc_top5': 0.9683}
val_dataset = ILSVRC2012('data/ILSVRC2012', transform=val_transforms, label_list='data/data68594/val_list.txt', backend='pil')
# 模型验证
acc = cvt_l.evaluate(val_dataset, batch_size=128, num_workers=0, verbose=1)
print(acc)
Eval begin...
step 391/391 [==============================] - acc_top1: 0.8435 - acc_top5: 0.9697 - 2s/step          
Eval samples: 50000
{'acc_top1': 0.84346, 'acc_top5': 0.9697}
# resize到384

val384_transforms = T.Compose([
    T.Resize((384, 384), interpolation='bicubic'),
  #  T.CenterCrop(224),
    T.ToTensor(),
    T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
val_dataset = ILSVRC2012('data/ILSVRC2012', transform=val384_transforms, label_list='data/data68594/val_list.txt', backend='pil')
# 模型验证
acc = cvt_x.evaluate(val_dataset, batch_size=128, num_workers=0, verbose=1)
print(acc)
Eval begin...
step 391/391 [==============================] - acc_top1: 0.8775 - acc_top5: 0.9856 - 5s/step          
Eval samples: 50000
{'acc_top1': 0.8775, 'acc_top5': 0.98556}

总结

部分模型的准确率有点点不一样是不能避免的,PyTorch转PaddlePaddle的过程或者数据处理的过程都会有一点点不一样。但是总的来说,并没有大的不同,所以模型转换是成功的。

ConvNeXt算是最强的卷积分类网络了。在现有Transformer统治的情况下,ConvNeXt仍然以极强的建模能力为卷积网络扳回一城。不过说实话,卷积比Transformer好的一点且无法代替的一点就是卷积的输入可以是任何尺度,Transformer则较为麻烦。

关于作者

姓名:张晋

学校:上海应用技术大学,研二

研究方向:CV,显著目标检测

AI Stidio链接:https://aistudio.baidu.com/aistudio/personalcenter/thirdview/635490

github链接:https://github.com/zhangjin12138

个人荣誉:PPDE。CCF会员。《第三届中国AI+创新创业大赛:半监督学习目标定位竞赛》第一名。《CCF真实场景下的水表读数自动识别》第一名。一篇二区SCI。N篇待投。

如果喜欢这个项目的话,欢迎点赞关注。


Logo

学大模型,用大模型上飞桨星河社区!每天8点V100G算力免费领!免费领取ERNIE 4.0 100w Token >>>

更多推荐