泥鳅喜欢吃什么食物| 红颜知己代表什么关系| 县公安局长什么级别| cartoon什么意思| 阴茎进入阴道什么感觉| 办准生证需要什么资料| 脑血管堵塞吃什么药好| 艾滋病人有什么特征| 心阳不足吃什么中成药| 后续是什么意思| 肚子胀痛吃什么药| 舌苔发黄厚是什么原因| 备孕不应该吃什么| 小孩睡觉流鼻血是什么原因引起的| 睾丸炎吃什么药| 付诸行动是什么意思| 注意身体是什么意思| 尿道感染要吃什么药才能快速治好| 男戴观音女戴佛有什么讲究| 梦见着火了是什么意思| 甲状腺一度肿大是什么意思| 沙特是什么教派| 甲亢是一种什么病严重吗| 鹌鹑蛋不能和什么一起吃| 格调是什么意思| 什么人容易得甲亢| 鸡为什么喜欢吃泡沫| 海水是什么颜色的| 27属相是什么生肖| 过期的洗面奶可以用来做什么| 什么花有毒| 为什么右眼一直跳| 醴什么意思| 万岁是什么意思| 热淋是什么病| 宋威龙什么星座| 少腹是什么意思| 外阴瘙痒用什么效果好| 什么的仪式| 明目退翳是什么意思| dove什么意思| 重阳节吃什么好| 荨麻疹吃什么药好的快| 什么店可以买到老鼠药| 血糖高吃什么主食最好| 左手小手指麻木是什么原因引起的| 梦见家里办丧事是什么预兆| 三叉神经痛吃什么药效果好| 惗是什么意思| 40什么意思| 丙型肝炎吃什么药最好| 英姿的动物是什么生肖| 嗓子有粘痰什么原因| 蛛网膜囊肿是什么病| 特此通知写在什么位置| 自限性疾病是什么意思| c k是什么牌子| 疮疖是什么样子图片| 门口放镜子有什么讲究| 人体消化道中最长的器官是什么| 口腔上火了吃什么降火最快| 马提尼是什么酒| 坚果什么时候吃最好| 24k金是什么意思| 一什么阳光| 什么的后羿| 什么鱼吃泥鳅| 妇科炎症是什么原因引起的| 梦见纸人是什么意思| 双肺纤维条索是什么意思| 995是什么意思| 三宝是什么意思| 脸颊两边长痘痘是什么原因引起的| miracle是什么意思| 指甲月牙代表什么| 被艹是什么感觉| 1989年出生是什么命| 乳腺挂什么科| 什么叫宿根太阳花| 粘连是什么意思| 毛泽东女儿为什么姓李| 脑梗吃什么药好| 插入是什么感觉| 帽子丢了有什么预兆| 如意是干什么用的| 牛刀割鸡是什么生肖| 眼皮红肿是什么原因| 槟榔是什么味道| 土崩瓦解是什么意思| 乳酸偏高是什么意思| 今年三十岁属什么生肖| 水逆退散是什么意思| 一语道破什么意思| 腰果有什么好处| 脸上白一块一块的是什么原因| 母慈子孝下一句是什么| 生机勃勃什么意思| 传染病4项是什么| 手心发黄是什么原因| 80年出生属什么生肖| 黄芪的作用是什么| 牛磺酸是什么| 处女膜是什么样的| 我想成为一个什么样的人| 锁骨窝疼可能是什么病| 夜间睡觉流口水是什么原因| 头皮屑多是什么原因引起的| 为什么来月经| 英特纳雄耐尔是什么意思| 依从性是什么意思| 紫微斗数是什么| 17数字代表什么意思| 肾积水是什么原因造成的| 沉冤得雪是什么意思| 独立户口需要什么条件办理| 糖尿病吃什么水果比较好| 碧绿的什么| 白带发黄是什么原因引起的| 家里放什么最招财| 吃生花生有什么好处| 怀孕可以吃什么水果| 猪展是什么| 号什么意思| 肋膈角锐利是什么意思| 常喝柠檬水有什么好处和坏处| 什么是黄体酮| 甲状腺结节吃什么药| 梦见赢钱了是什么预兆| 粿是什么意思| 什么叫自私的人| 结肠炎吃什么药治疗效果好| 低压高有什么危险| 胆囊炎能吃什么| 小女子这厢有礼了什么意思| 牙龈肿痛吃什么药好| 啤酒加生鸡蛋一起喝有什么效果| 3月11日什么星座| 乳糖不耐受是什么意思| 丘疹是什么原因引起的| 极光是什么意思| 三月初一是什么星座| 测五行缺什么| cro公司是什么意思| 早起眼皮肿是什么原因引起的| 档案自由可投什么意思| 声东击西是什么意思| 夏朝前面是什么朝代| 菌痢的症状是什么样| 牛黄是什么东西| 满月脸是什么意思| 战五渣是什么意思| 娇喘什么意思| 心肌缺血吃什么药效果最好| 金目念什么| 黄子韬爸爸是干什么的| 五官立体是什么意思| 鄙人什么意思| 甲抗是什么原因引起的| 打2个喷嚏代表什么| 小孩经常吐是什么原因| 颐养天年是什么意思| 头皮痛什么原因引起的| 什么是性格| 辣椒油用什么能洗掉| 崽崽是什么意思| 喝蜂蜜水对身体有什么好处| 戴黄金对身体有什么好处| wb是什么| 书中自有颜如玉什么意思| 心脏衰竭吃什么药| 梦见狼是什么意思周公解梦| 猴和什么属相最配| 单脐动脉对胎儿有什么影响| 细胞是由什么构成的| 腊月十八是什么星座| 心脏病有什么症状| 空调除湿和制冷有什么区别| 女人吃什么水果最好| 伤元气是什么意思| 测骨龄去医院挂什么科| 附属医院是什么意思| 子宫在肚脐眼什么位置| 为什么第一次没有出血| 四两拨千斤是什么意思| 阿莫西林不能和什么一起吃| 十一月二十二是什么星座| 大天真香是什么意思| 贞操是什么| 悠悠岁月什么意思| 月经黑红色是什么原因| 吃什么油对心脑血管好| 率真是什么意思| 三尖瓣关闭不全是什么意思| 翻来覆去是什么意思| 为什么会得肾构错瘤| 摩羯座是什么象星座| 吃什么东西去湿气| 贝五行属什么| 脾虚要吃什么东西调理| 肾囊肿挂什么科| esim卡是什么| 枸杞是补什么的| 背部爱出汗是什么原因| 乌鸡白凤丸男性吃治疗什么| 岔气吃什么药最管用| tpc是什么意思| 死后是什么感觉| 头发白是什么原因引起的| 向左向右向前看是什么歌| 人格独立是什么意思| 查心电图挂什么科| 外痔疼痛用什么药最好| 现在买什么股票好| 肠梗阻挂什么科| 胃寒湿气重吃什么药效果最好| 什么鞋油好用| normal是什么意思| 怀孕有什么特征和反应| 1217是什么星座| 为什么总是拉肚子| 石女是什么意思啊| rem是什么意思| 鸽子喜欢吃什么食物| 15岁属什么| 儿童用什么牙膏最好可以保护牙齿| 障碍是什么意思| 心静自然凉是什么意思| 可心是什么意思| 月下老人什么意思| 当志愿者有什么好处| 虾不能和什么一起吃| 什么什么的天空| 甲钴胺片是治什么病| 哮喘吃什么食物好| 一个金字旁一个本念什么| 脂溢性脱发用什么洗发水好| 北京市市长是什么级别| 晴雨伞是什么意思| 帕罗西汀是什么药| 孩子手抖是什么原因| tap是什么意思| 前额白发是什么原因| 腰疼吃什么药效果好| 啤酒为什么是苦的| 尿路感染是什么原因造成的| 舅舅的女儿叫什么| 腹胀屁多是什么原因| 血压低吃什么中成药| 鳏寡孤独是什么意思| 消化不良吃什么中药| 钙果是什么水果| 规格型号是什么意思| 掉睫毛是什么原因| 李商隐是什么朝代的| 丰都为什么叫鬼城| 舌头麻是什么原因| 知了在树上干什么| 脖子粗大是什么原因| 今年77岁属什么生肖| 甘油三酯高不能吃什么| pab是什么意思| 下午五点多是什么时辰| 势如破竹是什么意思| 茶叶过期了有什么用途| 百度
"); //-->

博客专栏

EEPW首页 > 博客 > 征程 6E/M|如何解决量化部署时 mul 与 bool 类型数据交互的问题

密云水库库滨带水源保护(绿化)二期工程开始进...

发布人:地平线开发者 时间:2025-08-04 来源:工程师 发布文章
百度 公安部、国家安全部、司法部干部职工表示,一定不辱使命,努力创造安全的政治环境、稳定的社会环境、公正的法治环境,使人民群众共享全面依法治国的成果。

一、引言

使用 征程 6 工具链进行量化部署时,涉及 bool 类型数据计算时,会有一些与全 float 计算不同的情况,需要特别注意。

本文将重点结合 PyTorch 的 torch.mul(逐元素相乘)以及张量的 类型提升(Type Promotion) 规则,分析在 征程 6 工具链上 量化部署时 mul 与 bool 类型数据交互的问题。


二、bool 计算示例

在 PyTorch 中,bool 类型的数据用于表示 掩码(mask),常见的操作包括 torch.logical_not()、比较运算符(如 ==)等。当 bool 类型数据与其他数据类型进行算术运算时,PyTorch 会遵循 类型提升(Type Promotion) 规则,将 bool 转换为更高精度的数值类型。例如:

import torch
x = torch.tensor([1.0, 2.0, 3.0])
y = torch.tensor([True, False, True])
result = x * y  # 逐元素相乘
print(result)  # tensor([1., 0., 3.])
print(result.dtype)  # torch.float32

在这个例子中,bool 类型的 y 在计算时被提升为 float32 类型,因此计算结果仍然是 float32。

torch.mul 官方文档里确实没明确说支持 bool 类型输入(官网链接),但 PyTorch 底层的张量操作支持 bool,是一种 隐式支持,官方文档默认大家了解 PyTorch 的 类型提升(type promotion)规则。

三、模型中 bool 量化问题分析

在量化模型中,当 bool 数据在计算过程中发生类型提升,特别是浮点数过了 quant,再进行比较,可能会出现很大的量化误差。代码示例如下:

class small_model(nn.Module):
    def __init__(self):
        super(small_model, self).__init__()
        self.quant = QuantStub()
        self.dequant = DeQuantStub()
        
    def forward(self, actors_input):
        actors_input = self.quant(actors_input)
        print("actors_input:", actors_input)
        # actors_mask = torch.logical_not(actors_input[:, :, :, -1] == 0)    # 一定程度上正确写法
        actors_mask = actors_input[:, :, :, -1] == 1     # 错误写法,会导致 calib 指标崩掉
        print("actors_mask", actors_mask)
        print("actors_mask shape:", actors_mask.shape)
        print("actors_mask[:, :, :, None] shape:", actors_mask[:, :, :, None]。shape)
        actors_output = actors_input * actors_mask[:, :, :, None]
        return self.dequant(actors_output)

model = small_model()

## ================================================================#
# 生成随机数据
# torch.manual_seed(41)
# actors_data = torch.randn(1, 2, 4, 3)
# actors_mask = torch.randint(0, 2, (1, 2, 4, 1), dtype=torch.bool)
# example_input = torch.cat([actors_data, actors_mask], dim=-1)
example_input = torch.tensor([[[[ 0.2465, -0.4717, 60.5,  1.0000],
          [-0.2124,  0.5660, -1.6637,  0.0000],
          [ 0.3338,  1.6051, -1.5088,  1.0000],
          [-0.9215, -0.5901,  1.4871,  0.0000]],
          
         [[ 0.1650, -0.3785,  1.6710,  0.0000],
          [-0.3752,  0.2337,  0.4186,  0.0000],
          [-0.2221, -0.1745, -0.6064,  1.0000],
          [ 0.9174, -0.6317,  0.6133,  1.0000]]]])
print("example_input:", example_input)
## ================================================================#
output = model(example_input)
print("float output:", output)

使用 actors_mask = actors_data[:, :, :, -1] == 1 来生成布尔掩码。

example_input: tensor([[[[ 0.2465, -0.4717, 60.5,  1.0000],
          [-0.2124,  0.5660, -1.6637,  0.0000],
          [ 0.3338,  1.6051, -1.5088,  1.0000],
          [-0.9215, -0.5901,  1.4871,  0.0000]],
          
         [[ 0.1650, -0.3785,  1.6710,  0.0000],
          [-0.3752,  0.2337,  0.4186,  0.0000],
          [-0.2221, -0.1745, -0.6064,  1.0000],
          [ 0.9174, -0.6317,  0.6133,  1.0000]]]])
actors_input: tensor([[[[ 0.2465, -0.4717, 60.5,  1.0000],
          [-0.2124,  0.5660, -1.6637,  0.0000],
          [ 0.3338,  1.6051, -1.5088,  1.0000],
          [-0.9215, -0.5901,  1.4871,  0.0000]],
          
         [[ 0.1650, -0.3785,  1.6710,  0.0000],
          [-0.3752,  0.2337,  0.4186,  0.0000],
          [-0.2221, -0.1745, -0.6064,  1.0000],
          [ 0.9174, -0.6317,  0.6133,  1.0000]]]])
actors_mask tensor([[[ True, False,  True, False],
         [False, False,  True,  True]]])
actors_mask shape torch.Size([1, 2, 4])
actors_mask[:, :, :, None] shape torch.Size([1, 2, 4, 1])
float output: tensor([[[[ 0.2465, -0.4717, 60.5,  1.0000],
          [-0.0000,  0.0000, -0.0000,  0.0000],
          [ 0.3338,  1.6051, -1.5088,  1.0000],
          [-0.0000, -0.0000,  0.0000,  0.0000]],
          
         [[ 0.0000, -0.0000,  0.0000,  0.0000],
          [-0.0000,  0.0000,  0.0000,  0.0000],
          [-0.2221, -0.1745, -0.6064,  1.0000],
          [ 0.9174, -0.6317,  0.6133,  1.0000]]]])

打印的结果如上,可以看到,float 输出没有任何问题。

然而,在 量化模型 中,这种 bool mask 运算会由于微小的量化误差发生非常大的变化,原因在:

actors_data = self.quant(actors_data)
actors_mask = actors_data[:, :, :, -1] == 1

数值 1 经过量化反量化后,可能会产生一个或多个 scale 的误差,原本是 1 的位置就不再是 1 了,会变成 0.9x 或 1.0x,这样就==1 就不再是 True 了。

打印看到 actors_mask 全部均为 False。

=========set_fake_quantize(calib_model, FakeQuantState.VALIDATION)=========
actors_input: QTensor(
  data = tensor([[[[ 0.2474, -0.4708, 60.4991,  1.0007],
          [-0.2123,  0.5668, -1.6636,  0.0000],
          [ 0.3342,  1.6045, -1.5085,  1.0007],
          [-0.9213, -0.5908,  1.4863,  0.0000]],
          
         [[ 0.1643, -0.3785,  1.6709,  0.0000],
          [-0.3748,  0.2345,  0.4191,  0.0000],
          [-0.2216, -0.1754, -0.6056,  1.0007],
          [ 0.9176, -0.6314,  0.6130,  1.0007]]]]),
  scale = tensor([0.0018]),
  zero_point = tensor([0]),
  dtype = qint16,
  per_channel_axis = -1,
  is_quantized = False
)
actors_mask tensor([[[False, False, False, False],
         [False, False, False, False]]])
actors_mask shape: torch.Size([1, 2, 4])
actors_mask[:, :, :, None] shape: torch.Size([1, 2, 4, 1])
calib_model out: tensor([[[[0., 0., 0., 0.],
          [0., 0., 0., 0.],
          [0., 0., 0., 0.],
          [0., 0., 0., 0.]],
          
         [[0., 0., 0., 0.],
          [0., 0., 0., 0.],
          [0., 0., 0., 0.],
          [0., 0., 0., 0.]]]])

这种结果明显是不符合预期的。

四、bool 量化问题解决

怎么修改呢?如下所示

        actors_mask = torch.logical_not(actors_data[:, :, :, -1] == 0)    # 一定程度上正确写法
        # actors_mask = actors_data[:, :, :, -1] == 1     # 错误写法,会导致calib指标崩掉

0 经过对称量化,依旧是 0,再经过 logical_not 即可。此时输出变为:结果是正确的。

=========set_fake_quantize(calib_model, FakeQuantState.VALIDATION)=========
actors_input: QTensor(
  data = tensor([[[[ 0.2474, -0.4708, 60.4991,  1.0007],
          [-0.2123,  0.5668, -1.6636,  0.0000],
          [ 0.3342,  1.6045, -1.5085,  1.0007],
          [-0.9213, -0.5908,  1.4863,  0.0000]],
          
         [[ 0.1643, -0.3785,  1.6709,  0.0000],
          [-0.3748,  0.2345,  0.4191,  0.0000],
          [-0.2216, -0.1754, -0.6056,  1.0007],
          [ 0.9176, -0.6314,  0.6130,  1.0007]]]]),
  scale = tensor([0.0018]),
  zero_point = tensor([0]),
  dtype = qint16,
  per_channel_axis = -1,
  is_quantized = False
)
actors_mask tensor([[[ True, False,  True, False],
         [False, False,  True,  True]]])
actors_mask shape: torch.Size([1, 2, 4])
actors_mask[:, :, :, None] shape: torch.Size([1, 2, 4, 1])
calib_model out: tensor([[[[ 0.2474, -0.4708, 60.4991,  1.0007],
          [ 0.0000,  0.0000,  0.0000,  0.0000],
          [ 0.3342,  1.6045, -1.5085,  1.0007],
          [ 0.0000,  0.0000,  0.0000,  0.0000]],
          
         [[ 0.0000,  0.0000,  0.0000,  0.0000],
          [ 0.0000,  0.0000,  0.0000,  0.0000],
          [-0.2216, -0.1754, -0.6056,  1.0007],
          [ 0.9176, -0.6314,  0.6130,  1.0007]]]])

这种方案一定正确吗?答案:不一定是正确的,需要考虑极值问题。另外,由于 mul 不支持输入为 bool 类型,这儿还会出现 cpu 算子问题。

生成的 quantized.onnx 可以看到,确实 mul 运行在 cpu 上。

4.1 CPU 算子问题

主要原因是:右侧工具自动进行:bool->float32

第一个思路是:直接将 actors_mask 转 torch.int16,

actors_mask = torch.logical_not(actors_input[:, :, :, -1] == 0).to(torch.int16)

这样是不行的。因为过了 quant 的 actors_input 是 Qtensor,而。to(torch.int16)强转的 actors_mask 是常规 torch tensor,这也是不行的。

接着就可以想到,应该转 float,然后过 quant,修改如下:

        actors_mask = torch.logical_not(actors_input[:, :, :, -1] == 0).to(torch.float)    # 一定程度上正确写法
        actors_mask = self.quant_mask(actors_mask)

此时 mul 左右两边都是 qtensor,打印信息如下:

=========set_fake_quantize(calib_model, FakeQuantState.VALIDATION)=========
actors_input: QTensor(
  data = tensor([[[[ 0.2474, -0.4708, 60.4991,  1.0007],
          [-0.2123,  0.5668, -1.6636,  0.0000],
          [ 0.3342,  1.6045, -1.5085,  1.0007],
          [-0.9213, -0.5908,  1.4863,  0.0000]],
          
         [[ 0.1643, -0.3785,  1.6709,  0.0000],
          [-0.3748,  0.2345,  0.4191,  0.0000],
          [-0.2216, -0.1754, -0.6056,  1.0007],
          [ 0.9176, -0.6314,  0.6130,  1.0007]]]]),
  scale = tensor([0.0018]),
  zero_point = tensor([0]),
  dtype = qint16,
  per_channel_axis = -1,
  is_quantized = False
)
actors_mask QTensor(
  data = tensor([[[1.0000, 0.0000, 1.0000, 0.0000],
         [0.0000, 0.0000, 1.0000, 1.0000]]]),
  scale = tensor([3.0518e-05]),
  zero_point = tensor([0]),
  dtype = qint16,
  per_channel_axis = -1,
  is_quantized = False
)
actors_mask shape: (1, 2, 4)
actors_mask[:, :, :, None] shape: (1, 2, 4, 1)
calib_model out: tensor([[[[ 0.2474, -0.4708, 60.4972,  1.0007],
          [ 0.0000,  0.0000,  0.0000,  0.0000],
          [ 0.3342,  1.6045, -1.5085,  1.0007],
          [ 0.0000,  0.0000,  0.0000,  0.0000]],
          
         [[ 0.0000,  0.0000,  0.0000,  0.0000],
          [ 0.0000,  0.0000,  0.0000,  0.0000],
          [-0.2216, -0.1754, -0.6056,  1.0007],
          [ 0.9176, -0.6314,  0.6130,  1.0007]]]])

可以看到,是全一段 BPU。

在不考虑极值的影响下,改动完成,此时代码如下:

class small_model(nn.Module):
    def __init__(self):
        super(small_model, self).__init__()
        self.quant = QuantStub()
        self.dequant = DeQuantStub()
        self.quant_mask = QuantStub()
        
    def forward(self, actors_input):
        actors_input = self.quant(actors_input)
        actors_mask = torch.logical_not(actors_input[:, :, :, -1] == 0).to(torch.float)    # 一定程度上正确写法
        actors_mask = self.quant_mask(actors_mask)
        actors_output = actors_input * actors_mask[:, :, :, None]  # + - * /
        return self.dequant(actors_output)
        
model = small_model()

## ================================================================#
# 生成随机数据
# torch.manual_seed(41)
# actors_data = torch.randn(1, 2, 4, 3)
# actors_mask = torch.randint(0, 2, (1, 2, 4, 1), dtype=torch.bool)
# example_input = torch.cat([actors_data, actors_mask], dim=-1)
example_input = torch.tensor([[[[ 0.2465, -0.4717, 60.5,  1.0000],
          [-0.2124,  0.5660, -1.6637,  0.0000],
          [ 0.3338,  1.6051, -1.5088,  1.0000],
          [-0.9215, -0.5901,  1.4871,  0.0000]],
          
         [[ 0.1650, -0.3785,  1.6710,  0.0000],
          [-0.3752,  0.2337,  0.4186,  0.0000],
          [-0.2221, -0.1745, -0.6064,  1.0000],
          [ 0.9174, -0.6317,  0.6133,  1.0000]]]])
print("example_input:", example_input)
## ================================================================#
output = model(example_input)
print("float output:", output)

4.2 极值问题bool 被其他极大值 影响

如果模型输入 actors_input 有极大值存在,例如 70000,int16 量化,会将 actors_mask 原本是 1 的地方给变为 0,量化输出示例如下:

=========set_fake_quantize(calib_model, FakeQuantState.VALIDATION)=========
actors_input: QTensor(
  data = tensor([[[[ 0.0000e+00,  0.0000e+00,  6.9999e+04,  0.0000e+00],
          [ 0.0000e+00,  0.0000e+00, -2.1363e+00,  0.0000e+00],
          [ 0.0000e+00,  2.1363e+00, -2.1363e+00,  0.0000e+00],
          [ 0.0000e+00,  0.0000e+00,  2.1363e+00,  0.0000e+00]],
          
         [[ 0.0000e+00,  0.0000e+00,  2.1363e+00,  0.0000e+00],
          [ 0.0000e+00,  0.0000e+00,  0.0000e+00,  0.0000e+00],
          [ 0.0000e+00,  0.0000e+00,  0.0000e+00,  0.0000e+00],
          [ 0.0000e+00,  0.0000e+00,  0.0000e+00,  0.0000e+00]]]]),
  scale = tensor([2.1363]),
  zero_point = tensor([0]),
  dtype = qint16,
  per_channel_axis = -1,
  is_quantized = False
)
actors_mask QTensor(
  data = tensor([[[0., 0., 0., 0.],
         [0., 0., 0., 0.]]]),
  scale = tensor([3.0518e-05]),
  zero_point = tensor([0]),
  dtype = qint16,
  per_channel_axis = -1,
  is_quantized = False
)
calib_model out: tensor([[[[0., 0., 0., 0.],
          [0., 0., 0., 0.],
          [0., 0., 0., 0.],
          [0., 0., 0., 0.]],
          
         [[0., 0., 0., 0.],
          [0., 0., 0., 0.],
          [0., 0., 0., 0.],
          [0., 0., 0., 0.]]]])

根据量化公式:

quantized=clamp(round(float/scale),qmin,qmax)

float:浮点数 数据,即 fp32(32-bit 浮点数)表示的张量值。

scale:缩放因子(scale factor),用于将浮点数缩放到整数范围(量化尺度)。

round(float/scale):对缩放后的值进行四舍五入,得到量化的整数表示。

clamp(…, qmin, qmax):将量化值限制在 最小值 qmin 和 最大值 qmax 之间,防止溢出。

在这个示例中,scale = 70000/32767 = 2.1263。bool 类型的 1,经过量化:round(1 / 2.1263)=0,由于 round 舍入误差的存在,原来的 1 也被变为了 0,再经过反量化也拯救不了这个舍入误差了。

bool 1 作为 极大值 的影响

如果模型输入 actors_data 都是非常小的数值,由于 bool 类型 1 的存在,会导致 1 成为极大值,影响量化 scale 的统计,继而影响其他数值的量化精细程度。

所以,最稳妥的方式,是将 actor_data 与 actor_mask 分开送入模型。actor_data 自己过 quant,actor_mask 自己过 quant_mask。

4.3 解决方案示例bool 类型已经变 为 0/1 的 float,可以这么写。需要注意,一定是只有 0 / 1 的 float,在模型中间也可以这么写。

class small_model(nn.Module):
    def __init__(self):
        super(small_model, self).__init__()
        self.quant = QuantStub()
        self.quant_mask = QuantStub()
        self.dequant = DeQuantStub()
        
    def forward(self, actors_input):
        actors_mask = actors_input[:, :, :, -1]
        actors_mask = self.quant_mask(actors_mask)  # 这种写法会导致模型输入位置有两个量化节点,且 scale 不同而删不掉, 未来用 vpu 可以这么写

        actors_data = actors_input[:,:,:,:-1]
        actors_data = self.quant(actors_data)       # 这种写法会导致模型输入位置有两个量化节点,且 scale 不同而删不掉, 未来用 vpu 可以这么写
        print("actors_data:", actors_data)
        print("actors_mask", actors_mask)
        actors_output = actors_data * actors_mask[:, :, :, None]  # + - * /
        return self.dequant(actors_output)

model = small_model()

## ================================================================#
# 生成随机数据
# torch.manual_seed(41)
# actors_data = torch.randn(1, 2, 4, 3)
# actors_mask = torch.randint(0, 2, (1, 2, 4, 1), dtype=torch.bool)
# example_input = torch.cat([actors_data, actors_mask], dim=-1)
example_input = torch.tensor([[[[ 0.2465, -0.4717, 70000,  1.0000],
          [-0.2124,  0.5660, -1.6637,  0.0000],
          [ 0.3338,  1.6051, -1.5088,  1.0000],
          [-0.9215, -0.5901,  1.4871,  0.0000]],
          
         [[ 0.1650, -0.3785,  1.6710,  0.0000],
          [-0.3752,  0.2337,  0.4186,  0.0000],
          [-0.2221, -0.1745, -0.6064,  1.0000],
          [ 0.9174, -0.6317,  0.6133,  1.0000]]]])
print("example_input:", example_input)
output = model(example_input)
print("float output:", output)

如果是模型首部,且确实是 bool 输入

class small_model(nn.Module):
    def __init__(self):
        super(small_model, self).__init__()
        self.quant = QuantStub()
        self.quant_mask = QuantStub()
        self.dequant = DeQuantStub()
        
    def forward(self, actors_input):
        actors_mask = actors_input["actors_mask"]
        actors_data = self.quant(actors_input["actors_data"])
        print("actors_data:", actors_data)
        print("actors_mask", actors_mask)
        actors_output = actors_data * self.quant_mask(actors_mask.to(torch.float)) # + - * /
        return self.dequant(actors_output)
        
# 生成随机数据
torch.manual_seed(41)
actors_data = torch.randn(1, 2, 4, 3)
actors_mask = torch.randint(0, 2, (1, 2, 4, 1), dtype=torch.bool)
example_input = {"actors_data":actors_data, "actors_mask":actors_mask}
print("example_input:", example_input)
output = model(example_input)
print("float output:", output)


*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。



相关推荐

技术专区

关闭
先河是什么意思 什么是种植牙 梦见过河是什么意思 脓血症是什么病严重吗 专长是什么意思
悲催是什么意思 小龙虾和什么不能一起吃 6.7是什么星座 隆鼻后吃什么消肿快 甘露茶叶属于什么茶
1月21日什么星座 33年属什么生肖 hpv是什么病严重吗 手足无措是什么意思 舍本逐末是什么意思
任字五行属什么 客厅用什么灯具好 农历九月五行属什么 黑洞是什么意思 感情里什么叫偏爱
八十岁是什么之年hcv8jop6ns6r.cn 高密度脂蛋白低是什么原因onlinewuye.com 资治通鉴讲的是什么hcv8jop9ns9r.cn 肝虚吃什么中成药hcv8jop0ns1r.cn 言外之意什么意思hcv9jop2ns3r.cn
西洋菜俗称叫什么hcv8jop3ns9r.cn 土字旁的字有什么hcv7jop5ns0r.cn 勤对什么gangsutong.com 眼红是什么意思hcv8jop2ns4r.cn 青龙是什么hcv8jop8ns2r.cn
口臭舌苔白厚吃什么药aiwuzhiyu.com 三高人群适合吃什么水果hcv8jop8ns4r.cn 小孩脾胃虚弱吃什么药wuhaiwuya.com 肝脏不好吃什么药xjhesheng.com 减肥吃什么肉类hcv9jop6ns2r.cn
氢氧化钙是什么东西mmeoe.com 摩羯座什么时候hcv9jop4ns2r.cn 麒麟是什么hcv9jop4ns8r.cn 阴道清洁度三度什么意思hcv7jop4ns5r.cn 梦见玉碎了是什么意思wuhaiwuya.com
百度