Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
MegEngine 天元
MegEngine
提交
02df634d
MegEngine
项目概览
MegEngine 天元
/
MegEngine
1 年多 前同步成功
通知
403
Star
4705
Fork
582
代码
文件
提交
分支
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看板
提交
02df634d
编写于
2月 03, 2021
作者:
M
Megvii Engine Team
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix(mge/quantization): set ``q_dict`` as an instance property
GitOrigin-RevId: 2f32008aadd9d0302285fda8667f71cbfb9552b4
上级
193e77d4
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
93 addition
and
56 deletion
+93
-56
imperative/python/megengine/quantization/observer.py
imperative/python/megengine/quantization/observer.py
+1
-1
imperative/python/megengine/tensor.py
imperative/python/megengine/tensor.py
+8
-2
imperative/python/test/unit/core/test_serialization.py
imperative/python/test/unit/core/test_serialization.py
+9
-5
imperative/python/test/unit/functional/test_tensor.py
imperative/python/test/unit/functional/test_tensor.py
+16
-0
imperative/python/test/unit/module/test_module_tensor.py
imperative/python/test/unit/module/test_module_tensor.py
+1
-0
imperative/python/test/unit/quantization/test_module.py
imperative/python/test/unit/quantization/test_module.py
+47
-36
imperative/python/test/unit/quantization/test_quantize.py
imperative/python/test/unit/quantization/test_quantize.py
+11
-12
未找到文件。
imperative/python/megengine/quantization/observer.py
浏览文件 @
02df634d
...
...
@@ -467,7 +467,7 @@ class PassiveObserver(Observer):
@
scale
.
setter
def
scale
(
self
,
value
):
assert
value
>
0
self
.
q_dict
[
"scale"
]
.
set_value
(
value
)
self
.
q_dict
[
"scale"
]
[...]
=
Tensor
(
value
)
def
get_qparams
(
self
):
return
self
.
q_dict
...
...
imperative/python/megengine/tensor.py
浏览文件 @
02df634d
...
...
@@ -25,7 +25,7 @@ from .utils.deprecation import deprecated
class
Tensor
(
_Tensor
,
ArrayMethodMixin
):
grad
=
None
dmap_callback
=
None
q_dict
=
{
"mode"
:
None
,
"scale"
:
None
,
"zero_point"
:
None
}
_q_dict
=
None
def
__new__
(
cls
,
data
,
dtype
=
None
,
device
=
None
,
is_const
=
False
,
no_cache
=
False
):
if
device
is
None
:
...
...
@@ -70,6 +70,12 @@ class Tensor(_Tensor, ArrayMethodMixin):
def
dtype
(
self
)
->
np
.
dtype
:
return
super
().
dtype
@
property
def
q_dict
(
self
):
if
self
.
_q_dict
is
None
:
self
.
_q_dict
=
{
"mode"
:
None
,
"scale"
:
None
,
"zero_point"
:
None
}
return
self
.
_q_dict
def
numpy
(
self
)
->
np
.
ndarray
:
return
super
().
numpy
()
...
...
@@ -135,7 +141,7 @@ class Tensor(_Tensor, ArrayMethodMixin):
return
state
def
__setstate__
(
self
,
state
):
self
.
q_dict
=
state
.
pop
(
"qdict"
)
self
.
_
q_dict
=
state
.
pop
(
"qdict"
)
tensor
=
Tensor
...
...
imperative/python/test/unit/core/test_serialization.py
浏览文件 @
02df634d
...
...
@@ -16,11 +16,6 @@ from megengine import Parameter, Tensor
def
test_tensor_serialization
():
def
tensor_eq
(
a
,
b
):
assert
a
.
dtype
==
b
.
dtype
assert
a
.
device
==
b
.
device
np
.
testing
.
assert_equal
(
a
.
numpy
(),
b
.
numpy
())
with
TemporaryFile
()
as
f
:
data
=
np
.
random
.
randint
(
low
=
0
,
high
=
7
,
size
=
[
233
])
a
=
Tensor
(
data
,
device
=
"xpux"
,
dtype
=
np
.
int32
)
...
...
@@ -67,3 +62,12 @@ def test_tensor_serialization():
assert
"cpu0"
in
str
(
b
.
device
)
np
.
testing
.
assert_equal
(
a
.
numpy
(),
b
.
numpy
())
mge
.
set_default_device
(
device_org
)
with
TemporaryFile
()
as
f
:
a
=
Tensor
(
0
)
a
.
q_dict
[
"scale"
]
=
Tensor
(
1.0
)
pickle
.
dump
(
a
,
f
)
f
.
seek
(
0
)
b
=
pickle
.
load
(
f
)
assert
isinstance
(
b
.
q_dict
[
"scale"
],
Tensor
)
np
.
testing
.
assert_equal
(
b
.
q_dict
[
"scale"
].
numpy
(),
1.0
)
imperative/python/test/unit/functional/test_tensor.py
浏览文件 @
02df634d
...
...
@@ -379,3 +379,19 @@ def test_copy_d2h():
def
test_copy_d2d
():
copy_test
(
"gpu0"
,
"gpu1"
)
copy_test
(
"gpu0:0"
,
"gpu0:1"
)
def
test_q_dict
():
x
=
tensor
(
1
)
assert
x
.
q_dict
[
"scale"
]
is
None
x
.
q_dict
[
"scale"
]
=
tensor
(
1.0
)
y
=
tensor
(
1
)
assert
y
.
q_dict
[
"scale"
]
is
None
y
.
q_dict
[
"scale"
]
=
tensor
(
2.0
)
assert
x
.
q_dict
[
"scale"
].
numpy
()
==
1.0
assert
y
.
q_dict
[
"scale"
].
numpy
()
==
2.0
z
=
x
+
y
assert
z
.
q_dict
[
"scale"
]
is
None
imperative/python/test/unit/module/test_module_tensor.py
浏览文件 @
02df634d
...
...
@@ -17,6 +17,7 @@ from megengine import Parameter, Tensor
from
megengine.module
import
Conv2d
# TODO: delete this test after deleting set_value
def
test_set_value
():
v0
=
np
.
random
.
random
((
2
,
3
)).
astype
(
np
.
float32
)
param
=
Parameter
(
v0
)
...
...
imperative/python/test/unit/quantization/test_module.py
浏览文件 @
02df634d
from
functools
import
partial
import
numpy
as
np
import
pytest
...
...
@@ -6,17 +8,21 @@ import megengine.functional as F
import
megengine.module
as
Float
import
megengine.module.qat
as
QAT
import
megengine.module.quantized
as
Q
from
megengine
import
Parameter
,
Tensor
from
megengine.core.tensor
import
dtype
from
megengine.quantization
import
min_max_fakequant_qc
onfig
from
megengine.quantization
import
FakeQuantize
,
MinMaxObserver
,
QC
onfig
from
megengine.quantization.quantize
import
(
disable_fake_quant
,
disable_observer
,
propagate_qconfig
,
)
"""
Calculate testing scales based on ``min_max_fakequant_qconfig``
"""
min_max_fakequant_qconfig
=
QConfig
(
weight_observer
=
partial
(
MinMaxObserver
,
dtype
=
"qint8"
,
narrow_range
=
True
),
act_observer
=
partial
(
MinMaxObserver
,
dtype
=
"qint8"
,
narrow_range
=
False
),
weight_fake_quant
=
partial
(
FakeQuantize
,
dtype
=
"qint8"
,
narrow_range
=
True
),
act_fake_quant
=
partial
(
FakeQuantize
,
dtype
=
"qint8"
,
narrow_range
=
False
),
)
inp_scale
=
np
.
float32
(
np
.
random
.
rand
()
+
1
)
...
...
@@ -31,21 +37,26 @@ def quant(x, scale):
return
x
.
astype
(
inp_dtype
)
def
fake_quant
(
x
,
scale
):
def
fake_quant
(
x
,
scale
,
qmin
,
qmax
):
x
=
x
/
scale
x
=
F
.
round
(
x
)
x
=
F
.
clip
(
x
,
-
128
,
127
)
x
=
F
.
clip
(
x
,
qmin
,
qmax
)
x
=
x
*
scale
return
x
fake_quant_act
=
partial
(
fake_quant
,
qmin
=-
128
,
qmax
=
127
)
fake_quant_weight
=
partial
(
fake_quant
,
qmin
=-
127
,
qmax
=
127
)
fake_quant_bias
=
partial
(
fake_quant
,
qmin
=-
(
2
**
31
),
qmax
=
2
**
31
-
1
)
def
init_qat_net
(
net
):
if
net
.
with_weight
:
net
.
weight_observer
.
min_val
.
set_value
(
min_val
[
0
])
net
.
weight_observer
.
max_val
.
set_value
(
max_val
[
0
])
net
.
weight_observer
.
min_val
[...]
=
Tensor
(
min_val
[
0
])
net
.
weight_observer
.
max_val
[...]
=
Tensor
(
max_val
[
0
])
if
net
.
with_act
:
net
.
act_observer
.
min_val
.
set_value
(
min_val
[
1
])
net
.
act_observer
.
max_val
.
set_value
(
max_val
[
1
])
net
.
act_observer
.
min_val
[...]
=
Tensor
(
min_val
[
1
])
net
.
act_observer
.
max_val
[...]
=
Tensor
(
max_val
[
1
])
def
test_quant_stub
():
...
...
@@ -71,7 +82,7 @@ def test_quant_stub():
normal
=
normal_net
(
x
)
qat_without_fakequant
=
qat_from_float
(
x
)
fake_quant_normal
=
fake_quant
(
normal_net
(
x
),
act_scale
)
fake_quant_normal
=
fake_quant
_act
(
normal_net
(
x
),
act_scale
)
qat
=
qat_net
(
x
)
q
=
q_net
(
x
).
numpy
()
*
act_scale
np
.
testing
.
assert_allclose
(
qat_without_fakequant
,
normal
)
...
...
@@ -99,7 +110,7 @@ def test_dequant_stub():
q_net
.
eval
()
x
=
mge
.
tensor
(
np
.
random
.
normal
(
size
=
(
3
,
3
)).
astype
(
"float32"
))
x
=
fake_quant
(
x
,
inp_scale
)
x
=
fake_quant
_act
(
x
,
inp_scale
)
x
.
q_dict
[
"scale"
]
=
inp_scale
normal
=
normal_net
(
x
)
...
...
@@ -134,12 +145,12 @@ def test_elemwise(kind):
x1_scale
=
np
.
float32
(
np
.
random
.
rand
()
+
1
)
x1
=
mge
.
tensor
(
np
.
random
.
normal
(
size
=
(
3
,
3
)).
astype
(
"float32"
))
x1
=
fake_quant
(
x1
,
x1_scale
)
x1
=
fake_quant
_act
(
x1
,
x1_scale
)
x1
.
q_dict
[
"scale"
]
=
x1_scale
x2_scale
=
np
.
float32
(
np
.
random
.
rand
()
+
1
)
x2
=
mge
.
tensor
(
np
.
random
.
normal
(
size
=
(
3
,
3
)).
astype
(
"float32"
))
x2
=
fake_quant
(
x2
,
x2_scale
)
x2
=
fake_quant
_act
(
x2
,
x2_scale
)
x2
.
q_dict
[
"scale"
]
=
x2_scale
x1_int8
=
quant
(
x1
,
x1_scale
)
...
...
@@ -149,13 +160,13 @@ def test_elemwise(kind):
if
kind
in
(
"ADD"
,
"MUL"
,
"FUSE_ADD_RELU"
):
normal
=
normal_net
(
x1
,
x2
)
qat_without_fakequant
=
qat_from_float
(
x1
,
x2
)
fake_quant_normal
=
fake_quant
(
normal_net
(
x1
,
x2
),
act_scale
)
fake_quant_normal
=
fake_quant
_act
(
normal_net
(
x1
,
x2
),
act_scale
)
qat
=
qat_net
(
x1
,
x2
)
q
=
q_net
(
x1_int8
,
x2_int8
).
numpy
()
*
act_scale
else
:
normal
=
normal_net
(
x1
)
qat_without_fakequant
=
qat_from_float
(
x1
)
fake_quant_normal
=
fake_quant
(
normal_net
(
x1
),
act_scale
)
fake_quant_normal
=
fake_quant
_act
(
normal_net
(
x1
),
act_scale
)
qat
=
qat_net
(
x1
)
q
=
q_net
(
x1_int8
).
numpy
()
*
act_scale
np
.
testing
.
assert_allclose
(
qat_without_fakequant
,
normal
)
...
...
@@ -175,17 +186,17 @@ def test_linear():
init_qat_net
(
qat_net
)
x
=
mge
.
tensor
(
np
.
random
.
normal
(
size
=
(
3
,
3
)).
astype
(
"float32"
))
x
=
fake_quant
(
x
,
inp_scale
)
x
=
fake_quant
_act
(
x
,
inp_scale
)
x
.
q_dict
[
"scale"
]
=
inp_scale
x_int8
=
quant
(
x
,
inp_scale
)
weight
=
np
.
random
.
normal
(
size
=
(
3
,
3
)).
astype
(
"float32"
)
bias
=
np
.
random
.
normal
(
size
=
(
3
,)).
astype
(
"float32"
)
normal_net
.
weight
.
set_value
(
fake_quant
(
weight
,
weight_scale
)
)
normal_net
.
bias
.
set_value
(
fake_quant
(
bias
,
inp_scale
*
weight_scale
)
)
qat_net
.
weight
.
set_value
(
weight
)
qat_net
.
bias
.
set_value
(
bias
)
normal_net
.
weight
[...]
=
fake_quant_weight
(
weight
,
weight_scale
)
normal_net
.
bias
[...]
=
fake_quant_bias
(
bias
,
inp_scale
*
weight_scale
)
qat_net
.
weight
[...]
=
Parameter
(
weight
)
qat_net
.
bias
[...]
=
Parameter
(
bias
)
qat_from_float
=
QAT
.
Linear
.
from_float_module
(
normal_net
)
qat_from_float
.
eval
()
...
...
@@ -197,11 +208,11 @@ def test_linear():
normal
=
normal_net
(
x
)
qat_without_fakequant
=
qat_from_float
(
x
)
fake_quant_normal
=
fake_quant
(
normal_net
(
x
),
act_scale
)
fake_quant_normal
=
fake_quant
_act
(
normal_net
(
x
),
act_scale
)
qat
=
qat_net
(
x
)
q
=
q_net
(
x_int8
).
numpy
()
*
act_scale
np
.
testing
.
assert_allclose
(
qat_without_fakequant
,
normal
)
np
.
testing
.
assert_allclose
(
qat
,
fake_quant_normal
)
np
.
testing
.
assert_allclose
(
qat
,
fake_quant_normal
.
numpy
()
)
np
.
testing
.
assert_allclose
(
q
,
fake_quant_normal
.
numpy
())
...
...
@@ -218,7 +229,7 @@ def test_conv(module):
init_qat_net
(
qat_net
)
x
=
mge
.
tensor
(
np
.
random
.
normal
(
size
=
(
1
,
3
,
3
,
3
)).
astype
(
"float32"
))
x
=
fake_quant
(
x
,
inp_scale
)
x
=
fake_quant
_act
(
x
,
inp_scale
)
x
.
q_dict
[
"scale"
]
=
inp_scale
x_int8
=
quant
(
x
,
inp_scale
)
...
...
@@ -226,15 +237,15 @@ def test_conv(module):
weight
=
np
.
random
.
normal
(
size
=
(
3
,
3
,
3
,
3
)).
astype
(
"float32"
)
bias
=
np
.
random
.
normal
(
size
=
(
1
,
3
,
1
,
1
)).
astype
(
"float32"
)
if
module
in
(
"ConvBn2d"
,
"ConvBnRelu2d"
):
normal_net
.
conv
.
weight
.
set_value
(
fake_quant
(
weight
,
weight_scale
)
)
normal_net
.
conv
.
bias
.
set_value
(
fake_quant
(
bias
,
inp_scale
*
weight_scale
)
)
qat_net
.
conv
.
weight
.
set_value
(
weight
)
qat_net
.
conv
.
bias
.
set_value
(
bias
)
normal_net
.
conv
.
weight
[...]
=
fake_quant_weight
(
weight
,
weight_scale
)
normal_net
.
conv
.
bias
[...]
=
fake_quant_bias
(
bias
,
inp_scale
*
weight_scale
)
qat_net
.
conv
.
weight
[...]
=
Parameter
(
weight
)
qat_net
.
conv
.
bias
[...]
=
Parameter
(
bias
)
else
:
normal_net
.
weight
.
set_value
(
fake_quant
(
weight
,
weight_scale
)
)
normal_net
.
bias
.
set_value
(
fake_quant
(
bias
,
inp_scale
*
weight_scale
)
)
qat_net
.
weight
.
set_value
(
weight
)
qat_net
.
bias
.
set_value
(
bias
)
normal_net
.
weight
[...]
=
fake_quant_weight
(
weight
,
weight_scale
)
normal_net
.
bias
[...]
=
fake_quant_bias
(
bias
,
inp_scale
*
weight_scale
)
qat_net
.
weight
[...]
=
Parameter
(
weight
)
qat_net
.
bias
[...]
=
Parameter
(
bias
)
qat_from_float
=
getattr
(
QAT
,
module
).
from_float_module
(
normal_net
)
qat_from_float
.
eval
()
...
...
@@ -246,9 +257,9 @@ def test_conv(module):
normal
=
normal_net
(
x
)
qat_without_fakequant
=
qat_from_float
(
x
)
fake_quant_normal
=
fake_quant
(
normal_net
(
x
),
act_scale
)
fake_quant_normal
=
fake_quant
_act
(
normal_net
(
x
),
act_scale
)
qat
=
qat_net
(
x
)
q
=
q_net
(
x_int8
).
numpy
()
*
act_scale
np
.
testing
.
assert_allclose
(
qat_without_fakequant
,
normal
,
atol
=
1e-
6
)
np
.
testing
.
assert_allclose
(
qat
,
fake_quant_normal
)
np
.
testing
.
assert_allclose
(
q
,
fake_quant_normal
.
numpy
())
np
.
testing
.
assert_allclose
(
qat_without_fakequant
,
normal
,
atol
=
1e-
5
)
np
.
testing
.
assert_allclose
(
qat
,
fake_quant_normal
,
atol
=
act_scale
)
np
.
testing
.
assert_allclose
(
q
,
fake_quant_normal
.
numpy
()
,
atol
=
act_scale
)
imperative/python/test/unit/quantization/test_quantize.py
浏览文件 @
02df634d
...
...
@@ -8,9 +8,8 @@
import
numpy
as
np
import
pytest
from
megengine
import
functional
from
megengine
import
Parameter
,
Tensor
from
megengine
import
module
as
Float
from
megengine
import
tensor
from
megengine.module
import
qat
as
QAT
from
megengine.module
import
quantized
as
Q
from
megengine.quantization
import
(
...
...
@@ -40,7 +39,7 @@ class Net(Float.Module):
self
.
quant
=
Float
.
QuantStub
()
self
.
linear
=
Float
.
Linear
(
3
,
3
)
self
.
dequant
=
Float
.
DequantStub
()
self
.
linear
.
bias
.
set_value
(
np
.
random
.
rand
(
3
))
self
.
linear
.
bias
[...]
=
Parameter
(
np
.
random
.
rand
(
3
))
def
forward
(
self
,
x
):
x
=
self
.
quant
(
x
)
...
...
@@ -55,7 +54,7 @@ class QATNet(Float.Module):
self
.
quant
=
QAT
.
QuantStub
()
self
.
linear
=
QAT
.
Linear
(
3
,
3
)
self
.
dequant
=
QAT
.
DequantStub
()
self
.
linear
.
bias
.
set_value
(
np
.
random
.
rand
(
3
))
self
.
linear
.
bias
[...]
=
Parameter
(
np
.
random
.
rand
(
3
))
def
forward
(
self
,
x
):
x
=
self
.
quant
(
x
)
...
...
@@ -90,12 +89,12 @@ def init_qat_net():
propagate_qconfig
(
net
,
min_max_fakequant_qconfig
)
min_val
=
np
.
random
.
randint
(
-
127
,
0
,
size
=
(
3
,))
max_val
=
np
.
random
.
randint
(
1
,
127
,
size
=
(
3
,))
net
.
quant
.
act_observer
.
min_val
.
set_value
(
min_val
[
0
])
net
.
quant
.
act_observer
.
max_val
.
set_value
(
max_val
[
0
])
net
.
linear
.
weight_observer
.
min_val
.
set_value
(
min_val
[
1
])
net
.
linear
.
weight_observer
.
max_val
.
set_value
(
max_val
[
1
])
net
.
linear
.
act_observer
.
min_val
.
set_value
(
min_val
[
2
])
net
.
linear
.
act_observer
.
max_val
.
set_value
(
max_val
[
2
])
net
.
quant
.
act_observer
.
min_val
[...]
=
Parameter
(
min_val
[
0
])
net
.
quant
.
act_observer
.
max_val
[...]
=
Parameter
(
max_val
[
0
])
net
.
linear
.
weight_observer
.
min_val
[...]
=
Parameter
(
min_val
[
1
])
net
.
linear
.
weight_observer
.
max_val
[...]
=
Parameter
(
max_val
[
1
])
net
.
linear
.
act_observer
.
min_val
[...]
=
Parameter
(
min_val
[
2
])
net
.
linear
.
act_observer
.
max_val
[...]
=
Parameter
(
max_val
[
2
])
return
net
...
...
@@ -144,7 +143,7 @@ def init_observer(module, data):
def
test_enable_and_disable_all
():
x
=
t
ensor
(
np
.
random
.
randint
(
1
,
10
,
size
=
(
3
,
3
)).
astype
(
np
.
float32
))
x
=
T
ensor
(
np
.
random
.
randint
(
1
,
10
,
size
=
(
3
,
3
)).
astype
(
np
.
float32
))
net
=
Net
()
y1
=
net
(
x
).
numpy
()
net
=
quantize_qat
(
net
,
min_max_fakequant_qconfig
)
...
...
@@ -180,7 +179,7 @@ def test_quantize():
def
test_apply_easy_quant
():
qat_net
=
init_qat_net
()
data
=
t
ensor
(
np
.
random
.
rand
(
2
,
3
,
3
,
3
),
dtype
=
np
.
float32
)
data
=
T
ensor
(
np
.
random
.
rand
(
2
,
3
,
3
,
3
),
dtype
=
np
.
float32
)
eq_net
=
reset_qconfig
(
qat_net
,
passive_qconfig
,
inplace
=
False
)
apply_easy_quant
(
eq_net
,
data
,
0.9
,
1.1
,
10
)
assert
isinstance
(
eq_net
.
quant
.
act_observer
,
PassiveObserver
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录