【C#深度学习之路】如何使用C#实现Yolov11模型的训练和推理
本文在Yolov5的基础上讲解Yolov11模型的改善点,可以借助之前的资料实现Yolov11模型的训练和推理
本文为原创文章,若需要转载,请注明出处。
原文地址:https://blog.csdn.net/qq_30270773/article/details/143722404
项目对应的Github地址:https://github.com/IntptrMax/YoloSharp
C#深度学习之路专栏地址:https://blog.csdn.net/qq_30270773/category_12829217.html
关注我的Github,可以获取更多资料,请为你感兴趣的项目送上一颗小星星:https://github.com/IntptrMax
项目背景
Yolov11模型是Yolov5、Yolov8模型的升级版本,引入了Transformer机制,相比Yolov5有一定的优势,也是一种使用十分广泛的视觉识别的深度学习模型。同大多数深度学习模型的跨平台使用者一样,一般都是在Python平台下进行训练,然后导出成onnx模型,供其他平台使用。这种使用方法必须经过一层转化,而且使用平台和训练平台大多不一样,存在一定的界限。
之前发布了如何使用除Python以外的平台训练Yolov5模型这份资料,估计属于公开的除Python平台外进行Yolov5训练的独一份资料,在这里继续公开发布如何使用除Python以外的平台训练Yolov11模型的相关资料,仍旧是全网独一份。如果该资料对你有帮助,请在我的Github上送我一颗小星星。该项目的Github链接为https://github.com/IntptrMax/YoloSharp
算法实现
由于Yolov11的算法衍生自Yolov8/Yolov5,两者在大多数地方相似,因此本文只介绍不同的地方,Yolov5的算法实现请参考https://blog.csdn.net/qq_30270773/article/details/143529308
,Yolov8的算法实现请参考https://blog.csdn.net/qq_30270773/article/details/143618554
模型结构
Yolov11的模型分为BackBone、Head两个主要模块。Yolov8的官方模型又可以分为n、s、l、x等几种不同的尺寸。尺寸越大,模型复杂度越高,效果越好,但消耗的资源越多。本文可以通过调整depth_multiple和width_multiple这两个参数显示不同尺寸的模型。
Yolov11的官方定义如下:
# YOLO11n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 2, C3k2, [256, False, 0.25]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 2, C3k2, [512, False, 0.25]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 2, C3k2, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 2, C3k2, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
- [-1, 2, C2PSA, [1024]] # 10
# YOLO11n head
head:
- [-1, 1, nn.Upsample, [None, 2, "nearest"]]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 2, C3k2, [512, False]] # 13
- [-1, 1, nn.Upsample, [None, 2, "nearest"]]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 2, C3k2, [256, False]] # 16 (P3/8-small)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 2, C3k2, [512, False]] # 19 (P4/16-medium)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 10], 1, Concat, [1]] # cat head P5
- [-1, 2, C3k2, [1024, True]] # 22 (P5/32-large)
- [[16, 19, 22], 1, Detect, [nc]] # Detect(P3, P4, P5)
从官方定义上看,与Yolov5不同的地方是C3模块被替换成了C3k2,这个模块的定义衍生自C2f这个模块,根据设置,使用C3k代替Bottleneck。其中C3k的实现如下:
public class C3k : Module<Tensor, Tensor>
{
private readonly Conv cv1;
private readonly Conv cv2;
private readonly Conv cv3;
public Sequential m = Sequential();
public C3k(int inChannels, int outChannels, int n = 1, bool shortcut = true, int groups = 1, float e = 0.5f) : base("C3k")
{
int c = (int)(outChannels * e);
cv1 = new Conv(inChannels, c, 1, 1);
cv2 = new Conv(inChannels, c, 1, 1);
cv3 = new Conv(2 * c, outChannels, 1);
for (int i = 0; i < n; i++)
{
this.m = this.m.append(new Bottleneck(c, c, (3, 3), shortcut, groups, e: 1.0f));
}
RegisterComponents();
}
public override Tensor forward(Tensor input)
{
return cv3.forward(cat([m.forward(cv1.forward(input)), cv2.forward(input)], 1));
}
}
另外较Yolov5、Yolov8模型,在backbone部分还引入了一个C2PSA层,在这个层中使用了Attention模块,Attention模块的实现如下:
public class Attention : Module<Tensor, Tensor>
{
private int num_heads;
private int head_dim;
private int key_dim;
private float scale;
private readonly Conv qkv;
private readonly Conv proj;
private readonly Conv pe;
public Attention(int dim, int num_heads = 8, float attn_ratio = 0.5f) : base("Attention")
{
this.num_heads = num_heads;
this.head_dim = dim / num_heads;
this.key_dim = (int)(this.head_dim * attn_ratio);
this.scale = (float)Math.Pow(key_dim, -0.5);
int nh_kd = this.key_dim * num_heads;
int h = dim + nh_kd * 2;
this.qkv = new Conv(dim, h, 1, act: false);
this.proj = new Conv(dim, dim, 1, act: false);
this.pe = new Conv(dim, dim, 3, 1, groups: dim, act: false);
RegisterComponents();
}
public override Tensor forward(Tensor x)
{
long B = x.shape[0];
long C = x.shape[1];
long H = x.shape[2];
long W = x.shape[3];
long N = H * W;
Tensor qkv = this.qkv.forward(x);
Tensor[] qkv_mix = qkv.view(B, this.num_heads, this.key_dim * 2 + this.head_dim, N).split(
[this.key_dim, this.key_dim, this.head_dim], dim: 2
);
Tensor q = qkv_mix[0];
Tensor k = qkv_mix[1];
Tensor v = qkv_mix[2];
Tensor attn = q.transpose(-2, -1).matmul(k) * this.scale;
attn = attn.softmax(dim: -1);
x = (v.matmul(attn.transpose(-2, -1))).view(B, C, H, W) + this.pe.forward(v.reshape(B, C, H, W));
x = this.proj.forward(x);
return x;
}
}
仔细阅读Attention模块代码,可以发现这个部分其实是一个多头的Self-Attention,这也是这个模型改变最大的部分。关于Self-Attention更多的资料,请参考Transformer这个项目。
其他与Yolov5相同的部分就不再解读了,详细请参考我之前发布的资料。
项目展望
目前已经实现了Yolov5、Yolov8、Yolov11的训练和推理方法,并且已经可以成功加载官方的预训练模型进行,或作为训练的基础权重。
目前官方在实现Attention使用了Self-Attention,这个部分还是消耗了不少显存资源的,如果使用Flash-Attention估计会用很小的精度损耗带来巨大的显存资源优化和计算速度提升,感兴趣的读者可以自行替换这个部分。
写在最后
使用C#深度学习项目是很多人所希望的。不过在该方向上资料很少,开发难度大。常规使用C#进行深度学习项目的方法为使用Python训练,转为Onnx模型再用C#调用。
目前我希望能够改变这一现象,希望能用纯C#平台进行训练和推理。这条路还很长,也很困难,希望有兴趣的读者能跟我一起让让C#的深度学习开发环境更为完善,以此能帮助到更多的人。
我在Github上已经将完整的代码发布了,项目地址为:https://github.com/IntptrMax/YoloSharp,期待你能在Github上送我一颗小星星。在我的Github里还GGMLSharp这个项目,这个项目也是C#平台下深度学习的开发包,希望能得到你的支持。
项目下载链接
更多推荐
所有评论(0)