utils.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. # Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import numpy as np
  15. import paddle
  16. from paddle.nn.quant import quant_layers
  17. layer_name_map = {
  18. 'Conv2DTranspose': paddle.nn.Conv2DTranspose,
  19. 'Conv2D': paddle.nn.Conv2D,
  20. 'Linear': paddle.nn.Linear,
  21. 'AdaptiveAvgPool2D': paddle.nn.AdaptiveAvgPool2D,
  22. 'AdaptiveMaxPool2D': paddle.nn.AdaptiveMaxPool2D,
  23. 'AvgPool2D': paddle.nn.AvgPool2D,
  24. 'MaxPool2D': paddle.nn.MaxPool2D,
  25. 'Hardswish': paddle.nn.Hardswish,
  26. 'LeakyReLU': paddle.nn.LeakyReLU,
  27. 'PReLU': paddle.nn.PReLU,
  28. 'ReLU': paddle.nn.ReLU,
  29. 'ReLU6': paddle.nn.ReLU6,
  30. 'Sigmoid': paddle.nn.Sigmoid,
  31. 'Softmax': paddle.nn.Softmax,
  32. 'Swish': paddle.nn.Swish,
  33. 'Tanh': paddle.nn.Tanh,
  34. 'BatchNorm': paddle.nn.BatchNorm,
  35. 'GroupNorm': paddle.nn.GroupNorm,
  36. 'LayerNorm': paddle.nn.LayerNorm,
  37. }
  38. # Apply fake quant for the inputs of these layers
  39. fake_quant_input_layers = [
  40. paddle.nn.Conv2D,
  41. paddle.nn.Linear,
  42. paddle.nn.Conv2DTranspose,
  43. ]
  44. # Apply fake quant for the output of these layers
  45. # TODO(jc): fix the problem of adding duplicate fake_quant ops
  46. # paddle.nn.AdaptiveAvgPool2D, paddle.nn.AvgPool2D, paddle.nn.ReLU,paddle.nn.LeakyReLU
  47. fake_quant_output_layers = [
  48. paddle.nn.quant.add,
  49. paddle.nn.quant.subtract,
  50. paddle.nn.quant.multiply,
  51. paddle.nn.quant.divide,
  52. paddle.nn.quant.matmul,
  53. ]
  54. fake_quant_leaf_layers = [
  55. quant_layers.FakeQuantAbsMax,
  56. quant_layers.FakeQuantChannelWiseAbsMax,
  57. quant_layers.FakeQuantMovingAverageAbsMax,
  58. quant_layers.MovingAverageAbsMaxScale,
  59. ]
  60. fake_quant_wrap_layers = [
  61. quant_layers.QuantizedConv2D,
  62. quant_layers.QuantizedLinear,
  63. quant_layers.QuantizedConv2DTranspose,
  64. quant_layers.QuantizedColumnParallelLinear,
  65. quant_layers.QuantizedRowParallelLinear,
  66. ]
  67. # The weight format of these layers is Cin * Cout * H * W
  68. spec_channel_axis_layers = [paddle.nn.Conv2DTranspose, paddle.nn.Linear]
  69. weight_op_types = [
  70. "conv2d",
  71. "depthwise_conv2d",
  72. "matmul",
  73. "conv2d_transpose",
  74. "depthwise_conv2d_transpose",
  75. ]
  76. fake_quantize_dequantize_op_types = [
  77. "fake_quantize_dequantize_abs_max",
  78. "fake_channel_wise_quantize_dequantize_abs_max",
  79. "fake_quantize_dequantize_moving_average_abs_max",
  80. ]
  81. def load_variable_data(scope, var_name):
  82. """
  83. Load variable value from scope
  84. """
  85. var_node = scope.find_var(var_name)
  86. assert var_node is not None, "Can not find " + var_name + " in the scope."
  87. return np.array(var_node.get_tensor())
  88. def find_previous_op(block, var_name):
  89. """
  90. Find the previous op for the input variable.
  91. """
  92. for op in block.ops:
  93. if var_name in op.output_arg_names:
  94. return op
  95. return None
  96. def find_next_ops(block, var_name):
  97. """
  98. Find all followed ops for the input variable.
  99. """
  100. res_ops = []
  101. for op in block.ops:
  102. if var_name in op.input_arg_names:
  103. res_ops.append(op)
  104. return res_ops
  105. def find_parent_layer_and_sub_name(model, name):
  106. """
  107. Given the model and the name of a layer, find the parent layer and
  108. the sub_name of the layer.
  109. For example, if name is 'block_1/convbn_1/conv_1', the parent layer is
  110. 'block_1/convbn_1' and the sub_name is `conv_1`.
  111. Args:
  112. model(paddle.nn.Layer): the model to be quantized.
  113. name(string): the name of a layer
  114. Returns:
  115. parent_layer, subname
  116. """
  117. assert isinstance(
  118. model, paddle.nn.Layer
  119. ), "The model must be the instance of paddle.nn.Layer."
  120. assert len(name) > 0, "The input (name) should not be empty."
  121. last_idx = 0
  122. idx = 0
  123. parent_layer = model
  124. while idx < len(name):
  125. if name[idx] == '.':
  126. sub_name = name[last_idx:idx]
  127. if hasattr(parent_layer, sub_name):
  128. parent_layer = getattr(parent_layer, sub_name)
  129. last_idx = idx + 1
  130. idx += 1
  131. sub_name = name[last_idx:idx]
  132. return parent_layer, sub_name
  133. def program_all_ops(program):
  134. """
  135. Return all ops for the input program.
  136. """
  137. all_ops = []
  138. for block in program.blocks:
  139. for op in block.ops:
  140. all_ops.append(op)
  141. return all_ops
  142. def is_leaf_layer(layer):
  143. """
  144. Whether the layer is leaf layer.
  145. """
  146. return isinstance(layer, paddle.nn.Layer) and len(layer.sublayers()) == 0
  147. def fp_numpy_to_naive(x_np):
  148. """
  149. Convert numpy to float or list.
  150. """
  151. if x_np.size == 1:
  152. return float(x_np)
  153. else:
  154. return x_np.tolist()