GitOrigin-RevId: 4ce73cfd80
tags/v1.3.0
@@ -91,6 +91,7 @@ class Function(ops.PyOpBase): | |||
Examples: | |||
.. code-block:: | |||
class Sigmoid(Function): | |||
def forward(self, x): | |||
y = 1 / (1 + F.exp(-x)) | |||
@@ -362,6 +362,9 @@ class ArrayMethodMixin(abc.ABC): | |||
@property | |||
def ndim(self): | |||
r""" | |||
Returns the number of dimensions of self :class:`~.Tensor`. | |||
""" | |||
shape = self._tuple_shape | |||
if shape is None: | |||
raise ValueError("unkown ndim") | |||
@@ -369,6 +372,10 @@ class ArrayMethodMixin(abc.ABC): | |||
@property | |||
def size(self): | |||
r""" | |||
Returns the size of the self :class:`~.Tensor`. | |||
The returned value is a subclass of :class:`tuple`. | |||
""" | |||
shape = self.shape | |||
if shape.__class__ is tuple: | |||
return np.prod(self.shape).item() | |||
@@ -376,9 +383,16 @@ class ArrayMethodMixin(abc.ABC): | |||
@property | |||
def T(self): | |||
r""" | |||
alias of :attr:`~.Tensor.transpose`. | |||
""" | |||
return self.transpose() | |||
def item(self, *args): | |||
r""" | |||
Returns the value of this :class:`~.Tensor` as a standard Python :class:`numbers.Number`. | |||
This only works for tensors with one element. For other cases, see :meth:`~.tolist`. | |||
""" | |||
if not args: | |||
if isinstance(self.size, int): | |||
assert self.size == 1 | |||
@@ -386,12 +400,26 @@ class ArrayMethodMixin(abc.ABC): | |||
return self[args].item() | |||
def tolist(self): | |||
r""" | |||
Returns the tensor as a (nested) list. | |||
For scalars, a standard Python number is returned, just like with :meth:`~.item`. | |||
Tensors are automatically moved to the CPU first if necessary. | |||
This operation is not differentiable. | |||
""" | |||
return self.numpy().tolist() | |||
def astype(self, dtype): | |||
r""" | |||
Returns a :class:`Tensor` with the same data and number of elements | |||
with the specified :attr:`~.Tensor.dtype`. | |||
""" | |||
return utils.astype(self, dtype) | |||
def reshape(self, *args): | |||
r""" | |||
See :func:`~.reshape`. | |||
""" | |||
return _reshape(self, _expand_args(args)) | |||
# FIXME: remove this method | |||
@@ -399,6 +427,9 @@ class ArrayMethodMixin(abc.ABC): | |||
return _broadcast(self, _expand_args(args)) | |||
def transpose(self, *args): | |||
r""" | |||
See :func:`~.transpose`. | |||
""" | |||
if self.ndim == 0: | |||
assert ( | |||
len(args) == 0 | |||
@@ -411,19 +442,22 @@ class ArrayMethodMixin(abc.ABC): | |||
return _transpose(self, _expand_args(args)) | |||
def flatten(self): | |||
r""" | |||
See :func:`~.flatten`. | |||
""" | |||
return self.reshape(-1) | |||
def sum(self, axis=None, keepdims: bool = False): | |||
r""" | |||
Returns the sum of each row of the input tensor in the given dimension ``axis``. | |||
If ``axis`` is a list of axises, reduce over all of them. | |||
If ``keepdims`` is ``True``, the shape of output tensor is the same as the input tensor, except in the dimension(s) ``axis`` where it is of size 1. Otherwise, ``axis`` is squeezed(see :meth:`~.functional.tensor.squeeze`). | |||
Same for prod/mean/max/min. | |||
If ``keepdims`` is ``True``, the shape of output tensor is the same as the input tensor, | |||
except in the dimension(s) ``axis`` where it is of size 1. | |||
Otherwise, ``axis`` is squeezed (see :func:`~.squeeze`). | |||
:param axis: the dimension or dimensions to reduce. | |||
:param keepdim: whether the output tensor has ndim retained or not. | |||
:param keepdims: whether the output tensor has ndim retained or not. | |||
:return: output tensor. | |||
Examples: | |||
@@ -441,12 +475,139 @@ class ArrayMethodMixin(abc.ABC): | |||
.. testoutput:: | |||
2 | |||
10. | |||
10.0 | |||
""" | |||
return _reduce("SUM")(self, axis, keepdims) | |||
prod = _reduce("PRODUCT") | |||
min = _reduce("MIN") | |||
max = _reduce("MAX") | |||
mean = _reduce("MEAN") | |||
def prod(self, axis=None, keepdims: bool = False): | |||
r""" | |||
Returns the product of each row of the input tensor in the given dimension ``axis``. | |||
If ``axis`` is a list of axises, reduce over all of them. | |||
If ``keepdims`` is ``True``, the shape of output tensor is the same as the input tensor, | |||
except in the dimension(s) ``axis`` where it is of size 1. | |||
Otherwise, ``axis`` is squeezed (see :func:`~.squeeze`). | |||
:param axis: the dimension or dimensions to reduce. | |||
:param keepdims: whether the output tensor has ndim retained or not. | |||
:return: output tensor. | |||
Examples: | |||
.. testcode:: | |||
from megengine import tensor | |||
a = tensor([False, True, True, False]) | |||
b = tensor([1.0, 2.0, 3.0, 4.0]) | |||
print(a.prod().numpy()) | |||
print(b.prod().numpy()) | |||
Outputs: | |||
.. testoutput:: | |||
0 | |||
24.0 | |||
""" | |||
return _reduce("PRODUCT")(self, axis, keepdims) | |||
def min(self, axis=None, keepdims: bool = False): | |||
r""" | |||
Returns the min value of each row of the input tensor in the given dimension ``axis``. | |||
If ``axis`` is a list of axises, reduce over all of them. | |||
If ``keepdims`` is ``True``, the shape of output tensor is the same as the input tensor, | |||
except in the dimension(s) ``axis`` where it is of size 1. | |||
Otherwise, ``axis`` is squeezed (see :func:`~.squeeze`). | |||
:param axis: the dimension or dimensions to reduce. | |||
:param keepdims: whether the output tensor has ndim retained or not. | |||
:return: output tensor. | |||
Examples: | |||
.. testcode:: | |||
from megengine import tensor | |||
a = tensor([False, True, True, False]) | |||
b = tensor([1.0, 2.0, 3.0, 4.0]) | |||
print(a.min().numpy()) | |||
print(b.min().numpy()) | |||
Outputs: | |||
.. testoutput:: | |||
False | |||
1.0 | |||
""" | |||
return _reduce("MIN")(self, axis, keepdims) | |||
def max(self, axis=None, keepdims: bool = False): | |||
r""" | |||
Returns the max value of each row of the input tensor in the given dimension ``axis``. | |||
If ``axis`` is a list of axises, reduce over all of them. | |||
If ``keepdims`` is ``True``, the shape of output tensor is the same as the input tensor, | |||
except in the dimension(s) ``axis`` where it is of size 1. | |||
Otherwise, ``axis`` is squeezed (see :func:`~.squeeze`). | |||
:param axis: the dimension or dimensions to reduce. | |||
:param keepdims: whether the output tensor has ndim retained or not. | |||
:return: output tensor. | |||
Examples: | |||
.. testcode:: | |||
from megengine import tensor | |||
a = tensor([False, True, True, False]) | |||
b = tensor([1.0, 2.0, 3.0, 4.0]) | |||
print(a.max().numpy()) | |||
print(b.max().numpy()) | |||
Outputs: | |||
.. testoutput:: | |||
True | |||
4.0 | |||
""" | |||
return _reduce("MAX")(self, axis, keepdims) | |||
def mean(self, axis=None, keepdims: bool = False): | |||
r""" | |||
Returns the mean value of each row of the input tensor in the given dimension ``axis``. | |||
If ``axis`` is a list of axises, reduce over all of them. | |||
If ``keepdims`` is ``True``, the shape of output tensor is the same as the input tensor, | |||
except in the dimension(s) ``axis`` where it is of size 1. | |||
Otherwise, ``axis`` is squeezed (see :func:`~.squeeze`). | |||
:param axis: the dimension or dimensions to reduce. | |||
:param keepdims: whether the output tensor has ndim retained or not. | |||
:return: output tensor. | |||
Examples: | |||
.. testcode:: | |||
from megengine import tensor | |||
a = tensor([False, True, True, False]) | |||
b = tensor([1.0, 2.0, 3.0, 4.0]) | |||
print(a.mean().numpy()) | |||
print(b.mean().numpy()) | |||
Outputs: | |||
.. testoutput:: | |||
0.5 | |||
2.5 | |||
""" | |||
return _reduce("MEAN")(self, axis, keepdims) |
@@ -42,6 +42,9 @@ def raise_timeout_error(): | |||
class DataLoader: | |||
r""" | |||
Provides a convenient way to iterate on a given dataset. | |||
""" | |||
__initialized = False | |||
def __init__( | |||
@@ -56,8 +59,6 @@ class DataLoader: | |||
divide: bool = False, | |||
): | |||
r""" | |||
Provides a convenient way to iterate on a given dataset. | |||
`DataLoader` combines a dataset with `sampler`, `transform` and `collator`, | |||
make it flexible to get minibatch continually from a dataset. | |||
@@ -87,7 +88,6 @@ class DataLoader: | |||
different sub-process will process different batch. Default: False | |||
""" | |||
if num_workers < 0: | |||
raise ValueError("num_workers should not be negative") | |||
@@ -12,7 +12,8 @@ from typing import Tuple | |||
class Dataset(ABC): | |||
r""" | |||
An abstract class for all datasets. | |||
An abstract base class for all datasets. | |||
__getitem__ and __len__ method are aditionally needed. | |||
""" | |||
@@ -32,6 +33,7 @@ class Dataset(ABC): | |||
class StreamDataset(Dataset): | |||
r""" | |||
An abstract class for stream data. | |||
__iter__ method is aditionally needed. | |||
""" | |||
@@ -51,12 +53,14 @@ class StreamDataset(Dataset): | |||
class ArrayDataset(Dataset): | |||
r""" | |||
ArrayDataset is a dataset for numpy array data. | |||
One or more numpy arrays are needed to initiate the dataset. | |||
And the dimensions represented sample number are expected to be the same. | |||
""" | |||
def __init__(self, *arrays): | |||
r""" | |||
ArrayDataset is a dataset for numpy array data, one or more numpy arrays | |||
are needed to initiate the dataset. And the dimensions represented sample number | |||
are expected to be the same. | |||
""" | |||
super().__init__() | |||
if not all(len(arrays[0]) == len(array) for array in arrays): | |||
raise ValueError("lengths of input arrays are inconsistent") | |||
@@ -21,7 +21,7 @@ logger = get_logger(__name__) | |||
class CIFAR10(VisionDataset): | |||
r""" ``Dataset`` for CIFAR10 meta data. | |||
r""" :class:`~.Dataset` for CIFAR10 meta data. | |||
""" | |||
url_path = "http://www.cs.utoronto.ca/~kriz/" | |||
@@ -138,6 +138,9 @@ class CIFAR10(VisionDataset): | |||
class CIFAR100(CIFAR10): | |||
r""" :class:`~.Dataset` for CIFAR100 meta data. | |||
""" | |||
url_path = "http://www.cs.utoronto.ca/~kriz/" | |||
raw_file_name = "cifar-100-python.tar.gz" | |||
raw_file_md5 = "eb9058c3a382ffc7106e4002c42a8d85" | |||
@@ -26,24 +26,25 @@ from .utils import is_img | |||
class ImageFolder(VisionDataset): | |||
def __init__(self, root: str, check_valid_func=None, class_name: bool = False): | |||
r""" | |||
ImageFolder is a class for loading image data and labels from a organized folder. | |||
r""" | |||
ImageFolder is a class for loading image data and labels from a organized folder. | |||
The folder is expected to be organized as followed: root/cls/xxx.img_ext | |||
The folder is expected to be organized as followed: root/cls/xxx.img_ext | |||
Labels are indices of sorted classes in the root directory. | |||
Labels are indices of sorted classes in the root directory. | |||
:param root: root directory of an image folder. | |||
:param loader: a function used to load image from path, | |||
if ``None``, default function that loads | |||
images with PIL will be called. | |||
:param check_valid_func: a function used to check if files in folder are | |||
expected image files, if ``None``, default function | |||
that checks file extensions will be called. | |||
:param class_name: if ``True``, return class name instead of class index. | |||
:param root: root directory of an image folder. | |||
:param loader: a function used to load image from path, | |||
if ``None``, default function that loads | |||
images with PIL will be called. | |||
:param check_valid_func: a function used to check if files in folder are | |||
expected image files, if ``None``, default function | |||
that checks file extensions will be called. | |||
:param class_name: if ``True``, return class name instead of class index. | |||
""" | |||
""" | |||
def __init__(self, root: str, check_valid_func=None, class_name: bool = False): | |||
super().__init__(root, order=("image", "image_category")) | |||
self.root = root | |||
@@ -22,7 +22,7 @@ logger = get_logger(__name__) | |||
class MNIST(VisionDataset): | |||
r""" ``Dataset`` for MNIST meta data. | |||
r""" :class:`~.Dataset` for MNIST meta data. | |||
""" | |||
url_path = "http://yann.lecun.com/exdb/mnist/" | |||
@@ -18,7 +18,7 @@ import megengine.distributed as dist | |||
class Sampler(ABC): | |||
r""" | |||
An abstract class for all Sampler | |||
An abstract base class for all Sampler | |||
""" | |||
@abstractmethod | |||
@@ -27,6 +27,28 @@ class Sampler(ABC): | |||
class MapSampler(Sampler): | |||
r""" | |||
Sampler for map dataset. | |||
:type dataset: `dataset` | |||
:param dataset: dataset to sample from. | |||
:type batch_size: positive integer | |||
:param batch_size: batch size for batch method. | |||
:type drop_last: bool | |||
:param drop_last: set ``True`` to drop the last incomplete batch, | |||
if the dataset size is not divisible by the batch size. If ``False`` and | |||
the size of dataset is not divisible by the batch_size, then the last batch will | |||
be smaller. Default: False | |||
:type num_samples: positive integer | |||
:param num_samples: number of samples assigned to one rank. | |||
:type world_size: positive integer | |||
:param world_size: number of ranks. | |||
:type rank: non-negative integer within 0 and world_size | |||
:param rank: rank id, non-negative interger within 0 and ``world_size``. | |||
:type seed: non-negative integer | |||
:param seed: seed for random operators. | |||
""" | |||
def __init__( | |||
self, | |||
dataset, | |||
@@ -37,27 +59,6 @@ class MapSampler(Sampler): | |||
rank=None, | |||
seed=None, | |||
): | |||
r""" | |||
An abstract class for all sampler. | |||
:type dataset: `dataset` | |||
:param dataset: dataset to sample from. | |||
:type batch_size: positive integer | |||
:param batch_size: batch size for batch method. | |||
:type drop_last: bool | |||
:param drop_last: set ``True`` to drop the last incomplete batch, | |||
if the dataset size is not divisible by the batch size. If ``False`` and | |||
the size of dataset is not divisible by the batch_size, then the last batch will | |||
be smaller. Default: False | |||
:type num_samples: positive integer | |||
:param num_samples: number of samples assigned to one rank. | |||
:type world_size: positive integer | |||
:param world_size: number of ranks. | |||
:type rank: non-negative integer within 0 and world_size | |||
:param rank: rank id, non-negative interger within 0 and ``world_size``. | |||
:type seed: non-negative integer | |||
:param seed: seed for random operators. | |||
""" | |||
if ( | |||
not isinstance(batch_size, int) | |||
or isinstance(batch_size, bool) | |||
@@ -156,7 +157,7 @@ class MapSampler(Sampler): | |||
class StreamSampler(Sampler): | |||
""" | |||
r""" | |||
Sampler for stream dataset. | |||
.. warning:: | |||
@@ -181,6 +182,10 @@ class StreamSampler(Sampler): | |||
class SequentialSampler(MapSampler): | |||
r""" | |||
Sample elements sequentially. | |||
""" | |||
def __init__( | |||
self, | |||
dataset, | |||
@@ -190,9 +195,6 @@ class SequentialSampler(MapSampler): | |||
world_size=None, | |||
rank=None, | |||
): | |||
r""" | |||
Sample elements sequentially. | |||
""" | |||
super().__init__(dataset, batch_size, drop_last, None, world_size, rank) | |||
if indices is not None and not isinstance(indices, collections.abc.Sequence): | |||
raise ValueError( | |||
@@ -212,6 +214,10 @@ class SequentialSampler(MapSampler): | |||
class RandomSampler(MapSampler): | |||
r""" | |||
Sample elements randomly without replacement. | |||
""" | |||
def __init__( | |||
self, | |||
dataset, | |||
@@ -222,9 +228,6 @@ class RandomSampler(MapSampler): | |||
rank=None, | |||
seed=None, | |||
): | |||
r""" | |||
Sample elements randomly without replacement. | |||
""" | |||
super().__init__(dataset, batch_size, drop_last, None, world_size, rank, seed) | |||
if indices is not None and not isinstance(indices, collections.abc.Sequence): | |||
raise ValueError( | |||
@@ -241,6 +244,13 @@ class RandomSampler(MapSampler): | |||
class ReplacementSampler(MapSampler): | |||
r""" | |||
Sample elements randomly with replacement. | |||
:type weights: List | |||
:param weights: weights for sampling indices, it could be unnormalized weights. | |||
""" | |||
def __init__( | |||
self, | |||
dataset, | |||
@@ -252,12 +262,6 @@ class ReplacementSampler(MapSampler): | |||
rank=None, | |||
seed=None, | |||
): | |||
r""" | |||
Sample elements randomly with replacement. | |||
:type weights: List | |||
:param weights: weights for sampling indices, it could be unnormalized weights. | |||
""" | |||
super().__init__( | |||
dataset, batch_size, drop_last, num_samples, world_size, rank, seed | |||
) | |||
@@ -410,6 +410,10 @@ class Resize(VisionTransform): | |||
class ShortestEdgeResize(VisionTransform): | |||
r""" | |||
Resize the input data with specified shortset edge. | |||
""" | |||
def __init__( | |||
self, | |||
min_size, | |||
@@ -1010,6 +1014,15 @@ class ColorJitter(VisionTransform): | |||
class Lighting(VisionTransform): | |||
r""" | |||
Apply AlexNet-Style "lighting" augmentation to input data. | |||
Input images are assumed to have 'RGB' channel order. | |||
The degree of color jittering is randomly sampled via a normal distribution, | |||
with standard deviation given by the scale parameter. | |||
""" | |||
def __init__(self, scale, *, order=None): | |||
super().__init__(order) | |||
if scale < 0: | |||
@@ -8,6 +8,7 @@ | |||
# "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
from .group import ( | |||
WORLD, | |||
Group, | |||
get_backend, | |||
get_client, | |||
get_mm_server_addr, | |||
@@ -29,6 +29,17 @@ _sd = None | |||
class Group: | |||
r""" | |||
Include ranked nodes running collective communication (See :mod:`~.functional.distributed`). | |||
By default collectives operate on the default group (also called ``WORLD``) | |||
and require all processes to enter the distributed function call. | |||
:param proc_ranks: rank list of the group, the first one is root rank. | |||
""" | |||
def __init__(self, proc_ranks): | |||
if len(proc_ranks) == 0: # empty group | |||
self.proc_ranks = None | |||
@@ -108,7 +108,7 @@ def conv2d( | |||
""" | |||
2D convolution operation. | |||
Refer to :class:`~.Conv2d` for more information. | |||
Refer to :class:`~.module.Conv2d` for more information. | |||
:param inp: feature map of the convolution operation. | |||
:param weight: convolution kernel. | |||
@@ -1046,9 +1046,9 @@ def warp_affine( | |||
.. note:: | |||
Here all available options for params are listed, | |||
however it does not mean that you can use all the combinations. | |||
On different platforms, different combinations are supported. | |||
Here all available options for params are listed, | |||
however it does not mean that you can use all the combinations. | |||
On different platforms, different combinations are supported. | |||
""" | |||
op = builtin.WarpAffine( | |||
border_mode=border_mode, border_val=border_val, format=format, imode=imode | |||
@@ -1088,9 +1088,9 @@ def warp_perspective( | |||
Default: "LINEAR". Currently only support "LINEAR" mode. | |||
:return: output tensor. | |||
Note: | |||
.. note:: | |||
The transformation matrix is the inverse of that used by `cv2.warpPerspective`. | |||
The transformation matrix is the inverse of that used by `cv2.warpPerspective`. | |||
Examples: | |||
@@ -15,7 +15,7 @@ from .module import Module | |||
class BatchMatMulActivation(Module): | |||
r""" | |||
Batched MatMul with activation(only relu supported), no transpose anywhere. | |||
Batched :func:`~.matmul` with activation(only :func:`~.relu` supported), no transpose anywhere. | |||
""" | |||
def __init__( | |||
@@ -14,8 +14,8 @@ from .module import Module | |||
class Concat(Module): | |||
r""" | |||
A :class:`~.Module` to do functional concat. Could be replaced with :class:`~.QATModule` | |||
version :class:`~.qat.concat.Concat` using :func:`~.quantize.quantize_qat`. | |||
A :class:`~.Module` to do functional :func:`~.concat`. Could be replaced with :class:`~.QATModule` | |||
version :class:`~.qat.Concat` using :func:`~.quantize.quantize_qat`. | |||
""" | |||
def forward(self, inps: Iterable[Tensor], axis: int = 0): | |||
@@ -100,7 +100,7 @@ class Conv1d(_ConvNd): | |||
For instance, given an input of the size :math:`(N, C_{\text{in}}, H)`, | |||
this layer generates an output of the size | |||
:math:`(N, C_{\text{out}}, H_{\text{out}}})` through the | |||
:math:`(N, C_{\text{out}}, H_{\text{out}})` through the | |||
process described as below: | |||
.. math:: | |||
@@ -130,7 +130,7 @@ class Conv1d(_ConvNd): | |||
spatial dimensions. Only zero-padding is supported. Default: 0 | |||
:param dilation: dilation of the 1D convolution operation. Default: 1 | |||
:param groups: number of groups into which the input and output channels are divided, | |||
so as to perform a "grouped convolution". When ``groups`` is not 1, | |||
so as to perform a "grouped convolution". When ``groups`` is not 1, | |||
``in_channels`` and ``out_channels`` must be divisible by ``groups``, | |||
and there would be an extra dimension at the beginning of the weight's | |||
shape. Specifically, the shape of weight would be `(groups, | |||
@@ -290,7 +290,7 @@ class Conv2d(_ConvNd): | |||
spatial dimensions. Only zero-padding is supported. Default: 0 | |||
:param dilation: dilation of the 2D convolution operation. Default: 1 | |||
:param groups: number of groups into which the input and output channels are divided, | |||
so as to perform a "grouped convolution". When ``groups`` is not 1, | |||
so as to perform a "grouped convolution". When ``groups`` is not 1, | |||
``in_channels`` and ``out_channels`` must be divisible by ``groups``, | |||
and there would be an extra dimension at the beginning of the weight's | |||
shape. Specifically, the shape of weight would be `(groups, | |||
@@ -422,7 +422,7 @@ class ConvTranspose2d(_ConvNd): | |||
spatial dimensions. Only zero-padding is supported. Default: 0 | |||
:param dilation: dilation of the 2D convolution operation. Default: 1 | |||
:param groups: number of groups into which the input and output channels are divided, | |||
so as to perform a "grouped convolution". When ``groups`` is not 1, | |||
so as to perform a "grouped convolution". When ``groups`` is not 1, | |||
``in_channels`` and ``out_channels`` must be divisible by ``groups``, | |||
and there would be an extra dimension at the beginning of the weight's | |||
shape. Specifically, the shape of weight would be ``(groups, | |||
@@ -592,9 +592,8 @@ class LocalConv2d(Conv2d): | |||
class ConvRelu2d(Conv2d): | |||
r""" | |||
A fused :class:`~.Module` including Conv2d and relu. Could be replaced | |||
with :class:`~.QATModule` version :class:`~.qat.conv.ConvRelu2d` using | |||
:func:`~.quantize.quantize_qat`. | |||
A fused :class:`~.Module` including :class:`~.module.Conv2d` and :func:`~.relu`. | |||
Could be replaced with :class:`~.QATModule` version :class:`~.qat.ConvRelu2d` using :func:`~.quantize.quantize_qat`. | |||
""" | |||
def forward(self, inp): | |||
@@ -51,8 +51,8 @@ class _ConvBnActivation2d(Module): | |||
class ConvBn2d(_ConvBnActivation2d): | |||
r""" | |||
A fused :class:`~.Module` including Conv2d, BatchNorm2d. Could be replaced | |||
with :class:`~.QATModule` version :class:`~.qat.conv_bn.ConvBn2d` using | |||
A fused :class:`~.Module` including :class:`~.module.Conv2d` and :class:`~.module.BatchNorm2d`. | |||
Could be replaced with :class:`~.QATModule` version :class:`~.qat.ConvBn2d` using | |||
:func:`~.quantize.quantize_qat`. | |||
""" | |||
@@ -62,9 +62,8 @@ class ConvBn2d(_ConvBnActivation2d): | |||
class ConvBnRelu2d(_ConvBnActivation2d): | |||
r""" | |||
A fused :class:`~.Module` including Conv2d, BatchNorm2d and relu. Could be replaced | |||
with :class:`~.QATModule` version :class:`~.qat.conv_bn.ConvBnRelu2d` using | |||
:func:`~.quantize.quantize_qat`. | |||
A fused :class:`~.Module` including :class:`~.module.Conv2d`, :class:`~.module.BatchNorm2d` and :func:`~.relu`. | |||
Could be replaced with :class:`~.QATModule` version :class:`~.qat.ConvBnRelu2d` using :func:`~.quantize.quantize_qat`. | |||
""" | |||
def forward(self, inp): | |||
@@ -12,8 +12,8 @@ from .module import Module | |||
class Elemwise(Module): | |||
r""" | |||
A :class:`~.Module` to do elemwise operator. Could be replaced with :class:`~.QATModule` | |||
version :class:`~.qat.elemwise.Elemwise` using :func:`~.quantize.quantize_qat`. | |||
A :class:`~.Module` to do :mod:`~.functional.elemwise` operator. Could be replaced with :class:`~.QATModule` | |||
version :class:`~.qat.Elemwise` using :func:`~.quantize.quantize_qat`. | |||
:param method: the elemwise method, support the following string. | |||
It will do the normal elemwise operator for float. | |||
@@ -12,6 +12,10 @@ from .module import QATModule | |||
class BatchMatMulActivation(Float.BatchMatMulActivation, QATModule): | |||
r""" | |||
A :class:`~.QATModule` :class:`~.module.BatchMatMulActivation` with QAT support. | |||
""" | |||
def forward(self, inp): | |||
w_qat = self.apply_quant_weight(self.weight) | |||
b_qat = fake_quant_bias(self.bias, inp, w_qat) | |||
@@ -14,7 +14,7 @@ from .module import QATModule | |||
class Concat(Float.Concat, QATModule): | |||
r""" | |||
A :class:`~.QATModule` to do functional concat with QAT support. | |||
A :class:`~.QATModule` to do functional :func:`~.concat` with QAT support. | |||
Could be applied with :class:`~.Observer` and :class:`~.FakeQuantize`. | |||
""" | |||
@@ -13,7 +13,7 @@ from .module import QATModule | |||
class Conv2d(Float.Conv2d, QATModule): | |||
r""" | |||
A :class:`~.QATModule` Conv2d with QAT support. | |||
A :class:`~.QATModule` :class:`~.module.Conv2d` with QAT support. | |||
Could be applied with :class:`~.Observer` and :class:`~.FakeQuantize`. | |||
""" | |||
@@ -54,7 +54,7 @@ class Conv2d(Float.Conv2d, QATModule): | |||
class ConvRelu2d(Conv2d): | |||
r""" | |||
A :class:`~.QATModule` include Conv2d and Relu with QAT support. | |||
A :class:`~.QATModule` include :class:`~.module.Conv2d` and :func:`~.relu` with QAT support. | |||
Could be applied with :class:`~.Observer` and :class:`~.FakeQuantize`. | |||
""" | |||
@@ -164,7 +164,7 @@ class _ConvBnActivation2d(Float._ConvBnActivation2d, QATModule): | |||
class ConvBn2d(_ConvBnActivation2d): | |||
r""" | |||
A fused :class:`~.QATModule` including Conv2d, BatchNorm2d with QAT support. | |||
A fused :class:`~.QATModule` including :class:`~.module.Conv2d` and :class:`~.module.BatchNorm2d` with QAT support. | |||
Could be applied with :class:`~.Observer` and :class:`~.FakeQuantize`. | |||
""" | |||
@@ -174,7 +174,7 @@ class ConvBn2d(_ConvBnActivation2d): | |||
class ConvBnRelu2d(_ConvBnActivation2d): | |||
r""" | |||
A fused :class:`~.QATModule` including Conv2d, BatchNorm2d and relu with QAT support. | |||
A fused :class:`~.QATModule` including :class:`~.module.Conv2d`, :class:`~.module.BatchNorm2d` and :func:`~.relu` with QAT support. | |||
Could be applied with :class:`~.Observer` and :class:`~.FakeQuantize`. | |||
""" | |||
@@ -11,10 +11,10 @@ from .module import QATModule | |||
class Elemwise(Float.Elemwise, QATModule): | |||
r""" | |||
A :class:`~.QATModule` to do elemwise operator with QAT support. | |||
A :class:`~.QATModule` to do :mod:`~.functional.elemwise` operator with QAT support. | |||
Could be applied with :class:`~.Observer` and :class:`~.FakeQuantize`. | |||
:param method: the elemwise method, see :class:`~.module.elemwise.Elemwise` for detail. | |||
:param method: the elemwise method, see :class:`~.module.Elemwise` for detail. | |||
""" | |||
with_weight = False | |||
@@ -12,7 +12,7 @@ from .module import QATModule | |||
class Linear(Float.Linear, QATModule): | |||
r""" | |||
A :class:`~.QATModule` version of :class:`~.module.linear.Linear`. | |||
A :class:`~.QATModule` version of :class:`~.module.Linear`. | |||
Could be applied with :class:`~.Observer` and :class:`~.FakeQuantize`. | |||
:param in_features: size of each input sample. | |||
@@ -14,9 +14,9 @@ from ..module import Module | |||
class QATModule(Module): | |||
r""" | |||
Base class of quantized-float related Module, basically for QAT and Calibration. | |||
Base class of quantized-float related :class:`~.Module`, basically for QAT and Calibration. | |||
Use :meth:`~.QATModule.from_float_module` to generate a instance from float :class:`~.Module`. | |||
Use :meth:`from_float_module` to generate a instance from float :class:`~.Module`. | |||
Or use :func:`~.quantize.quantize_qat` to do it recursively and automatically. | |||
Can also be converted to :class:`~.QuantizedModule` for deployment using | |||
@@ -11,7 +11,7 @@ from .module import QATModule | |||
class QuantStub(Float.QuantStub, QATModule): | |||
r""" | |||
A helper QATModule simply return input, but will quantize | |||
A helper :class:`~.QATModule` simply return input, but will quantize | |||
input after converted to :class:`~.QuantizedModule`. | |||
""" | |||
@@ -31,7 +31,7 @@ class QuantStub(Float.QuantStub, QATModule): | |||
class DequantStub(Float.DequantStub, QATModule): | |||
r""" | |||
A helper QATModule simply return input, but will de-quantize | |||
A helper :class:`~.QATModule` simply return input, but will de-quantize | |||
input after converted to :class:`~.QuantizedModule`. | |||
""" | |||
@@ -19,6 +19,8 @@ from .module import QuantizedModule | |||
class BatchMatMulActivation(Float.BatchMatMulActivation, QuantizedModule): | |||
r"""Quantized version of :class:`~.qat.BatchMatMulActivation`.""" | |||
def __init__( | |||
self, | |||
batch: int, | |||
@@ -15,7 +15,7 @@ from .module import QuantizedModule | |||
class Concat(QuantizedModule): | |||
r""" | |||
A :class:`~.QuantizedModule` to do quantized concat, used for inference only. | |||
A :class:`~.QuantizedModule` to do quantized :func:`~.concat`, used for inference only. | |||
""" | |||
def __init__(self, dtype=None): | |||
@@ -18,11 +18,11 @@ from .module import QuantizedModule | |||
class Conv2d(Float.Conv2d, QuantizedModule): | |||
r"""Quantized version of :class:`~.qat.conv.Conv2d`.""" | |||
r""" | |||
r"""Quantized version of :class:`~.qat.Conv2d`. | |||
Applies a 2D convolution over a quantized input tensor, used for inference only. | |||
The parameter is same with :class: `~.Conv2d`. | |||
The parameter is same with :class:`~.module.Conv2d`. | |||
""" | |||
def __init__( | |||
@@ -102,7 +102,7 @@ class Conv2d(Float.Conv2d, QuantizedModule): | |||
class ConvRelu2d(Conv2d): | |||
r"""Quantized version of :class:`~.qat.conv.ConvRelu2d`.""" | |||
r"""Quantized version of :class:`~.qat.ConvRelu2d`.""" | |||
def forward(self, inp): | |||
return self.calc_conv_quantized(inp, nonlinear_mode="RELU") |
@@ -14,7 +14,7 @@ class _ConvBnActivation2d(Conv2d): | |||
r""" | |||
Applies a 2D convolution over a quantized input tensor, used for inference only. | |||
The parameter is same with :class: `~.Conv2d`. | |||
The parameter is same with :class: `~.module.Conv2d`. | |||
""" | |||
@classmethod | |||
@@ -44,14 +44,14 @@ class _ConvBnActivation2d(Conv2d): | |||
class ConvBn2d(_ConvBnActivation2d): | |||
r"""Quantized version of :class:`~.qat.conv_bn.ConvBn2d`.""" | |||
r"""Quantized version of :class:`~.qat.ConvBn2d`.""" | |||
def forward(self, inp): | |||
return self.calc_conv_quantized(inp, nonlinear_mode="IDENTITY") | |||
class ConvBnRelu2d(_ConvBnActivation2d): | |||
r"""Quantized version of :class:`~.qat.conv_bn.ConvBnRelu2d`.""" | |||
r"""Quantized version of :class:`~.qat.ConvBnRelu2d`.""" | |||
def forward(self, inp): | |||
return self.calc_conv_quantized(inp, nonlinear_mode="RELU") |
@@ -12,7 +12,7 @@ from .module import QuantizedModule | |||
class Elemwise(QuantizedModule): | |||
r"""Quantized version of :class:`~.qat.elemwise.Elemwise`.""" | |||
r"""Quantized version of :class:`~.qat.Elemwise`.""" | |||
def __init__(self, method, dtype=None): | |||
super().__init__() | |||
@@ -15,7 +15,7 @@ from .module import QuantizedModule | |||
class Linear(QuantizedModule): | |||
r"""Quantized version of :class:`~.qat.linear.Linear`.""" | |||
r"""Quantized version of :class:`~.qat.Linear`.""" | |||
def __init__(self, dtype: np.dtype = None): | |||
super().__init__() | |||
@@ -13,8 +13,8 @@ from ..qat import QATModule | |||
class QuantizedModule(Module): | |||
r""" | |||
Base class of quantized Module, which should be converted from QATModule | |||
and not support traning. | |||
Base class of quantized :class:`~.Module`, | |||
which should be converted from :class:`~.QATModule` and not support traning. | |||
""" | |||
def __call__(self, *inputs, **kwargs): | |||
@@ -11,7 +11,7 @@ from .module import QuantizedModule | |||
class QuantStub(QuantizedModule): | |||
r""" | |||
Quantized version of :class:`~.qat.quant_dequant.QuantStub`, | |||
Quantized version of :class:`~.qat.QuantStub`, | |||
will convert input to quantized dtype. | |||
""" | |||
@@ -33,7 +33,7 @@ class QuantStub(QuantizedModule): | |||
class DequantStub(QuantizedModule): | |||
r""" | |||
Quantized version of :class:`~.qat.quant_dequant.DequantStub`, | |||
Quantized version of :class:`~.qat.DequantStub`, | |||
will restore quantized input to float32 dtype. | |||
""" | |||
@@ -24,6 +24,10 @@ from .utils.naming import auto_naming | |||
class Tensor(_Tensor, ArrayMethodMixin): | |||
r""" | |||
A tensor object represents a multidimensional, homogeneous array of fixed-size items. | |||
""" | |||
grad = None | |||
dmap_callback = None | |||
_q_dict = None | |||
@@ -59,6 +63,20 @@ class Tensor(_Tensor, ArrayMethodMixin): | |||
@property | |||
def shape(self) -> Union[tuple, "Tensor"]: | |||
r""" | |||
Returns a :class:`tuple` or a :class:`~.Tensor` represents tensor dimensions. | |||
.. note:: | |||
The shape of a tensor was usually represented by a :class:`tuple`. | |||
But if a tensor was treated as symbolic placeholder with tracing, | |||
it's shape could also be a :class:`~.Tensor`. See :class:`~.trace` for more details. | |||
The shape property is usually used to get the current shape of a tensor, | |||
but may also be used to reshape the tensor in-place by assigning a tuple of tensor dimensions to it. | |||
As with :func:`~.reshape`, one of the new shape dimensions can be -1, | |||
in which case its value is inferred from the size of the tensor and the remaining dimensions. | |||
""" | |||
shape = super().shape | |||
if shape == () or not use_symbolic_shape(): | |||
return shape | |||
@@ -69,7 +87,17 @@ class Tensor(_Tensor, ArrayMethodMixin): | |||
return super().shape | |||
@property | |||
def device(self) -> CompNode: | |||
r""" | |||
Returns a string represents the device a :class:`~.Tensor` storaged on. | |||
""" | |||
return super().device | |||
@property | |||
def dtype(self) -> np.dtype: | |||
r""" | |||
Returns a :class:`numpy.dtype` object represents the data type of a :class:`~.Tensor`. | |||
""" | |||
return super().dtype | |||
@property | |||
@@ -79,8 +107,17 @@ class Tensor(_Tensor, ArrayMethodMixin): | |||
return self._q_dict | |||
def numpy(self) -> np.ndarray: | |||
r""" | |||
Returns self :class:`~.Tensor` as a :class:`numpy.ndarray`. | |||
""" | |||
return super().numpy() | |||
def detach(self): | |||
r""" | |||
Returns a new :class:`~.Tensor`, detached from the current graph. | |||
""" | |||
return super().detach() | |||
def _reset(self, other): | |||
super()._reset(other) | |||
@@ -113,6 +150,9 @@ class Tensor(_Tensor, ArrayMethodMixin): | |||
self *= 0 | |||
def to(self, device): | |||
r""" | |||
Copy self :class:`~.Tensor` to specified device. See :func:`~.copy` | |||
""" | |||
if isinstance(device, str) and not _valid_device(device): | |||
raise ValueError( | |||
"invalid device name {}. For the correct format of the device name, please refer to the instruction of megengine.device.set_default_device()".format( | |||