ZhengyangZhang commited on
Commit
a126df3
·
verified ·
1 Parent(s): 5815ea1

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. lib/python3.12/site-packages/torch/ao/__init__.py +19 -0
  2. lib/python3.12/site-packages/torch/ao/nn/__init__.py +22 -0
  3. lib/python3.12/site-packages/torch/ao/nn/__pycache__/__init__.cpython-312.pyc +0 -0
  4. lib/python3.12/site-packages/torch/ao/nn/intrinsic/__init__.py +40 -0
  5. lib/python3.12/site-packages/torch/ao/nn/intrinsic/__pycache__/__init__.cpython-312.pyc +0 -0
  6. lib/python3.12/site-packages/torch/ao/nn/intrinsic/modules/__init__.py +41 -0
  7. lib/python3.12/site-packages/torch/ao/nn/intrinsic/modules/__pycache__/__init__.cpython-312.pyc +0 -0
  8. lib/python3.12/site-packages/torch/ao/nn/intrinsic/modules/__pycache__/fused.cpython-312.pyc +0 -0
  9. lib/python3.12/site-packages/torch/ao/nn/intrinsic/modules/fused.py +245 -0
  10. lib/python3.12/site-packages/torch/ao/nn/intrinsic/qat/__init__.py +1 -0
  11. lib/python3.12/site-packages/torch/ao/nn/intrinsic/qat/__pycache__/__init__.cpython-312.pyc +0 -0
  12. lib/python3.12/site-packages/torch/ao/nn/intrinsic/qat/modules/__init__.py +32 -0
  13. lib/python3.12/site-packages/torch/ao/nn/intrinsic/qat/modules/__pycache__/__init__.cpython-312.pyc +0 -0
  14. lib/python3.12/site-packages/torch/ao/nn/intrinsic/qat/modules/__pycache__/conv_fused.cpython-312.pyc +0 -0
  15. lib/python3.12/site-packages/torch/ao/nn/intrinsic/qat/modules/__pycache__/linear_fused.cpython-312.pyc +0 -0
  16. lib/python3.12/site-packages/torch/ao/nn/intrinsic/qat/modules/__pycache__/linear_relu.cpython-312.pyc +0 -0
  17. lib/python3.12/site-packages/torch/ao/nn/intrinsic/qat/modules/conv_fused.py +1055 -0
  18. lib/python3.12/site-packages/torch/ao/nn/intrinsic/qat/modules/linear_fused.py +193 -0
  19. lib/python3.12/site-packages/torch/ao/nn/intrinsic/qat/modules/linear_relu.py +51 -0
  20. lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/__init__.py +15 -0
  21. lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/__pycache__/__init__.cpython-312.pyc +0 -0
  22. lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/dynamic/__init__.py +1 -0
  23. lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/dynamic/__pycache__/__init__.cpython-312.pyc +0 -0
  24. lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/dynamic/modules/__init__.py +6 -0
  25. lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/dynamic/modules/__pycache__/__init__.cpython-312.pyc +0 -0
  26. lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/dynamic/modules/__pycache__/linear_relu.cpython-312.pyc +0 -0
  27. lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/dynamic/modules/linear_relu.py +60 -0
  28. lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/modules/__init__.py +18 -0
  29. lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/modules/__pycache__/__init__.cpython-312.pyc +0 -0
  30. lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/modules/__pycache__/bn_relu.cpython-312.pyc +0 -0
  31. lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/modules/__pycache__/conv_add.cpython-312.pyc +0 -0
  32. lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/modules/__pycache__/conv_relu.cpython-312.pyc +0 -0
  33. lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/modules/__pycache__/linear_relu.cpython-312.pyc +0 -0
  34. lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/modules/bn_relu.py +105 -0
  35. lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/modules/conv_add.py +145 -0
  36. lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/modules/conv_relu.py +263 -0
  37. lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/modules/linear_relu.py +187 -0
  38. lib/python3.12/site-packages/torch/ao/nn/qat/__init__.py +1 -0
  39. lib/python3.12/site-packages/torch/ao/nn/quantizable/__init__.py +1 -0
  40. lib/python3.12/site-packages/torch/ao/nn/quantizable/__pycache__/__init__.cpython-312.pyc +0 -0
  41. lib/python3.12/site-packages/torch/ao/nn/quantizable/modules/__init__.py +9 -0
  42. lib/python3.12/site-packages/torch/ao/nn/quantizable/modules/__pycache__/__init__.cpython-312.pyc +0 -0
  43. lib/python3.12/site-packages/torch/ao/nn/quantizable/modules/__pycache__/activation.cpython-312.pyc +0 -0
  44. lib/python3.12/site-packages/torch/ao/nn/quantizable/modules/__pycache__/rnn.cpython-312.pyc +0 -0
  45. lib/python3.12/site-packages/torch/ao/nn/quantizable/modules/activation.py +550 -0
  46. lib/python3.12/site-packages/torch/ao/nn/quantizable/modules/rnn.py +596 -0
  47. lib/python3.12/site-packages/torch/ao/nn/quantized/__init__.py +39 -0
  48. lib/python3.12/site-packages/torch/ao/nn/quantized/__pycache__/__init__.cpython-312.pyc +0 -0
  49. lib/python3.12/site-packages/torch/ao/nn/quantized/__pycache__/functional.cpython-312.pyc +0 -0
  50. lib/python3.12/site-packages/torch/ao/nn/quantized/dynamic/__init__.py +1 -0
lib/python3.12/site-packages/torch/ao/__init__.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # mypy: allow-untyped-defs
2
+ # torch.ao is a package with a lot of interdependencies.
3
+ # We will use lazy import to avoid cyclic dependencies here.
4
+
5
+
6
+ __all__ = [
7
+ "nn",
8
+ "ns",
9
+ "quantization",
10
+ "pruning",
11
+ ]
12
+
13
+
14
+ def __getattr__(name):
15
+ if name in __all__:
16
+ import importlib
17
+
18
+ return importlib.import_module("." + name, __name__)
19
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
lib/python3.12/site-packages/torch/ao/nn/__init__.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # mypy: allow-untyped-defs
2
+ # We are exposing all subpackages to the end-user.
3
+ # Because of possible inter-dependency, we want to avoid
4
+ # the cyclic imports, thus implementing lazy version
5
+ # as per https://peps.python.org/pep-0562/
6
+
7
+ import importlib
8
+
9
+
10
+ __all__ = [
11
+ "intrinsic",
12
+ "qat",
13
+ "quantizable",
14
+ "quantized",
15
+ "sparse",
16
+ ]
17
+
18
+
19
+ def __getattr__(name):
20
+ if name in __all__:
21
+ return importlib.import_module("." + name, __name__)
22
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
lib/python3.12/site-packages/torch/ao/nn/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (647 Bytes). View file
 
lib/python3.12/site-packages/torch/ao/nn/intrinsic/__init__.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # mypy: allow-untyped-defs
2
+ from .modules import * # noqa: F403
3
+ from .modules.fused import _FusedModule # noqa: F403
4
+
5
+
6
+ # # Subpackages
7
+ # from . import qat # noqa: F403
8
+ # from . import quantized # noqa: F403
9
+
10
+ __all__ = [
11
+ "ConvBn1d",
12
+ "ConvBn2d",
13
+ "ConvBn3d",
14
+ "ConvBnReLU1d",
15
+ "ConvBnReLU2d",
16
+ "ConvBnReLU3d",
17
+ "ConvReLU1d",
18
+ "ConvReLU2d",
19
+ "ConvReLU3d",
20
+ "LinearReLU",
21
+ "BNReLU2d",
22
+ "BNReLU3d",
23
+ "LinearBn1d",
24
+ "LinearLeakyReLU",
25
+ "LinearTanh",
26
+ "ConvAdd2d",
27
+ "ConvAddReLU2d",
28
+ ]
29
+
30
+
31
+ # We are exposing all subpackages to the end-user.
32
+ # Because of possible inter-dependency, we want to avoid
33
+ # the cyclic imports, thus implementing lazy version
34
+ # as per https://peps.python.org/pep-0562/
35
+ def __getattr__(name):
36
+ if name in __all__:
37
+ import importlib
38
+
39
+ return importlib.import_module("." + name, __name__)
40
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
lib/python3.12/site-packages/torch/ao/nn/intrinsic/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (890 Bytes). View file
 
lib/python3.12/site-packages/torch/ao/nn/intrinsic/modules/__init__.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .fused import ( # noqa: F401
2
+ _FusedModule,
3
+ BNReLU2d,
4
+ BNReLU3d,
5
+ ConvAdd2d,
6
+ ConvAddReLU2d,
7
+ ConvBn1d,
8
+ ConvBn2d,
9
+ ConvBn3d,
10
+ ConvBnReLU1d,
11
+ ConvBnReLU2d,
12
+ ConvBnReLU3d,
13
+ ConvReLU1d,
14
+ ConvReLU2d,
15
+ ConvReLU3d,
16
+ LinearBn1d,
17
+ LinearLeakyReLU,
18
+ LinearReLU,
19
+ LinearTanh,
20
+ )
21
+
22
+
23
+ __all__ = [
24
+ "ConvBn1d",
25
+ "ConvBn2d",
26
+ "ConvBn3d",
27
+ "ConvBnReLU1d",
28
+ "ConvBnReLU2d",
29
+ "ConvBnReLU3d",
30
+ "ConvReLU1d",
31
+ "ConvReLU2d",
32
+ "ConvReLU3d",
33
+ "LinearReLU",
34
+ "BNReLU2d",
35
+ "BNReLU3d",
36
+ "LinearBn1d",
37
+ "LinearLeakyReLU",
38
+ "LinearTanh",
39
+ "ConvAdd2d",
40
+ "ConvAddReLU2d",
41
+ ]
lib/python3.12/site-packages/torch/ao/nn/intrinsic/modules/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (746 Bytes). View file
 
lib/python3.12/site-packages/torch/ao/nn/intrinsic/modules/__pycache__/fused.cpython-312.pyc ADDED
Binary file (13.1 kB). View file
 
lib/python3.12/site-packages/torch/ao/nn/intrinsic/modules/fused.py ADDED
@@ -0,0 +1,245 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # mypy: allow-untyped-defs
2
+ import torch
3
+ from torch.nn import (
4
+ BatchNorm1d,
5
+ BatchNorm2d,
6
+ BatchNorm3d,
7
+ Conv1d,
8
+ Conv2d,
9
+ Conv3d,
10
+ Linear,
11
+ ReLU,
12
+ )
13
+ from torch.nn.utils.parametrize import type_before_parametrizations
14
+
15
+
16
+ __all__ = [
17
+ "ConvReLU1d",
18
+ "ConvReLU2d",
19
+ "ConvReLU3d",
20
+ "LinearReLU",
21
+ "ConvBn1d",
22
+ "ConvBn2d",
23
+ "ConvBnReLU1d",
24
+ "ConvBnReLU2d",
25
+ "ConvBn3d",
26
+ "ConvBnReLU3d",
27
+ "BNReLU2d",
28
+ "BNReLU3d",
29
+ "LinearBn1d",
30
+ "LinearLeakyReLU",
31
+ "LinearTanh",
32
+ "ConvAdd2d",
33
+ "ConvAddReLU2d",
34
+ ]
35
+
36
+
37
+ # Used for identifying intrinsic modules used in quantization
38
+ class _FusedModule(torch.nn.Sequential):
39
+ pass
40
+
41
+
42
+ class ConvReLU1d(_FusedModule):
43
+ r"""This is a sequential container which calls the Conv1d and ReLU modules.
44
+ During quantization this will be replaced with the corresponding fused module."""
45
+
46
+ def __init__(self, conv, relu):
47
+ assert (
48
+ type_before_parametrizations(conv) == Conv1d
49
+ and type_before_parametrizations(relu) == ReLU
50
+ ), f"Incorrect types for input modules{type_before_parametrizations(conv)}{type_before_parametrizations(relu)}"
51
+ super().__init__(conv, relu)
52
+
53
+
54
+ class ConvReLU2d(_FusedModule):
55
+ r"""This is a sequential container which calls the Conv2d and ReLU modules.
56
+ During quantization this will be replaced with the corresponding fused module."""
57
+
58
+ def __init__(self, conv, relu):
59
+ assert (
60
+ type_before_parametrizations(conv) == Conv2d
61
+ and type_before_parametrizations(relu) == ReLU
62
+ ), f"Incorrect types for input modules{type_before_parametrizations(conv)}{type_before_parametrizations(relu)}"
63
+ super().__init__(conv, relu)
64
+
65
+
66
+ class ConvReLU3d(_FusedModule):
67
+ r"""This is a sequential container which calls the Conv3d and ReLU modules.
68
+ During quantization this will be replaced with the corresponding fused module."""
69
+
70
+ def __init__(self, conv, relu):
71
+ assert (
72
+ type_before_parametrizations(conv) == Conv3d
73
+ and type_before_parametrizations(relu) == ReLU
74
+ ), f"Incorrect types for input modules{type_before_parametrizations(conv)}{type_before_parametrizations(relu)}"
75
+ super().__init__(conv, relu)
76
+
77
+
78
+ class LinearReLU(_FusedModule):
79
+ r"""This is a sequential container which calls the Linear and ReLU modules.
80
+ During quantization this will be replaced with the corresponding fused module."""
81
+
82
+ def __init__(self, linear, relu):
83
+ assert (
84
+ type_before_parametrizations(linear) == Linear
85
+ and type_before_parametrizations(relu) == ReLU
86
+ ), f"Incorrect types for input modules{type_before_parametrizations(linear)}{type_before_parametrizations(relu)}"
87
+ super().__init__(linear, relu)
88
+
89
+
90
+ class ConvBn1d(_FusedModule):
91
+ r"""This is a sequential container which calls the Conv 1d and Batch Norm 1d modules.
92
+ During quantization this will be replaced with the corresponding fused module."""
93
+
94
+ def __init__(self, conv, bn):
95
+ assert (
96
+ type_before_parametrizations(conv) == Conv1d
97
+ and type_before_parametrizations(bn) == BatchNorm1d
98
+ ), f"Incorrect types for input modules{type_before_parametrizations(conv)}{type_before_parametrizations(bn)}"
99
+ super().__init__(conv, bn)
100
+
101
+
102
+ class ConvBn2d(_FusedModule):
103
+ r"""This is a sequential container which calls the Conv 2d and Batch Norm 2d modules.
104
+ During quantization this will be replaced with the corresponding fused module."""
105
+
106
+ def __init__(self, conv, bn):
107
+ assert (
108
+ type_before_parametrizations(conv) == Conv2d
109
+ and type_before_parametrizations(bn) == BatchNorm2d
110
+ ), f"Incorrect types for input modules{type_before_parametrizations(conv)}{type_before_parametrizations(bn)}"
111
+ super().__init__(conv, bn)
112
+
113
+
114
+ class ConvBnReLU1d(_FusedModule):
115
+ r"""This is a sequential container which calls the Conv 1d, Batch Norm 1d, and ReLU modules.
116
+ During quantization this will be replaced with the corresponding fused module."""
117
+
118
+ def __init__(self, conv, bn, relu):
119
+ assert (
120
+ type_before_parametrizations(conv) == Conv1d
121
+ and type_before_parametrizations(bn) == BatchNorm1d
122
+ and type_before_parametrizations(relu) == ReLU
123
+ ), f"Incorrect types for input modules{type_before_parametrizations(conv)}{type_before_parametrizations(bn)}{type_before_parametrizations(relu)}" # noqa: B950
124
+ super().__init__(conv, bn, relu)
125
+
126
+
127
+ class ConvBnReLU2d(_FusedModule):
128
+ r"""This is a sequential container which calls the Conv 2d, Batch Norm 2d, and ReLU modules.
129
+ During quantization this will be replaced with the corresponding fused module."""
130
+
131
+ def __init__(self, conv, bn, relu):
132
+ assert (
133
+ type_before_parametrizations(conv) == Conv2d
134
+ and type_before_parametrizations(bn) == BatchNorm2d
135
+ and type_before_parametrizations(relu) == ReLU
136
+ ), f"Incorrect types for input modules{type_before_parametrizations(conv)}{type_before_parametrizations(bn)}{type_before_parametrizations(relu)}" # noqa: B950
137
+ super().__init__(conv, bn, relu)
138
+
139
+
140
+ class ConvBn3d(_FusedModule):
141
+ r"""This is a sequential container which calls the Conv 3d and Batch Norm 3d modules.
142
+ During quantization this will be replaced with the corresponding fused module."""
143
+
144
+ def __init__(self, conv, bn):
145
+ assert (
146
+ type_before_parametrizations(conv) == Conv3d
147
+ and type_before_parametrizations(bn) == BatchNorm3d
148
+ ), f"Incorrect types for input modules{type_before_parametrizations(conv)}{type_before_parametrizations(bn)}"
149
+ super().__init__(conv, bn)
150
+
151
+
152
+ class ConvBnReLU3d(_FusedModule):
153
+ r"""This is a sequential container which calls the Conv 3d, Batch Norm 3d, and ReLU modules.
154
+ During quantization this will be replaced with the corresponding fused module."""
155
+
156
+ def __init__(self, conv, bn, relu):
157
+ assert (
158
+ type_before_parametrizations(conv) == Conv3d
159
+ and type_before_parametrizations(bn) == BatchNorm3d
160
+ and type_before_parametrizations(relu) == ReLU
161
+ ), f"Incorrect types for input modules{type_before_parametrizations(conv)}{type_before_parametrizations(bn)}{type_before_parametrizations(relu)}" # noqa: B950
162
+ super().__init__(conv, bn, relu)
163
+
164
+
165
+ class BNReLU2d(_FusedModule):
166
+ r"""This is a sequential container which calls the BatchNorm 2d and ReLU modules.
167
+ During quantization this will be replaced with the corresponding fused module."""
168
+
169
+ def __init__(self, batch_norm, relu):
170
+ assert (
171
+ type_before_parametrizations(batch_norm) == BatchNorm2d
172
+ and type_before_parametrizations(relu) == ReLU
173
+ ), f"Incorrect types for input modules{type_before_parametrizations(batch_norm)}{type_before_parametrizations(relu)}"
174
+ super().__init__(batch_norm, relu)
175
+
176
+
177
+ class BNReLU3d(_FusedModule):
178
+ r"""This is a sequential container which calls the BatchNorm 3d and ReLU modules.
179
+ During quantization this will be replaced with the corresponding fused module."""
180
+
181
+ def __init__(self, batch_norm, relu):
182
+ assert (
183
+ type_before_parametrizations(batch_norm) == BatchNorm3d
184
+ and type_before_parametrizations(relu) == ReLU
185
+ ), f"Incorrect types for input modules{type_before_parametrizations(batch_norm)}{type_before_parametrizations(relu)}"
186
+ super().__init__(batch_norm, relu)
187
+
188
+
189
+ class LinearBn1d(_FusedModule):
190
+ r"""This is a sequential container which calls the Linear and BatchNorm1d modules.
191
+ During quantization this will be replaced with the corresponding fused module."""
192
+
193
+ def __init__(self, linear, bn):
194
+ assert (
195
+ type_before_parametrizations(linear) == Linear
196
+ and type_before_parametrizations(bn) == BatchNorm1d
197
+ ), f"Incorrect types for input modules{type_before_parametrizations(linear)}{type_before_parametrizations(bn)}"
198
+ super().__init__(linear, bn)
199
+
200
+
201
+ class LinearLeakyReLU(_FusedModule):
202
+ r"""This is a sequential container which calls the Linear and LeakyReLU modules.
203
+ During quantization this will be replaced with the corresponding fused module."""
204
+
205
+ def __init__(self, linear, leaky_relu):
206
+ assert (
207
+ type(linear) == Linear and type(leaky_relu) == torch.nn.LeakyReLU
208
+ ), f"Incorrect types for input modules{type(linear)}{type(leaky_relu)}"
209
+ super().__init__(linear, leaky_relu)
210
+
211
+
212
+ class LinearTanh(_FusedModule):
213
+ r"""This is a sequential container which calls the Linear and Tanh modules.
214
+ During quantization this will be replaced with the corresponding fused module."""
215
+
216
+ def __init__(self, linear, tanh):
217
+ assert (
218
+ type(linear) == Linear and type(tanh) == torch.nn.Tanh
219
+ ), f"Incorrect types for input modules{type(linear)}{type(tanh)}"
220
+ super().__init__(linear, tanh)
221
+
222
+
223
+ class ConvAdd2d(_FusedModule):
224
+ r"""This is a sequential container which calls the Conv2d modules with extra Add.
225
+ During quantization this will be replaced with the corresponding fused module."""
226
+
227
+ def __init__(self, conv, add):
228
+ super().__init__(conv)
229
+ self.add = add
230
+
231
+ def forward(self, x1, x2): # type: ignore[override]
232
+ return self.add(self[0](x1), x2)
233
+
234
+
235
+ class ConvAddReLU2d(_FusedModule):
236
+ r"""This is a sequential container which calls the Conv2d, add, Relu.
237
+ During quantization this will be replaced with the corresponding fused module."""
238
+
239
+ def __init__(self, conv, add, relu):
240
+ super().__init__(conv)
241
+ self.add = add
242
+ self.relu = relu
243
+
244
+ def forward(self, x1, x2): # type: ignore[override]
245
+ return self.relu(self.add(self[0](x1), x2))
lib/python3.12/site-packages/torch/ao/nn/intrinsic/qat/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .modules import * # noqa: F403
lib/python3.12/site-packages/torch/ao/nn/intrinsic/qat/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (233 Bytes). View file
 
lib/python3.12/site-packages/torch/ao/nn/intrinsic/qat/modules/__init__.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .conv_fused import (
2
+ ConvBn1d,
3
+ ConvBn2d,
4
+ ConvBn3d,
5
+ ConvBnReLU1d,
6
+ ConvBnReLU2d,
7
+ ConvBnReLU3d,
8
+ ConvReLU1d,
9
+ ConvReLU2d,
10
+ ConvReLU3d,
11
+ freeze_bn_stats,
12
+ update_bn_stats,
13
+ )
14
+ from .linear_fused import LinearBn1d
15
+ from .linear_relu import LinearReLU
16
+
17
+
18
+ __all__ = [
19
+ "LinearReLU",
20
+ "LinearBn1d",
21
+ "ConvReLU1d",
22
+ "ConvReLU2d",
23
+ "ConvReLU3d",
24
+ "ConvBn1d",
25
+ "ConvBn2d",
26
+ "ConvBn3d",
27
+ "ConvBnReLU1d",
28
+ "ConvBnReLU2d",
29
+ "ConvBnReLU3d",
30
+ "update_bn_stats",
31
+ "freeze_bn_stats",
32
+ ]
lib/python3.12/site-packages/torch/ao/nn/intrinsic/qat/modules/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (685 Bytes). View file
 
lib/python3.12/site-packages/torch/ao/nn/intrinsic/qat/modules/__pycache__/conv_fused.cpython-312.pyc ADDED
Binary file (34.2 kB). View file
 
lib/python3.12/site-packages/torch/ao/nn/intrinsic/qat/modules/__pycache__/linear_fused.cpython-312.pyc ADDED
Binary file (8.65 kB). View file
 
lib/python3.12/site-packages/torch/ao/nn/intrinsic/qat/modules/__pycache__/linear_relu.cpython-312.pyc ADDED
Binary file (3.24 kB). View file
 
lib/python3.12/site-packages/torch/ao/nn/intrinsic/qat/modules/conv_fused.py ADDED
@@ -0,0 +1,1055 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # mypy: allow-untyped-defs
2
+ import math
3
+ from typing import ClassVar, Optional, Type
4
+
5
+ import torch
6
+ import torch.ao.nn.intrinsic as nni
7
+ import torch.ao.nn.qat as nnqat
8
+ import torch.nn as nn
9
+ import torch.nn.functional as F
10
+ from torch.nn import init
11
+ from torch.nn.modules.utils import _pair, _single, _triple
12
+ from torch.nn.parameter import Parameter
13
+ from torch.nn.utils import fuse_conv_bn_weights
14
+
15
+
16
+ __all__ = [
17
+ "ConvBn1d",
18
+ "ConvBnReLU1d",
19
+ "ConvReLU1d",
20
+ "ConvBn2d",
21
+ "ConvBnReLU2d",
22
+ "ConvReLU2d",
23
+ "ConvBn3d",
24
+ "ConvBnReLU3d",
25
+ "ConvReLU3d",
26
+ "update_bn_stats",
27
+ "freeze_bn_stats",
28
+ ]
29
+ _BN_CLASS_MAP = {
30
+ 1: nn.BatchNorm1d,
31
+ 2: nn.BatchNorm2d,
32
+ 3: nn.BatchNorm3d,
33
+ }
34
+
35
+
36
+ class _ConvBnNd(nn.modules.conv._ConvNd, nni._FusedModule):
37
+ _version = 2
38
+ _FLOAT_MODULE: ClassVar[Type[nn.modules.conv._ConvNd]]
39
+
40
+ def __init__(
41
+ self,
42
+ # ConvNd args
43
+ in_channels,
44
+ out_channels,
45
+ kernel_size,
46
+ stride,
47
+ padding,
48
+ dilation,
49
+ transposed,
50
+ output_padding,
51
+ groups,
52
+ bias,
53
+ padding_mode,
54
+ # BatchNormNd args
55
+ # num_features: out_channels
56
+ eps=1e-05,
57
+ momentum=0.1,
58
+ # affine: True
59
+ # track_running_stats: True
60
+ # Args for this module
61
+ freeze_bn=False,
62
+ qconfig=None,
63
+ dim=2,
64
+ ):
65
+ nn.modules.conv._ConvNd.__init__(
66
+ self,
67
+ in_channels,
68
+ out_channels,
69
+ kernel_size,
70
+ stride,
71
+ padding,
72
+ dilation,
73
+ transposed,
74
+ output_padding,
75
+ groups,
76
+ False,
77
+ padding_mode,
78
+ )
79
+ assert qconfig, "qconfig must be provided for QAT module"
80
+ self.qconfig = qconfig
81
+ self.freeze_bn = freeze_bn if self.training else True
82
+ self.bn = _BN_CLASS_MAP[dim](out_channels, eps, momentum, True, True)
83
+ self.weight_fake_quant = self.qconfig.weight()
84
+ if bias:
85
+ self.bias = Parameter(torch.empty(out_channels))
86
+ else:
87
+ self.register_parameter("bias", None)
88
+ self.reset_bn_parameters()
89
+
90
+ # this needs to be called after reset_bn_parameters,
91
+ # as they modify the same state
92
+ if self.training:
93
+ if freeze_bn:
94
+ self.freeze_bn_stats()
95
+ else:
96
+ self.update_bn_stats()
97
+ else:
98
+ self.freeze_bn_stats()
99
+
100
+ self._enable_slow_path_for_better_numerical_stability = False
101
+
102
+ def reset_running_stats(self):
103
+ self.bn.reset_running_stats()
104
+
105
+ def reset_bn_parameters(self):
106
+ self.bn.reset_running_stats()
107
+ init.uniform_(self.bn.weight)
108
+ init.zeros_(self.bn.bias)
109
+ # note: below is actually for conv, not BN
110
+ if self.bias is not None:
111
+ fan_in, _ = init._calculate_fan_in_and_fan_out(self.weight)
112
+ bound = 1 / math.sqrt(fan_in)
113
+ init.uniform_(self.bias, -bound, bound)
114
+
115
+ def reset_parameters(self):
116
+ super().reset_parameters()
117
+
118
+ def update_bn_stats(self):
119
+ self.freeze_bn = False
120
+ self.bn.training = True
121
+ return self
122
+
123
+ def freeze_bn_stats(self):
124
+ self.freeze_bn = True
125
+ self.bn.training = False
126
+ return self
127
+
128
+ def _forward(self, input):
129
+ if self._enable_slow_path_for_better_numerical_stability:
130
+ return self._forward_slow(input)
131
+ return self._forward_approximate(input)
132
+
133
+ def _forward_approximate(self, input):
134
+ """Approximated method to fuse conv and bn. It requires only one forward pass.
135
+ conv_orig = conv / scale_factor where scale_factor = bn.weight / running_std
136
+ """
137
+ assert self.bn.running_var is not None
138
+ running_std = torch.sqrt(self.bn.running_var + self.bn.eps)
139
+ scale_factor = self.bn.weight / running_std
140
+ weight_shape = [1] * len(self.weight.shape)
141
+ weight_shape[0] = -1
142
+ bias_shape = [1] * len(self.weight.shape)
143
+ bias_shape[1] = -1
144
+ scaled_weight = self.weight_fake_quant(
145
+ self.weight * scale_factor.reshape(weight_shape)
146
+ )
147
+ # using zero bias here since the bias for original conv
148
+ # will be added later
149
+ if self.bias is not None:
150
+ zero_bias = torch.zeros_like(self.bias, dtype=input.dtype)
151
+ else:
152
+ zero_bias = torch.zeros(
153
+ self.out_channels, device=scaled_weight.device, dtype=input.dtype
154
+ )
155
+ conv = self._conv_forward(input, scaled_weight, zero_bias)
156
+ conv_orig = conv / scale_factor.reshape(bias_shape)
157
+ if self.bias is not None:
158
+ conv_orig = conv_orig + self.bias.reshape(bias_shape)
159
+ conv = self.bn(conv_orig)
160
+ return conv
161
+
162
+ def _forward_slow(self, input):
163
+ """
164
+ A more accurate but slow method to compute conv bn fusion, following https://arxiv.org/pdf/1806.08342.pdf
165
+ It requires two forward passes but handles the case bn.weight == 0
166
+
167
+ Conv: Y = WX + B_c
168
+ Conv without bias: Y0 = WX = Y - B_c, Y = Y0 + B_c
169
+
170
+ Batch statistics:
171
+ mean_Y = Y.mean()
172
+ = Y0.mean() + B_c
173
+ var_Y = (Y - mean_Y)^2.mean()
174
+ = (Y0 - Y0.mean())^2.mean()
175
+ BN (r: bn.weight, beta: bn.bias):
176
+ Z = r * (Y - mean_Y) / sqrt(var_Y + eps) + beta
177
+ = r * (Y0 - Y0.mean()) / sqrt(var_Y + eps) + beta
178
+
179
+ Fused Conv BN training (std_Y = sqrt(var_Y + eps)):
180
+ Z = (r * W / std_Y) * X + r * (B_c - mean_Y) / std_Y + beta
181
+ = (r * W / std_Y) * X - r * Y0.mean() / std_Y + beta
182
+
183
+ Fused Conv BN inference (running_std = sqrt(running_var + eps)):
184
+ Z = (r * W / running_std) * X - r * (running_mean - B_c) / running_std + beta
185
+
186
+ QAT with fused conv bn:
187
+ Z_train = fake_quant(r * W / running_std) * X * (running_std / std_Y) - r * Y0.mean() / std_Y + beta
188
+ = conv(X, fake_quant(r * W / running_std)) * (running_std / std_Y) - r * Y0.mean() / std_Y + beta
189
+ Z_inference = conv(X, fake_quant(r * W / running_std)) - r * (running_mean - B_c) / running_std + beta
190
+ """
191
+
192
+ assert self.bn.running_var is not None
193
+ assert self.bn.running_mean is not None
194
+
195
+ # using zero bias here since the bias for original conv
196
+ # will be added later
197
+ zero_bias = torch.zeros(
198
+ self.out_channels, device=self.weight.device, dtype=input.dtype
199
+ )
200
+
201
+ weight_shape = [1] * len(self.weight.shape)
202
+ weight_shape[0] = -1
203
+ bias_shape = [1] * len(self.weight.shape)
204
+ bias_shape[1] = -1
205
+
206
+ if self.bn.training:
207
+ # needed to compute batch mean/std
208
+ conv_out = self._conv_forward(input, self.weight, zero_bias)
209
+ # update bn statistics
210
+ with torch.no_grad():
211
+ conv_out_bias = (
212
+ conv_out
213
+ if self.bias is None
214
+ else conv_out + self.bias.reshape(bias_shape)
215
+ )
216
+ self.bn(conv_out_bias)
217
+
218
+ # fused conv + bn without bias using bn running statistics
219
+ running_std = torch.sqrt(self.bn.running_var + self.bn.eps)
220
+ scale_factor = self.bn.weight / running_std
221
+ scaled_weight = self.weight_fake_quant(
222
+ self.weight * scale_factor.reshape(weight_shape)
223
+ )
224
+ # fused conv without bias for inference: (r * W / running_std) * X
225
+ conv_bn = self._conv_forward(input, scaled_weight, zero_bias)
226
+
227
+ avg_dims = [0] + list(range(2, len(self.weight.shape)))
228
+ batch_mean = conv_out.mean(avg_dims)
229
+ batch_var = torch.square(conv_out - batch_mean.reshape(bias_shape)).mean(
230
+ avg_dims
231
+ )
232
+ batch_std = torch.sqrt(batch_var + self.bn.eps)
233
+
234
+ # scale to use batch std in training mode
235
+ # conv(X, r * W / std_Y) = conv(X, r * W / running_std) * (running_std / std_Y)
236
+ unscale_factor = running_std / batch_std
237
+ conv_bn *= unscale_factor.reshape(bias_shape)
238
+
239
+ fused_mean = batch_mean
240
+ fused_std = batch_std
241
+ else:
242
+ # fused conv + bn without bias using bn running statistics
243
+ running_std = torch.sqrt(self.bn.running_var + self.bn.eps)
244
+ scale_factor = self.bn.weight / running_std
245
+ scaled_weight = self.weight_fake_quant(
246
+ self.weight * scale_factor.reshape(weight_shape)
247
+ )
248
+ # fused conv without bias for inference: (r * W / running_std) * X
249
+ conv_bn = self._conv_forward(input, scaled_weight, zero_bias)
250
+
251
+ fused_mean = self.bn.running_mean - (
252
+ self.bias if self.bias is not None else 0
253
+ )
254
+ fused_std = running_std
255
+
256
+ # fused bias = beta - r * mean / std
257
+ fused_bias = self.bn.bias - self.bn.weight * fused_mean / fused_std
258
+ conv_bn += fused_bias.reshape(bias_shape)
259
+
260
+ # HACK to let conv bias participate in loss to avoid DDP error (parameters
261
+ # were not used in producing loss)
262
+ if self.bias is not None:
263
+ conv_bn += (self.bias - self.bias).reshape(bias_shape)
264
+
265
+ return conv_bn
266
+
267
+ def extra_repr(self):
268
+ # TODO(jerryzh): extend
269
+ return super().extra_repr()
270
+
271
+ def forward(self, input):
272
+ return self._forward(input)
273
+
274
+ def train(self, mode=True):
275
+ """
276
+ Batchnorm's training behavior is using the self.training flag. Prevent
277
+ changing it if BN is frozen. This makes sure that calling `model.train()`
278
+ on a model with a frozen BN will behave properly.
279
+ """
280
+ self.training = mode
281
+ if not self.freeze_bn:
282
+ for module in self.children():
283
+ module.train(mode)
284
+ return self
285
+
286
+ # ===== Serialization version history =====
287
+ #
288
+ # Version 1/None
289
+ # self
290
+ # |--- weight : Tensor
291
+ # |--- bias : Tensor
292
+ # |--- gamma : Tensor
293
+ # |--- beta : Tensor
294
+ # |--- running_mean : Tensor
295
+ # |--- running_var : Tensor
296
+ # |--- num_batches_tracked : Tensor
297
+ #
298
+ # Version 2
299
+ # self
300
+ # |--- weight : Tensor
301
+ # |--- bias : Tensor
302
+ # |--- bn : Module
303
+ # |--- weight : Tensor (moved from v1.self.gamma)
304
+ # |--- bias : Tensor (moved from v1.self.beta)
305
+ # |--- running_mean : Tensor (moved from v1.self.running_mean)
306
+ # |--- running_var : Tensor (moved from v1.self.running_var)
307
+ # |--- num_batches_tracked : Tensor (moved from v1.self.num_batches_tracked)
308
+ def _load_from_state_dict(
309
+ self,
310
+ state_dict,
311
+ prefix,
312
+ local_metadata,
313
+ strict,
314
+ missing_keys,
315
+ unexpected_keys,
316
+ error_msgs,
317
+ ):
318
+ version = local_metadata.get("version", None)
319
+ if version is None or version == 1:
320
+ # BN related parameters and buffers were moved into the BN module for v2
321
+ v2_to_v1_names = {
322
+ "bn.weight": "gamma",
323
+ "bn.bias": "beta",
324
+ "bn.running_mean": "running_mean",
325
+ "bn.running_var": "running_var",
326
+ "bn.num_batches_tracked": "num_batches_tracked",
327
+ }
328
+ for v2_name, v1_name in v2_to_v1_names.items():
329
+ if prefix + v1_name in state_dict:
330
+ state_dict[prefix + v2_name] = state_dict[prefix + v1_name]
331
+ state_dict.pop(prefix + v1_name)
332
+ elif prefix + v2_name in state_dict:
333
+ # there was a brief period where forward compatibility
334
+ # for this module was broken (between
335
+ # https://github.com/pytorch/pytorch/pull/38478
336
+ # and https://github.com/pytorch/pytorch/pull/38820)
337
+ # and modules emitted the v2 state_dict format while
338
+ # specifying that version == 1. This patches the forward
339
+ # compatibility issue by allowing the v2 style entries to
340
+ # be used.
341
+ pass
342
+ elif strict:
343
+ missing_keys.append(prefix + v2_name)
344
+
345
+ super()._load_from_state_dict(
346
+ state_dict,
347
+ prefix,
348
+ local_metadata,
349
+ strict,
350
+ missing_keys,
351
+ unexpected_keys,
352
+ error_msgs,
353
+ )
354
+
355
+ @classmethod
356
+ def from_float(cls, mod, use_precomputed_fake_quant=False):
357
+ r"""Create a qat module from a float module or qparams_dict
358
+
359
+ Args: `mod` a float module, either produced by torch.ao.quantization utilities
360
+ or directly from user
361
+ """
362
+ # The ignore is because _FLOAT_MODULE is a TypeVar here where the bound
363
+ # has no __name__ (code is fine though)
364
+ assert type(mod) == cls._FLOAT_MODULE, (
365
+ "qat."
366
+ + cls.__name__
367
+ + ".from_float only works for "
368
+ + cls._FLOAT_MODULE.__name__
369
+ )
370
+ assert hasattr(mod, "qconfig"), "Input float module must have qconfig defined"
371
+ assert mod.qconfig, "Input float module must have a valid qconfig"
372
+ qconfig = mod.qconfig
373
+ conv, bn = mod[0], mod[1] # type: ignore[index]
374
+ qat_convbn = cls(
375
+ conv.in_channels,
376
+ conv.out_channels,
377
+ conv.kernel_size,
378
+ conv.stride,
379
+ conv.padding,
380
+ conv.dilation,
381
+ conv.groups,
382
+ conv.bias is not None,
383
+ conv.padding_mode,
384
+ bn.eps,
385
+ bn.momentum,
386
+ False,
387
+ qconfig,
388
+ )
389
+ qat_convbn.weight = conv.weight
390
+ qat_convbn.bias = conv.bias
391
+ qat_convbn.bn.weight = bn.weight
392
+ qat_convbn.bn.bias = bn.bias
393
+ qat_convbn.bn.running_mean = bn.running_mean
394
+ qat_convbn.bn.running_var = bn.running_var
395
+ # mypy error: Cannot determine type of 'num_batches_tracked'
396
+ qat_convbn.bn.num_batches_tracked = bn.num_batches_tracked
397
+ return qat_convbn
398
+
399
+ def to_float(self):
400
+ cls = type(self)
401
+ conv = cls._FLOAT_CONV_MODULE( # type: ignore[attr-defined]
402
+ self.in_channels,
403
+ self.out_channels,
404
+ self.kernel_size,
405
+ self.stride,
406
+ self.padding,
407
+ self.dilation,
408
+ self.groups,
409
+ self.bias is not None,
410
+ self.padding_mode,
411
+ )
412
+ conv.weight = torch.nn.Parameter(self.weight.detach())
413
+ if self.bias is not None:
414
+ conv.bias = torch.nn.Parameter(self.bias.detach())
415
+
416
+ if cls._FLOAT_BN_MODULE: # type: ignore[attr-defined]
417
+ # fuse bn into conv
418
+ assert self.bn.running_var is not None and self.bn.running_mean is not None
419
+ conv.weight, conv.bias = fuse_conv_bn_weights(
420
+ conv.weight,
421
+ conv.bias,
422
+ self.bn.running_mean,
423
+ self.bn.running_var,
424
+ self.bn.eps,
425
+ self.bn.weight,
426
+ self.bn.bias,
427
+ )
428
+
429
+ if cls._FLOAT_RELU_MODULE: # type: ignore[attr-defined]
430
+ modules = []
431
+ modules.append(conv)
432
+ relu = cls._FLOAT_RELU_MODULE() # type: ignore[attr-defined]
433
+ modules.append(relu)
434
+ conv_relu = cls._FUSED_FLOAT_MODULE(*modules) # type: ignore[attr-defined]
435
+ conv_relu.train(self.training)
436
+ return conv_relu
437
+ else:
438
+ conv.train(self.training)
439
+ return conv
440
+
441
+
442
+ class ConvBn1d(_ConvBnNd, nn.Conv1d):
443
+ r"""
444
+ A ConvBn1d module is a module fused from Conv1d and BatchNorm1d,
445
+ attached with FakeQuantize modules for weight,
446
+ used in quantization aware training.
447
+
448
+ We combined the interface of :class:`torch.nn.Conv1d` and
449
+ :class:`torch.nn.BatchNorm1d`.
450
+
451
+ Similar to :class:`torch.nn.Conv1d`, with FakeQuantize modules initialized
452
+ to default.
453
+
454
+ Attributes:
455
+ freeze_bn:
456
+ weight_fake_quant: fake quant module for weight
457
+
458
+ """
459
+ _FLOAT_BN_MODULE: ClassVar[Type[nn.BatchNorm1d]] = nn.BatchNorm1d
460
+ _FLOAT_RELU_MODULE: ClassVar[Optional[Type[nn.Module]]] = None
461
+ _FLOAT_MODULE: ClassVar[Type[nn.Module]] = nni.ConvBn1d # type: ignore[assignment]
462
+ _FLOAT_CONV_MODULE: ClassVar[Type[nn.Conv1d]] = nn.Conv1d
463
+
464
+ def __init__(
465
+ self,
466
+ # Conv1d args
467
+ in_channels,
468
+ out_channels,
469
+ kernel_size,
470
+ stride=1,
471
+ padding=0,
472
+ dilation=1,
473
+ groups=1,
474
+ bias=None,
475
+ padding_mode="zeros",
476
+ # BatchNorm1d args
477
+ # num_features: out_channels
478
+ eps=1e-05,
479
+ momentum=0.1,
480
+ # affine: True
481
+ # track_running_stats: True
482
+ # Args for this module
483
+ freeze_bn=False,
484
+ qconfig=None,
485
+ ):
486
+ kernel_size = _single(kernel_size)
487
+ stride = _single(stride)
488
+ padding = _single(padding)
489
+ dilation = _single(dilation)
490
+ _ConvBnNd.__init__(
491
+ self,
492
+ in_channels,
493
+ out_channels,
494
+ kernel_size,
495
+ stride,
496
+ padding,
497
+ dilation,
498
+ False,
499
+ _single(0),
500
+ groups,
501
+ bias,
502
+ padding_mode,
503
+ eps,
504
+ momentum,
505
+ freeze_bn,
506
+ qconfig,
507
+ dim=1,
508
+ )
509
+
510
+
511
+ class ConvBnReLU1d(ConvBn1d):
512
+ r"""
513
+ A ConvBnReLU1d module is a module fused from Conv1d, BatchNorm1d and ReLU,
514
+ attached with FakeQuantize modules for weight,
515
+ used in quantization aware training.
516
+
517
+ We combined the interface of :class:`torch.nn.Conv1d` and
518
+ :class:`torch.nn.BatchNorm1d` and :class:`torch.nn.ReLU`.
519
+
520
+ Similar to `torch.nn.Conv1d`, with FakeQuantize modules initialized to
521
+ default.
522
+
523
+ Attributes:
524
+ weight_fake_quant: fake quant module for weight
525
+
526
+ """
527
+ # base class defines _FLOAT_MODULE as "ConvBn1d"
528
+ _FLOAT_MODULE: ClassVar[Type[nn.Module]] = nni.ConvBnReLU1d
529
+ _FLOAT_CONV_MODULE: ClassVar[Type[nn.Conv1d]] = nn.Conv1d
530
+ _FLOAT_BN_MODULE: ClassVar[Type[nn.BatchNorm1d]] = nn.BatchNorm1d
531
+ _FLOAT_RELU_MODULE: ClassVar[Optional[Type[nn.Module]]] = nn.ReLU
532
+ # module class after fusing bn into conv
533
+ _FUSED_FLOAT_MODULE: ClassVar[Optional[Type[nn.Module]]] = nni.ConvReLU1d
534
+
535
+ def __init__(
536
+ self,
537
+ # Conv1d args
538
+ in_channels,
539
+ out_channels,
540
+ kernel_size,
541
+ stride=1,
542
+ padding=0,
543
+ dilation=1,
544
+ groups=1,
545
+ bias=None,
546
+ padding_mode="zeros",
547
+ # BatchNorm1d args
548
+ # num_features: out_channels
549
+ eps=1e-05,
550
+ momentum=0.1,
551
+ # affine: True
552
+ # track_running_stats: True
553
+ # Args for this module
554
+ freeze_bn=False,
555
+ qconfig=None,
556
+ ):
557
+ super().__init__(
558
+ in_channels,
559
+ out_channels,
560
+ kernel_size,
561
+ stride,
562
+ padding,
563
+ dilation,
564
+ groups,
565
+ bias,
566
+ padding_mode,
567
+ eps,
568
+ momentum,
569
+ freeze_bn,
570
+ qconfig,
571
+ )
572
+
573
+ def forward(self, input):
574
+ return F.relu(self._forward(input))
575
+
576
+ @classmethod
577
+ def from_float(cls, mod, use_precomputed_fake_quant=False):
578
+ return super().from_float(mod, use_precomputed_fake_quant)
579
+
580
+
581
+ class ConvReLU1d(nnqat.Conv1d, nni._FusedModule):
582
+ r"""A ConvReLU1d module is a fused module of Conv1d and ReLU, attached with
583
+ FakeQuantize modules for weight for
584
+ quantization aware training.
585
+
586
+ We combined the interface of :class:`~torch.nn.Conv1d` and
587
+ :class:`~torch.nn.BatchNorm1d`.
588
+
589
+ Attributes:
590
+ weight_fake_quant: fake quant module for weight
591
+
592
+ """
593
+ _FLOAT_MODULE: ClassVar[Type[nni.ConvReLU1d]] = nni.ConvReLU1d # type: ignore[assignment]
594
+ _FLOAT_CONV_MODULE: ClassVar[Type[nn.Conv1d]] = nn.Conv1d
595
+ _FLOAT_BN_MODULE: ClassVar[Optional[Type[nn.Module]]] = None
596
+ _FLOAT_RELU_MODULE: ClassVar[Optional[Type[nn.Module]]] = nn.ReLU
597
+
598
+ def __init__(
599
+ self,
600
+ in_channels,
601
+ out_channels,
602
+ kernel_size,
603
+ stride=1,
604
+ padding=0,
605
+ dilation=1,
606
+ groups=1,
607
+ bias=True,
608
+ padding_mode="zeros",
609
+ qconfig=None,
610
+ ):
611
+ super().__init__(
612
+ in_channels,
613
+ out_channels,
614
+ kernel_size,
615
+ stride=stride,
616
+ padding=padding,
617
+ dilation=dilation,
618
+ groups=groups,
619
+ bias=bias,
620
+ padding_mode=padding_mode,
621
+ qconfig=qconfig,
622
+ )
623
+ assert qconfig, "qconfig must be provided for QAT module"
624
+ self.qconfig = qconfig
625
+ self.weight_fake_quant = self.qconfig.weight()
626
+
627
+ def forward(self, input):
628
+ return F.relu(
629
+ self._conv_forward(input, self.weight_fake_quant(self.weight), self.bias)
630
+ )
631
+
632
+ @classmethod
633
+ def from_float(cls, mod, use_precomputed_fake_quant=False):
634
+ return super().from_float(
635
+ mod, use_precomputed_fake_quant=use_precomputed_fake_quant
636
+ )
637
+
638
+
639
+ class ConvBn2d(_ConvBnNd, nn.Conv2d):
640
+ r"""
641
+ A ConvBn2d module is a module fused from Conv2d and BatchNorm2d,
642
+ attached with FakeQuantize modules for weight,
643
+ used in quantization aware training.
644
+
645
+ We combined the interface of :class:`torch.nn.Conv2d` and
646
+ :class:`torch.nn.BatchNorm2d`.
647
+
648
+ Similar to :class:`torch.nn.Conv2d`, with FakeQuantize modules initialized
649
+ to default.
650
+
651
+ Attributes:
652
+ freeze_bn:
653
+ weight_fake_quant: fake quant module for weight
654
+
655
+ """
656
+ _FLOAT_MODULE: ClassVar[Type[nni.ConvBn2d]] = nni.ConvBn2d # type: ignore[assignment]
657
+ _FLOAT_CONV_MODULE: ClassVar[Type[nn.Conv2d]] = nn.Conv2d
658
+ _FLOAT_BN_MODULE: ClassVar[Optional[Type[nn.Module]]] = nn.BatchNorm2d
659
+ _FLOAT_RELU_MODULE: ClassVar[Optional[Type[nn.Module]]] = None
660
+
661
+ def __init__(
662
+ self,
663
+ # ConvNd args
664
+ in_channels,
665
+ out_channels,
666
+ kernel_size,
667
+ stride=1,
668
+ padding=0,
669
+ dilation=1,
670
+ groups=1,
671
+ bias=None,
672
+ padding_mode="zeros",
673
+ # BatchNorm2d args
674
+ # num_features: out_channels
675
+ eps=1e-05,
676
+ momentum=0.1,
677
+ # affine: True
678
+ # track_running_stats: True
679
+ # Args for this module
680
+ freeze_bn=False,
681
+ qconfig=None,
682
+ ):
683
+ kernel_size = _pair(kernel_size)
684
+ stride = _pair(stride)
685
+ padding = _pair(padding)
686
+ dilation = _pair(dilation)
687
+ _ConvBnNd.__init__(
688
+ self,
689
+ in_channels,
690
+ out_channels,
691
+ kernel_size,
692
+ stride,
693
+ padding,
694
+ dilation,
695
+ False,
696
+ _pair(0),
697
+ groups,
698
+ bias,
699
+ padding_mode,
700
+ eps,
701
+ momentum,
702
+ freeze_bn,
703
+ qconfig,
704
+ dim=2,
705
+ )
706
+
707
+
708
+ class ConvBnReLU2d(ConvBn2d):
709
+ r"""
710
+ A ConvBnReLU2d module is a module fused from Conv2d, BatchNorm2d and ReLU,
711
+ attached with FakeQuantize modules for weight,
712
+ used in quantization aware training.
713
+
714
+ We combined the interface of :class:`torch.nn.Conv2d` and
715
+ :class:`torch.nn.BatchNorm2d` and :class:`torch.nn.ReLU`.
716
+
717
+ Similar to `torch.nn.Conv2d`, with FakeQuantize modules initialized to
718
+ default.
719
+
720
+ Attributes:
721
+ weight_fake_quant: fake quant module for weight
722
+
723
+ """
724
+ # base class defines _FLOAT_MODULE as "ConvBn2d"
725
+ _FLOAT_MODULE: ClassVar[Type[nni.ConvBnReLU2d]] = nni.ConvBnReLU2d # type: ignore[assignment]
726
+ _FLOAT_CONV_MODULE: ClassVar[Type[nn.Conv2d]] = nn.Conv2d
727
+ _FLOAT_BN_MODULE: ClassVar[Type[nn.BatchNorm2d]] = nn.BatchNorm2d
728
+ _FLOAT_RELU_MODULE: ClassVar[Optional[Type[nn.Module]]] = nn.ReLU
729
+ # module class after fusing bn into conv
730
+ _FUSED_FLOAT_MODULE: ClassVar[Optional[Type[nni.ConvReLU2d]]] = nni.ConvReLU2d
731
+
732
+ def __init__(
733
+ self,
734
+ # Conv2d args
735
+ in_channels,
736
+ out_channels,
737
+ kernel_size,
738
+ stride=1,
739
+ padding=0,
740
+ dilation=1,
741
+ groups=1,
742
+ bias=None,
743
+ padding_mode="zeros",
744
+ # BatchNorm2d args
745
+ # num_features: out_channels
746
+ eps=1e-05,
747
+ momentum=0.1,
748
+ # affine: True
749
+ # track_running_stats: True
750
+ # Args for this module
751
+ freeze_bn=False,
752
+ qconfig=None,
753
+ ):
754
+ super().__init__(
755
+ in_channels,
756
+ out_channels,
757
+ kernel_size,
758
+ stride,
759
+ padding,
760
+ dilation,
761
+ groups,
762
+ bias,
763
+ padding_mode,
764
+ eps,
765
+ momentum,
766
+ freeze_bn,
767
+ qconfig,
768
+ )
769
+
770
+ def forward(self, input):
771
+ return F.relu(self._forward(input))
772
+
773
+ @classmethod
774
+ def from_float(cls, mod, use_precomputed_fake_quant=False):
775
+ return super().from_float(mod, use_precomputed_fake_quant)
776
+
777
+
778
+ class ConvReLU2d(nnqat.Conv2d, nni._FusedModule):
779
+ r"""A ConvReLU2d module is a fused module of Conv2d and ReLU, attached with
780
+ FakeQuantize modules for weight for
781
+ quantization aware training.
782
+
783
+ We combined the interface of :class:`~torch.nn.Conv2d` and
784
+ :class:`~torch.nn.BatchNorm2d`.
785
+
786
+ Attributes:
787
+ weight_fake_quant: fake quant module for weight
788
+
789
+ """
790
+ _FLOAT_MODULE: ClassVar[Type[nn.Module]] = nni.ConvReLU2d # type: ignore[assignment]
791
+ _FLOAT_CONV_MODULE: ClassVar[Type[nn.Conv2d]] = nn.Conv2d
792
+ _FLOAT_BN_MODULE: ClassVar[Optional[Type[nn.Module]]] = None
793
+ _FLOAT_RELU_MODULE: ClassVar[Optional[Type[nn.Module]]] = nn.ReLU
794
+
795
+ def __init__(
796
+ self,
797
+ in_channels,
798
+ out_channels,
799
+ kernel_size,
800
+ stride=1,
801
+ padding=0,
802
+ dilation=1,
803
+ groups=1,
804
+ bias=True,
805
+ padding_mode="zeros",
806
+ qconfig=None,
807
+ ):
808
+ super().__init__(
809
+ in_channels,
810
+ out_channels,
811
+ kernel_size,
812
+ stride=stride,
813
+ padding=padding,
814
+ dilation=dilation,
815
+ groups=groups,
816
+ bias=bias,
817
+ padding_mode=padding_mode,
818
+ qconfig=qconfig,
819
+ )
820
+ assert qconfig, "qconfig must be provided for QAT module"
821
+ self.qconfig = qconfig
822
+ self.weight_fake_quant = self.qconfig.weight()
823
+
824
+ def forward(self, input):
825
+ return F.relu(
826
+ self._conv_forward(input, self.weight_fake_quant(self.weight), self.bias)
827
+ )
828
+
829
+ @classmethod
830
+ def from_float(cls, mod, use_precomputed_fake_quant=False):
831
+ return super().from_float(
832
+ mod, use_precomputed_fake_quant=use_precomputed_fake_quant
833
+ )
834
+
835
+
836
+ class ConvBn3d(_ConvBnNd, nn.Conv3d):
837
+ r"""
838
+ A ConvBn3d module is a module fused from Conv3d and BatchNorm3d,
839
+ attached with FakeQuantize modules for weight,
840
+ used in quantization aware training.
841
+
842
+ We combined the interface of :class:`torch.nn.Conv3d` and
843
+ :class:`torch.nn.BatchNorm3d`.
844
+
845
+ Similar to :class:`torch.nn.Conv3d`, with FakeQuantize modules initialized
846
+ to default.
847
+
848
+ Attributes:
849
+ freeze_bn:
850
+ weight_fake_quant: fake quant module for weight
851
+
852
+ """
853
+ _FLOAT_MODULE: ClassVar[Type[nni.ConvBn3d]] = nni.ConvBn3d # type: ignore[assignment]
854
+ _FLOAT_CONV_MODULE: ClassVar[Type[nn.Conv3d]] = nn.Conv3d
855
+ _FLOAT_BN_MODULE: ClassVar[Optional[Type[nn.Module]]] = nn.BatchNorm3d
856
+ _FLOAT_RELU_MODULE: ClassVar[Optional[Type[nn.Module]]] = None
857
+
858
+ def __init__(
859
+ self,
860
+ # ConvNd args
861
+ in_channels,
862
+ out_channels,
863
+ kernel_size,
864
+ stride=1,
865
+ padding=0,
866
+ dilation=1,
867
+ groups=1,
868
+ bias=None,
869
+ padding_mode="zeros",
870
+ # BatchNorm3d args
871
+ # num_features: out_channels
872
+ eps=1e-05,
873
+ momentum=0.1,
874
+ # affine: True
875
+ # track_running_stats: True
876
+ # Args for this module
877
+ freeze_bn=False,
878
+ qconfig=None,
879
+ ):
880
+ kernel_size = _triple(kernel_size)
881
+ stride = _triple(stride)
882
+ padding = _triple(padding)
883
+ dilation = _triple(dilation)
884
+ _ConvBnNd.__init__(
885
+ self,
886
+ in_channels,
887
+ out_channels,
888
+ kernel_size,
889
+ stride,
890
+ padding,
891
+ dilation,
892
+ False,
893
+ _triple(0),
894
+ groups,
895
+ bias,
896
+ padding_mode,
897
+ eps,
898
+ momentum,
899
+ freeze_bn,
900
+ qconfig,
901
+ dim=3,
902
+ )
903
+
904
+
905
+ class ConvBnReLU3d(ConvBn3d):
906
+ r"""
907
+ A ConvBnReLU3d module is a module fused from Conv3d, BatchNorm3d and ReLU,
908
+ attached with FakeQuantize modules for weight,
909
+ used in quantization aware training.
910
+
911
+ We combined the interface of :class:`torch.nn.Conv3d` and
912
+ :class:`torch.nn.BatchNorm3d` and :class:`torch.nn.ReLU`.
913
+
914
+ Similar to `torch.nn.Conv3d`, with FakeQuantize modules initialized to
915
+ default.
916
+
917
+ Attributes:
918
+ weight_fake_quant: fake quant module for weight
919
+
920
+ """
921
+ _FLOAT_MODULE: ClassVar[Type[nni.ConvBnReLU3d]] = nni.ConvBnReLU3d # type: ignore[assignment]
922
+ _FLOAT_CONV_MODULE: ClassVar[Type[nn.Conv3d]] = nn.Conv3d
923
+ _FLOAT_BN_MODULE: ClassVar[Type[nn.BatchNorm3d]] = nn.BatchNorm3d
924
+ _FLOAT_RELU_MODULE: ClassVar[Optional[Type[nn.ReLU]]] = nn.ReLU
925
+ # module class after fusing bn into conv
926
+ _FUSED_FLOAT_MODULE: ClassVar[Optional[Type[nni.ConvReLU3d]]] = nni.ConvReLU3d
927
+
928
+ def __init__(
929
+ self,
930
+ # Conv3d args
931
+ in_channels,
932
+ out_channels,
933
+ kernel_size,
934
+ stride=1,
935
+ padding=0,
936
+ dilation=1,
937
+ groups=1,
938
+ bias=None,
939
+ padding_mode="zeros",
940
+ # BatchNorm3d args
941
+ # num_features: out_channels
942
+ eps=1e-05,
943
+ momentum=0.1,
944
+ # affine: True
945
+ # track_running_stats: True
946
+ # Args for this module
947
+ freeze_bn=False,
948
+ qconfig=None,
949
+ ):
950
+ super().__init__(
951
+ in_channels,
952
+ out_channels,
953
+ kernel_size,
954
+ stride,
955
+ padding,
956
+ dilation,
957
+ groups,
958
+ bias,
959
+ padding_mode,
960
+ eps,
961
+ momentum,
962
+ freeze_bn,
963
+ qconfig,
964
+ )
965
+
966
+ def forward(self, input):
967
+ return F.relu(ConvBn3d._forward(self, input))
968
+
969
+ @classmethod
970
+ def from_float(cls, mod, use_precomputed_fake_quant=False):
971
+ return super().from_float(
972
+ mod, use_precomputed_fake_quant=use_precomputed_fake_quant
973
+ )
974
+
975
+
976
+ class ConvReLU3d(nnqat.Conv3d, nni._FusedModule):
977
+ r"""A ConvReLU3d module is a fused module of Conv3d and ReLU, attached with
978
+ FakeQuantize modules for weight for
979
+ quantization aware training.
980
+
981
+ We combined the interface of :class:`~torch.nn.Conv3d` and
982
+ :class:`~torch.nn.BatchNorm3d`.
983
+
984
+ Attributes:
985
+ weight_fake_quant: fake quant module for weight
986
+
987
+ """
988
+ _FLOAT_MODULE: ClassVar[Type[nni.ConvReLU3d]] = nni.ConvReLU3d # type: ignore[assignment]
989
+ _FLOAT_CONV_MODULE: ClassVar[Type[nn.Conv3d]] = nn.Conv3d
990
+ _FLOAT_BN_MODULE: ClassVar[Optional[Type[nn.Module]]] = None
991
+ _FLOAT_RELU_MODULE: ClassVar[Optional[Type[nn.Module]]] = nn.ReLU
992
+
993
+ def __init__(
994
+ self,
995
+ in_channels,
996
+ out_channels,
997
+ kernel_size,
998
+ stride=1,
999
+ padding=0,
1000
+ dilation=1,
1001
+ groups=1,
1002
+ bias=True,
1003
+ padding_mode="zeros",
1004
+ qconfig=None,
1005
+ ):
1006
+ super().__init__(
1007
+ in_channels,
1008
+ out_channels,
1009
+ kernel_size,
1010
+ stride=stride,
1011
+ padding=padding,
1012
+ dilation=dilation,
1013
+ groups=groups,
1014
+ bias=bias,
1015
+ padding_mode=padding_mode,
1016
+ qconfig=qconfig,
1017
+ )
1018
+ assert qconfig, "qconfig must be provided for QAT module"
1019
+ self.qconfig = qconfig
1020
+ self.weight_fake_quant = self.qconfig.weight()
1021
+
1022
+ def forward(self, input):
1023
+ return F.relu(
1024
+ self._conv_forward(input, self.weight_fake_quant(self.weight), self.bias)
1025
+ )
1026
+
1027
+ @classmethod
1028
+ def from_float(cls, mod, use_precomputed_fake_quant=False):
1029
+ return super().from_float(
1030
+ mod, use_precomputed_fake_quant=use_precomputed_fake_quant
1031
+ )
1032
+
1033
+
1034
+ def update_bn_stats(mod):
1035
+ if type(mod) in {
1036
+ ConvBnReLU1d,
1037
+ ConvBnReLU2d,
1038
+ ConvBnReLU3d,
1039
+ ConvBn1d,
1040
+ ConvBn2d,
1041
+ ConvBn3d,
1042
+ }:
1043
+ mod.update_bn_stats()
1044
+
1045
+
1046
+ def freeze_bn_stats(mod):
1047
+ if type(mod) in {
1048
+ ConvBnReLU1d,
1049
+ ConvBnReLU2d,
1050
+ ConvBnReLU3d,
1051
+ ConvBn1d,
1052
+ ConvBn2d,
1053
+ ConvBn3d,
1054
+ }:
1055
+ mod.freeze_bn_stats()
lib/python3.12/site-packages/torch/ao/nn/intrinsic/qat/modules/linear_fused.py ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # mypy: allow-untyped-defs
2
+ import torch
3
+ import torch.ao.nn.intrinsic as nni
4
+ import torch.nn as nn
5
+ import torch.nn.functional as F
6
+ from torch.nn import init
7
+ from torch.nn.parameter import Parameter
8
+ from torch.nn.utils.fusion import fuse_linear_bn_weights
9
+
10
+
11
+ __all__ = [
12
+ "LinearBn1d",
13
+ ]
14
+
15
+
16
+ class LinearBn1d(nn.modules.linear.Linear, nni._FusedModule):
17
+ r"""
18
+ A LinearBn1d module is a module fused from Linear and BatchNorm1d, attached
19
+ with FakeQuantize modules for weight, used in quantization aware training.
20
+
21
+ We combined the interface of :class:`torch.nn.Linear` and
22
+ :class:torch.nn.BatchNorm1d`.
23
+
24
+ Similar to :class:`torch.nn.Linear`, with FakeQuantize modules initialized
25
+ to default.
26
+
27
+ Attributes:
28
+ freeze_bn:
29
+ weight_fake_quant: fake quant module for weight
30
+
31
+ """
32
+
33
+ def __init__(
34
+ self,
35
+ # Linear args
36
+ in_features,
37
+ out_features,
38
+ bias=True,
39
+ # BatchNorm1d args
40
+ # num_features: out_features
41
+ eps=1e-05,
42
+ momentum=0.1,
43
+ # affine: True
44
+ # track_running_stats: True
45
+ # Args for this module
46
+ freeze_bn=False,
47
+ qconfig=None,
48
+ ):
49
+ nn.modules.linear.Linear.__init__(self, in_features, out_features, bias)
50
+ assert qconfig, "qconfig must be provided for QAT module"
51
+ self.qconfig = qconfig
52
+ self.freeze_bn = freeze_bn if self.training else True
53
+ self.bn = nn.BatchNorm1d(out_features, eps, momentum, True, True)
54
+ self.weight_fake_quant = self.qconfig.weight()
55
+ if bias:
56
+ self.bias = Parameter(torch.empty(out_features))
57
+ else:
58
+ self.register_parameter("bias", None)
59
+ self.reset_bn_parameters()
60
+
61
+ # this needs to be called after reset_bn_parameters,
62
+ # as they modify the same state
63
+ if self.training:
64
+ if freeze_bn:
65
+ self.freeze_bn_stats()
66
+ else:
67
+ self.update_bn_stats()
68
+ else:
69
+ self.freeze_bn_stats()
70
+
71
+ def reset_running_stats(self):
72
+ self.bn.reset_running_stats()
73
+
74
+ def reset_bn_parameters(self):
75
+ self.bn.reset_running_stats()
76
+ init.uniform_(self.bn.weight)
77
+ init.zeros_(self.bn.bias)
78
+
79
+ def reset_parameters(self):
80
+ super().reset_parameters()
81
+
82
+ def update_bn_stats(self):
83
+ self.freeze_bn = False
84
+ self.bn.training = True
85
+ return self
86
+
87
+ def freeze_bn_stats(self):
88
+ self.freeze_bn = True
89
+ self.bn.training = False
90
+ return self
91
+
92
+ def forward(self, input):
93
+ assert self.bn.running_var is not None
94
+
95
+ # Scale the linear weights by BN's running statistics to reduce
96
+ # weight jitter, see https://arxiv.org/pdf/1806.08342.pdf, page 18
97
+ # for motivation.
98
+ #
99
+ # Instead of
100
+ #
101
+ # x1 = F.linear(x0, fq(w), b)
102
+ # x2 = self.bn(x1)
103
+ #
104
+ # We have
105
+ #
106
+ # # scale the weight by previous batch's running statistics
107
+ # scale_factor = bn.w / bn.running_std_from_prev_batch
108
+ # # do the linear transformation without bias
109
+ # x1_scaled = F.linear(x0, fq(w * scale_factor), 0)
110
+ # # reverse the scaling and add original bias
111
+ # x1_orig = x1_scaled / scale_factor + b
112
+ # x2 = self.bn(x1_orig)
113
+
114
+ running_std = torch.sqrt(self.bn.running_var + self.bn.eps)
115
+ scale_factor = self.bn.weight / running_std
116
+ weight_shape = [1] * len(self.weight.shape)
117
+ weight_shape[0] = -1
118
+ bias_shape = [1] * len(self.weight.shape)
119
+ bias_shape[1] = -1
120
+ scaled_weight = self.weight_fake_quant(
121
+ self.weight * scale_factor.reshape(weight_shape)
122
+ )
123
+ if self.bias is not None:
124
+ zero_bias = torch.zeros_like(self.bias)
125
+ else:
126
+ zero_bias = torch.zeros(self.out_features, device=scaled_weight.device)
127
+ linear_out = F.linear(input, scaled_weight, zero_bias)
128
+ linear_out_orig = linear_out / scale_factor.reshape(bias_shape)
129
+ if self.bias is not None:
130
+ linear_out_orig = linear_out_orig + self.bias.reshape(bias_shape)
131
+ bn_out = self.bn(linear_out_orig)
132
+ return bn_out
133
+
134
+ def train(self, mode=True):
135
+ """
136
+ Batchnorm's training behavior is using the self.training flag. Prevent
137
+ changing it if BN is frozen. This makes sure that calling `model.train()`
138
+ on a model with a frozen BN will behave properly.
139
+ """
140
+ self.training = mode
141
+ if not self.freeze_bn:
142
+ for module in self.children():
143
+ module.train(mode)
144
+ return self
145
+
146
+ @classmethod
147
+ def from_float(cls, mod, use_precomputed_fake_quant=False):
148
+ r"""Create a qat module from a float module or qparams_dict
149
+
150
+ Args: `mod' a float module, either produced by torch.ao.quantization
151
+ utilities or directly from user
152
+ """
153
+ assert type(mod) == nni.LinearBn1d, (
154
+ "qat."
155
+ + cls.__name__
156
+ + ".from_float only works for "
157
+ + nni.LinearBn1d.__name__
158
+ )
159
+ assert hasattr(mod, "qconfig"), "Input float module must have qconfig defined"
160
+ assert mod.qconfig, "Input float module must have a valid config"
161
+ qconfig = mod.qconfig
162
+ linear, bn = mod[0], mod[1]
163
+ qat_linearbn = cls(
164
+ linear.in_features,
165
+ linear.out_features,
166
+ linear.bias is not None,
167
+ bn.eps,
168
+ bn.momentum,
169
+ False,
170
+ qconfig,
171
+ )
172
+ qat_linearbn.weight = linear.weight
173
+ qat_linearbn.bias = linear.bias
174
+ qat_linearbn.bn.weight = bn.weight
175
+ qat_linearbn.bn.bias = bn.bias
176
+ qat_linearbn.bn.running_mean = bn.running_mean
177
+ qat_linearbn.bn.running_var = bn.running_var
178
+ qat_linearbn.bn.num_batches_tracked = bn.num_batches_tracked
179
+ return qat_linearbn
180
+
181
+ def to_float(self):
182
+ linear = torch.nn.Linear(self.in_features, self.out_features)
183
+ assert self.bn.running_var is not None and self.bn.running_mean is not None
184
+ linear.weight, linear.bias = fuse_linear_bn_weights(
185
+ self.weight,
186
+ self.bias,
187
+ self.bn.running_mean,
188
+ self.bn.running_var,
189
+ self.bn.eps,
190
+ self.bn.weight,
191
+ self.bn.bias,
192
+ )
193
+ return linear
lib/python3.12/site-packages/torch/ao/nn/intrinsic/qat/modules/linear_relu.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # mypy: allow-untyped-defs
2
+ import torch
3
+ import torch.ao.nn.intrinsic as nni
4
+ import torch.ao.nn.qat as nnqat
5
+ import torch.nn.functional as F
6
+
7
+
8
+ class LinearReLU(nnqat.Linear, nni._FusedModule):
9
+ r"""
10
+ A LinearReLU module fused from Linear and ReLU modules, attached with
11
+ FakeQuantize modules for weight, used in
12
+ quantization aware training.
13
+
14
+ We adopt the same interface as :class:`torch.nn.Linear`.
15
+
16
+ Similar to `torch.ao.nn.intrinsic.LinearReLU`, with FakeQuantize modules initialized to
17
+ default.
18
+
19
+ Attributes:
20
+ weight: fake quant module for weight
21
+
22
+ Examples::
23
+
24
+ >>> # xdoctest: +SKIP
25
+ >>> m = nn.qat.LinearReLU(20, 30)
26
+ >>> input = torch.randn(128, 20)
27
+ >>> output = m(input)
28
+ >>> print(output.size())
29
+ torch.Size([128, 30])
30
+ """
31
+ _FLOAT_MODULE = nni.LinearReLU # type: ignore[assignment]
32
+
33
+ def __init__(self, in_features, out_features, bias=True, qconfig=None):
34
+ super().__init__(in_features, out_features, bias, qconfig)
35
+
36
+ def forward(self, input):
37
+ return F.relu(F.linear(input, self.weight_fake_quant(self.weight), self.bias))
38
+
39
+ @classmethod
40
+ def from_float(cls, mod, use_precomputed_fake_quant=False):
41
+ return super().from_float(mod, use_precomputed_fake_quant)
42
+
43
+ def to_float(self):
44
+ linear = torch.nn.Linear(
45
+ self.in_features, self.out_features, self.bias is not None
46
+ )
47
+ linear.weight = torch.nn.Parameter(self.weight.detach())
48
+ if self.bias is not None:
49
+ linear.bias = torch.nn.Parameter(self.bias.detach())
50
+ relu = torch.nn.ReLU()
51
+ return torch.ao.nn.intrinsic.LinearReLU(linear, relu)
lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/__init__.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .modules import * # noqa: F403
2
+
3
+
4
+ __all__ = [
5
+ "BNReLU2d",
6
+ "BNReLU3d",
7
+ "ConvReLU1d",
8
+ "ConvReLU2d",
9
+ "ConvReLU3d",
10
+ "LinearReLU",
11
+ "LinearLeakyReLU",
12
+ "LinearTanh",
13
+ "ConvAdd2d",
14
+ "ConvAddReLU2d",
15
+ ]
lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (388 Bytes). View file
 
lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/dynamic/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .modules import * # noqa: F403
lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/dynamic/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (247 Bytes). View file
 
lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/dynamic/modules/__init__.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ from .linear_relu import LinearReLU
2
+
3
+
4
+ __all__ = [
5
+ "LinearReLU",
6
+ ]
lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/dynamic/modules/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (307 Bytes). View file
 
lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/dynamic/modules/__pycache__/linear_relu.cpython-312.pyc ADDED
Binary file (3.37 kB). View file
 
lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/dynamic/modules/linear_relu.py ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # mypy: allow-untyped-defs
2
+ import torch
3
+ import torch.ao.nn.intrinsic as nni
4
+ import torch.ao.nn.quantized.dynamic as nnqd
5
+
6
+
7
+ __all__ = ["LinearReLU"]
8
+
9
+
10
+ class LinearReLU(nnqd.Linear):
11
+ r"""
12
+ A LinearReLU module fused from Linear and ReLU modules that can be used
13
+ for dynamic quantization.
14
+ Supports both, FP16 and INT8 quantization.
15
+
16
+ We adopt the same interface as :class:`torch.ao.nn.quantized.dynamic.Linear`.
17
+
18
+ Attributes:
19
+ Same as torch.ao.nn.quantized.dynamic.Linear
20
+
21
+ Examples::
22
+
23
+ >>> # xdoctest: +SKIP
24
+ >>> m = nn.intrinsic.quantized.dynamic.LinearReLU(20, 30)
25
+ >>> input = torch.randn(128, 20)
26
+ >>> output = m(input)
27
+ >>> print(output.size())
28
+ torch.Size([128, 30])
29
+ """
30
+ _FLOAT_MODULE = nni.LinearReLU # type: ignore[assignment]
31
+
32
+ def __init__(self, in_features, out_features, bias=True, dtype=torch.qint8):
33
+ super().__init__(in_features, out_features, bias, dtype)
34
+
35
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
36
+ if self._packed_params.dtype == torch.qint8:
37
+ # TODO check if we should set reduce_rage = True by default here
38
+ Y = torch.ops.quantized.linear_relu_dynamic(
39
+ x, self._packed_params._packed_params, reduce_range=True
40
+ )
41
+ elif self._packed_params.dtype == torch.float16:
42
+ Y = torch.ops.quantized.linear_relu_dynamic_fp16(
43
+ x, self._packed_params._packed_params
44
+ )
45
+ else:
46
+ raise RuntimeError("Unsupported dtype on dynamic quantized linear relu!")
47
+ return Y.to(x.dtype)
48
+
49
+ def _get_name(self):
50
+ return "DynamicQuantizedLinearReLU"
51
+
52
+ @classmethod
53
+ def from_float(cls, mod, use_precomputed_fake_quant=False):
54
+ return super().from_float(
55
+ mod, use_precomputed_fake_quant=use_precomputed_fake_quant
56
+ )
57
+
58
+ @classmethod
59
+ def from_reference(cls, ref_qlinear_relu):
60
+ return super().from_reference(ref_qlinear_relu[0])
lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/modules/__init__.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .bn_relu import BNReLU2d, BNReLU3d
2
+ from .conv_add import ConvAdd2d, ConvAddReLU2d
3
+ from .conv_relu import ConvReLU1d, ConvReLU2d, ConvReLU3d
4
+ from .linear_relu import LinearLeakyReLU, LinearReLU, LinearTanh
5
+
6
+
7
+ __all__ = [
8
+ "LinearReLU",
9
+ "ConvReLU1d",
10
+ "ConvReLU2d",
11
+ "ConvReLU3d",
12
+ "BNReLU2d",
13
+ "BNReLU3d",
14
+ "LinearLeakyReLU",
15
+ "LinearTanh",
16
+ "ConvAdd2d",
17
+ "ConvAddReLU2d",
18
+ ]
lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/modules/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (610 Bytes). View file
 
lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/modules/__pycache__/bn_relu.cpython-312.pyc ADDED
Binary file (4.61 kB). View file
 
lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/modules/__pycache__/conv_add.cpython-312.pyc ADDED
Binary file (5.29 kB). View file
 
lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/modules/__pycache__/conv_relu.cpython-312.pyc ADDED
Binary file (10.6 kB). View file
 
lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/modules/__pycache__/linear_relu.cpython-312.pyc ADDED
Binary file (9.9 kB). View file
 
lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/modules/bn_relu.py ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # mypy: allow-untyped-defs
2
+
3
+ import torch
4
+ import torch.ao.nn.intrinsic
5
+ import torch.ao.nn.intrinsic.qat
6
+ import torch.ao.nn.quantized as nnq
7
+
8
+
9
+ __all__ = ["BNReLU2d", "BNReLU3d"]
10
+
11
+
12
+ class BNReLU2d(nnq.BatchNorm2d):
13
+ r"""
14
+ A BNReLU2d module is a fused module of BatchNorm2d and ReLU
15
+
16
+ We adopt the same interface as :class:`torch.ao.nn.quantized.BatchNorm2d`.
17
+
18
+ Attributes:
19
+ Same as torch.ao.nn.quantized.BatchNorm2d
20
+
21
+ """
22
+ _FLOAT_MODULE = torch.ao.nn.intrinsic.BNReLU2d
23
+
24
+ def __init__(self, num_features, eps=1e-5, momentum=0.1, device=None, dtype=None):
25
+ super().__init__(
26
+ num_features, eps=eps, momentum=momentum, device=device, dtype=dtype
27
+ )
28
+
29
+ def forward(self, input):
30
+ # Temporarily using len(shape) instead of ndim due to JIT issue
31
+ # https://github.com/pytorch/pytorch/issues/23890
32
+ if len(input.shape) != 4:
33
+ raise ValueError("Input shape must be `(N, C, H, W)`!")
34
+ return torch.ops.quantized.batch_norm2d_relu(
35
+ input,
36
+ self.weight,
37
+ self.bias,
38
+ self.running_mean,
39
+ self.running_var,
40
+ self.eps,
41
+ self.scale,
42
+ self.zero_point,
43
+ )
44
+
45
+ def _get_name(self):
46
+ return "QuantizedBNReLU2d"
47
+
48
+ @classmethod
49
+ def from_float(cls, mod, use_precomputed_fake_quant=False):
50
+ # TODO: Add qat support for BNReLU2d
51
+ return super().from_float(
52
+ mod, use_precomputed_fake_quant=use_precomputed_fake_quant
53
+ )
54
+
55
+ @classmethod
56
+ def from_reference(cls, bn_relu, output_scale, output_zero_point):
57
+ return super().from_reference(bn_relu[0], output_scale, output_zero_point)
58
+
59
+
60
+ class BNReLU3d(nnq.BatchNorm3d):
61
+ r"""
62
+ A BNReLU3d module is a fused module of BatchNorm3d and ReLU
63
+
64
+ We adopt the same interface as :class:`torch.ao.nn.quantized.BatchNorm3d`.
65
+
66
+ Attributes:
67
+ Same as torch.ao.nn.quantized.BatchNorm3d
68
+
69
+ """
70
+ _FLOAT_MODULE = torch.ao.nn.intrinsic.BNReLU3d
71
+
72
+ def __init__(self, num_features, eps=1e-5, momentum=0.1, device=None, dtype=None):
73
+ super().__init__(
74
+ num_features, eps=eps, momentum=momentum, device=device, dtype=dtype
75
+ )
76
+
77
+ def forward(self, input):
78
+ # Temporarily using len(shape) instead of ndim due to JIT issue
79
+ # https://github.com/pytorch/pytorch/issues/23890
80
+ if len(input.shape) != 5:
81
+ raise ValueError("Input shape must be `(N, C, D, H, W)`!")
82
+ return torch.ops.quantized.batch_norm3d_relu(
83
+ input,
84
+ self.weight,
85
+ self.bias,
86
+ self.running_mean,
87
+ self.running_var,
88
+ self.eps,
89
+ self.scale,
90
+ self.zero_point,
91
+ )
92
+
93
+ def _get_name(self):
94
+ return "QuantizedBNReLU3d"
95
+
96
+ @classmethod
97
+ def from_float(cls, mod, use_precomputed_fake_quant=False):
98
+ # TODO: Add qat support for BNReLU3d
99
+ return super().from_float(
100
+ mod, use_precomputed_fake_quant=use_precomputed_fake_quant
101
+ )
102
+
103
+ @classmethod
104
+ def from_reference(cls, bn_relu, output_scale, output_zero_point):
105
+ return super().from_reference(bn_relu[0], output_scale, output_zero_point)
lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/modules/conv_add.py ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # mypy: allow-untyped-defs
2
+ import torch
3
+ import torch.ao.nn.intrinsic
4
+ import torch.ao.nn.intrinsic.qat
5
+ import torch.ao.nn.quantized as nnq
6
+ import torch.nn.functional as F
7
+
8
+
9
+ _reverse_repeat_padding = nnq.modules.conv._reverse_repeat_padding
10
+
11
+
12
+ class ConvAdd2d(nnq.Conv2d):
13
+ r"""
14
+ A ConvAdd2d module is a fused module of Conv2d and Add
15
+
16
+ We adopt the same interface as :class:`torch.ao.nn.quantized.Conv2d`.
17
+
18
+ Attributes:
19
+ Same as torch.ao.nn.quantized.Conv2d
20
+
21
+ """
22
+ _FLOAT_MODULE = torch.ao.nn.intrinsic.ConvAdd2d # type: ignore[assignment]
23
+
24
+ def __init__(
25
+ self,
26
+ in_channels,
27
+ out_channels,
28
+ kernel_size,
29
+ stride=1,
30
+ padding=0,
31
+ dilation=1,
32
+ groups=1,
33
+ bias=True,
34
+ padding_mode="zeros",
35
+ device=None,
36
+ dtype=None,
37
+ ):
38
+ super().__init__(
39
+ in_channels,
40
+ out_channels,
41
+ kernel_size,
42
+ stride=stride,
43
+ padding=padding,
44
+ dilation=dilation,
45
+ groups=groups,
46
+ bias=bias,
47
+ padding_mode=padding_mode,
48
+ device=device,
49
+ dtype=dtype,
50
+ )
51
+
52
+ def forward(self, input, extra_input): # type: ignore[override]
53
+ # Temporarily using len(shape) instead of ndim due to JIT issue
54
+ # https://github.com/pytorch/pytorch/issues/23890
55
+ if len(input.shape) != 4:
56
+ raise ValueError("Input shape must be `(N, C, H, W)`!")
57
+ if self.padding_mode != "zeros":
58
+ _reversed_padding_repeated_twice = _reverse_repeat_padding(self.padding)
59
+ input = F.pad(
60
+ input, _reversed_padding_repeated_twice, mode=self.padding_mode
61
+ )
62
+ return torch.ops.quantized.conv2d_add(
63
+ input, extra_input, self._packed_params, self.scale, self.zero_point
64
+ )
65
+
66
+ def _get_name(self):
67
+ return "QuantizedConvAdd2d"
68
+
69
+ @classmethod
70
+ def from_float(cls, mod, use_precomputed_fake_quant=False):
71
+ return super().from_float(
72
+ mod, use_precomputed_fake_quant=use_precomputed_fake_quant
73
+ )
74
+
75
+ @classmethod
76
+ def from_reference(cls, ref_qconv, output_scale, output_zero_point):
77
+ return super().from_reference(ref_qconv[0], output_scale, output_zero_point)
78
+
79
+
80
+ class ConvAddReLU2d(nnq.Conv2d):
81
+ r"""
82
+ A ConvAddReLU2d module is a fused module of Conv2d, Add and Relu
83
+
84
+ We adopt the same interface as :class:`torch.ao.nn.quantized.Conv2d`.
85
+
86
+ Attributes:
87
+ Same as torch.ao.nn.quantized.Conv2d
88
+
89
+ """
90
+ _FLOAT_MODULE = torch.ao.nn.intrinsic.ConvAddReLU2d # type: ignore[assignment]
91
+
92
+ def __init__(
93
+ self,
94
+ in_channels,
95
+ out_channels,
96
+ kernel_size,
97
+ stride=1,
98
+ padding=0,
99
+ dilation=1,
100
+ groups=1,
101
+ bias=True,
102
+ padding_mode="zeros",
103
+ device=None,
104
+ dtype=None,
105
+ ):
106
+ super().__init__(
107
+ in_channels,
108
+ out_channels,
109
+ kernel_size,
110
+ stride=stride,
111
+ padding=padding,
112
+ dilation=dilation,
113
+ groups=groups,
114
+ bias=bias,
115
+ padding_mode=padding_mode,
116
+ device=device,
117
+ dtype=dtype,
118
+ )
119
+
120
+ def forward(self, input, extra_input): # type: ignore[override]
121
+ # Temporarily using len(shape) instead of ndim due to JIT issue
122
+ # https://github.com/pytorch/pytorch/issues/23890
123
+ if len(input.shape) != 4:
124
+ raise ValueError("Input shape must be `(N, C, H, W)`!")
125
+ if self.padding_mode != "zeros":
126
+ _reversed_padding_repeated_twice = _reverse_repeat_padding(self.padding)
127
+ input = F.pad(
128
+ input, _reversed_padding_repeated_twice, mode=self.padding_mode
129
+ )
130
+ return torch.ops.quantized.conv2d_add_relu(
131
+ input, extra_input, self._packed_params, self.scale, self.zero_point
132
+ )
133
+
134
+ def _get_name(self):
135
+ return "QuantizedConvAddReLU2d"
136
+
137
+ @classmethod
138
+ def from_float(cls, mod, use_precomputed_fake_quant=False):
139
+ return super().from_float(
140
+ mod, use_precomputed_fake_quant=use_precomputed_fake_quant
141
+ )
142
+
143
+ @classmethod
144
+ def from_reference(cls, ref_qconv, output_scale, output_zero_point):
145
+ return super().from_reference(ref_qconv[0], output_scale, output_zero_point)
lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/modules/conv_relu.py ADDED
@@ -0,0 +1,263 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # mypy: allow-untyped-defs
2
+
3
+ import torch
4
+ import torch.ao.nn.intrinsic
5
+ import torch.ao.nn.intrinsic.qat
6
+ import torch.ao.nn.quantized as nnq
7
+ import torch.nn.functional as F
8
+ from torch.nn.utils import fuse_conv_bn_weights
9
+
10
+
11
+ __all__ = [
12
+ "ConvReLU1d",
13
+ "ConvReLU2d",
14
+ "ConvReLU3d",
15
+ ]
16
+
17
+ _reverse_repeat_padding = nnq.modules.conv._reverse_repeat_padding
18
+
19
+
20
+ # TODO: factor out the common parts to ConvNd
21
+ class ConvReLU1d(nnq.Conv1d):
22
+ r"""
23
+ A ConvReLU1d module is a fused module of Conv1d and ReLU
24
+
25
+ We adopt the same interface as :class:`torch.ao.nn.quantized.Conv1d`.
26
+
27
+ Attributes:
28
+ Same as torch.ao.nn.quantized.Conv1d
29
+
30
+ """
31
+ _FLOAT_MODULE = torch.ao.nn.intrinsic.ConvReLU1d # type: ignore[assignment]
32
+
33
+ def __init__(
34
+ self,
35
+ in_channels,
36
+ out_channels,
37
+ kernel_size,
38
+ stride=1,
39
+ padding=0,
40
+ dilation=1,
41
+ groups=1,
42
+ bias=True,
43
+ padding_mode="zeros",
44
+ device=None,
45
+ dtype=None,
46
+ ):
47
+ super().__init__(
48
+ in_channels,
49
+ out_channels,
50
+ kernel_size,
51
+ stride=stride,
52
+ padding=padding,
53
+ dilation=dilation,
54
+ groups=groups,
55
+ bias=bias,
56
+ padding_mode=padding_mode,
57
+ device=device,
58
+ dtype=dtype,
59
+ )
60
+
61
+ def forward(self, input):
62
+ # Temporarily using len(shape) instead of ndim due to JIT issue
63
+ # https://github.com/pytorch/pytorch/issues/23890
64
+ if len(input.shape) != 3:
65
+ raise ValueError("Input shape must be `(N, C, L)`!")
66
+ if self.padding_mode != "zeros":
67
+ # Padding in Conv1d is stored as (p, p), need to get (p,)
68
+ _reversed_padding_repeated_twice = _reverse_repeat_padding(self.padding[:1])
69
+ input = F.pad(
70
+ input, _reversed_padding_repeated_twice, mode=self.padding_mode
71
+ )
72
+ return torch.ops.quantized.conv1d_relu(
73
+ input, self._packed_params, self.scale, self.zero_point
74
+ )
75
+
76
+ def _get_name(self):
77
+ return "QuantizedConvReLU1d"
78
+
79
+ @classmethod
80
+ def from_float(cls, mod, use_precomputed_fake_quant=False):
81
+ if type(mod) == torch.ao.nn.intrinsic.qat.ConvBnReLU1d:
82
+ assert mod.bn.running_var is not None and mod.bn.running_mean is not None
83
+ mod.weight, mod.bias = fuse_conv_bn_weights(
84
+ mod.weight,
85
+ mod.bias,
86
+ mod.bn.running_mean,
87
+ mod.bn.running_var,
88
+ mod.bn.eps,
89
+ mod.bn.weight,
90
+ mod.bn.bias,
91
+ )
92
+ return super().from_float(mod, use_precomputed_fake_quant)
93
+
94
+ @classmethod
95
+ def from_reference(cls, ref_qconv, output_scale, output_zero_point):
96
+ assert (
97
+ type(ref_qconv) != torch.ao.nn.intrinsic.ConvBnReLU1d
98
+ ), "BatchNorm1d should be fused into Conv1d before converting to reference module"
99
+ return super().from_reference(ref_qconv[0], output_scale, output_zero_point)
100
+
101
+
102
+ class ConvReLU2d(nnq.Conv2d):
103
+ r"""
104
+ A ConvReLU2d module is a fused module of Conv2d and ReLU
105
+
106
+ We adopt the same interface as :class:`torch.ao.nn.quantized.Conv2d`.
107
+
108
+ Attributes:
109
+ Same as torch.ao.nn.quantized.Conv2d
110
+
111
+ """
112
+ _FLOAT_MODULE = torch.ao.nn.intrinsic.ConvReLU2d # type: ignore[assignment]
113
+
114
+ def __init__(
115
+ self,
116
+ in_channels,
117
+ out_channels,
118
+ kernel_size,
119
+ stride=1,
120
+ padding=0,
121
+ dilation=1,
122
+ groups=1,
123
+ bias=True,
124
+ padding_mode="zeros",
125
+ device=None,
126
+ dtype=None,
127
+ ):
128
+ super().__init__(
129
+ in_channels,
130
+ out_channels,
131
+ kernel_size,
132
+ stride=stride,
133
+ padding=padding,
134
+ dilation=dilation,
135
+ groups=groups,
136
+ bias=bias,
137
+ padding_mode=padding_mode,
138
+ device=device,
139
+ dtype=dtype,
140
+ )
141
+
142
+ def forward(self, input):
143
+ # Temporarily using len(shape) instead of ndim due to JIT issue
144
+ # https://github.com/pytorch/pytorch/issues/23890
145
+ if len(input.shape) != 4:
146
+ raise ValueError("Input shape must be `(N, C, H, W)`!")
147
+ if self.padding_mode != "zeros":
148
+ _reversed_padding_repeated_twice = _reverse_repeat_padding(self.padding)
149
+ input = F.pad(
150
+ input, _reversed_padding_repeated_twice, mode=self.padding_mode
151
+ )
152
+ return torch.ops.quantized.conv2d_relu(
153
+ input, self._packed_params, self.scale, self.zero_point
154
+ )
155
+
156
+ def _get_name(self):
157
+ return "QuantizedConvReLU2d"
158
+
159
+ @classmethod
160
+ def from_float(cls, mod, use_precomputed_fake_quant=False):
161
+ if type(mod) == torch.ao.nn.intrinsic.qat.ConvBnReLU2d:
162
+ assert mod.bn.running_var is not None and mod.bn.running_mean is not None
163
+ mod.weight, mod.bias = fuse_conv_bn_weights(
164
+ mod.weight,
165
+ mod.bias,
166
+ mod.bn.running_mean,
167
+ mod.bn.running_var,
168
+ mod.bn.eps,
169
+ mod.bn.weight,
170
+ mod.bn.bias,
171
+ )
172
+ return super().from_float(
173
+ mod, use_precomputed_fake_quant=use_precomputed_fake_quant
174
+ )
175
+
176
+ @classmethod
177
+ def from_reference(cls, ref_qconv, output_scale, output_zero_point):
178
+ assert (
179
+ type(ref_qconv) != torch.ao.nn.intrinsic.ConvBnReLU2d
180
+ ), "BatchNorm2d should be fused into Conv2d before converting to reference module"
181
+ return super().from_reference(ref_qconv[0], output_scale, output_zero_point)
182
+
183
+
184
+ class ConvReLU3d(nnq.Conv3d):
185
+ r"""
186
+ A ConvReLU3d module is a fused module of Conv3d and ReLU
187
+
188
+ We adopt the same interface as :class:`torch.ao.nn.quantized.Conv3d`.
189
+
190
+ Attributes: Same as torch.ao.nn.quantized.Conv3d
191
+
192
+ """
193
+ _FLOAT_MODULE = torch.ao.nn.intrinsic.ConvReLU3d # type: ignore[assignment]
194
+
195
+ def __init__(
196
+ self,
197
+ in_channels,
198
+ out_channels,
199
+ kernel_size,
200
+ stride=1,
201
+ padding=0,
202
+ dilation=1,
203
+ groups=1,
204
+ bias=True,
205
+ padding_mode="zeros",
206
+ device=None,
207
+ dtype=None,
208
+ ):
209
+ assert padding_mode != "reflect", "Conv3d does not support reflection padding"
210
+ super().__init__(
211
+ in_channels,
212
+ out_channels,
213
+ kernel_size,
214
+ stride=stride,
215
+ padding=padding,
216
+ dilation=dilation,
217
+ groups=groups,
218
+ bias=bias,
219
+ padding_mode=padding_mode,
220
+ device=device,
221
+ dtype=dtype,
222
+ )
223
+
224
+ def forward(self, input):
225
+ # Temporarily using len(shape) instead of ndim due to JIT issue
226
+ # https://github.com/pytorch/pytorch/issues/23890
227
+ if len(input.shape) != 5:
228
+ raise ValueError("Input shape must be `(N, C, D, H, W)`!")
229
+ if self.padding_mode != "zeros":
230
+ _reversed_padding_repeated_twice = _reverse_repeat_padding(self.padding)
231
+ input = F.pad(
232
+ input, _reversed_padding_repeated_twice, mode=self.padding_mode
233
+ )
234
+ return torch.ops.quantized.conv3d_relu(
235
+ input, self._packed_params, self.scale, self.zero_point
236
+ )
237
+
238
+ def _get_name(self):
239
+ return "QuantizedConvReLU3d"
240
+
241
+ @classmethod
242
+ def from_float(cls, mod, use_precomputed_fake_quant=False):
243
+ if type(mod) == torch.ao.nn.intrinsic.qat.ConvBnReLU3d:
244
+ assert mod.bn.running_var is not None and mod.bn.running_mean is not None
245
+ mod.weight, mod.bias = fuse_conv_bn_weights(
246
+ mod.weight,
247
+ mod.bias,
248
+ mod.bn.running_mean,
249
+ mod.bn.running_var,
250
+ mod.bn.eps,
251
+ mod.bn.weight,
252
+ mod.bn.bias,
253
+ )
254
+ return super().from_float(
255
+ mod, use_precomputed_fake_quant=use_precomputed_fake_quant
256
+ )
257
+
258
+ @classmethod
259
+ def from_reference(cls, ref_qconv, output_scale, output_zero_point):
260
+ assert (
261
+ type(ref_qconv) != torch.ao.nn.intrinsic.ConvBnReLU3d
262
+ ), "BatchNorm3d should be fused into Conv3d before converting to reference module"
263
+ return super().from_reference(ref_qconv[0], output_scale, output_zero_point)
lib/python3.12/site-packages/torch/ao/nn/intrinsic/quantized/modules/linear_relu.py ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # mypy: allow-untyped-defs
2
+ import torch
3
+ import torch.ao.nn.intrinsic as nni
4
+ import torch.ao.nn.quantized as nnq
5
+ from torch.ao.nn.quantized.modules.utils import _quantize_weight
6
+
7
+
8
+ __all__ = [
9
+ "LinearReLU",
10
+ "LinearLeakyReLU",
11
+ "LinearTanh",
12
+ ]
13
+
14
+
15
+ class LinearReLU(nnq.Linear):
16
+ r"""
17
+ A LinearReLU module fused from Linear and ReLU modules
18
+
19
+ We adopt the same interface as :class:`torch.ao.nn.quantized.Linear`.
20
+
21
+ Attributes:
22
+ Same as torch.ao.nn.quantized.Linear
23
+
24
+ Examples::
25
+
26
+ >>> # xdoctest: +SKIP
27
+ >>> m = nn.intrinsic.LinearReLU(20, 30)
28
+ >>> input = torch.randn(128, 20)
29
+ >>> output = m(input)
30
+ >>> print(output.size())
31
+ torch.Size([128, 30])
32
+ """
33
+ _FLOAT_MODULE = nni.LinearReLU # type: ignore[assignment]
34
+
35
+ def __init__(self, in_features, out_features, bias=True, dtype=torch.qint8):
36
+ super().__init__(in_features, out_features, bias, dtype)
37
+
38
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
39
+ return torch.ops.quantized.linear_relu(
40
+ x, self._packed_params._packed_params, self.scale, self.zero_point
41
+ )
42
+
43
+ def _get_name(self):
44
+ return "QuantizedLinearReLU"
45
+
46
+ @classmethod
47
+ def from_float(cls, mod, use_precomputed_fake_quant=False):
48
+ return super().from_float(mod, use_precomputed_fake_quant)
49
+
50
+ @classmethod
51
+ def from_reference(cls, ref_linear_relu, output_scale, output_zero_point):
52
+ return super().from_reference(
53
+ ref_linear_relu[0], output_scale, output_zero_point
54
+ )
55
+
56
+
57
+ class LinearLeakyReLU(nnq.Linear):
58
+ r"""
59
+ For onednn backend only
60
+ A LinearLeakyReLU module fused from Linear and LeakyReLU modules
61
+ We adopt the same interface as :class:`torch.ao.nn.quantized.Linear`.
62
+ Attributes:
63
+ Same as torch.ao.nn.quantized.Linear
64
+ + negative_slope
65
+ Examples::
66
+ >>> # xdoctest: +SKIP
67
+ >>> m = nn.intrinsic.LinearLeakyReLU(20, 30, 0.01)
68
+ >>> input = torch.randn(128, 20)
69
+ >>> output = m(input)
70
+ >>> print(output.size())
71
+ torch.Size([128, 30])
72
+ """
73
+ _FLOAT_MODULE = nni.LinearLeakyReLU # type: ignore[assignment]
74
+
75
+ def __init__(
76
+ self, in_features, out_features, negative_slope, bias=True, dtype=torch.qint8
77
+ ):
78
+ super().__init__(in_features, out_features, bias, dtype)
79
+ self.negative_slope = negative_slope
80
+
81
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
82
+ return torch.ops.quantized.linear_leaky_relu(
83
+ x,
84
+ self._packed_params._packed_params,
85
+ self.scale,
86
+ self.zero_point,
87
+ self.negative_slope,
88
+ )
89
+
90
+ def _get_name(self):
91
+ return "QuantizedLinearLeakyReLU"
92
+
93
+ @classmethod
94
+ def from_float(cls, mod, use_precomputed_fake_quant=False):
95
+ assert (
96
+ type(mod) == nni.LinearLeakyReLU
97
+ ), "Input float module should be LinearLeakyReLU"
98
+ assert hasattr(mod, "qconfig"), "Input float module must have qconfig defined"
99
+ activation_post_process = mod.activation_post_process
100
+ leaky_relu = mod[1]
101
+ mod = mod[0]
102
+ weight_post_process = mod.qconfig.weight()
103
+ weight_post_process(mod.weight)
104
+ dtype = weight_post_process.dtype
105
+ act_scale, act_zp = activation_post_process.calculate_qparams() # type: ignore[union-attr,operator]
106
+ assert dtype == torch.qint8, "Weight observer must have dtype torch.qint8"
107
+ qweight = _quantize_weight(mod.weight.float(), weight_post_process)
108
+ qlinear_leaky_relu = cls(
109
+ mod.in_features, mod.out_features, leaky_relu.negative_slope, dtype=dtype
110
+ )
111
+ qlinear_leaky_relu.set_weight_bias(qweight, mod.bias)
112
+ qlinear_leaky_relu.scale = float(act_scale)
113
+ qlinear_leaky_relu.zero_point = int(act_zp)
114
+ return qlinear_leaky_relu
115
+
116
+ @classmethod
117
+ def from_reference(cls, ref_mod, output_scale, output_zero_point):
118
+ linear = ref_mod[0]
119
+ leaky_relu = ref_mod[1]
120
+ qlinear_leaky_relu = cls(
121
+ linear.in_features, linear.out_features, leaky_relu.negative_slope
122
+ )
123
+ qweight = linear.get_quantized_weight()
124
+ qlinear_leaky_relu.set_weight_bias(qweight, linear.bias)
125
+ qlinear_leaky_relu.scale = float(output_scale)
126
+ qlinear_leaky_relu.zero_point = int(output_zero_point)
127
+ return qlinear_leaky_relu
128
+
129
+
130
+ class LinearTanh(nnq.Linear):
131
+ r"""
132
+ A LinearTanh module fused from Linear and Tanh modules
133
+
134
+ We adopt the same interface as :class:`torch.ao.nn.quantized.Linear`.
135
+
136
+ Attributes:
137
+ Same as torch.ao.nn.quantized.Linear
138
+
139
+ Examples::
140
+
141
+ >>> # xdoctest: +SKIP
142
+ >>> m = nn.intrinsic.LinearTanh(20, 30)
143
+ >>> input = torch.randn(128, 20)
144
+ >>> output = m(input)
145
+ >>> print(output.size())
146
+ torch.Size([128, 30])
147
+ """
148
+ _FLOAT_MODULE = nni.LinearTanh # type: ignore[assignment]
149
+
150
+ def __init__(self, in_features, out_features, bias=True, dtype=torch.qint8):
151
+ super().__init__(in_features, out_features, bias, dtype)
152
+
153
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
154
+ return torch.ops.quantized.linear_tanh(
155
+ x, self._packed_params._packed_params, self.scale, self.zero_point
156
+ )
157
+
158
+ def _get_name(self):
159
+ return "QuantizedLinearTanh"
160
+
161
+ @classmethod
162
+ def from_float(cls, mod, use_precomputed_fake_quant=False):
163
+ assert type(mod) == nni.LinearTanh, "Input float module should be LinearTanh"
164
+ assert hasattr(mod, "qconfig"), "Input float module must have qconfig defined"
165
+ activation_post_process = mod.activation_post_process
166
+ mod = mod[0]
167
+ weight_post_process = mod.qconfig.weight()
168
+ weight_post_process(mod.weight)
169
+ dtype = weight_post_process.dtype
170
+ act_scale, act_zp = activation_post_process.calculate_qparams() # type: ignore[union-attr,operator]
171
+ assert dtype == torch.qint8, "Weight observer must have dtype torch.qint8"
172
+ qweight = _quantize_weight(mod.weight.float(), weight_post_process)
173
+ qlinear_tanh = cls(mod.in_features, mod.out_features, dtype=dtype)
174
+ qlinear_tanh.set_weight_bias(qweight, mod.bias)
175
+ qlinear_tanh.scale = float(act_scale)
176
+ qlinear_tanh.zero_point = int(act_zp)
177
+ return qlinear_tanh
178
+
179
+ @classmethod
180
+ def from_reference(cls, ref_mod, output_scale, output_zero_point):
181
+ linear = ref_mod[0]
182
+ qlinear_tanh = cls(linear.in_features, linear.out_features)
183
+ qweight = linear.get_quantized_weight()
184
+ qlinear_tanh.set_weight_bias(qweight, linear.bias)
185
+ qlinear_tanh.scale = float(output_scale)
186
+ qlinear_tanh.zero_point = int(output_zero_point)
187
+ return qlinear_tanh
lib/python3.12/site-packages/torch/ao/nn/qat/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .modules import * # noqa: F403
lib/python3.12/site-packages/torch/ao/nn/quantizable/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .modules import * # noqa: F403
lib/python3.12/site-packages/torch/ao/nn/quantizable/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (231 Bytes). View file
 
lib/python3.12/site-packages/torch/ao/nn/quantizable/modules/__init__.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ from .activation import MultiheadAttention
2
+ from .rnn import LSTM, LSTMCell
3
+
4
+
5
+ __all__ = [
6
+ "LSTM",
7
+ "LSTMCell",
8
+ "MultiheadAttention",
9
+ ]
lib/python3.12/site-packages/torch/ao/nn/quantizable/modules/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (359 Bytes). View file
 
lib/python3.12/site-packages/torch/ao/nn/quantizable/modules/__pycache__/activation.cpython-312.pyc ADDED
Binary file (24.2 kB). View file
 
lib/python3.12/site-packages/torch/ao/nn/quantizable/modules/__pycache__/rnn.cpython-312.pyc ADDED
Binary file (26.2 kB). View file
 
lib/python3.12/site-packages/torch/ao/nn/quantizable/modules/activation.py ADDED
@@ -0,0 +1,550 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # mypy: allow-untyped-defs
2
+ import warnings
3
+ from typing import Optional, Tuple
4
+
5
+ import torch
6
+ import torch.jit # this is needed to avoid a circular import
7
+ import torch.nn.functional as F
8
+ from torch import nn, Tensor
9
+
10
+
11
+ __all__ = ["MultiheadAttention"]
12
+
13
+
14
+ class MultiheadAttention(nn.MultiheadAttention):
15
+ _FLOAT_MODULE = nn.MultiheadAttention
16
+
17
+ r"""Quantizable implementation of the MultiheadAttention.
18
+
19
+ Note::
20
+ Please, refer to :class:`~torch.nn.MultiheadAttention` for more
21
+ information
22
+
23
+ Allows the model to jointly attend to information from different
24
+ representation subspaces.
25
+ See reference: Attention Is All You Need
26
+
27
+ The original MHA module is not quantizable.
28
+ This reimplements it by explicitly instantiating the linear layers.
29
+
30
+ .. math::
31
+ \text{MultiHead}(Q, K, V) = \text{Concat}(head_1,\dots,head_h)W^O
32
+ \text{where} head_i = \text{Attention}(QW_i^Q, KW_i^K, VW_i^V)
33
+
34
+ Args:
35
+ embed_dim: total dimension of the model.
36
+ num_heads: parallel attention heads.
37
+ dropout: a Dropout layer on attn_output_weights. Default: 0.0.
38
+ bias: add bias as module parameter. Default: True.
39
+ add_bias_kv: add bias to the key and value sequences at dim=0.
40
+ add_zero_attn: add a new batch of zeros to the key and
41
+ value sequences at dim=1.
42
+ kdim: total number of features in key. Default: None.
43
+ vdim: total number of features in value. Default: None.
44
+ batch_first: If ``True``, then the input and output tensors are provided
45
+ as (batch, seq, feature). Default: ``False`` (seq, batch, feature).
46
+
47
+ Note that if :attr:`kdim` and :attr:`vdim` are None, they will be set
48
+ to :attr:`embed_dim` such that query, key, and value have the same
49
+ number of features.
50
+
51
+ Examples::
52
+
53
+ >>> import torch.ao.nn.quantizable as nnqa
54
+ >>> multihead_attn = nnqa.MultiheadAttention(embed_dim, num_heads)
55
+ >>> attn_output, attn_output_weights = multihead_attn(query, key, value)
56
+
57
+ Note::
58
+ Please, follow the quantization flow to convert the quantizable MHA.
59
+ """
60
+ __constants__ = ["batch_first"]
61
+
62
+ def __init__(
63
+ self,
64
+ embed_dim: int,
65
+ num_heads: int,
66
+ dropout: float = 0.0,
67
+ bias: bool = True,
68
+ add_bias_kv: bool = False,
69
+ add_zero_attn: bool = False,
70
+ kdim: Optional[int] = None,
71
+ vdim: Optional[int] = None,
72
+ batch_first: bool = False,
73
+ device=None,
74
+ dtype=None,
75
+ ) -> None:
76
+ factory_kwargs = {"device": device, "dtype": dtype}
77
+ super().__init__(
78
+ embed_dim,
79
+ num_heads,
80
+ dropout,
81
+ bias,
82
+ add_bias_kv,
83
+ add_zero_attn,
84
+ kdim,
85
+ vdim,
86
+ batch_first,
87
+ **factory_kwargs,
88
+ )
89
+ self.linear_Q = nn.Linear(
90
+ self.embed_dim, self.embed_dim, bias=bias, **factory_kwargs
91
+ )
92
+ self.linear_K = nn.Linear(
93
+ self.kdim, self.embed_dim, bias=bias, **factory_kwargs
94
+ )
95
+ self.linear_V = nn.Linear(
96
+ self.vdim, self.embed_dim, bias=bias, **factory_kwargs
97
+ )
98
+ # for the type: ignore, see https://github.com/pytorch/pytorch/issues/58969
99
+ self.out_proj = nn.Linear(self.embed_dim, self.embed_dim, bias=bias, **factory_kwargs) # type: ignore[assignment]
100
+
101
+ # Functionals
102
+ self.q_scaling_product = torch.ao.nn.quantized.FloatFunctional()
103
+ # note: importing torch.ao.nn.quantized at top creates a circular import
104
+
105
+ # Quant/Dequant
106
+ self.quant_attn_output = torch.ao.quantization.QuantStub()
107
+ self.quant_attn_output_weights = torch.ao.quantization.QuantStub()
108
+ self.dequant_q = torch.ao.quantization.DeQuantStub()
109
+ self.dequant_k = torch.ao.quantization.DeQuantStub()
110
+ self.dequant_v = torch.ao.quantization.DeQuantStub()
111
+
112
+ def _get_name(self):
113
+ return "QuantizableMultiheadAttention"
114
+
115
+ @classmethod
116
+ def from_float(cls, other):
117
+ assert type(other) == cls._FLOAT_MODULE
118
+ assert hasattr(other, "qconfig"), "The float module must have 'qconfig'"
119
+ # Setting the dropout to 0.0!
120
+ observed = cls(
121
+ other.embed_dim,
122
+ other.num_heads,
123
+ other.dropout,
124
+ (other.in_proj_bias is not None),
125
+ (other.bias_k is not None),
126
+ other.add_zero_attn,
127
+ other.kdim,
128
+ other.vdim,
129
+ other.batch_first,
130
+ )
131
+ observed.bias_k = other.bias_k
132
+ observed.bias_v = other.bias_v
133
+ observed.qconfig = other.qconfig
134
+
135
+ # Set the linear weights
136
+ # for the type: ignores, see https://github.com/pytorch/pytorch/issues/58969
137
+ observed.out_proj.weight = other.out_proj.weight
138
+ observed.out_proj.bias = other.out_proj.bias
139
+ if other._qkv_same_embed_dim:
140
+ # Use separate params
141
+ bias = other.in_proj_bias
142
+ _start = 0
143
+ _end = _start + other.embed_dim
144
+ weight = other.in_proj_weight[_start:_end, :]
145
+ if bias is not None:
146
+ bias = torch.nn.Parameter(bias[_start:_end], bias.requires_grad)
147
+ observed.linear_Q.weight = torch.nn.Parameter(weight, weight.requires_grad)
148
+ observed.linear_Q.bias = bias
149
+
150
+ bias = other.in_proj_bias
151
+ _start = _end
152
+ _end = _start + other.embed_dim
153
+ weight = other.in_proj_weight[_start:_end, :]
154
+ if bias is not None:
155
+ bias = torch.nn.Parameter(bias[_start:_end], bias.requires_grad)
156
+ observed.linear_K.weight = torch.nn.Parameter(weight, weight.requires_grad)
157
+ observed.linear_K.bias = bias
158
+
159
+ bias = other.in_proj_bias
160
+ _start = _end
161
+ weight = other.in_proj_weight[_start:, :]
162
+ if bias is not None:
163
+ bias = torch.nn.Parameter(bias[_start:], bias.requires_grad)
164
+ observed.linear_V.weight = torch.nn.Parameter(weight, weight.requires_grad)
165
+ observed.linear_V.bias = bias
166
+ else:
167
+ observed.linear_Q.weight = nn.Parameter(other.q_proj_weight)
168
+ observed.linear_K.weight = nn.Parameter(other.k_proj_weight)
169
+ observed.linear_V.weight = nn.Parameter(other.v_proj_weight)
170
+ if other.in_proj_bias is None:
171
+ observed.linear_Q.bias = None
172
+ observed.linear_K.bias = None
173
+ observed.linear_V.bias = None
174
+ else:
175
+ observed.linear_Q.bias = nn.Parameter(
176
+ other.in_proj_bias[0 : other.embed_dim]
177
+ )
178
+ observed.linear_K.bias = nn.Parameter(
179
+ other.in_proj_bias[other.embed_dim : (other.embed_dim * 2)]
180
+ )
181
+ observed.linear_V.bias = nn.Parameter(
182
+ other.in_proj_bias[(other.embed_dim * 2) :]
183
+ )
184
+ observed.eval()
185
+ # Explicit prepare
186
+ observed = torch.ao.quantization.prepare(observed, inplace=True)
187
+ return observed
188
+
189
+ @torch.jit.unused
190
+ def dequantize(self):
191
+ r"""Utility to convert the quantized MHA back to float.
192
+
193
+ The motivation for this is that it is not trivial to conver the weights
194
+ from the format that is used in the quantized version back to the
195
+ float.
196
+ """
197
+ fp = self._FLOAT_MODULE(
198
+ self.embed_dim,
199
+ self.num_heads,
200
+ self.dropout,
201
+ (self.linear_Q._weight_bias()[1] is not None), # type: ignore[operator]
202
+ (self.bias_k is not None),
203
+ self.add_zero_attn,
204
+ self.kdim,
205
+ self.vdim,
206
+ self.batch_first,
207
+ )
208
+ assert fp._qkv_same_embed_dim == self._qkv_same_embed_dim
209
+ if self.bias_k is not None:
210
+ fp.bias_k = nn.Parameter(self.bias_k.dequantize())
211
+ if self.bias_v is not None:
212
+ fp.bias_v = nn.Parameter(self.bias_v.dequantize())
213
+
214
+ # Set the linear weights
215
+ # Note: Because the linear layers are quantized, mypy does not nkow how
216
+ # to deal with them -- might need to ignore the typing checks.
217
+ # for the type: ignore[has-type], see https://github.com/pytorch/pytorch/issues/58969
218
+ w, b = self.out_proj._weight_bias() # type: ignore[operator, has-type]
219
+ fp.out_proj.weight = nn.Parameter(w.dequantize())
220
+ if b is not None:
221
+ fp.out_proj.bias = nn.Parameter(b)
222
+
223
+ wQ, bQ = self.linear_Q._weight_bias() # type: ignore[operator]
224
+ wQ = wQ.dequantize()
225
+ wK, bK = self.linear_K._weight_bias() # type: ignore[operator]
226
+ wK = wK.dequantize()
227
+ wV, bV = self.linear_V._weight_bias() # type: ignore[operator]
228
+ wV = wV.dequantize()
229
+ if fp._qkv_same_embed_dim:
230
+ # Use separate params
231
+ _start = 0
232
+ _end = _start + fp.embed_dim
233
+ fp.in_proj_weight[_start:_end, :] = wQ
234
+ if fp.in_proj_bias is not None:
235
+ assert all(bQ == 0)
236
+ fp.in_proj_bias[_start:_end] = bQ
237
+
238
+ _start = _end
239
+ _end = _start + fp.embed_dim
240
+ fp.in_proj_weight[_start:_end, :] = wK
241
+ if fp.in_proj_bias is not None:
242
+ assert all(bK == 0)
243
+ fp.in_proj_bias[_start:_end] = bK
244
+
245
+ _start = _end
246
+ fp.in_proj_weight[_start:, :] = wV
247
+ if fp.in_proj_bias is not None:
248
+ assert all(bV == 0)
249
+ fp.in_proj_bias[_start:] = bV
250
+ else:
251
+ fp.q_proj_weight = nn.Parameter(wQ)
252
+ fp.k_proj_weight = nn.Parameter(wK)
253
+ fp.v_proj_weight = nn.Parameter(wV)
254
+ if fp.in_proj_bias is None:
255
+ self.linear_Q.bias = None
256
+ self.linear_K.bias = None
257
+ self.linear_V.bias = None
258
+ else:
259
+ fp.in_proj_bias[0 : fp.embed_dim] = bQ
260
+ fp.in_proj_bias[fp.embed_dim : (fp.embed_dim * 2)] = bK
261
+ fp.in_proj_bias[(fp.embed_dim * 2) :] = bV
262
+
263
+ return fp
264
+
265
+ @classmethod
266
+ def from_observed(cls, other):
267
+ # The whole flow is float -> observed -> quantized
268
+ # This class does float -> observed only
269
+ # See nn.quantized.MultiheadAttention
270
+ raise NotImplementedError(
271
+ "It looks like you are trying to prepare an "
272
+ "MHA module. Please, see "
273
+ "the examples on quantizable MHAs."
274
+ )
275
+
276
+ def forward(
277
+ self,
278
+ query: Tensor,
279
+ key: Tensor,
280
+ value: Tensor,
281
+ key_padding_mask: Optional[Tensor] = None,
282
+ need_weights: bool = True,
283
+ attn_mask: Optional[Tensor] = None,
284
+ average_attn_weights: bool = True,
285
+ is_causal: bool = False,
286
+ ) -> Tuple[Tensor, Optional[Tensor]]:
287
+ r"""
288
+ Note::
289
+ Please, refer to :func:`~torch.nn.MultiheadAttention.forward` for more
290
+ information
291
+
292
+ Args:
293
+ query, key, value: map a query and a set of key-value pairs to an output.
294
+ See "Attention Is All You Need" for more details.
295
+ key_padding_mask: if provided, specified padding elements in the key will
296
+ be ignored by the attention. When given a binary mask and a value is True,
297
+ the corresponding value on the attention layer will be ignored.
298
+ need_weights: output attn_output_weights.
299
+ attn_mask: 2D or 3D mask that prevents attention to certain positions. A 2D mask will be broadcasted for all
300
+ the batches while a 3D mask allows to specify a different mask for the entries of each batch.
301
+
302
+ Shape:
303
+ - Inputs:
304
+ - query: :math:`(L, N, E)` where L is the target sequence length, N is the batch size, E is
305
+ the embedding dimension. :math:`(N, L, E)` if ``batch_first`` is ``True``.
306
+ - key: :math:`(S, N, E)`, where S is the source sequence length, N is the batch size, E is
307
+ the embedding dimension. :math:`(N, S, E)` if ``batch_first`` is ``True``.
308
+ - value: :math:`(S, N, E)` where S is the source sequence length, N is the batch size, E is
309
+ the embedding dimension. :math:`(N, S, E)` if ``batch_first`` is ``True``.
310
+ - key_padding_mask: :math:`(N, S)` where N is the batch size, S is the source sequence length.
311
+ If a BoolTensor is provided, the positions with the
312
+ value of ``True`` will be ignored while the position with the value of ``False`` will be unchanged.
313
+ - attn_mask: 2D mask :math:`(L, S)` where L is the target sequence length, S is the source sequence length.
314
+ 3D mask :math:`(N*num_heads, L, S)` where N is the batch size, L is the target sequence length,
315
+ S is the source sequence length. attn_mask ensure that position i is allowed to attend the unmasked
316
+ positions. If a BoolTensor is provided, positions with ``True``
317
+ is not allowed to attend while ``False`` values will be unchanged. If a FloatTensor
318
+ is provided, it will be added to the attention weight.
319
+ - is_causal: If specified, applies a causal mask as attention mask. Mutually exclusive with providing attn_mask.
320
+ Default: ``False``.
321
+ - average_attn_weights: If true, indicates that the returned ``attn_weights`` should be averaged across
322
+ heads. Otherwise, ``attn_weights`` are provided separately per head. Note that this flag only has an
323
+ effect when ``need_weights=True.``. Default: True (i.e. average weights across heads)
324
+
325
+ - Outputs:
326
+ - attn_output: :math:`(L, N, E)` where L is the target sequence length, N is the batch size,
327
+ E is the embedding dimension. :math:`(N, L, E)` if ``batch_first`` is ``True``.
328
+ - attn_output_weights: If ``average_attn_weights=True``, returns attention weights averaged
329
+ across heads of shape :math:`(N, L, S)`, where N is the batch size, L is the target sequence length,
330
+ S is the source sequence length. If ``average_attn_weights=False``, returns attention weights per
331
+ head of shape :math:`(N, num_heads, L, S)`.
332
+ """
333
+ return self._forward_impl(
334
+ query,
335
+ key,
336
+ value,
337
+ key_padding_mask,
338
+ need_weights,
339
+ attn_mask,
340
+ average_attn_weights,
341
+ is_causal,
342
+ )
343
+
344
+ def _forward_impl(
345
+ self,
346
+ query: Tensor,
347
+ key: Tensor,
348
+ value: Tensor,
349
+ key_padding_mask: Optional[Tensor] = None,
350
+ need_weights: bool = True,
351
+ attn_mask: Optional[Tensor] = None,
352
+ average_attn_weights: bool = True,
353
+ is_causal: bool = False,
354
+ ) -> Tuple[Tensor, Optional[Tensor]]:
355
+ # This version will not deal with the static key/value pairs.
356
+ # Keeping it here for future changes.
357
+ #
358
+ # TODO: This method has some duplicate lines with the
359
+ # `torch.nn.functional.multi_head_attention`. Will need to refactor.
360
+ static_k = None
361
+ static_v = None
362
+
363
+ if attn_mask is not None and is_causal:
364
+ raise AssertionError("Only allow causal mask or attn_mask")
365
+
366
+ if is_causal:
367
+ raise AssertionError("causal mask not supported by AO MHA module")
368
+
369
+ if self.batch_first:
370
+ query, key, value = (x.transpose(0, 1) for x in (query, key, value))
371
+
372
+ tgt_len, bsz, embed_dim_to_check = query.size()
373
+ assert self.embed_dim == embed_dim_to_check
374
+ # allow MHA to have different sizes for the feature dimension
375
+ assert key.size(0) == value.size(0) and key.size(1) == value.size(1)
376
+
377
+ head_dim = self.embed_dim // self.num_heads
378
+ assert (
379
+ head_dim * self.num_heads == self.embed_dim
380
+ ), "embed_dim must be divisible by num_heads"
381
+ scaling = float(head_dim) ** -0.5
382
+
383
+ q = self.linear_Q(query)
384
+ k = self.linear_K(key)
385
+ v = self.linear_V(value)
386
+
387
+ q = self.q_scaling_product.mul_scalar(q, scaling)
388
+
389
+ if attn_mask is not None:
390
+ if attn_mask.dtype == torch.uint8:
391
+ warnings.warn(
392
+ "Byte tensor for `attn_mask` in `nn.MultiheadAttention` is deprecated. "
393
+ "Use bool tensor instead.",
394
+ stacklevel=3,
395
+ )
396
+ attn_mask = attn_mask.to(torch.bool)
397
+ assert (
398
+ attn_mask.is_floating_point() or attn_mask.dtype == torch.bool
399
+ ), f"Only float and bool types are supported for attn_mask, not {attn_mask.dtype}"
400
+
401
+ if attn_mask.dim() == 2:
402
+ attn_mask = attn_mask.unsqueeze(0)
403
+ if list(attn_mask.size()) != [1, query.size(0), key.size(0)]:
404
+ raise RuntimeError("The size of the 2D attn_mask is not correct.")
405
+ elif attn_mask.dim() == 3:
406
+ if list(attn_mask.size()) != [
407
+ bsz * self.num_heads,
408
+ query.size(0),
409
+ key.size(0),
410
+ ]:
411
+ raise RuntimeError("The size of the 3D attn_mask is not correct.")
412
+ else:
413
+ raise RuntimeError(
414
+ f"attn_mask's dimension {attn_mask.dim()} is not supported"
415
+ )
416
+ # attn_mask's dim is 3 now.
417
+
418
+ # convert ByteTensor key_padding_mask to bool
419
+ if key_padding_mask is not None and key_padding_mask.dtype == torch.uint8:
420
+ warnings.warn(
421
+ "Byte tensor for `key_padding_mask` in `nn.MultiheadAttention` is deprecated. "
422
+ "Use bool tensor instead.",
423
+ stacklevel=3,
424
+ )
425
+ key_padding_mask = key_padding_mask.to(torch.bool)
426
+ if self.bias_k is not None and self.bias_v is not None:
427
+ if static_k is None and static_v is None:
428
+ # Explicitly assert that bias_k and bias_v are not None
429
+ # in a way that TorchScript can understand.
430
+ bias_k = self.bias_k
431
+ assert bias_k is not None
432
+ bias_v = self.bias_v
433
+ assert bias_v is not None
434
+
435
+ k = torch.cat([k, bias_k.repeat(1, bsz, 1)])
436
+ v = torch.cat([v, bias_v.repeat(1, bsz, 1)])
437
+ if attn_mask is not None:
438
+ attn_mask = F.pad(attn_mask, (0, 1))
439
+ if key_padding_mask is not None:
440
+ key_padding_mask = F.pad(key_padding_mask, (0, 1))
441
+ else:
442
+ assert static_k is None, "bias cannot be added to static key."
443
+ assert static_v is None, "bias cannot be added to static value."
444
+ else:
445
+ assert self.bias_k is None
446
+ assert self.bias_v is None
447
+
448
+ q = q.contiguous().view(tgt_len, bsz * self.num_heads, head_dim).transpose(0, 1)
449
+ if k is not None:
450
+ k = k.contiguous().view(-1, bsz * self.num_heads, head_dim).transpose(0, 1)
451
+ if v is not None:
452
+ v = v.contiguous().view(-1, bsz * self.num_heads, head_dim).transpose(0, 1)
453
+
454
+ if static_k is not None:
455
+ assert static_k.size(0) == bsz * self.num_heads
456
+ assert static_k.size(2) == head_dim
457
+ k = static_k
458
+
459
+ if static_v is not None:
460
+ assert static_v.size(0) == bsz * self.num_heads
461
+ assert static_v.size(2) == head_dim
462
+ v = static_v
463
+
464
+ src_len = k.size(1)
465
+
466
+ if key_padding_mask is not None:
467
+ assert key_padding_mask.size(0) == bsz
468
+ assert key_padding_mask.size(1) == src_len
469
+
470
+ if self.add_zero_attn:
471
+ src_len += 1
472
+ k_zeros = torch.zeros((k.size(0), 1) + k.size()[2:])
473
+ if k.is_quantized:
474
+ k_zeros = torch.quantize_per_tensor(
475
+ k_zeros, k.q_scale(), k.q_zero_point(), k.dtype
476
+ )
477
+ k = torch.cat([k, k_zeros], dim=1)
478
+ v_zeros = torch.zeros((v.size(0), 1) + k.size()[2:])
479
+ if v.is_quantized:
480
+ v_zeros = torch.quantize_per_tensor(
481
+ v_zeros, v.q_scale(), v.q_zero_point(), v.dtype
482
+ )
483
+ v = torch.cat([v, v_zeros], dim=1)
484
+
485
+ if attn_mask is not None:
486
+ attn_mask = F.pad(attn_mask, (0, 1))
487
+ if key_padding_mask is not None:
488
+ key_padding_mask = F.pad(key_padding_mask, (0, 1))
489
+
490
+ # Leaving the quantized zone here
491
+ q = self.dequant_q(q)
492
+ k = self.dequant_k(k)
493
+ v = self.dequant_v(v)
494
+ attn_output_weights = torch.bmm(q, k.transpose(1, 2))
495
+ assert list(attn_output_weights.size()) == [
496
+ bsz * self.num_heads,
497
+ tgt_len,
498
+ src_len,
499
+ ]
500
+
501
+ if attn_mask is not None:
502
+ if attn_mask.dtype == torch.bool:
503
+ attn_output_weights.masked_fill_(attn_mask, float("-inf"))
504
+ else:
505
+ attn_output_weights += attn_mask
506
+
507
+ if key_padding_mask is not None:
508
+ attn_output_weights = attn_output_weights.view(
509
+ bsz, self.num_heads, tgt_len, src_len
510
+ )
511
+ attn_output_weights = attn_output_weights.masked_fill(
512
+ key_padding_mask.unsqueeze(1).unsqueeze(2),
513
+ float("-inf"),
514
+ )
515
+ attn_output_weights = attn_output_weights.view(
516
+ bsz * self.num_heads, tgt_len, src_len
517
+ )
518
+
519
+ attn_output_weights = F.softmax(attn_output_weights, dim=-1)
520
+ attn_output_weights = F.dropout(
521
+ attn_output_weights, p=self.dropout, training=self.training
522
+ )
523
+
524
+ attn_output = torch.bmm(attn_output_weights, v)
525
+ assert list(attn_output.size()) == [bsz * self.num_heads, tgt_len, head_dim]
526
+ if self.batch_first:
527
+ attn_output = attn_output.view(bsz, tgt_len, self.embed_dim)
528
+ else:
529
+ attn_output = (
530
+ attn_output.transpose(0, 1)
531
+ .contiguous()
532
+ .view(tgt_len, bsz, self.embed_dim)
533
+ )
534
+
535
+ # Reentering the quantized zone
536
+ attn_output = self.quant_attn_output(attn_output)
537
+ # for the type: ignore[has-type], see https://github.com/pytorch/pytorch/issues/58969
538
+ attn_output = self.out_proj(attn_output) # type: ignore[has-type]
539
+ attn_output_weights = self.quant_attn_output_weights(attn_output_weights)
540
+
541
+ if need_weights:
542
+ # average attention weights over heads
543
+ attn_output_weights = attn_output_weights.view(
544
+ bsz, self.num_heads, tgt_len, src_len
545
+ )
546
+ if average_attn_weights:
547
+ attn_output_weights = attn_output_weights.mean(dim=1)
548
+ return attn_output, attn_output_weights
549
+ else:
550
+ return attn_output, None
lib/python3.12/site-packages/torch/ao/nn/quantizable/modules/rnn.py ADDED
@@ -0,0 +1,596 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ We will recreate all the RNN modules as we require the modules to be decomposed
3
+ into its building blocks to be able to observe.
4
+ """
5
+
6
+ # mypy: allow-untyped-defs
7
+
8
+ import numbers
9
+ import warnings
10
+ from typing import Optional, Tuple
11
+
12
+ import torch
13
+ from torch import Tensor
14
+
15
+
16
+ __all__ = ["LSTMCell", "LSTM"]
17
+
18
+
19
+ class LSTMCell(torch.nn.Module):
20
+ r"""A quantizable long short-term memory (LSTM) cell.
21
+
22
+ For the description and the argument types, please, refer to :class:`~torch.nn.LSTMCell`
23
+
24
+ `split_gates`: specify True to compute the input/forget/cell/output gates separately
25
+ to avoid an intermediate tensor which is subsequently chunk'd. This optimization can
26
+ be beneficial for on-device inference latency. This flag is cascaded down from the
27
+ parent classes.
28
+
29
+ Examples::
30
+
31
+ >>> import torch.ao.nn.quantizable as nnqa
32
+ >>> rnn = nnqa.LSTMCell(10, 20)
33
+ >>> input = torch.randn(6, 10)
34
+ >>> hx = torch.randn(3, 20)
35
+ >>> cx = torch.randn(3, 20)
36
+ >>> output = []
37
+ >>> for i in range(6):
38
+ ... hx, cx = rnn(input[i], (hx, cx))
39
+ ... output.append(hx)
40
+ """
41
+ _FLOAT_MODULE = torch.nn.LSTMCell
42
+ __constants__ = ["split_gates"] # for jit.script
43
+
44
+ def __init__(
45
+ self,
46
+ input_dim: int,
47
+ hidden_dim: int,
48
+ bias: bool = True,
49
+ device=None,
50
+ dtype=None,
51
+ *,
52
+ split_gates=False,
53
+ ) -> None:
54
+ factory_kwargs = {"device": device, "dtype": dtype}
55
+ super().__init__()
56
+ self.input_size = input_dim
57
+ self.hidden_size = hidden_dim
58
+ self.bias = bias
59
+ self.split_gates = split_gates
60
+
61
+ if not split_gates:
62
+ self.igates: torch.nn.Module = torch.nn.Linear(
63
+ input_dim, 4 * hidden_dim, bias=bias, **factory_kwargs
64
+ )
65
+ self.hgates: torch.nn.Module = torch.nn.Linear(
66
+ hidden_dim, 4 * hidden_dim, bias=bias, **factory_kwargs
67
+ )
68
+ self.gates: torch.nn.Module = torch.ao.nn.quantized.FloatFunctional()
69
+ else:
70
+ # keep separate Linear layers for each gate
71
+ self.igates = torch.nn.ModuleDict()
72
+ self.hgates = torch.nn.ModuleDict()
73
+ self.gates = torch.nn.ModuleDict()
74
+ for g in ["input", "forget", "cell", "output"]:
75
+ # pyre-fixme[29]: `Union[torch._tensor.Tensor, torch.nn.modules.module.Module]`
76
+ self.igates[g] = torch.nn.Linear(
77
+ input_dim, hidden_dim, bias=bias, **factory_kwargs
78
+ )
79
+ # pyre-fixme[29]: `Union[torch._tensor.Tensor, torch.nn.modules.module.Module]`
80
+ self.hgates[g] = torch.nn.Linear(
81
+ hidden_dim, hidden_dim, bias=bias, **factory_kwargs
82
+ )
83
+ # pyre-fixme[29]: `Union[torch._tensor.Tensor, torch.nn.modules.module.Module]`
84
+ self.gates[g] = torch.ao.nn.quantized.FloatFunctional()
85
+
86
+ self.input_gate = torch.nn.Sigmoid()
87
+ self.forget_gate = torch.nn.Sigmoid()
88
+ self.cell_gate = torch.nn.Tanh()
89
+ self.output_gate = torch.nn.Sigmoid()
90
+
91
+ self.fgate_cx = torch.ao.nn.quantized.FloatFunctional()
92
+ self.igate_cgate = torch.ao.nn.quantized.FloatFunctional()
93
+ self.fgate_cx_igate_cgate = torch.ao.nn.quantized.FloatFunctional()
94
+
95
+ self.ogate_cy = torch.ao.nn.quantized.FloatFunctional()
96
+
97
+ self.initial_hidden_state_qparams: Tuple[float, int] = (1.0, 0)
98
+ self.initial_cell_state_qparams: Tuple[float, int] = (1.0, 0)
99
+ self.hidden_state_dtype: torch.dtype = torch.quint8
100
+ self.cell_state_dtype: torch.dtype = torch.quint8
101
+
102
+ def forward(
103
+ self, x: Tensor, hidden: Optional[Tuple[Tensor, Tensor]] = None
104
+ ) -> Tuple[Tensor, Tensor]:
105
+ if hidden is None or hidden[0] is None or hidden[1] is None:
106
+ hidden = self.initialize_hidden(x.shape[0], x.is_quantized)
107
+ hx, cx = hidden
108
+
109
+ if not self.split_gates:
110
+ igates = self.igates(x)
111
+ hgates = self.hgates(hx)
112
+ gates = self.gates.add(igates, hgates) # type: ignore[operator]
113
+
114
+ input_gate, forget_gate, cell_gate, out_gate = gates.chunk(4, 1)
115
+
116
+ input_gate = self.input_gate(input_gate)
117
+ forget_gate = self.forget_gate(forget_gate)
118
+ cell_gate = self.cell_gate(cell_gate)
119
+ out_gate = self.output_gate(out_gate)
120
+ else:
121
+ # apply each input + hidden projection and add together
122
+ gate = {}
123
+ for (key, gates), igates, hgates in zip(
124
+ self.gates.items(), # type: ignore[operator]
125
+ self.igates.values(), # type: ignore[operator]
126
+ self.hgates.values(), # type: ignore[operator]
127
+ ):
128
+ gate[key] = gates.add(igates(x), hgates(hx))
129
+
130
+ input_gate = self.input_gate(gate["input"])
131
+ forget_gate = self.forget_gate(gate["forget"])
132
+ cell_gate = self.cell_gate(gate["cell"])
133
+ out_gate = self.output_gate(gate["output"])
134
+
135
+ fgate_cx = self.fgate_cx.mul(forget_gate, cx)
136
+ igate_cgate = self.igate_cgate.mul(input_gate, cell_gate)
137
+ fgate_cx_igate_cgate = self.fgate_cx_igate_cgate.add(fgate_cx, igate_cgate)
138
+ cy = fgate_cx_igate_cgate
139
+
140
+ # TODO: make this tanh a member of the module so its qparams can be configured
141
+ tanh_cy = torch.tanh(cy)
142
+ hy = self.ogate_cy.mul(out_gate, tanh_cy)
143
+ return hy, cy
144
+
145
+ def initialize_hidden(
146
+ self, batch_size: int, is_quantized: bool = False
147
+ ) -> Tuple[Tensor, Tensor]:
148
+ h, c = torch.zeros((batch_size, self.hidden_size)), torch.zeros(
149
+ (batch_size, self.hidden_size)
150
+ )
151
+ if is_quantized:
152
+ (h_scale, h_zp) = self.initial_hidden_state_qparams
153
+ (c_scale, c_zp) = self.initial_cell_state_qparams
154
+ h = torch.quantize_per_tensor(
155
+ h, scale=h_scale, zero_point=h_zp, dtype=self.hidden_state_dtype
156
+ )
157
+ c = torch.quantize_per_tensor(
158
+ c, scale=c_scale, zero_point=c_zp, dtype=self.cell_state_dtype
159
+ )
160
+ return h, c
161
+
162
+ def _get_name(self):
163
+ return "QuantizableLSTMCell"
164
+
165
+ @classmethod
166
+ def from_params(cls, wi, wh, bi=None, bh=None, split_gates=False):
167
+ """Uses the weights and biases to create a new LSTM cell.
168
+
169
+ Args:
170
+ wi, wh: Weights for the input and hidden layers
171
+ bi, bh: Biases for the input and hidden layers
172
+ """
173
+ assert (bi is None) == (bh is None) # Either both None or both have values
174
+ input_size = wi.shape[1]
175
+ hidden_size = wh.shape[1]
176
+ cell = cls(
177
+ input_dim=input_size,
178
+ hidden_dim=hidden_size,
179
+ bias=(bi is not None),
180
+ split_gates=split_gates,
181
+ )
182
+
183
+ if not split_gates:
184
+ cell.igates.weight = torch.nn.Parameter(wi)
185
+ if bi is not None:
186
+ cell.igates.bias = torch.nn.Parameter(bi)
187
+ cell.hgates.weight = torch.nn.Parameter(wh)
188
+ if bh is not None:
189
+ cell.hgates.bias = torch.nn.Parameter(bh)
190
+ else:
191
+ # split weight/bias
192
+ for w, b, gates in zip([wi, wh], [bi, bh], [cell.igates, cell.hgates]):
193
+ for w_chunk, gate in zip(w.chunk(4, dim=0), gates.values()): # type: ignore[operator]
194
+ gate.weight = torch.nn.Parameter(w_chunk)
195
+
196
+ if b is not None:
197
+ for b_chunk, gate in zip(b.chunk(4, dim=0), gates.values()): # type: ignore[operator]
198
+ gate.bias = torch.nn.Parameter(b_chunk)
199
+
200
+ return cell
201
+
202
+ @classmethod
203
+ def from_float(cls, other, use_precomputed_fake_quant=False, split_gates=False):
204
+ assert type(other) == cls._FLOAT_MODULE
205
+ assert hasattr(other, "qconfig"), "The float module must have 'qconfig'"
206
+ observed = cls.from_params(
207
+ other.weight_ih,
208
+ other.weight_hh,
209
+ other.bias_ih,
210
+ other.bias_hh,
211
+ split_gates=split_gates,
212
+ )
213
+ observed.qconfig = other.qconfig
214
+ observed.igates.qconfig = other.qconfig
215
+ observed.hgates.qconfig = other.qconfig
216
+ if split_gates:
217
+ # also apply qconfig directly to Linear modules
218
+ for g in observed.igates.values():
219
+ g.qconfig = other.qconfig
220
+ for g in observed.hgates.values():
221
+ g.qconfig = other.qconfig
222
+ return observed
223
+
224
+
225
+ class _LSTMSingleLayer(torch.nn.Module):
226
+ r"""A single one-directional LSTM layer.
227
+
228
+ The difference between a layer and a cell is that the layer can process a
229
+ sequence, while the cell only expects an instantaneous value.
230
+ """
231
+
232
+ def __init__(
233
+ self,
234
+ input_dim: int,
235
+ hidden_dim: int,
236
+ bias: bool = True,
237
+ device=None,
238
+ dtype=None,
239
+ *,
240
+ split_gates=False,
241
+ ) -> None:
242
+ factory_kwargs = {"device": device, "dtype": dtype}
243
+ super().__init__()
244
+ self.cell = LSTMCell(
245
+ input_dim, hidden_dim, bias=bias, split_gates=split_gates, **factory_kwargs
246
+ )
247
+
248
+ def forward(self, x: Tensor, hidden: Optional[Tuple[Tensor, Tensor]] = None):
249
+ result = []
250
+ seq_len = x.shape[0]
251
+ for i in range(seq_len):
252
+ hidden = self.cell(x[i], hidden)
253
+ result.append(hidden[0]) # type: ignore[index]
254
+ result_tensor = torch.stack(result, 0)
255
+ return result_tensor, hidden
256
+
257
+ @classmethod
258
+ def from_params(cls, *args, **kwargs):
259
+ cell = LSTMCell.from_params(*args, **kwargs)
260
+ layer = cls(
261
+ cell.input_size, cell.hidden_size, cell.bias, split_gates=cell.split_gates
262
+ )
263
+ layer.cell = cell
264
+ return layer
265
+
266
+
267
+ class _LSTMLayer(torch.nn.Module):
268
+ r"""A single bi-directional LSTM layer."""
269
+
270
+ def __init__(
271
+ self,
272
+ input_dim: int,
273
+ hidden_dim: int,
274
+ bias: bool = True,
275
+ batch_first: bool = False,
276
+ bidirectional: bool = False,
277
+ device=None,
278
+ dtype=None,
279
+ *,
280
+ split_gates=False,
281
+ ) -> None:
282
+ factory_kwargs = {"device": device, "dtype": dtype}
283
+ super().__init__()
284
+ self.batch_first = batch_first
285
+ self.bidirectional = bidirectional
286
+ self.layer_fw = _LSTMSingleLayer(
287
+ input_dim, hidden_dim, bias=bias, split_gates=split_gates, **factory_kwargs
288
+ )
289
+ if self.bidirectional:
290
+ self.layer_bw = _LSTMSingleLayer(
291
+ input_dim,
292
+ hidden_dim,
293
+ bias=bias,
294
+ split_gates=split_gates,
295
+ **factory_kwargs,
296
+ )
297
+
298
+ def forward(self, x: Tensor, hidden: Optional[Tuple[Tensor, Tensor]] = None):
299
+ if self.batch_first:
300
+ x = x.transpose(0, 1)
301
+ if hidden is None:
302
+ hx_fw, cx_fw = (None, None)
303
+ else:
304
+ hx_fw, cx_fw = hidden
305
+ hidden_bw: Optional[Tuple[Tensor, Tensor]] = None
306
+ if self.bidirectional:
307
+ if hx_fw is None:
308
+ hx_bw = None
309
+ else:
310
+ hx_bw = hx_fw[1]
311
+ hx_fw = hx_fw[0]
312
+ if cx_fw is None:
313
+ cx_bw = None
314
+ else:
315
+ cx_bw = cx_fw[1]
316
+ cx_fw = cx_fw[0]
317
+ if hx_bw is not None and cx_bw is not None:
318
+ hidden_bw = hx_bw, cx_bw
319
+ if hx_fw is None and cx_fw is None:
320
+ hidden_fw = None
321
+ else:
322
+ hidden_fw = torch.jit._unwrap_optional(hx_fw), torch.jit._unwrap_optional(
323
+ cx_fw
324
+ )
325
+ result_fw, hidden_fw = self.layer_fw(x, hidden_fw)
326
+
327
+ if hasattr(self, "layer_bw") and self.bidirectional:
328
+ x_reversed = x.flip(0)
329
+ result_bw, hidden_bw = self.layer_bw(x_reversed, hidden_bw)
330
+ result_bw = result_bw.flip(0)
331
+
332
+ result = torch.cat([result_fw, result_bw], result_fw.dim() - 1)
333
+ if hidden_fw is None and hidden_bw is None:
334
+ h = None
335
+ c = None
336
+ elif hidden_fw is None:
337
+ (h, c) = torch.jit._unwrap_optional(hidden_bw)
338
+ elif hidden_bw is None:
339
+ (h, c) = torch.jit._unwrap_optional(hidden_fw)
340
+ else:
341
+ h = torch.stack([hidden_fw[0], hidden_bw[0]], 0) # type: ignore[list-item]
342
+ c = torch.stack([hidden_fw[1], hidden_bw[1]], 0) # type: ignore[list-item]
343
+ else:
344
+ result = result_fw
345
+ h, c = torch.jit._unwrap_optional(hidden_fw) # type: ignore[assignment]
346
+
347
+ if self.batch_first:
348
+ result.transpose_(0, 1)
349
+
350
+ return result, (h, c)
351
+
352
+ @classmethod
353
+ def from_float(cls, other, layer_idx=0, qconfig=None, **kwargs):
354
+ r"""
355
+ There is no FP equivalent of this class. This function is here just to
356
+ mimic the behavior of the `prepare` within the `torch.ao.quantization`
357
+ flow.
358
+ """
359
+ assert hasattr(other, "qconfig") or (qconfig is not None)
360
+
361
+ input_size = kwargs.get("input_size", other.input_size)
362
+ hidden_size = kwargs.get("hidden_size", other.hidden_size)
363
+ bias = kwargs.get("bias", other.bias)
364
+ batch_first = kwargs.get("batch_first", other.batch_first)
365
+ bidirectional = kwargs.get("bidirectional", other.bidirectional)
366
+ split_gates = kwargs.get("split_gates", False)
367
+
368
+ layer = cls(
369
+ input_size,
370
+ hidden_size,
371
+ bias,
372
+ batch_first,
373
+ bidirectional,
374
+ split_gates=split_gates,
375
+ )
376
+ layer.qconfig = getattr(other, "qconfig", qconfig)
377
+ wi = getattr(other, f"weight_ih_l{layer_idx}")
378
+ wh = getattr(other, f"weight_hh_l{layer_idx}")
379
+ bi = getattr(other, f"bias_ih_l{layer_idx}", None)
380
+ bh = getattr(other, f"bias_hh_l{layer_idx}", None)
381
+
382
+ layer.layer_fw = _LSTMSingleLayer.from_params(
383
+ wi, wh, bi, bh, split_gates=split_gates
384
+ )
385
+
386
+ if other.bidirectional:
387
+ wi = getattr(other, f"weight_ih_l{layer_idx}_reverse")
388
+ wh = getattr(other, f"weight_hh_l{layer_idx}_reverse")
389
+ bi = getattr(other, f"bias_ih_l{layer_idx}_reverse", None)
390
+ bh = getattr(other, f"bias_hh_l{layer_idx}_reverse", None)
391
+ layer.layer_bw = _LSTMSingleLayer.from_params(
392
+ wi, wh, bi, bh, split_gates=split_gates
393
+ )
394
+ return layer
395
+
396
+
397
+ class LSTM(torch.nn.Module):
398
+ r"""A quantizable long short-term memory (LSTM).
399
+
400
+ For the description and the argument types, please, refer to :class:`~torch.nn.LSTM`
401
+
402
+ Attributes:
403
+ layers : instances of the `_LSTMLayer`
404
+
405
+ .. note::
406
+ To access the weights and biases, you need to access them per layer.
407
+ See examples below.
408
+
409
+ Examples::
410
+
411
+ >>> import torch.ao.nn.quantizable as nnqa
412
+ >>> rnn = nnqa.LSTM(10, 20, 2)
413
+ >>> input = torch.randn(5, 3, 10)
414
+ >>> h0 = torch.randn(2, 3, 20)
415
+ >>> c0 = torch.randn(2, 3, 20)
416
+ >>> output, (hn, cn) = rnn(input, (h0, c0))
417
+ >>> # To get the weights:
418
+ >>> # xdoctest: +SKIP
419
+ >>> print(rnn.layers[0].weight_ih)
420
+ tensor([[...]])
421
+ >>> print(rnn.layers[0].weight_hh)
422
+ AssertionError: There is no reverse path in the non-bidirectional layer
423
+ """
424
+ _FLOAT_MODULE = torch.nn.LSTM
425
+
426
+ def __init__(
427
+ self,
428
+ input_size: int,
429
+ hidden_size: int,
430
+ num_layers: int = 1,
431
+ bias: bool = True,
432
+ batch_first: bool = False,
433
+ dropout: float = 0.0,
434
+ bidirectional: bool = False,
435
+ device=None,
436
+ dtype=None,
437
+ *,
438
+ split_gates: bool = False,
439
+ ) -> None:
440
+ factory_kwargs = {"device": device, "dtype": dtype}
441
+ super().__init__()
442
+ self.input_size = input_size
443
+ self.hidden_size = hidden_size
444
+ self.num_layers = num_layers
445
+ self.bias = bias
446
+ self.batch_first = batch_first
447
+ self.dropout = float(dropout)
448
+ self.bidirectional = bidirectional
449
+ self.training = False # Default to eval mode. If we want to train, we will explicitly set to training.
450
+ num_directions = 2 if bidirectional else 1
451
+
452
+ if (
453
+ not isinstance(dropout, numbers.Number)
454
+ or not 0 <= dropout <= 1
455
+ or isinstance(dropout, bool)
456
+ ):
457
+ raise ValueError(
458
+ "dropout should be a number in range [0, 1] "
459
+ "representing the probability of an element being "
460
+ "zeroed"
461
+ )
462
+ if dropout > 0:
463
+ warnings.warn(
464
+ "dropout option for quantizable LSTM is ignored. "
465
+ "If you are training, please, use nn.LSTM version "
466
+ "followed by `prepare` step."
467
+ )
468
+ if num_layers == 1:
469
+ warnings.warn(
470
+ "dropout option adds dropout after all but last "
471
+ "recurrent layer, so non-zero dropout expects "
472
+ f"num_layers greater than 1, but got dropout={dropout} "
473
+ f"and num_layers={num_layers}"
474
+ )
475
+
476
+ layers = [
477
+ _LSTMLayer(
478
+ self.input_size,
479
+ self.hidden_size,
480
+ self.bias,
481
+ batch_first=False,
482
+ bidirectional=self.bidirectional,
483
+ split_gates=split_gates,
484
+ **factory_kwargs,
485
+ )
486
+ ]
487
+ layers.extend(
488
+ _LSTMLayer(
489
+ self.hidden_size,
490
+ self.hidden_size,
491
+ self.bias,
492
+ batch_first=False,
493
+ bidirectional=self.bidirectional,
494
+ split_gates=split_gates,
495
+ **factory_kwargs,
496
+ )
497
+ for layer in range(1, num_layers)
498
+ )
499
+ self.layers = torch.nn.ModuleList(layers)
500
+
501
+ def forward(self, x: Tensor, hidden: Optional[Tuple[Tensor, Tensor]] = None):
502
+ if self.batch_first:
503
+ x = x.transpose(0, 1)
504
+
505
+ max_batch_size = x.size(1)
506
+ num_directions = 2 if self.bidirectional else 1
507
+ if hidden is None:
508
+ zeros = torch.zeros(
509
+ num_directions,
510
+ max_batch_size,
511
+ self.hidden_size,
512
+ dtype=torch.float,
513
+ device=x.device,
514
+ )
515
+ zeros.squeeze_(0)
516
+ if x.is_quantized:
517
+ zeros = torch.quantize_per_tensor(
518
+ zeros, scale=1.0, zero_point=0, dtype=x.dtype
519
+ )
520
+ hxcx = [(zeros, zeros) for _ in range(self.num_layers)]
521
+ else:
522
+ hidden_non_opt = torch.jit._unwrap_optional(hidden)
523
+ if isinstance(hidden_non_opt[0], Tensor):
524
+ hx = hidden_non_opt[0].reshape(
525
+ self.num_layers, num_directions, max_batch_size, self.hidden_size
526
+ )
527
+ cx = hidden_non_opt[1].reshape(
528
+ self.num_layers, num_directions, max_batch_size, self.hidden_size
529
+ )
530
+ hxcx = [
531
+ (hx[idx].squeeze(0), cx[idx].squeeze(0))
532
+ for idx in range(self.num_layers)
533
+ ]
534
+ else:
535
+ hxcx = hidden_non_opt
536
+
537
+ hx_list = []
538
+ cx_list = []
539
+ for idx, layer in enumerate(self.layers):
540
+ x, (h, c) = layer(x, hxcx[idx])
541
+ hx_list.append(torch.jit._unwrap_optional(h))
542
+ cx_list.append(torch.jit._unwrap_optional(c))
543
+ hx_tensor = torch.stack(hx_list)
544
+ cx_tensor = torch.stack(cx_list)
545
+
546
+ # We are creating another dimension for bidirectional case
547
+ # need to collapse it
548
+ hx_tensor = hx_tensor.reshape(-1, hx_tensor.shape[-2], hx_tensor.shape[-1])
549
+ cx_tensor = cx_tensor.reshape(-1, cx_tensor.shape[-2], cx_tensor.shape[-1])
550
+
551
+ if self.batch_first:
552
+ x = x.transpose(0, 1)
553
+
554
+ return x, (hx_tensor, cx_tensor)
555
+
556
+ def _get_name(self):
557
+ return "QuantizableLSTM"
558
+
559
+ @classmethod
560
+ def from_float(cls, other, qconfig=None, split_gates=False):
561
+ assert isinstance(other, cls._FLOAT_MODULE)
562
+ assert hasattr(other, "qconfig") or qconfig
563
+ observed = cls(
564
+ other.input_size,
565
+ other.hidden_size,
566
+ other.num_layers,
567
+ other.bias,
568
+ other.batch_first,
569
+ other.dropout,
570
+ other.bidirectional,
571
+ split_gates=split_gates,
572
+ )
573
+ observed.qconfig = getattr(other, "qconfig", qconfig)
574
+ for idx in range(other.num_layers):
575
+ observed.layers[idx] = _LSTMLayer.from_float(
576
+ other, idx, qconfig, batch_first=False, split_gates=split_gates
577
+ )
578
+
579
+ # Prepare the model
580
+ if other.training:
581
+ observed.train()
582
+ observed = torch.ao.quantization.prepare_qat(observed, inplace=True)
583
+ else:
584
+ observed.eval()
585
+ observed = torch.ao.quantization.prepare(observed, inplace=True)
586
+ return observed
587
+
588
+ @classmethod
589
+ def from_observed(cls, other):
590
+ # The whole flow is float -> observed -> quantized
591
+ # This class does float -> observed only
592
+ raise NotImplementedError(
593
+ "It looks like you are trying to convert a "
594
+ "non-quantizable LSTM module. Please, see "
595
+ "the examples on quantizable LSTMs."
596
+ )
lib/python3.12/site-packages/torch/ao/nn/quantized/__init__.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from . import functional
2
+ from .modules import * # noqa: F403
3
+ from .modules import MaxPool2d
4
+
5
+
6
+ __all__ = [
7
+ "BatchNorm2d",
8
+ "BatchNorm3d",
9
+ "Conv1d",
10
+ "Conv2d",
11
+ "Conv3d",
12
+ "ConvTranspose1d",
13
+ "ConvTranspose2d",
14
+ "ConvTranspose3d",
15
+ "DeQuantize",
16
+ "ELU",
17
+ "Embedding",
18
+ "EmbeddingBag",
19
+ "GroupNorm",
20
+ "Hardswish",
21
+ "InstanceNorm1d",
22
+ "InstanceNorm2d",
23
+ "InstanceNorm3d",
24
+ "LayerNorm",
25
+ "LeakyReLU",
26
+ "Linear",
27
+ "LSTM",
28
+ "MultiheadAttention",
29
+ "Quantize",
30
+ "ReLU6",
31
+ "Sigmoid",
32
+ "Softmax",
33
+ "Dropout",
34
+ "PReLU",
35
+ # Wrapper modules
36
+ "FloatFunctional",
37
+ "FXFloatFunctional",
38
+ "QFunctional",
39
+ ]
lib/python3.12/site-packages/torch/ao/nn/quantized/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (693 Bytes). View file
 
lib/python3.12/site-packages/torch/ao/nn/quantized/__pycache__/functional.cpython-312.pyc ADDED
Binary file (32.2 kB). View file
 
lib/python3.12/site-packages/torch/ao/nn/quantized/dynamic/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .modules import * # noqa: F403