当前位置: 首页 > news >正文

西昌市建设工程管理局网站曼联vs维拉直播免费视频直播

西昌市建设工程管理局网站,曼联vs维拉直播免费视频直播,做文案需要用到的网站,114物流网站怎么做Pytorch导出onnx模型#xff0c;C转化为TensorRT并实现推理过程 前言 本文为旨在实现整个Python导出PyTorch模型#xff0c;C转化为TensorRT并实现推理过程过程#xff0c;只与模型推理#xff0c;模型部署相关#xff0c;不涉及模型训练。为突出整个部署过程而非具体模…Pytorch导出onnx模型C转化为TensorRT并实现推理过程 前言 本文为旨在实现整个Python导出PyTorch模型C转化为TensorRT并实现推理过程过程只与模型推理模型部署相关不涉及模型训练。为突出整个部署过程而非具体模型本身本文模型就采用最简单的分类模型并且直接使用 torchvision.model 中的权重。检测、分割等其他模型在前后处理部分会有不同但是模型本身的导出、转换和推理的过程基本是一致的。本文会先用 Pytorch 测试一个分类模型在一张测试图片上的结果将其转换为 onnx 模型再用 onnxruntime 测试结果再用 C 将其转换为 TensorRT 模型再测试推理结果。预期三者测试结果一致则转换成功。如果想要测试速度Python 可以使用 time.perf_counter() C 可以使用 std::chrono::high_resolution_clock 。建议多测数据集中的一些图片计算推理时间的均值和方差而不是只测一张图片。 1 Pytorch模型推理测试导出onnx 这部分我们使用 torchvision 实例化一个简单的 ResNet50 分类模型并将其导出为 onnx 模型。在这个过程中我们还需要使用一张图片进行推理并记录下 Python 模型的输出方便我们后面到处 TensoRT 模型并进行推理时进行准确性的验证。 由于 torchvision 中的 resnet50 分类模型中是没有进行最后的 softmax 操作的这里我们为了之后使用方便自己新建一个类 ResNet50_wSoftmax 将后处理 softmax 添加到模型中一起导出。 这也是 pytorch 导出 onnx 模型的一个推荐的方式就是将一些必要后处理添加到模型中一起导出这样做有两个优点 可以直接得到端到端的 onnx/tensorrt 模型不必在外面再做后处理操作再之后我们会将 onnx 模型转换为 tensorrt 模型在转换过程中 tensorrt 会对我们的模型进行一些针对特定的 Nvidia GPU 的推理优化我们将后处理一起合并到 onnx 模型中可能可以使得一些算子操作再转换为 tensorrt 的过程中同样得到优化。 最终代码如下 # export_onnx.py import torch import torchvision.models as models import cv2 import numpy as npclass ResNet50_wSoftmax(torch.nn.Module):# 将softmax后处理合并到模型中一起导出为onnxdef __init__(self):super().__init__()self.base_model models.resnet50(pretrainedTrue)self.softmax torch.nn.Softmax(dim1)def forward(self, x):y self.base_model(x)prob self.softmax(y)return probdef preprocessing(img):# 预处理BGR-RGB、归一化/除均值减标准差IMAGENET_MEAN [0.485, 0.456, 0.406]IMAGENET_STD [0.229, 0.224, 0.225]img img[:, :, ::-1]img cv2.resize(img, (224, 224))img img / 255.0img (img - IMAGENET_MEAN) / IMAGENET_STDimg img.transpose(2, 0, 1).astype(np.float32)tensor_img torch.from_numpy(img)[None]return tensor_imgif __name__ __main__:# model models.resnet50(pretrainedTrue)image_path test.jpgimg cv2.imread(image_path)tensor_img preprocessing(img)model ResNet50_wSoftmax() # 将后处理添加到模型中model.eval()pred model(tensor_img)[0]max_idx torch.argmax(pred)print(ftest_image: {image_path}, max_idx: {max_idx}, max_logit: {pred[max_idx].item()})dummpy_input torch.zeros(1, 3, 224, 224) # onnx的导出需要指定一个输入这里直接用上面的tenosr_img也可torch.onnx.export(model, dummpy_input, resnet50_wSoftmax.onnx,input_names[image],output_names[predict],opset_version11,dynamic_axes{image: {0: batch}, predict: {0: batch}} # 注意这里指定batchsize是动态可变的)执行结果会输出 test_image: test.jpg, max_idx: 971, probability: 0.994541585445404这些结果我们一会测试 onnx/tensorrt 模型时用于比对转换是否有误差。并得到一个 onnx 模型文件classifier.onnx 。 2 onnxruntime推理测试 我们将刚刚得到的 classifier.onnx 用 onnxruntime 来进行推理测试看结果是否相同。 这里我们就复用刚才测试 pytorch 模型时的预处理函数整个 onnxruntime 推理测试代码如下 import onnxruntime as ort import numpy as np import cv2 from export_onnx import preprocessingimage_path test.jpg ort_session ort.InferenceSession(classifier.onnx) # 创建一个推理sessionimg cv2.imread(image_path) input_img preprocessing(img)[None]pred ort_session.run(None, { image : input_img } )[0][0] max_idx np.argmax(pred) print(ftest_image: {image_path}, max_idx: {max_idx}, probability: {pred[max_idx]})输出 test_image: test.jpg, max_idx: 971, probability: 0.994541585445404可以看到跟我们 pytorch 模型的测试结果是一致的。 3 C onnx模型转换为tensorrt模型 本部分重度参考自课程tensorRT从零起步迈向高性能工业级部署就业导向 我们进行模型部署推理肯定是追求极致的推理速度这时再用 Python 来进行转换和推理就不合适了接下来我们就转战到 C 上将onnx模型转换为tensorrt模型。 对于大部分深度学习部署的 C/C 的初学者而言环境配置都是个老大难的问题。本身 C/C 的包管理就不如 Python 的 pip、conda 等来的直接方便再加上各种 nvidia driver/cuda/cudnn/cuda-runtime 的各种版本不对齐的问题包括笔者在内的许多萌新们初期总是会在环境配置遇到许多问题。但是本文关注的重点是整个模型转换和部署的过程不可能花大篇幅再去介绍环境配置将来有机会再单独写一篇介绍 Python/C 深度学习模型部署时环境配置的问题这里就直接给出笔者使用的关键软硬件的版本号/型号。 GPU: RTX 3060ti 12GB OS: ubuntu 18.04 gcc: 7.5 TensorRT: 8.x CUDA: 11.2 cuDNN: 8.x 头文件 包含的头文件 // tensorrt相关 #include NvInfer.h #include NvInferRuntime.h// onnx解析器相关 #include onnx-tensorrt/NvOnnxParser.h// cuda_runtime相关 #include cuda_runtime.h// 常用头文件 #include stdio.h #include math.h #include string #include iostream #include fstream #include vector #include memory #include functional #include unistd.h #include chrono// opencv #include opencv2/opencv.hpplogger类 首先我们要准备一个 logger 类来打印构建 tensorrt 模型过程中的一些错误或警告。按照指定的严重性程度 (severity)来打印信息。 inline const char* severity_string(nvinfer1::ILogger::Severity t) {switch (t) {case nvinfer1::ILogger::Severity::kINTERNAL_ERROR: return internal_error;case nvinfer1::ILogger::Severity::kERROR: return error;case nvinfer1::ILogger::Severity::kWARNING: return warning;case nvinfer1::ILogger::Severity::kINFO: return info;case nvinfer1::ILogger::Severity::kVERBOSE: return verbose;default: return unknown;} }class TRTLogger : public nvinfer1::ILogger { public:virtual void log(Severity severity, nvinfer1::AsciiChar const* msg) noexcept override {if (severity Severity::kWARNING) {if (severity Severity::kWARNING) printf(\033[33m%s: %s\033[0m\n, severity_string(severity), msg);else if (severity Severity::kERROR) printf(\031[33m%s: %s\033[0m\n, severity_string(severity), msg);else printf(%s: %s\n, severity_string(severity), msg);}} };build_model函数 build_model 函数各步骤已在代码中添加注释 bool build_model() {if (isFileExist( classifier.trtmodel )) {printf(classifier.trtmodel already exists.\n);return true;}TRTLogger logger;// 下面的builder, config, network是基本需要的组件// 形象的理解是你需要一个builder去build这个网络网络自身有结构这个结构可以有不同的配置nvinfer1::IBuilder* builder nvinfer1::createInferBuilder(logger);// 创建一个构建配置指定TensorRT应该如何优化模型tensorRT生成的模型只能在特定配置下运行nvinfer1::IBuilderConfig* config builder-createBuilderConfig();// 创建网络定义其中createNetworkV2(1)表示采用显性batch size新版tensorRT(7.0)时不建议采用0非显性batch sizenvinfer1::INetworkDefinition* network builder-createNetworkV2(1);// onnx parser解析器来解析onnx模型auto parser nvonnxparser::createParser(*network, logger);if (!parser-parseFromFile(classifier.onnx, 1)) {printf(Failed to parse classifier.onnx.\n);return false;}// 设置工作区大小printf(Workspace Size %.2f MB\n, (1 28) / 1024.0f / 1024.0f);config-setMaxWorkspaceSize(1 28);// 需要通过profile来使得batchsize时动态可变的这与我们之前导出onnx指定的动态batchsize是对应的int maxBatchSize 10;auto profile builder-createOptimizationProfile();auto input_tensor network-getInput(0);auto input_dims input_tensor-getDimensions();// 设置batchsize的最大/最小/最优值input_dims.d[0] 1;profile-setDimensions(input_tensor-getName(), nvinfer1::OptProfileSelector::kMIN, input_dims);profile-setDimensions(input_tensor-getName(), nvinfer1::OptProfileSelector::kOPT, input_dims);input_dims.d[0] maxBatchSize;profile-setDimensions(input_tensor-getName(), nvinfer1::OptProfileSelector::kMAX, input_dims);config-addOptimizationProfile(profile);// 开始构建tensorrt模型enginenvinfer1::ICudaEngine* engine builder-buildEngineWithConfig(*network, *config);if (engine nullptr) {printf(Build engine failed.\n);return false;}// 将构建好的tensorrt模型engine反序列化保存成文件nvinfer1::IHostMemory* model_data engine-serialize();FILE* f fopen(classifier.trtmodel, wb);fwrite(model_data-data(), 1, model_data-size(), f);fclose(f);// 逆序destory掉指针model_data-destroy();engine-destroy();network-destroy();config-destroy();builder-destroy();printf(Build Done.\n);return true; }调用 build_model 函数成功后我们会得到一个 classifier.trtmodel 文件。 make_nvshared 上面的实现有个比较不优雅的地方对于我们创建的 builder、config 等指针我们都需要一一进行 destroy从而避免内存泄漏。实际上这里我们可以通过共享指针来实现自动释放。 shared_ptr_T make_nvshared(_T *ptr) {return shared_ptr_T(ptr, [](_T* p){p-destroy();}); }在这里指定一下释放内存的方式之后就可以通过类似 auto network make_nvshared(builder-createNetworkV2(1));这样的方式创建智能指针他会自己 destroy 释放这样最后几行 destory 就不用写了。 4 tensorrt模型推理测试 我们上一步已经成功将 onnx 模型导出为了 tensorrt 模型现在我们用 tensorrt 模型来进行推理看一下结果是否与之前 pytorch 和 onnx 推理的结果一致如果一致则模型转换成功。 load_file load_file 函数用于加载我们的 tensorrt 模型 vectorunsigned char load_file(const string file) {ifstream in(file, ios::in | ios::binary);if (!in.is_open()) return {};in.seekg(0, ios::end);size_t length in.tellg();vectoruint8_t data;if (length 0) {in.seekg(0, ios::beg);data.resize(length);in.read((char*)data[0], length);}in.close();return data; }inference void inference(const string image_path) {TRTLogger logger;// 加载模型auto engine_data load_file(classifier.trtmodel);// 执行推理前需要创建一个推理的runtime接口实例。与builer一样runtime需要loggerauto runtime make_nvshared(nvinfer1::createInferRuntime(logger));auto engine make_nvshared(runtime-deserializeCudaEngine(engine_data.data(), engine_data.size()));if (engine nullptr) {printf(Deserialize cuda engine failed.\n);runtime-destroy();return;}if (engine-getNbBindings() ! 2) {printf(Must be single input, single Output, got %d output.\n, engine-getNbBindings() - 1);return;}// 创建CUDA流以确定这个batch的推理是独立的cudaStream_t stream nullptr;checkRuntime(cudaStreamCreate(stream));auto execution_context make_nvshared(engine-createExecutionContext());int input_batch 1;int input_channel 3;int input_height 224;int input_width 224;// 准备好input_data_host和input_data_device分别表示内存中的数据指针和显存中的数据指针// 一会儿将预处理过的图像数据搬运到GPUint input_numel input_batch * input_channel * input_height * input_width;float* input_data_host nullptr;float* input_data_device nullptr;checkRuntime(cudaMallocHost(input_data_host, input_numel * sizeof(float)));checkRuntime(cudaMalloc(input_data_device, input_numel * sizeof(float)));// 图片读取与预处理与之前python中的预处理方式一致// BGR-RGB、归一化/除均值减标准差float mean[] {0.406, 0.456, 0.485};float std[] {0.225, 0.224, 0.229};auto image cv::imread(image_path);cv::resize(image, image, cv::Size(input_width, input_height));int image_area image.cols * image.rows;unsigned char* pimage image.data;float* phost_b input_data_host image_area * 0;float* phost_g input_data_host image_area * 1;float* phost_r input_data_host image_area * 2;for (int i0; iimage_area; i, pimage 3) {*phost_r (pimage[0] / 255.0f - mean[0]) / std[0];*phost_g (pimage[1] / 255.0f - mean[1]) / std[1];*phost_b (pimage[2] / 255.0f - mean[2]) / std[2];}// 进行推理checkRuntime(cudaMemcpyAsync(input_data_device, input_data_host, input_numel *sizeof(float), cudaMemcpyHostToDevice, stream));const int num_classes 1000;float output_data_host[num_classes];float* output_data_device nullptr;checkRuntime(cudaMalloc(output_data_device, sizeof(output_data_host)));auto input_dims engine-getBindingDimensions(0);input_dims.d[0] input_batch;execution_context-setBindingDimensions(0, input_dims);// 用一个指针数组bindings指定input和output在gpu中的指针。float* bindings[] {input_data_device, output_data_device};bool success execution_context-enqueueV2((void**)bindings, stream, nullptr);checkRuntime(cudaMemcpyAsync(output_data_host, output_data_device, sizeof(output_data_host), cudaMemcpyDeviceToHost, stream));checkRuntime(cudaStreamSynchronize(stream));float* prob output_data_host;int predict_label max_element(prob, prob num_classes) - prob;float conf prob[predict_label];printf(test_image: %s, max_idx: %d, probability: %f, image_path.c_str(), predict_label, conf);// 释放显存checkRuntime(cudaStreamDestroy(stream));checkRuntime(cudaFreeHost(input_data_host));checkRuntime(cudaFree(input_data_device));checkRuntime(cudaFree(output_data_device)); } 最终得到输出 test_image: test.jpg, max_idx: 971, probability: 0.994527与之前 pytorch 和 onnx 推理的结果基本一致模型转换成功。 附录 给出完整的参考代码https://github.com/Adenialzz/Hello-AIDeployment/tree/master/HAID/tensorrt/resnet
http://www.zqtcl.cn/news/346800/

相关文章:

  • 潍坊网站制作价格网站维护入门教程
  • 微信网站怎么做下载附件wordpress英文主题汉化
  • 桂平网站设计python基础教程第二版
  • wordpress hermit杭州企业seo网站优化
  • 贵州做团队培训的网站法学网站阵地建设
  • 网站死链是什么西宁高端网站开发公司
  • 做团购网站的公司wordpress附件存放位置
  • 成都最专业做网站的仿win8网站模板
  • 国外设计类网站男女做暖暖试看网站
  • 网站设计哪个好珠海微网站进入
  • 云主机开网站教程模板网会员
  • 网站建设无锡虚拟网站官网
  • 品牌网站设计联系东莞网站优化公
  • 自己做整个网站的流程php装修网站源码
  • 天津网站建设班模拟网站建设软件有哪些
  • 服务类的网站怎么做做软件的网站担保网站
  • 最新电子产品网站模板海口网站排名提升
  • 北京社保网站减员怎么做phpcms v9 实现网站搜索
  • 视频运营管理网站济南网站建设 济南货梯
  • html电影网站模板下载工具阿里云网站建设 部署与发布笔记
  • 建设跨境网站微信seo是什么意思
  • 我做彩票网站开发彩票网站搭建织梦如何仿手机网站源码下载
  • 东仓建设网站手机便宜的网站建设
  • 吕梁市住房与城乡建设厅网站wordpress 乐趣公园
  • 沈阳正规制作网站公司吗德成建设集团有限公司网站
  • 做网站标准步骤大学两学一做专题网站
  • 如何在手机上做网站Windows怎么建设网站
  • 专门做稀有产品的网站海口网站制作设计
  • 怎么查看自己的网站是否被百度收录网站的设计制作流程
  • 视觉设计网站芜湖做网站找哪家好