导出模型与使用#

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


如果成功,你可以在 D:/path/to/save/ 目录下找到文件 my_first_project.vfmodel。 你可以复制模型文件到想部署检测流程 Flow 的其他主机上。

Note

模型文件的扩展名必须为 .vfmodel。 如果导出模型路径扩展名不为 .vfmodel,会自动补充扩展名 .vfmodel

打开导出模型#

当你部署检测流程 Flow 时,你可能需要在主机上对模型做一些调整。 此时,你首先需要加载导出的模型, 这次不再需要工程类 visionflow::Project。 与导出一样方便, VisionFlow 提供了模型类 visionflow::Model 来支持加载模型和模型调整。 请确保模型文件的路径有效,并且文件扩展名是符合要求的。

visionflow::Model model("D:/path/to/save/my_first_project.vfmodel");


直接修改模型中的参数#

现在,你可以通过模型类 visionflow::Model 来像工程类 visionflow::Project 一样修改模型参数。 虽然在实际场景中, 在部署阶段可修改的参数有限, VisionFlow 仍然允许通过接口修改模型中的任何参数。 在打开模型后, 你可以通过从模型中读取参数来修改参数, 并将修改后的参数重新保存回模型中。

// 根据工程中的工具名称读取工具参数。
std::string segmentation_id = "Segmentation";
auto batch_size = model.get_param({segmentation_id, "batch_size"});

// 转换为工具参数的对应类型,这里修改了一次推理的样本大小。
batch_size->as<visionflow::param::InferenceBatchSize>()
    .set_batch_size(2);

// 将修改后的参数重新保存回模型中。
model.set_param({segmentation_id, "batch_size"}, *batch_size);


Warning

使用 visionflow::Model::get_param() 接口设置的新参数仅在当前打开的模型中有效。 关闭此模型并重新打开后,这些改动都会丢失。 如果你希望永久保存这些修改, 需要将当前模型重新保存为一个新模型。

重新保存模型#

直接修改模型中的参数只会对当前打开的模型生效, 对于模型的重要修改可以通过重新保存模型来永久保留,以便后续使用。 visionflow::Model::resave_to() 同样支持加密功能。 注意遵守 保存模型的规则

model.resave_to("D:/other/path/resave.vfmodel");


获取模型中的工具列表#

通过 visionflow::Model::tool_list() 即可获取到此模型中的所有工具的 id 列表。

// 获取到所有工具的 ids
auto tool_list = model.tool_list();

获取工具的连接关系#

通过以上步骤,我们即可建立起不同工具间的节点连接关系,具体示例如下:

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::Sample 的属性。

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

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

计算节点#

什么是计算节点?#

计算节点是工具中的核心数据处理单元。计算节点将接收其他计算节点生成的参数和属性,并处理数据以生成新的参数或属性。

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

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