Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
MegEngine 天元
MegEngine
提交
d1be3127
MegEngine
项目概览
MegEngine 天元
/
MegEngine
接近 2 年 前同步成功
通知
414
Star
4708
Fork
583
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
MegEngine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
d1be3127
编写于
2月 02, 2021
作者:
M
Megvii Engine Team
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix(mge/quantization): fix tqt load and convert issue and observer calculate params issue
GitOrigin-RevId: f8511f72adbac3869f7bb05f3f1364329798119e
上级
30d6b4f6
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
32 addition
and
30 deletion
+32
-30
imperative/python/megengine/quantization/fake_quant.py
imperative/python/megengine/quantization/fake_quant.py
+13
-19
imperative/python/megengine/quantization/observer.py
imperative/python/megengine/quantization/observer.py
+11
-7
imperative/python/megengine/quantization/quantize.py
imperative/python/megengine/quantization/quantize.py
+4
-1
imperative/python/test/unit/quantization/test_observer.py
imperative/python/test/unit/quantization/test_observer.py
+4
-3
未找到文件。
imperative/python/megengine/quantization/fake_quant.py
浏览文件 @
d1be3127
...
@@ -6,12 +6,8 @@
...
@@ -6,12 +6,8 @@
# software distributed under the License is distributed on an
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import
math
import
math
from
typing
import
Iterable
import
numpy
as
np
from
..
import
functional
as
F
from
..
import
functional
as
F
from
..autodiff
import
Function
from
..core.tensor.dtype
import
_metadata_dict
,
get_quantized_dtype
from
..core.tensor.dtype
import
_metadata_dict
,
get_quantized_dtype
from
..module
import
Module
from
..module
import
Module
from
..tensor
import
Parameter
,
Tensor
from
..tensor
import
Parameter
,
Tensor
...
@@ -72,20 +68,10 @@ class TQT(_FakeQuantize):
...
@@ -72,20 +68,10 @@ class TQT(_FakeQuantize):
"""
"""
def
__init__
(
def
__init__
(
self
,
self
,
dtype
:
str
,
narrow_range
:
bool
=
False
,
enable
:
bool
=
True
,
**
kwargs
q_dict
,
dtype
:
str
,
narrow_range
:
bool
=
False
,
enable
:
bool
=
True
,
**
kwargs
):
):
super
().
__init__
(
dtype
,
narrow_range
,
enable
,
**
kwargs
)
super
().
__init__
(
dtype
,
narrow_range
,
enable
,
**
kwargs
)
assert
(
self
.
scale
=
Parameter
(
0.0
,
dtype
=
"float32"
)
q_dict
[
"mode"
]
==
QuantMode
.
SYMMERTIC
),
"only symmetric quantization is supported by TQT"
if
"scale"
not
in
q_dict
or
q_dict
[
"scale"
]
is
None
:
raise
AssertionError
(
"Can not get an initialized scale"
)
self
.
scale
=
Tensor
(
F
.
log
(
q_dict
[
"scale"
])
/
math
.
log
(
2
))
def
fake_quant_forward
(
self
,
inp
,
q_dict
=
None
):
def
fake_quant_forward
(
self
,
inp
,
q_dict
=
None
):
# when enable, TQT will do fakequant forward, finetune the scale
# when enable, TQT will do fakequant forward, finetune the scale
...
@@ -93,14 +79,22 @@ class TQT(_FakeQuantize):
...
@@ -93,14 +79,22 @@ class TQT(_FakeQuantize):
def
get_qparams
(
self
):
def
get_qparams
(
self
):
q_dict
=
get_qparam_dict
(
QuantMode
.
SYMMERTIC
)
q_dict
=
get_qparam_dict
(
QuantMode
.
SYMMERTIC
)
q_dict
[
"scale"
]
=
2
**
self
.
scale
q_dict
[
"scale"
]
=
2
**
self
.
scale
.
detach
()
return
q_dict
return
q_dict
def
set_qparams
(
self
,
q_dict
):
assert
(
q_dict
[
"mode"
]
==
QuantMode
.
SYMMERTIC
),
"only symmetric quantization is supported by TQT"
if
"scale"
not
in
q_dict
or
q_dict
[
"scale"
]
is
None
:
raise
AssertionError
(
"Can not get an initialized scale"
)
self
.
scale
.
_reset
(
F
.
log
(
q_dict
[
"scale"
])
/
math
.
log
(
2
))
def
get_dtype
(
self
):
def
get_dtype
(
self
):
q_dict
=
self
.
get_qparams
()
q_dict
=
self
.
get_qparams
()
scale
=
None
if
"scale"
not
in
q_dict
else
q_dict
[
"scale"
].
numpy
()
[
0
]
scale
=
None
if
"scale"
not
in
q_dict
else
q_dict
[
"scale"
].
numpy
()
zero_point
=
(
zero_point
=
(
None
if
"zero_point"
not
in
q_dict
else
q_dict
[
"zero_point"
].
numpy
()
[
0
]
None
if
"zero_point"
not
in
q_dict
else
q_dict
[
"zero_point"
].
numpy
()
)
)
return
get_quantized_dtype
(
self
.
dtype
,
scale
,
zero_point
)
return
get_quantized_dtype
(
self
.
dtype
,
scale
,
zero_point
)
...
...
imperative/python/megengine/quantization/observer.py
浏览文件 @
d1be3127
...
@@ -17,7 +17,7 @@ from ..distributed import WORLD, get_rank, is_distributed
...
@@ -17,7 +17,7 @@ from ..distributed import WORLD, get_rank, is_distributed
from
..functional.distributed
import
all_reduce_max
,
all_reduce_min
from
..functional.distributed
import
all_reduce_max
,
all_reduce_min
from
..module
import
Module
from
..module
import
Module
from
..tensor
import
Tensor
from
..tensor
import
Tensor
from
.utils
import
QuantMode
,
Round
,
get_qparam_dict
from
.utils
import
QuantMode
,
get_qparam_dict
class
Observer
(
Module
):
class
Observer
(
Module
):
...
@@ -110,7 +110,7 @@ class MinMaxObserver(Observer):
...
@@ -110,7 +110,7 @@ class MinMaxObserver(Observer):
(
max_val
-
min_val
)
/
(
self
.
qmax
-
self
.
qmin
),
self
.
scale_limit
(
max_val
-
min_val
)
/
(
self
.
qmax
-
self
.
qmin
),
self
.
scale_limit
)
)
# caculate zero_point
# caculate zero_point
q_dict
[
"zero_point"
]
=
self
.
qmin
-
Round
()((
min_val
/
q_dict
[
"scale"
])
)
q_dict
[
"zero_point"
]
=
self
.
qmin
-
F
.
round
(
min_val
/
q_dict
[
"scale"
]
)
return
q_dict
return
q_dict
...
@@ -453,12 +453,10 @@ class PassiveObserver(Observer):
...
@@ -453,12 +453,10 @@ class PassiveObserver(Observer):
This class can be set :attr:`scale` derectly.
This class can be set :attr:`scale` derectly.
"""
"""
def
__init__
(
self
,
q_dict
,
dtype
:
str
,
narrow_range
:
bool
=
False
,
**
kwargs
):
def
__init__
(
self
,
dtype
:
str
,
narrow_range
:
bool
=
False
,
**
kwargs
):
super
().
__init__
(
dtype
,
narrow_range
,
**
kwargs
)
super
().
__init__
(
dtype
,
narrow_range
,
**
kwargs
)
self
.
q_dict
=
deepcopy
(
q_dict
)
self
.
q_dict
=
None
if
"scale"
not
in
q_dict
or
q_dict
[
"scale"
]
is
None
:
self
.
orig_scale
=
None
raise
AssertionError
(
"Can not get an initialized scale"
)
self
.
orig_scale
=
q_dict
[
"scale"
].
numpy
()
@
property
@
property
def
scale
(
self
):
def
scale
(
self
):
...
@@ -472,6 +470,12 @@ class PassiveObserver(Observer):
...
@@ -472,6 +470,12 @@ class PassiveObserver(Observer):
def
get_qparams
(
self
):
def
get_qparams
(
self
):
return
self
.
q_dict
return
self
.
q_dict
def
set_qparams
(
self
,
q_dict
):
self
.
q_dict
=
deepcopy
(
q_dict
)
if
"scale"
not
in
q_dict
or
q_dict
[
"scale"
]
is
None
:
raise
AssertionError
(
"Can not get an initialized scale"
)
self
.
orig_scale
=
q_dict
[
"scale"
].
numpy
()
def
forward
(
self
,
x
):
def
forward
(
self
,
x
):
r
"""
r
"""
Just return input because :attr:`q_dict` is set by :func:`~.apply_easy_quant`.
Just return input because :attr:`q_dict` is set by :func:`~.apply_easy_quant`.
...
...
imperative/python/megengine/quantization/quantize.py
浏览文件 @
d1be3127
...
@@ -152,7 +152,10 @@ def reset_qconfig(module: Module, qconfig: QConfig, inplace: bool = True):
...
@@ -152,7 +152,10 @@ def reset_qconfig(module: Module, qconfig: QConfig, inplace: bool = True):
module
=
deepcopy
(
module
)
module
=
deepcopy
(
module
)
def
safe_call
(
func
,
q_dict
):
def
safe_call
(
func
,
q_dict
):
return
func
(
q_dict
=
q_dict
)
if
func
is
not
None
else
None
inst
=
func
()
if
func
is
not
None
else
None
if
inst
is
not
None
and
getattr
(
inst
,
"set_qparams"
,
None
)
is
not
None
:
inst
.
set_qparams
(
q_dict
)
return
inst
for
m
in
list
(
module
.
_flatten
(
predicate
=
is_qat
)):
for
m
in
list
(
module
.
_flatten
(
predicate
=
is_qat
)):
if
m
.
with_weight
:
if
m
.
with_weight
:
...
...
imperative/python/test/unit/quantization/test_observer.py
浏览文件 @
d1be3127
...
@@ -41,8 +41,8 @@ def test_exponential_moving_average_observer():
...
@@ -41,8 +41,8 @@ def test_exponential_moving_average_observer():
m
=
ExponentialMovingAverageObserver
(
momentum
=
t
)
m
=
ExponentialMovingAverageObserver
(
momentum
=
t
)
m
(
mge
.
tensor
(
x1
,
dtype
=
np
.
float32
))
m
(
mge
.
tensor
(
x1
,
dtype
=
np
.
float32
))
m
(
mge
.
tensor
(
x2
,
dtype
=
np
.
float32
))
m
(
mge
.
tensor
(
x2
,
dtype
=
np
.
float32
))
np
.
testing
.
assert_allclose
(
m
.
min_val
.
numpy
(),
expected_min
)
np
.
testing
.
assert_allclose
(
m
.
min_val
.
numpy
(),
expected_min
,
atol
=
1e-5
)
np
.
testing
.
assert_allclose
(
m
.
max_val
.
numpy
(),
expected_max
)
np
.
testing
.
assert_allclose
(
m
.
max_val
.
numpy
(),
expected_max
,
atol
=
1e-5
)
def
test_histogram_observer
():
def
test_histogram_observer
():
...
@@ -57,7 +57,8 @@ def test_histogram_observer():
...
@@ -57,7 +57,8 @@ def test_histogram_observer():
def
test_passive_observer
():
def
test_passive_observer
():
q_dict
=
{
"scale"
:
mge
.
tensor
(
1.0
)}
q_dict
=
{
"scale"
:
mge
.
tensor
(
1.0
)}
m
=
PassiveObserver
(
q_dict
,
"qint8"
)
m
=
PassiveObserver
(
"qint8"
)
m
.
set_qparams
(
q_dict
)
assert
m
.
orig_scale
==
1.0
assert
m
.
orig_scale
==
1.0
assert
m
.
scale
==
1.0
assert
m
.
scale
==
1.0
m
.
scale
=
2.0
m
.
scale
=
2.0
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录