通俗易懂的讲解一下量化操作(深度学习模型定点化)

您所在的位置:网站首页 量化投资的通俗理解 通俗易懂的讲解一下量化操作(深度学习模型定点化)

通俗易懂的讲解一下量化操作(深度学习模型定点化)

2024-02-03 16:21| 来源: 网络整理| 查看: 265

近几年随着人工智能技术发展,深度学习技术日趋成熟。如果想把已经训练好的模型应用在终端,如手机、车载、耳机、音箱等设备,需要将Python训练的模型转为C语言。此处就不赘述如何把Python模型转C语言的步骤了(都是矩阵乘l累加操作)。

本文意在通俗讲解一下C语言的浮点版本转定点版本的步骤。让初次接触量化(定点化)操作的小白能够有个初步认识,都是个人经验,如有表述不对还请多多指正。

废话不多说,让我们开始吧!!!!

众所周知,C语言在使用变量前都要先定义其类型(float,double,char,int,long等),如果想表示两个浮点数相乘,可以如下操作:

#include int main(){ float num1 = 3.141592; float num2 = 1.492; float num3 = 7.24; float result; result = num1 * num2 + num3; printf("%f * %f + %f = %f;\n",num1, num2, num3, result); return 0; }

以上代码的输出是3.141592 * 1.492000 + 7.240000 = 11.927256;

但是两个浮点数操作会比较耗费时钟周期数,这就导致功耗变高,甚至有些低功耗芯片上不支持浮点操作,我们就需要将其转化为定点版本。那我们该如何下手呢,接下来就讲一下具体操作步骤。

一、确定使用多少位的操作数来表示浮点

C语言的整型表示有8位(char),16位(short),32位(int),64位(long)等,如何选择多少位来表示浮点数取决于你所需的精度是多少。一般来说16位是比较合适的。具体的误差在后续会讲到。

二、对操作数定标

所谓的定标就是将浮点数乘以2的多少次方才能让数据最大的同时还不超过数据的表示范围。比如short表示的范围是-32768~32767,以num1为例,

int(3.141592 * (2^13)) = 25735 //此处我们是直接截断取整,也可以四舍五入,向上、下取整

int(3.141592 * (2^14)) = 51471

51471超出了short的表示范围,但是25735却没有超过表示范围,所以num1的标值Q1就选择13最为合适。同理可得num2的标值Q2选择14,num3的标值Q3选择12。

这样我们就得到了定点的num1, num2和num3:

num1_fix = 25735, num2_fix = 24444, num3_fix = 29655;

三、对定点后的三个数进行乘、加操作 #include #include include int main(){ float num1 = 3.141592; float num2 = 1.492; float num3 = 7.24; short Q1 = 13, Q2 = 14, Q3 = 12; short num1_fix, num2_fix, num3_fix; int32_t result_fix; float result; result = num1 * num2 + num3; printf("%f * %f + %f = %f;\n",num1, num2, num3, result); num1_fix = (short)(num1 * pow(2,Q1)); num2_fix = (short)(num2 * pow(2,Q2)); num3_fix = (short)(num3 * pow(2,Q3)); result_fix = (int32_t)num1_fix * (int32_t)num2_fix;//此时result_fix的标值是两个的数标值的和,即Q1+Q2 result_fix = result_fix >> (Q1+Q2-Q3);//右移n位是除以2^n,为了让num1和num2成完以后的标值和num3对应 result_fix = result_fix + (int32_t)num3_fix; printf("%d * %d + %d = %d;\n",num1_fix, num2_fix, num3_fix, result_fix); printf("%d / pow(2,%d) = %f\n",result_fix,Q3,(float)result_fix /pow(2,Q3)); return 0; }

以上代码的输出为:

3.141592 * 1.492000 + 7.240000 = 11.927256; 25735 * 24444 + 29655 = 48852; 48852 / pow(2,12) = 11.926758

此时对上述代码重点描述的是num1_fix*num2_fix后结果的Q值是Q1+Q2,相乘(相除)时两个数的标值不要求相同,但要记得乘完以后的结果的标值已改变,变为了Q1+Q2。但是两个定点数相加(相减)时的Q值必须要求一致,否则会出错。这就是为什么在加num3_fix之前要对result_fix进行移位的原因,为了将两个数的标值对其(标值只要一样就行,也可以不等于Q1,Q2,Q3任意一个,但是自己要清楚此时的标值),最终得到的结果是浮点结果*最终标值的数Q。将这个数除以对应的2^Q就是浮点的结果。

根据程序的输出结果可以看出,定点版本和浮点版本最终的结果误差为

abs(11.926758 - 11.927256)  = 0.000498 = 4.98*1e-4

误差可接受。到此浮点转定点的小实例已经讲解完毕,希望对你有用,谢谢~



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3