ConvNeXt实战:使用ConvNeXt实现植物幼苗分类(自创,非官方)

更新时间:2023-06-10 15:11:36 阅读: 评论:0

ConvNeXt实战:使⽤ConvNeXt实现植物幼苗分类(⾃创,⾮官⽅)
ConvNeXts 完全由标准 ConvNet 模块构建,在准确性和可扩展性⽅⾯与 Transformer 竞争,实现 87.8% ImageNet top-1 准确率,在 COCO 检测和 ADE20K 分割⽅⾯优于 Swin Transformers,同时保持标准 ConvNet 的简单性和效率。
如果github不能下载,可以使⽤下⾯的连接:
ConvNexts的特点;
使⽤7×7的卷积核,在VGG、ResNet等经典的CNN模型中,使⽤的是⼩卷积核,但是ConvNexts证明了⼤卷积和的有效性。作者尝试了⼏种内核⼤⼩,包括 3、5、7、9 和 11。⽹络的性能从 79.9% (3×3) 提⾼到 80.6% (7×7),⽽⽹络的 FLOPs ⼤致保持不变, 内核⼤⼩的好处在 7×7 处达到饱和点。
使⽤GELU(⾼斯误差线性单元)激活函数。GELUs是 dropout、zoneout、Relus的综合,GELUs对于输⼊乘以⼀个0,1组成的mask,⽽该mask的⽣成则是依概率随机的依赖于输⼊。实验效果要⽐Relus与ELUs都要好。下图是实验数据:
使⽤LayerNorm⽽不是BatchNorm。
倒置瓶颈。图 3 (a) ⾄ (b) 说明了这些配置。尽管深度卷积层的 FLOPs 增加了,但由于下采样残差块的快捷 1×1 卷积层的 FLOPs 显着减少,这种变化将整个⽹络的 FLOPs 减少到 4.6G。成绩从 80.5% 提⾼到 80.6%。在 ResNet-200/Swin-B ⽅案中,这⼀步带来了更多的收益(81.9% 到 82.6%),同
时也减少了 FLOP。
ConvNeXt残差模块
残差模块是整个模型的核⼼。如下图:
代码实现:
class Block(nn.Module):
r""" ConvNeXt Block. There are two equivalent implementations:
(1) DwConv -> LayerNorm (channels_first) -> 1x1 Conv -> GELU -> 1x1 Conv; all in (N, C, H, W)
(2) DwConv -> Permute to (N, H, W, C); LayerNorm (channels_last) -> Linear -> GELU -> Linear; Permute back
We u (2) as we find it slightly faster in PyTorch
Args:
dim (int): Number of input channels.
drop_path (float): Stochastic depth rate. Default: 0.0
layer_scale_init_value (float): Init value for Layer Scale. Default: 1e-6.
"""
def__init__(lf, dim, drop_path=0., layer_scale_init_value=1e-6):
super().__init__()
lf.dwconv = nn.Conv2d(dim, dim, kernel_size=7, padding=3, groups=dim)# depthwi conv
安全标志使用导则< = LayerNorm(dim, eps=1e-6)
lf.pwconv1 = nn.Linear(dim,4* dim)# pointwi/1x1 convs, implemented with linear layers
lf.act = nn.GELU()
lf.pwconv2 = nn.Linear(4* dim, dim)韩国烤牛肉
黄连羊肝丸
lf.gamma = nn.Parameter(layer_scale_init_value * s((dim)),
requires_grad=True)if layer_scale_init_value >0el None
lf.drop_path = DropPath(drop_path)if drop_path >0.el nn.Identity()
def forward(lf, x):
input= x
x = lf.dwconv(x)
x = x.permute(0,2,3,1)# (N, C, H, W) -> (N, H, W, C)
x = lf.norm(x)
x = lf.pwconv1(x)
x = lf.act(x)
x = lf.pwconv2(x)
if lf.gamma is not None:
x = lf.gamma * x
x = x.permute(0,3,1,2)# (N, H, W, C) -> (N, C, H, W)
x =input+ lf.drop_path(x)
return x
数据增强Cutout和Mixup
ConvNext使⽤了Cutout和Mixup,为了提⾼成绩我在我的代码中也加⼊这两种增强⽅式。官⽅使⽤timm,我没有采⽤官⽅的,⽽选择⽤torchtoolbox。安装命令:
pip install torchtoolbox
Cutout实现,在transforms中。
ansform import Cutout
# 数据预处理
transform = transforms.Compo([
transforms.Resize((224,224)),
Cutout(),
transforms.ToTensor(),
transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
])
Mixup实现,在train⽅法中。需要导⼊包:ls import mixup_data, mixup_criterion
for batch_idx,(data, target)in enumerate(train_loader):
data, target = (device, non_blocking=True), (device, non_blocking=True)
data, labels_a, labels_b, lam = mixup_data(data, target, alpha)
<_grad()
output = model(data)
loss = mixup_criterion(criterion, output, labels_a, labels_b, lam)
loss.backward()
optimizer.step()
print_loss = loss.data.item()
项⽬结构
使⽤tree命令,打印项⽬结构
ConvNext_demo
├─data
│├─test
心中的远方│└─train
│├─Black-grass
│├─Charlock
│├─Cleavers
│├─Common Chickweed
│├─Common wheat
│├─Fat Hen
│├─Loo Silky-bent
│├─Maize
│├─Scentless Mayweed
│├─Shepherds Pur
│├─Small-flowered Cranesbill
│└─Sugar beet
├─datat
│├─ __init__.py
│└─ datat.py
├─Model
│└─convnext.py
├─ test1.py
├─ test2.py
└─ train_connext.py
数据集
在⼯程的根⽬录新建data⽂件夹,获取数据集后,将trian和test解压放到data⽂件夹下⾯,如下图:
导⼊模型⽂件
从官⽅的链接中找到convnext.py⽂件,将其放⼊Model⽂件夹中。如图:
安装库,并导⼊需要的库名家作品
模型⽤到了timm库,如果没有需要安装,执⾏命令:
pip install timm
新建train_connext.py⽂件,导⼊所需要的包:
import torch.optim as optim
import torch
as nn
parallel
import torch.utils.data
import torch.utils.data.distributed
ansforms as transforms
from datat.datat import SeedlingData
见微知著什么意思from torch.autograd import Variable
vnext import convnext_tiny
ls import mixup_data, mixup_criterion
ansform import Cutout
设置全局参数
爱民如子
设置使⽤GPU,设置学习率、BatchSize、epoch等参数。
# 设置全局参数
modellr =1e-4
BATCH_SIZE =8
EPOCHS =300
DEVICE = torch.device('cuda'if torch.cuda.is_available()el'cpu')
数据预处理
数据处理⽐较简单,没有做复杂的尝试,有兴趣的可以加⼊⼀些处理。
# 数据预处理
transform = transforms.Compo([
transforms.Resize((224,224)),
Cutout(),
儿童时间管理
transforms.ToTensor(),
transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
])
transform_test = transforms.Compo([
transforms.Resize((224,224)),
transforms.ToTensor(),
transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
])
数据读取
然后我们在datat⽂件夹下⾯新建 init.py和datat.py,在mydatats.py⽂件夹写⼊下⾯的代码:
说⼀下代码的核⼼逻辑。
第⼀步 建⽴字典,定义类别对应的ID,⽤数字代替类别。
第⼆步 在__init__⾥⾯编写获取图⽚路径的⽅法。测试集只有⼀层路径直接读取,训练集在train⽂件夹下⾯是类别⽂件夹,先获取到类别,再获取到具体的图⽚路径。然后使⽤sklearn中切分数据集的⽅法,按照7:3的⽐例切分训练集和验证集。
第三步 在__getitem__⽅法中定义读取单个图⽚和类别的⽅法,由于图像中有位深度32位的,所以我在读取图像的时候做了转换。
代码如下:

本文发布于:2023-06-10 15:11:36,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/1032337.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:件夹   类别   数据   模块   读取   安装
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图