AI相关

AI 工程四阶段学习路线图:从入门到前沿

写在前面:为什么要懂这四个阶段? 很多人仍然认为"写好提示词就够了"——这已经过时了。这四个阶段不是孤立的知识点,而是一个完整的能力升级路径。 认知误区: 阶段一:提示工程 = AI 对话的精髓 阶段二:上下文工程 = 拉长对话 阶段三:驾驭工程 = 让 AI 更聪明 阶段四:循环工程 = 自动化提示 真相:

Continue reading →

从驾驭到循环:每次都要人启动,算不上自主

场景:系统很可靠,但人还是最慢的环节 想象一个场景:你有一个完美的 Harness 系统。AI 能够: 分析需求并写代码 运行测试并验证输出 修复发现的 bug 优化性能和代码质量 系统每一步都工作得很好,可靠、可预测、可控。但是,每当发现一个 bug,你必须说"修复这个 bug"。然后又发现另一个 bug,你又说"修复这个 too"。接着是一个新功能请求,你说"实现这个功能"。

Continue reading →

YOLO Rust 部署实战

第 9 章:Rust 使用 YOLO 完整教程 Rust 凭借内存安全、零成本抽象、极致性能三大特性,成为 YOLO 生产级部署的终极选择。在边缘计算、高并发场景下,Rust 的性能优势尤为显著。

Continue reading →

YOLO Golang 部署实战

第 8 章:Golang 使用 YOLO 完整教程 Go 语言凭借其高性能、低内存占用、原生并发特性,成为工业级 YOLO 部署的首选语言之一。本章将详细介绍 Go 生态中 YOLO 的完整实现方案。

Continue reading →

YOLO 常见问题与解决方案

环境安装问题 Q1: CUDA 不可用,只使用 CPU? 首先确认 NVIDIA 驱动版本是否支持所需 CUDA 版本,驱动版本过低会导致 CUDA 不可用: bash 1 2 3 4 5 6 # 检查驱动版本(Driver Version 需 >= 支持CUDA的最低版本) nvidia-smi # 检查CUDA工具包版本 nvcc --version # 重新安装对应CUDA版本的PyTorch pip3 install torch torchvision --index-url https://download.pytorch.org/whl/cu121 如果 nvidia-smi 显示 CUDA 版本但 PyTorch 仍使用 CPU,说明安装的是 CPU 版 PyTorch。卸载后用 --index-url 重新安装 CUDA 版本。CUDA 11.8 用户将 URL 中的 cu121 替换为 cu118。建议使用 conda 或 venv 虚拟环境隔离不同 CUDA 版本的 PyTorch,避免系统级冲突。

Continue reading →

YOLO 部署落地:模型导出与多平台部署

模型导出(17 种格式支持) Ultralytics 统一导出 API python 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 from ultralytics import YOLO model = YOLO("yolo26n.pt") # ========== 各种格式导出 ========== # 1. ONNX(跨平台通用) model.export(format="onnx", simplify=True, dynamic=True) # 2. TensorRT(NVIDIA GPU最佳) model.export(format="engine", half=True, workspace=4) # 3. OpenVINO(Intel CPU最佳) model.export(format="openvino", half=True) # 4. CoreML(Apple设备) model.export(format="coreml", int8=True) # 5. TFLite(Android/iOS移动端) model.export(format="tflite", int8=True) # 6. NCNN(移动端) model.export(format="ncnn") # 7. PaddlePaddle model.export(format="paddle") 各版本导出兼容性 格式 YOLOv8 YOLO11 YOLO26 ONNX ✅ ✅ ✅ 最佳 TensorRT ✅ ✅ ✅ 无 NMS 更简单 OpenVINO ✅ ✅ ✅ TFLite ✅ ✅ ✅ NCNN ✅ ✅ ✅ Python 部署实战 ONNX Runtime 部署 python 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import onnxruntime as ort import cv2 import numpy as np # 加载ONNX模型 session = ort.InferenceSession( "yolo26n.onnx", providers=["CUDAExecutionProvider", "CPUExecutionProvider"] ) def preprocess(image, imgsz=640): """图片预处理""" img = cv2.resize(image, (imgsz, imgsz)) img = img.transpose(2, 0, 1) / 255.0 return img[np.newaxis].astype(np.float32) # 推理 image = cv2.imread("test.jpg") input_data = preprocess(image) outputs = session.run(None, {"images": input_data}) # YOLO26特别注意:无需NMS后处理! # 输出已是最终检测结果 TensorRT Python 部署 python 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 import tensorrt as trt import pycuda.driver as cuda import pycuda.autoinit import numpy as np import time # ========== 1. 引擎加载与上下文创建 ========== TRT_LOGGER = trt.Logger(trt.Logger.WARNING) runtime = trt.Runtime(TRT_LOGGER) with open("yolo26n.engine", "rb") as f: engine = runtime.deserialize_cuda_engine(f.read()) context = engine.create_execution_context() # ========== 2. CUDA 内存分配 ========== stream = cuda.Stream() bindings = [] for i in range(engine.num_io_tensors): name = engine.get_tensor_name(i) shape = engine.get_tensor_shape(name) dtype = trt.nptype(engine.get_tensor_dtype(name)) size = trt.volume(shape) host_mem = cuda.pagelocked_empty(size, dtype) # 主机锁页内存 device_mem = cuda.mem_alloc(host_mem.nbytes) # 设备显存 bindings.append({"name": name, "host": host_mem, "device": device_mem, "shape": shape, "size": size, "dtype": dtype}) # ========== 3. 异步推理循环 ========== def async_infer(input_blob): # 输入拷贝:主机 → 设备 np.copyto(bindings[0]["host"], input_blob.ravel()) cuda.memcpy_htod_async(bindings[0]["device"], bindings[0]["host"], stream) # 设置张量地址并执行 context.set_tensor_address(bindings[0]["name"], int(bindings[0]["device"])) context.set_tensor_address(bindings[1]["name"], int(bindings[1]["device"])) context.execute_async_v3(stream.handle) # 输出拷贝:设备 → 主机 cuda.memcpy_dtoh_async(bindings[1]["host"], bindings[1]["device"], stream) stream.synchronize() return bindings[1]["host"].copy() # ========== 4. 性能基准测试 ========== def benchmark(warmup=10, runs=100): dummy = np.random.randn(1, 3, 640, 640).astype(np.float32) for _ in range(warmup): async_infer(dummy) latencies = [] for _ in range(runs): t0 = time.perf_counter() async_infer(dummy) latencies.append((time.perf_counter() - t0) * 1000) latencies.sort() print(f"TensorRT FP16 | 平均: {np.mean(latencies):.1f}ms | " f"P50: {latencies[runs//2]:.1f}ms | " f"P99: {latencies[int(runs*0.99)]:.1f}ms | " f"吞吐: {1000/np.mean(latencies):.0f} FPS") benchmark() OpenVINO 部署与性能基准 python 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 import openvino as ov import cv2 import numpy as np import time # ========== 1. ONNX → OpenVINO 转换 ========== # Ultralytics 统一导出: # model.export(format="openvino", half=True) core = ov.Core() model = core.read_model("yolo26n_openvino/yolo26n.xml") # ========== 2. CPU 推理 ========== compiled_cpu = core.compile_model(model, device_name="CPU") infer_request = compiled_cpu.create_infer_request() def openvino_infer(image): img = cv2.resize(image, (640, 640)) blob = img.transpose(2, 0, 1)[np.newaxis].astype(np.float32) / 255.0 outputs = infer_request.infer({"images": blob}) return outputs[next(iter(outputs))] # ========== 3. 异步推理管线(提升吞吐)========== def async_pipeline(images, num_requests=4): """多请求异步推理管线""" requests = [core.compile_model(model, "CPU").create_infer_request() for _ in range(num_requests)] results = [None] * len(images) def completion_callback(request, userdata): idx = userdata results[idx] = request.get_output_tensor().data.copy() for req in requests: req.set_callback(completion_callback) for i, img in enumerate(images): req = requests[i % num_requests] req.start_async({"images": preprocess(img)}, userdata=i) for req in requests: req.wait() return results # ========== 4. CPU vs NPU 基准对比 ========== def benchmark_openvino(): dummy = np.random.randn(1, 3, 640, 640).astype(np.float32) for device in ["CPU", "AUTO"]: compiled = core.compile_model(model, device) req = compiled.create_infer_request() # 预热(避免首次 kernel 编译开销) for _ in range(20): req.infer({"images": dummy}) times = [] for _ in range(200): t0 = time.perf_counter() req.infer({"images": dummy}) times.append((time.perf_counter() - t0) * 1000) times.sort() print(f"OpenVINO {device}: " f"平均 {np.mean(times):.1f}ms | " f"P99 {times[int(199*0.99)]:.1f}ms | " f"{1000/np.mean(times):.0f} FPS") benchmark_openvino() NCNN 移动端部署 NCNN 是腾讯开源的移动端推理框架,支持 ARM NEON 和 Vulkan GPU 加速。

Continue reading →

YOLO 进阶优化:轻量化、量化与精度提升

模型轻量化策略 模型尺寸选择 模型 参数 (M) mAP CPU 推理 适用场景 YOLO26n 2.8 38.9 最快 边缘设备、嵌入式 YOLO26s 9.4 48.2 很快 移动端、Web YOLO26m 21.8 53.1 中等 服务器、高性能 YOLO11n 2.6 39.6 快 轻量部署 YOLOv8n 3.2 37.3 基准 通用 知识蒸馏 python 1 2 3 4 5 6 7 8 9 10 # 大模型作为教师,小模型作为学生 teacher = YOLO("yolo26x.pt") student = YOLO("yolo26n.yaml") # 蒸馏训练(Ultralytics内置支持) student.train( data="data.yaml", distill="yolo26x.pt", # 教师模型 distill_ratio=0.5, # 蒸馏损失比例 ) 模型剪枝 结构化剪枝 vs 非结构化剪枝 类型 方法 稀疏模式 硬件加速 压缩率 非结构化 权重剪枝 随机稀疏 困难(需专用硬件) 高 结构化 通道剪枝 规整稀疏 原生加速 中等 Torch Prune 通道剪枝示例 python 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import torch import torch.nn.utils.prune as prune # 对卷积层进行 L1 非结构化剪枝 model = YOLO("yolo26n.pt") for name, module in model.model.named_modules(): if isinstance(module, torch.nn.Conv2d): prune.l1_unstructured(module, name="weight", amount=0.3) prune.remove(module, "weight") # 使剪枝永久化 # 通道剪枝使用 torch-pruning 库 # pip install torch-pruning import torch_pruning as tp model = YOLO("yolo26n.pt").model DG = tp.DependencyGraph() DG.build_dependency(model, example_inputs=torch.randn(1, 3, 640, 640)) # 按 L1 范数剪枝 20% 通道 pruning_plan = DG.get_pruning_plan( model.model[4], tp.prune_conv, pruning_dim=0, # 输出通道维度 idxs=list(range(0, 64, 5)) # 每 5 个通道保留一个 ) pruning_plan.exec() 剪枝比例指南 模型 安全剪枝比例 激进剪枝比例 mAP 损失 YOLO26n ≤20% 20-40% <1% / 2-5% YOLO26s ≤30% 30-50% <1% / 3-6% YOLO26m ≤40% 40-60% <1% / 3-8% YOLOv8n ≤20% 20-35% <1% / 2-4% 模型剪枝与量化 导出时量化 python 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 model = YOLO("yolo26n.pt") # INT8量化(需要校准数据) model.export( format="engine", # TensorRT int8=True, data="data.yaml", # 校准数据集 batch=8, ) # ONNX动态量化 model.export( format="onnx", dynamic=True, simplify=True, ) TensorRT INT8 校准流程详解 校准数据集准备 INT8 量化需要代表性校准数据来确定激活值的动态范围:

Continue reading →