神经网络量化与反量化( int8与float32之间的转换)+C语言实现

2023-05-16

神经网络量化与反量化(int8与float32之间的转换)

    • 一、背景知识
    • 二、量化与反量化结果做对比

一、背景知识

量化并不是什么新知识,我们在对图像做预处理时就用到了量化。回想一下,我们通常会将一张 uint8 类型、数值范围在 0~255 的图片归一成 float32 类型、数值范围在 0.0~1.0 的张量,这个过程就是反量化。类似地,我们经常将网络输出的范围在 0.0~1.0 之间的张量调整成数值为 0~255、uint8 类型的图片数据,这个过程就是量化。所以量化本质上只是对数值范围的重新调整,可以「粗略」理解为是一种线性映射。(之所以加「粗略」二字,是因为有些论文会用非线性量化,但目前在工业界落地的还都是线性量化,所以本文只讨论线性量化的方案)。

不过,可以明显看出,反量化一般没有信息损失,而量化一般都会有精度损失。这也非常好理解,float32 能保存的数值范围本身就比 uint8 多,因此必定有大量数值无法用 uint8 表示,只能四舍五入成 uint8 型的数值。量化模型和全精度模型的误差也来自四舍五入的 clip 操作。

这篇文章中会用到一些公式,这里我们用 r 表示浮点实数,q 表示量化后的定点整数。浮点和整型之间的换算公式为:

在这里插入图片描述

其中,S是 scale,表示实数和整数之间的比例关系,Z 是 zero point,表示实数中的 0 经过量化后对应的整数,它们的计算方法为:

在这里插入图片描述

rmax 、 rmin 分别是r的最大值和最小值, qmax、 qmin 同理。这个公式的推导比较简单,很多资料也有详细的介绍,这里不过多介绍。需要强调的一点是,定点整数的 zero point 就代表浮点实数的 0,二者之间的换算不存在精度损失,这一点可以从公式 (2) 中看出来,把 r=0代入后就可以得到 q=Z。这么做的目的是为了在 padding 时保证浮点数值的 0 和定点整数的 zero point 完全等价,保证定点和浮点之间的表征能够一致。

二、量化与反量化结果做对比

#include<stdio.h>
#include<string.h>
#include<math.h>
typedef char int8;


float find_float32_max(float *r)
{
    int len = sizeof(r) / sizeof(float); 
    float tmp=0.0f;
    for(int i=0;i<len;i++)
    {
        if(r[i]>tmp)
        {
            tmp = r[i];
        }  
    }
    return tmp;  
}

float find_float32_min(float *r)
{
    int len = sizeof(r) / sizeof(float); 
    float tmp=r[0];
    for(int i=0;i<len;i++)
    {
        if(r[i]<tmp)
        {
            tmp= r[i];
        }  
    }
    return tmp;  
}

//s 是scale 量化系数
float s_value(float *r,int8 *q)
{
    float r_max = find_float32_max(r);
    float r_min = find_float32_min(r);
    int8 q_max = 127;
    int8 q_min = -128;

    float s = (r_max-r_min)/(q_max-q_min);
    return s;
}

//z是zero point 表示实数中的0经过量化后的整数
float z_value(float *r,int8 *q)
{
    float r_max = find_float32_max(r);
    int8 q_max = 127;
    float s = s_value(r,q);
    float z = round(q_max-r_max/s); //越界了
    return z;
}

int float32_to_int8(float *r,int8 *q,float *s,float *z)
{

    *s = s_value(r,q);
    *z = z_value(r,q);

    printf("s=%f\n",*s);
    printf("z=%f\n",*z);

    int len = sizeof(r) / sizeof(float); 
    for(int i=0;i<len;i++)
        q[i] = (int8)round(r[i]/(*s)+(*z));

    return 0;
}

void float32_to_int8_test()
{
    float r[2]={2.1,8.6};
    int8 q[2];
    float s;  
    float z;
    int i;
    int len = sizeof(r) / sizeof(float); 
    float32_to_int8(r,q,&s,&z);

    printf("quantification result:\n");
    for( i=0;i<len;i++)
        printf("q[%d]=%d ",i,q[i]);

    printf("\n");

    printf("inverse quantization result:\n");
    for(i=0;i<len;i++)
    {
        r[i] =  s*(q[i]-z);
        printf("r[%d]=%f ",i,r[i]);
    }
}

int main()
{
    float32_to_int8_test();
    return 0;
}


输入的在这里插入图片描述

量化后的结果为对应为-128,127 ,反量化后的结果与没量化的初始结果发现精度有略微的损失,但是效率 可以提高四倍。
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

神经网络量化与反量化( int8与float32之间的转换)+C语言实现 的相关文章

  • PX4开发环境搭建

    PX4开发环境搭建 编译工具链的安装vscode 编译工具链的安装 下载ubuntu sh requirements txt wget https raw githubusercontent com PX4 Firmware master
  • TFmini在nora+(px4)上的使用和验证

    目标 xff1a 使用tfmini完成定高实验 设置 xff1a 1 sens tfmini cfg 设置为telem2 xff08 可修改为其他 xff0c 保证硬件连线一致 xff0c 1一般是无线数传所以没改过去 其他的对应在官网里有
  • ROS | Realsense中的IMU解算orientation

    文章目录 概述 一 定义介绍 二 操作教程 一 下载并编译imu tools功能包 1 创建工作空间并初始化 2 下载imu tools并编译 二 修改配置 1 修改imu tools源码 2 修改launch文件 3 启动解算 概述 本文
  • prometheus服务监控之mysql监控

    文章目录 上传解压安装mysqld exporter安装mariadb在数据库里创建mysql账号用户收集数据在mysql exporter中设置mysql配置信息启动mysql exporter配置prometheus拉取mysql节点信
  • HTTP请求头Authorization

    今天部署了一个Authorization项目 xff0c 由于改了auth服务器客户端id和密码 xff0c 而前端请求header没有修改 xff0c 登录时一直弹框要求输入用户名和密码 xff0c 输入后却无效 xff0c 只好改前端代
  • c语言编程规范第三部分

    3 头文件应向稳定的方向包含 头文件的包含关系是一种依赖 xff0c 一般来说 xff0c 应当让不稳定的模块依赖稳定的模块 xff0c 从而当不稳定的模块发生变化时 xff0c 不会影响 xff08 编译 xff09 稳定的模块 就我们的
  • 看完《C++ primer》后,我都收获了什么?

    文章目录 1 语言只是一个工具2 光学会一门语言还不够3 结语 迫于读研和未来就业的压力 xff0c 我研一上自学了C 43 43 的这门语言 xff0c 自我感觉比较认真的看完了 C 43 43 primer 这本书的大部分章节 xff0
  • Ubuntu18.04 ROS Melodic版本安装gazebo_ros_pkgs包

    疫情期间宅在家没法做实验 xff0c 只能上手gazebo做仿真 xff0c 导入实验室机器人的相关文件后 xff0c 打算看看效果 xff0c 运行代码 roslaunch probot gazebo probot anno gazebo
  • vim如何批量注释

    1 ctrl 43 v 进入 2 按箭头 选中要注释的首行 3 按下大写 i 进入插入模式 4输入 按esc 就可以看到如下内容
  • 还弄不明白【委托和事件】么?看这一篇就足够了!!!

    这两个概念长时间不用了 xff0c 今天看到CAD二次开发中用到了自定义事件 xff0c 有点迷糊了 xff0c 索性再整理一下加深印象 xff01 一说到委托和事件 xff0c 他们总是绑定在一起的不可分割 xff01 可能你会说啊 xf
  • 三种简单排序(冒泡、插入、选择)的比较和图解

    冒泡排序 这种排序方式是最容易理解的 xff0c 主体思想就是 xff1a 指针重复地走访过要排序的数列 xff0c 一次比较两个元素 xff0c 如果他们的顺序错误就把他们交换过来 走访数列的工作是重复地进行直到没有再需要交换 xff0c
  • ModuleNotFoundError: No module named 'XXX'的解决办法

    类似问题一 ModuleNotFoundError No module named 39 captcha 39 pycharm打开的项目 xff0c 在虚拟环境里通过终端命令python manage py runserver运行pytho
  • 微信小程序实现搜索功能以及效果(超详细)

    我们先来看一下实现哪些功能 1 搜索历史记录以及清空历史记录 2 热门搜索推荐以及更新推荐内容 3 根据输入框输入的内容来自动搜索相关查询 后台逻辑是模糊查询 后台就先不扯了 这里我用的是自己定义的虚拟数据 暂时没用后台接口 可能有点问题
  • 微信小程序实现收货地址城市选择效果(添加收货地址)

    先来张效果图 这里主要是城市选择效果 请忽视其他 不要吐槽 谢谢 接下来看一下代码吧 wxml lt pages my my add address index wxml gt lt view class 61 34 redact addr
  • uni-app实现商城多商家购物车功能(超详细, 附带源码)

    我们先来看一下效果 有什么不懂可以直接下方留言 先来看代码 lt template gt lt view class 61 34 cart 34 gt lt 购物车为空 S gt lt view v if 61 34 cartList le
  • 微信小程序web-view的使用教程

    最近公司有需求 xff0c 需要点击小程序首页banner xff0c 跳转到别人的h5页面 首先是域名的问题 xff1a 步骤 xff1a 先登录小程序开发平台 xff0c 将页面需要跳转的域名写上去 xff0c 注意了 xff0c 域名
  • uni-app实现上传图片裁剪效果(附源码)

    我们先来看一下效果 封装一个组件在components下创建一个 文件夹随意命名 xff0c 这里我是uni img cropper uni img cropper vue lt template gt lt view class 61 3
  • js 一维数组和二维数组实现足迹、浏览记录等场景

    再开发过程中 xff0c 再没有接口提供的情况下来实现浏览记录或者搜索记录等场景 我们可以利用本地缓存实现 xff0c 废话不多说 xff0c 直接上代码 xff1a 多维数组 64 param Array arr 数组 64 param
  • Markdown使用(超详细)

    xff08 HBuilderX xff09 掌握md及HBuilderX对md的强大支持 如果没有点右键设置自动换行 xff0c 可按Alt 43 滚轮横向滚动查看 很多人只把markdown用于网络文章发表 xff0c 这糟蹋了markd
  • 宫格导航 (自定义更灵活,超详细)

    先来看一下效果 调用方法 lt 页面调用 gt lt nav grid list 61 34 menu 34 64 click 61 34 34 gt lt nav grid gt 数据 export default data return

随机推荐