导出模型与使用#

在训练完模型并配置参数后,你可能希望将模型部署到其他主机上。 一种方法是直接将工程 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)

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

深入了解模型节点信息#

为了更好地理解和使用模型,您需要了解模型中不同类型的节点及其功能。模型主要由两种类型的节点组成:数据节点和计算节点。

节点分类及获取方法

数据节点详解#

什么是数据节点?#

数据节点是模型中的重要组成部分,它们代表了数据流动的端点。工具由节点和边组成,其中边表示节点之间的数据流,而节点则代表数据处理单元。数据节点承载两类数据:

  1. 参数数据:用于配置数据处理单元的参数

  2. 属性数据:由数据处理单元生成的样本 visionflow::Sample 的属性

数据节点详细信息的获取#

通过 visionflow::DataEdge 可以获取数据节点的详细信息:

虚拟节点与非虚拟节点的区别

数据节点分为两类:虚拟节点和非虚拟节点,它们有不同的特性和获取方法。

计算节点详解#

什么是计算节点?#

计算节点是工具中的核心数据处理单元。它们接收来自其他计算节点生成的参数和属性数据,经过处理后生成新的参数或属性数据。计算节点是模型执行逻辑的关键组件,负责实现各种算法和业务逻辑。

计算节点详细信息的获取#

通过 visionflow::ComputeNode 可以获取计算节点的详细信息:

通过深入理解这些节点类型和它们之间的关系,您可以更好地分析和优化模型的性能,也可以更有效地进行模型调试和定制化开发。