第四章副本 · 加载预训练模型
一个可能没有 AI 很难,但是会用 AI 则很简单的实验?可以尝试一下!
在该实验中,你需要比在 Exp2 更进一步,你需要直接使用 ONNX Runtime 加载预训练的 CNN 模型,用于和前几个小实验一样的滤波任务。
链接库
本实验仓库样板代码只提供了 Linux x64 和 macOS arm64 两个版本。
如果你要在 Windows 裸机上完成这个实验,你需要访问 ONNX Runtime Releases 页面下载对应的库并修改 Makefile 和相关文件。
你可以使用链接下载预训练模型:model.fp32.onnx,或在线下拷贝获得。
如果你懒得做这个实验,也可以看看支线实验中的插曲一 · 卷积图像修复网络,和 OS 没什么关系。我在其中介绍了机器学习和神经网络的基本概念,希望你可以有所收获。如果你对理论也不感兴趣,你或许也可以看看训练代码的实验过程与代码解析,只从代码中就可以学习训练神经网络模型基本的流程,如果你可以对它(ResNet)做出性能改进,你将可以取得本次实验的基本满分。
这部分没有和前文一样贴心的教程,从这开始换人了,根据任课老师的建议,本部分从原本的只需要调用一个函数就能获得 10 分,变成了一个相对复杂的题目。如果你打算询问 AI,我强烈建议你使用一个可以自己阅读本地文件的 IDE 或者 CLI(如本篇开头所说),使用 Web 上的 AI 聊天对本实验可能仍然有一定难度。
概览
以下给出一些基本的提示和参考资料,你可以通过任何方式,搜寻,扩充,理解,复用这些内容;除抄袭外,方法不限。你也可以比较一下将参考资料和基本思路告诉大语言模型,相比直接询问有多大的提升。
定位路径
src/ch4x/filter_cnn.c
/**
* TODO:
* Decide how the program locates the ONNX model file.
*
* Suggested directions:
* - hard-code a repo-relative path while you are experimenting
* - keep the path in one place so it is easy to change later
* - return NULL when the model path has not been configured yet
*/
static const char* cnn_model_path(void) {
return NULL;
}嗯,没有什么难度的,只需要返回一个路径即可。关于这里的「Suggested directions」,可以减少大语言模型犯错的概率,事实上,如果你知道一个修改的大致方向,你应该明确的和这些 LLM 指出。
如果你有很多的想法,你其实可以和大语言模型讨论实现之间的好坏,而不是把一个不好的直接发给它,并让它自己修改;和 LLM 聊聊,或许你还能学到更多。
filter_cnn.c,让它可以找到模型文件。创建可复用的 Session
src/ch4x/onnx_inference.c 中的 onnx_session_create() 函数
session = (OnnxSession*)calloc(1, sizeof(OnnxSession));
if (session == NULL) {
set_last_error("failed to allocate ONNX session");
return NULL;
}
/*
* TODO:
* Build the ONNX Runtime session here.
*
* A typical implementation needs few steps,
* you should setup environment, create session,
* setting device and somehow IO.
*
* You are required to make inference on your CPU.
*/
set_last_error("TODO: implement onnx_session_create in src/ch4x/onnx_inference.c");
free(session);
return NULL;以下是一些可能的参考资料,如果你有时间,可以自行阅读前两篇,其中包含了完成这部分代码的几乎全部内容;当然,你也可以直接把这两个链接交给 AI,取决于你的选择。
- Get started with ORT for C
- onnxruntime_c_api.h,该文件在
third_party/onnxruntime里也可以找到。
使用 ONNX Runtime 官方库,创建一个用于执行模型推理的 Session。
从 ImageBuffer 到输入张量
src/ch4x/onnx_inference.c 中的 onnx_run_inference() 函数
/*
* TODO:
* Prepare the input image data for the model and perform inference,
* then convert the model output back to the output image buffer.
*
* You will need to:
* - Transform the raw image bytes into the tensor format the model expects
* - Execute the model using the prepared session
* - Extract and post-process the result tensor into 8-bit image data
*
* On any error:
* - Use set_last_error() with a descriptive message
* - Clean up any temporary resources you allocated
* - Return -1
*
* Keep resource management careful to avoid leaks.
*/
set_last_error("TODO: implement onnx_run_inference in src/ch4x/onnx_inference.c");
return -1;除了上个步骤提供的参考资料外,再提供一个比较相关的示例代码。
你也可以和 AI 讨论一些其他的解决方案,或者也可以仔细询问关于张量格式的概念?
布局
HWC(也叫 NHWC,当加上 Batch 维度时)是最常见的像素优先布局:
- 外层是高度(Height) → 每一行
- 中间是宽度(Width) → 每一列
- 最内层是通道(Channel),对于 RGB 图像通常是 R、G、B 三个值连续存储
自行了解一下 CHW 布局?以及图片到张量的转化?
将 ImageBuffer 类型数据调整为适合 ONNX Runtime 加载的数据结构(张量)。
评估
复用在前几个小实验写的 SSIM 代码和 PSNR 计算过程,量化模型性能。
你需要使用在之前实验完成的 SSIM 及原本的 PSNR 指标评估它的性能,并计算增益。
提交作业时, 使用 make submit, 该命令会将 src 文件夹统一打包成 submit.tar.gz
同时需要将 output/ch4x/metrics.csv 放在同一个文件夹内, 文件名为 metrics.csv.
接下来可以开始支线实验 1,其介绍了机器学习和神经网络的基本概念,并给出了训练本实验中预训练模型的代码。
本文作者