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

从零构建深度学习推理框架-1 简介和Tensor

源代码作者:https://github.com/zjhellofss

本文仅作为个人学习心得领悟 ,将原作品提炼,更加适合新手

什么是推理框架?

深度学习推理框架用于对已训练完成的神经网络进行预测,也就是说,能够将深度训练框架例如Pytorch、Tensorflow中定义的算法移植到中心侧和端侧,并高效执行。与训练框架不同的是,深度学习推理框架没有梯度反向传播功能,因为算法模型文件中的权重系数已经被固化,推理框架只需要读取、加载并完成对新数据的预测即可。

模型加载阶段

训练完成的模型被放置在两个文件中,一个是模型定义文件,一个是权重文件

ONNX文件是将模型定义文件和权重文件合二为一的文件格式。

关于维度的预备知识

在Tensor张量中,共有三维数据进行顺序存放,分别是Channels(维度),Rows(行高), Cols(行宽),

三维矩阵我们可以看作多个连续的二维矩阵组成,最简单的方法就是std::vector<std::vector<std::vector<float>>>,但是这种方法非常不利于数据的访问(尤其是内存不连续的问题 、修改以及查询,特别是在扩容的时候非常不方便。不能满足使用需求

不连续会造成数组访问慢的问题,在这里我用chrono做了测试:

#include<iostream>
#include <gtest/gtest.h>
#include <armadillo>
#include <glog/logging.h>
#include <vector>
#include <chrono>
#define TICK(x) auto bench_##x = std::chrono::steady_clock::now();
#define TOCK(x) std::cout << #x ": " << std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::steady_clock::now() - bench_##x).count() *1000000<< "ns" << std::endl;
using namespace std;
int m = 10000 , n = 10000 , channel = 2;
TEST(test_compare_vector , speed2D){LOG(INFO)<<"Test of vector & cube"<<endl;vector<vector<float>> matA (m , vector<float>(n , 1));TICK(2D);for (int  i = 0; i <matA.size(); i++){for (int j = 0; j < matA[0].size(); j++){matA[i][j] = matA[i][j]*matA[j][i];}}TOCK(2D);arma::fcube matB( m , n , 1 , arma::fill::ones);TICK(cube);for (int  i = 0; i <m; i++){for (int j = 0; j < n; j++){matB(i , j , 0) = matB(i , j , 0)*matB( j , i , 0);}}TOCK(cube);}

因此,综合考虑灵活性和开发的难易度,作者在这里以Armadillo类中的arma::mat(矩阵 matrix)类和arma::cube 作为数据管理(三维矩阵)类来实现Tensor 库中类的主体,一个cube由多个matrix组成,cube又是Tensor类中的数据实际管理者。一块连续的大内存分配开始写一个tensor,工作量会特别大,折中!

 作者设计的类是以arma::cube为基础实现了Tensor我们主要是提供了更方便的访问方式和对外接口 

 上图即为Tensor与cube的对应关系。

 cube一般有多个维度,在channel维度上有多个matrix。

arma::cube(2,5,3),表示当前的三维矩阵共有2个矩阵构成,每个矩阵都是5行3列的。如果放在我们项目中会以这形式提供 Tensor tensor(2,5,3)

下图是这种情况下的三维结构图,可以看出一个Cube一共有两个Matrix,也就是共有两个Channel。一个Channel放一个Matrix. Matrix的行宽均为Rows和Cols.

 Tensor类方法总览

这里的很多都不需要我们重新去造轮子

比如Fill(float value)就可以直接调用cube里的fill:

void Tensor<float>::Fill(float value) {CHECK(!this->data_.empty());this->data_.fill(value);
}

再比如这个at:

float &Tensor<float>::at(uint32_t channel, uint32_t row, uint32_t col) {CHECK_LT(row, this->rows());CHECK_LT(col, this->cols());CHECK_LT(channel, this->channels());return this->data_.at(row, col, channel);
}

再难一些的就需要我们自己去实现了:

Fill(vector)方法实现:

TEST(test_tensor, fill) {using namespace kuiper_infer;Tensor<float> tensor(3, 3, 3);ASSERT_EQ(tensor.channels(), 3);ASSERT_EQ(tensor.rows(), 3);ASSERT_EQ(tensor.cols(), 3);std::vector<float> values;for (int i = 0; i < 27; ++i) {values.push_back((float) i);}tensor.Fill(values);LOG(INFO) << tensor.data();int index = 0;for (int c = 0; c < tensor.channels(); ++c) {for (int r = 0; r < tensor.rows(); ++r) {for (int c_ = 0; c_ < tensor.cols(); ++c_) {ASSERT_EQ(values.at(index), tensor.at(c, r, c_));index += 1;}}}LOG(INFO) << "Test1 passed!";
}

padding功能实现:

 


TEST(test_tensor, padding1) {using namespace kuiper_infer;Tensor<float> tensor(3, 3, 3);ASSERT_EQ(tensor.channels(), 3);ASSERT_EQ(tensor.rows(), 3);ASSERT_EQ(tensor.cols(), 3);tensor.Fill(1.f); // 填充为1tensor.Padding({1, 1, 1, 1}, 0); // 边缘填充为0ASSERT_EQ(tensor.rows(), 5);ASSERT_EQ(tensor.cols(), 5);int index = 0;// 检查一下边缘被填充的行、列是否都是0for (int c = 0; c < tensor.channels(); ++c) {for (int r = 0; r < tensor.rows(); ++r) {for (int c_ = 0; c_ < tensor.cols(); ++c_) {if (c_ == 0 || r == 0) {ASSERT_EQ(tensor.at(c, r, c_), 0);}index += 1;}}}LOG(INFO) << "Test2 passed!";
}

再谈谈Tensor类中数据的排布

我们以具体的图片作为例子,来讲讲Tensor中数据管理类arma::cube的数据排布方式Tensor类是arma::cube对外更方便的接口,所以说armadillo::cube怎么管理内存的,Tensor类就是怎么管理内存的。希望大家的能理解到位。如下图中的一个Cube,Cube的维度是2,每个维度上存放的是一个Matrix,一个Matrix中的存储空间被用来存放一张图像(lena) 。一个框内(channel)是一个Matrix,Matrix1存放在Cube第1维度(channel 1)上,Matrix2存放在Cube的第2维度上(channel 2). Matrix1和Matrix2的Rows和Cols均代表着图像的高和宽,在本例中就是512和384。

 

相关文章:

从零构建深度学习推理框架-1 简介和Tensor

源代码作者&#xff1a;https://github.com/zjhellofss 本文仅作为个人学习心得领悟 &#xff0c;将原作品提炼&#xff0c;更加适合新手 什么是推理框架&#xff1f; 深度学习推理框架用于对已训练完成的神经网络进行预测&#xff0c;也就是说&#xff0c;能够将深度训练框…...

使用WGCLOUD监测安卓(Android)设备的运行状态

WGCLOUD是一款开源运维监控软件&#xff0c;除了能监控各种服务器、主机、进程应用、端口、接口、docker容器、日志、数据等资源 WGCLOUD还可以监测安卓设备&#xff0c;比如安卓手机、安卓设备等 我们只要下载对应的安卓客户端&#xff0c;部署运行即可&#xff0c;如下是下…...

C++笔记之迭代器失效问题处理

C笔记之迭代器失效问题处理 code review! 参考博文&#xff1a;CSTL迭代器失效的几种情况总结 文章目录 C笔记之迭代器失效问题处理一.使用返回新迭代器的插入和删除操作二.对std::vector 来说&#xff0c;擦除&#xff08;erase&#xff09;元素会导致迭代器失效 一.使用返回…...

Tomcat的startup.bat文件出现闪退问题

对于双击Tomcat的startup.bat文件出现闪退问题&#xff0c;您提供的分析是正确的。主要原因是Tomcat需要Java Development Kit (JDK)的支持&#xff0c;而如果没有正确配置JAVA_HOME环境变量&#xff0c;Tomcat将无法找到JDK并启动&#xff0c;从而导致闪退。 以下是解决该问题…...

JAVA8-lambda表达式8:在设计模式-模板方法中的应用

传送门 JAVA8-lambda表达式1&#xff1a;什么是lambda表达式 JAVA8-lambda表达式2&#xff1a;常用的集合类api JAVA8-lambda表达式3&#xff1a;并行流&#xff0c;提升效率的利器&#xff1f; JAVA8-lambda表达式4&#xff1a;Optional用法 java8-lambda表达式5&#xf…...

React之组件间通信

React之组件间通信 组件通信&#xff1a; 简单讲就是组件之间的传值&#xff0c;包括state、函数等 1、父子组件通信 父组件给子组件传值 核心&#xff1a;1、自定义属性&#xff1b;2、props 父组件中: 自定义属性传值 import Header from /components/Headerconst Home ()…...

【MATLAB第58期】基于MATLAB的PCA-Kmeans、PCA-LVQ与BP神经网络分类预测模型对比

【MATLAB第58期】基于MATLAB的PCA-Kmeans、PCA-LVQ与BP神经网络分类预测模型对比 一、数据介绍 基于UCI葡萄酒数据集进行葡萄酒分类及产地预测 共包含178组样本数据&#xff0c;来源于三个葡萄酒产地&#xff0c;每组数据包含产地标签及13种化学元素含量&#xff0c;即已知类…...

CF1833 A-E

A题 题目链接&#xff1a;https://codeforces.com/problemset/problem/1833/A 基本思路&#xff1a;for循环遍历字符串s&#xff0c;依次截取字符串s的子串str&#xff0c;并保存到集合中&#xff0c;最后输出集合内元素的数目即可 AC代码&#xff1a; #include <iostrea…...

【深度学习】【Image Inpainting】Generative Image Inpainting with Contextual Attention

Generative Image Inpainting with Contextual Attention DeepFillv1 (CVPR’2018) 论文&#xff1a;https://arxiv.org/abs/1801.07892 论文代码&#xff1a;https://github.com/JiahuiYu/generative_inpainting 论文摘录 文章目录 效果一览摘要介绍论文贡献相关工作Image…...

二维深度卷积网络模型下的轴承故障诊断

1.数据集 使用凯斯西储大学轴承数据集&#xff0c;一共有4种负载下采集的数据&#xff0c;每种负载下有10种 故障状态&#xff1a;三种不同尺寸下的内圈故障、三种不同尺寸下的外圈故障、三种不同尺寸下的滚动体故障和一种正常状态 2.模型&#xff08;二维CNN&#xff09; 使…...

redis突然变慢问题定位

CPU 相关&#xff1a;使用复杂度过高命令、O&#xff08;N&#xff09;的这个N&#xff0c;数据的持久化&#xff0c;都与耗费过多的 CPU 资源有关 内存相关&#xff1a;bigkey 内存的申请和释放、数据过期、数据淘汰、碎片整理、内存大页、内存写时复制都与内存息息相关 磁盘…...

React井字棋游戏官方示例

在本篇技术博客中&#xff0c;我们将介绍一个React官方示例&#xff1a;井字棋游戏。我们将逐步讲解代码实现&#xff0c;包括游戏的组件结构、状态管理、胜者判定以及历史记录功能。让我们一起开始吧&#xff01; 项目概览 在这个井字棋游戏中&#xff0c;我们有以下组件&am…...

七大经典比较排序算法

1. 插入排序 (⭐️⭐️) &#x1f31f; 思想&#xff1a; 直接插入排序是一种简单的插入排序法&#xff0c;思想是是把待排序的数据按照下标从小到大&#xff0c;依次插入到一个已经排好的序列中&#xff0c;直至全部插入&#xff0c;得到一个新的有序序列。例如&#xff1a;…...

【点云处理教程】03使用 Python 实现地面检测

一、说明 这是我的“点云处理”教程的第3篇文章。“点云处理”教程对初学者友好&#xff0c;我们将在其中简单地介绍从数据准备到数据分割和分类的点云处理管道。 在上一教程中&#xff0c;我们在不使用 Open3D 库的情况下从深度数据计算点云。在本教程中&#xff0c;我们将首先…...

Python 日志记录:6大日志记录库的比较

Python 日志记录&#xff1a;6大日志记录库的比较 文章目录 Python 日志记录&#xff1a;6大日志记录库的比较前言一些日志框架建议1. logging - 内置的标准日志模块默认日志记录器自定义日志记录器生成结构化日志 2. Loguru - 最流行的Python第三方日志框架默认日志记录器自定…...

最近遇到一些问题的解决方案

最近遇到一些问题的解决方案 SpringBoot前后端分离参数传递方式总结Java8版本特性讲解idea使用git更新代码 : update project removeAll引发得java.lang.UnsupportedOperationException异常Java的split()函数用多个不同符号分割 Aspect注解切面demo 抽取公共组件&#xff0c;使…...

封装hutool工具生成JWT token

private static final String KEY "abcdef";/*** 生成token** param payload 可以存放用户的一些信息&#xff0c;不要存放敏感字段* return*/public static String createToken(Map<String, Object> payload) {//十分重要&#xff0c;不禁用发布到生产环境无…...

【手机】三星手机刷机解决SecSetupWizard已停止

三星手机恢复出厂设置之后&#xff0c;出现SecSetupWizard已停止的解决方案 零、问题 我手上有一部同学给的三星 GT-S6812I&#xff0c;这几天搞了张新卡&#xff0c;多余出的卡就放到这个手机上玩去了。因为是获取了root权限的&#xff08;直接使用KingRoot就可以&#xff0…...

GDAL C++ API 学习之路 OGRGeometry 抽象曲线基类 OGRCurve

OGRCurve class "ogrsf_frmts.h" OGRCurve 是 OGR&#xff08;OpenGIS Simple Features Reference Implementation&#xff09;几何库中的一个基类&#xff0c;表示曲线几何对象。它是 OGRLineString 和 OGRCircularString 的抽象基类&#xff0c;用于表示曲…...

etcd底层支持的数据库有哪些

etcd底层的数据库可以更换。在当前版本的etcd中&#xff0c;它使用的是BoltDB作为默认的后端存储引擎。但是&#xff0c;etcd提供了接口允许您更换数据库后端&#xff0c;以便根据需要选择更合适的存储引擎。 以下是etcd支持的一些后端数据库选项&#xff1a; BoltDB&#xff…...

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

基于IDIG-GAN的小样本电机轴承故障诊断

目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) ​梯度归一化(Gradient Normalization)​​ (2) ​判别器梯度间隙正则化(Discriminator Gradient Gap Regularization)​​ (3) ​自注意力机制(Self-Attention)​​ 3. 完整损失函数 二…...

Python 实现 Web 静态服务器(HTTP 协议)

目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1&#xff09;下载安装包2&#xff09;配置环境变量3&#xff09;安装镜像4&#xff09;node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1&#xff09;使用 http-server2&#xff09;详解 …...