YOLOv9模型重新参数化,将yolo.pt转为yolo-converted.pt

1、yolo-m转为yolo-m-converted

在我们使用train_dual.py训练好自己的模型后,我们会得到yolo系列的模型,比如我使用yolov9-m在数据集CityScapes上训练后,得到cityscapes-yolov9-m.pt,然后运行yolov9-m_to_converted.py代码得到cityscapes-yolov9-m-converted.pt,代码如下:记得修改nc为自己数据集的分类数,然后修改自己的加载模型路径和模型保存路径。

#!/usr/bin/env python
# coding: utf-8



import torch
from models.yolo import Model

# ## Convert YOLOv9-M

# In[ ]:


device = torch.device("cpu")
cfg = "../models/detect/gelan-m.yaml"
model = Model(cfg, ch=3, nc=8, anchors=3)
#model = model.half()
model = model.to(device)
_ = model.eval()
ckpt = torch.load('../runs/train/YOLOv9-m训练Cityscapes/weights/cityscapes-yolov9-m.pt', map_location='cpu')
model.names = ckpt['model'].names
model.nc = ckpt['model'].nc


# In[ ]:


idx = 0
for k, v in model.state_dict().items():
    if "model.{}.".format(idx) in k:
        if idx < 22:
            kr = k.replace("model.{}.".format(idx), "model.{}.".format(idx+1))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
        elif "model.{}.cv2.".format(idx) in k:
            kr = k.replace("model.{}.cv2.".format(idx), "model.{}.cv4.".format(idx+16))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
        elif "model.{}.cv3.".format(idx) in k:
            kr = k.replace("model.{}.cv3.".format(idx), "model.{}.cv5.".format(idx+16))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
        elif "model.{}.dfl.".format(idx) in k:
            kr = k.replace("model.{}.dfl.".format(idx), "model.{}.dfl2.".format(idx+16))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
    else:
        while True:
            idx += 1
            if "model.{}.".format(idx) in k:
                break
        if idx < 22:
            kr = k.replace("model.{}.".format(idx), "model.{}.".format(idx+1))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
        elif "model.{}.cv2.".format(idx) in k:
            kr = k.replace("model.{}.cv2.".format(idx), "model.{}.cv4.".format(idx+16))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
        elif "model.{}.cv3.".format(idx) in k:
            kr = k.replace("model.{}.cv3.".format(idx), "model.{}.cv5.".format(idx+16))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
        elif "model.{}.dfl.".format(idx) in k:
            kr = k.replace("model.{}.dfl.".format(idx), "model.{}.dfl2.".format(idx+16))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
_ = model.eval()


# In[ ]:


m_ckpt = {'model': model.half(),
          'optimizer': None,
          'best_fitness': None,
          'ema': None,
          'updates': None,
          'opt': None,
          'git': None,
          'date': None,
          'epoch': -1}
torch.save(m_ckpt, "./cityscapes-yolov9-m-converted.pt")


运行效果如下:

2、 使用重参后的模型进行推理

得到cityscapes-yolov9-m-converted.pt后,权重大小为38.7MB,使用detect.py进行检测

可以看到模型信息为:377 layers, 19926616 parameters, 9048 gradients, 76.0 GFLOPs

此时在使用原来的cityscapes-yolov9-m.pt,权重大小为63.1MB,进行检测,效果如下:

可以看到模型信息为:588 layers, 32563288 parameters, 0 gradients, 130.7 GFLOPs

对于示例图片,两个模型都做到了一致的检测结果:7 cars, 2 persons, 1 rider, 1 bicycle,这检测效果还是很好的,很多远一点、小一点的目标我自己肉眼都没看到。

无论是推理速度还是模型参数,经过重参后都有所提升,并且官方称两者的精度是一致的,做到了既保留了较高的精度,又缩小了模型复杂度。

但是!虽然经过重参后的模型能够使用detect.py进行检测推理,目前还无法使用val或者val_dual.py对重新参数化的模型进行验证,比如cityscapes-yolov9-m.pt经过参数重新化得到cityscapes-yolov9-m-converted.pt,将converted模型用于验证会报错,只能等后续官方维护了。

3、 yolo-s转为yolo-s-converted

运行yolov9-s_to_converted.py代码得到yolov9-s-converted.pt,代码如下:记得修改nc为自己数据集的分类数,然后修改自己的加载模型路径和模型保存路径。

#!/usr/bin/env python
# coding: utf-8



import torch
from models.yolo import Model

# ## Convert YOLOv9-S

# In[ ]:


device = torch.device("cpu")
cfg = "../models/detect/gelan-s.yaml"
model = Model(cfg, ch=3, nc=80, anchors=3)
#model = model.half()
model = model.to(device)
_ = model.eval()
ckpt = torch.load('../models/pretrained-weights/yolov9-s.pt', map_location='cpu')
model.names = ckpt['model'].names
model.nc = ckpt['model'].nc


# In[ ]:


idx = 0
for k, v in model.state_dict().items():
    if "model.{}.".format(idx) in k:
        if idx < 22:
            kr = k.replace("model.{}.".format(idx), "model.{}.".format(idx))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
        elif "model.{}.cv2.".format(idx) in k:
            kr = k.replace("model.{}.cv2.".format(idx), "model.{}.cv4.".format(idx+7))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
        elif "model.{}.cv3.".format(idx) in k:
            kr = k.replace("model.{}.cv3.".format(idx), "model.{}.cv5.".format(idx+7))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
        elif "model.{}.dfl.".format(idx) in k:
            kr = k.replace("model.{}.dfl.".format(idx), "model.{}.dfl2.".format(idx+7))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
    else:
        while True:
            idx += 1
            if "model.{}.".format(idx) in k:
                break
        if idx < 22:
            kr = k.replace("model.{}.".format(idx), "model.{}.".format(idx))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
        elif "model.{}.cv2.".format(idx) in k:
            kr = k.replace("model.{}.cv2.".format(idx), "model.{}.cv4.".format(idx+7))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
        elif "model.{}.cv3.".format(idx) in k:
            kr = k.replace("model.{}.cv3.".format(idx), "model.{}.cv5.".format(idx+7))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
        elif "model.{}.dfl.".format(idx) in k:
            kr = k.replace("model.{}.dfl.".format(idx), "model.{}.dfl2.".format(idx+7))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
_ = model.eval()


# In[ ]:


m_ckpt = {'model': model.half(),
          'optimizer': None,
          'best_fitness': None,
          'ema': None,
          'updates': None,
          'opt': None,
          'git': None,
          'date': None,
          'epoch': -1}
torch.save(m_ckpt, "./test_yolov9-s-converted.pt")


4、 yolo-c转为yolo-c-converted

运行yolov9-c_to_converted.py代码得到yolov9-c-converted.pt,代码如下:记得修改nc为自己数据集的分类数,然后修改自己的加载模型路径和模型保存路径。

#!/usr/bin/env python
# coding: utf-8



import torch
from models.yolo import Model

# ## Convert YOLOv9-C

# In[ ]:


device = torch.device("cpu")
cfg = "../models/detect/gelan-c.yaml"
model = Model(cfg, ch=3, nc=8, anchors=3)
#model = model.half()
model = model.to(device)
_ = model.eval()
ckpt = torch.load('../runs/train/YOLOv9-m训练Cityscapes/weights/best.pt', map_location='cpu')
model.names = ckpt['model'].names
model.nc = ckpt['model'].nc


# In[ ]:



idx = 0
for k, v in model.state_dict().items():
    if "model.{}.".format(idx) in k:
        if idx < 22:
            kr = k.replace("model.{}.".format(idx), "model.{}.".format(idx+1))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
        elif "model.{}.cv2.".format(idx) in k:
            kr = k.replace("model.{}.cv2.".format(idx), "model.{}.cv4.".format(idx+16))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
        elif "model.{}.cv3.".format(idx) in k:
            kr = k.replace("model.{}.cv3.".format(idx), "model.{}.cv5.".format(idx+16))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
        elif "model.{}.dfl.".format(idx) in k:
            kr = k.replace("model.{}.dfl.".format(idx), "model.{}.dfl2.".format(idx+16))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
    else:
        while True:
            idx += 1
            if "model.{}.".format(idx) in k:
                break
        if idx < 22:
            kr = k.replace("model.{}.".format(idx), "model.{}.".format(idx+1))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
        elif "model.{}.cv2.".format(idx) in k:
            kr = k.replace("model.{}.cv2.".format(idx), "model.{}.cv4.".format(idx+16))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
        elif "model.{}.cv3.".format(idx) in k:
            kr = k.replace("model.{}.cv3.".format(idx), "model.{}.cv5.".format(idx+16))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
        elif "model.{}.dfl.".format(idx) in k:
            kr = k.replace("model.{}.dfl.".format(idx), "model.{}.dfl2.".format(idx+16))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
_ = model.eval()


# In[ ]:


m_ckpt = {'model': model.half(),
          'optimizer': None,
          'best_fitness': None,
          'ema': None,
          'updates': None,
          'opt': None,
          'git': None,
          'date': None,
          'epoch': -1}
torch.save(m_ckpt, "./cityscapes-yolov9-c-converted.pt")


5、 yolo-e转为yolo-e-converted

运行yolov9-e_to_converted.py代码得到yolov9-e-converted.pt,代码如下:记得修改nc为自己数据集的分类数,然后修改自己的加载模型路径和模型保存路径。

#!/usr/bin/env python
# coding: utf-8



import torch
from models.yolo import Model

# ## Convert YOLOv9-E

# In[ ]:


device = torch.device("cpu")
cfg = "../models/detect/gelan-e.yaml"
model = Model(cfg, ch=3, nc=8, anchors=3)
#model = model.half()
model = model.to(device)
_ = model.eval()
ckpt = torch.load('../runs/train/YOLOv9-m训练Cityscapes/weights/best.pt', map_location='cpu')
model.names = ckpt['model'].names
model.nc = ckpt['model'].nc


# In[ ]:


idx = 0
for k, v in model.state_dict().items():
    if "model.{}.".format(idx) in k:
        if idx < 29:
            kr = k.replace("model.{}.".format(idx), "model.{}.".format(idx))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
        elif idx < 42:
            kr = k.replace("model.{}.".format(idx), "model.{}.".format(idx+7))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
        elif "model.{}.cv2.".format(idx) in k:
            kr = k.replace("model.{}.cv2.".format(idx), "model.{}.cv4.".format(idx+7))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
        elif "model.{}.cv3.".format(idx) in k:
            kr = k.replace("model.{}.cv3.".format(idx), "model.{}.cv5.".format(idx+7))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
        elif "model.{}.dfl.".format(idx) in k:
            kr = k.replace("model.{}.dfl.".format(idx), "model.{}.dfl2.".format(idx+7))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
    else:
        while True:
            idx += 1
            if "model.{}.".format(idx) in k:
                break
        if idx < 29:
            kr = k.replace("model.{}.".format(idx), "model.{}.".format(idx))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
        elif idx < 42:
            kr = k.replace("model.{}.".format(idx), "model.{}.".format(idx+7))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
        elif "model.{}.cv2.".format(idx) in k:
            kr = k.replace("model.{}.cv2.".format(idx), "model.{}.cv4.".format(idx+7))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
        elif "model.{}.cv3.".format(idx) in k:
            kr = k.replace("model.{}.cv3.".format(idx), "model.{}.cv5.".format(idx+7))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
        elif "model.{}.dfl.".format(idx) in k:
            kr = k.replace("model.{}.dfl.".format(idx), "model.{}.dfl2.".format(idx+7))
            model.state_dict()[k] -= model.state_dict()[k]
            model.state_dict()[k] += ckpt['model'].state_dict()[kr]
            print(k, "perfectly matched!!")
_ = model.eval()


# In[ ]:


m_ckpt = {'model': model.half(),
          'optimizer': None,
          'best_fitness': None,
          'ema': None,
          'updates': None,
          'opt': None,
          'git': None,
          'date': None,
          'epoch': -1}
torch.save(m_ckpt, "./cityscapes-yolov9-e-converted.pt")


### 加载 `best.pt` 权重文件中的 `weights` 参数 在 PyTorch 和 YOLO 模型中,加载 `.pt` 文件通常涉及使用 `torch.load()` 函数来读取保存的模型状态字典。对于 `best.pt` 这样的权重文件,可以通过以下方式实现加载并应用到模型中。 #### 使用 `state_dict` 方法加载权重 `.pt` 文件通常是通过 `torch.save(model.state_dict(), &#39;path_to_file&#39;)` 保存的模型参数集合。要加载这些参数,可以按照以下方法执行: ```python import torch # 定义模型架构 (假设为 model_class) model = model_class() # 加载 .pt 文件中的 state_dict checkpoint = torch.load(&#39;best.pt&#39;, map_location=torch.device(&#39;cpu&#39;)) # 如果 GPU 不可用,则指定 CPU # 提取 weights 参数 if &#39;state_dict&#39; in checkpoint: model_state_dict = checkpoint[&#39;state_dict&#39;] else: model_state_dict = checkpoint # 将提取的权重加载到模型中 model.load_state_dict(model_state_dict) # 设置模型为评估模式 model.eval() ``` 上述代码片段展示了如何从 `best.pt` 中加载权重,并将其应用于已定义好的模型实例[^1]。 #### 转换 `.pt` 到 `.weights` 如果需要将 `.pt` 文件转换成 Darknet 的 `.weights` 格式,可以根据以下逻辑完成转换过程。此部分主要针对 YOLOv3 或其他基于 Darknet 架构的模型设计。 ```python from collections import OrderedDict def convert_pt_to_weights(pt_path, output_weights_path): """ Convert a PyTorch (.pt) file to Darknet&#39;s binary format (.weights). Args: pt_path (str): Path of the input .pt file. output_weights_path (str): Output path for saving the converted .weights file. """ # Load the .pt file checkpoint = torch.load(pt_path, map_location=&#39;cpu&#39;) state_dict = checkpoint[&#39;state_dict&#39;] if &#39;state_dict&#39; in checkpoint else checkpoint # Initialize an ordered dictionary and write header information weights_ordered_dict = OrderedDict() with open(output_weights_path, &#39;wb&#39;) as f: seen_keys = set() # Write headers manually or based on your network structure major_version = minor_version = revision = 0 np.array([major_version, minor_version, revision], dtype=np.int32).tofile(f) total_elements_written = 0 for key, value in state_dict.items(): if any(substring in key for substring in [&#39;running_mean&#39;, &#39;running_var&#39;]): continue if key not in seen_keys: seen_keys.add(key) # Reshape tensor into C-contiguous order value_np = value.cpu().numpy() value_np = value_np.reshape(-1) if len(value_np.shape) > 1 else value_np # Write data type info first followed by actual values dtypes_map = { torch.float32: b&#39;\x00\x00&#39;, torch.int32: b&#39;\x01\x00&#39; } f.write(dtypes_map[value.dtype]) value.tofile(f) total_elements_written += value.numel() print(f"Total elements written: {total_elements_written}") convert_pt_to_weights(&#39;best.pt&#39;, &#39;converted.weights&#39;) ``` 该脚本实现了从 `.pt` 文件向 `.weights` 文件的转换功能[^2][^4]。 #### 解析 `.cfg` 并加载自定义权重 当涉及到特定配置文件(如 `.cfg`),需先解析其网络结构再逐层匹配对应的权重。以下是简化版流程说明: 1. **解析 `.cfg` 文件**:利用 Python 编写解析器获取每一层模块及其超参。 2. **初始化模型对象**:依据解析后的信息创建相应的神经网络组件。 3. **映射权重至各层**:遍历预存的权重数组,按顺序填充 BatchNorm 及 Convolutional 层的相关字段。 具体实现可参考官方文档或其他开源项目[^3]。 --- ###
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜深人静打代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值