|
|
""" |
|
|
对比YOLOv11 backbone和原始YOLOP backbone的差异 |
|
|
""" |
|
|
import sys |
|
|
import os |
|
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
|
|
sys.path.append(BASE_DIR) |
|
|
|
|
|
import torch |
|
|
from lib.models.YOLOP_YOLOv11 import YOLOPWithYOLOv11, YOLOv11Backbone |
|
|
from lib.models.YOLOP import get_net |
|
|
from lib.config import cfg |
|
|
from lib.config import update_config |
|
|
|
|
|
|
|
|
def count_parameters(model): |
|
|
"""统计参数数量""" |
|
|
total = sum(p.numel() for p in model.parameters()) |
|
|
trainable = sum(p.numel() for p in model.parameters() if p.requires_grad) |
|
|
return total, trainable |
|
|
|
|
|
|
|
|
def get_model_size(model): |
|
|
"""估算模型大小(MB)""" |
|
|
param_size = sum(p.numel() * p.element_size() for p in model.parameters()) |
|
|
buffer_size = sum(b.numel() * b.element_size() for b in model.buffers()) |
|
|
size_mb = (param_size + buffer_size) / (1024 ** 2) |
|
|
return size_mb |
|
|
|
|
|
|
|
|
def test_inference_speed(model, input_size=(1, 3, 640, 640), num_runs=100, warmup=10): |
|
|
"""测试推理速度""" |
|
|
import time |
|
|
model.eval() |
|
|
device = next(model.parameters()).device |
|
|
|
|
|
|
|
|
dummy_input = torch.randn(input_size).to(device) |
|
|
|
|
|
|
|
|
with torch.no_grad(): |
|
|
for _ in range(warmup): |
|
|
_ = model(dummy_input) |
|
|
|
|
|
|
|
|
torch.cuda.synchronize() if device.type == 'cuda' else None |
|
|
start_time = time.time() |
|
|
|
|
|
with torch.no_grad(): |
|
|
for _ in range(num_runs): |
|
|
_ = model(dummy_input) |
|
|
torch.cuda.synchronize() if device.type == 'cuda' else None |
|
|
|
|
|
end_time = time.time() |
|
|
avg_time = (end_time - start_time) / num_runs * 1000 |
|
|
fps = 1000 / avg_time |
|
|
|
|
|
return avg_time, fps |
|
|
|
|
|
|
|
|
def main(): |
|
|
print("="*80) |
|
|
print("Backbone Comparison: YOLOv11 vs Original YOLOP") |
|
|
print("="*80) |
|
|
|
|
|
|
|
|
print("\n1. Creating models...") |
|
|
|
|
|
print(" Creating YOLOv11-based YOLOP...") |
|
|
model_yolov11 = YOLOPWithYOLOv11(num_seg_class=2) |
|
|
|
|
|
print(" Creating original YOLOP...") |
|
|
try: |
|
|
model_original = get_net(cfg) |
|
|
except Exception as e: |
|
|
print(f" Failed to create original YOLOP: {e}") |
|
|
model_original = None |
|
|
|
|
|
print("✓ Models created") |
|
|
|
|
|
|
|
|
print("\n" + "="*80) |
|
|
print("Parameter Comparison") |
|
|
print("="*80) |
|
|
|
|
|
|
|
|
yolov11_backbone_params, _ = count_parameters(model_yolov11.backbone) |
|
|
yolov11_total_params, _ = count_parameters(model_yolov11) |
|
|
yolov11_size = get_model_size(model_yolov11) |
|
|
|
|
|
print("\nYOLOv11-based YOLOP:") |
|
|
print(f" Backbone parameters: {yolov11_backbone_params:,}") |
|
|
print(f" Total parameters: {yolov11_total_params:,}") |
|
|
print(f" Model size: {yolov11_size:.2f} MB") |
|
|
|
|
|
if model_original: |
|
|
original_total_params, _ = count_parameters(model_original) |
|
|
original_size = get_model_size(model_original) |
|
|
|
|
|
print("\nOriginal YOLOP:") |
|
|
print(f" Total parameters: {original_total_params:,}") |
|
|
print(f" Model size: {original_size:.2f} MB") |
|
|
|
|
|
print("\nDifference:") |
|
|
param_diff = yolov11_total_params - original_total_params |
|
|
size_diff = yolov11_size - original_size |
|
|
print(f" Parameters: {param_diff:+,} ({param_diff/original_total_params*100:+.2f}%)") |
|
|
print(f" Size: {size_diff:+.2f} MB ({size_diff/original_size*100:+.2f}%)") |
|
|
|
|
|
|
|
|
print("\n" + "="*80) |
|
|
print("Output Shape Comparison") |
|
|
print("="*80) |
|
|
|
|
|
test_input = torch.randn(1, 3, 640, 640) |
|
|
|
|
|
print("\nYOLOv11-based YOLOP:") |
|
|
with torch.no_grad(): |
|
|
det_out, da_out, ll_out = model_yolov11(test_input) |
|
|
print(f" Detection output: {type(det_out)}") |
|
|
if isinstance(det_out, tuple): |
|
|
for i, out in enumerate(det_out): |
|
|
if isinstance(out, list): |
|
|
print(f" Element {i}: list with {len(out)} items") |
|
|
for j, item in enumerate(out): |
|
|
print(f" [{j}] {item.shape}") |
|
|
else: |
|
|
print(f" Element {i}: {out.shape}") |
|
|
print(f" Drivable area output: {da_out.shape}") |
|
|
print(f" Lane line output: {ll_out.shape}") |
|
|
|
|
|
if model_original: |
|
|
print("\nOriginal YOLOP:") |
|
|
with torch.no_grad(): |
|
|
det_out_orig, da_out_orig, ll_out_orig = model_original(test_input) |
|
|
print(f" Detection output: {type(det_out_orig)}") |
|
|
if isinstance(det_out_orig, tuple): |
|
|
for i, out in enumerate(det_out_orig): |
|
|
if isinstance(out, list): |
|
|
print(f" Element {i}: list with {len(out)} items") |
|
|
for j, item in enumerate(out): |
|
|
print(f" [{j}] {item.shape}") |
|
|
else: |
|
|
print(f" Element {i}: {out.shape}") |
|
|
print(f" Drivable area output: {da_out_orig.shape}") |
|
|
print(f" Lane line output: {ll_out_orig.shape}") |
|
|
|
|
|
|
|
|
print("\n" + "="*80) |
|
|
print("Inference Speed Comparison (CPU)") |
|
|
print("="*80) |
|
|
|
|
|
print("\nTesting YOLOv11-based YOLOP...") |
|
|
try: |
|
|
avg_time_yolov11, fps_yolov11 = test_inference_speed(model_yolov11, num_runs=50, warmup=5) |
|
|
print(f" Average time: {avg_time_yolov11:.2f} ms") |
|
|
print(f" FPS: {fps_yolov11:.2f}") |
|
|
except Exception as e: |
|
|
print(f" Failed: {e}") |
|
|
avg_time_yolov11, fps_yolov11 = None, None |
|
|
|
|
|
if model_original: |
|
|
print("\nTesting original YOLOP...") |
|
|
try: |
|
|
avg_time_original, fps_original = test_inference_speed(model_original, num_runs=50, warmup=5) |
|
|
print(f" Average time: {avg_time_original:.2f} ms") |
|
|
print(f" FPS: {fps_original:.2f}") |
|
|
|
|
|
if avg_time_yolov11 and avg_time_original: |
|
|
time_diff = avg_time_yolov11 - avg_time_original |
|
|
print(f"\nSpeed difference: {time_diff:+.2f} ms ({time_diff/avg_time_original*100:+.2f}%)") |
|
|
except Exception as e: |
|
|
print(f" Failed: {e}") |
|
|
|
|
|
|
|
|
print("\n" + "="*80) |
|
|
print("Backbone Architecture Comparison") |
|
|
print("="*80) |
|
|
|
|
|
print("\nYOLOv11 Backbone:") |
|
|
print(f" Number of layers: {len(model_yolov11.backbone.layers)}") |
|
|
print(f" Output feature indices: {model_yolov11.backbone.out_indices}") |
|
|
print(" Layer types:") |
|
|
for i, layer in enumerate(model_yolov11.backbone.layers): |
|
|
print(f" [{i:2d}] {type(layer).__name__}") |
|
|
|
|
|
if model_original and hasattr(model_original, 'model'): |
|
|
print("\nOriginal YOLOP Backbone:") |
|
|
print(f" Number of layers: {len(model_original.model)}") |
|
|
print(" Layer types (first 10):") |
|
|
for i in range(min(10, len(model_original.model))): |
|
|
layer = model_original.model[i] |
|
|
print(f" [{i:2d}] {type(layer).__name__}") |
|
|
|
|
|
|
|
|
print("\n" + "="*80) |
|
|
print("Summary") |
|
|
print("="*80) |
|
|
print("\nKey differences:") |
|
|
print(" ✓ YOLOv11 uses newer modules: C3k2, C2PSA, SPPF") |
|
|
print(" ✓ Original YOLOP uses: Focus, BottleneckCSP, SPP") |
|
|
print(" ✓ YOLOv11 backbone can be initialized with pre-trained weights") |
|
|
print(" ✓ Both models have the same output format (compatible with training code)") |
|
|
|
|
|
print("\nRecommendations:") |
|
|
print(" • Use YOLOv11 backbone with pre-trained weights for better initial performance") |
|
|
print(" • Consider freezing backbone for faster training of detection/segmentation heads") |
|
|
print(" • Monitor both training speed and accuracy during experiments") |
|
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
|
main() |
|
|
|