资讯动态

Caffe-Windows深度学习环境编译与模型部署实战指南

发布时间:2026/10/13 21:07:58 来源:尧图企业网站定制
简介Caffe深度学习框架的Windows版本资源包面向想在Visual Studio与CUDA环境下使用Caffe、但不愿从零配置Linux环境的开发者。压缩包内含完整源码树与构建辅助文件覆盖从编译到测试的常见需求可显著降低Windows端的安装门槛。资源共888个文件总大小8.67MB核心类型包括cpp/hpp源文件、cu/cuh GPU内核、prototxt网络描述、py/m脚本接口以及cmake/vcxproj/sln工程配置目录结构沿官方Caffe布局组织。已有293人学习适合深度学习入门者及需要在Windows上训练或部署模型的工程人员。包内提供GeneratePB.bat等辅助脚本、gtest单元测试文件、MNIST训练示例及多种网络定义配合CMake与Visual Studio工程文件可快速完成CPU/GPU环境编译、接口验证与模型训练是动手实践Caffe的实用资料。1. caffe-windows是个什么东西为什么老模型离了它跑不起来如果你这些年一直在 Linux 上玩深度学习突然拿到一个基于 caffe 训练的模型要在一个 Windows 机器上复现推理大概率会卡在第一关caffe 官方并不原生支持 Windows源码拉下来连编译都过不去。而这个 caffe-windows 资源就是把这个问题替你解决了的一个可编译工程包。它自带 VS 解决方案、三方依赖、示例脚本和模型文件核心价值在于让你不用自己去拼一堆老版本依赖链直接打开工程就能把 caffe 的 CPU/GPU 版本编出来跑通经典的 MNIST 训练和 CaffeNet 分类。适合需要复现老论文实验、接手别人的 caffe 工程、或者在 Windows 上做迁移学习的从业者。别指望它有新框架那种开箱即用的体验它更像一把需要拧对几个螺丝才能用的老式钳子。2. 环境准备VS版本、CUDA与依赖库的对应关系为什么必须一次核对完2.1 版本组合是 caffe-windows 的第一道门槛我用过好几版 Windows 上的 caffe 工程最大的感受是编译不过十次有八次不是代码问题而是版本搭配问题。caffe 是 2014 年左右开始流行的框架它的依赖库版本停留在一个特定时期跟你机器上最新的 VS、最新的 CUDA 往往配不上。这个 caffe-windows 工程包里面通常会给出几个版本的配置文件比如CommonSettings.props里会区分 VS2013、VS2015、VS2017 的路径映射。我见过不少人是这样翻车的机器上装的是 Visual Studio 2022打开工程的.sln提示需要升级工具集手一抖就点了“确定”结果编译到一半全是 C 标准库的语法错误比如std::unary_function被删掉之类的老接口消失问题。原因很简单caffe 的老代码是按 C11 写的VS2022 默认用的是 C17 标准很多旧写法会被标记为 error而且新版 MSVC 对模板实例化更严格老代码直接被拒。我一般会这样处理如果只是想快速跑通优先用 VS2015 或者 VS2017这两个版本对 caffe 老代码兼容性最好。系统是 Win10 或 Win11 都没问题VS2015 编译出来的程序在 Win11 上一样能跑不需要操作系统严格匹配。如果非要装在 VS2019 上需要在属性管理器里把每个项目的PlatformToolset改为v142然后单独处理 C 标准版本遇到的编译错误多一些但也不是完全不能走。2.2 CUDA 与 cuDNN版本不匹配是玄学重灾区GPU 版本的 caffe 依赖 CUDA 和 cuDNN。这个 caffe-windows 工程包里CommonSettings.props里面会写死一个默认的 CUDA 路径比如C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0。如果你机器上装的是 CUDA 11.x这个路径根本不存在编译到 cuDNN 相关的源文件时直接报“找不到 cudnn.h”。更隐蔽的坑是CUDA 11 的算力代码生成机制跟 CUDA 8/9 不一样就算你把路径改对了编译出来的 kernel 在你的新显卡上可能直接报 “no kernel image is available for execution on the device”。所以在动手编译之前我强烈建议你先把自己的 GPU 算力查一下表格放在下面供参考不同架构对应不同的 sm 值。GPU 架构计算能力CUDA 支持版本备注Kepler3.0 / 3.5CUDA 8 以前老显卡建议 CPU 模式Maxwell5.0 / 5.2CUDA 8 / 9稳定搭配 caffePascal6.0 / 6.1CUDA 8 / 9 / 10最常见的搭配Volta7.0 / 7.5CUDA 10 以上需要额外改配置Turing / Ampere7.5 / 8.6CUDA 11需改源码不建议硬上如果你确定只是做 CPU 推理那更简单把CommonSettings.props里的UseCUDA和UseCuDNN都设为false后面所有跟 CUDA 相关的编译选项都会绕开。CPU 模式下 caffe 跑 MNIST 训练也没问题就是慢一些几分钟一个 epoch做验证完全够。2.3 三方依赖库NuGet、OpenCV、Python 路径怎么统一这个 caffe-windows 工程包一般把三方依赖放在了3rdparty目录包含glog、gflags、protobuf、lmdb、leveldb、opencv、hdf5这些库的预编译静态库和 DLL。好处是省去了手动编译这些库的时间坏处是它们的运行库版本和你机器上的 VS 运行库必须匹配。比如 3rdparty 里的 DLL 是用 VS2015 编译的而你的系统里只装了 VS2019 的 VC Redistributable一般没问题因为 VS2015-2022 的运行库是二进制兼容的。但如果你拿到的是用 VS2013 编译的依赖包那运行的时候就会遇到各种内存分配相关的诡异崩溃。你需要重点检查的是这几项配置PythonSupporttrue/PythonSupport MatlabSupportfalse/MatlabSupport OpenCV3true/OpenCV3 UseCuDNNtrue/UseCuDNN UseCPUOnlyfalse/UseCPUOnly NugetPackageDirectory$(SolutionDir)packages\/NugetPackageDirectory这段配置位于 caffe-windows 工程根目录的CommonSettings.props文件里。PythonSupport控制是否编译 pycaffe 接口MatlabSupport同理OpenCV3表示使用 OpenCV 3.x如果你用的是包内自带的 opencv保持默认即可UseCuDNN控制是否使用 cuDNN 加速UseCPUOnly为 true 时会忽略 CUDA 配置NugetPackageDirectory定义了 NuGet 包的恢复路径。如果开启了 NuGet 自动恢复首次编译时会从网上下载一部分缺失的依赖包网络不好时这个过程会卡很久我通常会在3rdparty齐全的情况下把EnableNuGetPackageRestore设为 false完全离线编译。还有一个很容易忽略的点Python 路径。如果你打算使用 pycaffeCommonSettings.props里需要指定PythonDir指向你 Anaconda 的根目录比如D:\Anaconda3\。这里的路径斜杠必须带反斜杠结尾且 Python 版本位数必须与 caffe 编译平台一致也就是 x64 编译对应 64 位 Python否则链接python37.lib时会报 LNK1112 之类的位数不匹配错误。2.4 写一个环境自检脚本比反复翻配置文件省事环境检查不该靠肉眼我每次拿到新的 caffe-windows 工程副本都会先跑一个简单脚本确认关键的版本信息落在预期范围再决定怎么改配置。echo off rem 检查 VS 版本号 cl 21 | findstr /i Version rem 检查 CUDA 版本 nvcc --version | findstr /i release rem 检查 Python 版本和位数 python -c import struct;print(struct.calcsize(P)*8) rem 检查 cuDNN 头文件里的版本宏 findstr /C:CUDNN_MAJOR C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\include\cudnn.h脚本的作用是先把编译依赖的五个关键项一次性列出来MSVC 版本、CUDA release 版本、Python 位数、cuDNN 主版本号。逻辑很简单就是用各自自带的命令行工具打印版本号。需要注意cl是 VS 的 C 编译器必须在 VS 开发者命令行里运行普通 cmd 窗口会提示找不到命令。nvcc同理需要 CUDA 的 bin 目录加入 PATH。如果python命令没有指向你打算给 caffe 用的那个解释器建议直接用绝对路径执行比如D:\Anaconda3\python.exe -c ...避免 PATH 里多个 Python 互相干扰。3. 编译流程从.props到caffe.exe的三个步骤参数逐个说清楚3.1 配置阶段.props 文件是最核心的开关面板整个 caffe-windows 编译过程本质上就是围绕CommonSettings.props和caffe.sln两个文件做的操作。.props文件相当于 MSBuild 的公共属性面板VS 里打开属性管理器能看到它在每个项目的属性生效之前被加载所以你在里面定义的路径、开关、宏会被所有子项目继承。我第一次用这个工程的时候直接打开.sln就按 F5 编译结果报了“无法找到 cudnn.h”这类错误。后来才明白CommonSettings.props里有几个选型参数必须提前确认CudaArchitecturesm_61/CudaArchitecture CudaArchitecture Condition$(CudaArchitecture) sm_52/CudaArchitectureCudaArchitecture决定 CUDA 编译器为哪种 GPU 架构生成机器码。如果你的显卡是 GTX 1060计算能力是 6.1填sm_61编译出的 kernel 就能直接用。如果填高了比如填sm_75而你的显卡是 Pascal 架构运行时就会报“no kernel image is available”。这个参数可以直接在命令行里覆盖msbuild caffe.sln /p:CudaArchitecturesm_61。还有一种做法是同时列出多个架构用分号分隔但那样编译时间会成倍增加不推荐。还要注意CpuOnlyBuild参数如果设成 truecaffe 会编译成纯 CPU 版本所有caffe_gpu相关的源文件都会被排除链接时也不需要 CUDA 库。CPU 版本对入门用户其实是更稳的选择因为少了一半的编译错误可能。3.2 命令行编译libcaffe、caffe、pycaffe 这三个目标怎么选VS 界面编译适合交互式排错但如果你要反复清洁重编命令行 msbuild 是更好的方式。下面的命令依次执行先编核心静态库再编命令行工具最后编 Python 接口。rem 进入 VS 开发者命令行环境x64 版本 call C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Auxiliary\Build\vcvars64.bat rem 编译核心库 libcaffe这是整个工程的心脏 msbuild caffe.sln /t:libcaffe /p:ConfigurationRelease /p:Platformx64 /m rem 编译命令行工具 caffe.exe msbuild caffe.sln /t:caffe /p:ConfigurationRelease /p:Platformx64 /m rem 编译 Python 接口 pycaffe msbuild caffe.sln /t:pycaffe /p:ConfigurationRelease /p:Platformx64 /m/t后面跟的是 MSBuild 的 target 名称对应解决方案里的项目名不是文件名。/p:ConfigurationRelease指定 Release 配置/p:Platformx64指定 64 位平台/m表示并行编译加速。这一步最容易出问题的是libcaffe编译期间的 proto 生成步骤caffe 的网络描述文件caffe.proto需要先用protoc生成caffe.pb.h和caffe.pb.ccVS 工程里这一步骤是作为编译前事件自动完成的但如果你的protoc版本和工具链不匹配生成的头文件会说缺失需要手动执行一次 protoc 命令。3.3 修改源码适配高版本 CUDA老工程的必经手术如果你的 CUDA 版本超过 10.0直接编译大概率会遇到caffe/proto/caffe.pb.h这类报错之前先在一处源码挂掉include/caffe/util/device_alternate.hpp里有一个判断 GPU 是否可用的宏老代码用的是cudaDeviceProp和cudaGetDeviceProperties新版本 CUDA 把一些cudaDeviceProp的成员变量标记为 deprecated但不至于编译失败。真正会编译失败的是CUDNN_CONVOLUTION_FWD_ALGO_IMPLICIT_PRECOMP_GEMM这类枚举值在 cuDNN 7 以后某些算法枚举被改名或废弃。遇到这种情况我一般会先关闭UseCuDNN用纯 GPU 模式编译等跑通了再针对 cuDNN 相关代码做具体修改。纯 GPU 模式只依赖 CUDA 核心库不依赖 cuDNN兼容性宽泛得多。如果你想硬上 cuDNN常见做法是在cudnn.hpp里把废弃的枚举映射到新版对应枚举比如把CUDNN_CONVOLUTION_FWD_ALGO_IMPLICIT_PRECOMP_GEMM替换成CUDNN_CONVOLUTION_FWD_ALGO_IMPLICIT_GEMM这在大部分卷积场景下是等价的但到 ResNet 这种深层网络时性能会有明显差异具体取舍看你的使用场景。3.4 编译输出的东西在哪、怎么确认成功编译成功后输出目录一般在build\x64\Release\下面这个目录里会有下面几个核心产物。表格可以帮你快速确认该找什么文件。文件类型用途caffe.exe可执行文件命令行工具用于 train / test / timelibcaffe.lib静态库链接给 C 项目用的主库caffe.pydPython 扩展pycaffe 接口需要配合python/caffe包目录convert_mnist_data.exe数据转换工具把 MNIST 原始二进制转成 lmdb 格式compute_image_mean.exe均值计算工具从训练集计算图片均值用于预处理编译成功的标志是 msbuild 输出结尾出现Build succeeded而且上述文件都真实存在。有个细节pycaffe 的caffe.pyd在 Release 目录下但python/caffe目录里的.py文件需要被 import 时的路径找到通常做法是把build\x64\Release\和python\两个路径都加入PYTHONPATH环境变量否则import caffe会报找不到模块。4. 避坑清单编译失败与运行时崩溃的五个常见场景现象、原因、对策4.1 场景一caffe.pb.h 文件缺失导致的首次编译失败你在编译 libcaffe 时发现错误列表里先是“无法打开包括文件: caffe/proto/caffe.pb.h”然后跟着几百个依赖它的红错看起来像是源码不全。原因是 caffe.proto 的描述文件还没有被 protoc 编译器生成出头文件。VS 工程里虽然配置了“生成代码”的预编译事件但protoc.exe的路径有时候没有正确指定或者碰巧被别的版本的 protobuf 工具抢占了。解决的顺序是先看看src\caffe\proto\caffe.proto这个文件在不在。在的话直接手动跑一次 protocrem 进入 3rdparty 里 protobuf 工具目录不同版本路径略有差异 protoc.exe -I.\src\caffe\proto --cpp_out.\include\caffe\proto .\src\caffe\proto\caffe.proto执行完检查include\caffe\proto\caffe.pb.h是否生成。如果 protoc 版本太新生成的代码可能要配 C17 才能编译这时候建议换用工程 3rdparty 里自带的老版 protoc尽量不要用系统安装的最新版。需要注意caffe.pb.cc文件默认生成在当前的--cpp_out目录你可能还需要把它挪到源码树对应的位置或者让 VS 工程能自动找到。4.2 场景二python 扩展编译不通过或 import 后崩溃pycaffe 编译报错链接失败或者在import caffe后直接进程崩掉没有任何 Python 报错信息只是弹窗“python.exe 已停止工作”。原因通常是 Python 版本、位数、或者运行库不一致。caffe 的 Python 接口是 C 扩展它链接到python39.lib等导入库同时运行时需要用同一个 Python 解释器去加载.pyd。如果你编译时指定的PythonDir是 32 位 Python 的路径而 caffe 本身是 x64 编译的链接阶段就会报 LNK1112 或 LNK2005。另一种可能电脑上安装了多个 Pythonimport caffe时某个 Python 去加载了针对另一个版本编译的.pyd。解决方法是在CommonSettings.props里把PythonDir指向你要用的那个解释器根目录确保它是 64 位的然后用同一个解释器执行下面的验证import sys, struct print(sys.version) print(struct.calcsize(P) * 8) # 输出 64 表示解释器是 64 位需要注意即使在 Windows 命令提示符里输入python显示的路径正确也要确认这个路径跟编译时PythonDir指向的是同一份尤其是你使用了 Anaconda 就一定要用 Anaconda 自带的python.exe不要用 Windows 应用商店默认安装的那个短链接入口。4.3 场景三运行时提示缺少 DLL程序无法启动编译全部成功caffe.exe --version一跑就弹窗“找不到 libglog.dll”或“找不到 cudnn64_7.dll”程序根本无法启动。原因是 caffe 依赖的三方库 DLL 没有被系统找到。它们在 3rdparty 的bin或lib目录里静静地躺着但没有进入 PATH 环境变量也没有被复制到 caffe.exe 所在目录。解决方法是把3rdparty\bin目录和 CUDA 的bin目录都加入系统 PATH。如果需要保持环境干净也可以直接把3rdparty\bin下的*.dll复制到build\x64\Release\里一劳永逸但不优雅。我用的是后者因为复制的 DLL 跟着 exe 走换机器部署不容易漏代价是占用一些存储空间。如果加入 PATH 依然报缺少别的 DLL可以在命令行里用dumpbin /dependents caffe.exe查看完整的依赖清单逐个对照 3rdparty 目录排查。4.4 场景四GPU 模式下训练时显存报错或性能极低训练启动后很快报Check failed: error cudaSuccess (2 vs. 0) out of memory甚至直接把显存吃光后系统卡死。还有一种情况是不报错但速度慢到比 CPU 还差GPU 利用率几乎为 0。显存不足的原因一方面是你的batch_size设得太大在solver.prototxt里 batch_size 和模型输入分辨率共同决定单次迭代显存占用而 caffe 默认会在每个test_iter里做完整测试集推理可能一次性把显存冲爆。另一方面是 caffe 的 CUDNN 模式会为每一个卷积层预留工作空间cudnn_conv_workspace参数如果配置得太大也会加速显存消耗。性能低下的原因集中在前面提到的 CudaArchitecture 设置不对kernel 在 GPU 上做了 JIT 编译或走了兼容模式的老代码路径。解决要分两步先把solver.prototxt里的batch_size调小比如从 128 降到 32同时把test_iter调小或者干脆注释掉测试阶段先训几轮看显存曲线。然后把CommonSettings.props里的CudaArchitecture精确改为你的显卡型号对应的sm_XX值例如 RTX 2080 Ti 用sm_75GTX 1080 用sm_61。改完需要重编 libcaffe 和 caffe因为 kernel 编译信息是编译期嵌入的不是运行时读配置文件。4.5 场景五网络结构改动后报维度不匹配前向对齐困难你已经按照论文把deploy.prototxt改了层结构比如把全连接层换成了 GAP全局平均池化准备用原模型做迁移学习但一跑caffe test就报Error: Shape mismatch in blob fc8...改了半天也不知道哪层算错了。原因本质上不是代码缺陷而是 caffe 的 blob 形状依赖前一层的输出通道和池化核大小连续推导任何一层尺寸变化都会往后传导报错信息只显示当前 mismatch 点不会告诉你最早是从哪一层偏差开始的。解决方法是写一个小脚本逐层打印 blob 的 shape对着你的网络结构纸核对每一层。下面是一个在 Linux 和 Windows pycaffe 都能跑的检查脚本import caffe net caffe.Net(deploy.prototxt, weights.caffemodel, caffe.TEST) for name, blob in net.blobs.items(): print(name, list(blob.data.shape))脚本作用是遍历网络中每一层的前向输出张量并打印形状。net.blobs是一个 OrderedDict键是层名值是 blob 对象blob.data.shape给出 (N, C, H, W)。需要注意deploy.prototxt里最后必须包含input_shape或者input_dim否则脚本直接报错。只有当你对全链路的 shape 都确认无误后才算真正解决了 mismatch 问题。要求不高的场景也可以直接用caffe.Net的参数caffe.TEST忽略掉训练阶段的 loss 层只看主干网络输出。5. 验证部署MNIST训练与Python分类接口的真实跑法5.1 数据转换从原始二进制到 lmdb 的必经之路任何 caffe 网络的训练和测试输入数据都得是 lmdb 或 leveldb 格式caffe 不直接吃图片文件夹。这个 caffe-windows 工程包在data\mnist目录下放了 MNIST 原始数据的下载脚本但 Windows 上没有 Linux 的wget我一般直接手工下载那四个 gz 文件放在data\mnist\下。解压后用工程自带的convert_mnist_data.exe转到 lmdbbuild\x64\Release\convert_mnist_data.exe ^ data\mnist\train-images-idx3-ubyte ^ data\mnist\train-labels-idx1-ubyte ^ examples\mnist\mnist_train_lmdb ^ 0四个参数分别是训练图像文件路径、训练标签文件路径、输出 lmdb 目录、是否需要打乱数据0 表示不打乱。这个工具内部按固定格式读取 MNIST 的 magic number 和图像尺寸如果你的原始文件不是 MNIST 标准格式这一步就会崩溃。转换成功后会生成data.mdb和lock.mdb两个文件这是 lmdb 启动时自动创建的看到它们就说明转换成功。5.2 训练参数解读solver.prototxt 里每行都能改出不同效果接下来看examples\mnist\lenet_solver.prototxt这个文件是训练控制台。核心参数我用一个表格列出方便你对照自己的训练任务去替换。参数示例值含义netexamples/mnist/lenet_train_test.prototxt网络结构文件路径test_iter100测试时迭代次数和 test batch 共同覆盖测试集test_interval500每训练这么多迭代跑一次测试base_lr0.01基础学习率momentum0.9动量系数让梯度方向更平滑weight_decay0.0005权重衰减防止过拟合lr_policyinv学习率衰减策略inv 是按迭代数倒数衰减snapshot5000每 5000 次迭代保存一次模型快照训练命令很简单build\x64\Release\caffe.exe train --solverexamples/mnist/lenet_solver.prototxt如果一切顺利几分钟内会开始打印迭代日志能看到每一轮的 loss 逐渐下降测试阶段会输出 accuracy。如果你只是想验证环境不想等完整训练可以改max_iter成 200或者直接在命令行覆盖参数caffe train --solver... --max_iter200。需要注意的是这种命令行覆盖方式在某些老版本 caffe 里不生效所以最稳妥的还是直接编辑 solver 文件。5.3 Python 接口用 CaffeNet 做一张图片的分类训练跑通之后更实用的验证是 Python 接口。这个过程中最常见的需求是加载预训练模型bvlc_reference_caffenet.caffemodel对一张图做分类。代码不长但每一步都有讲究import caffe import numpy as np # 设置网络为测试模式读取结构和权重 net caffe.Net( models/bvlc_reference_caffenet/deploy.prototxt, models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel, caffe.TEST ) # 配置输入预处理把 HxWxC 的图片转换成 CxHxW transformer caffe.io.Transformer({data: net.blobs[data].data.shape}) transformer.set_transpose(data, (2, 0, 1)) transformer.set_mean(data, np.load(python/caffe/imagenet/ilsvrc_2012_mean.npy).mean(1).mean(1)) transformer.set_raw_scale(data, 255) transformer.set_channel_swap(data, (2, 1, 0)) # 送入一张图片注意必须 reshape 成 batch 大小 net.blobs[data].reshape(1, 3, 227, 227) image caffe.io.load_image(examples/images/cat.jpg) net.blobs[data].data[...] transformer.preprocess(data, image) # 前向传播得到分类概率 output net.forward() prob output[prob][0] top_k prob.argsort()[-5:][::-1] print(top_k, prob[top_k])代码的逻辑分四段载入网络、构造预处理流水线、送入图片、取 top 结果。容易出错的细节在transformer.set_mean那一行ilsvrc_2012_mean.npy是 3 通道均值图caffe 官方给的均值是 227x227x3 的格式而这里用.mean(1).mean(1)把它压缩成 3 个通道均值这个是简化处理对单张图片分类影响很小。set_channel_swap处理的是 RGB 与 BGR 通道顺序caffe 预训练模型基于 BGR 图像训练所以这一步不能省。如果你用自己的图片做测试注意caffe.io.load_image会读取成 [0,1] 范围的浮点图所以后面要乘以raw_scale255。5.4 服务化前验证命令行工具也能直接测单张图片有些场景你不想写 Python 脚本比如部署在纯 C 环境里那就可以用caffe.exe自带的test或classify功能。但老版 caffe-windows 默认不带 classify 功能需要自己编译tools/classification.cpp相对繁琐。更轻量的做法是写一个极短的 Batch 文件循环调用caffe.exe test不断更换测试集来验证模型稳定性或者直接采用caffe time来评估前向推断耗时build\x64\Release\caffe.exe time -model models/bvlc_reference_caffenet/deploy.prototxt ^ -weights models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel ^ -iterations 100time子命令会执行指定次数的前向和反向传播输出平均每层耗时和总耗时这个数据对于判断 GPU 是否真正在工作很有价值。如果所有层的耗时都在 0.1 ms 级别说明 GPU 可能根本没被唤起回去检查 CudaArchitecture 设置。100 次迭代的耗时数据已经足够稳定不需要设更大。6. 进阶用法把Caffe模型参数洗成numpy为迁移学习铺路caffe 自带的老接口虽然不够新潮但它的模型结构非常透明你可以从deploy.prototxt里看到每一层的名字和参数形状这就有了一个在别的框架里很难得的优势把任意层权重导出成通用格式供 PyTorch、TensorFlow 或者其他工具消费。这一步最典型的需求就是你手里只有 caffe 老模型但你的整个训练管线已经迁到了 PyTorch不想为了一个旧模型重新搭 caffe 环境。导出权重的核心思路很简单遍历net.params字典把每个名字对应的 blob 数据存成 numpy 的压缩包。import caffe import numpy as np net caffe.Net(deploy.prototxt, xxx.caffemodel, caffe.TEST) for layer_name, param_blobs in net.params.items(): arrays [np.array(blob.data) for blob in param_blobs] np.savez(fweights/{layer_name}.npz, *arrays)逻辑说明net.params是层名到参数 blob 列表的映射。对于卷积层blobs[0]是卷积核形状是 (输出通道, 输入通道, 核高, 核宽)blobs[1]是偏置形状是 (输出通道,)。全连接层同理blobs[0]是权重矩阵blobs[1]是偏置但形状是 (输出维度, 输入维度)。保存之后每个.npz文件可以直接被np.load读取拿到原始参数矩阵再配合现代框架的load_state_dict或from_pretrained做权重初始化。这里有一个必须注意的差异caffe 的卷积核布局是 (C_out, C_in, H, W)而 PyTorch 是 (C_out, C_in, H, W)看起来很一致但全连接层 caffe 的形状是 (C_out, C_in)PyTorch 是 (C_in, C_out)需要转置. 我第一次做转换时就因为这个转置问题在模型微调时损失完全降不下去白跑了一个多星期。从那以后我每次加载 caffe 权重都会用一个小脚本把每个层的 shapes 先打印出来手工核对一遍再放进训练代码里。做完权重导出之后还有一件事值得做利用 caffe 的前向网络作为特征提取器。比如你只需要倒数第二层的输出用来做图片检索或者训练一个小型分类器那就不用像上面那样导出全部权重只需要用 caffe 的前向传播保存中间层特征。net.blobs[fc7].data[0].copy()这个过程相当于把 caffe 当作一个特征仓库你只需要写少量代码就能把任意层的特征批量落盘。唯一的代价是你必须保留 deploy.prototxt 和训练时的预处理流程特别是 mean 值否则特征分布跟预训练状态不一样下游模型的精度会受直接影响。我一般会把transformer里的 mean 值也同步保存成一个.npy文件跟特征一起留档方便以后回查。caffe-windows 工程本身虽然老但模型权重是通用的只要你能把参数安全取出来后面的路就宽了。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑