YOLOv10 仓库 SAM 模型构建全解析build.py 源码、ViT 变体配置与调用链路详解【免费下载链接】yolov10YOLOv10: Real-Time End-to-End Object Detection [NeurIPS 2024]项目地址: https://gitcode.com/GitHub_Trending/yo/yolov10本篇文章聚焦 YOLOv10 仓库中 Segment Anything ModelSAM的模型构建模块 ultralytics/models/sam/build.py系统拆解build_sam_vit_h、build_sam_vit_l、build_sam_vit_b、build_mobile_sam、_build_sam与统一入口build_sam六个构建函数的参数配置、内部结构与调用方式并结合仓库中的SAM模型类与Predictor预测器源码说明这些构建函数如何被实际加载与使用。读完本篇你将掌握在 YOLOv10 环境下按权重名自动构建不同规格 SAM 模型的能力理解 ViT / TinyViT 图像编码器、提示编码器与掩码解码器的组装原理。一、背景SAM 如何进入 YOLOv10 仓库SAMSegment Anything Model是面向通用图像分割任务的模型核心能力是可提示分割promptable segmentation用户只需给出点、框或掩码等提示模型即可输出对应目标的分割掩码。在 YOLOv10 仓库中SAM 被封装为 ultralytics/models/sam/model.py 中的SAM类并作为segment任务的一个实现接入统一的引擎体系。而所有 SAM 模型实例的生产线正是build.py。该文件从sam_model_map中根据权重文件名分发到对应规格的构建函数最终统一进入_build_sam完成图像编码器、提示编码器、掩码解码器三大子模块的组装与权重加载。权重文件如 sam_b.pt │ ▼ build_sam(ckpt) ──► sam_model_map 按文件名匹配 │ ├── sam_h.pt ──► build_sam_vit_h │ ├── sam_l.pt ──► build_sam_vit_l │ ├── sam_b.pt ──► build_sam_vit_b │ └── mobile_sam.pt ──► build_mobile_sam ▼ _build_sam(encoder_embed_dim, encoder_depth, encoder_num_heads, ...) │ ├── 图像编码器ImageEncoderViT或 Mobile-SAM 的 TinyViT ├── PromptEncoder提示编码器 ├── MaskDecoder掩码解码器内含 TwoWayTransformer └── 权重加载 sam.eval() ▼ Sam(nn.Module) 实例二、统一入口 build_sam按权重文件自动分发build_sam是面向外部使用者的唯一入口build.py#L149-L160其签名如下def build_sam(ckptsam_b.pt): Build a SAM model specified by ckpt.其内部逻辑非常简洁将传入的ckpt允许Path类型会先str()转换与 sam_model_map 的四个键sam_h.pt、sam_l.pt、sam_b.pt、mobile_sam.pt逐个做endswith后缀匹配。例如传入sam_b.pt会命中sam_b.pt并调用build_sam_vit_b传入任意本地绝对路径只要文件名以这四个键之一结尾即可匹配。匹配失败的兜底行为如果没有任何键命中会抛出FileNotFoundError错误信息中列出全部受支持的模型名防止用户误传不支持的权重文件raise FileNotFoundError(f{ckpt} is not a supported SAM model. Available models are: \n {sam_model_map.keys()})从源码结构可以推断该设计刻意与 ultralytics/models/sam/model.py#L34-L46 中SAM.__init__的文件扩展名校验只接受.pt或.pth形成两级防线前者约束文件类型后者约束具体规格。三、四个变体构建函数与参数对照build_sam_vit_h、build_sam_vit_l、build_sam_vit_b与build_mobile_sam四个函数均接收可选的checkpointNone参数其区别完全体现在传给_build_sam的编码器超参数上。对照表如下依据 build.py#L21-L63函数对应权重encoder_embed_dimencoder_depthencoder_num_headsencoder_global_attn_indexesmobile_sambuild_sam_vit_hsam_h.pt12803216[7, 15, 23, 31]Falsebuild_sam_vit_lsam_l.pt10242416[5, 11, 17, 23]Falsebuild_sam_vit_bsam_b.pt7681212[2, 5, 8, 11]Falsebuild_mobile_sammobile_sam.pt[64, 128, 160, 320][2, 2, 6, 2][2, 4, 5, 10]NoneTrue对前三个 ViT 变体而言三个核心超参数的含义是encoder_embed_dimViT 的嵌入维度通道数决定每个 patch 映射到多少维特征空间是参数量与表达能力的主要调节旋钮encoder_depthTransformer 编码器块Block的堆叠层数encoder_num_heads每个多头注意力块的头数encoder_global_attn_indexes使用全局注意力的块索引列表其余块使用窗口注意力window attention以节省计算量。以sam_b.pt为例[2, 5, 8, 11]表示 12 层中第 2、5、8、11 层0 起始采用全局注意力其余层采用window_size14的窗口注意力。而build_mobile_sam的三个超参数均为列表而非标量这是因为其底层走 TinyViT 编码器需要逐阶段stage指定通道数、深度与头数且encoder_global_attn_indexes显式传None、mobile_samTrue从而在_build_sam内部切换到 TinyViT 分支。四、_build_sam核心组装工厂源码剖析所有变体最终都汇聚到 _build_sam。该函数固定了 SAM 的全局架构常量再根据mobile_sam标志选择编码器最后组装完整模型并加载权重。4.1 全局架构常量prompt_embed_dim 256 # 提示与掩码解码器的统一嵌入维度 image_size 1024 # 编码器输入图像边长正方形 vit_patch_size 16 # ViT patch 尺寸 image_embedding_size image_size // vit_patch_size # 1024 // 16 64由此可计算1024×1024 输入经 16×16 patch 划分后图像编码器输出的空间特征图为 64×64这与后续PromptEncoder接收的image_embedding_size(64, 64)严格对应build.py#L109-L114。4.2 图像编码器分支选择_build_sam使用三元表达式在两种编码器之间切换image_encoder ( TinyViT(...) # mobile_samTrue 时 if mobile_sam else ImageEncoderViT(...) # 默认 ViT 分支 )ViT 分支sam_h/l/b使用 encoders.py 中的ImageEncoderViT关键参数包括img_size1024、patch_size16、in_chans3RGB 三通道mlp_ratio4MLP 隐藏维度为嵌入维度的 4 倍norm_layerpartial(torch.nn.LayerNorm, eps1e-6)使用带 1e-6 eps 的 LayerNormqkv_biasTrue、use_rel_posTrue启用相对位置编码通过add_decomposed_rel_pos注入注意力图见 encoders.py#L536-L573window_size14窗口注意力的窗口尺寸out_chansprompt_embed_dimneck 输出通道固定为 256。从 encoders.py#L98-L114 可以看到neck 由两个 1×1 / 3×3 卷积与LayerNorm2d组成负责将编码特征投影到 256 维并保持 64×64 空间分辨率。TinyViT 分支mobile_sam使用 tiny_encoder.py 中的TinyViT其超参数包括embed_dimsencoder_embed_dim四段[64, 128, 160, 320]、depths[2, 2, 6, 2]、num_heads[2, 4, 5, 10]、window_sizes[7, 7, 14, 7]、mlp_ratio4.0、mbconv_expand_ratio4.0、local_conv_size3、layer_lr_decay0.8。TinyViT 内部大量使用Conv2d_BN卷积 BatchNorm 的组合见 tiny_encoder.py#L23-L35与MBConv倒残差块结构显著轻量化。4.3 提示编码器 PromptEncoderprompt_encoderPromptEncoder( embed_dimprompt_embed_dim, # 256 image_embedding_size(64, 64), input_image_size(1024, 1024), mask_in_chans16, )PromptEncoderencoders.py#L128-L285负责将三类提示编码为稀疏嵌入点与框和稠密嵌入掩码点与框提示通过PositionEmbeddingRandom随机空间频率位置编码处理后分别叠加 4 个可学习 point embedding正点、负点 2 个框角点得到稀疏嵌入掩码提示经mask_downscaling卷积序列输入 1 通道逐步升至 16 通道再投影到 256 维得到稠密嵌入无掩码时使用no_mask_embed广播到 64×64 空间。4.4 掩码解码器 MaskDecoder 与 TwoWayTransformermask_decoderMaskDecoder( num_multimask_outputs3, # 歧义消解时输出 3 个候选掩码 transformerTwoWayTransformer( depth2, embedding_dimprompt_embed_dim, # 256 mlp_dim2048, num_heads8, ), transformer_dimprompt_embed_dim, iou_head_depth3, iou_head_hidden_dim256, )MaskDecoderdecoders.py#L12-L151是掩码生成的最后环节它维护 1 个 IoU token 与num_multimask_outputs 1 4个 mask tokentoken 总数 5通过TwoWayTransformer在图像嵌入与输出 token 之间做双向注意力随后经output_upscaling两次转置卷积将 64×64 上采样到 256×256与output_hypernetworks_mlps超网络逐通道生成掩码最后用iou_prediction_head3 层 MLP预测每个掩码的质量分数。multimask_output开关决定返回单个掩码还是 3 个候选掩码。4.5 像素归一化常量pixel_mean[123.675, 116.28, 103.53], pixel_std[58.395, 57.12, 57.375],这两组 ImageNet 统计量被注册为Sam的 buffer见 modules/sam.py#L64-L65并同步出现在预测器 predict.py#L339-L340 的self.mean/self.std中用于推理时对输入图像做标准化。4.6 权重加载与推理模式if checkpoint is not None: checkpoint attempt_download_asset(checkpoint) with open(checkpoint, rb) as f: state_dict torch.load(f) sam.load_state_dict(state_dict) sam.eval()权重加载通过 ultralytics/utils/downloads.py 中的attempt_download_asset完成若传入的checkpoint是仓库内置名称如sam_b.pt会自动解析并下载对应资产随后torch.load读取state_dict并load_state_dict灌入模型。无论是否传入权重构建出的模型都会调用sam.eval()进入推理模式。文件末尾被注释掉的sam.load_state_dict(torch.load(checkpoint), strictTrue)表明这是从早期版本演进后的先下载再加载的稳健写法。五、调用链路从 SAM 模型类到 Predictorbuild.py的构建函数在仓库中通过两条路径被真正调用路径一模型加载。model.py#L48-L56 中SAM._load直接调用self.model build_sam(weights)因此SAM(sam_b.pt)或命令行yolo predict modelsam_b.pt最终都会经build_sam完成模型构造。路径二预测器初始化。predict.py#L316-L347 中Predictor.setup_model在model is None时调用model build_sam(self.args.model)并随后将模型移动到select_device选择的设备、复制归一化均值/方差set_imagepredict.py#L401-L423还会直接调用self.model.image_encoder(im)预提取图像特征以支持多次提示复用。值得一提的限制构建出的 SAM 模型当前不支持批处理推理——predict.py#L118 明确断言len(im) 1并注释SAM model does not currently support batched inference。同时 model.py#L44-L45 规定只能加载.pt/.pth权重。六、实践要点与选择建议按任务规模选规格官方权重中sam_b.pt12 层、768 维体积与计算量最小适合快速验证sam_l.pt24 层、1024 维与sam_h.pt32 层、1280 维表达力更强但更重mobile_sam.pt采用 TinyViT 编码器面向资源受限的边缘场景。统一入口优先与SAM模型类集成的场景应优先使用build_sam(ckpt)它会自动完成文件名匹配与错误提示避免直接调用四个变体函数导致的分发逻辑绕行。权重加载自动化attempt_download_asset会为内置权重名自动处理下载本地有自定义.pt权重时确保文件名以sam_h.pt/sam_l.pt/sam_b.pt/mobile_sam.pt结尾即可命中对应构建分支。七、相关文件索引构建工厂ultralytics/models/sam/build.py模型封装类ultralytics/models/sam/model.py预测器实现ultralytics/models/sam/predict.py图像编码器 / 提示编码器ultralytics/models/sam/modules/encoders.py掩码解码器ultralytics/models/sam/modules/decoders.pyTinyViT 编码器ultralytics/models/sam/modules/tiny_encoder.pySAM 主模块ultralytics/models/sam/modules/sam.py【免费下载链接】yolov10YOLOv10: Real-Time End-to-End Object Detection [NeurIPS 2024]项目地址: https://gitcode.com/GitHub_Trending/yo/yolov10创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考