Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support fuse layers for ptq #35015

Merged
merged 37 commits into from
Aug 31, 2021
Merged

support fuse layers for ptq #35015

merged 37 commits into from
Aug 31, 2021

Conversation

XGZhang11
Copy link
Contributor

@XGZhang11 XGZhang11 commented Aug 19, 2021

PR types

New features

PR changes

Others

Describe

支持了用于离线量化的层融合。可以将卷积层或全连接层以及其后的bn层融合为一个卷积层,计算在inference下是等价的。在离线量化时,可以指定需要融合的层进行融合。层融合可以进一步加速推理,适配某些不支持bn的硬件。

@paddle-bot-old
Copy link

Thanks for your contribution!
Please wait for the result of CI firstly. See Paddle CI Manual for details.

quant_model = ptq.quantize(model, fuse=True, fuse_list=f_l)
quant_h = ptq.quantize(model_h, fuse=True, fuse_list=f_l)
for name, layer in quant_model.named_sublayers():
print(name, layer)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

需要check fuse之后quant_model是否符合预期,比如check layer的类型,而不是只print

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已加assert,用于判断是否还存在bn层

fuse(bool): Whether fuse layers.
Default: False.
fuse_list(list): The layers to fuse.
Default: None.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. 如果设置fuse=True,但fuse_list是None,会发生什么。
  2. 如果设置,格式是啥

这里的注释不全。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

"""
Add quant config and hook to the target layer.

Args:
model(paddle.nn.Layer): The model to be quantized.
inplace(bool): Whether apply quantization to the input model.
Default: False.
fuse(bool): Whether fuse layers.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whether to fuse

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

f_l = [['features.0', 'features.1'], ['features.4', 'features.5']]
quant_model = self.ptq.quantize(model, fuse=True, fuse_list=f_l)
for name, layer in quant_model.named_sublayers():
print(name, layer)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

同上

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

(after_acc_top1, self.eval_acc_top1))
self.assertTrue(
infer_acc_top1 >= after_acc_top1,
msg='The acc is lower after converting model.')
Copy link
Contributor

@qingqing01 qingqing01 Aug 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

加下注释为什么 after_acc_top1, eval_acc_top1, infer_acc_top1 是这个关系。 和 before_acc_top1是啥关系

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done。after和before主要是convert前后的关系,eval_acc_top1是0.95,用于检查精度是否正确,infer是存储后又load出来



def fuse_layers(model, layers_to_fuse, inplace=False):
'''fuse layers in layers_to_fuse'''
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

请添加参数说明

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


def _fuse_layers(model, layers_list):
'''fuse all the layers in layers_list'''
lay_list = []
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

改成layer_list?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

setattr(parent_layer, sub_name, new_layers[i])


def fuse_func(lay_list):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

方法命名规则请保持一致,如果是模块内函数,请加上下划线。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

def fuse_func(lay_list):
'''choose the fuser method and fuse layers'''
types = tuple(type(m) for m in lay_list)
fuser_method = layer_list_to_fuse_method.get(types, None)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

严格来讲,不是layer list to fuse method, 是types_to_fusion_method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已改

Comment on lines 67 to 70
for i in range(1, len(lay_list)):
identity = Identity()
identity.training = lay_list[0].training
new_layers[i] = identity
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

为什么要加identity呢?不能直接把bn layer删掉么?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这样方便把bn的post hook改到identity上

types = tuple(type(m) for m in lay_list)
fuser_method = layer_list_to_fuse_method.get(types, None)
new_layers = [None] * len(lay_list)
fused = fuser_method(*lay_list)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fused改成fused_layer?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

def fuse_func(lay_list):
'''choose the fuser method and fuse layers'''
types = tuple(type(m) for m in lay_list)
fuser_method = layer_list_to_fuse_method.get(types, None)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

请斟酌下"fuser_method"的命名是否合适。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已改成fusion_method

fused_conv.weight.set_value(fused_weight)
if fused_conv.bias is None:
fused_conv.bias = paddle.create_parameter(
shape=[fused_conv._out_channels], is_bias=True, dtype='float32')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dtype设置为bn.bias.dtype?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

fused_linear.weight.set_value(fused_weight)
if fused_linear.bias is None:
fused_linear.bias = paddle.create_parameter(
shape=[fused_linear.weight.shape[1]], is_bias=True, dtype='float32')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dtype同上

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


_logger = get_logger(
__name__, logging.INFO, fmt='%(asctime)s-%(levelname)s: %(message)s')


class TestFuseLinearBn(unittest.TestCase):
"""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

补充注释

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Contributor

@XiaoguangHu01 XiaoguangHu01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@wanghaoshuang wanghaoshuang merged commit ef53625 into PaddlePaddle:develop Aug 31, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants