|
|
|
@@ -12,7 +12,7 @@ |
|
|
|
# See the License for the specific language governing permissions and |
|
|
|
# limitations under the License. |
|
|
|
# ============================================================================ |
|
|
|
"""Quantization aware.""" |
|
|
|
"""Quantization aware training.""" |
|
|
|
|
|
|
|
from functools import partial |
|
|
|
import numpy as np |
|
|
|
@@ -43,6 +43,7 @@ __all__ = [ |
|
|
|
'Conv2dQuant', |
|
|
|
'DenseQuant', |
|
|
|
'ActQuant', |
|
|
|
'LeakyReLUQuant', |
|
|
|
'HSwishQuant', |
|
|
|
'HSigmoidQuant', |
|
|
|
'TensorAddQuant', |
|
|
|
@@ -349,7 +350,7 @@ class FakeQuantWithMinMax(Cell): |
|
|
|
self.maxq = Parameter(Tensor(max_array), name='quant_max', requires_grad=False) |
|
|
|
|
|
|
|
# init fake quant relative op |
|
|
|
if per_channel: |
|
|
|
if self.per_channel: |
|
|
|
quant_fun = partial(Q.FakeQuantPerChannel, channel_axis=self.channel_axis) |
|
|
|
ema_fun = partial(Q.MinMaxUpdatePerChannel, channel_axis=self.channel_axis) |
|
|
|
else: |
|
|
|
@@ -369,7 +370,7 @@ class FakeQuantWithMinMax(Cell): |
|
|
|
num_bits=self.num_bits, |
|
|
|
symmetric=self.symmetric, |
|
|
|
narrow_range=self.narrow_range, |
|
|
|
quant_delay=quant_delay) |
|
|
|
quant_delay=self.quant_delay) |
|
|
|
self.fake_quant_train = quant_fun(training=True) |
|
|
|
self.fake_quant_infer = quant_fun(training=False) |
|
|
|
|
|
|
|
@@ -832,7 +833,7 @@ class ActQuant(_QuantActivation): |
|
|
|
Tensor, with the same type and shape as the `x`. |
|
|
|
|
|
|
|
Examples: |
|
|
|
>>> act_quant = nn.ActQuant(4, 1) |
|
|
|
>>> act_quant = nn.ActQuant(nn.ReLU) |
|
|
|
>>> input_x = Tensor(np.array([[1, 2, -1], [-2, 0, -1]]), mindspore.float32) |
|
|
|
>>> result = act_quant(input_x) |
|
|
|
""" |
|
|
|
@@ -855,7 +856,7 @@ class ActQuant(_QuantActivation): |
|
|
|
symmetric=symmetric, |
|
|
|
narrow_range=narrow_range, |
|
|
|
quant_delay=quant_delay) |
|
|
|
self.act = activation() |
|
|
|
self.act = activation |
|
|
|
|
|
|
|
def construct(self, x): |
|
|
|
x = self.act(x) |
|
|
|
@@ -865,6 +866,75 @@ class ActQuant(_QuantActivation): |
|
|
|
def get_origin(self): |
|
|
|
return self.act |
|
|
|
|
|
|
|
class LeakyReLUQuant(_QuantActivation): |
|
|
|
r""" |
|
|
|
LeakyReLUQuant activation function. Add Fake Quant OP after HSwish OP. |
|
|
|
|
|
|
|
For a more Detailed overview of HSwish op. |
|
|
|
|
|
|
|
Args: |
|
|
|
activation (Cell): Activation cell class. |
|
|
|
ema_decay (float): Exponential Moving Average algorithm parameter. Default: 0.999. |
|
|
|
per_channel (bool): Quantization granularity based on layer or on channel. Default: False. |
|
|
|
num_bits (int): Quantization number bit, support 4 and 8bit. Default: 8. |
|
|
|
symmetric (bool): Quantization algorithm use symmetric or not. Default: False. |
|
|
|
narrow_range (bool): Quantization algorithm use narrow range or not. Default: False. |
|
|
|
quant_delay (int): Quantization delay parameters according by global step. Default: 0. |
|
|
|
|
|
|
|
Inputs: |
|
|
|
- **x** (Tensor) - The input of HSwishQuant. |
|
|
|
|
|
|
|
Outputs: |
|
|
|
Tensor, with the same type and shape as the `x`. |
|
|
|
|
|
|
|
Examples: |
|
|
|
>>> activation = nn.LeakyReLUQuant(nn.LeakyReLU()) |
|
|
|
>>> input = Tensor(np.array([[1, 2, 1], [-2, 0, -1]]), mindspore.float32) |
|
|
|
>>> result = activation(input) |
|
|
|
""" |
|
|
|
|
|
|
|
def __init__(self, |
|
|
|
activation, |
|
|
|
ema_decay=0.999, |
|
|
|
per_channel=False, |
|
|
|
num_bits=8, |
|
|
|
symmetric=False, |
|
|
|
narrow_range=False, |
|
|
|
quant_delay=0): |
|
|
|
super(LeakyReLUQuant, self).__init__() |
|
|
|
self.fake_quant_act_before = FakeQuantWithMinMax(min_init=-6, |
|
|
|
max_init=6, |
|
|
|
ema=True, |
|
|
|
ema_decay=ema_decay, |
|
|
|
per_channel=per_channel, |
|
|
|
num_bits=num_bits, |
|
|
|
symmetric=symmetric, |
|
|
|
narrow_range=narrow_range, |
|
|
|
quant_delay=quant_delay) |
|
|
|
self.fake_quant_act_after = FakeQuantWithMinMax(min_init=-6, |
|
|
|
max_init=6, |
|
|
|
ema=True, |
|
|
|
ema_decay=ema_decay, |
|
|
|
per_channel=per_channel, |
|
|
|
num_bits=num_bits, |
|
|
|
symmetric=symmetric, |
|
|
|
narrow_range=narrow_range, |
|
|
|
quant_delay=quant_delay) |
|
|
|
if issubclass(activation.__class__, nn.LeakyReLU): |
|
|
|
self.act = activation |
|
|
|
else: |
|
|
|
raise ValueError("Activation should be `nn.LeakyReLU`") |
|
|
|
|
|
|
|
def construct(self, x): |
|
|
|
x = self.fake_quant_act_before(x) |
|
|
|
x = self.act(x) |
|
|
|
x = self.fake_quant_act_after(x) |
|
|
|
return x |
|
|
|
|
|
|
|
def get_origin(self): |
|
|
|
return self.act |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class HSwishQuant(_QuantActivation): |
|
|
|
r""" |
|
|
|
@@ -888,9 +958,9 @@ class HSwishQuant(_QuantActivation): |
|
|
|
Tensor, with the same type and shape as the `x`. |
|
|
|
|
|
|
|
Examples: |
|
|
|
>>> hswish_quant = nn.HSwishQuant(4, 1) |
|
|
|
>>> input_x = Tensor(np.array([[1, 2, 1], [-2, 0, -1]]), mindspore.float32) |
|
|
|
>>> result = hswish_quant(input_x) |
|
|
|
>>> activation = nn.HSwishQuant(nn.HSwish()) |
|
|
|
>>> input = Tensor(np.array([[1, 2, 1], [-2, 0, -1]]), mindspore.float32) |
|
|
|
>>> result = activation(input) |
|
|
|
""" |
|
|
|
|
|
|
|
def __init__(self, |
|
|
|
@@ -920,8 +990,8 @@ class HSwishQuant(_QuantActivation): |
|
|
|
symmetric=symmetric, |
|
|
|
narrow_range=narrow_range, |
|
|
|
quant_delay=quant_delay) |
|
|
|
if issubclass(activation, nn.HSwish): |
|
|
|
self.act = activation() |
|
|
|
if issubclass(activation.__class__, nn.HSwish): |
|
|
|
self.act = activation |
|
|
|
else: |
|
|
|
raise ValueError("Activation should be `nn.HSwish`") |
|
|
|
|
|
|
|
@@ -957,9 +1027,9 @@ class HSigmoidQuant(_QuantActivation): |
|
|
|
Tensor, with the same type and shape as the `x`. |
|
|
|
|
|
|
|
Examples: |
|
|
|
>>> hsigmoid_quant = nn.HSigmoidQuant(4, 1) |
|
|
|
>>> input_x = Tensor(np.array([[1, 2, 1], [-2, 0, -1]]), mindspore.float32) |
|
|
|
>>> result = hsigmoid_quant(input_x) |
|
|
|
>>> activation = nn.HSigmoidQuant(nn.HSigmoid()) |
|
|
|
>>> input = Tensor(np.array([[1, 2, 1], [-2, 0, -1]]), mindspore.float32) |
|
|
|
>>> result = activation(input) |
|
|
|
""" |
|
|
|
|
|
|
|
def __init__(self, |
|
|
|
@@ -989,8 +1059,8 @@ class HSigmoidQuant(_QuantActivation): |
|
|
|
symmetric=symmetric, |
|
|
|
narrow_range=narrow_range, |
|
|
|
quant_delay=quant_delay) |
|
|
|
if issubclass(activation, nn.HSigmoid): |
|
|
|
self.act = activation() |
|
|
|
if issubclass(activation.__class__, nn.HSigmoid): |
|
|
|
self.act = activation |
|
|
|
else: |
|
|
|
raise ValueError("Activation should be `nn.HSigmoid`") |
|
|
|
|
|
|
|
|