一、概述

  深度学习模型能够在各种生产场景中发挥重要的作用,而深度学习模型往往在Python环境下完成训练,因而训练好的模型如何在生产环境下实现稳定可靠的部署,便是一个重要内容。C++开发平台广泛存在于各种复杂的生产环境,随着业务效能需求的不断提高,充分运用深度学习技术的优势显得尤为重要。本文介绍如何实现将深度学习模型部署在C++平台上。

二、步骤

  s1. Python环境中安装深度学习框架(如PyTorch、TensorFlow等);

  s2. P ython环境中设计并训练深度学习模型;

  s3. 将训练好的模型保存为.onnx格式的模型文件;

  s4. C++环境中安装Microsoft.ML.OnnxRuntime程序包;

  (Visual Studio 2022中可通过项目->管理NuGet程序包完成快捷安装)

  s5. C++环境中加载模型文件,完成功能开发。

三、示例

  在Python环境下设计并训练一个关于手写数字识别的卷积神经网络(CNN)模型,将模型导出为ONNX格式的文件,然后在C++环境下完成对模型的部署和推理。

1. Python训练和导出

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.functional import F # 定义简单的CNN模型
class SimpleCNN(nn.Module):
def __init__(self):
super(SimpleCNN, self).__init__()
self.conv1 = nn.Conv2d(1, 16, kernel_size=3, stride=1, padding=1)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(16, 32, kernel_size=3, stride=1, padding=1)
self.fc1 = nn.Linear(32 * 7 * 7, 128)
self.fc2 = nn.Linear(128, 10) def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = x.view(-1, 32 * 7 * 7)
x = F.relu(self.fc1(x))
x = self.fc2(x)
return x # 数据预处理
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
]) # 加载训练数据
train_dataset = datasets.MNIST('data', train=True, download=True, transform=transform)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=64, shuffle=True) # 初始化模型、损失函数和优化器
model = SimpleCNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001) # 训练模型
def train(model, train_loader, criterion, optimizer, epochs=5):
model.train()
for epoch in range(epochs):
running_loss = 0.0
for batch_idx, (data, target) in enumerate(train_loader):
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
running_loss += loss.item()
print(f'Epoch {epoch+1}, Loss: {running_loss/len(train_loader)}') # 训练模型
train(model, train_loader, criterion, optimizer) # 导出为ONNX格式
dummy_input = torch.randn(1, 1, 28, 28)
torch.onnx.export(
model,
dummy_input,
"mnist_model.onnx",
export_params=True,
opset_version=11,
do_constant_folding=True,
input_names=['input'],
output_names=['output'],
dynamic_axes={'input': {0: 'batch_size'}, 'output': {0: 'batch_size'}}
) print("模型已成功导出为mnist_model.onnx")

2. C++ 部署和推理

#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>
#include <onnxruntime_cxx_api.h> int main() {
// 初始化环境
Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "MNIST");
Ort::SessionOptions session_options;
session_options.SetIntraOpNumThreads(1);
session_options.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_ALL); // 加载模型
std::wstring model_path = L"mnist_model.onnx";
Ort::Session session(env, model_path.c_str(), session_options); // 准备输入
std::vector<int64_t> input_shape = { 1, 1, 28, 28 };
size_t input_tensor_size = 28 * 28;
std::vector<float> input_tensor_values(input_tensor_size); // 读取测试图片
cv::Mat test_image = cv::imread("test.jpg", cv::IMREAD_GRAYSCALE); // 将Mat数据复制到vector中
for (int i = 0; i < test_image.rows; ++i) {
for (int j = 0; j < test_image.cols; ++j) {
input_tensor_values[i * test_image.cols + j] = static_cast<float>(test_image.at<uchar>(i, j)); // 注意:uchar是unsigned char的缩写,表示无符号字符,通常用于存储灰度值
}
} // 创建输入张量
auto memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);
Ort::Value input_tensor = Ort::Value::CreateTensor<float>(
memory_info, input_tensor_values.data(), input_tensor_size, input_shape.data(), 4); // 设置输入输出名称
std::vector<const char*> input_names;
std::vector<const char*> output_names;
input_names.push_back(session.GetInputNameAllocated(0, Ort::AllocatorWithDefaultOptions()).get());
output_names.push_back(session.GetOutputNameAllocated(0, Ort::AllocatorWithDefaultOptions()).get()); // 运行推理
auto output_tensors = session.Run(
Ort::RunOptions{ nullptr },
input_names.data(),
&input_tensor,
1,
output_names.data(),
1); // 获取输出结果
float* output = output_tensors[0].GetTensorMutableData<float>();
std::vector<float> results(output, output + 10); // 找到预测的数字
int predicted_digit = 0;
float max_probability = results[0];
for (int i = 1; i < 10; i++) {
if (results[i] > max_probability) {
max_probability = results[i];
predicted_digit = i;
}
} std::cout << "预测结果: " << predicted_digit << std::endl;
std::cout << "置信度分布:" << std::endl;
for (int i = 0; i < 10; i++) {
std::cout << "数字 " << i << ": " << results[i] << std::endl;
} return 0;
}

测试图片:

程序运行:

End.

深度学习模型在C++平台的部署的更多相关文章

  1. flask部署深度学习模型

    flask部署深度学习模型 作为著名Python web框架之一的Flask,具有简单轻量.灵活.扩展丰富且上手难度低的特点,因此成为了机器学习和深度学习模型上线跑定时任务,提供API的首选框架. 众 ...

  2. PyTorch如何构建深度学习模型?

    简介 每过一段时间,就会有一个深度学习库被开发,这些深度学习库往往可以改变深度学习领域的景观.Pytorch就是这样一个库. 在过去的一段时间里,我研究了Pytorch,我惊叹于它的操作简易.Pyto ...

  3. 用 Java 训练深度学习模型,原来可以这么简单!

    本文适合有 Java 基础的人群 作者:DJL-Keerthan&Lanking HelloGitHub 推出的<讲解开源项目> 系列.这一期是由亚马逊工程师:Keerthan V ...

  4. CUDA上深度学习模型量化的自动化优化

    CUDA上深度学习模型量化的自动化优化 深度学习已成功应用于各种任务.在诸如自动驾驶汽车推理之类的实时场景中,模型的推理速度至关重要.网络量化是加速深度学习模型的有效方法.在量化模型中,数据和模型参数 ...

  5. CUDA上的量化深度学习模型的自动化优化

    CUDA上的量化深度学习模型的自动化优化 深度学习已成功应用于各种任务.在诸如自动驾驶汽车推理之类的实时场景中,模型的推理速度至关重要.网络量化是加速深度学习模型的有效方法.在量化模型中,数据和模型参 ...

  6. TVM将深度学习模型编译为WebGL

    使用TVM将深度学习模型编译为WebGL TVM带有全新的OpenGL / WebGL后端! OpenGL / WebGL后端 TVM已经瞄准了涵盖各种平台的大量后端:CPU,GPU,移动设备等.这次 ...

  7. 『高性能模型』Roofline Model与深度学习模型的性能分析

    转载自知乎:Roofline Model与深度学习模型的性能分析 在真实世界中,任何模型(例如 VGG / MobileNet 等)都必须依赖于具体的计算平台(例如CPU / GPU / ASIC 等 ...

  8. Roofline Model与深度学习模型的性能分析

    原文链接: https://zhuanlan.zhihu.com/p/34204282 最近在不同的计算平台上验证几种经典深度学习模型的训练和预测性能时,经常遇到模型的实际测试性能表现和自己计算出的复 ...

  9. Apple的Core ML3简介——为iPhone构建深度学习模型(附代码)

    概述 Apple的Core ML 3是一个为开发人员和程序员设计的工具,帮助程序员进入人工智能生态 你可以使用Core ML 3为iPhone构建机器学习和深度学习模型 在本文中,我们将为iPhone ...

  10. AI佳作解读系列(一)——深度学习模型训练痛点及解决方法

    1 模型训练基本步骤 进入了AI领域,学习了手写字识别等几个demo后,就会发现深度学习模型训练是十分关键和有挑战性的.选定了网络结构后,深度学习训练过程基本大同小异,一般分为如下几个步骤 定义算法公 ...

随机推荐

  1. 感觉程序员要被 AI 淘汰了?学什么才有机会?

    感觉程序员要被 AI 淘汰了?学什么才有机会? ️ 推荐观看视频版:https://www.bilibili.com/video/BV1i9Z8YhEja AI 会淘汰程序员么? 我的答案是 &quo ...

  2. 学习Linux只要学会这个命令就够了!

    大家好,我是良许. 这段时间又是搬家,又是找新办公室,现在终于安顿下来了,有时间给大家分享干货了. 今天给大家介绍一个 Linux 超级实用命令,有了这个命令,你就可以愉快使用 Linux 上几乎所有 ...

  3. Armbian安装防火墙软件

    在Armbian操作系统中安装防火墙是一项提升系统安全性的重要步骤.Armbian是一个针对ARM架构设备的Debian Linux发行版,它广泛应用于各类ARM开发板和单板计算机上.下面将具体展开讲 ...

  4. 使用Python解析求解扩散方程

    引言 大家好!今天我们来探讨一个非常重要的物理问题-扩散方程,并用 Python 来求解它.扩散现象广泛存在于自然界中,从气体.液体中分子的扩散,到热量的传递,甚至污染物的扩散,都是扩散方程的应用场景 ...

  5. Ruby+Appium+testunit实现app自动化demo

    1.安装对应库 gem install test-unit gem install appium_lib 2.编写代码 代码如下: require 'appium_lib' require 'test ...

  6. MySQL InnoDB 引擎中的聚簇索引和非聚簇索引有什么区别?

    MySQL InnoDB 引擎中的聚簇索引和非聚簇索引的区别 在 MySQL 的 InnoDB 存储引擎中,聚簇索引和非聚簇索引是两种常见的索引类型,它们在数据存储结构和使用场景上有显著区别. 1. ...

  7. 21.7K star!全流程研发项目管理神器,开源免费不限商用!

    嗨,大家好,我是小华同学,关注我们获得"最新.最全.最优质"开源项目和高效工作学习方法 「禅道开源版」作为国内首个开源项目管理软件,已为100万+团队提供专业研发管理解决方案.从需 ...

  8. 69.9K star!这个API调试神器让你告别Postman,开源免费真香!

    嗨,大家好,我是小华同学,关注我们获得"最新.最全.最优质"开源项目和高效工作学习方法 Hoppscotch 是一款专为开发者打造的轻量级API调试工具,凭借其极简的界面设计和强大 ...

  9. 基于Java Swing开发好看的皮肤

    先介绍几款开源及商业的皮肤. Weblaf:非常赞的套件,界面现代.简约.依赖包较少. 有开源也有商业协议,个人最喜欢的皮肤.https://github.com/mgarin/weblaf PgsL ...

  10. 国内首个「混合推理模型」Qwen3深夜开源,盘点它的N种对接方式!

    今日凌晨,通义千问团队正式开源了 Qwen3 大模型,并且一口气发布了 8 个型号,其中包括 0.6B.1.7B.4B.8B.14B.32B 以及 30B-A3B 和 235B-A22B,使用者可以根 ...