导出模型与使用#
在训练完模型并配置参数后,你可能希望将模型部署到其他主机上。 一种方法是直接将工程 Project 复制到另一台主机上, 然后用它来部署你的检测流程 Flow。 然而工程 Project 通常包含用于训练和验证模型的所有数据。 它的大小可能相当大,因此不便于直接复制使用。 VisionFlow 支持将模型导出为一个单独文件,并去除不必要的数据,以方便部署使用。
导出模型#
例如,你有一个训练好的工程 visionflow::Project my_first_project,
那么你可以轻松导出模型到需要的地方。
visionflow::Project::export_model() 同时也支持加密功能。
my_first_project->export_model("D:/path/to/save/my_first_project.vfmodel");
my_first_project.export_model("D:/path/to/save/my_first_project.vfmodel")
my_first_project.export_model("D:/path/to/save/my_first_project.vfmodel");
如果成功,你可以在 D:/path/to/save/ 目录下找到文件 my_first_project.vfmodel。 你可以复制模型文件到想要运行模型的其他主机上。
Note
模型文件的扩展名必须为 .vfmodel。 如果导出模型路径扩展名不为 .vfmodel,会自动补充扩展名 .vfmodel。
打开导出模型#
当你部署检测流程 Flow 时,你可能需要在主机上对模型做一些调整,例如修改部分过滤阈值、调整判定规则等。
此时,你首先需要加载导出的模型,并通过模型的接口对模型内的参数进行修改。
VisionFlow 提供了模型类 visionflow::Model 来加载模型、读取和修改模型中的数据,及通过模型创建可执行的检查流程。
你可以像下面示例这样,通过给定模型文件路径创建 visionflow::Model 对象,请确保模型文件的路径有效,并且文件扩展名是符合要求的。
visionflow::ModelOptions options;
// 自动保存修改的参数并且缓存极速推理的中间缓存物,加速再次创建极速推理模式的Runtime的速度
options.auto_resave_on_change = true;
options.password = "";
visionflow::Model model("D:/path/to/save/my_first_project.vfmodel", options);
options = visionflow.ModelOptions()
# 自动保存修改的参数并且缓存极速推理的中间缓存物,加速再次创建极速推理模式的Runtime的速度
options.auto_resave_on_change = True
options.password = ""
model = visionflow.Model("D:/path/to/save/my_first_project.vfmodel", options)
var options = new visionflow.ModelOptions();
// 自动保存修改的参数并且缓存极速推理的中间缓存物,加速再次创建极速推理模式的Runtime的速度
options.auto_resave_on_change = true;
options.password = "";
var model = new visionflow.Model("D:/path/to/save/my_first_project.vfmodel", options);
直接修改模型中的参数#
现在,你可以通过模型类 visionflow::Model 来像工程类 visionflow::Project 一样修改模型参数。
虽然在实际场景中,在部署阶段可修改的参数有限, VisionFlow 仍然允许通过接口修改模型中的任何参数。
在打开模型后,你可以通过 visionflow::Model::get_param() 接口从模型中读取需要修改的参数对象,修改参数对象中
的值,然后通过 visionflow::Model::set_param() 接口将修改后的参数重新保存回模型中。
// 根据工程中的工具名称读取工具参数。
std::string segmentation_id = "Segmentation";
auto batch_size = model.get_param({segmentation_id, visionflow::Segmentation::batch_size});
// 转换为工具参数的对应类型,这里修改了一次推理的样本大小。
batch_size->as<visionflow::param::InferenceBatchSize>()
.set_batch_size(2);
// 将修改后的参数重新保存回模型中。
model.set_param({segmentation_id, visionflow::Segmentation::batch_size}, *batch_size);
# 根据工程中的工具名称读取工具参数。
segmentation_id = "Segmentation"
batch_size = model.get_param(visionflow.ToolNodeId(segmentation_id, visionflow.Segmentation.batch_size))
# 转换为工具参数的对应类型,这里修改了一次推理的样本大小。
batch_size.set_batch_size(2)
# 将修改后的参数重新保存回模型中。
model.set_param(visionflow.ToolNodeId(segmentation_id, visionflow.Segmentation.batch_size), batch_size)
Note
对于 visionflow::DataEdge::kParam 使用接口 visionflow::Model::get_param(),
对于 visionflow::DataEdge::kProp 使用接口 visionflow::Model::get_context()。
同样,对于 visionflow::DataEdge::kParam 使用接口 visionflow::Model::set_param(),
对于 visionflow::DataEdge::kProp 使用 visionflow::Model::set_context()。
Warning
使用 visionflow::Model::get_param() 接口设置的新参数仅在当前打开的模型中有效。
关闭此模型并重新打开后,这些改动都会丢失。如果你希望永久保存这些修改,需要将当前模型重新保存为一个新模型。
重新保存模型#
直接修改模型中的参数只会对当前打开的模型生效,当你释放或析构当前的模型对象再重新打开同一模型时,这些修改都会丢失。
对于模型的重要修改可以通过 visionflow::Model::resave_to() 接口重新保存模型来永久保留相关修改,以便后续使用。
你也可以在打开模型时将 visionflow::ModelOptions::auto_resave_on_change 设置为 true ,以便于模型对象释放或析构时
自动重新保存模型。(自动重新保存模型会替换掉原来的旧模型文件,请谨慎使用此选项以免旧模型文件丢失。)
model.resave_to("D:/other/path/resave.vfmodel");
model.resave_to("D:/other/path/resave.vfmodel")
model.resave_to("D:/other/path/resave.vfmodel")
获取模型中的工具列表#
通过 visionflow::Model::tool_list() 即可获取到此模型中的所有工具的 id 列表。
// 获取到所有工具的 ids
auto tool_list = model.tool_list();
获得模型内部工具连接关系#
当您需要深入了解模型内部的工具构成和数据流向时,可以通过以下步骤来解析模型结构:
第一步:获取工具列表
首先通过 visionflow::Model::tool_list() 获取模型中所有工具的ID列表。
第二步:获取工具详细信息
通过 visionflow::Model::tool_info() 获取每个工具的详细信息,该函数返回 visionflow::ToolInfo 对象,其中包含了工具名称、工具类型以及工具内各个输入、输出数据节点和计算节点的信息。
第三步:分析节点连接关系 通过遍历工具的输入输出节点,可以建立完整的节点连接图谱,了解数据在不同工具间的流转方式。
以下是一个完整的示例,演示如何构建工具间的节点连接关系图:
auto tool_list = model.tool_list();
// 用于记录节点间的连接关系
// key: 一个节点的唯一标识
// value: 此节点后都连接了哪些节点
std::map<ToolNodeId, std::vector<ToolNodeId>> node_graph;
// 遍历 tool_list
for (const auto &tool_id : tool_list) {
// 获取到 tool 的具体信息: tool_info
auto tool_info = model.tool_info(tool_id);
// 遍历所有的输入节点 input_edges
for (const auto &node : tool_info.input_edges()) {
// 当前节点的 tool_node_id (唯一标识)
auto current_tool_node_id = ToolNodeId(tool_id, node.id());
// 如果 real_id
// 的返回值不是其自身,则说明此输入节点与其他工具的输出节点间存在连接关系
if (model.real_id(current_tool_node_id) == current_tool_node_id)
continue;
// 遍历所有与此输入节点有连接关系的节点(也即其他工具的输出节点)
for (const auto &tool_node_id : node.redirects()) {
// tool_node_id 的后面连接了 current_tool_node_id
node_graph[tool_node_id].emplace_back(current_tool_node_id);
}
}
}
Note
关于
visionflow::Model::real_id()需要注意的是,对于综合判断工具中的输入节点其可能对应多个不同工具的输出节点,因此对于visionflow::ToolNodeId其有一个后缀的概念,在执行visionflow::Model::real_id()时可以通过visionflow::ToolNodeId::operator[]()接口添加一个下标后缀,应精确标识用于获取哪一个连接节点关于一个
visionflow::ToolNodeId对象是否有后缀?具体下标后缀是什么?可以分别通过visionflow::ToolNodeId::has_index()和visionflow::ToolNodeId::index()获取得到
深入了解模型节点信息#
为了更好地理解和使用模型,您需要了解模型中不同类型的节点及其功能。模型主要由两种类型的节点组成:数据节点和计算节点。
节点分类及获取方法
输入节点:可通过
visionflow::ToolInfo::input_edges()获取得到输出节点:可通过
visionflow::ToolInfo::output_edges()获取得到数据节点:可通过
visionflow::ToolInfo::data_edges()获取得到计算节点:可通过
visionflow::ToolInfo::compute_nodes()获取得到
数据节点详解#
什么是数据节点?#
数据节点是模型中的重要组成部分,它们代表了数据流动的端点。工具由节点和边组成,其中边表示节点之间的数据流,而节点则代表数据处理单元。数据节点承载两类数据:
参数数据:用于配置数据处理单元的参数
属性数据:由数据处理单元生成的样本
visionflow::Sample的属性
数据节点详细信息的获取#
通过 visionflow::DataEdge 可以获取数据节点的详细信息:
获取数据节点的 id:
visionflow::DataEdge::id()获取数据节点的数据类型:
visionflow::DataEdge::type()获取数据节点的 concept type
visionflow::DataEdge::DataCptTag:visionflow::DataEdge::cpt_tag()获取数据节点的最大连接数:
visionflow::DataEdge::allow_max_connect()获取数据节点的最后一次更新时间:
visionflow::DataEdge::last_update_time()判断数据节点是否是输出节点:
visionflow::DataEdge::is_tool_output()
虚拟节点与非虚拟节点的区别
数据节点分为两类:虚拟节点和非虚拟节点,它们有不同的特性和获取方法。
- 判断数据节点是否是虚拟节点 (虚拟节点:其是一个工具的输入数据节点但又只能由其他工具生成):
visionflow::DataEdge::is_virtual_port() - 虚拟节点特有方法 (对于非虚拟节点返回数据为空):
获取节点所需要的 feature names,只有提供了所需特征类型的节点才能够与之相连接
visionflow::DataEdge::required_features()获取哪些工具中的哪些输出节点连接到了此数据节点
visionflow::DataEdge::redirects()
- 非虚拟节点特有方法 (对于虚拟节点返回数据为空):
获取哪些计算节点可以生成此数据节点:
visionflow::DataEdge::generated_by()获取哪些计算节点用到了此数据节点:
visionflow::DataEdge::used_by()获取数据节点是否处于可用状态:
visionflow::DataEdge::is_active()
- 判断数据节点是否是虚拟节点 (虚拟节点:其是一个工具的输入数据节点但又只能由其他工具生成):
计算节点详解#
什么是计算节点?#
计算节点是工具中的核心数据处理单元。它们接收来自其他计算节点生成的参数和属性数据,经过处理后生成新的参数或属性数据。计算节点是模型执行逻辑的关键组件,负责实现各种算法和业务逻辑。
计算节点详细信息的获取#
通过 visionflow::ComputeNode 可以获取计算节点的详细信息:
获取计算节点的 id:
visionflow::ComputeNode::id()获取计算节点的数据类型:
visionflow::ComputeNode::type()获取计算节点的最后一次更新时间:
visionflow::ComputeNode::last_update_time()获取计算节点所需要的参数数据节点:
visionflow::ComputeNode::param_nodes()获取计算节点所需要的属性数据节点:
visionflow::ComputeNode::input_nodes()获取计算节点所生成的数据节点:
visionflow::ComputeNode::output_nodes()获取计算节点的 concept type
visionflow::ComputeNode::ComputeCptTag:visionflow::ComputeNode::cpt_tag()
通过深入理解这些节点类型和它们之间的关系,您可以更好地分析和优化模型的性能,也可以更有效地进行模型调试和定制化开发。