From d077c1b2c9439e9065952817a66c2cc7e7bf1667 Mon Sep 17 00:00:00 2001 From: Jiarong Han Date: Fri, 11 Nov 2022 16:21:18 +0800 Subject: [PATCH 01/46] fix swish and prelu (#39) --- tensorlayerx/backend/ops/__init__.py | 1 + tensorlayerx/backend/ops/mindspore_nn.py | 21 +++++++++++---- tensorlayerx/backend/ops/paddle_nn.py | 25 ++++++++++++++--- tensorlayerx/backend/ops/tensorflow_nn.py | 24 ++++++++++++----- tensorlayerx/backend/ops/torch_nn.py | 22 +++++++++++---- tensorlayerx/nn/layers/activation.py | 33 +++++++---------------- 6 files changed, 82 insertions(+), 44 deletions(-) diff --git a/tensorlayerx/backend/ops/__init__.py b/tensorlayerx/backend/ops/__init__.py index e75312d..0303a92 100644 --- a/tensorlayerx/backend/ops/__init__.py +++ b/tensorlayerx/backend/ops/__init__.py @@ -210,6 +210,7 @@ from .load_backend import hardsigmoid from .load_backend import numel from .load_backend import hardswish +from .load_backend import swish # dtype from .load_backend import ( DType, float16, float32, float64, int8, int16, int32, int64, uint8, uint16, uint32, uint64, bool, complex64, diff --git a/tensorlayerx/backend/ops/mindspore_nn.py b/tensorlayerx/backend/ops/mindspore_nn.py index 865760e..8780fa6 100644 --- a/tensorlayerx/backend/ops/mindspore_nn.py +++ b/tensorlayerx/backend/ops/mindspore_nn.py @@ -2485,18 +2485,24 @@ class PReLU(Cell): def __init__(self, data_format): super(PReLU, self).__init__() self.data_format = data_format + self.prelu = P.PReLU() def __call__(self, input, weight): - - prelu = P.PReLU() - v = prelu(input, F.cast(weight, input.dtype)) + if self.data_format == 'channels_last' : + input = nhwc_to_nchw(input) + v = self.prelu(input, F.cast(weight, input.dtype)) + if self.data_format == 'channels_last': + v = nchw_to_nhwc(v) return v def prelu(input, weight, data_format): - + if data_format == 'channels_last': + input = nhwc_to_nchw(input) prelu = P.PReLU() v = prelu(input, F.cast(weight, input.dtype)) + if data_format == 'channels_last': + v = nchw_to_nhwc(v) return v def hardsigmoid(input): @@ -2507,4 +2513,9 @@ def hardsigmoid(input): def hardswish(input): op = ms.ops.HSwish() - return op(input) \ No newline at end of file + return op(input) + + +def swish(input): + op = ms.ops.Sigmoid() + return op(input) * input \ No newline at end of file diff --git a/tensorlayerx/backend/ops/paddle_nn.py b/tensorlayerx/backend/ops/paddle_nn.py index 6ec096b..2f82f1e 100644 --- a/tensorlayerx/backend/ops/paddle_nn.py +++ b/tensorlayerx/backend/ops/paddle_nn.py @@ -2061,16 +2061,29 @@ def __call__(self, inputs): class PReLU(object): def __init__(self, data_format): - self.data_format, _ = preprocess_2d_format(data_format, None) + # self.data_format, _ = preprocess_2d_format(data_format, None) + self.data_format = data_format def __call__(self, input, weight): + dim = input.ndim + if dim == 3: + self.data_format, _ = preprocess_1d_format(self.data_format, None) + elif dim == 4: + self.data_format, _ = preprocess_2d_format(self.data_format, None) + elif dim == 5: + self.data_format, _ = preprocess_3d_format(self.data_format, None) return F.prelu(input, weight, data_format=self.data_format) def prelu(input, weight, data_format): - - data_format, _ = preprocess_2d_format(data_format, None) + dim = input.ndim + if dim == 3: + data_format, _ = preprocess_1d_format(data_format, None) + elif dim == 4: + data_format, _ = preprocess_2d_format(data_format, None) + elif dim == 5: + data_format, _ = preprocess_3d_format(data_format, None) return F.prelu(input, weight, data_format=data_format) def hardsigmoid(input): @@ -2079,4 +2092,8 @@ def hardsigmoid(input): def hardswish(input): - return F.hardswish(input) \ No newline at end of file + return F.hardswish(input) + +def swish(input): + + return F.swish(input) \ No newline at end of file diff --git a/tensorlayerx/backend/ops/tensorflow_nn.py b/tensorlayerx/backend/ops/tensorflow_nn.py index 76df513..fbcb93e 100644 --- a/tensorlayerx/backend/ops/tensorflow_nn.py +++ b/tensorlayerx/backend/ops/tensorflow_nn.py @@ -2906,17 +2906,25 @@ def __init__(self, data_format): self.data_format = data_format def __call__(self, input, weight): - + if self.data_format == 'channels_first': + input = nchw_to_nhwc(input) pos = tf.nn.relu(input) - neg = -tf.nn.sigmoid(weight) * tf.nn.relu(-input) - return pos + neg + neg = -weight * tf.nn.relu(-input) + output = pos + neg + if self.data_format == 'channels_first': + output = nhwc_to_nchw(output) + return output def prelu(input, weight, data_format): - + if data_format == 'channels_first': + input = nchw_to_nhwc(input) pos = tf.nn.relu(input) - neg = -tf.nn.sigmoid(weight) * tf.nn.relu(-input) - return pos + neg + neg = -weight * tf.nn.relu(-input) + output = pos + neg + if data_format == 'channels_first': + output = nhwc_to_nchw(output) + return output def hardsigmoid(input): @@ -2940,3 +2948,7 @@ def hardswish(input): return x + +def swish(input): + + return tf.sigmoid(input) * input \ No newline at end of file diff --git a/tensorlayerx/backend/ops/torch_nn.py b/tensorlayerx/backend/ops/torch_nn.py index 34b6e5b..23cc309 100644 --- a/tensorlayerx/backend/ops/torch_nn.py +++ b/tensorlayerx/backend/ops/torch_nn.py @@ -2179,13 +2179,21 @@ def __init__(self, data_format): self.data_format = data_format def __call__(self, input, weight): - # weight = weight.to(input.device) - return torch.prelu(input, weight) + if self.data_format == 'channels_last' : + input = nhwc_to_nchw(input) + output = torch.prelu(input, weight) + if self.data_format == 'channels_last': + output = nchw_to_nhwc(output) + return output def prelu(input, weight, data_format): - weight = weight.to(input.device) - return torch.prelu(input, weight) + if data_format == 'channels_last': + input = nhwc_to_nchw(input) + output = torch.prelu(input, weight) + if data_format == 'channels_last': + output = nchw_to_nhwc(output) + return output def hardsigmoid(input): @@ -2193,4 +2201,8 @@ def hardsigmoid(input): def hardswish(input): - return torch.nn.functional.hardswish(input) \ No newline at end of file + return torch.nn.functional.hardswish(input) + +def swish(input): + + return torch.sigmoid(input) * input \ No newline at end of file diff --git a/tensorlayerx/nn/layers/activation.py b/tensorlayerx/nn/layers/activation.py index 3b655a5..93ead36 100644 --- a/tensorlayerx/nn/layers/activation.py +++ b/tensorlayerx/nn/layers/activation.py @@ -46,9 +46,10 @@ def __init__( super(PRelu, self).__init__(name) self.num_parameters = num_parameters - self.init = init + self.init = tlx.initializers.constant(value=init) self.data_format = data_format - + self.build() + self._built = True logging.info("PRelu %s: num_parameters: %s" % (self.name, self.num_parameters)) def __repr__(self): @@ -59,29 +60,13 @@ def __repr__(self): s += ')' return s.format(classname=self.__class__.__name__, **self.__dict__) - def build(self, inputs_shape): - dim = len(inputs_shape) - if self.data_format == 'channels_last': - w_shape = (self.num_parameters, ) - elif self.data_format == 'channels_first': - if dim == 4: - w_shape = (1, self.num_parameters, 1, 1) - elif dim == 3: - w_shape = (1, self.num_parameters, 1) - elif dim == 5: - w_shape = (1, self.num_parameters, 1, 1, 1) - elif dim < 3: - w_shape = (self.num_parameters, ) - - self.alpha = self._get_weights("alpha", shape=w_shape, init=tlx.initializers.constant(value=self.init)) + def build(self): + + w_shape = (self.num_parameters, ) + self.alpha = self._get_weights("alpha", shape=w_shape, init=self.init) self.prelu = tlx.ops.PReLU(data_format = self.data_format) def forward(self, inputs): - if self._forward_state == False: - if self._built == False: - self.build(tlx.get_tensor_shape(inputs)) - self._built = True - self._forward_state = True output = self.prelu(inputs, self.alpha) @@ -827,11 +812,11 @@ class Swish(Module): def __init__(self): super(Swish, self).__init__() - self.sigmoid = tlx.ops.Sigmoid() + # self.sigmoid = tlx.ops.Sigmoid() self._built = True def forward(self, x): - outputs = self.sigmoid(x) * x + outputs = tlx.ops.swish(x) if not self._nodes_fixed and self._build_graph: self._add_node(x, outputs) From af2e8396179a00a745f04a1133b5f63ea060775c Mon Sep 17 00:00:00 2001 From: Jiarong Han Date: Fri, 25 Nov 2022 15:00:20 +0800 Subject: [PATCH 02/46] Update requirements_ms.txt --- requirements/requirements_ms.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/requirements_ms.txt b/requirements/requirements_ms.txt index 00457bc..8ff702b 100644 --- a/requirements/requirements_ms.txt +++ b/requirements/requirements_ms.txt @@ -1 +1 @@ -mindspore==1.6.1 \ No newline at end of file +mindspore==1.8.1 From 490ba52217cbc0227aea83d1930e2ac57dc7a738 Mon Sep 17 00:00:00 2001 From: Eric_lai Date: Fri, 16 Dec 2022 17:21:07 +0800 Subject: [PATCH 03/46] Add paddle backend ops --- tensorlayerx/backend/__init__.py | 4 ++ tensorlayerx/backend/ops/__init__.py | 6 +++ tensorlayerx/backend/ops/mindspore_backend.py | 36 +++++++++++++- tensorlayerx/backend/ops/oneflow_backend.py | 36 +++++++++++++- tensorlayerx/backend/ops/paddle_backend.py | 49 +++++++++++++++++-- .../backend/ops/tensorflow_backend.py | 37 +++++++++++++- tensorlayerx/backend/ops/torch_backend.py | 35 +++++++++++++ tensorlayerx/losses/torch_cost.py | 1 - tensorlayerx/nn/core/common.py | 3 +- tensorlayerx/optimizers/__init__.py | 3 ++ 10 files changed, 202 insertions(+), 8 deletions(-) diff --git a/tensorlayerx/backend/__init__.py b/tensorlayerx/backend/__init__.py index 508e707..ec6cbc7 100644 --- a/tensorlayerx/backend/__init__.py +++ b/tensorlayerx/backend/__init__.py @@ -18,6 +18,10 @@ from .ops import gelu from .ops import bias_add from .ops import moments +from .ops import histogram +from .ops import flatten +from .ops import index_select +from .ops import dot from .ops import ReLU from .ops import ELU diff --git a/tensorlayerx/backend/ops/__init__.py b/tensorlayerx/backend/ops/__init__.py index 0303a92..e9a2685 100644 --- a/tensorlayerx/backend/ops/__init__.py +++ b/tensorlayerx/backend/ops/__init__.py @@ -40,6 +40,11 @@ from .load_backend import rnnbase from .load_backend import layernorm from .load_backend import multiheadattention +from .load_backend import histogram +from .load_backend import flatten +from .load_backend import interpolate +from .load_backend import index_select +from .load_backend import dot from .load_backend import ReLU from .load_backend import ELU @@ -82,6 +87,7 @@ from .load_backend import TernaryConv from .load_backend import QuanConv from .load_backend import QuanConvBn +from .load_backend import Swish # load ops from .load_backend import Variable diff --git a/tensorlayerx/backend/ops/mindspore_backend.py b/tensorlayerx/backend/ops/mindspore_backend.py index 75f0417..edd2dec 100644 --- a/tensorlayerx/backend/ops/mindspore_backend.py +++ b/tensorlayerx/backend/ops/mindspore_backend.py @@ -1912,4 +1912,38 @@ def topk(input, k, dim=None, largest=True, sorted=True): def numel(input): - return ms.ops.size(input) \ No newline at end of file + return ms.ops.size(input) + + +def histogram(input, bins=100, min=0, max=0, name=None): + raise NotImplementedError + + +def flatten(x, start_axis=0, stop_axis=-1, name=None): + raise NotImplementedError + +def interpolate(x, + size=None, + scale_factor=None, + mode='nearest', + align_corners=False, + align_mode=0, + data_format='NCHW', + name=None): + raise NotImplementedError + + +def index_select(x, index, axis=0, name=None): + raise NotImplementedError + + +def dot(x, y, name=None): + raise NotImplementedError + + +class Swish(object): + def __init__(self): + pass + + def __call__(self, x): + raise NotImplementedError \ No newline at end of file diff --git a/tensorlayerx/backend/ops/oneflow_backend.py b/tensorlayerx/backend/ops/oneflow_backend.py index 7291862..452f6f7 100644 --- a/tensorlayerx/backend/ops/oneflow_backend.py +++ b/tensorlayerx/backend/ops/oneflow_backend.py @@ -1874,4 +1874,38 @@ def roll(input, shifts, dims=None): def logsoftmax(input, dim=None): - return F.log_softmax(input, dim) \ No newline at end of file + return F.log_softmax(input, dim) + +def histogram(input, bins=100, min=0, max=0, name=None): + raise NotImplementedError + + +def flatten(x, start_axis=0, stop_axis=-1, name=None): + raise NotImplementedError + + +def interpolate(x, + size=None, + scale_factor=None, + mode='nearest', + align_corners=False, + align_mode=0, + data_format='NCHW', + name=None): + raise NotImplementedError + + +def index_select(x, index, axis=0, name=None): + raise NotImplementedError + + +def dot(x, y, name=None): + raise NotImplementedError + + +class Swish(object): + def __init__(self): + pass + + def __call__(self, x): + raise NotImplementedError \ No newline at end of file diff --git a/tensorlayerx/backend/ops/paddle_backend.py b/tensorlayerx/backend/ops/paddle_backend.py index 083a14b..10a34c7 100644 --- a/tensorlayerx/backend/ops/paddle_backend.py +++ b/tensorlayerx/backend/ops/paddle_backend.py @@ -1222,8 +1222,8 @@ def linspace(start, stop, num): return pd.linspace(start, stop, num) -def slice(inputs, starts, sizes): - return pd.slice(inputs, starts=starts, ends=sizes) +def slice(inputs, axes, starts, sizes): + return pd.slice(inputs, axes=axes, starts=starts, ends=sizes) def add_n(inputs): @@ -1928,4 +1928,47 @@ def topk(input, k, dim=None, largest=True, sorted=True): def numel(input): - return paddle.numel(input) \ No newline at end of file + return paddle.numel(input) + + +def histogram(input, bins=100, min=0, max=0, name=None): + return paddle.histogram(input, bins=bins, min=min, max=max, name=name) + + +def flatten(x, start_axis=0, stop_axis=-1, name=None): + return paddle.flatten(x, start_axis=start_axis, stop_axis=stop_axis, name=name) + + +def interpolate(x, + size=None, + scale_factor=None, + mode='nearest', + align_corners=False, + align_mode=0, + data_format='NCHW', + name=None): + return paddle.nn.functional.interpolate(x, + size=size, + scale_factor=scale_factor, + mode=mode, + align_corners=align_corners, + align_mode=align_mode, + data_format=data_format, + name=name) + + +def index_select(x, index, axis=0, name=None): + return paddle.index_select(x, index, axis=axis, name=name) + + +def dot(x, y, name=None): + return paddle.dot(x, y, name=name) + + +class Swish(object): + def __init__(self): + pass + + def __call__(self, x): + return paddle.nn.functional.swish(x) + diff --git a/tensorlayerx/backend/ops/tensorflow_backend.py b/tensorlayerx/backend/ops/tensorflow_backend.py index 68f51f2..edeefc5 100644 --- a/tensorlayerx/backend/ops/tensorflow_backend.py +++ b/tensorlayerx/backend/ops/tensorflow_backend.py @@ -4100,4 +4100,39 @@ def numel(input): ''' - return tf.size(input) \ No newline at end of file + return tf.size(input) + + +def histogram(input, bins=100, min=0, max=0, name=None): + raise NotImplementedError + + +def flatten(x, start_axis=0, stop_axis=-1, name=None): + raise NotImplementedError + + +def interpolate(x, + size=None, + scale_factor=None, + mode='nearest', + align_corners=False, + align_mode=0, + data_format='NCHW', + name=None): + raise NotImplementedError + + +def index_select(x, index, axis=0, name=None): + raise NotImplementedError + + +def dot(x, y, name=None): + raise NotImplementedError + + +class Swish(object): + def __init__(self): + pass + + def __call__(self, x): + raise NotImplementedError \ No newline at end of file diff --git a/tensorlayerx/backend/ops/torch_backend.py b/tensorlayerx/backend/ops/torch_backend.py index b1353bf..453ebf2 100644 --- a/tensorlayerx/backend/ops/torch_backend.py +++ b/tensorlayerx/backend/ops/torch_backend.py @@ -1749,3 +1749,38 @@ def topk(input, k, dim=-1, largest=True, sorted=True): def numel(input): return torch.numel(input) + + +def histogram(input, bins=100, min=0, max=0, name=None): + raise NotImplementedError + + +def flatten(x, start_axis=0, stop_axis=-1, name=None): + raise NotImplementedError + + +def interpolate(x, + size=None, + scale_factor=None, + mode='nearest', + align_corners=False, + align_mode=0, + data_format='NCHW', + name=None): + raise NotImplementedError + + +def index_select(x, index, axis=0, name=None): + raise NotImplementedError + + +def dot(x, y, name=None): + raise NotImplementedError + + +class Swish(object): + def __init__(self): + pass + + def __call__(self, x): + raise NotImplementedError \ No newline at end of file diff --git a/tensorlayerx/losses/torch_cost.py b/tensorlayerx/losses/torch_cost.py index ad42df4..4e86d1e 100644 --- a/tensorlayerx/losses/torch_cost.py +++ b/tensorlayerx/losses/torch_cost.py @@ -1,7 +1,6 @@ #! /usr/bin/python # -*- coding: utf-8 -*- -from django.shortcuts import redirect import torch __all__ = [ diff --git a/tensorlayerx/nn/core/common.py b/tensorlayerx/nn/core/common.py index a34f20d..a562edf 100644 --- a/tensorlayerx/nn/core/common.py +++ b/tensorlayerx/nn/core/common.py @@ -23,7 +23,8 @@ "softplus": tlx.ops.Softplus, "tanh": tlx.ops.Tanh, "sigmoid": tlx.ops.Sigmoid, - "softmax": tlx.ops.Softmax + "softmax": tlx.ops.Softmax, + "swish": tlx.ops.Swish } _initializers_dict = { diff --git a/tensorlayerx/optimizers/__init__.py b/tensorlayerx/optimizers/__init__.py index 132d5e8..38d2acc 100644 --- a/tensorlayerx/optimizers/__init__.py +++ b/tensorlayerx/optimizers/__init__.py @@ -24,3 +24,6 @@ from .load_optimizers_backend import Lamb from .load_optimizers_backend import LARS from tensorlayerx.optimizers import lr + +__all__ = ['Adadelta', 'Adagrad', 'Adam', 'Adamax', 'Ftrl', 'Nadam', 'RMSprop', 'SGD', 'Momentum', 'Lamb', 'LARS'] + From d15dd6aded3389145c8486ef1b4d375980dfac1c Mon Sep 17 00:00:00 2001 From: Jiarong Han Date: Fri, 16 Dec 2022 17:43:32 +0800 Subject: [PATCH 04/46] add paddle backend ops (#56) --- tensorlayerx/backend/__init__.py | 4 ++ tensorlayerx/backend/ops/__init__.py | 4 ++ tensorlayerx/backend/ops/mindspore_backend.py | 23 +++++- tensorlayerx/backend/ops/oneflow_backend.py | 33 ++++++++- tensorlayerx/backend/ops/paddle_backend.py | 21 +++++- .../backend/ops/tensorflow_backend.py | 71 ++++++++++++++++++- tensorlayerx/backend/ops/torch_backend.py | 26 ++++++- 7 files changed, 171 insertions(+), 11 deletions(-) diff --git a/tensorlayerx/backend/__init__.py b/tensorlayerx/backend/__init__.py index ec6cbc7..e8032af 100644 --- a/tensorlayerx/backend/__init__.py +++ b/tensorlayerx/backend/__init__.py @@ -162,6 +162,10 @@ from .ops import hardsigmoid from .ops import hardswish from .ops import numel +from .ops import expand +from .ops import unique +from .ops import flip +from .ops import mv # dtype from .ops import ( DType, float16, float32, float64, int8, int16, int32, int64, uint8, uint16, uint32, uint64, bool, complex64, diff --git a/tensorlayerx/backend/ops/__init__.py b/tensorlayerx/backend/ops/__init__.py index e9a2685..75dc8c6 100644 --- a/tensorlayerx/backend/ops/__init__.py +++ b/tensorlayerx/backend/ops/__init__.py @@ -217,6 +217,10 @@ from .load_backend import numel from .load_backend import hardswish from .load_backend import swish +from .load_backend import expand +from .load_backend import unique +from .load_backend import flip +from .load_backend import mv # dtype from .load_backend import ( DType, float16, float32, float64, int8, int16, int32, int64, uint8, uint16, uint32, uint64, bool, complex64, diff --git a/tensorlayerx/backend/ops/mindspore_backend.py b/tensorlayerx/backend/ops/mindspore_backend.py index edd2dec..8d0fdfb 100644 --- a/tensorlayerx/backend/ops/mindspore_backend.py +++ b/tensorlayerx/backend/ops/mindspore_backend.py @@ -1431,7 +1431,7 @@ def angle(x): return convert_to_tensor(np.angle(x_np)) -def argmax(x, axis=None, dtype='int64'): +def argmax(x, axis=None, keepdim=False, dtype='int64'): return ms.numpy.argmax(x, axis=axis) @@ -1946,4 +1946,23 @@ def __init__(self): pass def __call__(self, x): - raise NotImplementedError \ No newline at end of file + raise NotImplementedError + +def expand(x, shape): + + + raise NotImplementedError + +def unique(x, return_index=False, return_inverse=False, return_counts=False, axis=None, dtype='int64'): + + raise NotImplementedError + + +def flip(x, axis): + + raise NotImplementedError + + +def mv(x, vec): + + raise NotImplementedError diff --git a/tensorlayerx/backend/ops/oneflow_backend.py b/tensorlayerx/backend/ops/oneflow_backend.py index 452f6f7..31741a3 100644 --- a/tensorlayerx/backend/ops/oneflow_backend.py +++ b/tensorlayerx/backend/ops/oneflow_backend.py @@ -1455,7 +1455,7 @@ def angle(x): return convert_to_tensor(np.angle(x_np)) -def argmax(x, axis=None, dtype='int64'): +def argmax(x, axis=None, keepdim=False, dtype='int64'): """ Returns the index with the largest value across axes of a tensor. @@ -1876,6 +1876,7 @@ def logsoftmax(input, dim=None): return F.log_softmax(input, dim) + def histogram(input, bins=100, min=0, max=0, name=None): raise NotImplementedError @@ -1908,4 +1909,32 @@ def __init__(self): pass def __call__(self, x): - raise NotImplementedError \ No newline at end of file + raise NotImplementedError + +def topk(input, k, dim=-1, largest=True, sorted=True): + + return flow.topk(input, k, dim, largest, sorted) + +def numel(input): + + return flow.numel(input) + +def expand(x, shape): + + + raise NotImplementedError + +def unique(x, return_index=False, return_inverse=False, return_counts=False, axis=None, dtype='int64'): + + raise NotImplementedError + + +def flip(x, axis): + + raise NotImplementedError + + +def mv(x, vec): + + raise NotImplementedError + diff --git a/tensorlayerx/backend/ops/paddle_backend.py b/tensorlayerx/backend/ops/paddle_backend.py index 10a34c7..36ec4a7 100644 --- a/tensorlayerx/backend/ops/paddle_backend.py +++ b/tensorlayerx/backend/ops/paddle_backend.py @@ -1458,8 +1458,8 @@ def acosh(x): return pd.log(x + pd.sqrt(pd.pow(x, 2) - 1)) -def argmax(x, axis=None, dtype='int64'): - return pd.argmax(x, axis=axis, dtype=dtype) +def argmax(x, axis=None,keepdim=False, dtype='int64'): + return pd.argmax(x, axis=axis, keepdim = keepdim, dtype=dtype) def argmin(x, axis=None, dtype='int64'): @@ -1972,3 +1972,20 @@ def __init__(self): def __call__(self, x): return paddle.nn.functional.swish(x) + +def expand(x, shape): + + return paddle.expand(x, shape) + +def unique(x, return_index=False, return_inverse=False, return_counts=False, axis=None, dtype='int64'): + + return paddle.unique(x, return_index, return_inverse, return_counts, axis, dtype) + +def flip(x, axis): + + return paddle.flip(x, axis) + +def mv(x, vec): + + return paddle.mv(x, vec) + diff --git a/tensorlayerx/backend/ops/tensorflow_backend.py b/tensorlayerx/backend/ops/tensorflow_backend.py index edeefc5..18d1210 100644 --- a/tensorlayerx/backend/ops/tensorflow_backend.py +++ b/tensorlayerx/backend/ops/tensorflow_backend.py @@ -1818,7 +1818,7 @@ def angle(x): return tf.math.angle(x) -def argmax(x, axis=None, dtype='int64'): +def argmax(x, axis=None, keepdim=False, dtype='int64'): """ Returns the index with the largest value across axes of a tensor. @@ -4103,6 +4103,7 @@ def numel(input): return tf.size(input) + def histogram(input, bins=100, min=0, max=0, name=None): raise NotImplementedError @@ -4135,4 +4136,70 @@ def __init__(self): pass def __call__(self, x): - raise NotImplementedError \ No newline at end of file + raise NotImplementedError + +def expand(x, shape): + ''' + + Parameters + ---------- + x : Tensor + The input Tensor, its data type is bool, float32, float64, int32 or int64. + shape : list|tuple|Tensor + The result shape after expanding. + + + ''' + + raise NotImplementedError + +def unique(x, return_index=False, return_inverse=False, return_counts=False, axis=None, dtype='int64'): + """ + + Parameters + ---------- + x : Tensor + The input tensor + return_index : bool + If True, also return the indices of the input tensor that result in the unique Tensor. + return_inverse : bool + If True, also return the indices for where elements in the original input ended up in the returned unique tensor. + return_counts : bool + If True, also return the counts for each unique element. + axis : int + The axis to apply unique. If None, the input will be flattened. Default: None. + dtype : str + The date type of indices or inverse tensor: int32 or int64. Default: int64. + + """ + + raise NotImplementedError + + +def flip(x, axis): + """ + + Parameters + ---------- + x : Tensor + The input tensor + axis : list|tuple|int + The axis(axes) to flip on. + + """ + raise NotImplementedError + + +def mv(x, vec): + """ + + Parameters + ---------- + x : Tensor + A tensor with shape [M,N] , The data type of the input Tensor x should be one of float32, float64. + vec : Tensor + A tensor with shape [N] , The data type of the input Tensor x should be one of float32, float64. + + + """ + pass diff --git a/tensorlayerx/backend/ops/torch_backend.py b/tensorlayerx/backend/ops/torch_backend.py index 453ebf2..61bc4bc 100644 --- a/tensorlayerx/backend/ops/torch_backend.py +++ b/tensorlayerx/backend/ops/torch_backend.py @@ -1293,8 +1293,8 @@ def angle(x): return torch.angle(x) -def argmax(x, axis=None, dtype='int64'): - return torch.argmax(x, dim=axis) +def argmax(x, axis=None, keepdim=False, dtype='int64'): + return torch.argmax(x, dim=axis, keepdim=keepdim) def argmin(x, axis=None, dtype='int64'): @@ -1751,6 +1751,7 @@ def numel(input): return torch.numel(input) + def histogram(input, bins=100, min=0, max=0, name=None): raise NotImplementedError @@ -1783,4 +1784,23 @@ def __init__(self): pass def __call__(self, x): - raise NotImplementedError \ No newline at end of file + raise NotImplementedError + +def expand(x, shape): + + return x.expand(shape) + +def unique(x, return_index=False, return_inverse=False, return_counts=False, axis=None, dtype='int64'): + + raise NotImplementedError + + +def flip(x, axis): + + return torch.flip(x, axis) + + +def mv(x, vec): + + return torch.mv(x, vec) + From b874d0f5949349257c386dafd1e169cfd5728b69 Mon Sep 17 00:00:00 2001 From: Jiarong Han Date: Fri, 23 Dec 2022 17:43:05 +0800 Subject: [PATCH 05/46] add some functions (#57) --- tensorlayerx/backend/__init__.py | 7 ++++ tensorlayerx/backend/ops/__init__.py | 7 ++++ tensorlayerx/backend/ops/mindspore_nn.py | 33 ++++++++++++++++- tensorlayerx/backend/ops/oneflow_nn.py | 44 +++++++++++++++++++++-- tensorlayerx/backend/ops/paddle_nn.py | 37 ++++++++++++++++++- tensorlayerx/backend/ops/tensorflow_nn.py | 31 +++++++++++++++- tensorlayerx/backend/ops/torch_nn.py | 32 ++++++++++++++++- tensorlayerx/losses/mindspore_cost.py | 6 ++++ tensorlayerx/losses/oneflow_cost.py | 5 +++ tensorlayerx/losses/paddle_cost.py | 7 ++++ tensorlayerx/losses/tensorflow_cost.py | 10 ++++++ tensorlayerx/losses/torch_cost.py | 7 ++++ 12 files changed, 220 insertions(+), 6 deletions(-) diff --git a/tensorlayerx/backend/__init__.py b/tensorlayerx/backend/__init__.py index e8032af..7c0ff6b 100644 --- a/tensorlayerx/backend/__init__.py +++ b/tensorlayerx/backend/__init__.py @@ -206,5 +206,12 @@ from .ops import Meshgrid from .ops import BatchToSpace from .ops import DepthToSpace +from .ops import linear +from .ops import adaptive_avg_pool1d +from .ops import adaptive_avg_pool2d +from .ops import adaptive_avg_pool3d +from .ops import adaptive_max_pool1d +from .ops import adaptive_max_pool2d +from .ops import adaptive_max_pool3d from tensorlayerx.backend import ops \ No newline at end of file diff --git a/tensorlayerx/backend/ops/__init__.py b/tensorlayerx/backend/ops/__init__.py index 75dc8c6..6211124 100644 --- a/tensorlayerx/backend/ops/__init__.py +++ b/tensorlayerx/backend/ops/__init__.py @@ -268,3 +268,10 @@ from .load_backend import ClipGradByNorm from .load_backend import ClipByGlobalNorm from .load_backend import Einsum +from .load_backend import linear +from .load_backend import adaptive_avg_pool1d +from .load_backend import adaptive_avg_pool2d +from .load_backend import adaptive_avg_pool3d +from .load_backend import adaptive_max_pool1d +from .load_backend import adaptive_max_pool2d +from .load_backend import adaptive_max_pool3d \ No newline at end of file diff --git a/tensorlayerx/backend/ops/mindspore_nn.py b/tensorlayerx/backend/ops/mindspore_nn.py index 8780fa6..ad17fd4 100644 --- a/tensorlayerx/backend/ops/mindspore_nn.py +++ b/tensorlayerx/backend/ops/mindspore_nn.py @@ -1698,6 +1698,17 @@ def __init__(self, output_size, data_format): def __call__(self, inputs): raise NotImplementedError +def adaptive_avg_pool1d(input, output_size): + + raise NotImplementedError + +def adaptive_avg_pool2d(input, output_size): + + raise NotImplementedError + +def adaptive_avg_pool3d(input, output_size): + + raise NotImplementedError class AdaptiveMaxPool1D(Cell): @@ -1768,6 +1779,18 @@ def __init__(self, output_size, data_format): def __call__(self, inputs): raise NotImplementedError +def adaptive_max_pool1d(input, output_size, return_indices = False): + + raise NotImplementedError + +def adaptive_max_pool2d(input, output_size, return_indices = False): + + raise NotImplementedError + +def adaptive_max_pool3d(input, output_size, return_indices=False): + + raise NotImplementedError + class BinaryConv2D(Cell): @@ -2518,4 +2541,12 @@ def hardswish(input): def swish(input): op = ms.ops.Sigmoid() - return op(input) * input \ No newline at end of file + return op(input) * input + +def linear(input, weight, bias = None): + matmul = P.MatMul(transpose_b=True) + output = matmul(input, weight) + if bias: + bias_add = P.BiasAdd() + output = bias_add(output, bias) + return output diff --git a/tensorlayerx/backend/ops/oneflow_nn.py b/tensorlayerx/backend/ops/oneflow_nn.py index b8e6ecf..556ee1a 100644 --- a/tensorlayerx/backend/ops/oneflow_nn.py +++ b/tensorlayerx/backend/ops/oneflow_nn.py @@ -1665,6 +1665,19 @@ def __call__(self, inputs): output = nchw_to_nhwc(output) return output +def adaptive_avg_pool1d(input, output_size): + + return F.adaptive_avg_pool1d(input, output_size) + + +def adaptive_avg_pool2d(input, output_size): + + return F.adaptive_avg_pool2d(input, output_size) + + +def adaptive_avg_pool3d(input, output_size): + + return F.adaptive_avg_pool3d(input, output_size) class AdaptiveMaxPool1D(object): @@ -1710,6 +1723,17 @@ def __call__(self, inputs): output = nchw_to_nhwc(output) return output +def adaptive_max_pool1d(input, output_size, return_indices = False): + + return F.adaptive_max_pool1d(input, output_size, return_indices) + +def adaptive_max_pool2d(input, output_size, return_indices = False): + + return F.adaptive_max_pool2d(input, output_size, return_indices) + +def adaptive_max_pool3d(input, output_size, return_indices=False): + + return F.adaptive_max_pool3d(input, output_size, return_indices) class BinaryConv2D(object): @@ -2180,5 +2204,21 @@ def __call__(self, input, weight): def prelu(input, weight, data_format): - weight = weight.to(input.device) - return F.prelu(input, weight) \ No newline at end of file + + return F.prelu(input, weight) + +def hardsigmoid(input): + + return F.hardsigmoid(input) + +def hardswish(input): + + return F.hardswish(input) + +def swish(input): + + return F.swish(input) + +def linear(input, weight, bias = None): + + return F.linear(input, weight, bias) \ No newline at end of file diff --git a/tensorlayerx/backend/ops/paddle_nn.py b/tensorlayerx/backend/ops/paddle_nn.py index 2f82f1e..bc0b917 100644 --- a/tensorlayerx/backend/ops/paddle_nn.py +++ b/tensorlayerx/backend/ops/paddle_nn.py @@ -1298,6 +1298,26 @@ def __call__(self, inputs): return F.adaptive_avg_pool3d(inputs, output_size=self.output_size, data_format=self.data_format) +def adaptive_avg_pool1d(input, output_size, data_format = 'NCL'): + data_format, _ = preprocess_1d_format(data_format, None) + + if data_format == 'NLC': + input = nhwc_to_nchw(input) + output = F.adaptive_avg_pool1d(input, output_size) + if data_format == 'NLC': + output = nchw_to_nhwc(output) + + return output + + +def adaptive_avg_pool2d(input, output_size, data_format = 'NCHW'): + data_format, _ = preprocess_2d_format(data_format, None) + return F.adaptive_avg_pool2d(input, output_size=output_size, data_format=data_format) + + +def adaptive_avg_pool3d(input, output_size, data_format = 'NCDHW'): + data_format, _ = preprocess_3d_format(data_format, None) + return F.adaptive_avg_pool3d(input, output_size, data_format=data_format) class AdaptiveMaxPool1D(object): @@ -1354,6 +1374,17 @@ def __call__(self, inputs): return output +def adaptive_max_pool1d(input, output_size, return_indices = False): + + return F.adaptive_max_pool1d(input, output_size, return_indices) + +def adaptive_max_pool2d(input, output_size, return_indices = False): + + return F.adaptive_max_pool2d(input, output_size, return_indices) + +def adaptive_max_pool3d(input, output_size, return_indices=False): + + return F.adaptive_max_pool3d(input, output_size, return_indices) class BinaryConv2D(object): @@ -2096,4 +2127,8 @@ def hardswish(input): def swish(input): - return F.swish(input) \ No newline at end of file + return F.swish(input) + +def linear(input, weight, bias = None): + + return F.linear(input, weight, bias) \ No newline at end of file diff --git a/tensorlayerx/backend/ops/tensorflow_nn.py b/tensorlayerx/backend/ops/tensorflow_nn.py index fbcb93e..01df7c7 100644 --- a/tensorlayerx/backend/ops/tensorflow_nn.py +++ b/tensorlayerx/backend/ops/tensorflow_nn.py @@ -1913,6 +1913,17 @@ def __call__(self, inputs): return outputs +def adaptive_avg_pool1d(input, output_size): + + raise NotImplementedError + +def adaptive_avg_pool2d(input, output_size): + + raise NotImplementedError + +def adaptive_avg_pool3d(input, output_size): + + raise NotImplementedError class AdaptiveMaxPool1D(object): @@ -1989,6 +2000,17 @@ def __call__(self, inputs): return outputs +def adaptive_max_pool1d(input, output_size, return_indices = False): + + raise NotImplementedError + +def adaptive_max_pool2d(input, output_size, return_indices = False): + + raise NotImplementedError + +def adaptive_max_pool3d(input, output_size, return_indices=False): + + raise NotImplementedError class BinaryConv2D(object): @@ -2951,4 +2973,11 @@ def hardswish(input): def swish(input): - return tf.sigmoid(input) * input \ No newline at end of file + return tf.sigmoid(input) * input + +def linear(input, weight, bias = None): + + output = tf.matmul(input, weight, transpose_b=True) + if bias: + output = output + bias + return output \ No newline at end of file diff --git a/tensorlayerx/backend/ops/torch_nn.py b/tensorlayerx/backend/ops/torch_nn.py index 23cc309..df770cf 100644 --- a/tensorlayerx/backend/ops/torch_nn.py +++ b/tensorlayerx/backend/ops/torch_nn.py @@ -1649,6 +1649,21 @@ def __call__(self, inputs): return output +def adaptive_avg_pool1d(input, output_size): + + return F.adaptive_avg_pool1d(input, output_size) + + +def adaptive_avg_pool2d(input, output_size): + + return F.adaptive_avg_pool2d(input, output_size) + + +def adaptive_avg_pool3d(input, output_size): + + return F.adaptive_avg_pool3d(input, output_size) + + class AdaptiveMaxPool1D(object): def __init__(self, output_size, data_format): @@ -1692,6 +1707,17 @@ def __call__(self, inputs): output = nchw_to_nhwc(output) return output +def adaptive_max_pool1d(input, output_size, return_indices = False): + + return F.adaptive_max_pool1d(input, output_size, return_indices) + +def adaptive_max_pool2d(input, output_size, return_indices = False): + + return F.adaptive_max_pool2d(input, output_size, return_indices) + +def adaptive_max_pool3d(input, output_size, return_indices=False): + + return F.adaptive_max_pool3d(input, output_size, return_indices) class BinaryConv2D(object): @@ -2205,4 +2231,8 @@ def hardswish(input): def swish(input): - return torch.sigmoid(input) * input \ No newline at end of file + return torch.sigmoid(input) * input + +def linear(input, weight, bias = None): + + return torch.nn.functional.linear(input, weight, bias) \ No newline at end of file diff --git a/tensorlayerx/losses/mindspore_cost.py b/tensorlayerx/losses/mindspore_cost.py index 52c2801..742843e 100644 --- a/tensorlayerx/losses/mindspore_cost.py +++ b/tensorlayerx/losses/mindspore_cost.py @@ -23,6 +23,7 @@ 'maxnorm_regularizer', 'maxnorm_o_regularizer', 'maxnorm_i_regularizer', + 'L1Loss' ] softmax_cross_entropy_with_logits = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean') @@ -713,3 +714,8 @@ def huber_loss( # ) # return loss raise NotImplementedError("Not Implemented.") + +def L1Loss(input, target, reduction='mean'): + + loss = nn.L1Loss(reduction=reduction) + return loss(input, target) \ No newline at end of file diff --git a/tensorlayerx/losses/oneflow_cost.py b/tensorlayerx/losses/oneflow_cost.py index d752524..734167d 100644 --- a/tensorlayerx/losses/oneflow_cost.py +++ b/tensorlayerx/losses/oneflow_cost.py @@ -20,6 +20,7 @@ 'maxnorm_regularizer', 'maxnorm_o_regularizer', 'maxnorm_i_regularizer', + 'L1Loss' ] @@ -560,3 +561,7 @@ def _cast(a, threshold, flag=False): a = flow.where(a >= threshold, one, a) a = flow.where(a < threshold, zero, a) return a + +def L1Loss(input, target, reduction='mean'): + + return flow.nn.functional.l1_loss(input, target, reduction=reduction) \ No newline at end of file diff --git a/tensorlayerx/losses/paddle_cost.py b/tensorlayerx/losses/paddle_cost.py index 19a179f..209fc3d 100644 --- a/tensorlayerx/losses/paddle_cost.py +++ b/tensorlayerx/losses/paddle_cost.py @@ -22,6 +22,7 @@ 'maxnorm_regularizer', 'maxnorm_o_regularizer', 'maxnorm_i_regularizer', + 'L1Loss' ] @@ -567,3 +568,9 @@ def huber_loss( """ raise NotImplementedError("Not Implemented.") + + +def L1Loss(input, target, reduction='mean'): + + return pd.nn.functional.l1_loss(input, target, reduction) + diff --git a/tensorlayerx/losses/tensorflow_cost.py b/tensorlayerx/losses/tensorflow_cost.py index 4fd9345..0f34df5 100644 --- a/tensorlayerx/losses/tensorflow_cost.py +++ b/tensorlayerx/losses/tensorflow_cost.py @@ -27,6 +27,7 @@ 'maxnorm_regularizer', 'maxnorm_o_regularizer', 'maxnorm_i_regularizer', + 'L1Loss' ] @@ -855,3 +856,12 @@ def huber_loss( ), name=name ) return loss + +def L1Loss(input, target, reduction='mean'): + + x = tf.abs(input-target) + if reduction == 'mean': + x = tf.reduce_mean(x) + elif reduction == 'sum': + x = tf.reduce_sum(x) + return x \ No newline at end of file diff --git a/tensorlayerx/losses/torch_cost.py b/tensorlayerx/losses/torch_cost.py index 4e86d1e..c28b0cb 100644 --- a/tensorlayerx/losses/torch_cost.py +++ b/tensorlayerx/losses/torch_cost.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- import torch +import torch.nn.functional as F __all__ = [ 'softmax_cross_entropy_with_logits', @@ -21,6 +22,7 @@ 'maxnorm_regularizer', 'maxnorm_o_regularizer', 'maxnorm_i_regularizer', + 'L1Loss' ] @@ -563,3 +565,8 @@ def _cast(a, threshold, flag=False): a = torch.where(a >= threshold, one, a) a = torch.where(a < threshold, zero, a) return a + + +def L1Loss(input, target, reduction='mean'): + + return torch.nn.functional.l1_loss(input, target, reduction=reduction) From 66c578875c77692183a6cc4800c580ba296f7fd4 Mon Sep 17 00:00:00 2001 From: Laicheng0830 Date: Wed, 28 Dec 2022 18:36:39 +0800 Subject: [PATCH 06/46] fix paddle backend --- tensorlayerx/backend/ops/paddle_nn.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tensorlayerx/backend/ops/paddle_nn.py b/tensorlayerx/backend/ops/paddle_nn.py index bc0b917..a937263 100644 --- a/tensorlayerx/backend/ops/paddle_nn.py +++ b/tensorlayerx/backend/ops/paddle_nn.py @@ -8,7 +8,7 @@ import numpy as np import paddle.fluid as fluid from paddle.nn import initializer as I -from paddle.fluid.layers.utils import map_structure, flatten, pack_sequence_as +from paddle.fluid.layers.utils import map_structure, pack_sequence_as from paddle.fluid.data_feeder import convert_dtype from paddle.fluid.dygraph import Layer, LayerList from paddle.nn.layer.rnn import RNNCellBase @@ -1509,9 +1509,9 @@ def split_states(states, bidirectional=False, state_components=1): def concat_states(states, bidirectional=False, state_components=1): if state_components == 1: - return pd.stack(flatten(states)) + return pd.stack(pd.flatten(states)) else: - states = flatten(states) + states = pd.flatten(states) componnets = [] for i in range(state_components): componnets.append(states[i::state_components]) From 9074ceadd0119f3154b075558b6fe7a8b1f41341 Mon Sep 17 00:00:00 2001 From: Cheng Lai Date: Fri, 6 Jan 2023 16:46:19 +0800 Subject: [PATCH 07/46] Fix docs (#58) --- docs/user/contributing.rst | 27 +----- docs/user/examples.rst | 92 +------------------- docs/user/installation.rst | 170 +------------------------------------ 3 files changed, 11 insertions(+), 278 deletions(-) diff --git a/docs/user/contributing.rst b/docs/user/contributing.rst index 555d483..1816c8b 100644 --- a/docs/user/contributing.rst +++ b/docs/user/contributing.rst @@ -4,10 +4,10 @@ Contributing =============== -TensorLayerx is a major ongoing research project in Peking University and Pengcheng Laboratory, the first version was established at Imperial College London in 2016. The goal of the project is to develop a compositional language that is compatible with multiple deep learning frameworks, +TensorLayerX is a major ongoing research project in Peking University and Pengcheng Laboratory, the first version was established at Imperial College London in 2016. The goal of the project is to develop a compositional language that is compatible with multiple deep learning frameworks, while complex learning systems can be built through composition of neural network modules. -Numerous contributors come from various horizons such as: Imperial College London, Tsinghua University, Carnegie Mellon University, Stanford, University of Technology of Compiegne, Google, Microsoft, Bloomberg and etc. +Numerous contributors come from various horizons such as: Peking University, Pengcheng Laboratory. You can easily open a Pull Request (PR) on `GitHub `__, every little step counts and will be credited. As an open-source project, we highly welcome and value contributions! @@ -23,7 +23,7 @@ As an open-source project, we highly welcome and value contributions! Project Maintainers -------------------------- -The TensorLayer project was started by `Hao Dong `_ at Imperial College London in June 2016. +TensorLayerX is a major ongoing research project in Peking University and Pengcheng Laboratory. For TensorLayerX, it is now actively developing and maintaining by the following people *(in alphabetical order)*: @@ -31,26 +31,7 @@ For TensorLayerX, it is now actively developing and maintaining by the following - **Hao Dong** (`@zsdonghao `_) - ``_ - **Jiarong Han** (`@hanjr92 `_) - ``_ -For TensorLayer 2.x, it is now actively developing and maintaining by the following people who has more than 50 contributions: - -- **Hao Dong** (`@zsdonghao `_) - ``_ -- **Jingqing Zhang** (`@JingqingZ `_) - ``_ -- **Rundi Wu** (`@ChrisWu1997 `_) - ``_ -- **Ruihai Wu** (`@warshallrho `_) - ``_ - -For TensorLayer 1.x, it was actively developed and maintained by the following people *(in alphabetical order)*: - -- **Akara Supratak** (`@akaraspt `_) - ``_ -- **Fangde Liu** (`@fangde `_) - ``_ -- **Guo Li** (`@lgarithm `_) - ``_ -- **Hao Dong** (`@zsdonghao `_) - ``_ -- **Jonathan Dekhtiar** (`@DEKHTIARJonathan `_) - ``_ -- **Luo Mai** (`@luomai `_) - ``_ -- **Pan Wang** (`@FerociousPanda `_) - ``_ (UI) -- **Simiao Yu** (`@nebulaV `_) - ``_ - - -Numerous other contributors can be found in the `Github Contribution Graph `_. +Numerous other contributors can be found in the `Github Contribution Graph `_. What to contribute diff --git a/docs/user/examples.rst b/docs/user/examples.rst index 717704d..120e723 100644 --- a/docs/user/examples.rst +++ b/docs/user/examples.rst @@ -12,10 +12,10 @@ Commonly used dataset and pretrained models - MNIST, see `OpenI `__. or `MNIST `__. - CIFAR10, see `OpenI `__. or `CIFAR10 `__. - - YOLOv4 Pretrained Model, see `OpenI `__. or `Baidu `__. password: idsz - - VGG16 Pretrained Model, see `OpenI `__. or `Baidu `__. password: t36u - - VGG19 Pretrained Model, see `OpenI `__. or `Baidu `__. password: rb8w - - ResNet50 Pretrained Model, see `OpenI `__. or `Baidu `__. password: 3nui + - YOLOv4 Pretrained Model, see `OpenI `__. + - VGG16 Pretrained Model, see `OpenI `__. + - VGG19 Pretrained Model, see `OpenI `__. + - ResNet50 Pretrained Model, see `OpenI `__. Basics ============ @@ -43,90 +43,6 @@ Pretrained Models - YOLOv4 (MS-COCO). Object Detection demo, see `pretrained_yolov4.py `__. and YOLOv4 model, see `yolo.py `__. - All pretrained models in `pretrained-models `__. -Vision -================== -Warning:These examples below only support Tensorlayer 2.0. TensorlayerX is under development. - - Arbitrary Style Transfer in Real-time with Adaptive Instance Normalization, see `examples `__. - - ArcFace: Additive Angular Margin Loss for Deep Face Recognition, see `InsignFace `__. - - BinaryNet. Model compression, see `mnist `__ `cifar10 `__. - - Ternary Weight Network. Model compression, see `mnist `__ `cifar10 `__. - - DoReFa-Net. Model compression, see `mnist `__ `cifar10 `__. - - QuanCNN. Model compression, sees `mnist `__ `cifar10 `__. - - Wide ResNet (CIFAR) by `ritchieng `__. - - `Spatial Transformer Networks `__ by `zsdonghao `__. - - `U-Net for brain tumor segmentation `__ by `zsdonghao `__. - - Variational Autoencoder (VAE) for (CelebA) by `yzwxx `__. - - Variational Autoencoder (VAE) for (MNIST) by `BUPTLdy `__. - - Image Captioning - Reimplementation of Google's `im2txt `__ by `zsdonghao `__. - -Adversarial Learning -======================== -Warning:These examples below only support Tensorlayer 2.0. TensorlayerX is under development. - - DCGAN (CelebA). Generating images by `Deep Convolutional Generative Adversarial Networks `__ by `zsdonghao `__. - - `Generative Adversarial Text to Image Synthesis `__ by `zsdonghao `__. - - `Unsupervised Image to Image Translation with Generative Adversarial Networks `__ by `zsdonghao `__. - - `Improved CycleGAN `__ with resize-convolution by `luoxier `__. - - `Super Resolution GAN `__ by `zsdonghao `__. - - `BEGAN: Boundary Equilibrium Generative Adversarial Networks `__ by `2wins `__. - - `DAGAN: Fast Compressed Sensing MRI Reconstruction `__ by `nebulaV `__. - -Natural Language Processing -============================== -Warning:These examples below only support Tensorlayer 2.0. TensorlayerX is under development. - - Word Embedding (Word2vec). Train a word embedding matrix, see `tutorial_word2vec_basic.py `__. - - Restore Embedding matrix. Restore a pre-train embedding matrix, see `tutorial_generate_text.py `__. - - Text Generation. Generates new text scripts, using LSTM network, see `tutorial_generate_text.py `__. - - Chinese Text Anti-Spam by `pakrchen `__. - - `Chatbot in 200 lines of code `__ for `Seq2Seq `__. - - FastText Sentence Classification (IMDB), see `tutorial_imdb_fasttext.py `__ by `tomtung `__. - -Reinforcement Learning -============================== -Warning:These examples below only support Tensorlayer 2.0. TensorlayerX is under development. - - Policy Gradient / Network (Atari Ping Pong), see `tutorial_atari_pong.py `__. - - Deep Q-Network (Frozen lake), see `tutorial_frozenlake_dqn.py `__. - - Q-Table learning algorithm (Frozen lake), see `tutorial_frozenlake_q_table.py `__. - - Asynchronous Policy Gradient using TensorDB (Atari Ping Pong) by `nebulaV `__. - - AC for discrete action space (Cartpole), see `tutorial_cartpole_ac.py `__. - - A3C for continuous action space (Bipedal Walker), see `tutorial_bipedalwalker_a3c*.py `__. - - `DAGGER `__ for (`Gym Torcs `__) by `zsdonghao `__. - - `TRPO `__ for continuous and discrete action space by `jjkke88 `__. - -Miscellaneous -================= -Warning:These examples below only support Tensorlayer 2.0. TensorlayerX is under development. - -- `Sipeed `__ : Run TensorLayer on AI Chips - -.. - - TensorDB by `fangde `__ see `tl_paper `__. - - A simple web service - `TensorFlask `__ by `JoelKronander `__. - -.. - Applications - ============= - - There are some good applications implemented by TensorLayer. - You may able to find some useful examples for your project. - If you want to share your application, please contact tensorlayer@gmail.com. - - 1D CNN + LSTM for Biosignal - --------------------------------- - - Author : `Akara Supratak `__ - - Introduction - ^^^^^^^^^^^^ - - Implementation - ^^^^^^^^^^^^^^ - - Citation - ^^^^^^^^ - - - - .. _GitHub: https://github.com/tensorlayer/tensorlayer .. _Deeplearning Tutorial: http://deeplearning.stanford.edu/tutorial/ diff --git a/docs/user/installation.rst b/docs/user/installation.rst index 2fb1e13..886798f 100644 --- a/docs/user/installation.rst +++ b/docs/user/installation.rst @@ -17,41 +17,6 @@ which cover installing the TensorFlow for a range of operating systems including Mac OX, Linux and Windows, or ask for help on `tensorlayer@gmail.com `_ or `FAQ `_. - -Install Backend -========================= -TensorLayerX supports multiple deep learning backends, default TensorFlow as backend also supports MindSpore, PaddlePaddle and PyTorch. - -.. code-block:: bash - - pip3 install tensorflow-gpu==2.0.0-beta1 # specific version (YOU SHOULD INSTALL THIS ONE NOW) - pip3 install tensorflow-gpu # GPU version - pip3 install tensorflow # CPU version - - -The installation instructions of TensorFlow are written to be very detailed on `TensorFlow`_ website. -However, there are something need to be considered. For example, `TensorFlow`_ officially supports GPU acceleration for Linux, Mac OX and Windows at present. For ARM processor architecture, you need to install TensorFlow from source. - -If you want to use mindspore backend, you should install mindspore==1.6.1. - -.. code-block:: bash - - pip install https://ms-release.obs.cn-north-4.myhuaweicloud.com/1.6.1/MindSpore/gpu/x86_64/cuda-10.1/mindspore_gpu-1.6.1-cp37-cp37m-linux_x86_64.whl --trusted-host ms-release.obs.cn-north-4.myhuaweicloud.com -i https://pypi.tuna.tsinghua.edu.cn/simple - - -If you want to use paddlepaddle backend, you should install paddlepaddle>=2.1.1 - -.. code-block:: bash - - python -m pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple - - -If you want to use PyTorch backend, you should install PyTorch>=1.8.0 - -.. code-block:: bash - - pip3 install torch==1.8.2+cu102 torchvision==0.9.2+cu102 torchaudio===0.8.2 -f https://download.pytorch.org/whl/lts/1.8/torch_lts.html - Install TensorLayerX ========================= @@ -83,139 +48,10 @@ Alternatively, you can build from the source. # First clone the repository and change the current directory to the newly cloned repository git clone https://github.com/tensorlayer/TensorLayerX.git cd tensorlayer + python setup.py install - # Install virtualenv if necessary - sudo pip3 install virtualenv - # Then create a virtualenv called `venv` - virtualenv venv - - # Activate the virtualenv - - ## Linux: - source venv/bin/activate - - ## Windows: - venv\Scripts\activate.bat - - # basic installation - pip3 install . - - # ============= IF TENSORFLOW IS NOT ALREADY INSTALLED ============= # - - # for a machine **without** an NVIDIA GPU - pip3 install -e ".[all_cpu_dev]" - - # for a machine **with** an NVIDIA GPU - pip3 install -e ".[all_gpu_dev]" - - -If you want install TensorLayer 2.X, It does not support multiple backends. - -.. code-block:: bash - - [stable version] pip3 install tensorlayer==2.x.x - -If you want install TensorLayer 1.X, the simplest way to install TensorLayer 1.X is as follow. It will also install the numpy and matplotlib automatically. - -.. code-block:: bash - - [stable version] pip3 install tensorlayer==1.x.x - -However, if you want to modify or extend TensorLayer 1.X, you can download the repository from -`Github`_ and install it as follow. - -.. code-block:: bash - - cd to the root of the git tree - pip3 install -e . - -This command will run the ``setup.py`` to install TensorLayerX. The ``-e`` reflects -editable, then you can edit the source code in ``tensorlayer`` folder, and ``import`` the edited -TensorLayerX. - - -GPU support -========================== - -Thanks to NVIDIA supports, training a fully connected network on a -GPU, which may be 10 to 20 times faster than training them on a CPU. -For convolutional network, may have 50 times faster. -This requires an NVIDIA GPU with CUDA and cuDNN support. - - -CUDA ----- - -The TensorFlow website also teach how to install the CUDA and cuDNN, please see -`TensorFlow GPU Support `_. - -Download and install the latest CUDA is available from NVIDIA website: - - - `CUDA download and install `_ - - -.. - After installation, make sure ``/usr/local/cuda/bin`` is in your ``PATH`` (use ``echo #PATH`` to check), and - ``nvcc --version`` works. Also ensure ``/usr/local/cuda/lib64`` is in your - ``LD_LIBRARY_PATH``, so the CUDA libraries can be found. - -If CUDA is set up correctly, the following command should print some GPU information on -the terminal: - -.. code-block:: bash - - python -c "import tensorflow" - - -cuDNN --------- - -Apart from CUDA, NVIDIA also provides a library for common neural network operations that especially -speeds up Convolutional Neural Networks (CNNs). Again, it can be obtained from -NVIDIA after registering as a developer (it take a while): - -Download and install the latest cuDNN is available from NVIDIA website: - - - `cuDNN download and install `_ - - -To install it, copy the ``*.h`` files to ``/usr/local/cuda/include`` and the -``lib*`` files to ``/usr/local/cuda/lib64``. +This command will run the ``setup.py`` to install TensorLayerX. .. _TensorFlow: https://www.tensorflow.org/versions/master/get_started/os_setup.html .. _GitHub: https://github.com/tensorlayer/tensorlayer -.. _TensorLayer: https://github.com/tensorlayer/tensorlayer/ - - - -Windows User -============== - -TensorLayer is built on the top of Python-version TensorFlow, so please install Python first. -Note:We highly recommend installing Anaconda. The lowest version requirements of Python is py36. - -`Anaconda download `_ - -GPU support ------------- -Thanks to NVIDIA supports, training a fully connected network on a GPU, which may be 10 to 20 times faster than training them on a CPU. For convolutional network, may have 50 times faster. This requires an NVIDIA GPU with CUDA and cuDNN support. - -1. Installing Microsoft Visual Studio -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -You should preinstall Microsoft Visual Studio (VS) before installing CUDA. The lowest version requirements is VS2010. We recommend installing VS2015 or VS2013. CUDA7.5 supports VS2010, VS2012 and VS2013. CUDA8.0 also supports VS2015. - -2. Installing CUDA -^^^^^^^^^^^^^^^^^^^^^^^ -Download and install the latest CUDA is available from NVIDIA website: - -`CUDA download `_ - -We do not recommend modifying the default installation directory. - -3. Installing cuDNN -^^^^^^^^^^^^^^^^^^^^^^ -The NVIDIA CUDA® Deep Neural Network library (cuDNN) is a GPU-accelerated library of primitives for deep neural networks. Download and extract the latest cuDNN is available from NVIDIA website: - -`cuDNN download `_ - -After extracting cuDNN, you will get three folders (bin, lib, include). Then these folders should be copied to CUDA installation. (The default installation directory is `C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v8.0`) +.. _TensorLayer: https://github.com/tensorlayer/tensorlayer/ \ No newline at end of file From cb5d25153157c2e5bdb3e5c018600c9b095f0580 Mon Sep 17 00:00:00 2001 From: Jiarong Han Date: Fri, 6 Jan 2023 17:43:03 +0800 Subject: [PATCH 08/46] add some functions (#60) --- tensorlayerx/backend/__init__.py | 7 + tensorlayerx/backend/ops/__init__.py | 9 +- tensorlayerx/backend/ops/mindspore_nn.py | 83 ++++----- tensorlayerx/backend/ops/oneflow_nn.py | 118 +++++++------ tensorlayerx/backend/ops/paddle_nn.py | 125 +++++++------- tensorlayerx/backend/ops/tensorflow_nn.py | 44 +++++ tensorlayerx/backend/ops/torch_nn.py | 151 ++++++++++++---- tensorlayerx/nn/layers/__init__.py | 1 + tensorlayerx/nn/layers/fold.py | 201 ++++++++++++++++++++++ 9 files changed, 533 insertions(+), 206 deletions(-) create mode 100644 tensorlayerx/nn/layers/fold.py diff --git a/tensorlayerx/backend/__init__.py b/tensorlayerx/backend/__init__.py index 7c0ff6b..c9a900f 100644 --- a/tensorlayerx/backend/__init__.py +++ b/tensorlayerx/backend/__init__.py @@ -213,5 +213,12 @@ from .ops import adaptive_max_pool1d from .ops import adaptive_max_pool2d from .ops import adaptive_max_pool3d +from .ops import unfold +from .ops import avg_pool1d +from .ops import avg_pool2d +from .ops import avg_pool3d +from .ops import max_pool1d +from .ops import max_pool2d +from .ops import max_pool3d from tensorlayerx.backend import ops \ No newline at end of file diff --git a/tensorlayerx/backend/ops/__init__.py b/tensorlayerx/backend/ops/__init__.py index 6211124..5a9a9d5 100644 --- a/tensorlayerx/backend/ops/__init__.py +++ b/tensorlayerx/backend/ops/__init__.py @@ -274,4 +274,11 @@ from .load_backend import adaptive_avg_pool3d from .load_backend import adaptive_max_pool1d from .load_backend import adaptive_max_pool2d -from .load_backend import adaptive_max_pool3d \ No newline at end of file +from .load_backend import adaptive_max_pool3d +from .load_backend import unfold +from .load_backend import avg_pool1d +from .load_backend import avg_pool2d +from .load_backend import avg_pool3d +from .load_backend import max_pool1d +from .load_backend import max_pool2d +from .load_backend import max_pool3d \ No newline at end of file diff --git a/tensorlayerx/backend/ops/mindspore_nn.py b/tensorlayerx/backend/ops/mindspore_nn.py index ad17fd4..a441d7d 100644 --- a/tensorlayerx/backend/ops/mindspore_nn.py +++ b/tensorlayerx/backend/ops/mindspore_nn.py @@ -793,6 +793,18 @@ def max_pool(input, ksize, strides, padding, data_format=None): return outputs +def max_pool1d(input, kernel_size, stride=None, padding=0, return_mask=False, ceil_mode=False, data_format='NCL'): + raise NotImplementedError + + +def max_pool2d(input, kernel_size, stride=None, padding=0, ceil_mode=False, return_mask=False, data_format='NCHW'): + raise NotImplementedError + + +def max_pool3d(input, kernel_size, stride=None, padding=0, ceil_mode=False, return_mask=False, data_format="NCDHW"): + raise NotImplementedError + + class AvgPool1d(Cell): def __init__(self, ksize, strides, padding, data_format=None): @@ -892,36 +904,6 @@ def __call__(self, inputs): return outputs -def max_pool3d(input, ksize, strides, padding, data_format=None, name=None): - """ - Performs the max pooling on the input. - - Parameters - ---------- - input : tensor - A 5-D Tensor of the format specified by data_format. - ksize : int or list of ints - An int or list of ints that has length 1, 3 or 5. - The size of the window for each dimension of the input tensor. - strides : int or list of ints - An int or list of ints that has length 1, 3 or 5. - The stride of the sliding window for each dimension of the input tensor. - padding : string - 'VALID' or 'SAME'. The padding algorithm. See the "returns" section of tf.ops.convolution for details. - data_format : string - "NDHWC", "NCDHW". Defaults to "NDHWC". The data format of the input and output data. - With the default format "NDHWC", the data is stored in the order of: [batch, in_depth, in_height, in_width, in_channels]. - Alternatively, the format could be "NCDHW", the data storage order is: [batch, in_channels, in_depth, in_height, in_width]. - name : string - A name for the operation (optional). - - Returns - ------- - A Tensor of format specified by data_format. The max pooled output tensor. - """ - pass - - class AvgPool3d(Cell): def __init__(self, ksize, strides, padding, data_format='NCDHW'): @@ -935,31 +917,22 @@ def __call__(self, inputs): return self.avg_pool(inputs) -def avg_pool3d(input, ksize, strides, padding, data_format=None, name=None): - """ - Performs the average pooling on the input. +def avg_pool1d(input, kernel_size, stride=None, padding=0, count_include_pad=True, ceil_mode=False, data_format='NCL'): + raise NotImplementedError - Parameters - ---------- - input : tensor - A 5-D Tensor of shape [batch, height, width, channels] and type float32, float64, qint8, quint8, or qint32. - ksize : int or list of ints - An int or list of ints that has length 1, 3 or 5. The size of the window for each dimension of the input tensor. - strides : int or list of ints - An int or list of ints that has length 1, 3 or 5. - The stride of the sliding window for each dimension of the input tensor. - padding : string - 'VALID' or 'SAME'. The padding algorithm. See the "returns" section of tf.ops.convolution for details. - data_format : string - 'NDHWC' and 'NCDHW' are supported. - name : string - Optional name for the operation. - Returns - ------- - A Tensor with the same type as value. The average pooled output tensor. - """ - pass +def avg_pool2d( + input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, + divisor_override=None, data_format='NCHW' +): + raise NotImplementedError + + +def avg_pool3d(input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, + divisor_override=None, data_format='NCDHW' + ): + + raise NotImplementedError def pool(input, window_shape, pooling_type, strides=None, padding='VALID', data_format=None, dilations=None, name=None): @@ -2550,3 +2523,7 @@ def linear(input, weight, bias = None): bias_add = P.BiasAdd() output = bias_add(output, bias) return output + +def unfold(input, kernel_size, dilation = 1, padding = 0, stride = 1): + + return ms.ops.unfold(input, kernel_size, stride=stride, padding=padding, dilation=dilation) \ No newline at end of file diff --git a/tensorlayerx/backend/ops/oneflow_nn.py b/tensorlayerx/backend/ops/oneflow_nn.py index 556ee1a..969dcbf 100644 --- a/tensorlayerx/backend/ops/oneflow_nn.py +++ b/tensorlayerx/backend/ops/oneflow_nn.py @@ -885,6 +885,19 @@ def max_pool(input, ksize, strides, padding, data_format=None): return maxpool_obj(input) +def max_pool1d(input, kernel_size, stride=None, padding=0, return_mask=False, ceil_mode=False, data_format='NCL'): + raise NotImplementedError + + +def max_pool2d(input, kernel_size, stride=None, padding=0, ceil_mode=False, return_mask=False, data_format='NCHW'): + raise NotImplementedError + + +def max_pool3d(input, kernel_size, stride=None, padding=0, ceil_mode=False, return_mask=False, data_format="NCDHW"): + raise NotImplementedError + + + class AvgPool1d(object): def __init__(self, ksize, strides, padding, data_format=None): @@ -997,37 +1010,37 @@ def __call__(self, inputs): return self.max_pool3d(inputs) -def max_pool3d(input, ksize, strides, padding, data_format=None): - """ - Performs the max pooling on the input. - - Parameters - ---------- - input : tensor - A 5-D Tensor of the format specified by data_format. - ksize : int or list of ints - An int or list of ints that has length 1, 3 or 5. - The size of the window for each dimension of the input tensor. - strides : int or list of ints - An int or list of ints that has length 1, 3 or 5. - The stride of the sliding window for each dimension of the input tensor. - padding : string - 'VALID' or 'SAME'. The padding algorithm. See the "returns" section of tf.ops.convolution for details. - data_format : string - "NDHWC", "NCDHW". Defaults to "NDHWC". The data format of the input and output data. - With the default format "NDHWC", the data is stored in the order of: [batch, in_depth, in_height, in_width, in_channels]. - Alternatively, the format could be "NCDHW", the data storage order is: [batch, in_channels, in_depth, in_height, in_width]. - name : string - A name for the operation (optional). - - Returns - ------- - A Tensor of format specified by data_format. The max pooled output tensor. - """ - - data_format, padding = preprocess_3d_format(data_format, padding) - max_pool3d_obj = MaxPool(ksize, strides, padding, data_format) - return max_pool3d_obj(input) +# def max_pool3d(input, ksize, strides, padding, data_format=None): +# """ +# Performs the max pooling on the input. +# +# Parameters +# ---------- +# input : tensor +# A 5-D Tensor of the format specified by data_format. +# ksize : int or list of ints +# An int or list of ints that has length 1, 3 or 5. +# The size of the window for each dimension of the input tensor. +# strides : int or list of ints +# An int or list of ints that has length 1, 3 or 5. +# The stride of the sliding window for each dimension of the input tensor. +# padding : string +# 'VALID' or 'SAME'. The padding algorithm. See the "returns" section of tf.ops.convolution for details. +# data_format : string +# "NDHWC", "NCDHW". Defaults to "NDHWC". The data format of the input and output data. +# With the default format "NDHWC", the data is stored in the order of: [batch, in_depth, in_height, in_width, in_channels]. +# Alternatively, the format could be "NCDHW", the data storage order is: [batch, in_channels, in_depth, in_height, in_width]. +# name : string +# A name for the operation (optional). +# +# Returns +# ------- +# A Tensor of format specified by data_format. The max pooled output tensor. +# """ +# +# data_format, padding = preprocess_3d_format(data_format, padding) +# max_pool3d_obj = MaxPool(ksize, strides, padding, data_format) +# return max_pool3d_obj(input) class AvgPool3d(object): @@ -1040,33 +1053,22 @@ def __call__(self, inputs): return self.avg_pool3d_obj(inputs) -def avg_pool3d(input, ksize, strides, padding, data_format=None): - """ - Performs the average pooling on the input. +def avg_pool1d(input, kernel_size, stride=None, padding=0, count_include_pad=True, ceil_mode=False, data_format='NCL'): - Parameters - ---------- - input : tensor - A 5-D Tensor of shape [batch, height, width, channels] and type float32, float64, qint8, quint8, or qint32. - ksize : int or list of ints - An int or list of ints that has length 1, 3 or 5. The size of the window for each dimension of the input tensor. - strides : int or list of ints - An int or list of ints that has length 1, 3 or 5. - The stride of the sliding window for each dimension of the input tensor. - padding : string - 'VALID' or 'SAME'. The padding algorithm. See the "returns" section of tf.ops.convolution for details. - data_format : string - 'NDHWC' and 'NCDHW' are supported. - name : string - Optional name for the operation. + raise NotImplementedError - Returns - ------- - A Tensor with the same type as value. The average pooled output tensor. - """ - avg_pool_obj = AvgPool(ksize, strides, padding, data_format) - return avg_pool_obj(input) +def avg_pool2d( + input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, + divisor_override=None, data_format='NCHW' +): + raise NotImplementedError + + +def avg_pool3d(input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, + divisor_override=None, data_format='NCDHW' + ): + raise NotImplementedError def pool(input, window_shape, pooling_type, strides=None, padding='VALID', data_format=None, dilations=None, name=None): @@ -2221,4 +2223,8 @@ def swish(input): def linear(input, weight, bias = None): - return F.linear(input, weight, bias) \ No newline at end of file + return F.linear(input, weight, bias) + +def unfold(input, kernel_size, dilation = 1, padding = 0, stride = 1): + + return F.unfold(input, kernel_size, stride=stride, padding=padding, dilation=dilation) \ No newline at end of file diff --git a/tensorlayerx/backend/ops/paddle_nn.py b/tensorlayerx/backend/ops/paddle_nn.py index a937263..3e84f35 100644 --- a/tensorlayerx/backend/ops/paddle_nn.py +++ b/tensorlayerx/backend/ops/paddle_nn.py @@ -692,11 +692,9 @@ def __call__(self, inputs): ) return outputs - def max_pool(input, ksize, strides, padding, data_format=None): """ Performs the max pooling on the input. - Parameters ---------- input : tensor @@ -711,13 +709,41 @@ def max_pool(input, ksize, strides, padding, data_format=None): The stride of the sliding window for each dimension of the input tensor. padding : string 'VALID' or 'SAME'. The padding algorithm. See the "returns" section of tf.ops.convolution for details. - Returns ------- A Tensor of format specified by data_format. The max pooled output tensor. """ pass +def max_pool1d(input, kernel_size, stride=None, padding=0, return_mask=False, ceil_mode=False, data_format='NCL'): + + data_format, padding = preprocess_1d_format(data_format=data_format, padding=padding) + if data_format != 'NCL': + input = pd.transpose(input, [0, 2, 1]) + output = F.max_pool1d(input, kernel_size, stride = stride, padding = padding, return_mask=return_mask, ceil_mode=ceil_mode) + if data_format != 'NCL': + if return_mask: + output[0] = pd.transpose(output[0], [0, 2, 1]) + output[1] = pd.transpose(output[1], [0, 2, 1]) + else: + output = pd.transpose(output, [0, 2, 1]) + return output + +def max_pool2d(input, kernel_size, stride=None, padding=0, ceil_mode=False, return_mask=False, data_format='NCHW'): + + data_format, padding = preprocess_2d_format(data_format=data_format, padding=padding) + return F.max_pool2d( + input, kernel_size, stride=stride, padding=padding, ceil_mode=ceil_mode, + return_mask=return_mask, data_format = data_format + ) + +def max_pool3d(input, kernel_size, stride=None, padding=0, ceil_mode=False, return_mask=False, data_format="NCDHW"): + data_format, padding = preprocess_3d_format(data_format=data_format, padding=padding) + return F.max_pool3d( + input, kernel_size, stride=stride, padding=padding, ceil_mode=ceil_mode, + return_mask=return_mask, data_format=data_format + ) + class AvgPool1d(object): @@ -749,11 +775,9 @@ def __call__(self, inputs): ) return outputs - def avg_pool(input, ksize, strides, padding): """ Performs the avg pooling on the input. - Parameters ---------- input : tensor @@ -768,13 +792,39 @@ def avg_pool(input, ksize, strides, padding): The stride of the sliding window for each dimension of the input tensor. padding : string 'VALID' or 'SAME'. The padding algorithm. See the "returns" section of tf.ops.convolution for details. - Returns ------- A Tensor of format specified by data_format. The average pooled output tensor. """ pass +def avg_pool1d(input, kernel_size, stride=None, padding=0, count_include_pad=True, ceil_mode=False, data_format='NCL'): + data_format, padding = preprocess_1d_format(data_format=data_format, padding=padding) + if data_format != 'NCL': + input = pd.transpose(input, [0, 2, 1]) + output = F.avg_pool1d( + input, kernel_size, stride = stride, padding = padding, exclusive=count_include_pad, ceil_mode=ceil_mode + ) + if data_format != 'NCL': + output = pd.transpose(output, [0, 2, 1]) + return output + +def avg_pool2d( + input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, + divisor_override=None, data_format='NCHW' +): + data_format, padding = preprocess_2d_format(data_format=data_format, padding=padding) + return F.avg_pool2d(input, kernel_size, stride = stride, padding = padding, + exclusive=count_include_pad, ceil_mode=ceil_mode, + divisor_override=divisor_override,data_format=data_format) + +def avg_pool3d(input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, + divisor_override=None, data_format='NCDHW' +): + data_format, padding = preprocess_3d_format(data_format=data_format, padding=padding) + return F.avg_pool3d(input, kernel_size, stride=stride, padding=padding, + exclusive=count_include_pad, ceil_mode=ceil_mode, + divisor_override=divisor_override, data_format=data_format) class MaxPool3d(object): @@ -790,36 +840,6 @@ def __call__(self, inputs): return outputs -def max_pool3d(input, ksize, strides, padding, data_format=None, name=None): - """ - Performs the max pooling on the input. - - Parameters - ---------- - input : tensor - A 5-D Tensor of the format specified by data_format. - ksize : int or list of ints - An int or list of ints that has length 1, 3 or 5. - The size of the window for each dimension of the input tensor. - strides : int or list of ints - An int or list of ints that has length 1, 3 or 5. - The stride of the sliding window for each dimension of the input tensor. - padding : string - 'VALID' or 'SAME'. The padding algorithm. See the "returns" section of tf.ops.convolution for details. - data_format : string - "NDHWC", "NCDHW". Defaults to "NDHWC". The data format of the input and output data. - With the default format "NDHWC", the data is stored in the order of: [batch, in_depth, in_height, in_width, in_channels]. - Alternatively, the format could be "NCDHW", the data storage order is: [batch, in_channels, in_depth, in_height, in_width]. - name : string - A name for the operation (optional). - - Returns - ------- - A Tensor of format specified by data_format. The max pooled output tensor. - """ - pass - - class AvgPool3d(object): def __init__(self, ksize, strides, padding, data_format=None): @@ -834,33 +854,6 @@ def __call__(self, inputs): return outputs -def avg_pool3d(input, ksize, strides, padding, data_format=None, name=None): - """ - Performs the average pooling on the input. - - Parameters - ---------- - input : tensor - A 5-D Tensor of shape [batch, height, width, channels] and type float32, float64, qint8, quint8, or qint32. - ksize : int or list of ints - An int or list of ints that has length 1, 3 or 5. The size of the window for each dimension of the input tensor. - strides : int or list of ints - An int or list of ints that has length 1, 3 or 5. - The stride of the sliding window for each dimension of the input tensor. - padding : string - 'VALID' or 'SAME'. The padding algorithm. See the "returns" section of tf.ops.convolution for details. - data_format : string - 'NDHWC' and 'NCDHW' are supported. - name : string - Optional name for the operation. - - Returns - ------- - A Tensor with the same type as value. The average pooled output tensor. - """ - pass - - def pool(input, window_shape, pooling_type, strides=None, padding='VALID', data_format=None, dilations=None, name=None): """ Performs an N-D pooling operation. @@ -2131,4 +2124,8 @@ def swish(input): def linear(input, weight, bias = None): - return F.linear(input, weight, bias) \ No newline at end of file + return F.linear(input, weight, bias) + +def unfold(input, kernel_size, dilation = 1, padding = 0, stride = 1): + + return F.unfold(input, kernel_size, strides=stride, paddings=padding, dilations=dilation) \ No newline at end of file diff --git a/tensorlayerx/backend/ops/tensorflow_nn.py b/tensorlayerx/backend/ops/tensorflow_nn.py index 01df7c7..0a06515 100644 --- a/tensorlayerx/backend/ops/tensorflow_nn.py +++ b/tensorlayerx/backend/ops/tensorflow_nn.py @@ -838,6 +838,18 @@ def max_pool(input, ksize, strides, padding, data_format=None): outputs = tf.nn.max_pool(input=input, ksize=ksize, strides=strides, padding=padding, data_format=data_format) return outputs +def max_pool1d(input, kernel_size, stride=None, padding=0, return_mask=False, ceil_mode=False, data_format='NCL'): + + raise NotImplementedError + +def max_pool2d(input, kernel_size, stride=None, padding=0, ceil_mode=False, return_mask=False, data_format='NCHW'): + + raise NotImplementedError + +def max_pool3d(input, kernel_size, stride=None, padding=0, ceil_mode=False, return_mask=False, data_format="NCDHW"): + + raise NotImplementedError + class AvgPool1d(object): @@ -920,6 +932,25 @@ def avg_pool(input, ksize, strides, padding): ) return outputs +def avg_pool1d(input, kernel_size, stride=None, padding=0, count_include_pad=True, ceil_mode=False, data_format='NCL'): + + raise NotImplementedError + + +def avg_pool2d( + input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, + divisor_override=None, data_format='NCHW' +): + + raise NotImplementedError + + +def avg_pool3d(input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, + divisor_override=None, data_format='NCDHW' +): + + raise NotImplementedError + class MaxPool3d(object): @@ -2980,4 +3011,17 @@ def linear(input, weight, bias = None): output = tf.matmul(input, weight, transpose_b=True) if bias: output = output + bias + return output + +def unfold(input, kernel_size, dilation = 1, padding = 0, stride = 1): + + input = tf.transpose(input, perm=[0, 2, 3, 1]) + kernel_size = [1,] + list(kernel_size) + [1] + stride = [1,] + list(stride) + [1] + dilation = [1,] + list(dilation) + [1] + padding = [[0, 0], [padding[0],padding[0]], [padding[1],padding[1]], [0, 0]] + input = tf.pad(input, paddings=padding, mode='CONSTANT', constant_values=0) + output = tf.image.extract_patches(input, sizes = kernel_size, strides=stride, padding='VALID', rates=dilation) + output = tf.transpose(output, perm=[0, 3, 1, 2]) + output = tf.reshape(output, shape=[output.shape[0], output.shape[1], output.shape[2] * output.shape[3]]) return output \ No newline at end of file diff --git a/tensorlayerx/backend/ops/torch_nn.py b/tensorlayerx/backend/ops/torch_nn.py index df770cf..6f35dda 100644 --- a/tensorlayerx/backend/ops/torch_nn.py +++ b/tensorlayerx/backend/ops/torch_nn.py @@ -873,6 +873,52 @@ def max_pool(input, ksize, strides, padding, data_format=None): maxpool_obj = MaxPool(ksize, strides, padding, data_format) return maxpool_obj(input) +def max_pool1d(input, kernel_size, stride=None, padding=0, return_mask=False, ceil_mode=False, data_format='NCL'): + + data_format, padding = preprocess_1d_format(data_format=data_format, padding=padding) + if data_format != 'NCL': + input = torch.permute(input, [0, 2, 1]) + output = F.max_pool1d(input, kernel_size, stride = stride, padding = padding, return_indices=return_mask, ceil_mode=ceil_mode) + if data_format != 'NCL': + if return_mask: + output[0] = torch.permute(output[0], [0, 2, 1]) + output[1] = torch.permute(output[1], [0, 2, 1]) + else: + output = torch.permute(output, [0, 2, 1]) + return output + +def max_pool2d(input, kernel_size, stride=None, padding=0, ceil_mode=False, return_mask=False, data_format='NCHW'): + + data_format, padding = preprocess_2d_format(data_format=data_format, padding=padding) + if data_format != 'NCHW': + input = torch.permute(input, [0, 3, 1, 2]) + output = F.max_pool2d( + input, kernel_size, stride=stride, padding=padding, ceil_mode=ceil_mode, return_indices=return_mask + ) + if data_format != 'NCHW': + if return_mask: + output[0] = torch.permute(output[0], [0, 2, 3, 1]) + output[1] = torch.permute(output[1], [0, 2, 3, 1]) + else: + output = torch.permute(output, [0, 2, 3, 1]) + return output + +def max_pool3d(input, kernel_size, stride=None, padding=0, ceil_mode=False, return_mask=False, data_format="NCDHW"): + data_format, padding = preprocess_3d_format(data_format=data_format, padding=padding) + if data_format != 'NCDHW': + input = torch.permute(input, [0, 4, 1, 2, 3]) + + output = F.max_pool3d( + input, kernel_size, stride=stride, padding=padding, ceil_mode=ceil_mode, return_indices=return_mask + ) + if data_format != 'NCDHW': + if return_mask: + output[0] = torch.permute(output[0], [0, 2, 3, 4, 1]) + output[1] = torch.permute(output[1], [0, 2, 3, 4, 1]) + else: + output = torch.permute(output, [0, 2, 3, 4, 1]) + return output + class AvgPool1d(object): @@ -975,6 +1021,43 @@ def avg_pool(input, ksize, strides, padding): avg_pool_obj = AvgPool(ksize, strides, padding) return avg_pool_obj(input) +def avg_pool1d(input, kernel_size, stride=None, padding=0, count_include_pad=True, ceil_mode=False, data_format='NCL'): + data_format, padding = preprocess_1d_format(data_format=data_format, padding=padding) + if data_format != 'NCL': + input = torch.permute(input, [0, 2, 1]) + output = F.avg_pool1d( + input, kernel_size, stride = stride, padding = padding, count_include_pad=count_include_pad, ceil_mode=ceil_mode + ) + if data_format != 'NCL': + output = torch.permute(output, [0, 2, 1]) + return output + +def avg_pool2d( + input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, + divisor_override=None, data_format='NCHW' +): + data_format, padding = preprocess_2d_format(data_format=data_format, padding=padding) + if data_format != 'NCHW': + input = torch.permute(input, [0, 3, 1, 2]) + output = F.avg_pool2d(input, kernel_size, stride = stride, padding = padding, + count_include_pad=count_include_pad, ceil_mode=ceil_mode, + divisor_override=divisor_override) + if data_format != 'NCHW': + output = torch.permute(output, [0, 2, 3, 1]) + return output + +def avg_pool3d(input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, + divisor_override=None, data_format='NCDHW' +): + data_format, padding = preprocess_3d_format(data_format=data_format, padding=padding) + if data_format != 'NCDHW': + input = torch.permute(input, [0, 4, 1, 2, 3]) + output = F.avg_pool3d(input, kernel_size, stride=stride, padding=padding, + count_include_pad=count_include_pad, ceil_mode=ceil_mode, + divisor_override=divisor_override) + if data_format != 'NCDHW': + output = torch.permute(output, [0, 2, 3, 4, 1]) + return output class MaxPool3d(object): @@ -986,37 +1069,37 @@ def __call__(self, inputs): return self.max_pool3d(inputs) -def max_pool3d(input, ksize, strides, padding, data_format=None): - """ - Performs the max pooling on the input. - - Parameters - ---------- - input : tensor - A 5-D Tensor of the format specified by data_format. - ksize : int or list of ints - An int or list of ints that has length 1, 3 or 5. - The size of the window for each dimension of the input tensor. - strides : int or list of ints - An int or list of ints that has length 1, 3 or 5. - The stride of the sliding window for each dimension of the input tensor. - padding : string - 'VALID' or 'SAME'. The padding algorithm. See the "returns" section of tf.ops.convolution for details. - data_format : string - "NDHWC", "NCDHW". Defaults to "NDHWC". The data format of the input and output data. - With the default format "NDHWC", the data is stored in the order of: [batch, in_depth, in_height, in_width, in_channels]. - Alternatively, the format could be "NCDHW", the data storage order is: [batch, in_channels, in_depth, in_height, in_width]. - name : string - A name for the operation (optional). - - Returns - ------- - A Tensor of format specified by data_format. The max pooled output tensor. - """ - - data_format, padding = preprocess_3d_format(data_format, padding) - max_pool3d_obj = MaxPool(ksize, strides, padding, data_format) - return max_pool3d_obj(input) +# def max_pool3d(input, ksize, strides, padding, data_format=None): +# """ +# Performs the max pooling on the input. +# +# Parameters +# ---------- +# input : tensor +# A 5-D Tensor of the format specified by data_format. +# ksize : int or list of ints +# An int or list of ints that has length 1, 3 or 5. +# The size of the window for each dimension of the input tensor. +# strides : int or list of ints +# An int or list of ints that has length 1, 3 or 5. +# The stride of the sliding window for each dimension of the input tensor. +# padding : string +# 'VALID' or 'SAME'. The padding algorithm. See the "returns" section of tf.ops.convolution for details. +# data_format : string +# "NDHWC", "NCDHW". Defaults to "NDHWC". The data format of the input and output data. +# With the default format "NDHWC", the data is stored in the order of: [batch, in_depth, in_height, in_width, in_channels]. +# Alternatively, the format could be "NCDHW", the data storage order is: [batch, in_channels, in_depth, in_height, in_width]. +# name : string +# A name for the operation (optional). +# +# Returns +# ------- +# A Tensor of format specified by data_format. The max pooled output tensor. +# """ +# +# data_format, padding = preprocess_3d_format(data_format, padding) +# max_pool3d_obj = MaxPool(ksize, strides, padding, data_format) +# return max_pool3d_obj(input) class AvgPool3d(object): @@ -2235,4 +2318,8 @@ def swish(input): def linear(input, weight, bias = None): - return torch.nn.functional.linear(input, weight, bias) \ No newline at end of file + return torch.nn.functional.linear(input, weight, bias) + +def unfold(input, kernel_size, dilation = 1, padding = 0, stride = 1): + + return torch.nn.functional.unfold(input, kernel_size, stride=stride, padding=padding, dilation=dilation) \ No newline at end of file diff --git a/tensorlayerx/nn/layers/__init__.py b/tensorlayerx/nn/layers/__init__.py index 2f21d39..807ff3f 100644 --- a/tensorlayerx/nn/layers/__init__.py +++ b/tensorlayerx/nn/layers/__init__.py @@ -23,3 +23,4 @@ from .stack import * # from .utils import * from .Transformer import * +from .fold import * diff --git a/tensorlayerx/nn/layers/fold.py b/tensorlayerx/nn/layers/fold.py new file mode 100644 index 0000000..928555f --- /dev/null +++ b/tensorlayerx/nn/layers/fold.py @@ -0,0 +1,201 @@ +#! /usr/bin/python +# -*- coding: utf-8 -*- + +import tensorlayerx as tlx +from tensorlayerx import logging +from tensorlayerx.nn.core import Module + +__all__ = [ + # 'Fold', #TODO + 'Unfold', +] + +class Fold(Module): + r"""Combines an array of sliding local blocks into a large containing + tensor. + + Consider a batched :attr:`input` tensor containing sliding local blocks, + e.g., patches of images, of shape :math:`(N, C \times \prod(\text{kernel\_size}), L)`, + where :math:`N` is batch dimension, :math:`C \times \prod(\text{kernel\_size})` + is the number of values within a block (a block has :math:`\prod(\text{kernel\_size})` + spatial locations each containing a :math:`C`-channeled vector), and + :math:`L` is the total number of blocks. (This is exactly the + same specification as the output shape of :class:`~torch.nn.Unfold`.) This + operation combines these local blocks into the large :attr:`output` tensor + of shape :math:`(N, C, \text{output\_size}[0], \text{output\_size}[1], \dots)` + by summing the overlapping values. Similar to :class:`~torch.nn.Unfold`, the + arguments must satisfy + + .. math:: + L = \prod_d \left\lfloor\frac{\text{output\_size}[d] + 2 \times \text{padding}[d] % + - \text{dilation}[d] \times (\text{kernel\_size}[d] - 1) - 1}{\text{stride}[d]} + 1\right\rfloor, + + where :math:`d` is over all spatial dimensions. + + * :attr:`output_size` describes the spatial shape of the large containing + tensor of the sliding local blocks. It is useful to resolve the ambiguity + when multiple input shapes map to same number of sliding blocks, e.g., + with ``stride > 0``. + + The :attr:`padding`, :attr:`stride` and :attr:`dilation` arguments specify + how the sliding blocks are retrieved. + + * :attr:`stride` controls the stride for the sliding blocks. + + * :attr:`padding` controls the amount of implicit zero-paddings on both + sides for :attr:`padding` number of points for each dimension before + reshaping. + + * :attr:`dilation` controls the spacing between the kernel points; also known as the à trous algorithm. + It is harder to describe, but this `link`_ has a nice visualization of what :attr:`dilation` does. + + Parameters + ---------- + output_size : int or tuple + the shape of the spatial dimensions of the + output (i.e., ``output.sizes()[2:]``) + kernel_size : int or tuple + the size of the sliding blocks + stride : int or tuple + the stride of the sliding blocks in the input spatial dimensions. Default: 1 + padding : int or tuple, optional + implicit zero padding to be added on both sides of input. Default: 0 + dilation : int or tuple, optional + a parameter that controls the stride of elements within the neighborhood. Default: 1 + + .. warning:: + Currently, only 4-D output tensors (batched image-like tensors) are + supported. + + Shape: + - Input: :math:`(N, C \times \prod(\text{kernel\_size}), L)` + - Output: :math:`(N, C, \text{output\_size}[0], \text{output\_size}[1], \dots)` as described above + + Examples + ---------- + >>> import numpy as np + >>> import tensorlayerx as tlx + >>> fold = tlx.nn.Fold(output_size=(4, 5), kernel_size=(2, 2)) + >>> input = tlx.convert_to_tensor( np.random.random(1, 3 * 2 * 2, 12)) + >>> output = fold(input) + >>> output.shape + + """ + pass + +class Unfold(Module): + r"""Extracts sliding local blocks from a batched input tensor. + + Consider a batched :attr:`input` tensor of shape :math:`(N, C, *)`, + where :math:`N` is the batch dimension, :math:`C` is the channel dimension, + and :math:`*` represent arbitrary spatial dimensions. This operation flattens + each sliding :attr:`kernel_size`-sized block within the spatial dimensions + of :attr:`input` into a column (i.e., last dimension) of a 3-D :attr:`output` + tensor of shape :math:`(N, C \times \prod(\text{kernel\_size}), L)`, where + :math:`C \times \prod(\text{kernel\_size})` is the total number of values + within each block (a block has :math:`\prod(\text{kernel\_size})` spatial + locations each containing a :math:`C`-channeled vector), and :math:`L` is + the total number of such blocks: + + .. math:: + L = \prod_d \left\lfloor\frac{\text{spatial\_size}[d] + 2 \times \text{padding}[d] % + - \text{dilation}[d] \times (\text{kernel\_size}[d] - 1) - 1}{\text{stride}[d]} + 1\right\rfloor, + + where :math:`\text{spatial\_size}` is formed by the spatial dimensions + of :attr:`input` (:math:`*` above), and :math:`d` is over all spatial + dimensions. + + Therefore, indexing :attr:`output` at the last dimension (column dimension) + gives all values within a certain block. + + The :attr:`padding`, :attr:`stride` and :attr:`dilation` arguments specify + how the sliding blocks are retrieved. + + * :attr:`stride` controls the stride for the sliding blocks. + + * :attr:`padding` controls the amount of implicit zero-paddings on both + sides for :attr:`padding` number of points for each dimension before + reshaping. + + * :attr:`dilation` controls the spacing between the kernel points; also known as the à trous algorithm. + It is harder to describe, but this `link`_ has a nice visualization of what :attr:`dilation` does. + + Parameters + ---------- + kernel_size (int or tuple): + the size of the sliding blocks + stride : int or tuple, optional + the stride of the sliding blocks in the input spatial dimensions. Default: 1 + padding : int or tuple, optional) + implicit zero padding to be added on both sides of input. Default: 0 + dilation : int or tuple, optional + a parameter that controls the stride of elements within the neighborhood. Default: 1 + + .. warning:: + Currently, only 4-D input tensors (batched image-like tensors) are + supported. + + Shape: + - Input: :math:`(N, C, *)` + - Output: :math:`(N, C \times \prod(\text{kernel\_size}), L)` as described above + + Examples + ---------- + >>> import numpy as np + >>> import tensorlayerx as tlx + >>> unfold = nn.Unfold(kernel_size=(2, 3)) + >>> input = tlx.convert_to_tensor(np.random.random(2, 5, 3, 4)) + >>> output = unfold(input) + >>> # each patch contains 30 values (2x3=6 vectors, each of 5 channels) + >>> # 4 blocks (2x3 kernels) in total in the 3x4 input + >>> output.size() + + """ + + + def __init__( + self, + kernel_size , + dilation = 1, + padding = 0, + stride = 1, + name = 'unfold', + ) -> None: + super(Unfold, self).__init__() + msg = "{} must be int or 2-tuple for 4D input" + self.kernel_size = self.assert_int_or_pair(kernel_size, "kernel_size", msg) + self.dilation = self.assert_int_or_pair(dilation, "dilation", msg) + self.padding = self.assert_int_or_pair(padding, "padding", msg) + self.stride = self.assert_int_or_pair(stride, "stride", msg) + self.name = name + self.build() + self._built = True + + def assert_int_or_pair(arg, arg_name, message): + assert isinstance(arg, int) or len(arg) == 2, message.format(arg_name) + if isinstance(arg, int): + return [arg,] * 2 + + def __repr__(self): + s = '{classname}(' + s += 'kernel_size={kernel_size},' + s += 'dilation={dilation},' + s += 'padding={padding},' + s += 'stride={stride},' + s += 'name={name}' + s += ")" + return s.format(classname=self.__class__.__name__, **self.__dict__) + + def build(self, inputs_shape=None): + pass + + def forward(self, input): + if len(input.shape) != 4: + raise NotImplementedError("Input Error: Only 4D input Tensors are supported (got {}D)".format(len(input.shape))) + output = tlx.ops.unfold(input, self.kernel_size, self.dilation, + self.padding, self.stride) + + if not self._nodes_fixed and self._build_graph: + self._add_node(input, output) + self._nodes_fixed = True + return output From 2eb6b2111e2db326082f5417b25d65e7fa7734d9 Mon Sep 17 00:00:00 2001 From: Eric_lai Date: Mon, 9 Jan 2023 10:58:05 +0800 Subject: [PATCH 09/46] Update docs --- docs/index.rst | 1 - docs/user/examples.rst | 36 ++++----- docs/user/get_involved.rst | 77 ------------------- ...mdb_LSTM_simple.py => imdb_lstm_simple.py} | 0 ...load_paddle_parameters_to_tensorlayerx.py} | 0 ...oad_pytorch_parameters_to_tensorlayerx.py} | 0 ...nist_Sequential.py => mnist_sequential.py} | 0 ...odule_Container.py => module_container.py} | 0 ...er_Container.py => parameter_container.py} | 0 ...odel_load.py => tensorlayer_model_load.py} | 0 ...rlayerx_graph.py => tensorlayerx_graph.py} | 0 ..._tensorboardX.py => using_tensorboardx.py} | 0 12 files changed, 15 insertions(+), 99 deletions(-) delete mode 100644 docs/user/get_involved.rst rename examples/basic_tutorials/{imdb_LSTM_simple.py => imdb_lstm_simple.py} (100%) rename examples/basic_tutorials/{tutorial_load_paddle_parameters_to_tensorlayerx.py => load_paddle_parameters_to_tensorlayerx.py} (100%) rename examples/basic_tutorials/{tutorial_load_pytorch_parameters_to_tensorlayerx.py => load_pytorch_parameters_to_tensorlayerx.py} (100%) rename examples/basic_tutorials/{mnist_Sequential.py => mnist_sequential.py} (100%) rename examples/basic_tutorials/{Module_Container.py => module_container.py} (100%) rename examples/basic_tutorials/{Parameter_Container.py => parameter_container.py} (100%) rename examples/basic_tutorials/{tutorial_tensorlayer_model_load.py => tensorlayer_model_load.py} (100%) rename examples/basic_tutorials/{tutorial_tensorlayerx_graph.py => tensorlayerx_graph.py} (100%) rename examples/basic_tutorials/{tutorial_using_tensorboardX.py => using_tensorboardx.py} (100%) diff --git a/docs/index.rst b/docs/index.rst index fd7ab36..36fa840 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -34,7 +34,6 @@ to the library as a developer. user/installation user/examples user/contributing - user/get_involved user/faq .. toctree:: diff --git a/docs/user/examples.rst b/docs/user/examples.rst index 120e723..f8f886d 100644 --- a/docs/user/examples.rst +++ b/docs/user/examples.rst @@ -6,42 +6,36 @@ Examples We list some examples here, but more tutorials and applications can be found in `Github examples `__. -Commonly used dataset and pretrained models -=========================================== - - - MNIST, see `OpenI `__. or `MNIST `__. - - CIFAR10, see `OpenI `__. or `CIFAR10 `__. - - - YOLOv4 Pretrained Model, see `OpenI `__. - - VGG16 Pretrained Model, see `OpenI `__. - - VGG19 Pretrained Model, see `OpenI `__. - - ResNet50 Pretrained Model, see `OpenI `__. - Basics ============ - Multi-layer perceptron (MNIST), simple usage and supports multiple backends. Classification task, see `mnist_mlp.py `__. - Generative Adversarial Networks (MNIST), simple usage and supports multiple backends. See `mnist_gan.py `__. - Convolutional Network (CIFAR-10), simple usage and supports multiple backends. Classification task, see `cifar10_cnn.py `__. - - Recurrent Neural Network (IMDB), simple usage and supports multiple backends. Text classification task, see `imdb_LSTM_simple.py `__. + - Recurrent Neural Network (IMDB), simple usage and supports multiple backends. Text classification task, see `imdb_lstm_simple.py `__. - Using tensorlayerx to automatic inference input shape. See `automatic_inference_input _shape.py `__. - - Using ModuleList in tensorlayerx. See `tutorial_ModuleList.py `__. - - Using Sequential in tensorlayerx. See `mnist_Sequential.py `__. + - Using ModuleList in tensorlayerx. See `module_contaniner.py `__. + - Using Sequential in tensorlayerx. See `mnist_sequential.py `__. - Using Dataflow in tensorlayerx. See `mnist_dataflow.py `__. - Using nested layer in tensorlayerx. See `nested_usage_of_layer.py `__. - Using tensorlayerx to save tensorflow model to pb. See `tensorflow_model_save_to_pb.py `__. - - Using tensorlayerx to load model from npz. See `tutorial_tensorlayer_model_load.py `__. + - Using tensorlayerx to load model from npz. See `tensorlayer_model_load.py `__. + - Using tensorlayerx model training monitoring. See `using_tensorboardx.py `__. + - Load the Paddle model parameters using tensorlayerx. See `load_paddle_parameters_to_tensorlayerx.py `__. + - Load the PyTorch model parameters using tensorlayerx. See `load_pytorch_parameters_to_tensorlayerx.py `__. +Commonly used dataset and pretrained models +=========================================== -Pretrained Models -================== + - MNIST, see `OpenI `__. or `MNIST `__. + - CIFAR10, see `OpenI `__. or `CIFAR10 `__. - - VGG 16 (ImageNet). Classification task demo, see `pretrained_vgg16 `__. and VGG model, see `vgg.py `__. - - Resnet50 (ImageNet). Classification task demo, see `pretrained_resnet50.py `__. and Resnet model, see `resnet.py `__. - - YOLOv4 (MS-COCO). Object Detection demo, see `pretrained_yolov4.py `__. and YOLOv4 model, see `yolo.py `__. - - All pretrained models in `pretrained-models `__. + - YOLOv4 Pretrained Model, see `OpenI `__. + - VGG16 Pretrained Model, see `OpenI `__. + - VGG19 Pretrained Model, see `OpenI `__. + - ResNet50 Pretrained Model, see `OpenI `__. .. _GitHub: https://github.com/tensorlayer/tensorlayer diff --git a/docs/user/get_involved.rst b/docs/user/get_involved.rst deleted file mode 100644 index 90d699a..0000000 --- a/docs/user/get_involved.rst +++ /dev/null @@ -1,77 +0,0 @@ - - -========================= -Get Involved in Research -========================= - -Ph.D. Postition @ PKU -============================================================= - - -Hi, I am `Hao Dong `__, the founder of this project and a new faculty member in EECS, Peking University. I now have a few Ph.D. positions per year open for international students who would like to study AI. If you or your friends are interested in it, feel free to contact me. -PKU is a top 30 university in the global ranking. The application is competitive, apply early is recommended. Please check the following links for more details. - -- `About the International Elite Ph.D. Program in Computer Science `__ -- `My homepage `__ - -Contact: hao.dong [AT] pku.edu.cn - - - -Faculty Postition @ PKU -============================================================= - -The Center on Frontiers of Computing Studies (CFCS), Peking University (PKU), China, is a university new initiative co-founded by Professors John Hopcroft (Turing Awardee) and Wen Gao (CAE, ACM/IEEE Fellow). The center aims at developing the excellence on two fronts: research and education. On the research front, the center will provide a world-class research environment, where innovation and impactful research is the central aim, measured by professional reputation among world scholars, not by counting the number of publications and research funding. On the education front, the center deeply involves in the Turing Class, an elite undergraduate program that draws the cream of the crop from the PKU undergraduate talent pool. New curriculum and pedagogy are designed and practiced in this program, with the aim to cultivate a new generation of computer scientist/engineers that are solid in both theories and practices. - -**Positions and Qualification** - -The center invites applications for tenured/tenure-track faculty positions. We are seeking applicants from all areas of Computer Science, spanning theoretical foundations, systems, software, and applications, with special interests in artificial intelligence and machine learning. We are especially interested in applicants conducting research at the frontiers of Computer Science with other disciplines, such as data sciences, engineering, as well as mathematical, medical, physical, and social sciences. - -Applicants are expected to have completed (or be completing) a Ph.D., have demonstrated the ability to pursue a program of research, and have a strong commitment to undergraduate and graduate teaching. A successful candidate will be expected to teach one to two courses at the undergraduate and graduate levels in each semester, and to build and lead a team of undergraduate and graduate students in innovative research. - -We are also seeking qualified candidates for postdoctoral positions. Candidates should have a Ph.D. in a relevant discipline or expect a Ph. D within a year, with a substantive record of research accomplishments, and the ability to work collaboratively with faculty members in the center. - -**To Apply** - -Applicants should send a full curriculum vitae; copies of 3-5 key publications; 3-5 names and contact information of references; and a statement of research and teaching to: CFCS_recruiting[at]pku[dot]edu[dot]cn . To expedite the process, please arrange to have the reference letters sent directly to the above email address. - -Application for a postdoctoral position should include a curriculum vita, brief statement of research, and three to five names and contact information of recommendation, and can be directly addressed to an individual faculty member. - -We conduct review of applications monthly, immediately upon the recipient of all application materials at the beginning of each month. However, it is highly recommended that applicants submit complete applications sooner than later, as the positions are to be filled quickly. - - -Postdoc Postition @ ICL -================================================== - -Data science is therefore by nature at the core of all modern transdisciplinary scientific activities, as it involves the whole life cycle of data, from acquisition and exploration to analysis and communication of the results. Data science is not only concerned with the tools and methods to obtain, manage and analyse data: it is also about extracting value from data and translating it from asset to product. - -Launched on 1st April 2014, the Data Science Institute (DSI) at Imperial College London aims to enhance Imperial's excellence in data-driven research across its faculties by fulfilling the following objectives. - -The Data Science Institute is housed in purpose built facilities in the heart of the Imperial College campus in South Kensington. Such a central location provides excellent access to collabroators across the College and across London. - - - To act as a focal point for coordinating data science research at Imperial College by facilitating access to funding, engaging with global partners, and stimulating cross-disciplinary collaboration. - - To develop data management and analysis technologies and services for supporting data driven research in the College. - - To promote the training and education of the new generation of data scientist by developing and coordinating new degree courses, and conducting public outreach programmes on data science. - - To advise College on data strategy and policy by providing world-class data science expertise. - - To enable the translation of data science innovation by close collaboration with industry and supporting commercialization. - -If you are interested in working with us, please check our -`vacancies `__ -and other ways to -`get involved `__ -, or feel free to -`contact us `__. - -Software Engineer @ SurgicalAI.cn -============================================================= -SurgicalAI is a startup founded by the data scientists and surgical robot experts from Imperial College. Our objective is AI democratise Surgery. By combining 5G, AI and Cloud Computing, SurgicalAI is building a platform enable junor surgeons to perfom complex procedures. As one of the most impactful startup, SurgicalAI is supported by Nvidia, AWS and top surgeons around the world. - -Currently based in Hangzhou, China, we are building digital solution for cardiac surgery like TAVR, LAA and Orthopedidcs like TKA and UNA. A demo can be found at here - -We are activly looking for experts in robotic navigation, computer graphics and medical image analysis experts to join us, building digitalized surgical service platform for the aging world. - -Home Page: http://www.surgicalai.cn - -Demo Page: http://demo5g.surgicalai.cn - -Contact: liufangde@surgicalai.cn diff --git a/examples/basic_tutorials/imdb_LSTM_simple.py b/examples/basic_tutorials/imdb_lstm_simple.py similarity index 100% rename from examples/basic_tutorials/imdb_LSTM_simple.py rename to examples/basic_tutorials/imdb_lstm_simple.py diff --git a/examples/basic_tutorials/tutorial_load_paddle_parameters_to_tensorlayerx.py b/examples/basic_tutorials/load_paddle_parameters_to_tensorlayerx.py similarity index 100% rename from examples/basic_tutorials/tutorial_load_paddle_parameters_to_tensorlayerx.py rename to examples/basic_tutorials/load_paddle_parameters_to_tensorlayerx.py diff --git a/examples/basic_tutorials/tutorial_load_pytorch_parameters_to_tensorlayerx.py b/examples/basic_tutorials/load_pytorch_parameters_to_tensorlayerx.py similarity index 100% rename from examples/basic_tutorials/tutorial_load_pytorch_parameters_to_tensorlayerx.py rename to examples/basic_tutorials/load_pytorch_parameters_to_tensorlayerx.py diff --git a/examples/basic_tutorials/mnist_Sequential.py b/examples/basic_tutorials/mnist_sequential.py similarity index 100% rename from examples/basic_tutorials/mnist_Sequential.py rename to examples/basic_tutorials/mnist_sequential.py diff --git a/examples/basic_tutorials/Module_Container.py b/examples/basic_tutorials/module_container.py similarity index 100% rename from examples/basic_tutorials/Module_Container.py rename to examples/basic_tutorials/module_container.py diff --git a/examples/basic_tutorials/Parameter_Container.py b/examples/basic_tutorials/parameter_container.py similarity index 100% rename from examples/basic_tutorials/Parameter_Container.py rename to examples/basic_tutorials/parameter_container.py diff --git a/examples/basic_tutorials/tutorial_tensorlayer_model_load.py b/examples/basic_tutorials/tensorlayer_model_load.py similarity index 100% rename from examples/basic_tutorials/tutorial_tensorlayer_model_load.py rename to examples/basic_tutorials/tensorlayer_model_load.py diff --git a/examples/basic_tutorials/tutorial_tensorlayerx_graph.py b/examples/basic_tutorials/tensorlayerx_graph.py similarity index 100% rename from examples/basic_tutorials/tutorial_tensorlayerx_graph.py rename to examples/basic_tutorials/tensorlayerx_graph.py diff --git a/examples/basic_tutorials/tutorial_using_tensorboardX.py b/examples/basic_tutorials/using_tensorboardx.py similarity index 100% rename from examples/basic_tutorials/tutorial_using_tensorboardX.py rename to examples/basic_tutorials/using_tensorboardx.py From 4f44628c8429b2f72035b60b951a62d19c53d690 Mon Sep 17 00:00:00 2001 From: Jiarong Han Date: Tue, 10 Jan 2023 15:37:30 +0800 Subject: [PATCH 10/46] fix maxpool1d/2d/3d (#61) --- tensorlayerx/backend/ops/mindspore_nn.py | 34 ++- tensorlayerx/backend/ops/oneflow_nn.py | 28 +- tensorlayerx/backend/ops/paddle_nn.py | 81 ++--- tensorlayerx/backend/ops/tensorflow_nn.py | 356 ++++++++++++++-------- tensorlayerx/backend/ops/torch_nn.py | 196 +++++------- tensorlayerx/nn/layers/pooling.py | 39 ++- 6 files changed, 413 insertions(+), 321 deletions(-) diff --git a/tensorlayerx/backend/ops/mindspore_nn.py b/tensorlayerx/backend/ops/mindspore_nn.py index a441d7d..06b71a8 100644 --- a/tensorlayerx/backend/ops/mindspore_nn.py +++ b/tensorlayerx/backend/ops/mindspore_nn.py @@ -728,12 +728,15 @@ def moments(x, axes, shift=None, keepdims=False): class MaxPool1d(Cell): - def __init__(self, ksize, strides, padding, data_format=None): + def __init__(self, ksize, strides, padding, return_mask, data_format=None): super(MaxPool1d, self).__init__() self.data_format, padding = preprocess_1d_format(data_format=data_format, padding=padding) self.expand = P.ExpandDims() _strides = (1, strides) _ksize = (1, ksize) + self.return_mask = return_mask + if self.return_mask: + raise NotImplementedError if self.data_format == 'NWC': self.squeeze = P.Squeeze(1) _data_format = 'NHWC' @@ -755,9 +758,12 @@ def construct(self, inputs): class MaxPool(Cell): - def __init__(self, ksize, strides, padding, data_format='NHWC'): + def __init__(self, ksize, strides, padding, return_mask, data_format='NHWC'): super(MaxPool, self).__init__() data_format, padding = preprocess_2d_format(data_format=data_format, padding=padding) + self.return_mask = return_mask + if self.return_mask: + raise NotImplementedError self.maxpool = P.MaxPool(kernel_size=ksize, strides=strides, pad_mode=padding, data_format=data_format) def construct(self, inputs): @@ -793,15 +799,15 @@ def max_pool(input, ksize, strides, padding, data_format=None): return outputs -def max_pool1d(input, kernel_size, stride=None, padding=0, return_mask=False, ceil_mode=False, data_format='NCL'): +def max_pool1d(input, kernel_size, stride=None, padding=0, return_mask=False, data_format='NCL'): raise NotImplementedError -def max_pool2d(input, kernel_size, stride=None, padding=0, ceil_mode=False, return_mask=False, data_format='NCHW'): +def max_pool2d(input, kernel_size, stride=None, padding=0, return_mask=False, data_format='NCHW'): raise NotImplementedError -def max_pool3d(input, kernel_size, stride=None, padding=0, ceil_mode=False, return_mask=False, data_format="NCDHW"): +def max_pool3d(input, kernel_size, stride=None, padding=0, return_mask=False, data_format="NCDHW"): raise NotImplementedError @@ -890,9 +896,12 @@ def avg_pool(input, ksize, strides, padding): class MaxPool3d(Cell): - def __init__(self, ksize, strides, padding, data_format=None): + def __init__(self, ksize, strides, padding, return_mask, data_format=None): super(MaxPool3d, self).__init__() self.data_format, self.padding = preprocess_3d_format(data_format, padding) + self.return_mask = return_mask + if self.return_mask: + raise NotImplementedError if data_format == 'NDHWC': raise NotImplementedError("The optional value for data format. Currently only support ‘NCDHW’.") self.max_pool3d = P.MaxPool3D( @@ -917,20 +926,17 @@ def __call__(self, inputs): return self.avg_pool(inputs) -def avg_pool1d(input, kernel_size, stride=None, padding=0, count_include_pad=True, ceil_mode=False, data_format='NCL'): +def avg_pool1d(input, kernel_size, stride=None, padding=0, data_format='NCL'): + raise NotImplementedError -def avg_pool2d( - input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, - divisor_override=None, data_format='NCHW' -): +def avg_pool2d(input, kernel_size, stride=None, padding=0, data_format='NCHW'): + raise NotImplementedError -def avg_pool3d(input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, - divisor_override=None, data_format='NCDHW' - ): +def avg_pool3d(input, kernel_size, stride=None, padding=0, data_format='NCDHW'): raise NotImplementedError diff --git a/tensorlayerx/backend/ops/oneflow_nn.py b/tensorlayerx/backend/ops/oneflow_nn.py index 969dcbf..a4c14e8 100644 --- a/tensorlayerx/backend/ops/oneflow_nn.py +++ b/tensorlayerx/backend/ops/oneflow_nn.py @@ -785,8 +785,9 @@ def moments(x, axes, shift=None, keepdims=False): class MaxPool1d(object): - def __init__(self, ksize, strides, padding, data_format=None): + def __init__(self, ksize, strides, padding, return_mask, data_format=None): self.data_format, self.padding = preprocess_1d_format(data_format=data_format, padding=padding) + self.return_mask = return_mask self.max_pool1d = MaxPool([ksize, ], strides, padding, data_format) def __call__(self, inputs): @@ -795,9 +796,10 @@ def __call__(self, inputs): class MaxPool(object): - def __init__(self, ksize, strides, padding, data_format=None): + def __init__(self, ksize, strides, padding, return_mask, data_format=None): self.ksize = ksize self.strides = strides + self.return_mask = return_mask if data_format in ['channels_last', 'NLC', 'NWC', 'NHWC', 'NDHWC']: self.data_format = 'channels_last' elif data_format in ['channels_first', 'NCL', 'NCW', 'NCHW', 'NCDHW']: @@ -885,15 +887,15 @@ def max_pool(input, ksize, strides, padding, data_format=None): return maxpool_obj(input) -def max_pool1d(input, kernel_size, stride=None, padding=0, return_mask=False, ceil_mode=False, data_format='NCL'): +def max_pool1d(input, kernel_size, stride=None, padding=0, return_mask=False, data_format='NCL'): raise NotImplementedError -def max_pool2d(input, kernel_size, stride=None, padding=0, ceil_mode=False, return_mask=False, data_format='NCHW'): +def max_pool2d(input, kernel_size, stride=None, padding=0, return_mask=False, data_format='NCHW'): raise NotImplementedError -def max_pool3d(input, kernel_size, stride=None, padding=0, ceil_mode=False, return_mask=False, data_format="NCDHW"): +def max_pool3d(input, kernel_size, stride=None, padding=0, return_mask=False, data_format="NCDHW"): raise NotImplementedError @@ -1002,8 +1004,9 @@ def avg_pool(input, ksize, strides, padding): class MaxPool3d(object): - def __init__(self, ksize, strides, padding, data_format=None): + def __init__(self, ksize, strides, padding, return_mask, data_format=None): self.data_format, self.padding = preprocess_3d_format(data_format, padding) + self.return_mask = return_mask self.max_pool3d = MaxPool(ksize, strides, padding, data_format) def __call__(self, inputs): @@ -1053,21 +1056,18 @@ def __call__(self, inputs): return self.avg_pool3d_obj(inputs) -def avg_pool1d(input, kernel_size, stride=None, padding=0, count_include_pad=True, ceil_mode=False, data_format='NCL'): +def avg_pool1d(input, kernel_size, stride=None, padding=0, data_format='NCL'): raise NotImplementedError -def avg_pool2d( - input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, - divisor_override=None, data_format='NCHW' -): +def avg_pool2d(input, kernel_size, stride=None, padding=0, data_format='NCHW'): + raise NotImplementedError -def avg_pool3d(input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, - divisor_override=None, data_format='NCDHW' - ): +def avg_pool3d(input, kernel_size, stride=None, padding=0, data_format='NCDHW'): + raise NotImplementedError diff --git a/tensorlayerx/backend/ops/paddle_nn.py b/tensorlayerx/backend/ops/paddle_nn.py index 3e84f35..2fc179e 100644 --- a/tensorlayerx/backend/ops/paddle_nn.py +++ b/tensorlayerx/backend/ops/paddle_nn.py @@ -665,30 +665,38 @@ def moments(x, axes, shift=None, keepdims=False): class MaxPool1d(object): - def __init__(self, ksize, strides, padding, data_format=None): + def __init__(self, ksize, strides, padding, return_mask, data_format=None): self.data_format, self.padding = preprocess_1d_format(data_format=data_format, padding=padding) self.ksize = ksize self.strides = strides + self.return_mask = return_mask def __call__(self, inputs): if self.data_format == 'NLC': inputs = nhwc_to_nchw(inputs) - outputs = F.max_pool1d(inputs, self.ksize, self.strides, self.padding) + outputs = F.max_pool1d(inputs, self.ksize, self.strides, self.padding, return_mask=self.return_mask) if self.data_format == 'NLC': - outputs = nchw_to_nhwc(outputs) - return outputs + if self.return_mask: + output = [None, None] + output[0] = nchw_to_nhwc(outputs[0]) + output[1] = nchw_to_nhwc(outputs[1]) + else: + output = nchw_to_nhwc(outputs) + return output class MaxPool(object): - def __init__(self, ksize, strides, padding, data_format=None): + def __init__(self, ksize, strides, padding, return_mask, data_format=None): self.data_format, self.padding = preprocess_2d_format(data_format, padding) self.ksize = ksize self.strides = strides + self.return_mask = return_mask def __call__(self, inputs): outputs = F.max_pool2d( - x=inputs, kernel_size=self.ksize, stride=self.strides, padding=self.padding, data_format=self.data_format + x=inputs, kernel_size=self.ksize, stride=self.strides, padding=self.padding, + return_mask=self.return_mask, data_format=self.data_format ) return outputs @@ -715,33 +723,33 @@ def max_pool(input, ksize, strides, padding, data_format=None): """ pass -def max_pool1d(input, kernel_size, stride=None, padding=0, return_mask=False, ceil_mode=False, data_format='NCL'): +def max_pool1d(input, kernel_size, stride=None, padding=0, return_mask=False, data_format='NCL'): data_format, padding = preprocess_1d_format(data_format=data_format, padding=padding) - if data_format != 'NCL': - input = pd.transpose(input, [0, 2, 1]) - output = F.max_pool1d(input, kernel_size, stride = stride, padding = padding, return_mask=return_mask, ceil_mode=ceil_mode) - if data_format != 'NCL': + if data_format == 'NLC': + input =nhwc_to_nchw(input) + output = F.max_pool1d(input, kernel_size, stride = stride, padding = padding, return_mask=return_mask) + if data_format == 'NLC': if return_mask: - output[0] = pd.transpose(output[0], [0, 2, 1]) - output[1] = pd.transpose(output[1], [0, 2, 1]) + outputs = [None, None] + outputs[0] = nchw_to_nhwc(output[0]) + outputs[1] = nchw_to_nhwc(output[1]) else: - output = pd.transpose(output, [0, 2, 1]) - return output + outputs = nchw_to_nhwc(output) + return outputs -def max_pool2d(input, kernel_size, stride=None, padding=0, ceil_mode=False, return_mask=False, data_format='NCHW'): +def max_pool2d(input, kernel_size, stride=None, padding=0, return_mask=False, data_format='NCHW'): data_format, padding = preprocess_2d_format(data_format=data_format, padding=padding) return F.max_pool2d( - input, kernel_size, stride=stride, padding=padding, ceil_mode=ceil_mode, - return_mask=return_mask, data_format = data_format + input, kernel_size, stride=stride, padding=padding, return_mask=return_mask, data_format = data_format ) -def max_pool3d(input, kernel_size, stride=None, padding=0, ceil_mode=False, return_mask=False, data_format="NCDHW"): +def max_pool3d(input, kernel_size, stride=None, padding=0, return_mask=False, data_format="NCDHW"): + data_format, padding = preprocess_3d_format(data_format=data_format, padding=padding) return F.max_pool3d( - input, kernel_size, stride=stride, padding=padding, ceil_mode=ceil_mode, - return_mask=return_mask, data_format=data_format + input, kernel_size, stride=stride, padding=padding, return_mask=return_mask, data_format=data_format ) @@ -798,44 +806,37 @@ def avg_pool(input, ksize, strides, padding): """ pass -def avg_pool1d(input, kernel_size, stride=None, padding=0, count_include_pad=True, ceil_mode=False, data_format='NCL'): +def avg_pool1d(input, kernel_size, stride=None, padding=0, data_format='NCL'): data_format, padding = preprocess_1d_format(data_format=data_format, padding=padding) if data_format != 'NCL': - input = pd.transpose(input, [0, 2, 1]) + input = nhwc_to_nchw(input) output = F.avg_pool1d( - input, kernel_size, stride = stride, padding = padding, exclusive=count_include_pad, ceil_mode=ceil_mode + input, kernel_size, stride = stride, padding = padding ) if data_format != 'NCL': - output = pd.transpose(output, [0, 2, 1]) + output = nchw_to_nhwc(output) return output -def avg_pool2d( - input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, - divisor_override=None, data_format='NCHW' -): +def avg_pool2d(input, kernel_size, stride=None, padding=0, data_format='NCHW'): data_format, padding = preprocess_2d_format(data_format=data_format, padding=padding) - return F.avg_pool2d(input, kernel_size, stride = stride, padding = padding, - exclusive=count_include_pad, ceil_mode=ceil_mode, - divisor_override=divisor_override,data_format=data_format) + return F.avg_pool2d(input, kernel_size, stride = stride, padding = padding, data_format=data_format) -def avg_pool3d(input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, - divisor_override=None, data_format='NCDHW' -): +def avg_pool3d(input, kernel_size, stride=None, padding=0, data_format='NCDHW'): data_format, padding = preprocess_3d_format(data_format=data_format, padding=padding) - return F.avg_pool3d(input, kernel_size, stride=stride, padding=padding, - exclusive=count_include_pad, ceil_mode=ceil_mode, - divisor_override=divisor_override, data_format=data_format) + return F.avg_pool3d(input, kernel_size, stride=stride, padding=padding, data_format=data_format) class MaxPool3d(object): - def __init__(self, ksize, strides, padding, data_format=None): + def __init__(self, ksize, strides, padding, return_mask, data_format=None): self.data_format, self.padding = preprocess_3d_format(data_format, padding) self.ksize = ksize self.strides = strides + self.return_mask = return_mask def __call__(self, inputs): outputs = F.max_pool3d( - inputs, kernel_size=self.ksize, stride=self.strides, padding=self.padding, data_format=self.data_format + inputs, kernel_size=self.ksize, stride=self.strides, padding=self.padding, + return_mask=self.return_mask, data_format=self.data_format ) return outputs diff --git a/tensorlayerx/backend/ops/tensorflow_nn.py b/tensorlayerx/backend/ops/tensorflow_nn.py index 0a06515..e33f896 100644 --- a/tensorlayerx/backend/ops/tensorflow_nn.py +++ b/tensorlayerx/backend/ops/tensorflow_nn.py @@ -750,11 +750,12 @@ def moments(x, axes, shift=None, keepdims=False): class MaxPool1d(object): - def __init__(self, ksize, strides, padding, data_format=None): + def __init__(self, ksize, strides, padding, return_mask,data_format=None): self.data_format, self.padding = preprocess_1d_format(data_format=data_format, padding=padding) self.ksize = ksize self.strides = strides self.padding_value = None + self.return_mask = return_mask if not isinstance(self.padding, str): self.padding_value = preprocess_padding(self.padding, '1d', self.data_format) self.padding = "VALID" @@ -762,43 +763,56 @@ def __init__(self, ksize, strides, padding, data_format=None): def __call__(self, inputs): if self.padding_value is not None: inputs = tf.pad(inputs, self.padding_value) - outputs = tf.nn.max_pool( - input=inputs, ksize=self.ksize, strides=self.strides, padding=self.padding, data_format=self.data_format - ) + if self.return_mask: + raise NotImplementedError + else: + outputs = tf.nn.max_pool( + input=inputs, ksize=self.ksize, strides=self.strides, padding=self.padding, data_format=self.data_format + ) return outputs class MaxPool(object): - def __init__(self, ksize, strides, padding, data_format=None): + def __init__(self, ksize, strides, padding, return_mask,data_format=None): self.ksize = ksize self.strides = strides self.data_format = data_format self.padding = padding + self.return_mask = return_mask + self.data_format, self.padding = preprocess_2d_format(data_format=self.data_format, padding=self.padding) + self.padding_value = None + if not isinstance(self.padding, str): + self.padding_value = preprocess_padding(self.padding, '2d', self.data_format) + self.padding = "VALID" - def __call__(self, inputs): - if len(inputs.shape) == 3: - self.data_format, self.padding = preprocess_1d_format(data_format=self.data_format, padding=self.padding) - if not isinstance(self.padding, str): - self.padding_value = preprocess_padding(self.padding, '1d', self.data_format) - self.padding = "VALID" - inputs = tf.pad(inputs, self.padding_value) - elif len(inputs.shape) == 4: - self.data_format, self.padding = preprocess_2d_format(data_format=self.data_format, padding=self.padding) - if not isinstance(self.padding, str): - self.padding_value = preprocess_padding(self.padding, '2d', self.data_format) - self.padding = "VALID" - inputs = tf.pad(inputs, self.padding_value) - elif len(inputs.shape) == 5: - self.data_format, self.padding = preprocess_3d_format(data_format=self.data_format, padding=self.padding) - if not isinstance(self.padding, str): - self.padding_value = preprocess_padding(self.padding, '3d', self.data_format) - self.padding = "VALID" - inputs = tf.pad(inputs, self.padding_value) - outputs = tf.nn.max_pool( - input=inputs, ksize=self.ksize, strides=self.strides, padding=self.padding, data_format=self.data_format - ) + def __call__(self, inputs): + # if len(inputs.shape) == 3: + # self.data_format, self.padding = preprocess_1d_format(data_format=self.data_format, padding=self.padding) + # if not isinstance(self.padding, str): + # self.padding_value = preprocess_padding(self.padding, '1d', self.data_format) + # self.padding = "VALID" + # inputs = tf.pad(inputs, self.padding_value) + # elif len(inputs.shape) == 4: + if self.padding_value is not None: + inputs = tf.pad(inputs, self.padding_value) + # elif len(inputs.shape) == 5: + # self.data_format, self.padding = preprocess_3d_format(data_format=self.data_format, padding=self.padding) + # if not isinstance(self.padding, str): + # self.padding_value = preprocess_padding(self.padding, '3d', self.data_format) + # self.padding = "VALID" + # inputs = tf.pad(inputs, self.padding_value) + + if self.return_mask: + outputs = tf.nn.max_pool_with_argmax( + input=inputs, ksize=self.ksize, strides=self.strides, padding=self.padding, data_format=self.data_format, + include_batch_in_index=True + ) + else: + outputs = tf.nn.max_pool( + input=inputs, ksize=self.ksize, strides=self.strides, padding=self.padding, data_format=self.data_format + ) return outputs @@ -838,17 +852,59 @@ def max_pool(input, ksize, strides, padding, data_format=None): outputs = tf.nn.max_pool(input=input, ksize=ksize, strides=strides, padding=padding, data_format=data_format) return outputs -def max_pool1d(input, kernel_size, stride=None, padding=0, return_mask=False, ceil_mode=False, data_format='NCL'): +def max_pool1d(input, kernel_size, stride=None, padding=0, return_mask=False, data_format='NCL'): - raise NotImplementedError + data_format, padding = preprocess_1d_format(data_format=data_format, padding=padding) + padding_value = None + if not isinstance(padding, str): + padding_value = preprocess_padding(padding, '1d', data_format) + padding = "VALID" + if padding_value is not None: + input = tf.pad(input, padding_value) + if return_mask: + raise NotImplementedError + else: + outputs = tf.nn.max_pool( + input=input, ksize=kernel_size, strides=stride, padding=padding, data_format=data_format + ) + return outputs -def max_pool2d(input, kernel_size, stride=None, padding=0, ceil_mode=False, return_mask=False, data_format='NCHW'): +def max_pool2d(input, kernel_size, stride=None, padding=0, return_mask=False, data_format='NCHW'): - raise NotImplementedError + data_format, padding = preprocess_2d_format(data_format=data_format, padding=padding) + padding_value = None + if not isinstance(padding, str): + padding_value = preprocess_padding(padding, '2d', data_format) + padding = "VALID" + if padding_value is not None: + input = tf.pad(input, padding_value) + if return_mask: + outputs = tf.nn.max_pool_with_argmax( + input=input, ksize=kernel_size, strides=stride, padding=padding, data_format=data_format, + include_batch_in_index=True + ) + else: + outputs = tf.nn.max_pool( + input=input, ksize=kernel_size, strides=stride, padding=padding, data_format=data_format + ) + return outputs -def max_pool3d(input, kernel_size, stride=None, padding=0, ceil_mode=False, return_mask=False, data_format="NCDHW"): +def max_pool3d(input, kernel_size, stride=None, padding=0, return_mask=False, data_format="NCDHW"): - raise NotImplementedError + data_format, padding = preprocess_3d_format(data_format=data_format, padding=padding) + padding_value = None + if not isinstance(padding, str): + padding_value = preprocess_padding(padding, '3d', data_format) + padding = "VALID" + if padding_value is not None: + input = tf.pad(input, padding_value) + if return_mask: + raise NotImplementedError + else: + outputs = tf.nn.max_pool( + input=input, ksize=kernel_size, strides=stride, padding=padding, data_format=data_format + ) + return outputs class AvgPool1d(object): @@ -932,33 +988,84 @@ def avg_pool(input, ksize, strides, padding): ) return outputs -def avg_pool1d(input, kernel_size, stride=None, padding=0, count_include_pad=True, ceil_mode=False, data_format='NCL'): +def avg_pool1d(input, kernel_size, stride=None, padding=0, data_format='NCL'): - raise NotImplementedError + data_format, padding = preprocess_1d_format(data_format=data_format, padding=padding) + padding_value = None + if not isinstance(padding, str): + padding_value = preprocess_padding(padding, '1d', data_format) + padding = "VALID" + if padding_value is not None: + input = tf.pad(input, padding_value) + output = tf.nn.pool( + input=input, + window_shape=kernel_size, + pooling_type="AVG", + strides=stride, + padding=padding, + data_format=data_format, + ) + return output -def avg_pool2d( - input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, - divisor_override=None, data_format='NCHW' -): - raise NotImplementedError +def avg_pool2d(input, kernel_size, stride=None, padding=0, data_format='NCHW'): + + data_format, padding = preprocess_2d_format(data_format=data_format, padding=padding) + if isinstance(kernel_size, int): + kernel_size = [kernel_size, kernel_size] + if isinstance(stride, int): + stride = [stride, stride] + padding_value = None + if not isinstance(padding, str): + padding_value = preprocess_padding(padding, '2d', data_format) + padding = "VALID" + if padding_value is not None: + input = tf.pad(input, padding_value) + output = tf.nn.pool( + input=input, + window_shape=kernel_size, + pooling_type="AVG", + strides=stride, + padding=padding, + data_format=data_format, + ) + return output -def avg_pool3d(input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, - divisor_override=None, data_format='NCDHW' -): +def avg_pool3d(input, kernel_size, stride=None, padding=0, data_format='NCDHW'): - raise NotImplementedError + + data_format, padding = preprocess_3d_format(data_format=data_format, padding=padding) + if isinstance(kernel_size, int): + kernel_size = [kernel_size, kernel_size, kernel_size] + if isinstance(stride, int): + stride = [stride, stride, stride] + padding_value = None + if not isinstance(padding, str): + padding_value = preprocess_padding(padding, '3d', data_format) + padding = "VALID" + if padding_value is not None: + input = tf.pad(input, padding_value) + output = tf.nn.pool( + input=input, + window_shape=kernel_size, + pooling_type="AVG", + strides=stride, + padding=padding, + data_format=data_format, + ) + return output class MaxPool3d(object): - def __init__(self, ksize, strides, padding, data_format=None): + def __init__(self, ksize, strides, padding, return_mask, data_format=None): self.data_format, self.padding = preprocess_3d_format(data_format, padding) self.ksize = ksize self.strides = strides self.padding_value = None + self.return_mask = return_mask if not isinstance(self.padding, str): self.padding_value = preprocess_padding(self.padding, '3d', self.data_format) self.padding = "VALID" @@ -966,53 +1073,56 @@ def __init__(self, ksize, strides, padding, data_format=None): def __call__(self, inputs): if self.padding_value is not None: inputs = tf.pad(inputs, self.padding_value) - outputs = tf.nn.max_pool3d( - input=inputs, - ksize=self.ksize, - strides=self.strides, - padding=self.padding, - data_format=self.data_format, - ) + if self.return_mask: + raise NotImplementedError + else: + outputs = tf.nn.max_pool3d( + input=inputs, + ksize=self.ksize, + strides=self.strides, + padding=self.padding, + data_format=self.data_format, + ) return outputs -def max_pool3d(input, ksize, strides, padding, data_format=None): - """ - Performs the max pooling on the input. - - Parameters - ---------- - input : tensor - A 5-D Tensor of the format specified by data_format. - ksize : int or list of ints - An int or list of ints that has length 1, 3 or 5. - The size of the window for each dimension of the input tensor. - strides : int or list of ints - An int or list of ints that has length 1, 3 or 5. - The stride of the sliding window for each dimension of the input tensor. - padding : string - 'VALID' or 'SAME'. The padding algorithm. See the "returns" section of tf.ops.convolution for details. - data_format : string - "NDHWC", "NCDHW". Defaults to "NDHWC". The data format of the input and output data. - With the default format "NDHWC", the data is stored in the order of: [batch, in_depth, in_height, in_width, in_channels]. - Alternatively, the format could be "NCDHW", the data storage order is: [batch, in_channels, in_depth, in_height, in_width]. - name : string - A name for the operation (optional). - - Returns - ------- - A Tensor of format specified by data_format. The max pooled output tensor. - """ - - data_format, padding = preprocess_3d_format(data_format, padding) - outputs = tf.nn.max_pool3d( - input=input, - ksize=ksize, - strides=strides, - padding=padding, - data_format=data_format, - ) - return outputs +# def max_pool3d(input, ksize, strides, padding, data_format=None): +# """ +# Performs the max pooling on the input. +# +# Parameters +# ---------- +# input : tensor +# A 5-D Tensor of the format specified by data_format. +# ksize : int or list of ints +# An int or list of ints that has length 1, 3 or 5. +# The size of the window for each dimension of the input tensor. +# strides : int or list of ints +# An int or list of ints that has length 1, 3 or 5. +# The stride of the sliding window for each dimension of the input tensor. +# padding : string +# 'VALID' or 'SAME'. The padding algorithm. See the "returns" section of tf.ops.convolution for details. +# data_format : string +# "NDHWC", "NCDHW". Defaults to "NDHWC". The data format of the input and output data. +# With the default format "NDHWC", the data is stored in the order of: [batch, in_depth, in_height, in_width, in_channels]. +# Alternatively, the format could be "NCDHW", the data storage order is: [batch, in_channels, in_depth, in_height, in_width]. +# name : string +# A name for the operation (optional). +# +# Returns +# ------- +# A Tensor of format specified by data_format. The max pooled output tensor. +# """ +# +# data_format, padding = preprocess_3d_format(data_format, padding) +# outputs = tf.nn.max_pool3d( +# input=input, +# ksize=ksize, +# strides=strides, +# padding=padding, +# data_format=data_format, +# ) +# return outputs class AvgPool3d(object): @@ -1039,40 +1149,40 @@ def __call__(self, inputs): return outputs -def avg_pool3d(input, ksize, strides, padding, data_format=None): - """ - Performs the average pooling on the input. - - Parameters - ---------- - input : tensor - A 5-D Tensor of shape [batch, height, width, channels] and type float32, float64, qint8, quint8, or qint32. - ksize : int or list of ints - An int or list of ints that has length 1, 3 or 5. The size of the window for each dimension of the input tensor. - strides : int or list of ints - An int or list of ints that has length 1, 3 or 5. - The stride of the sliding window for each dimension of the input tensor. - padding : string - 'VALID' or 'SAME'. The padding algorithm. See the "returns" section of tf.ops.convolution for details. - data_format : string - 'NDHWC' and 'NCDHW' are supported. - name : string - Optional name for the operation. - - Returns - ------- - A Tensor with the same type as value. The average pooled output tensor. - """ - - data_format, padding = preprocess_3d_format(data_format, padding) - outputs = tf.nn.avg_pool3d( - input=input, - ksize=ksize, - strides=strides, - padding=padding, - data_format=data_format, - ) - return outputs +# def avg_pool3d(input, ksize, strides, padding, data_format=None): +# """ +# Performs the average pooling on the input. +# +# Parameters +# ---------- +# input : tensor +# A 5-D Tensor of shape [batch, height, width, channels] and type float32, float64, qint8, quint8, or qint32. +# ksize : int or list of ints +# An int or list of ints that has length 1, 3 or 5. The size of the window for each dimension of the input tensor. +# strides : int or list of ints +# An int or list of ints that has length 1, 3 or 5. +# The stride of the sliding window for each dimension of the input tensor. +# padding : string +# 'VALID' or 'SAME'. The padding algorithm. See the "returns" section of tf.ops.convolution for details. +# data_format : string +# 'NDHWC' and 'NCDHW' are supported. +# name : string +# Optional name for the operation. +# +# Returns +# ------- +# A Tensor with the same type as value. The average pooled output tensor. +# """ +# +# data_format, padding = preprocess_3d_format(data_format, padding) +# outputs = tf.nn.avg_pool3d( +# input=input, +# ksize=ksize, +# strides=strides, +# padding=padding, +# data_format=data_format, +# ) +# return outputs def pool(input, window_shape, pooling_type, strides=None, padding='VALID', data_format=None, dilations=None, name=None): diff --git a/tensorlayerx/backend/ops/torch_nn.py b/tensorlayerx/backend/ops/torch_nn.py index 6f35dda..e82b965 100644 --- a/tensorlayerx/backend/ops/torch_nn.py +++ b/tensorlayerx/backend/ops/torch_nn.py @@ -774,9 +774,9 @@ def moments(x, axes, shift=None, keepdims=False): class MaxPool1d(object): - def __init__(self, ksize, strides, padding, data_format=None): + def __init__(self, ksize, strides, padding, return_mask, data_format=None): self.data_format, self.padding = preprocess_1d_format(data_format=data_format, padding=padding) - self.max_pool1d = MaxPool([ksize,], strides, padding, data_format) + self.max_pool1d = MaxPool([ksize,], strides, padding,return_mask, data_format) def __call__(self, inputs): return self.max_pool1d(inputs) @@ -784,9 +784,10 @@ def __call__(self, inputs): class MaxPool(object): - def __init__(self, ksize, strides, padding, data_format=None): + def __init__(self, ksize, strides, padding, return_mask = False, data_format=None): self.ksize = ksize self.strides = strides + self.return_mask = return_mask if data_format in ['channels_last', 'NLC', 'NWC', 'NHWC', 'NDHWC']: self.data_format = 'channels_last' elif data_format in ['channels_first', 'NCL', 'NCW', 'NCHW', 'NCDHW']: @@ -802,20 +803,29 @@ def __call__(self, inputs): if self.padding in ['SAME', 'same']: out = self.maxpool1d_same_padding(inputs) else: - out = F.max_pool1d(inputs, self.ksize, self.strides, padding=self.padding) + out = F.max_pool1d(inputs, self.ksize, self.strides, padding=self.padding, + return_indices=self.return_mask) if len(inputs.shape) == 4: if self.padding in ['SAME', 'same']: out = self.maxpool2d_same_padding(inputs) else: - out = F.max_pool2d(inputs, self.ksize, self.strides, padding=self.padding) + out = F.max_pool2d(inputs, self.ksize, self.strides, padding=self.padding, + return_indices=self.return_mask) if len(inputs.shape) == 5: if self.padding in ['SAME', 'same']: out = self.maxpool3d_same_padding(inputs) else: - out = F.max_pool3d(inputs, self.ksize, self.strides, padding=self.padding) + out = F.max_pool3d(inputs, self.ksize, self.strides, padding=self.padding, + return_indices=self.return_mask) if self.data_format == 'channels_last': - return nchw_to_nhwc(out) + if self.return_mask: + outputs = [None, None] + outputs[0] = nchw_to_nhwc(out[0]) + outputs[1] = nchw_to_nhwc(out[1]) + return outputs + else: + return nchw_to_nhwc(out) else: return out @@ -823,7 +833,7 @@ def maxpool1d_same_padding(self, input): rows_odd, padding_rows = same_padding(input, self.ksize, self.strides, 1) if rows_odd: input = F.pad(input, [0, int(rows_odd)], 'constant', float('-inf')) - return F.max_pool1d(input, self.ksize, self.strides, padding=(padding_rows // 2)) + return F.max_pool1d(input, self.ksize, self.strides, padding=(padding_rows // 2), return_indices=self.return_mask) def maxpool2d_same_padding(self, input): rows_odd, cols_odd, padding_rows, padding_cols = same_padding(input, self.ksize, self.strides, (1, 1)) @@ -831,7 +841,8 @@ def maxpool2d_same_padding(self, input): # TODO The fill value for maxpool is -INF. input = F.pad(input, [0, int(rows_odd), 0, int(cols_odd)], 'constant', float('-inf')) - return F.max_pool2d(input, self.ksize, self.strides, padding=(padding_rows // 2, padding_cols // 2)) + return F.max_pool2d(input, self.ksize, self.strides, padding=(padding_rows // 2, padding_cols // 2), + return_indices=self.return_mask) def maxpool3d_same_padding(self, input): rows_odd, cols_odd, depth_odd, padding_rows, padding_cols, padding_depth = same_padding( @@ -840,11 +851,12 @@ def maxpool3d_same_padding(self, input): if rows_odd or cols_odd or depth_odd: input = F.pad(input, [0, int(cols_odd), 0, int(rows_odd), 0, int(depth_odd)], 'constant', float('-inf')) return F.max_pool3d( - input, self.ksize, self.strides, padding=(padding_rows // 2, padding_cols // 2, padding_depth // 2) + input, self.ksize, self.strides, padding=(padding_rows // 2, padding_cols // 2, padding_depth // 2), + return_indices=self.return_mask ) -def max_pool(input, ksize, strides, padding, data_format=None): +def max_pool(input, ksize, strides, padding, return_mask, data_format=None): """ Performs the max pooling on the input. @@ -870,54 +882,25 @@ def max_pool(input, ksize, strides, padding, data_format=None): A Tensor of format specified by data_format. The max pooled output tensor. """ - maxpool_obj = MaxPool(ksize, strides, padding, data_format) + maxpool_obj = MaxPool(ksize, strides, padding, return_mask, data_format) return maxpool_obj(input) -def max_pool1d(input, kernel_size, stride=None, padding=0, return_mask=False, ceil_mode=False, data_format='NCL'): +def max_pool1d(input, kernel_size, stride=None, padding=0, return_mask=False, data_format='NCL'): - data_format, padding = preprocess_1d_format(data_format=data_format, padding=padding) - if data_format != 'NCL': - input = torch.permute(input, [0, 2, 1]) - output = F.max_pool1d(input, kernel_size, stride = stride, padding = padding, return_indices=return_mask, ceil_mode=ceil_mode) - if data_format != 'NCL': - if return_mask: - output[0] = torch.permute(output[0], [0, 2, 1]) - output[1] = torch.permute(output[1], [0, 2, 1]) - else: - output = torch.permute(output, [0, 2, 1]) - return output -def max_pool2d(input, kernel_size, stride=None, padding=0, ceil_mode=False, return_mask=False, data_format='NCHW'): - - data_format, padding = preprocess_2d_format(data_format=data_format, padding=padding) - if data_format != 'NCHW': - input = torch.permute(input, [0, 3, 1, 2]) - output = F.max_pool2d( - input, kernel_size, stride=stride, padding=padding, ceil_mode=ceil_mode, return_indices=return_mask - ) - if data_format != 'NCHW': - if return_mask: - output[0] = torch.permute(output[0], [0, 2, 3, 1]) - output[1] = torch.permute(output[1], [0, 2, 3, 1]) - else: - output = torch.permute(output, [0, 2, 3, 1]) - return output + maxpool_obj = MaxPool(kernel_size, stride, padding, return_mask, data_format) + return maxpool_obj(input) -def max_pool3d(input, kernel_size, stride=None, padding=0, ceil_mode=False, return_mask=False, data_format="NCDHW"): - data_format, padding = preprocess_3d_format(data_format=data_format, padding=padding) - if data_format != 'NCDHW': - input = torch.permute(input, [0, 4, 1, 2, 3]) - - output = F.max_pool3d( - input, kernel_size, stride=stride, padding=padding, ceil_mode=ceil_mode, return_indices=return_mask - ) - if data_format != 'NCDHW': - if return_mask: - output[0] = torch.permute(output[0], [0, 2, 3, 4, 1]) - output[1] = torch.permute(output[1], [0, 2, 3, 4, 1]) - else: - output = torch.permute(output, [0, 2, 3, 4, 1]) - return output +def max_pool2d(input, kernel_size, stride=None, padding=0, return_mask=False, data_format='NCHW'): + + + maxpool_obj = MaxPool(kernel_size, stride, padding, return_mask, data_format) + return maxpool_obj(input) + +def max_pool3d(input, kernel_size, stride=None, padding=0, return_mask=False, data_format="NCDHW"): + + maxpool_obj = MaxPool(kernel_size, stride, padding, return_mask, data_format) + return maxpool_obj(input) class AvgPool1d(object): @@ -1021,49 +1004,26 @@ def avg_pool(input, ksize, strides, padding): avg_pool_obj = AvgPool(ksize, strides, padding) return avg_pool_obj(input) -def avg_pool1d(input, kernel_size, stride=None, padding=0, count_include_pad=True, ceil_mode=False, data_format='NCL'): - data_format, padding = preprocess_1d_format(data_format=data_format, padding=padding) - if data_format != 'NCL': - input = torch.permute(input, [0, 2, 1]) - output = F.avg_pool1d( - input, kernel_size, stride = stride, padding = padding, count_include_pad=count_include_pad, ceil_mode=ceil_mode - ) - if data_format != 'NCL': - output = torch.permute(output, [0, 2, 1]) - return output +def avg_pool1d(input, kernel_size, stride=None, padding=0, data_format='NCL'): + data_format, padding = preprocess_1d_format(data_format, padding) + avg_pool_obj = AvgPool(kernel_size, stride, padding, data_format) + return avg_pool_obj(input) -def avg_pool2d( - input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, - divisor_override=None, data_format='NCHW' -): - data_format, padding = preprocess_2d_format(data_format=data_format, padding=padding) - if data_format != 'NCHW': - input = torch.permute(input, [0, 3, 1, 2]) - output = F.avg_pool2d(input, kernel_size, stride = stride, padding = padding, - count_include_pad=count_include_pad, ceil_mode=ceil_mode, - divisor_override=divisor_override) - if data_format != 'NCHW': - output = torch.permute(output, [0, 2, 3, 1]) - return output +def avg_pool2d(input, kernel_size, stride=None, padding=0, data_format='NCHW'): + data_format, padding = preprocess_2d_format(data_format, padding) + avg_pool_obj = AvgPool(kernel_size, stride, padding, data_format) + return avg_pool_obj(input) -def avg_pool3d(input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, - divisor_override=None, data_format='NCDHW' -): - data_format, padding = preprocess_3d_format(data_format=data_format, padding=padding) - if data_format != 'NCDHW': - input = torch.permute(input, [0, 4, 1, 2, 3]) - output = F.avg_pool3d(input, kernel_size, stride=stride, padding=padding, - count_include_pad=count_include_pad, ceil_mode=ceil_mode, - divisor_override=divisor_override) - if data_format != 'NCDHW': - output = torch.permute(output, [0, 2, 3, 4, 1]) - return output +def avg_pool3d(input, kernel_size, stride=None, padding=0, data_format='NCDHW'): + data_format, padding = preprocess_3d_format(data_format, padding) + avg_pool_obj = AvgPool(kernel_size, stride, padding, data_format) + return avg_pool_obj(input) class MaxPool3d(object): - def __init__(self, ksize, strides, padding, data_format=None): + def __init__(self, ksize, strides, padding, return_mask, data_format=None): self.data_format, self.padding = preprocess_3d_format(data_format, padding) - self.max_pool3d = MaxPool(ksize, strides, padding, data_format) + self.max_pool3d = MaxPool(ksize, strides, padding, return_mask, data_format) def __call__(self, inputs): return self.max_pool3d(inputs) @@ -1112,33 +1072,33 @@ def __call__(self, inputs): return self.avg_pool3d_obj(inputs) -def avg_pool3d(input, ksize, strides, padding, data_format=None): - """ - Performs the average pooling on the input. - - Parameters - ---------- - input : tensor - A 5-D Tensor of shape [batch, height, width, channels] and type float32, float64, qint8, quint8, or qint32. - ksize : int or list of ints - An int or list of ints that has length 1, 3 or 5. The size of the window for each dimension of the input tensor. - strides : int or list of ints - An int or list of ints that has length 1, 3 or 5. - The stride of the sliding window for each dimension of the input tensor. - padding : string - 'VALID' or 'SAME'. The padding algorithm. See the "returns" section of tf.ops.convolution for details. - data_format : string - 'NDHWC' and 'NCDHW' are supported. - name : string - Optional name for the operation. - - Returns - ------- - A Tensor with the same type as value. The average pooled output tensor. - """ - - avg_pool_obj = AvgPool(ksize, strides, padding, data_format) - return avg_pool_obj(input) +# def avg_pool3d(input, ksize, strides, padding, data_format=None): +# """ +# Performs the average pooling on the input. +# +# Parameters +# ---------- +# input : tensor +# A 5-D Tensor of shape [batch, height, width, channels] and type float32, float64, qint8, quint8, or qint32. +# ksize : int or list of ints +# An int or list of ints that has length 1, 3 or 5. The size of the window for each dimension of the input tensor. +# strides : int or list of ints +# An int or list of ints that has length 1, 3 or 5. +# The stride of the sliding window for each dimension of the input tensor. +# padding : string +# 'VALID' or 'SAME'. The padding algorithm. See the "returns" section of tf.ops.convolution for details. +# data_format : string +# 'NDHWC' and 'NCDHW' are supported. +# name : string +# Optional name for the operation. +# +# Returns +# ------- +# A Tensor with the same type as value. The average pooled output tensor. +# """ +# +# avg_pool_obj = AvgPool(ksize, strides, padding, data_format) +# return avg_pool_obj(input) def pool(input, window_shape, pooling_type, strides=None, padding='VALID', data_format=None, dilations=None, name=None): diff --git a/tensorlayerx/nn/layers/pooling.py b/tensorlayerx/nn/layers/pooling.py index 8c0d817..4401955 100644 --- a/tensorlayerx/nn/layers/pooling.py +++ b/tensorlayerx/nn/layers/pooling.py @@ -38,6 +38,8 @@ class MaxPool1d(Module): Stride of the pooling operation. padding : str or int The padding method: 'VALID' or 'SAME'. + return_mask : bool + Whether to return the max indices along with the outputs. data_format : str One of channels_last (default, [batch, length, channel]) or channels_first. The ordering of the dimensions in the inputs. name : None or str @@ -58,6 +60,7 @@ def __init__( kernel_size=3, stride=2, padding='SAME', + return_mask = False, data_format='channels_last', name=None # 'maxpool1d' ): @@ -65,18 +68,19 @@ def __init__( self.kernel_size = kernel_size self.stride = stride self.padding = padding + self.return_mask = return_mask self.data_format = data_format self.build() self._built = True logging.info( - "MaxPool1d %s: kernel_size: %s stride: %s padding: %s" % - (self.name, str(kernel_size), str(stride), str(padding)) + "MaxPool1d %s: kernel_size: %s stride: %s padding: %s return_mask: %s" % + (self.name, str(kernel_size), str(stride), str(padding), str(return_mask)) ) def __repr__(self): - s = ('{classname}(kernel_size={kernel_size}' ', stride={stride}, padding={padding}') + s = ('{classname}(kernel_size={kernel_size}' ', stride={stride}, padding={padding}, return_mask={return_mask}') if self.name is not None: s += ', name=\'{name}\'' s += ')' @@ -85,7 +89,8 @@ def __repr__(self): def build(self, inputs_shape=None): # https://tensorflow.google.cn/versions/r2.0/api_docs/python/tf/nn/pool self.max_pool = tlx.ops.MaxPool1d( - ksize=self.kernel_size, strides=self.stride, padding=self.padding, data_format=self.data_format + ksize=self.kernel_size, strides=self.stride, padding=self.padding, + return_mask=self.return_mask, data_format=self.data_format ) def forward(self, inputs): @@ -179,6 +184,8 @@ class MaxPool2d(Module): (height, width) for stride. padding : int、tuple or str The padding method: 'VALID' or 'SAME'. + return_mask : bool + Whether to return the max indices along with the outputs. data_format : str One of channels_last (default, [batch, height, width, channel]) or channels_first. The ordering of the dimensions in the inputs. name : None or str @@ -199,6 +206,7 @@ def __init__( kernel_size=(3, 3), stride=(2, 2), padding='SAME', + return_mask=False, data_format='channels_last', name=None # 'maxpool2d' ): @@ -206,18 +214,19 @@ def __init__( self.kernel_size = self.check_param(kernel_size) self.stride = self.check_param(stride) self.padding = padding + self.return_mask = return_mask self.data_format = data_format self.build() self._built = True logging.info( - "MaxPool2d %s: kernel_size: %s stride: %s padding: %s" % - (self.name, str(kernel_size), str(stride), str(padding)) + "MaxPool2d %s: kernel_size: %s stride: %s padding: %s return_mask: %s" % + (self.name, str(kernel_size), str(stride), str(padding), str(return_mask)) ) def __repr__(self): - s = ('{classname}(kernel_size={kernel_size}' ', stride={stride}, padding={padding}') + s = ('{classname}(kernel_size={kernel_size}' ', stride={stride}, padding={padding}, return_mask={return_mask}') if self.name is not None: s += ', name=\'{name}\'' s += ')' @@ -225,7 +234,8 @@ def __repr__(self): def build(self, inputs_shape=None): self.max_pool = tlx.ops.MaxPool( - ksize=self.kernel_size, strides=self.stride, padding=self.padding, data_format=self.data_format + ksize=self.kernel_size, strides=self.stride, padding=self.padding, + return_mask=self.return_mask, data_format=self.data_format ) def forward(self, inputs): @@ -317,6 +327,8 @@ class MaxPool3d(Module): Strides of the pooling operation. padding : int、tuple or str The padding method: 'VALID' or 'SAME'. + return_mask : bool + Whether to return the max indices along with the outputs. data_format : str One of channels_last (default, [batch, depth, height, width, channel]) or channels_first. The ordering of the dimensions in the inputs. name : None or str @@ -342,6 +354,7 @@ def __init__( kernel_size=(3, 3, 3), stride=(2, 2, 2), padding='VALID', + return_mask = False, data_format='channels_last', name=None # 'maxpool3d' ): @@ -349,18 +362,19 @@ def __init__( self.kernel_size = self.check_param(kernel_size, '3d') self.stride = self.check_param(stride, '3d') self.padding = padding + self.return_mask = return_mask self.data_format = data_format self.build() self._built = True logging.info( - "MaxPool3d %s: kernel_size: %s stride: %s padding: %s" % - (self.name, str(kernel_size), str(stride), str(padding)) + "MaxPool3d %s: kernel_size: %s stride: %s padding: %s return_mask: %s" % + (self.name, str(kernel_size), str(stride), str(padding), str(return_mask)) ) def __repr__(self): - s = ('{classname}(kernel_size={kernel_size}' ', stride={stride}, padding={padding}') + s = ('{classname}(kernel_size={kernel_size}' ', stride={stride}, padding={padding}, return_mask={return_mask}') if self.name is not None: s += ', name=\'{name}\'' s += ')' @@ -368,7 +382,8 @@ def __repr__(self): def build(self, inputs_shape=None): self.max_pool3d = tlx.ops.MaxPool3d( - ksize=self.kernel_size, strides=self.stride, padding=self.padding, data_format=self.data_format + ksize=self.kernel_size, strides=self.stride, padding=self.padding, + return_mask=self.return_mask, data_format=self.data_format ) def forward(self, inputs): From 2aa149a21401aecbe38691dccbac6f7b4f7ff6e7 Mon Sep 17 00:00:00 2001 From: Cheng Lai Date: Wed, 11 Jan 2023 15:52:25 +0800 Subject: [PATCH 11/46] Fix build html docs (#62) --- docs/modules/distributed.rst | 23 - docs/modules/prepro.rst | 641 ---------------------- tensorlayerx/backend/ops/tensorflow_nn.py | 1 - tensorlayerx/model/core.py | 38 +- 4 files changed, 9 insertions(+), 694 deletions(-) delete mode 100644 docs/modules/distributed.rst delete mode 100644 docs/modules/prepro.rst diff --git a/docs/modules/distributed.rst b/docs/modules/distributed.rst deleted file mode 100644 index 3fa68cf..0000000 --- a/docs/modules/distributed.rst +++ /dev/null @@ -1,23 +0,0 @@ -API - Distributed Training -============================= - -(Alpha release - usage might change later) - -Helper API to run a distributed training. -Check these `examples `_. - -.. automodule:: tensorlayerx.utils.distributed - -.. autosummary:: - - Trainer - -Distributed training --------------------- - -Trainer -^^^^^^^^^^^ - -.. autofunction:: Trainer - - diff --git a/docs/modules/prepro.rst b/docs/modules/prepro.rst deleted file mode 100644 index 40e69de..0000000 --- a/docs/modules/prepro.rst +++ /dev/null @@ -1,641 +0,0 @@ -API - Data Pre-Processing -========================= - -.. automodule:: tensorlayerx.utils.prepro - -.. autosummary:: - - affine_rotation_matrix - affine_horizontal_flip_matrix - affine_vertical_flip_matrix - affine_shift_matrix - affine_shear_matrix - affine_zoom_matrix - affine_respective_zoom_matrix - - transform_matrix_offset_center - affine_transform - affine_transform_cv2 - affine_transform_keypoints - projective_transform_by_points - - rotation - rotation_multi - crop - crop_multi - flip_axis - flip_axis_multi - shift - shift_multi - - shear - shear_multi - shear2 - shear_multi2 - swirl - swirl_multi - elastic_transform - elastic_transform_multi - - zoom - respective_zoom - zoom_multi - - brightness - brightness_multi - - illumination - - rgb_to_hsv - hsv_to_rgb - adjust_hue - - imresize - - pixel_value_scale - - samplewise_norm - featurewise_norm - - channel_shift - channel_shift_multi - - drop - - array_to_img - - find_contours - pt2map - binary_dilation - dilation - binary_erosion - erosion - - - obj_box_coord_rescale - obj_box_coords_rescale - obj_box_coord_scale_to_pixelunit - obj_box_coord_centroid_to_upleft_butright - obj_box_coord_upleft_butright_to_centroid - obj_box_coord_centroid_to_upleft - obj_box_coord_upleft_to_centroid - - parse_darknet_ann_str_to_list - parse_darknet_ann_list_to_cls_box - - obj_box_horizontal_flip - obj_box_imresize - obj_box_crop - obj_box_shift - obj_box_zoom - - keypoint_random_crop - keypoint_resize_random_crop - keypoint_random_rotate - keypoint_random_flip - keypoint_random_resize - keypoint_random_resize_shortestedge - - pad_sequences - remove_pad_sequences - process_sequences - sequences_add_start_id - sequences_add_end_id - sequences_add_end_id_after_pad - sequences_get_mask - - -.. - Threading - ------------ - .. autofunction:: threading_data - - -Affine Transform ----------------- - - -Python can be FAST -^^^^^^^^^^^^^^^^^^ - -Image augmentation is a critical step in deep learning. -Though TensorFlow has provided ``tf.image``, -image augmentation often remains as a key bottleneck. -``tf.image`` has three limitations: - -- Real-world visual tasks such as object detection, segmentation, and pose estimation - must cope with image meta-data (e.g., coordinates). - These data are beyond ``tf.image`` - which processes images as tensors. - -- ``tf.image`` operators - breaks the pure Python programing experience (i.e., users have to - use ``tf.py_func`` in order to call image functions written in Python); however, - frequent uses of ``tf.py_func`` slow down TensorFlow, - making users hard to balance flexibility and performance. - -- ``tf.image`` API is inflexible. Image operations are - performed in an order. They are hard to jointly optimize. More importantly, - sequential image operations can significantly - reduces the quality of images, thus affecting training accuracy. - - -TensorLayer addresses these limitations by providing a -high-performance image augmentation API in Python. -This API bases on affine transformation and ``cv2.wrapAffine``. -It allows you to combine multiple image processing functions into -a single matrix operation. This combined operation -is executed by the fast ``cv2`` library, offering 78x performance improvement (observed in -`openpose-plus `_ for example). -The following example illustrates the rationale -behind this tremendous speed up. - - -Example -^^^^^^^ - -The source code of complete examples can be found \ -`here `__. -The following is a typical Python program that applies rotation, shifting, flipping, zooming and shearing to an image, - -.. code-block:: python - - image = tlx.vis.read_image('tiger.jpeg') - - xx = tlx.prepro.rotation(image, rg=-20, is_random=False) - xx = tlx.prepro.flip_axis(xx, axis=1, is_random=False) - xx = tlx.prepro.shear2(xx, shear=(0., -0.2), is_random=False) - xx = tlx.prepro.zoom(xx, zoom_range=0.8) - xx = tlx.prepro.shift(xx, wrg=-0.1, hrg=0, is_random=False) - - tlx.vis.save_image(xx, '_result_slow.png') - - -However, by leveraging affine transformation, image operations can be combined into one: - -.. code-block:: python - - # 1. Create required affine transformation matrices - M_rotate = tlx.prepro.affine_rotation_matrix(angle=20) - M_flip = tlx.prepro.affine_horizontal_flip_matrix(prob=1) - M_shift = tlx.prepro.affine_shift_matrix(wrg=0.1, hrg=0, h=h, w=w) - M_shear = tlx.prepro.affine_shear_matrix(x_shear=0.2, y_shear=0) - M_zoom = tlx.prepro.affine_zoom_matrix(zoom_range=0.8) - - # 2. Combine matrices - # NOTE: operations are applied in a reversed order (i.e., rotation is performed first) - M_combined = M_shift.dot(M_zoom).dot(M_shear).dot(M_flip).dot(M_rotate) - - # 3. Convert the matrix from Cartesian coordinates (the origin in the middle of image) - # to image coordinates (the origin on the top-left of image) - transform_matrix = tlx.prepro.transform_matrix_offset_center(M_combined, x=w, y=h) - - # 4. Transform the image using a single operation - result = tlx.prepro.affine_transform_cv2(image, transform_matrix) # 76 times faster - - tlx.vis.save_image(result, '_result_fast.png') - - -The following figure illustrates the rational behind combined affine transformation. - -.. image:: ../images/affine_transform_why.jpg - :width: 100 % - :align: center - - -Using combined affine transformation has two key benefits. First, it allows \ -you to leverage a pure Python API to achieve orders of magnitudes of speed up in image augmentation, -and thus prevent data pre-processing from becoming a bottleneck in training. \ -Second, performing sequential image transformation requires multiple image interpolations. \ -This produces low-quality input images. In contrast, a combined transformation performs the \ -interpolation only once, and thus -preserve the content in an image. The following figure illustrates these two benefits: - -.. image:: ../images/affine_transform_comparison.jpg - :width: 100 % - :align: center - -The major reason for combined affine transformation being fast is because it has lower computational complexity. -Assume we have ``k`` affine transformations ``T1, ..., Tk``, where ``Ti`` can be represented by 3x3 matrixes. -The sequential transformation can be represented as ``y = Tk (... T1(x))``, -and the time complexity is ``O(k N)`` where ``N`` is the cost of applying one transformation to image ``x``. -``N`` is linear to the size of ``x``. -For the combined transformation ``y = (Tk ... T1) (x)`` -the time complexity is ``O(27(k - 1) + N) = max{O(27k), O(N)} = O(N)`` (assuming 27k << N) where 27 = 3^3 is the cost for combining two transformations. - - -Get rotation matrix -^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: affine_rotation_matrix - -Get horizontal flipping matrix -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: affine_horizontal_flip_matrix - -Get vertical flipping matrix -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: affine_vertical_flip_matrix - -Get shifting matrix -^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: affine_shift_matrix - -Get shearing matrix -^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: affine_shear_matrix - -Get zooming matrix -^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: affine_zoom_matrix - -Get respective zooming matrix -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: affine_respective_zoom_matrix - -Cartesian to image coordinates -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: transform_matrix_offset_center - -.. - Apply image transform - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - .. autofunction:: affine_transform - -Apply image transform -^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: affine_transform_cv2 - -Apply keypoint transform -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: affine_transform_keypoints - - -Images ------------ - -Projective transform by points -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: projective_transform_by_points - -Rotation -^^^^^^^^^ -.. autofunction:: rotation -.. autofunction:: rotation_multi - -Crop -^^^^^^^^^ -.. autofunction:: crop -.. autofunction:: crop_multi - -Flip -^^^^^^^^^ -.. autofunction:: flip_axis -.. autofunction:: flip_axis_multi - -Shift -^^^^^^^^^ -.. autofunction:: shift -.. autofunction:: shift_multi - -Shear -^^^^^^^^^ -.. autofunction:: shear -.. autofunction:: shear_multi - -Shear V2 -^^^^^^^^^^^ -.. autofunction:: shear2 -.. autofunction:: shear_multi2 - -Swirl -^^^^^^^^^ -.. autofunction:: swirl -.. autofunction:: swirl_multi - -Elastic transform -^^^^^^^^^^^^^^^^^^ -.. autofunction:: elastic_transform -.. autofunction:: elastic_transform_multi - -Zoom -^^^^^^^^^ -.. autofunction:: zoom -.. autofunction:: zoom_multi - -Respective Zoom -^^^^^^^^^^^^^^^^^ -.. autofunction:: respective_zoom - -Brightness -^^^^^^^^^^^^ -.. autofunction:: brightness -.. autofunction:: brightness_multi - -Brightness, contrast and saturation -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: illumination - -RGB to HSV -^^^^^^^^^^^^^^ -.. autofunction:: rgb_to_hsv - -HSV to RGB -^^^^^^^^^^^^^^ -.. autofunction:: hsv_to_rgb - -Adjust Hue -^^^^^^^^^^^^^^ -.. autofunction:: adjust_hue - -Resize -^^^^^^^^^^^^ -.. autofunction:: imresize - -Pixel value scale -^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: pixel_value_scale - -Normalization -^^^^^^^^^^^^^^^ -.. autofunction:: samplewise_norm -.. autofunction:: featurewise_norm - -Channel shift -^^^^^^^^^^^^^^ -.. autofunction:: channel_shift -.. autofunction:: channel_shift_multi - -Noise -^^^^^^^^^^^^^^ -.. autofunction:: drop - -Numpy and PIL -^^^^^^^^^^^^^^ -.. autofunction:: array_to_img - -Find contours -^^^^^^^^^^^^^^ -.. autofunction:: find_contours - -Points to Image -^^^^^^^^^^^^^^^^^ -.. autofunction:: pt2map - -Binary dilation -^^^^^^^^^^^^^^^^^ -.. autofunction:: binary_dilation - -Greyscale dilation -^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: dilation - -Binary erosion -^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: binary_erosion - -Greyscale erosion -^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: erosion - - - -Object detection -------------------- - -Tutorial for Image Aug -^^^^^^^^^^^^^^^^^^^^^^^ - -Hi, here is an example for image augmentation on VOC dataset. - -.. code-block:: python - - import tensorlayer as tl - - ## download VOC 2012 dataset - imgs_file_list, _, _, _, classes, _, _,\ - _, objs_info_list, _ = tlx.files.load_voc_dataset(dataset="2012") - - ## parse annotation and convert it into list format - ann_list = [] - for info in objs_info_list: - ann = tlx.prepro.parse_darknet_ann_str_to_list(info) - c, b = tlx.prepro.parse_darknet_ann_list_to_cls_box(ann) - ann_list.append([c, b]) - - # read and save one image - idx = 2 # you can select your own image - image = tlx.vis.read_image(imgs_file_list[idx]) - tlx.vis.draw_boxes_and_labels_to_image(image, ann_list[idx][0], - ann_list[idx][1], [], classes, True, save_name='_im_original.png') - - # left right flip - im_flip, coords = tlx.prepro.obj_box_horizontal_flip(image, - ann_list[idx][1], is_rescale=True, is_center=True, is_random=False) - tlx.vis.draw_boxes_and_labels_to_image(im_flip, ann_list[idx][0], - coords, [], classes, True, save_name='_im_flip.png') - - # resize - im_resize, coords = tlx.prepro.obj_box_imresize(image, - coords=ann_list[idx][1], size=[300, 200], is_rescale=True) - tlx.vis.draw_boxes_and_labels_to_image(im_resize, ann_list[idx][0], - coords, [], classes, True, save_name='_im_resize.png') - - # crop - im_crop, clas, coords = tlx.prepro.obj_box_crop(image, ann_list[idx][0], - ann_list[idx][1], wrg=200, hrg=200, - is_rescale=True, is_center=True, is_random=False) - tlx.vis.draw_boxes_and_labels_to_image(im_crop, clas, coords, [], - classes, True, save_name='_im_crop.png') - - # shift - im_shfit, clas, coords = tlx.prepro.obj_box_shift(image, ann_list[idx][0], - ann_list[idx][1], wrg=0.1, hrg=0.1, - is_rescale=True, is_center=True, is_random=False) - tlx.vis.draw_boxes_and_labels_to_image(im_shfit, clas, coords, [], - classes, True, save_name='_im_shift.png') - - # zoom - im_zoom, clas, coords = tlx.prepro.obj_box_zoom(image, ann_list[idx][0], - ann_list[idx][1], zoom_range=(1.3, 0.7), - is_rescale=True, is_center=True, is_random=False) - tlx.vis.draw_boxes_and_labels_to_image(im_zoom, clas, coords, [], - classes, True, save_name='_im_zoom.png') - - -In practice, you may want to use threading method to process a batch of images as follows. - -.. code-block:: python - - import tensorlayer as tl - import random - - batch_size = 64 - im_size = [416, 416] - n_data = len(imgs_file_list) - jitter = 0.2 - def _data_pre_aug_fn(data): - im, ann = data - clas, coords = ann - ## change image brightness, contrast and saturation randomly - im = tlx.prepro.illumination(im, gamma=(0.5, 1.5), - contrast=(0.5, 1.5), saturation=(0.5, 1.5), is_random=True) - ## flip randomly - im, coords = tlx.prepro.obj_box_horizontal_flip(im, coords, - is_rescale=True, is_center=True, is_random=True) - ## randomly resize and crop image, it can have same effect as random zoom - tmp0 = random.randint(1, int(im_size[0]*jitter)) - tmp1 = random.randint(1, int(im_size[1]*jitter)) - im, coords = tlx.prepro.obj_box_imresize(im, coords, - [im_size[0]+tmp0, im_size[1]+tmp1], is_rescale=True, - interp='bicubic') - im, clas, coords = tlx.prepro.obj_box_crop(im, clas, coords, - wrg=im_size[1], hrg=im_size[0], is_rescale=True, - is_center=True, is_random=True) - ## rescale value from [0, 255] to [-1, 1] (optional) - im = im / 127.5 - 1 - return im, [clas, coords] - - # randomly read a batch of image and the corresponding annotations - idexs = tlx.utils.get_random_int(min=0, max=n_data-1, number=batch_size) - b_im_path = [imgs_file_list[i] for i in idexs] - b_images = tlx.prepro.threading_data(b_im_path, fn=tlx.vis.read_image) - b_ann = [ann_list[i] for i in idexs] - - # threading process - data = tlx.prepro.threading_data([_ for _ in zip(b_images, b_ann)], - _data_pre_aug_fn) - b_images2 = [d[0] for d in data] - b_ann = [d[1] for d in data] - - # save all images - for i in range(len(b_images)): - tlx.vis.draw_boxes_and_labels_to_image(b_images[i], - ann_list[idexs[i]][0], ann_list[idexs[i]][1], [], - classes, True, save_name='_bbox_vis_%d_original.png' % i) - tlx.vis.draw_boxes_and_labels_to_image((b_images2[i]+1)*127.5, - b_ann[i][0], b_ann[i][1], [], classes, True, - save_name='_bbox_vis_%d.png' % i) - -Image Aug with TF Dataset API -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- Example code for VOC `here `__. - -Coordinate pixel unit to percentage -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: obj_box_coord_rescale - -Coordinates pixel unit to percentage -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: obj_box_coords_rescale - -Coordinate percentage to pixel unit -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: obj_box_coord_scale_to_pixelunit - -Coordinate [x_center, x_center, w, h] to up-left button-right -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: obj_box_coord_centroid_to_upleft_butright - -Coordinate up-left button-right to [x_center, x_center, w, h] -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: obj_box_coord_upleft_butright_to_centroid - -Coordinate [x_center, x_center, w, h] to up-left-width-high -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: obj_box_coord_centroid_to_upleft - -Coordinate up-left-width-high to [x_center, x_center, w, h] -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: obj_box_coord_upleft_to_centroid - -Darknet format string to list -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: parse_darknet_ann_str_to_list - -Darknet format split class and coordinate -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: parse_darknet_ann_list_to_cls_box - -Image Aug - Flip -^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: obj_box_horizontal_flip - -Image Aug - Resize -^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: obj_box_imresize - -Image Aug - Crop -^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: obj_box_crop - -Image Aug - Shift -^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: obj_box_shift - -Image Aug - Zoom -^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: obj_box_zoom - -Keypoints ------------- - -Image Aug - Crop -^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: keypoint_random_crop - -Image Aug - Resize then Crop -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: keypoint_resize_random_crop - -Image Aug - Rotate -^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: keypoint_random_rotate - -Image Aug - Flip -^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: keypoint_random_flip - -Image Aug - Resize -^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: keypoint_random_resize - -Image Aug - Resize Shortest Edge -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: keypoint_random_resize_shortestedge - - -Sequence ---------- - -More related functions can be found in ``tensorlayer.nlp``. - -Padding -^^^^^^^^^ -.. autofunction:: pad_sequences - -Remove Padding -^^^^^^^^^^^^^^^^^ -.. autofunction:: remove_pad_sequences - - -Process -^^^^^^^^^ -.. autofunction:: process_sequences - -Add Start ID -^^^^^^^^^^^^^^^ -.. autofunction:: sequences_add_start_id - - -Add End ID -^^^^^^^^^^^^^^^ -.. autofunction:: sequences_add_end_id - -Add End ID after pad -^^^^^^^^^^^^^^^^^^^^^^^ -.. autofunction:: sequences_add_end_id_after_pad - -Get Mask -^^^^^^^^^ -.. autofunction:: sequences_get_mask diff --git a/tensorlayerx/backend/ops/tensorflow_nn.py b/tensorlayerx/backend/ops/tensorflow_nn.py index e33f896..d46ca0c 100644 --- a/tensorlayerx/backend/ops/tensorflow_nn.py +++ b/tensorlayerx/backend/ops/tensorflow_nn.py @@ -2,7 +2,6 @@ # -*- coding: utf-8 -*- import tensorflow as tf -import torch.nn.functional from tensorflow.python.framework import ops from tensorflow.python.ops import math_ops, array_ops from tensorflow.python.training import moving_averages diff --git a/tensorlayerx/model/core.py b/tensorlayerx/model/core.py index 79a226a..01f2a13 100644 --- a/tensorlayerx/model/core.py +++ b/tensorlayerx/model/core.py @@ -2,7 +2,6 @@ # -*- coding: utf-8 -*- from collections.abc import Iterable -from tensorboardX import SummaryWriter from tqdm import trange from tensorlayerx.nn.core.common import _save_weights, _load_weights, \ @@ -93,7 +92,7 @@ def __init__(self, network, loss_fn=None, optimizer=None, metrics=None, **kwargs self.all_weights = network.all_weights self.train_weights = self.network.trainable_weights - def train(self, n_epoch, train_dataset=None, test_dataset=False, print_train_batch=False, print_freq=5, loss_monitor=False): + def train(self, n_epoch, train_dataset=None, test_dataset=False, print_train_batch=False, print_freq=5): if not isinstance(train_dataset, Iterable): raise Exception("Expected type in (train_dataset, Iterable), but got {}.".format(type(train_dataset))) @@ -101,29 +100,25 @@ def train(self, n_epoch, train_dataset=None, test_dataset=False, print_train_bat self.tf_train( n_epoch=n_epoch, train_dataset=train_dataset, network=self.network, loss_fn=self.loss_fn, train_weights=self.train_weights, optimizer=self.optimizer, metrics=self.metrics, - print_train_batch=print_train_batch, print_freq=print_freq, test_dataset=test_dataset, - loss_monitor=loss_monitor + print_train_batch=print_train_batch, print_freq=print_freq, test_dataset=test_dataset ) elif tlx.BACKEND == 'mindspore': self.ms_train( n_epoch=n_epoch, train_dataset=train_dataset, network=self.network, loss_fn=self.loss_fn, train_weights=self.train_weights, optimizer=self.optimizer, metrics=self.metrics, - print_train_batch=print_train_batch, print_freq=print_freq, test_dataset=test_dataset, - loss_monitor=loss_monitor + print_train_batch=print_train_batch, print_freq=print_freq, test_dataset=test_dataset ) elif tlx.BACKEND == 'paddle': self.pd_train( n_epoch=n_epoch, train_dataset=train_dataset, network=self.network, loss_fn=self.loss_fn, train_weights=self.train_weights, optimizer=self.optimizer, metrics=self.metrics, - print_train_batch=print_train_batch, print_freq=print_freq, test_dataset=test_dataset, - loss_monitor=loss_monitor + print_train_batch=print_train_batch, print_freq=print_freq, test_dataset=test_dataset ) elif tlx.BACKEND == 'torch': self.th_train( n_epoch=n_epoch, train_dataset=train_dataset, network=self.network, loss_fn=self.loss_fn, train_weights=self.train_weights, optimizer=self.optimizer, metrics=self.metrics, - print_train_batch=print_train_batch, print_freq=print_freq, test_dataset=test_dataset, - loss_monitor=loss_monitor + print_train_batch=print_train_batch, print_freq=print_freq, test_dataset=test_dataset ) def eval(self, test_dataset): @@ -272,7 +267,7 @@ def load_weights(self, file_path, format=None, in_order=True, skip=False): def tf_train( self, n_epoch, train_dataset, network, loss_fn, train_weights, optimizer, metrics, print_train_batch, - print_freq, test_dataset, loss_monitor + print_freq, test_dataset ): with Progress(TextColumn("[progress.description]{task.description}"), BarColumn(), @@ -344,13 +339,9 @@ def tf_train( progress.reset(batch_tqdm) - if loss_monitor: - writer.export_scalars_to_json("./all_scalars.json") - writer.close() - def ms_train( self, n_epoch, train_dataset, network, loss_fn, train_weights, optimizer, metrics, print_train_batch, - print_freq, test_dataset, loss_monitor + print_freq, test_dataset ): net_with_criterion = WithLoss(network, loss_fn) train_network = GradWrap(net_with_criterion, network.trainable_weights) @@ -420,13 +411,9 @@ def ms_train( progress.reset(batch_tqdm) - if loss_monitor: - writer.export_scalars_to_json("./all_scalars.json") - writer.close() - def pd_train( self, n_epoch, train_dataset, network, loss_fn, train_weights, optimizer, metrics, print_train_batch, - print_freq, test_dataset, loss_monitor + print_freq, test_dataset ): with Progress(TextColumn("[progress.description]{task.description}"), BarColumn(), @@ -495,13 +482,9 @@ def pd_train( progress.reset(batch_tqdm) - if loss_monitor: - writer.export_scalars_to_json("./all_scalars.json") - writer.close() - def th_train( self, n_epoch, train_dataset, network, loss_fn, train_weights, optimizer, metrics, print_train_batch, - print_freq, test_dataset, loss_monitor + print_freq, test_dataset ): # device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') # network = network.to(device) @@ -570,9 +553,6 @@ def th_train( progress.reset(batch_tqdm) - if loss_monitor: - writer.export_scalars_to_json("./all_scalars.json") - writer.close() class WithGrad(object): """Module that returns the gradients. From eb12fc7478a6ff5a6898e3d701649e420055beab Mon Sep 17 00:00:00 2001 From: Jiarong Han Date: Wed, 11 Jan 2023 17:16:35 +0800 Subject: [PATCH 12/46] update conv2dtranspose (#63) * add conv2d output_padding/group/output_size * fix bug * fix __init__ --- tensorlayerx/backend/__init__.py | 1 + tensorlayerx/backend/ops/__init__.py | 3 +- tensorlayerx/backend/ops/mindspore_nn.py | 94 ++--------- tensorlayerx/backend/ops/oneflow_nn.py | 9 +- tensorlayerx/backend/ops/paddle_nn.py | 30 ++-- tensorlayerx/backend/ops/tensorflow_nn.py | 132 ++++++++------- tensorlayerx/backend/ops/torch_nn.py | 150 ++++++++++++++++-- .../nn/layers/convolution/simplified_conv.py | 38 ++++- 8 files changed, 280 insertions(+), 177 deletions(-) diff --git a/tensorlayerx/backend/__init__.py b/tensorlayerx/backend/__init__.py index c9a900f..7858994 100644 --- a/tensorlayerx/backend/__init__.py +++ b/tensorlayerx/backend/__init__.py @@ -220,5 +220,6 @@ from .ops import max_pool1d from .ops import max_pool2d from .ops import max_pool3d +from .ops import conv2d_transpose from tensorlayerx.backend import ops \ No newline at end of file diff --git a/tensorlayerx/backend/ops/__init__.py b/tensorlayerx/backend/ops/__init__.py index 5a9a9d5..bed367f 100644 --- a/tensorlayerx/backend/ops/__init__.py +++ b/tensorlayerx/backend/ops/__init__.py @@ -281,4 +281,5 @@ from .load_backend import avg_pool3d from .load_backend import max_pool1d from .load_backend import max_pool2d -from .load_backend import max_pool3d \ No newline at end of file +from .load_backend import max_pool3d +from .load_backend import conv2d_transpose \ No newline at end of file diff --git a/tensorlayerx/backend/ops/mindspore_nn.py b/tensorlayerx/backend/ops/mindspore_nn.py index 06b71a8..7173b1d 100644 --- a/tensorlayerx/backend/ops/mindspore_nn.py +++ b/tensorlayerx/backend/ops/mindspore_nn.py @@ -1129,7 +1129,8 @@ def conv1d_transpose( class Conv2d_transpose(Cell): - def __init__(self, strides, padding, data_format, dilations=None, out_channel=None, k_size=None, in_channels=None): + def __init__(self, strides, padding, data_format, dilations=None, out_channel=None, k_size=None, + in_channels=None, groups = 1, output_padding = 0,): super(Conv2d_transpose, self).__init__() self.data_format, self.padding = preprocess_2d_format(data_format, padding) self.in_channels = in_channels @@ -1137,6 +1138,8 @@ def __init__(self, strides, padding, data_format, dilations=None, out_channel=No self.k_size = k_size self.strides = strides self.dilations = dilations + self.groups = groups + self.output_padding = output_padding if self.data_format == 'NHWC': raise NotImplementedError("The optional value for data format. Currently only support “NCWH”.") @@ -1160,14 +1163,16 @@ def __init__(self, strides, padding, data_format, dilations=None, out_channel=No pad=self.pad, stride=self.strides, dilation=self.dilations, - group=1) + group=self.groups) if isinstance(self.padding, int): self.padding_top, self.padding_bottom, self.padding_left, self.padding_right = (self.padding,) * 4 else: self.padding_top, self.padding_bottom = (self.padding[0],) * 2 self.padding_left, self.padding_right = (self.padding[1],) * 2 - def construct(self, x, filters): + def construct(self, x, filters, output_size): + if output_size is not None: + raise NotImplementedError n, _, h, w = P.Shape()(x) h_out = self._deconv_output_length(self.is_valid, self.is_same, self.is_pad, h, self.k_size[0], self.strides[0], self.dilations[0], self.padding_top + self.padding_bottom) @@ -1193,85 +1198,8 @@ def _deconv_output_length(self, is_valid, is_same, is_pad, input_length, filter_ return length -# class Conv2d_transpose(Cell): -# -# def __init__(self, strides, padding, data_format, dilations=None, out_channel=None, k_size=None, in_channels=None): -# super(Conv2d_transpose, self).__init__() -# self.data_format, self.padding = preprocess_2d_format(data_format, padding) -# self.in_channels = in_channels -# self.out_channel = out_channel -# self.k_size = k_size -# self.strides = strides -# self.dilations = dilations -# -# if self.data_format == 'NHWC': -# raise NotImplementedError("The optional value for data format. Currently only support “NCWH”.") -# -# self.conv2d_transpose = P.Conv2DBackpropInput( -# out_channel=self.in_channels, kernel_size=self.k_size, pad_mode=self.padding, stride=self.strides, -# dilation=self.dilations, mode=1, group=1, data_format=self.data_format -# ) -# self.shape = P.Shape() -# -# def _deconv_output_length(self, input_length, filter_size, stride_size, dilation_size): -# length = 0 -# filter_size = filter_size + (filter_size - 1) * (dilation_size - 1) -# -# if self.padding == 'same': -# length = input_length * stride_size -# elif self.padding == 'valid': -# length = input_length * stride_size + max(filter_size - stride_size, 0) -# -# return length -# -# def construct(self, x, filters): -# if self.data_format == 'NHWC': -# h_axis, w_axis = 1, 2 -# n, h, w, _ = self.shape(x) -# else: -# h_axis, w_axis = 2, 3 -# n, _, h, w = self.shape(x) -# -# if isinstance(self.strides, int): -# strides_h = self.strides -# strides_w = self.strides -# else: -# strides_list = list(self.strides) -# if len(strides_list) == 2: -# strides_h = strides_list[0] -# strides_w = strides_list[1] -# elif len(strides_list) == 4: -# strides_h = strides_list[h_axis] -# strides_w = strides_list[w_axis] -# -# if self.dilations is not None: -# if isinstance(self.dilations, int): -# dilations_h = self.dilations -# dilations_w = self.dilations -# else: -# dilations_list = list(self.dilations) -# if len(dilations_list) == 2: -# dilations_h = dilations_list[0] -# dilations_w = dilations_list[1] -# elif len(dilations_list) == 4: -# dilations_h = dilations_list[h_axis] -# dilations_w = dilations_list[w_axis] -# -# h_out = self._deconv_output_length(h, self.k_size[0], strides_h, dilations_h) -# w_out = self._deconv_output_length(w, self.k_size[1], strides_w, dilations_w) -# -# if self.data_format == 'NCHW': -# output_size = (n, self.out_channel, h_out, w_out) -# else: -# output_size = (n, h_out, w_out, self.out_channel) -# output = self.conv2d_transpose(x, filters, output_size) -# -# return output - - -def conv2d_transpose( - input, filters, output_shape, strides, padding='SAME', data_format='NHWC', dilations=None, name=None -): + +def conv2d_transpose(x, weight, bias=None, stride=1, padding=0, output_padding=0, groups=1, dilation=1, data_format='NCHW', output_size=None): """ The transpose of conv2d. @@ -1303,7 +1231,7 @@ def conv2d_transpose( ------- A Tensor with the same type as input. """ - pass + raise NotImplementedError class Conv3d_transpose(Cell): diff --git a/tensorlayerx/backend/ops/oneflow_nn.py b/tensorlayerx/backend/ops/oneflow_nn.py index a4c14e8..250e6bd 100644 --- a/tensorlayerx/backend/ops/oneflow_nn.py +++ b/tensorlayerx/backend/ops/oneflow_nn.py @@ -1313,14 +1313,16 @@ class Conv2d_transpose(object): def __init__( self, strides, padding, data_format='NHWC', dilations=None, name=None, out_channel=None, k_size=None, - in_channels=None + in_channels=None, groups = 1, output_padding = 0, ): self.strides = strides self.dilations = dilations self.name = name self.data_format, self.padding = preprocess_2d_format(data_format, padding) + self.groups = groups + self.output_padding = output_padding - def __call__(self, input, filters): + def __call__(self, input, filters, output_size): if self.data_format == 'NHWC': input = nhwc_to_nchw(input) if self.padding == 'same': @@ -1385,8 +1387,7 @@ def conv2d_transpose( A Tensor with the same type as input. """ - conv2d_transpose_obj = Conv2d_transpose(strides, padding, data_format, dilations) - return conv2d_transpose_obj(input, filters) + raise NotImplementedError class Conv3d_transpose(object): diff --git a/tensorlayerx/backend/ops/paddle_nn.py b/tensorlayerx/backend/ops/paddle_nn.py index 2fc179e..054737f 100644 --- a/tensorlayerx/backend/ops/paddle_nn.py +++ b/tensorlayerx/backend/ops/paddle_nn.py @@ -1010,24 +1010,29 @@ def conv1d_transpose( class Conv2d_transpose(object): def __init__( - self, strides, padding, data_format='NHWC', dilations=None, name=None, out_channel=None, k_size=None, - in_channels=None + self, strides, padding, data_format='NHWC', dilations=None, name=None, out_channels=None, k_size=None, + in_channels=None, groups = 1, output_padding = 0, ): self.strides = strides self.dilations = dilations self.data_format, self.padding = preprocess_2d_format(data_format, padding) + self.groups = groups + self.output_padding = output_padding + + def __call__(self, input, filters, output_size): + if output_size is None: + self.output_padding = self.output_padding + else: + self.output_padding = 0 - def __call__(self, input, filters): output = F.conv2d_transpose( x=input, weight=filters, stride=self.strides, padding=self.padding, dilation=self.dilations, - data_format=self.data_format + data_format=self.data_format, groups=self.groups, output_size=output_size, output_padding=self.output_padding ) return output -def conv2d_transpose( - input, filters, output_shape, strides, padding='SAME', data_format='NHWC', dilations=None, name=None -): +def conv2d_transpose(x, weight, bias=None, stride=1, padding=0, output_padding=0, groups=1, dilation=1, data_format='NCHW', output_size=None): """ The transpose of conv2d. @@ -1062,11 +1067,14 @@ def conv2d_transpose( data_format, padding = preprocess_2d_format(data_format, padding) output = F.conv2d_transpose( x=input, - weight=filters, - output_size=output_shape, - stride=strides, + weight=weight, + bias=bias, + stride=stride, padding=padding, - dilation=dilations, + output_padding=output_padding, + dilation=dilation, + groups=groups, + output_size=output_size, data_format=data_format, ) return output diff --git a/tensorlayerx/backend/ops/tensorflow_nn.py b/tensorlayerx/backend/ops/tensorflow_nn.py index d46ca0c..53e5dea 100644 --- a/tensorlayerx/backend/ops/tensorflow_nn.py +++ b/tensorlayerx/backend/ops/tensorflow_nn.py @@ -1417,16 +1417,36 @@ def conv1d_transpose( class Conv2d_transpose(object): def __init__( - self, strides, padding, data_format='NHWC', dilations=None, name=None, out_channel=None, k_size=None, - in_channels=None + self, strides, padding, data_format='NHWC', dilations=None, name=None, out_channels=None, k_size=None, + in_channels=None, groups = 1, output_padding = 0, ): self.strides = strides self.dilations = dilations self.name = name self.data_format, self.padding = preprocess_2d_format(data_format, padding) self._padding = padding + self.groups = groups + if groups != 1: + raise NotImplementedError + self.output_padding = output_padding + self.out_channel = out_channels + self.in_channel = in_channels - def __call__(self, input, filters): + def _output_padding(self, output_shape, output_size): + + if len(output_size) != 2: + raise ValueError( + "ConvTranspose2D: for 4D input, output_size must have 2 elements (got {})" + .format(len(output_size))) + res = [] + for i in range(2): + if output_size[i] < output_shape[i]: + ValueError( + "output size must greater than {}".format(output_shape)) + res.append(output_size[i] - output_shape[i]) + return tuple(res) + + def __call__(self, input, filters, output_size = None): if self.data_format == 'NHWC': h_axis, w_axis = 1, 2 else: @@ -1437,9 +1457,9 @@ def __call__(self, input, filters): batch_size = input.shape[0] input_h, input_w = input_shape[h_axis], input_shape[w_axis] kernel_h, kernel_w = filters_shape[0], filters_shape[1] - output_channels = filters_shape[2] dilations_h, dilations_w = 1, 1 + if isinstance(self.strides, int): strides_h = self.strides strides_w = self.strides @@ -1487,18 +1507,39 @@ def __call__(self, input, filters): self.padding = [[0, 0], [self._padding[0], self._padding[0]],[self._padding[1], self._padding[1]], [0, 0]] if self.data_format == 'NCHW': - out_shape = (batch_size, output_channels, output_h, output_w) + out_shape = (batch_size, self.out_channel, output_h, output_w) else: - out_shape = (batch_size, output_h, output_w, output_channels) - - output_shape = tf.stack(out_shape) - - outputs = tf.nn.conv2d_transpose( - input=input, filters=filters, output_shape=output_shape, strides=self.strides, padding=self.padding, - data_format=self.data_format, dilations=self.dilations, name=self.name - ) - return outputs + out_shape = (batch_size, output_h, output_w, self.out_channel) + if output_size is None: + output_padding = preprocess_padding(self.output_padding, '2d', self.data_format) + if self.data_format == 'NHWC': + output_padding[1][1] = 0 + output_padding[2][1] = 0 + else: + output_padding[2][1] = 0 + output_padding[3][1] = 0 + outputs = tf.nn.conv2d_transpose( + input=input, filters=filters, output_shape=out_shape, strides=self.strides, padding=self.padding, + data_format=self.data_format, dilations=self.dilations, name=self.name + ) + outputs = tf.pad(outputs, output_padding) + return outputs + else: + output_padding = self._output_padding(output_shape = [output_h, output_w], output_size=output_size) + output_padding = preprocess_padding(output_padding, '2d', self.data_format) + if self.data_format == 'NHWC': + output_padding[1][1] = 0 + output_padding[2][1] = 0 + else: + output_padding[2][1] = 0 + output_padding[3][1] = 0 + outputs = tf.nn.conv2d_transpose( + input=input, filters=filters, output_shape=out_shape, strides=self.strides, padding=self.padding, + data_format=self.data_format, dilations=self.dilations, name=self.name + ) + outputs = tf.pad(outputs, output_padding) + return outputs def conv2d_transpose( input, filters, output_shape, strides, padding='SAME', data_format='NHWC', dilations=None, name=None @@ -1535,18 +1576,19 @@ def conv2d_transpose( A Tensor with the same type as input. """ - data_format, padding = preprocess_2d_format(data_format, padding) - outputs = tf.nn.conv2d_transpose( - input=input, - filters=filters, - output_shape=output_shape, - strides=strides, - padding=padding, - data_format=data_format, - dilations=dilations, - name=name, - ) - return outputs + # data_format, padding = preprocess_2d_format(data_format, padding) + # outputs = tf.nn.conv2d_transpose( + # input=input, + # filters=filters, + # output_shape=output_shape, + # strides=strides, + # padding=padding, + # data_format=data_format, + # dilations=dilations, + # name=name, + # ) + # return outputs + raise NotImplementedError class Conv3d_transpose(object): @@ -1894,39 +1936,17 @@ def __init__(self, strides, padding, data_format, dilations, out_channel, k_size self.groups = groups if isinstance(padding, int) or isinstance(padding, tuple): self.padding = preprocess_padding(self.padding, '2d', self.data_format) - if self.data_format == 'NHWC': - self.channels_axis = 3 - else: - self.channels_axis = 1 def __call__(self, input, filters): - if self.groups == 1: - outputs = tf.nn.conv2d( - input=input, - filters=filters, - strides=self.strides, - padding=self.padding, - data_format=self.data_format, - dilations=self.dilations, - ) - else: - inputgroups = tf.split(input, num_or_size_splits=self.groups, axis=self.channels_axis) - weightsgroups = tf.split(filters, num_or_size_splits=self.groups, axis=self.channels_axis) - convgroups = [] - for i, k in zip(inputgroups, weightsgroups): - convgroups.append( - tf.nn.conv2d( - input=i, - filters=k, - strides=self.strides, - padding=self.padding, - data_format=self.data_format, - dilations=self.dilations, - ) - ) - outputs = tf.concat(axis=self.channels_axis, values=convgroups) - + outputs = tf.nn.conv2d( + input=input, + filters=filters, + strides=self.strides, + padding=self.padding, + data_format=self.data_format, + dilations=self.dilations, + ) return outputs diff --git a/tensorlayerx/backend/ops/torch_nn.py b/tensorlayerx/backend/ops/torch_nn.py index e82b965..b6155a9 100644 --- a/tensorlayerx/backend/ops/torch_nn.py +++ b/tensorlayerx/backend/ops/torch_nn.py @@ -5,7 +5,8 @@ import torch.nn.functional as F from torch import _VF from torch.nn import Module - +import collections +from itertools import repeat def padding_format(padding): """ @@ -1338,50 +1339,110 @@ def conv1d_transpose( conv1d_transpose_obj = Conv1d_transpose(strides, padding, data_format, dilations) return conv1d_transpose_obj(input, filters) +def _ntuple(n, name="parse"): + def parse(x): + if isinstance(x, collections.abc.Iterable): + return tuple(x) + return tuple(repeat(x, n)) + + parse.__name__ = name + return parse + + +_single = _ntuple(1, "_single") class Conv2d_transpose(object): def __init__( - self, strides, padding, data_format='NHWC', dilations=None, name=None, out_channel=None, k_size=None, - in_channels=None + self, strides, padding, data_format='NHWC', dilations=None, name=None, out_channels=None, k_size=None, + in_channels=None, groups = 1, output_padding = 0, ): self.strides = strides self.dilations = dilations self.name = name self.data_format, self.padding = preprocess_2d_format(data_format, padding) + self.groups = groups + self.output_padding = output_padding - def __call__(self, input, filters): + def _output_padding(self, input, output_size, + stride, padding, kernel_size, + num_spatial_dims, dilation = None): + if output_size is None: + ret = _single(self.output_padding) # converting to list if was not already + else: + has_batch_dim = input.dim() == num_spatial_dims + 2 + num_non_spatial_dims = 2 if has_batch_dim else 1 + if len(output_size) == num_non_spatial_dims + num_spatial_dims: + output_size = output_size[num_non_spatial_dims:] + if len(output_size) != num_spatial_dims: + raise ValueError( + "ConvTranspose{}D: for {}D input, output_size must have {} or {} elements (got {})" + .format(num_spatial_dims, input.dim(), num_spatial_dims, + num_non_spatial_dims + num_spatial_dims, len(output_size))) + + min_sizes = [] + max_sizes = [] + for d in range(num_spatial_dims): + dim_size = ((input.size(d + num_non_spatial_dims) - 1) * stride[d] - + 2 * padding[d] + + (dilation[d] if dilation is not None else 1) * (kernel_size[d] - 1) + 1) + min_sizes.append(dim_size) + max_sizes.append(min_sizes[d] + stride[d] - 1) + + for i in range(len(output_size)): + size = output_size[i] + min_size = min_sizes[i] + max_size = max_sizes[i] + if size < min_size or size > max_size: + raise ValueError(( + "requested an output size of {}, but valid sizes range " + "from {} to {} (for an input of {})").format( + output_size, min_sizes, max_sizes, input.size()[2:])) + + res = [] + for d in range(num_spatial_dims): + res.append(output_size[d] - min_sizes[d]) + + ret = res + return ret + + def __call__(self, input, filters, output_size): if self.data_format == 'NHWC': input = nhwc_to_nchw(input) if self.padding == 'same': - out = self.conv2d_transpore_same(input, filters) + out = self.conv2d_transpore_same(input, filters, output_size) else: + out_padding = self._output_padding(input, output_size, self.strides, (0 if isinstance(self.padding, str) else self.padding), + filters.shape, + 2, self.dilations) out = F.conv_transpose2d( input, weight=filters, padding=(0 if isinstance(self.padding, str) else self.padding), stride=self.strides, - dilation=self.dilations + dilation=self.dilations, + output_padding = out_padding, + groups = self.groups ) if self.data_format == 'NHWC': out = nchw_to_nhwc(out) return out - def conv2d_transpore_same(self,input, filters): + def conv2d_transpore_same(self,input, filters, output_size): rows_odd, cols_odd, padding_rows, padding_cols = same_padding_deconvolution(input, filters, self.strides, (1, 1)) if rows_odd or cols_odd: input = F.pad(input, [0, int(rows_odd), 0, int(cols_odd)]) out_padding = 0 else: out_padding = 1 + out_padding = self._output_padding(input, output_size, self.strides, (padding_rows // 2, padding_cols // 2), filters.shape, + 2, self.dilations) out = F.conv_transpose2d(input, weight=filters, padding=(padding_rows // 2, padding_cols // 2), stride=self.strides, - dilation=self.dilations, output_padding=out_padding) + dilation=self.dilations, output_padding=out_padding, groups=self.groups) return out -def conv2d_transpose( - input, filters, output_shape, strides, padding='SAME', data_format='NHWC', dilations=None, name=None -): +def conv2d_transpose(x, weight, bias=None, stride=1, padding=0, output_padding=0, groups=1, dilation=1, data_format='NCHW', output_size=None): """ The transpose of conv2d. @@ -1413,10 +1474,71 @@ def conv2d_transpose( ------- A Tensor with the same type as input. """ + data_format, padding = preprocess_2d_format(data_format, padding) + if isinstance(padding, str): + raise ValueError("padding should be int or tuple of int.") + def _output_padding(input, output_size, + stride, padding, kernel_size, + num_spatial_dims, dilation = None): + if output_size is None: + ret = _single(output_padding) # converting to list if was not already + else: + has_batch_dim = input.dim() == num_spatial_dims + 2 + num_non_spatial_dims = 2 if has_batch_dim else 1 + if len(output_size) == num_non_spatial_dims + num_spatial_dims: + output_size = output_size[num_non_spatial_dims:] + if len(output_size) != num_spatial_dims: + raise ValueError( + "ConvTranspose{}D: for {}D input, output_size must have {} or {} elements (got {})" + .format(num_spatial_dims, input.dim(), num_spatial_dims, + num_non_spatial_dims + num_spatial_dims, len(output_size))) + + min_sizes = [] + max_sizes = [] + for d in range(num_spatial_dims): + dim_size = ((input.size(d + num_non_spatial_dims) - 1) * stride[d] - + 2 * padding[d] + + (dilation[d] if dilation is not None else 1) * (kernel_size[d] - 1) + 1) + min_sizes.append(dim_size) + max_sizes.append(min_sizes[d] + stride[d] - 1) + + for i in range(len(output_size)): + size = output_size[i] + min_size = min_sizes[i] + max_size = max_sizes[i] + if size < min_size or size > max_size: + raise ValueError(( + "requested an output size of {}, but valid sizes range " + "from {} to {} (for an input of {})").format( + output_size, min_sizes, max_sizes, input.size()[2:])) + + res = [] + for d in range(num_spatial_dims): + res.append(output_size[d] - min_sizes[d]) + + ret = res + return ret - conv2d_transpose_obj = Conv2d_transpose(strides, padding, data_format, dilations) - return conv2d_transpose_obj(input, filters) - + if data_format == 'NHWC': + x = nhwc_to_nchw(x) + + out_padding = _output_padding(x, output_size, stride, + padding, + weight.shape[2:], + 2, dilation) + out = F.conv_transpose2d( + x, + weight=weight, + bias = bias, + padding=padding, + stride=stride, + dilation=dilation, + output_padding=out_padding, + groups=groups + ) + if data_format == 'NHWC': + out = nchw_to_nhwc(out) + return out class Conv3d_transpose(object): diff --git a/tensorlayerx/nn/layers/convolution/simplified_conv.py b/tensorlayerx/nn/layers/convolution/simplified_conv.py index 8eb105a..48585e5 100644 --- a/tensorlayerx/nn/layers/convolution/simplified_conv.py +++ b/tensorlayerx/nn/layers/convolution/simplified_conv.py @@ -613,6 +613,10 @@ class ConvTranspose2d(Module): The activation function of this layer. padding : int, tuple or str The padding algorithm type: "SAME" or "VALID". + output_padding : int or list or tuple + Additional size added to one side of each dimension in the output shape. Default: 0. + groups : int + Number of blocked connections from input channels to output channels. Default: 1 data_format : str "channels_last" (NHWC, default) or "channels_first" (NCHW). W_init : initializer or str @@ -641,10 +645,12 @@ def __init__( out_channels=32, kernel_size=(3, 3), stride=(1, 1), + dilation=(1, 1), act=None, padding='SAME', + output_padding=0, + groups=1, data_format='channels_last', - dilation=(1, 1), W_init='truncated_normal', b_init='constant', in_channels=None, @@ -656,6 +662,8 @@ def __init__( self.stride = self.check_param(stride) self.padding = padding self.data_format = data_format + self.output_padding = self.check_param(output_padding) + self.groups = groups self.dilation = self.check_param(dilation) self.W_init = self.str_to_init(W_init) self.b_init = self.str_to_init(b_init) @@ -666,9 +674,10 @@ def __init__( self._built = True logging.info( - "ConvTranspose2d %s: out_channels: %d kernel_size: %s stride: %s pad: %s act: %s" % ( + "ConvTranspose2d %s: out_channels: %d kernel_size: %s stride: %s pad: %s act: %s output_padding: %s groups: %s" % ( self.name, out_channels, str(kernel_size), str(stride), padding, - self.act.__class__.__name__ if self.act is not None else 'No Activation' + self.act.__class__.__name__ if self.act is not None else 'No Activation', + str(output_padding), str(groups) ) ) @@ -676,7 +685,7 @@ def __repr__(self): actstr = self.act.__class__.__name__ if self.act is not None else 'No Activation' s = ( '{classname}(in_channels={in_channels}, out_channels={out_channels}, kernel_size={kernel_size}' - ', stride={stride}, padding={padding}' + ', stride={stride}, padding={padding}, output_padding={output_padding}, groups={groups}' ) if self.dilation != (1, ) * len(self.dilation): s += ', dilation={dilation}' @@ -698,8 +707,20 @@ def build(self, inputs_shape): else: raise Exception("data_format should be either channels_last or channels_first") + + if self.groups < 1: + raise ValueError( + "The groups must be a integer greater than or equal to 1, but we got :{}".format(self.groups) + ) + + if self.out_channels % self.groups != 0: + raise ValueError( + "The channels of output must be divisible by groups, but we got: the channels of output" + "is {}, the groups is {}.".format(self.out_channels, self.groups) + ) + #TODO channels first filter shape [out_channel, in_channel, filter_h, filter_w] - self.filter_shape = (self.kernel_size[0], self.kernel_size[1], self.out_channels, self.in_channels) + self.filter_shape = (self.kernel_size[0], self.kernel_size[1], int(self.out_channels/self.groups), self.in_channels) self.filters = self._get_weights("filters", shape=self.filter_shape, init=self.W_init)#, transposed=True) self.b_init_flag = False @@ -710,21 +731,22 @@ def build(self, inputs_shape): self.conv2d_transpose = tlx.ops.Conv2d_transpose( strides=self.stride, padding=self.padding, data_format=self.data_format, dilations=self.dilation, - out_channel=self.out_channels, k_size=(self.kernel_size[0], self.kernel_size[1]), in_channels=self.in_channels + out_channels=self.out_channels, k_size=(self.kernel_size[0], self.kernel_size[1]), in_channels=self.in_channels, + groups = self.groups, output_padding = self.output_padding ) self.act_init_flag = False if self.act: self.act_init_flag = True - def forward(self, inputs): + def forward(self, inputs, output_size = None): if self._forward_state == False: if self._built == False: self.build(tlx.get_tensor_shape(inputs)) self._built = True self._forward_state = True - outputs = self.conv2d_transpose(inputs, self.filters) + outputs = self.conv2d_transpose(inputs, self.filters, output_size) if self.b_init_flag: outputs = self.bias_add(outputs, self.biases) if self.act_init_flag: From 2986b304b62317b9e14c182f364b2db1454d3448 Mon Sep 17 00:00:00 2001 From: Jiarong Han Date: Thu, 12 Jan 2023 09:56:05 +0800 Subject: [PATCH 13/46] fix docs/vision (#64) --- docs/modules/vision.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/modules/vision.rst b/docs/modules/vision.rst index e76b522..861fc0d 100644 --- a/docs/modules/vision.rst +++ b/docs/modules/vision.rst @@ -57,7 +57,7 @@ Vision Transforms list StandardizePerImage -.. automodule:: tensorlayerx.vision.utils +.. automodule:: tensorlayerx.vision .. ----------------------------------------------------------- .. Vision IO @@ -235,16 +235,16 @@ Vision IO load_image ^^^^^^^^^^^^^^^^^^^^^ -.. autoclass:: load_image +.. autoclass:: tensorlayerx.vision.load_image save_image ^^^^^^^^^^^^^^^^^^^^^ -.. autoclass:: save_image +.. autoclass:: tensorlayerx.vision.save_image load_images ^^^^^^^^^^^^^^^^^^^^^ -.. autoclass:: load_images +.. autoclass:: tensorlayerx.vision.load_images save_image ^^^^^^^^^^^^^^^^^^^^^ -.. autoclass:: save_images \ No newline at end of file +.. autoclass:: tensorlayerx.vision.save_images \ No newline at end of file From a8ba55b2a4128519629499344512ba7327499feb Mon Sep 17 00:00:00 2001 From: Eric_lai Date: Thu, 12 Jan 2023 10:17:36 +0800 Subject: [PATCH 14/46] Add necessary modules --- docs/conf.py | 1 + docs/modules/db.rst | 260 ------------------------------------- tensorlayerx/model/core.py | 1 - 3 files changed, 1 insertion(+), 261 deletions(-) delete mode 100644 docs/modules/db.rst diff --git a/docs/conf.py b/docs/conf.py index ce9d883..2756418 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -72,6 +72,7 @@ 'tensorflow', 'tqdm', 'h5py', + 'rich', # TL C++ Packages 'tensorlayerx.third_party.roi_pooling.roi_pooling.roi_pooling_ops', diff --git a/docs/modules/db.rst b/docs/modules/db.rst deleted file mode 100644 index 2481583..0000000 --- a/docs/modules/db.rst +++ /dev/null @@ -1,260 +0,0 @@ -API - Database -========================= - -This is the alpha version of database management system. -If you have any trouble, please ask for help at `tensorlayer@gmail.com `_ . - -Why Database ----------------- - -TensorLayer is designed for real world production, capable of large scale machine learning applications. -TensorLayer database is introduced to address the many data management challenges in the large scale machine learning projects, such as: - -1. Finding training data from an enterprise data warehouse. -2. Loading large datasets that are beyond the storage limitation of one computer. -3. Managing different models with version control, and comparing them(e.g. accuracy). -4. Automating the process of training, evaluating and deploying machine learning models. - -With the TensorLayer system, we introduce this database technology to address the challenges above. - -The database management system is designed with the following three principles in mind. - -Everything is Data -^^^^^^^^^^^^^^^^^^ - -Data warehouses can store and capture the entire machine learning development process. The data can be categorized as: - -1. Dataset: This includes all the data used for training, validation and prediction. The labels can be manually specified or generated by model prediction. -2. Model architecture: The database includes a table that stores different model architectures, enabling users to reuse the many model development works. -3. Model parameters: This database stores all the model parameters of each epoch in the training step. -4. Tasks: A project usually include many small tasks. Each task contains the necessary information such as hyper-parameters for training or validation. For a training task, typical information includes training data, the model parameter, the model architecture, how many epochs the training task has. Validation, testing and inference are also supported by the task system. -5. Loggings: The logs store all the metrics of each machine learning model, such as the time stamp, loss and accuracy of each batch or epoch. - -TensorLayer database in principle is a keyword based search engine. Each model, parameter, or training data is assigned many tags. -The storage system organizes data into two layers: the index layer, and the blob layer. The index layer stores all the tags and references to the blob storage. The index layer is implemented based on NoSQL document database such as MongoDB. The blob layer stores videos, medical images or label masks in large chunk size, which is usually implemented based on a file system. Our database is based on MongoDB. The blob system is based on the GridFS while the indexes are stored as documents. - - -Everything is identified by Query -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Within the database framework, any entity within the data warehouse, such as the data, model or tasks is specified by the database query language. -As a reference, the query is more space efficient for storage and it can specify multiple objects in a concise way. -Another advantage of such a design is enabling a highly flexible software system. -Many system can be implemented by simply rewriting different components, with many new applications can be implemented just by update the query without modification of any application code. - -.. - A pulling based Stream processing pipeline - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - For large training datasets, we provide a stream interface, which can in theory support an unlimitedly large dataset. - A stream interface, implemented as a python generators, keeps on generating new data during training. - When using the stream interface, the idea of epoch does not apply anymore, instead, we specify the batch size and image a epoch will have a fixed large number of steps. - - Many techniques are introduced behind the stream interface for performance optimization. - The stream interface is based on the database cursor technology. - For every data query, only the cursors are returned immediately, not the actual query results. - The actual data are loaded later when the generators are evaluated. - - The data loading is further optimized in many ways: - - 1. Data are compressed and decompressed, - 2. The data are loaded in bulk model to further optimize the IO traffic - 3. The data argumentation or random sampling are computed on the fly, only after the data are loaded into the local computer memory. - 4. We also introduced simple cache system that stores the recent blob data. - - Based on the stream interface, a continuos machine learning system can be easily implemented. - On a distributed system, the model training, validation and deployment can be run by different computing node which are all running continuously. - The trainer keeps on optimizing the models with new added data, the evaluation node keeps on evaluating the recent generated models and the deployment system keeps pulling the best models from the our database warehouse for application. - -Preparation --------------- - -In principle, the database can be implemented by any document oriented NoSQL database system. -The existing implementation is based on MongoDB. -Further implementations on other databases will be released depending on the progress. -It will be straightforward to port our database system to Google Cloud, AWS and Azure. -The following tutorials are based on the MongoDB implementation. - -Installing and running MongoDB -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The installation instruction of MongoDB can be found at -`MongoDB Docs `__. -There are also many MongoDB services from Amazon or GCP, such as Mongo Atlas from MongoDB -User can also use docker, which is a powerful tool for `deploying software `_ . -After installing MongoDB, a MongoDB management tool with graphic user interface will be extremely useful. -Users can also install Studio3T(MongoChef), which is powerful user interface tool for MongoDB and is free for non-commercial use `studio3t `_. - -Tutorials ----------- - -Connect to the database -^^^^^^^^^^^^^^^^^^^^^^^^^ - -Similar with MongoDB management tools, IP and port number are required for connecting to the database. -To distinguish the different projects, the database instances have a ``project_name`` argument. -In the following example, we connect to MongoDB on a local machine with the IP ``localhost``, and port ``27017`` (this is the default port number of MongoDB). - -.. code-block:: python - - db = tlx.utils.db.TensorHub(ip='localhost', port=27017, dbname='temp', - username=None, password='password', project_name='tutorial') - -Dataset management -^^^^^^^^^^^^^^^^^^^^ - -You can save a dataset into the database and allow all machines to access it. -Apart from the dataset key, you can also insert a custom argument such as version and description, for better managing the datasets. -Note that, all saving functions will automatically save a timestamp, allowing you to load staff (data, model, task) using the timestamp. - -.. code-block:: python - - db.save_dataset(dataset=[X_train, y_train, X_test, y_test], dataset_name='mnist', description='this is a tutorial') - -After saving the dataset, others can access the dataset as followed: - -.. code-block:: python - - dataset = db.find_dataset('mnist') - dataset = db.find_dataset('mnist', version='1.0') - -If you have multiple datasets that use the same dataset key, you can get all of them as followed: - -.. code-block:: python - - datasets = db.find_all_datasets('mnist') - - -Model management -^^^^^^^^^^^^^^^^^^^^^^^^^ - -Save model architecture and parameters into database. -The model architecture is represented by a TL graph, and the parameters are stored as a list of array. - -.. code-block:: python - - db.save_model(net, accuracy=0.8, loss=2.3, name='second_model') - -After saving the model into database, we can load it as follow: - -.. code-block:: python - - net = db.find_model(sess=sess, accuracy=0.8, loss=2.3) - -If there are many models, you can use MongoDB's 'sort' method to find the model you want. -To get the newest or oldest model, you can sort by time: - -.. code-block:: python - - ## newest model - - net = db.find_model(sess=sess, sort=[("time", pymongo.DESCENDING)]) - net = db.find_model(sess=sess, sort=[("time", -1)]) - - ## oldest model - - net = db.find_model(sess=sess, sort=[("time", pymongo.ASCENDING)]) - net = db.find_model(sess=sess, sort=[("time", 1)]) - -If you save the model along with accuracy, you can get the model with the best accuracy as followed: - -.. code-block:: python - - net = db.find_model(sess=sess, sort=[("test_accuracy", -1)]) - -To delete all models in a project: - -.. code-block:: python - - db.delete_model() - -If you want to specify which model you want to delete, you need to put arguments inside. - - -Event / Logging management -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Save training log: - -.. code-block:: python - - db.save_training_log(accuracy=0.33) - db.save_training_log(accuracy=0.44) - -Delete logs that match the requirement: - -.. code-block:: python - - db.delete_training_log(accuracy=0.33) - -Delete all logging of this project: - -.. code-block:: python - - db.delete_training_log() - db.delete_validation_log() - db.delete_testing_log() - -Task distribution -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -A project usually consists of many tasks such as hyper parameter selection. -To make it easier, we can distribute these tasks to several GPU servers. -A task consists of a task script, hyper parameters, desired result and a status. - -A task distributor can push both dataset and tasks into a database, allowing task runners on GPU servers to pull and run. -The following is an example that pushes 3 tasks with different hyper parameters. - -.. code-block:: python - - ## save dataset into database, then allow other servers to use it - X_train, y_train, X_val, y_val, X_test, y_test = tlx.files.load_mnist_dataset(shape=(-1, 784)) - db.save_dataset((X_train, y_train, X_val, y_val, X_test, y_test), 'mnist', description='handwriting digit') - - ## push tasks into database, then allow other servers pull tasks to run - db.create_task( - task_name='mnist', script='task_script.py', hyper_parameters=dict(n_units1=800, n_units2=800), - saved_result_keys=['test_accuracy'], description='800-800' - ) - - db.create_task( - task_name='mnist', script='task_script.py', hyper_parameters=dict(n_units1=600, n_units2=600), - saved_result_keys=['test_accuracy'], description='600-600' - ) - - db.create_task( - task_name='mnist', script='task_script.py', hyper_parameters=dict(n_units1=400, n_units2=400), - saved_result_keys=['test_accuracy'], description='400-400' - ) - - ## wait for tasks to finish - while db.check_unfinished_task(task_name='mnist'): - print("waiting runners to finish the tasks") - time.sleep(1) - - ## you can get the model and result from database and do some analysis at the end - -The task runners on GPU servers can monitor the database, and run the tasks immediately when they are made available. -In the task script, we can save the final model and results to the database, this allows task distributors to get the desired model and results. - -.. code-block:: python - - ## monitors the database and pull tasks to run - while True: - print("waiting task from distributor") - db.run_task(task_name='mnist', sort=[("time", -1)]) - time.sleep(1) - -Example codes -^^^^^^^^^^^^^^^^ - -See `here `__. - - -TensorHub API ---------------------- - -.. automodule:: tensorlayerx.utils.db - -.. autoclass:: TensorHub - :members: diff --git a/tensorlayerx/model/core.py b/tensorlayerx/model/core.py index 01f2a13..3271879 100644 --- a/tensorlayerx/model/core.py +++ b/tensorlayerx/model/core.py @@ -2,7 +2,6 @@ # -*- coding: utf-8 -*- from collections.abc import Iterable -from tqdm import trange from tensorlayerx.nn.core.common import _save_weights, _load_weights, \ _save_standard_weights_dict, _load_standard_weights_dict From 39a740efa1d202d3b34c60683b0703393340be38 Mon Sep 17 00:00:00 2001 From: Eric_lai Date: Fri, 13 Jan 2023 15:27:22 +0800 Subject: [PATCH 15/46] Adjust the image ratio --- docs/index.rst | 2 +- docs/user/my_figs/img_tensorlayer.png | Bin 14657 -> 0 bytes docs/user/my_figs/img_tlayer.png | Bin 4259 -> 0 bytes docs/user/my_figs/img_tlayer_big.png | Bin 4263383 -> 0 bytes docs/user/my_figs/img_tunelayer.png | Bin 4259 -> 0 bytes docs/user/my_figs/tl_black_logo.png | Bin 127091 -> 0 bytes docs/user/my_figs/tl_transparent_logo.png | Bin 150323 -> 0 bytes docs/user/my_figs/tl_white_logo.png | Bin 83507 -> 0 bytes docs/user/my_figs/tlx_transparent_logo.png | Bin 101005 -> 70602 bytes 9 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 docs/user/my_figs/img_tensorlayer.png delete mode 100644 docs/user/my_figs/img_tlayer.png delete mode 100644 docs/user/my_figs/img_tlayer_big.png delete mode 100644 docs/user/my_figs/img_tunelayer.png delete mode 100644 docs/user/my_figs/tl_black_logo.png delete mode 100644 docs/user/my_figs/tl_transparent_logo.png delete mode 100644 docs/user/my_figs/tl_white_logo.png diff --git a/docs/index.rst b/docs/index.rst index 36fa840..897f169 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,7 +3,7 @@ Welcome to TensorLayerX .. image:: user/my_figs/tlx_transparent_logo.png - :width: 30 % + :width: 60 % :align: center :target: https://github.com/tensorlayer/TensorLayerX diff --git a/docs/user/my_figs/img_tensorlayer.png b/docs/user/my_figs/img_tensorlayer.png deleted file mode 100644 index c6b1f7c73bd042cac39d903f8db70cccb3803751..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14657 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 L(#I8O;BWsIKe#*ZylP|gF-E+_Ro!|ML z8~CCS1o|2qS{RZ@Bx64u3nq~ughZk~GoS*`l}+n7!1xOSLVbK=17e#m$9#V!vEjU2 zp?LiboL~#qS8uSD<>pPs5YCpXlShPq|AF?Si7^1yEFm~Bgk)X%yuNVsLCgb=cduC1 zfe3areUOk*Ubu`zn(@F7|(tYBrcruMWgQh9vr+Kw^)_{>)185DQ3s$z{ylzjS z5JT$-IHx<#Y1!oAWH(J!R?XR{ynIiVI52vyi&=BKK`UaPzsbnQE5vuN?sBzIXbN=E z4Q*zLJtDI=0zF$ef7!FDLaL zDmr&eg>lh3`xWEOU5wu4MwB2@qPWVZrowVCy*7yTpvUBtoNa^ct3*^R!RNG zmIYn5tj5dLMCAm;lCMuy%4JWjZj4M1c1#9O&41(TKjeapk|%5QA8yTC63f3ozl*Pb z!=O4rf)8JBJPxkKRj_sd;>AzoAyQ+1Ju^By3Doz#?q~HpGp7nD|#%S2LHn(dPr>`pBRT+ zrm%{kD$BU&ZqZ6Tv!&X18yj*qzAKj{o(`lc-Q=<`M@GD3^tyRcw6JwIgK6k0gt6xxcZbn*i0)=C+EXXx;)9P6m zy)!+8zAxoUvb_O$@I&StskfbY1vb{1QiVTHG=FXqaZL85@L^pX@+rmWizdf#lS3n& z*?w}aUsU)ErTS7kndk5<=@TlAMB>siDVge<>7nKHIp10KocxW4pgXodJrj`+`5A~V z8RRfwCY(e146ZfhoOLnPUsG{!F2Y4nGRk{{vH44&KRRh@NDcXs{N7?@5>$fX z6kPfSGZjh%UCN(&`y(Y{M}9jcg0;b0C=qm_x2W_&!4lSAss3kXv!}-F+!UCB5bx!0 znBQx&T`&dBK!{p1wQ25t!x@rJ2MXJh++B;B5=NjH^SH;RUC5lST%k7A7(co9?gLllgTnM=d+^+rh$vjAOw;-$*Zw ztuLwKd{&=(Q;c)9NfyUg1~A@MeWTkK=St%}F*}sW3sLdG<|i8`8!~*Lk_ZqSEJF}= z@uJ5^We^&rAdatMFpR4ez|Guc4EAyfgx>#bx-AHx@dzyW1jyBi#JE|6>tV`-?*v9e z)ViGzK;P6y06NYO0$769iPd>xU9u1dL84L=Wi~R2TuTH5j;2R}BqF`o<2u2l*Vfsa zf&}CdAT1M6wM%+fAP4gUIY<0E_NgUM22pAAD?Hwse>;lP^kD#CM1Y&4pi!n2Bz!vw zE?)@pR;PC00E$QWC!}&2^ap!Y9SG)3V5*rwGLN%mpoIyCZZzm6-#QzD`jI)H#0HR$ zZVSh_+INsj8_?5u_mebl=}*Jt`AEW&?e!j@z8p* z7KaQkz=sDU(9??CF&LiD_gHQhslf$70BUXv1STrHhSO3o)Eo| zp)T&A5irAH4jxKO`Y?4FLE>Jk9vr}x2IPU~+33-tGwNaC0q3~6E@W5_2E>ez4Mh^@ zl9$ug7CAHz6H$=$xr!VRoB@FlOr5+N=%lW}CmRNjk@{$qd?7fqNDYl2lt5lfaN0~Y zkTHNuq2Jw3AQGKoz*)QqbPLhN*)Tr3w?oZ*DNKtB6qYlAU^-jp2@WqZl2(9=_H$yDW(7p_WM$^oB}CuPd#AYubr7=^2;mp6@F!kj~n{TJgBc<_!CG zOOYrrB^$M}E~>wC-lw5c>__^S15Swoe^s}Gk3Ftk3YLleq#?y5`_)0uXQJdNR4iGJ z=n>`^t|euoMr|)lK~5~}%0phBz6hEycU)qXc~BepXK3MPUaXOk|7Z@hysG~?;0xTf z4rC%*m;Y!1Eb;j30%FOURwYV0z=Rv(T>UBBN4BuUzN5ST_7@SB5+2h)dg3u{8}{3e zIg(1f!=HU(d9z*OumL7Mr1Xt2Y2B7CJ5t33gp>*#r_a=q|C@d(SCQLKUCWdWS!ENf M{d@wkN^g<$cX%^b4gdfE diff --git a/docs/user/my_figs/img_tlayer_big.png b/docs/user/my_figs/img_tlayer_big.png deleted file mode 100644 index 3679b70cf2a10faa74bd94c1d0a9886a760336b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4263383 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

LAYRQ`?1zlu;usP|mU?i>My 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

L;QcPO#Vj1+d6yv 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 M{d@wkN^g<$cX%^b4gdfE diff --git a/docs/user/my_figs/tl_black_logo.png b/docs/user/my_figs/tl_black_logo.png deleted file mode 100644 index 8bf892db9e0b6035c0ec9ebe9f08f4e28f9ba847..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 127091 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 diff --git a/docs/user/my_figs/tl_transparent_logo.png b/docs/user/my_figs/tl_transparent_logo.png deleted file mode 100644 index 359a232dd719a910628736ed4cd724eafa85c187..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150323 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%0AJnFXtQ}UI##Py-sk~Y>^ZQU|@U@7(tI_ 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 Ba_Rs8 diff --git a/docs/user/my_figs/tl_white_logo.png b/docs/user/my_figs/tl_white_logo.png deleted file mode 100644 index a42806d2026db643b4804914bc3a09f902dbb0cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 83507 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%0A%rVo&u2i6PE>n8 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 ZR0yUkB(!S7gWd>)f}E;s?rlTw{{f9$#Cre$ diff --git a/docs/user/my_figs/tlx_transparent_logo.png b/docs/user/my_figs/tlx_transparent_logo.png index 15a58a89d79d1dee78a2bde3b65288d61d44e819..a6f31e4e80c079754f7adfa2fc1efb98367480bb 100644 GIT binary patch literal 70602 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 literal 101005 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 J)-~hD{{z2Pp11%2 From 91b93a02f06b8696807a7fc66546d98b4d0e55f5 Mon Sep 17 00:00:00 2001 From: Eric_lai Date: Tue, 17 Jan 2023 17:21:40 +0800 Subject: [PATCH 16/46] Add Pad2D and fix docs --- tensorlayerx/backend/ops/__init__.py | 1 + tensorlayerx/backend/ops/mindspore_backend.py | 8 ++ tensorlayerx/backend/ops/oneflow_backend.py | 8 ++ tensorlayerx/backend/ops/paddle_backend.py | 25 +++++++ .../backend/ops/tensorflow_backend.py | 18 +++++ tensorlayerx/backend/ops/torch_backend.py | 17 +++++ tensorlayerx/files/__init__.py | 8 -- tensorlayerx/nn/layers/padding.py | 75 +++++++++++++++++++ tensorlayerx/optimizers/__init__.py | 8 -- 9 files changed, 152 insertions(+), 16 deletions(-) diff --git a/tensorlayerx/backend/ops/__init__.py b/tensorlayerx/backend/ops/__init__.py index bed367f..e3c268b 100644 --- a/tensorlayerx/backend/ops/__init__.py +++ b/tensorlayerx/backend/ops/__init__.py @@ -259,6 +259,7 @@ from .load_backend import Sign from .load_backend import Resize from .load_backend import Pad +from .load_backend import Pad2d from .load_backend import Minimum from .load_backend import Maximum from .load_backend import Meshgrid diff --git a/tensorlayerx/backend/ops/mindspore_backend.py b/tensorlayerx/backend/ops/mindspore_backend.py index 8d0fdfb..434c838 100644 --- a/tensorlayerx/backend/ops/mindspore_backend.py +++ b/tensorlayerx/backend/ops/mindspore_backend.py @@ -746,6 +746,14 @@ def reduce_min(input_tensor, axis=None, keepdims=False): return outputs +class Pad2d(object): + def __init__(self, padding, mode='constant', value=0.0, data_format="NCHW", name=None): + pass + + def __call__(self, x): + pass + + class Pad(Cell): def __init__(self, paddings, mode="REFLECT", constant_values=0): diff --git a/tensorlayerx/backend/ops/oneflow_backend.py b/tensorlayerx/backend/ops/oneflow_backend.py index 31741a3..95ec64e 100644 --- a/tensorlayerx/backend/ops/oneflow_backend.py +++ b/tensorlayerx/backend/ops/oneflow_backend.py @@ -733,6 +733,14 @@ def reduce_min(input_tensor, axis=None, keepdims=False): return flow.min(input_tensor) +class Pad2d(object): + def __init__(self, padding, mode='constant', value=0.0, data_format="NCHW", name=None): + pass + + def __call__(self, x): + pass + + class Pad(object): def __init__(self, paddings, mode="REFLECT", constant_values=0.0): diff --git a/tensorlayerx/backend/ops/paddle_backend.py b/tensorlayerx/backend/ops/paddle_backend.py index 36ec4a7..568120e 100644 --- a/tensorlayerx/backend/ops/paddle_backend.py +++ b/tensorlayerx/backend/ops/paddle_backend.py @@ -72,6 +72,12 @@ complex64 = paddle.complex64 complex128 = paddle.complex128 +def _npairs(x, n): + if isinstance(x, (paddle.Tensor, list, tuple)): + return x + x = [x] * (n * 2) + return x + def _getter(init_fn, **kwargs): """Return an named eager tensor.""" @@ -838,6 +844,25 @@ def reduce_min(input_tensor, axis=None, keepdims=False): return pd.min(input_tensor, axis, keepdim=keepdims) +class Pad2d(object): + def __init__(self, padding, mode='constant', value=0.0, data_format="NCHW", name=None): + self._pad = _npairs(padding, 2) + self._mode = mode + self._value = value + self._data_format = data_format + self._name = name + + def __call__(self, x): + return F.pad( + x, + pad=self._pad, + mode=self._mode, + value=self._value, + data_format=self._data_format, + name=self._name, + ) + + class Pad(object): def __init__(self, paddings, mode="REFLECT", constant_values=0): diff --git a/tensorlayerx/backend/ops/tensorflow_backend.py b/tensorlayerx/backend/ops/tensorflow_backend.py index 18d1210..117e96c 100644 --- a/tensorlayerx/backend/ops/tensorflow_backend.py +++ b/tensorlayerx/backend/ops/tensorflow_backend.py @@ -927,6 +927,24 @@ def reduce_min(x, axis=None, keepdims=False): return tf.reduce_min(x, axis=axis, keepdims=keepdims) +class Pad2d(object): + def __init__(self, padding, mode='constant', value=0.0, data_format="NCHW", name=None): + self.padding = [[0, 0], [padding[0], padding[1]], + [padding[2], padding[3]], [0, 0]] + self._mode = mode + self._value = value + self._data_format = data_format + self._name = name + + def __call__(self, x): + if self._data_format == "NCHW": + x = nchw_to_nhwc(x) + outputs = tf.pad(x, self.padding, mode=self._mode, constant_values=self._value) + if self._data_format == "NCHW": + outputs = nhwc_to_nchw(outputs) + return outputs + + class Pad(object): def __init__(self, paddings, mode="REFLECT", constant_values=0): diff --git a/tensorlayerx/backend/ops/torch_backend.py b/tensorlayerx/backend/ops/torch_backend.py index 61bc4bc..c0918bc 100644 --- a/tensorlayerx/backend/ops/torch_backend.py +++ b/tensorlayerx/backend/ops/torch_backend.py @@ -608,6 +608,23 @@ def reduce_min(input_tensor, axis=None, keepdims=False): return torch.min(input_tensor) +class Pad2d(object): + def __init__(self, padding, mode='constant', value=0.0, data_format="NCHW", name=None): + self.padding = padding + self._mode = mode + self._value = value + self._data_format = data_format + self._name = name + + def __call__(self, x): + if self._data_format == "NHWC": + x = nhwc_to_nchw(x) + output = torch.nn.functional.pad(x, self.padding, self._mode, value=self._value) + if self._data_format == "NHWC": + output = nchw_to_nhwc(output) + return output + + class Pad(object): def __init__(self, paddings, mode="REFLECT", constant_values=0.0): diff --git a/tensorlayerx/files/__init__.py b/tensorlayerx/files/__init__.py index a7351f5..48476cd 100644 --- a/tensorlayerx/files/__init__.py +++ b/tensorlayerx/files/__init__.py @@ -1,13 +1,5 @@ #! /usr/bin/python # -*- coding: utf-8 -*- -""" -TensorLayer provides rich layer implementations trailed for -various benchmarks and domain-specific problems. In addition, we also -support transparent access to native TensorFlow parameters. -For example, we provide not only layers for local response normalization, but also -layers that allow user to apply ``tf.ops.lrn`` on ``network.outputs``. -More functions can be found in `TensorFlow API `__. -""" from .dataset_loaders.celebA_dataset import * from .dataset_loaders.cifar10_dataset import * diff --git a/tensorlayerx/nn/layers/padding.py b/tensorlayerx/nn/layers/padding.py index f778997..52bbf78 100644 --- a/tensorlayerx/nn/layers/padding.py +++ b/tensorlayerx/nn/layers/padding.py @@ -10,6 +10,7 @@ 'ZeroPad1d', 'ZeroPad2d', 'ZeroPad3d', + 'Pad2D' ] @@ -78,6 +79,80 @@ def forward(self, inputs): return outputs +class Pad2D(Module): + """ + This interface is used to construct a callable object of the ``Pad2D`` class. + Pad tensor according to 'pad', 'mode' and 'value'. + If mode is 'reflect', pad[0] and pad[1] must be no greater + than width-1. The height dimension has the same condition. + Parameters + ---------- + padding : Tensor|list[int]|int + The padding size with data type int. If is int, use the same padding in all dimensions. + Else [len(padding)/2] dimensions of input will be padded. + The pad has the form (pad_left, pad_right, pad_top, pad_bottom). + mode : str, optional + Four modes: 'constant' (default), 'reflect', 'replicate', 'circular'. Default is 'constant'. + - 'constant' mode, uses a constant value to pad the input tensor. + - 'reflect' mode, uses reflection of the input boundaries to pad the input tensor. + - 'replicate' mode, uses input boundaries to pad the input tensor. + - 'circular' mode, uses circular input to pad the input tensor. + value : float, optional + The value to fill the padded areas. Default is :math:`0.0`。 + data_format : str, optional + An string from: "NCHW", "NHWC". Specify the data format of the input data. Default is "NCHW"。 + name : str, optional + For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None. + Returns: + ----------- + None + Examples: + ------------- + With TensorLayer + + >>> net = tlx.nn.Input([10, 224, 224, 3], name='input') + >>> padlayer = tlx.nn.Pad2D([0, 3, 3, 0], "constant", name='inpad')(net) + >>> print(padlayer) + >>> output shape : (10, 230, 230, 3) + """ + + def __init__( + self, padding, mode='constant', value=0.0, data_format="NCHW", name=None + ): + super(Pad2D, self).__init__() + self.padding = padding + self.mode = mode + self.value = value + self.data_format = data_format + self.name = name + self.build() + self._built = True + + def __repr__(self): + s = '{classname}(padding={padding}, mode={mode}, value={value}, data_format={data_format}' + if self.name is not None: + s += ', name=\'{name}\'' + s += ')' + return s.format(classname=self.__class__.__name__, **self.__dict__) + + def build(self, inputs_shape=None): + self.padlayer = tlx.ops.Pad2d( + padding=self.padding, + mode=self.mode, + value=self.value, + data_format=self.data_format, + name=self.name) + + def forward(self, x): + output = self.padlayer(x) + + if not self._nodes_fixed and self._build_graph: + self._add_node(x, output) + self._nodes_fixed = True + + return output + + class ZeroPad1d(Module): """ The :class:`ZeroPad1d` class is a 1D padding layer for signal [batch, length, channel]. diff --git a/tensorlayerx/optimizers/__init__.py b/tensorlayerx/optimizers/__init__.py index 38d2acc..2592422 100644 --- a/tensorlayerx/optimizers/__init__.py +++ b/tensorlayerx/optimizers/__init__.py @@ -1,13 +1,5 @@ #! /usr/bin/python # -*- coding: utf-8 -*- -""" -TensorLayer provides rich layer implementations trailed for -various benchmarks and domain-specific problems. In addition, we also -support transparent access to native TensorFlow parameters. -For example, we provide not only layers for local response normalization, but also -layers that allow user to apply ``tf.ops.lrn`` on ``network.outputs``. -More functions can be found in `TensorFlow API `__. -""" # from .amsgrad import AMSGrad From 0f5ec378a1aa93ecb9d0ce08d1ef86781b5f029a Mon Sep 17 00:00:00 2001 From: Jiarong Han Date: Wed, 18 Jan 2023 10:29:33 +0800 Subject: [PATCH 17/46] Update requirements.txt --- requirements/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 9662627..71826ff 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -10,4 +10,4 @@ h5py>=2.9 cloudpickle>=0.8.1 tensorboardX>=2.5 rich>=12.2 - +six=1.15.0 From 7ef86fcc5a0248f9d7cab26e1b314f231fa6b2be Mon Sep 17 00:00:00 2001 From: Jiarong Han Date: Thu, 19 Jan 2023 15:02:35 +0800 Subject: [PATCH 18/46] update files/datasets download info (#65) --- tensorlayerx/dataflow/dataloader.py | 8 ++++---- tensorlayerx/files/dataset_loaders/celebA_dataset.py | 8 ++++++-- tensorlayerx/files/dataset_loaders/cifar10_dataset.py | 8 +++++--- .../files/dataset_loaders/cyclegan_dataset.py | 7 ++++++- .../files/dataset_loaders/flickr_1M_dataset.py | 11 +++++++---- .../files/dataset_loaders/flickr_25k_dataset.py | 7 +++++-- tensorlayerx/files/dataset_loaders/imdb_dataset.py | 9 ++++++--- .../files/dataset_loaders/matt_mahoney_dataset.py | 7 +++++-- tensorlayerx/files/dataset_loaders/mnist_dataset.py | 7 ++++++- .../files/dataset_loaders/mnist_fashion_dataset.py | 8 +++++++- tensorlayerx/files/dataset_loaders/mpii_dataset.py | 8 +++++--- .../files/dataset_loaders/nietzsche_dataset.py | 7 +++++-- tensorlayerx/logging/tl_logging.py | 2 +- 13 files changed, 68 insertions(+), 29 deletions(-) diff --git a/tensorlayerx/dataflow/dataloader.py b/tensorlayerx/dataflow/dataloader.py index 1cd1a25..a4f0ec8 100644 --- a/tensorlayerx/dataflow/dataloader.py +++ b/tensorlayerx/dataflow/dataloader.py @@ -68,12 +68,12 @@ def __init__( ): self.dataset = dataset assert num_workers >= 0, "num_workers should be a non_negative integer" - if num_workers == 0 and prefetch_factor != 2: - raise ValueError("prefetch_factor option should not be specified, when num_workers is 0.") + # if num_workers == 0 and prefetch_factor != 2: + # raise ValueError("prefetch_factor option should not be specified, when num_workers is 0.") if persistent_workers and num_workers == 0: raise ValueError('persistent_workers option needs num_workers > 0') - self.num_workers = num_workers - self.prefetch_factor = prefetch_factor + self.num_workers = 0 # TODO optimizer multiprocess in multi backends + self.prefetch_factor = 2 self.time_out = time_out self.worker_init_fn = worker_init_fn if isinstance(dataset, IterableDataset): diff --git a/tensorlayerx/files/dataset_loaders/celebA_dataset.py b/tensorlayerx/files/dataset_loaders/celebA_dataset.py index c66f44b..acb6b25 100644 --- a/tensorlayerx/files/dataset_loaders/celebA_dataset.py +++ b/tensorlayerx/files/dataset_loaders/celebA_dataset.py @@ -3,10 +3,9 @@ import os import zipfile - from tensorlayerx import logging from tensorlayerx.files.utils import (download_file_from_google_drive, exists_or_mkdir, load_file_list) - +logging.set_verbosity(logging.INFO) __all__ = ['load_celebA_dataset'] @@ -21,6 +20,11 @@ def load_celebA_dataset(path='data'): The path that the data is downloaded to, defaults is ``data/celebA/``. """ + logging.info("The dataset is stored on google drive, if you can't download it from google drive, " + "please download it from the official website manually. " + "Large-scale CelebFaces Attributes (CelebA) Dataset . " + "Please place dataset 'img_align_celeba.zip' under 'data/celebA/' by default.") + data_dir = 'celebA' filename, drive_id = "img_align_celeba.zip", "0B7EVK8r0v71pZjFTYXZWM3FlRnM" save_path = os.path.join(path, filename) diff --git a/tensorlayerx/files/dataset_loaders/cifar10_dataset.py b/tensorlayerx/files/dataset_loaders/cifar10_dataset.py index 5d75b81..62aa589 100644 --- a/tensorlayerx/files/dataset_loaders/cifar10_dataset.py +++ b/tensorlayerx/files/dataset_loaders/cifar10_dataset.py @@ -4,12 +4,11 @@ import os import pickle import sys - import numpy as np from tensorlayerx import logging from tensorlayerx.files.utils import maybe_download_and_extract - +logging.set_verbosity(logging.INFO) __all__ = ['load_cifar10_dataset'] @@ -46,7 +45,10 @@ def load_cifar10_dataset(shape=(-1, 32, 32, 3), path='data', plotable=False): """ path = os.path.join(path, 'cifar10') - logging.info("Load or Download cifar10 > {}".format(path)) + logging.info("If can't download this dataset automatically, " + "please download it from the official website manually." + "CIFAR10 Dataset ." + "Please place dataset 'cifar-10-python.tar.gz' under 'data/cifar10/' by default.") #Helper function to unpickle the data def unpickle(file): diff --git a/tensorlayerx/files/dataset_loaders/cyclegan_dataset.py b/tensorlayerx/files/dataset_loaders/cyclegan_dataset.py index edeb08f..4a7c900 100644 --- a/tensorlayerx/files/dataset_loaders/cyclegan_dataset.py +++ b/tensorlayerx/files/dataset_loaders/cyclegan_dataset.py @@ -8,7 +8,7 @@ from tensorlayerx import logging from tensorlayerx.vision import load_images from tensorlayerx.files.utils import (del_file, folder_exists, load_file_list, maybe_download_and_extract) - +logging.set_verbosity(logging.INFO) __all__ = ['load_cyclegan_dataset'] @@ -30,6 +30,11 @@ def load_cyclegan_dataset(filename='summer2winter_yosemite', path='data'): path = os.path.join(path, 'cyclegan') url = 'https://people.eecs.berkeley.edu/~taesung_park/CycleGAN/datasets/' + logging.info("If can't download this dataset automatically, " + "please download it from the official website manually." + "cyclegan Dataset ." + "Please place dataset under 'data/cyclegan/' by default.") + if folder_exists(os.path.join(path, filename)) is False: logging.info("[*] {} is nonexistent in {}".format(filename, path)) maybe_download_and_extract(filename + '.zip', path, url, extract=True) diff --git a/tensorlayerx/files/dataset_loaders/flickr_1M_dataset.py b/tensorlayerx/files/dataset_loaders/flickr_1M_dataset.py index 3514fef..328ff17 100644 --- a/tensorlayerx/files/dataset_loaders/flickr_1M_dataset.py +++ b/tensorlayerx/files/dataset_loaders/flickr_1M_dataset.py @@ -4,8 +4,8 @@ import os from tensorlayerx import logging -from tensorlayerx.vision import load_images - +from tensorlayerx.utils import visualize +logging.set_verbosity(logging.INFO) from tensorlayerx.files.utils import ( del_file, folder_exists, load_file_list, load_folder_list, maybe_download_and_extract, read_file ) @@ -30,7 +30,7 @@ def load_flickr1M_dataset(tag='sky', size=10, path="data", n_threads=50, printab size : int integer between 1 to 10. 1 means 100k images ... 5 means 500k images, 10 means all 1 million images. Default is 10. path : str - The path that the data is downloaded to, defaults is ``data/flickr25k/``. + The path that the data is downloaded to, defaults is ``data/flickr1M/``. n_threads : int The number of thread to read image. printable : boolean @@ -57,7 +57,10 @@ def load_flickr1M_dataset(tag='sky', size=10, path="data", n_threads=50, printab ] tag_zip = 'tags.zip' url = 'http://press.liacs.nl/mirflickr/mirflickr1m/' - + logging.info("If can't download this dataset automatically, " + "please download it from the official website manually." + "flickr1M Dataset ." + "Please place dataset under 'data/flickr1M/' by default.") # download dataset for image_zip in images_zip[0:size]: image_folder = image_zip.split(".")[0] diff --git a/tensorlayerx/files/dataset_loaders/flickr_25k_dataset.py b/tensorlayerx/files/dataset_loaders/flickr_25k_dataset.py index 2f61ced..3aee458 100644 --- a/tensorlayerx/files/dataset_loaders/flickr_25k_dataset.py +++ b/tensorlayerx/files/dataset_loaders/flickr_25k_dataset.py @@ -5,7 +5,7 @@ from tensorlayerx import logging from tensorlayerx.vision import load_images - +logging.set_verbosity(logging.INFO) from tensorlayerx.files.utils import ( del_file, folder_exists, load_file_list, maybe_download_and_extract, natural_keys, read_file ) @@ -49,7 +49,10 @@ def load_flickr25k_dataset(tag='sky', path="data", n_threads=50, printable=False filename = 'mirflickr25k.zip' url = 'http://press.liacs.nl/mirflickr/mirflickr25k/' - + logging.info("If can't download this dataset automatically, " + "please download it from the official website manually." + "flickr25k Dataset ." + "Please place dataset under 'data/flickr25k/' by default.") # download dataset if folder_exists(os.path.join(path, "mirflickr")) is False: logging.info("[*] Flickr25k is nonexistent in {}".format(path)) diff --git a/tensorlayerx/files/dataset_loaders/imdb_dataset.py b/tensorlayerx/files/dataset_loaders/imdb_dataset.py index 86702b8..fb6318a 100644 --- a/tensorlayerx/files/dataset_loaders/imdb_dataset.py +++ b/tensorlayerx/files/dataset_loaders/imdb_dataset.py @@ -6,9 +6,9 @@ import numpy as np import six.moves.cPickle as pickle - +from tensorlayerx import logging from tensorlayerx.files.utils import maybe_download_and_extract - +logging.set_verbosity(logging.INFO) __all__ = ['load_imdb_dataset'] @@ -52,7 +52,10 @@ def load_imdb_dataset( """ path = os.path.join(path, 'imdb') - + logging.info("If can't download this dataset automatically, " + "please download it from the official website manually." + "imdb Dataset ." + "Please place dataset under 'data/imdb/' by default.") filename = "imdb.pkl" url = 'https://s3.amazonaws.com/text-datasets/' maybe_download_and_extract(filename, path, url) diff --git a/tensorlayerx/files/dataset_loaders/matt_mahoney_dataset.py b/tensorlayerx/files/dataset_loaders/matt_mahoney_dataset.py index 00d3823..21818c9 100644 --- a/tensorlayerx/files/dataset_loaders/matt_mahoney_dataset.py +++ b/tensorlayerx/files/dataset_loaders/matt_mahoney_dataset.py @@ -6,7 +6,7 @@ from tensorlayerx import logging from tensorlayerx.files.utils import maybe_download_and_extract - +logging.set_verbosity(logging.INFO) __all__ = ['load_matt_mahoney_text8_dataset'] @@ -35,7 +35,10 @@ def load_matt_mahoney_text8_dataset(path='data'): """ path = os.path.join(path, 'mm_test8') - logging.info("Load or Download matt_mahoney_text8 Dataset> {}".format(path)) + logging.info("If can't download this dataset automatically, " + "please download it from the official website manually." + "mm_test8 Dataset ." + "Please place dataset under 'data/mm_test8/' by default.") filename = 'text8.zip' url = 'http://mattmahoney.net/dc/' diff --git a/tensorlayerx/files/dataset_loaders/mnist_dataset.py b/tensorlayerx/files/dataset_loaders/mnist_dataset.py index c306dd0..d077146 100644 --- a/tensorlayerx/files/dataset_loaders/mnist_dataset.py +++ b/tensorlayerx/files/dataset_loaders/mnist_dataset.py @@ -2,7 +2,8 @@ # -*- coding: utf-8 -*- from tensorlayerx.files.utils import _load_mnist_dataset - +from tensorlayerx import logging +logging.set_verbosity(logging.INFO) __all__ = ['load_mnist_dataset'] @@ -28,4 +29,8 @@ def load_mnist_dataset(shape=(-1, 784), path='data'): >>> X_train, y_train, X_val, y_val, X_test, y_test = tlx.files.load_mnist_dataset(shape=(-1,784), path='datasets') >>> X_train, y_train, X_val, y_val, X_test, y_test = tlx.files.load_mnist_dataset(shape=(-1, 28, 28, 1)) """ + logging.info("If can't download this dataset automatically, " + "please download it from the official website manually." + "mnist Dataset ." + "Please place dataset under 'data/mnist/' by default.") return _load_mnist_dataset(shape, path, name='mnist', url='http://yann.lecun.com/exdb/mnist/') diff --git a/tensorlayerx/files/dataset_loaders/mnist_fashion_dataset.py b/tensorlayerx/files/dataset_loaders/mnist_fashion_dataset.py index b317c6b..82d7ca2 100644 --- a/tensorlayerx/files/dataset_loaders/mnist_fashion_dataset.py +++ b/tensorlayerx/files/dataset_loaders/mnist_fashion_dataset.py @@ -2,7 +2,8 @@ # -*- coding: utf-8 -*- from tensorlayerx.files.utils import _load_mnist_dataset - +from tensorlayerx import logging +logging.set_verbosity(logging.INFO) __all__ = ['load_fashion_mnist_dataset'] @@ -28,6 +29,11 @@ def load_fashion_mnist_dataset(shape=(-1, 784), path='data'): >>> X_train, y_train, X_val, y_val, X_test, y_test = tlx.files.load_fashion_mnist_dataset(shape=(-1,784), path='datasets') >>> X_train, y_train, X_val, y_val, X_test, y_test = tlx.files.load_fashion_mnist_dataset(shape=(-1, 28, 28, 1)) """ + logging.info("If can't download this dataset automatically, " + "please download it from the official website manually." + "fashion_mnist Dataset ." + "Please place dataset under 'data/fashion_mnist/' by default.") + return _load_mnist_dataset( shape, path, name='fashion_mnist', url='http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/' ) diff --git a/tensorlayerx/files/dataset_loaders/mpii_dataset.py b/tensorlayerx/files/dataset_loaders/mpii_dataset.py index dcffaf9..efeb7ef 100644 --- a/tensorlayerx/files/dataset_loaders/mpii_dataset.py +++ b/tensorlayerx/files/dataset_loaders/mpii_dataset.py @@ -5,7 +5,7 @@ from tensorlayerx import logging from tensorlayerx.files.utils import (del_file, folder_exists, load_file_list, maybe_download_and_extract) - +logging.set_verbosity(logging.INFO) __all__ = ['load_mpii_pose_dataset'] @@ -47,8 +47,10 @@ def load_mpii_pose_dataset(path='data', is_16_pos_only=False): - `MPII Keyponts and ID `__ """ path = os.path.join(path, 'mpii_human_pose') - logging.info("Load or Download MPII Human Pose > {}".format(path)) - + logging.info("If can't download this dataset automatically, " + "please download it from the official website manually." + "mpii_human_pose Dataset ." + "Please place dataset under 'data/mpii_human_pose/' by default.") # annotation url = "http://datasets.d2.mpi-inf.mpg.de/andriluka14cvpr/" tar_filename = "mpii_human_pose_v1_u12_2.zip" diff --git a/tensorlayerx/files/dataset_loaders/nietzsche_dataset.py b/tensorlayerx/files/dataset_loaders/nietzsche_dataset.py index cb14293..000b083 100644 --- a/tensorlayerx/files/dataset_loaders/nietzsche_dataset.py +++ b/tensorlayerx/files/dataset_loaders/nietzsche_dataset.py @@ -5,7 +5,7 @@ from tensorlayerx import logging from tensorlayerx.files.utils import maybe_download_and_extract - +logging.set_verbosity(logging.INFO) __all__ = ['load_nietzsche_dataset'] @@ -30,7 +30,10 @@ def load_nietzsche_dataset(path='data'): >>> words = words.split() """ - logging.info("Load or Download nietzsche dataset > {}".format(path)) + logging.info("If can't download this dataset automatically, " + "please download it from the official website manually." + "nietzsche Dataset ." + "Please place dataset under 'data/nietzsche/' by default.") path = os.path.join(path, 'nietzsche') filename = "nietzsche.txt" diff --git a/tensorlayerx/logging/tl_logging.py b/tensorlayerx/logging/tl_logging.py index 538968b..98a915a 100644 --- a/tensorlayerx/logging/tl_logging.py +++ b/tensorlayerx/logging/tl_logging.py @@ -77,7 +77,7 @@ def _get_logger(): # Add the output handler. _handler = _logging.StreamHandler(_logging_target) - _handler.setFormatter(_logging.Formatter('[TL] %(message)s')) + _handler.setFormatter(_logging.Formatter('[TLX] %(message)s')) logger.addHandler(_handler) _logger = logger From 73d48728262ee59913c75b6d9813e682fd59e44c Mon Sep 17 00:00:00 2001 From: Jiarong Han Date: Thu, 19 Jan 2023 15:11:38 +0800 Subject: [PATCH 19/46] Update requirements.txt --- requirements/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 71826ff..5e9191e 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -10,4 +10,4 @@ h5py>=2.9 cloudpickle>=0.8.1 tensorboardX>=2.5 rich>=12.2 -six=1.15.0 +six==1.15.0 From 7dabe49c11eab08fcfa54ad21dc8923d90241e6e Mon Sep 17 00:00:00 2001 From: Jiarong Han Date: Thu, 19 Jan 2023 16:37:17 +0800 Subject: [PATCH 20/46] fix celebA dataset load (#66) --- .../files/dataset_loaders/celebA_dataset.py | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/tensorlayerx/files/dataset_loaders/celebA_dataset.py b/tensorlayerx/files/dataset_loaders/celebA_dataset.py index acb6b25..65c836b 100644 --- a/tensorlayerx/files/dataset_loaders/celebA_dataset.py +++ b/tensorlayerx/files/dataset_loaders/celebA_dataset.py @@ -27,19 +27,21 @@ def load_celebA_dataset(path='data'): data_dir = 'celebA' filename, drive_id = "img_align_celeba.zip", "0B7EVK8r0v71pZjFTYXZWM3FlRnM" - save_path = os.path.join(path, filename) - image_path = os.path.join(path, data_dir) + file_path = os.path.join(path, data_dir) + image_path = os.path.join(path, data_dir, "img_align_celeba") + save_path = os.path.join(path, data_dir, filename) if os.path.exists(image_path): - logging.info('[*] {} already exists'.format(save_path)) + logging.info('[*] {} already exists'.format(image_path)) else: - exists_or_mkdir(path) - download_file_from_google_drive(drive_id, save_path) - zip_dir = '' + if not os.path.exists(save_path): + exists_or_mkdir(file_path) + download_file_from_google_drive(drive_id, save_path) + zip_dir = '' with zipfile.ZipFile(save_path) as zf: zip_dir = zf.namelist()[0] - zf.extractall(path) - os.remove(save_path) - os.rename(os.path.join(path, zip_dir), image_path) + zf.extractall(file_path) + # os.remove(save_path) + # os.rename(os.path.join(path, zip_dir), image_path) data_files = load_file_list(path=image_path, regx='\\.jpg', printable=False) for i, _v in enumerate(data_files): From 2055574c64775dd9e6d77c5ba7382aadf8014a91 Mon Sep 17 00:00:00 2001 From: Jiarong Han Date: Thu, 19 Jan 2023 18:15:52 +0800 Subject: [PATCH 21/46] fix load_images (#67) --- tensorlayerx/vision/transforms/utils.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tensorlayerx/vision/transforms/utils.py b/tensorlayerx/vision/transforms/utils.py index cb8d0a1..cefafc1 100644 --- a/tensorlayerx/vision/transforms/utils.py +++ b/tensorlayerx/vision/transforms/utils.py @@ -92,10 +92,16 @@ def load_images(path, n_threads = 10): ''' images = [] files = sorted(os.listdir(path)) - for file in range(0, len(files), n_threads): - image_list = files[file:file + n_threads] - image = threading_data(image_list, fn=load_image, path = path) - images.extend(image) + if n_threads == 0: + for file in files: + file = os.path.join(path, file) + image = load_image(file) + images.append(image) + else: + for file in range(0, len(files), n_threads): + image_list = files[file:file + n_threads] + image = threading_data(image_list, fn=load_image, path = path) + images.extend(image) return images From 2c2d73c5a30c1ea0048e6b2efa13180785e64656 Mon Sep 17 00:00:00 2001 From: Yiliang Liu Date: Fri, 20 Jan 2023 12:23:09 +0800 Subject: [PATCH 22/46] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5b778c4..672055b 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,8 @@ This project is maintained by researchers from Peking University, Imperial Colle 🇨🇳 TensorLayerX 是一个跨平台开发框架,支持TensorFlow, Pytorch, MindSpore, PaddlePaddle, OneFlow和Jittor,用户不需要修改任何代码即可以运行在各类操作系统和AI硬件上(如Nvidia-GPU 和 Huawei-Ascend),并支持混合框架的开发。这个项目由北京大学、鹏城实验室、爱丁堡大学、帝国理工、清华、普林斯顿、斯坦福等机构的研究人员维护。 [支持列表](https://shimo.im/sheets/kJGCCTxXvqj99RGV/F5m5Z)。 +GitHub项目地址:https://github.com/tensorlayer/TensorLayerX +启智平台(国内访问):https://openi.pcl.ac.cn/OpenI/TensorLayerX # Document TensorLayerX has extensive documentation for both beginners and professionals. From 51bc1e1819c024953866e98e193f7cc413006c62 Mon Sep 17 00:00:00 2001 From: Jiarong Han Date: Fri, 20 Jan 2023 14:37:21 +0800 Subject: [PATCH 23/46] Update requirements_torch.txt --- requirements/requirements_torch.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/requirements_torch.txt b/requirements/requirements_torch.txt index 4ba4a7a..8894d71 100644 --- a/requirements/requirements_torch.txt +++ b/requirements/requirements_torch.txt @@ -1 +1 @@ -torch>=1.10.0 \ No newline at end of file +torch==1.10.0 From c987ee44190c669359f5f035fa98c973ebe78272 Mon Sep 17 00:00:00 2001 From: hanjr92 Date: Thu, 2 Feb 2023 10:03:15 +0800 Subject: [PATCH 24/46] fix convtranspose2d --- tensorlayerx/backend/ops/torch_nn.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tensorlayerx/backend/ops/torch_nn.py b/tensorlayerx/backend/ops/torch_nn.py index b6155a9..d939879 100644 --- a/tensorlayerx/backend/ops/torch_nn.py +++ b/tensorlayerx/backend/ops/torch_nn.py @@ -1235,7 +1235,8 @@ def same_padding_deconvolution(input, weight, strides, dilations): input_cols = input.size(3) out_rows = input_rows * strides[0] - strides[0] + 1 - out_cols = input_rows * strides[1] - strides[1] + 1 + out_cols = input_cols * strides[1] - strides[1] + 1 + padding_rows = max(0, (input_rows - 1) * strides[0] + (filter_rows - 1) * dilations[0] + 1 - out_rows) padding_cols = max(0, (input_cols - 1) * strides[1] + (filter_cols - 1) * dilations[1] + 1 - out_cols) @@ -1250,8 +1251,8 @@ def same_padding_deconvolution(input, weight, strides, dilations): input_depth = input.size(4) out_rows = input_rows * strides[0] - strides[0] + 1 - out_cols = input_rows * strides[1] - strides[1] + 1 - out_depth = input_rows * strides[2] - strides[2] + 1 + out_cols = input_cols * strides[1] - strides[1] + 1 + out_depth = input_depth * strides[2] - strides[2] + 1 padding_rows = max(0, (input_rows - 1) * strides[0] + (filter_rows - 1) * dilations[0] + 1 - out_rows) padding_cols = max(0, (input_cols - 1) * strides[1] + (filter_cols - 1) * dilations[1] + 1 - out_cols) @@ -1410,7 +1411,7 @@ def __call__(self, input, filters, output_size): if self.data_format == 'NHWC': input = nhwc_to_nchw(input) if self.padding == 'same': - out = self.conv2d_transpore_same(input, filters, output_size) + out = self.conv2d_transpore_same(input, filters) else: out_padding = self._output_padding(input, output_size, self.strides, (0 if isinstance(self.padding, str) else self.padding), filters.shape, @@ -1428,15 +1429,13 @@ def __call__(self, input, filters, output_size): out = nchw_to_nhwc(out) return out - def conv2d_transpore_same(self,input, filters, output_size): + def conv2d_transpore_same(self,input, filters): rows_odd, cols_odd, padding_rows, padding_cols = same_padding_deconvolution(input, filters, self.strides, (1, 1)) if rows_odd or cols_odd: input = F.pad(input, [0, int(rows_odd), 0, int(cols_odd)]) out_padding = 0 else: out_padding = 1 - out_padding = self._output_padding(input, output_size, self.strides, (padding_rows // 2, padding_cols // 2), filters.shape, - 2, self.dilations) out = F.conv_transpose2d(input, weight=filters, padding=(padding_rows // 2, padding_cols // 2), stride=self.strides, dilation=self.dilations, output_padding=out_padding, groups=self.groups) return out From 2bf117cf71fb4ddb539bf36807ea0af1f4a67edc Mon Sep 17 00:00:00 2001 From: Cheng Lai Date: Fri, 3 Feb 2023 16:00:57 +0800 Subject: [PATCH 25/46] TensorLayerX 0.5.8 Release (#68) --- README.md | 5 +++++ README.rst | 2 +- setup.py | 2 +- tensorlayerx/__init__.py | 13 ++++++++++++- tensorlayerx/package_info.py | 2 +- 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 672055b..3601a20 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,11 @@ More resources can be found [here](https://github.com/tensorlayer) ## Installation +### TensorLayerX corresponds to the back-end version +| TensorLayerX | TensorFlow | MindSpore | PaddlePaddle|PyTorch| +| :-----:| :----: | :----: |:-----:|:----:| +| v0.5.8 | v2.4.0 | v1.8.1 | v2.2.0 | v1.10.0 | +| v0.5.7 | v2.0.0 | v1.6.1 | v2.0.2 | v1.10.0 | ### Via docker Docker is an open source application container engine. In the [TensorLayerX Docker Repository](https://hub.docker.com/repository/docker/tensorlayer/tensorlayerx), diff --git a/README.rst b/README.rst index 716e1cf..ff2ba3a 100644 --- a/README.rst +++ b/README.rst @@ -89,5 +89,5 @@ License TensorLayerX is released under the Apache 2.0 license. -.. |TENSORLAYER-LOGO| image:: https://git.openi.org.cn/TensorLayer/tensorlayer3.0/src/branch/master/img/tl_transparent_logo.png +.. |TENSORLAYER-LOGO| image:: https://git.openi.org.cn/hanjr/tensorlayerx-image/raw/branch/master/tlx-LOGO--02.jpg :target: https://tensorlayerx.readthedocs.io/en/latest/ \ No newline at end of file diff --git a/setup.py b/setup.py index 9d5f0a4..8f4ea19 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ MAJOR = 0 MINOR = 5 -PATCH = 7 +PATCH = 8 PRE_RELEASE = '' # Use the following formatting: (major, minor, patch, prerelease) VERSION = (MAJOR, MINOR, PATCH, PRE_RELEASE) diff --git a/tensorlayerx/__init__.py b/tensorlayerx/__init__.py index a2e6cf6..1970a1a 100644 --- a/tensorlayerx/__init__.py +++ b/tensorlayerx/__init__.py @@ -4,7 +4,7 @@ # import backend from .backend import * - +import warnings import os from tensorlayerx.package_info import ( @@ -33,3 +33,14 @@ # global vars global_flag = {} global_dict = {} + +backend_v = { + 'tensorflow': '2.4.0', + 'mindspore': '1.8.1', + 'paddle': '2.2.0', + 'torch': '1.10.0', +} + +if BACKEND_VERSION != backend_v[BACKEND]: + warnings.warn("The version of the backend you have installed does not match the specified backend version " + "and may not work, please install version {} {}.".format(BACKEND, backend_v[BACKEND])) \ No newline at end of file diff --git a/tensorlayerx/package_info.py b/tensorlayerx/package_info.py index a07fa2c..80d5442 100644 --- a/tensorlayerx/package_info.py +++ b/tensorlayerx/package_info.py @@ -4,7 +4,7 @@ MAJOR = 0 MINOR = 5 -PATCH = 7 +PATCH = 8 PRE_RELEASE = '' # Use the following formatting: (major, minor, patch, prerelease) VERSION = (MAJOR, MINOR, PATCH, PRE_RELEASE) From 270304095438fa3fbb29766833906d70b90e436a Mon Sep 17 00:00:00 2001 From: Hao <10713581+zsdonghao@users.noreply.github.com> Date: Tue, 7 Feb 2023 12:41:50 +0800 Subject: [PATCH 26/46] Update README.md --- README.md | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 3601a20..651d84f 100644 --- a/README.md +++ b/README.md @@ -14,15 +14,12 @@ [![Downloads](https://pepy.tech/badge/tensorlayerx/week)](https://pepy.tech/project/tensorlayerx/week) [![Docker Pulls](https://img.shields.io/docker/pulls/tensorlayer/tensorlayerx.svg)](https://hub.docker.com/r/tensorlayer/tensorlayerx/) -🇬🇧 TensorLayerX is a multi-backend AI framework, which supports TensorFlow, Pytorch, MindSpore, PaddlePaddle, OneFlow and Jittor as the backends, allowing users to run the code on different hardware like Nvidia-GPU and Huawei-Ascend. +[TensorLayerX](https://tensorlayerx.readthedocs.io) is a multi-backend AI framework, which supports TensorFlow, Pytorch, MindSpore, PaddlePaddle, OneFlow and Jittor as the backends, allowing users to run the code on different hardware like Nvidia-GPU and Huawei-Ascend. This project is maintained by researchers from Peking University, Imperial College London, Princeton, Stanford, Tsinghua, Edinburgh and Peng Cheng Lab. -[supported layers](https://shimo.im/sheets/kJGCCTxXvqj99RGV/F5m5Z). -🇨🇳 TensorLayerX 是一个跨平台开发框架,支持TensorFlow, Pytorch, MindSpore, PaddlePaddle, OneFlow和Jittor,用户不需要修改任何代码即可以运行在各类操作系统和AI硬件上(如Nvidia-GPU 和 Huawei-Ascend),并支持混合框架的开发。这个项目由北京大学、鹏城实验室、爱丁堡大学、帝国理工、清华、普林斯顿、斯坦福等机构的研究人员维护。 -[支持列表](https://shimo.im/sheets/kJGCCTxXvqj99RGV/F5m5Z)。 -GitHub项目地址:https://github.com/tensorlayer/TensorLayerX -启智平台(国内访问):https://openi.pcl.ac.cn/OpenI/TensorLayerX +GitHub: https://github.com/tensorlayer/TensorLayerX +OpenI: https://openi.pcl.ac.cn/OpenI/TensorLayerX # Document TensorLayerX has extensive documentation for both beginners and professionals. @@ -31,7 +28,8 @@ TensorLayerX has extensive documentation for both beginners and professionals. # DeepLearning course 🔥We have opened a video course for introductory learning deep learning, with example codes based on TensorLayerX. -[Bilibili link](https://www.bilibili.com/video/BV1xB4y1h7V2?share_source=copy_web&vd_source=467c17f872fcde378494433520e19999) +[Bilibili link](https://www.bilibili.com/video/BV1xB4y1h7V2?share_source=copy_web&vd_source=467c17f872fcde378494433520e19999) (chinese) + # Design Features Compare with [TensorLayer](https://github.com/tensorlayer/TensorLayer), [TensorLayerX](http://tensorlayerx.readthedocs.io)(TLX) is a brand new seperated project for platform-agnostic purpose. @@ -54,9 +52,9 @@ Compare to TensorLayer version: - [Examples](https://github.com/tensorlayer/TensorLayerX/tree/main/examples) for tutorials✅ - [GammaGL](https://github.com/BUPT-GAMMA/GammaGL) is a multi-backend graph learning library based on TensorLayerX.✅ - OpenIVA an easy-to-use product-level deployment framework✅ -- [TLXZoo](https://github.com/tensorlayer/TLXZoo) pretrained models/backbones🚧 -- TLXCV a bunch of Computer Vision applications🚧 -- TLXNLP a bunch of Natural Language Processing applications🚧 +- [TLXZoo](https://github.com/tensorlayer/TLXZoo) pretrained models/backbones +- TLXCV a bunch of Computer Vision applications +- TLXNLP a bunch of Natural Language Processing applications - TLXRL a bunch of Reinforcement Learning applications, check [RLZoo](https://github.com/tensorlayer/RLzoo) for the old version✅ More resources can be found [here](https://github.com/tensorlayer) @@ -140,14 +138,6 @@ Join our community as a code contributor, find out more in our [Help wanted list If you find TensorLayerX useful for your project, please cite the following papers: ``` -@article{tensorlayer2017, - author = {Dong, Hao and Supratak, Akara and Mai, Luo and Liu, Fangde and Oehmichen, Axel and Yu, Simiao and Guo, Yike}, - journal = {ACM Multimedia}, - title = {{TensorLayer: A Versatile Library for Efficient Deep Learning Development}}, - url = {http://tensorlayer.org}, - year = {2017} -} - @inproceedings{tensorlayer2021, title={TensorLayer 3.0: A Deep Learning Library Compatible With Multiple Backends}, author={Lai, Cheng and Han, Jiarong and Dong, Hao}, @@ -156,6 +146,13 @@ If you find TensorLayerX useful for your project, please cite the following pape year={2021}, organization={IEEE} } +@article{tensorlayer2017, + author = {Dong, Hao and Supratak, Akara and Mai, Luo and Liu, Fangde and Oehmichen, Axel and Yu, Simiao and Guo, Yike}, + journal = {ACM Multimedia}, + title = {{TensorLayer: A Versatile Library for Efficient Deep Learning Development}}, + url = {http://tensorlayer.org}, + year = {2017} +} ``` From b25c1e1975514055611cdf4a78db8eb0a509d8c5 Mon Sep 17 00:00:00 2001 From: Hao <10713581+zsdonghao@users.noreply.github.com> Date: Tue, 7 Feb 2023 12:45:13 +0800 Subject: [PATCH 27/46] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 4a6f60f..c9d44f0 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ __pycache__/ *.py[cod] *$py.class +.DS_Store # C extensions *.so From 2667942804aaa0cc319be0d0e5a4065b5b5fcd1c Mon Sep 17 00:00:00 2001 From: Hao <10713581+zsdonghao@users.noreply.github.com> Date: Tue, 7 Feb 2023 12:53:59 +0800 Subject: [PATCH 28/46] Update README.md --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 651d84f..694468a 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,18 @@ MLP.set_eval() Join our community as a code contributor, find out more in our [Help wanted list](https://github.com/tensorlayer/TensorLayerX/issues/5) and [Contributing](https://tensorlayerx.readthedocs.io/en/latest/user/contributing.html) guide! +# Getting Involved + +We suggest users to report bugs using Github issues. Users can also discuss how to use TensorLayerX in the following slack channel. + +
+ +
+

+ + # Contact - tensorlayer@gmail.com From bf82f149cd6cf0f4720eb47c1e56e82374750274 Mon Sep 17 00:00:00 2001 From: Hao <10713581+zsdonghao@users.noreply.github.com> Date: Tue, 7 Feb 2023 12:55:58 +0800 Subject: [PATCH 29/46] Update README.md --- README.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 694468a..07867ba 100644 --- a/README.md +++ b/README.md @@ -27,19 +27,15 @@ TensorLayerX has extensive documentation for both beginners and professionals. [![English Documentation](https://img.shields.io/badge/documentation-english-blue.svg)](https://tensorlayerx.readthedocs.io/en/latest/) # DeepLearning course -🔥We have opened a video course for introductory learning deep learning, with example codes based on TensorLayerX. +We have opened a video course for introductory learning deep learning, with example codes based on TensorLayerX. [Bilibili link](https://www.bilibili.com/video/BV1xB4y1h7V2?share_source=copy_web&vd_source=467c17f872fcde378494433520e19999) (chinese) # Design Features -Compare with [TensorLayer](https://github.com/tensorlayer/TensorLayer), [TensorLayerX](http://tensorlayerx.readthedocs.io)(TLX) is a brand new seperated project for platform-agnostic purpose. - -Compare to TensorLayer version: +[TensorLayerX](http://tensorlayerx.readthedocs.io)(TLX) is a platform-agnostic framework, supporting worldwide frameworks and AI chips, enabling one code runs on all platform.

-🔥TensorLayerX inherits the features of the previous verison, including ***Simplicity***, ***Flexibility*** and ***Zero-cost Abstraction***. ***Compare with [TensorLayer](https://github.com/tensorlayer/TensorLayer), TensorLayerX supports more backends, such as TensorFlow, MindSpore, PaddlePaddle and PyTorch. It allows users to run the same code on different hardwares like Nvidia-GPU and Huawei-Ascend.*** In addition, more features are ***under development***. - - ***Model Zoo***: Build a series of model Zoos containing classic and sota models,covering CV, NLP, RL and other fields. - ***Deploy***: In feature, TensorLayerX will support the ONNX protocol, supporting model export, import and deployment. From b079e149601a19f621818e899e4b22610cae6b0a Mon Sep 17 00:00:00 2001 From: Hao <10713581+zsdonghao@users.noreply.github.com> Date: Tue, 7 Feb 2023 12:57:49 +0800 Subject: [PATCH 30/46] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 07867ba..32dd361 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ We have opened a video course for introductory learning deep learning, with exam # Design Features -[TensorLayerX](http://tensorlayerx.readthedocs.io)(TLX) is a platform-agnostic framework, supporting worldwide frameworks and AI chips, enabling one code runs on all platform. +[TensorLayerX](http://tensorlayerx.readthedocs.io)(TLX) is a platform-agnostic framework, supporting worldwide frameworks and AI chips, enabling one code runs on all platforms.

From 5e628359b334de069e9d4811a5ab9717a12fa1c6 Mon Sep 17 00:00:00 2001 From: Hao <10713581+zsdonghao@users.noreply.github.com> Date: Tue, 7 Feb 2023 12:58:40 +0800 Subject: [PATCH 31/46] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 32dd361..6f2477d 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,8 @@ TensorLayerX has extensive documentation for both beginners and professionals. [![English Documentation](https://img.shields.io/badge/documentation-english-blue.svg)](https://tensorlayerx.readthedocs.io/en/latest/) -# DeepLearning course -We have opened a video course for introductory learning deep learning, with example codes based on TensorLayerX. +# Deep Learning course +We have video courses for deep learning, with example codes based on TensorLayerX. [Bilibili link](https://www.bilibili.com/video/BV1xB4y1h7V2?share_source=copy_web&vd_source=467c17f872fcde378494433520e19999) (chinese) # Design Features From ebe77ecb2915b5bf237b6127224971fbd95942f9 Mon Sep 17 00:00:00 2001 From: Hao <10713581+zsdonghao@users.noreply.github.com> Date: Tue, 7 Feb 2023 17:44:19 +0800 Subject: [PATCH 32/46] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 6f2477d..0169738 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ [![Downloads](https://pepy.tech/badge/tensorlayerx/week)](https://pepy.tech/project/tensorlayerx/week) [![Docker Pulls](https://img.shields.io/docker/pulls/tensorlayer/tensorlayerx.svg)](https://hub.docker.com/r/tensorlayer/tensorlayerx/) -[TensorLayerX](https://tensorlayerx.readthedocs.io) is a multi-backend AI framework, which supports TensorFlow, Pytorch, MindSpore, PaddlePaddle, OneFlow and Jittor as the backends, allowing users to run the code on different hardware like Nvidia-GPU and Huawei-Ascend. +[TensorLayerX](https://tensorlayerx.readthedocs.io) is a multi-backend AI framework, supports TensorFlow, Pytorch, MindSpore, PaddlePaddle, OneFlow and Jittor as the backends, allowing users to run the code on different hardware like Nvidia-GPU, Huawei-Ascend, Cambricon and more. This project is maintained by researchers from Peking University, Imperial College London, Princeton, Stanford, Tsinghua, Edinburgh and Peng Cheng Lab. @@ -36,9 +36,9 @@ We have video courses for deep learning, with example codes based on TensorLayer

-- ***Model Zoo***: Build a series of model Zoos containing classic and sota models,covering CV, NLP, RL and other fields. +- ***Model Zoo***: Build a series of model Zoos containing classic and sota models, covering CV, NLP, RL and other fields. -- ***Deploy***: In feature, TensorLayerX will support the ONNX protocol, supporting model export, import and deployment. +- ***Deploy***: Support the ONNX protocol, model export, import and deployment. - ***Parallel***: In order to improve the efficiency of neural network model training, parallel computing is indispensable. @@ -60,7 +60,7 @@ More resources can be found [here](https://github.com/tensorlayer) ## Installation -### TensorLayerX corresponds to the back-end version +### The latest TensorLayerX compatible with the following backend version | TensorLayerX | TensorFlow | MindSpore | PaddlePaddle|PyTorch| | :-----:| :----: | :----: |:-----:|:----:| | v0.5.8 | v2.4.0 | v1.8.1 | v2.2.0 | v1.10.0 | @@ -91,7 +91,7 @@ For more installation instructions, please refer to [Installtion](https://tensor ## Define a model -You can immediately use tensorlayerx to define a model, using your favourite framework in the background, like so: +You can immediately use TensorLayerX to define a model, using your favourite framework in the background, like so: ```python import os os.environ['TL_BACKEND'] = 'tensorflow' # modify this line, switch to any framework easily! From 93a1b36f24fa524d9423bfb1091c968cd32a66e1 Mon Sep 17 00:00:00 2001 From: Hao <10713581+zsdonghao@users.noreply.github.com> Date: Tue, 7 Feb 2023 17:47:34 +0800 Subject: [PATCH 33/46] Update README.md --- README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0169738..be13136 100644 --- a/README.md +++ b/README.md @@ -32,15 +32,14 @@ We have video courses for deep learning, with example codes based on TensorLayer # Design Features -[TensorLayerX](http://tensorlayerx.readthedocs.io)(TLX) is a platform-agnostic framework, supporting worldwide frameworks and AI chips, enabling one code runs on all platforms. -

-- ***Model Zoo***: Build a series of model Zoos containing classic and sota models, covering CV, NLP, RL and other fields. +- ***Compatibility***: Support worldwide frameworks and AI chips, enabling one code runs on all platforms. + +- ***Model Zoo***: Provide a series of applications containing classic and SOTA models, covering CV, NLP, RL and other fields. -- ***Deploy***: Support the ONNX protocol, model export, import and deployment. +- ***Deploy***: Support ONNX protocol, model export, import and deployment. -- ***Parallel***: In order to improve the efficiency of neural network model training, parallel computing is indispensable. # Resources From e2f6106ad9de1a775a68b12192145dbb5c2d4ebe Mon Sep 17 00:00:00 2001 From: Hao <10713581+zsdonghao@users.noreply.github.com> Date: Tue, 7 Feb 2023 17:48:25 +0800 Subject: [PATCH 34/46] update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index be13136..841bed7 100644 --- a/README.md +++ b/README.md @@ -159,7 +159,7 @@ If you find TensorLayerX useful for your project, please cite the following pape title = {{TensorLayer: A Versatile Library for Efficient Deep Learning Development}}, url = {http://tensorlayer.org}, year = {2017} -} +} ``` From 8d1a02c4a4d862ff861b48f8fc4a5c19f39fcbd9 Mon Sep 17 00:00:00 2001 From: Hao <10713581+zsdonghao@users.noreply.github.com> Date: Tue, 7 Feb 2023 17:52:28 +0800 Subject: [PATCH 35/46] Update README.md --- README.md | 78 +++++++++++++++++++++++++++---------------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 841bed7..989c70b 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,40 @@ We have video courses for deep learning, with example codes based on TensorLayer - ***Deploy***: Support ONNX protocol, model export, import and deployment. +# Multi-backend Design + +You can immediately use TensorLayerX to define a model, using your favourite framework in the background, like so: +```python +import os +os.environ['TL_BACKEND'] = 'tensorflow' # modify this line, switch to any framework easily! +#os.environ['TL_BACKEND'] = 'mindspore' +#os.environ['TL_BACKEND'] = 'paddle' +#os.environ['TL_BACKEND'] = 'torch' +import tensorlayerx as tlx +from tensorlayerx.nn import Module +from tensorlayerx.nn import Linear +class CustomModel(Module): + + def __init__(self): + super(CustomModel, self).__init__() + + self.linear1 = Linear(out_features=800, act=tlx.ReLU, in_features=784) + self.linear2 = Linear(out_features=800, act=tlx.ReLU, in_features=800) + self.linear3 = Linear(out_features=10, act=None, in_features=800) + + def forward(self, x, foo=False): + z = self.linear1(x) + z = self.linear2(z) + out = self.linear3(z) + if foo: + out = tlx.softmax(out) + return out + +MLP = CustomModel() +MLP.set_eval() +``` + + # Resources @@ -55,16 +89,14 @@ We have video courses for deep learning, with example codes based on TensorLayer More resources can be found [here](https://github.com/tensorlayer) -# Quick Start +# Installation -## Installation - -### The latest TensorLayerX compatible with the following backend version +## The latest TensorLayerX compatible with the following backend version | TensorLayerX | TensorFlow | MindSpore | PaddlePaddle|PyTorch| | :-----:| :----: | :----: |:-----:|:----:| | v0.5.8 | v2.4.0 | v1.8.1 | v2.2.0 | v1.10.0 | | v0.5.7 | v2.0.0 | v1.6.1 | v2.0.2 | v1.10.0 | -### Via docker +## Via docker Docker is an open source application container engine. In the [TensorLayerX Docker Repository](https://hub.docker.com/repository/docker/tensorlayer/tensorlayerx), different versions of TensorLayerX have been installed in docker images. @@ -75,51 +107,19 @@ docker pull tensorlayer/tensorlayerx:tagname ``` -### Via pip +## Via pip for the stable version ```bash # install from pypi pip3 install tensorlayerx ``` -### Build from source +## Build from source for the latest version ```bash # install from Github pip3 install git+https://github.com/tensorlayer/tensorlayerx.git ``` For more installation instructions, please refer to [Installtion](https://tensorlayerx.readthedocs.io/en/latest/user/installation.html) -## Define a model - -You can immediately use TensorLayerX to define a model, using your favourite framework in the background, like so: -```python -import os -os.environ['TL_BACKEND'] = 'tensorflow' # modify this line, switch to any framework easily! -#os.environ['TL_BACKEND'] = 'mindspore' -#os.environ['TL_BACKEND'] = 'paddle' -#os.environ['TL_BACKEND'] = 'torch' -import tensorlayerx as tlx -from tensorlayerx.nn import Module -from tensorlayerx.nn import Linear -class CustomModel(Module): - - def __init__(self): - super(CustomModel, self).__init__() - - self.linear1 = Linear(out_features=800, act=tlx.ReLU, in_features=784) - self.linear2 = Linear(out_features=800, act=tlx.ReLU, in_features=800) - self.linear3 = Linear(out_features=10, act=None, in_features=800) - - def forward(self, x, foo=False): - z = self.linear1(x) - z = self.linear2(z) - out = self.linear3(z) - if foo: - out = tlx.softmax(out) - return out - -MLP = CustomModel() -MLP.set_eval() -``` # Contributing Join our community as a code contributor, find out more in our [Help wanted list](https://github.com/tensorlayer/TensorLayerX/issues/5) and [Contributing](https://tensorlayerx.readthedocs.io/en/latest/user/contributing.html) guide! From 28e8dcd6ac3c9308a2a0b85a168c84aae587662b Mon Sep 17 00:00:00 2001 From: Hao <10713581+zsdonghao@users.noreply.github.com> Date: Tue, 7 Feb 2023 17:56:06 +0800 Subject: [PATCH 36/46] Update README.md --- README.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 989c70b..5f64bca 100644 --- a/README.md +++ b/README.md @@ -77,14 +77,12 @@ MLP.set_eval() # Resources -- [TLX2ONNX](https://github.com/tensorlayer/TLX2ONNX/) ONNX Model Exporter for TensorLayerX. ✅ -- [Examples](https://github.com/tensorlayer/TensorLayerX/tree/main/examples) for tutorials✅ -- [GammaGL](https://github.com/BUPT-GAMMA/GammaGL) is a multi-backend graph learning library based on TensorLayerX.✅ -- OpenIVA an easy-to-use product-level deployment framework✅ -- [TLXZoo](https://github.com/tensorlayer/TLXZoo) pretrained models/backbones -- TLXCV a bunch of Computer Vision applications -- TLXNLP a bunch of Natural Language Processing applications -- TLXRL a bunch of Reinforcement Learning applications, check [RLZoo](https://github.com/tensorlayer/RLzoo) for the old version✅ +- [Examples](https://github.com/tensorlayer/TensorLayerX/tree/main/examples) for tutorials +- [GammaGL](https://github.com/BUPT-GAMMA/GammaGL) is series of graph learning algorithm +- [TLXZoo](https://github.com/tensorlayer/TLXZoo) a series of pretrained backbones +- TLXCV a series of Computer Vision applications +- TLXNLP a series of Natural Language Processing applications +- [TLX2ONNX](https://github.com/tensorlayer/TLX2ONNX/) ONNX model exporter for TensorLayerX. More resources can be found [here](https://github.com/tensorlayer) From 95ddcd3ac474c4c317c16ee8a58b0ad4f7622aee Mon Sep 17 00:00:00 2001 From: Yiliang Liu Date: Tue, 7 Feb 2023 18:03:04 +0800 Subject: [PATCH 37/46] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5f64bca..b8de7a4 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,7 @@ MLP.set_eval() - TLXCV a series of Computer Vision applications - TLXNLP a series of Natural Language Processing applications - [TLX2ONNX](https://github.com/tensorlayer/TLX2ONNX/) ONNX model exporter for TensorLayerX. +- [paddle2tlx](https://github.com/tensorlayer/paddle2tlx) model code converter from PaddlePaddle to TensorLayerX. More resources can be found [here](https://github.com/tensorlayer) From 16a7ff33cd3fe8f956872763d25197395c0eea78 Mon Sep 17 00:00:00 2001 From: Yiliang Liu Date: Tue, 7 Feb 2023 18:04:57 +0800 Subject: [PATCH 38/46] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b8de7a4..a1b1b19 100644 --- a/README.md +++ b/README.md @@ -80,8 +80,8 @@ MLP.set_eval() - [Examples](https://github.com/tensorlayer/TensorLayerX/tree/main/examples) for tutorials - [GammaGL](https://github.com/BUPT-GAMMA/GammaGL) is series of graph learning algorithm - [TLXZoo](https://github.com/tensorlayer/TLXZoo) a series of pretrained backbones -- TLXCV a series of Computer Vision applications -- TLXNLP a series of Natural Language Processing applications +- [TLXCV](https://github.com/tensorlayer/TLXCV) a series of Computer Vision applications +- [TLXNLP](https://github.com/tensorlayer/TLXNLP) a series of Natural Language Processing applications - [TLX2ONNX](https://github.com/tensorlayer/TLX2ONNX/) ONNX model exporter for TensorLayerX. - [paddle2tlx](https://github.com/tensorlayer/paddle2tlx) model code converter from PaddlePaddle to TensorLayerX. From 10b42466b335f98497445882d4f1c2aa14c56e34 Mon Sep 17 00:00:00 2001 From: Yiliang Liu Date: Tue, 7 Feb 2023 18:05:44 +0800 Subject: [PATCH 39/46] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a1b1b19..ca474f8 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ MLP.set_eval() - [TLXCV](https://github.com/tensorlayer/TLXCV) a series of Computer Vision applications - [TLXNLP](https://github.com/tensorlayer/TLXNLP) a series of Natural Language Processing applications - [TLX2ONNX](https://github.com/tensorlayer/TLX2ONNX/) ONNX model exporter for TensorLayerX. -- [paddle2tlx](https://github.com/tensorlayer/paddle2tlx) model code converter from PaddlePaddle to TensorLayerX. +- [Paddle2TLX](https://github.com/tensorlayer/paddle2tlx) model code converter from PaddlePaddle to TensorLayerX. More resources can be found [here](https://github.com/tensorlayer) From a9ac69cdff8d069c96c395b9d91e09f022d553c6 Mon Sep 17 00:00:00 2001 From: Hao <10713581+zsdonghao@users.noreply.github.com> Date: Tue, 7 Feb 2023 18:08:55 +0800 Subject: [PATCH 40/46] Update README.md --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ca474f8..63a54c6 100644 --- a/README.md +++ b/README.md @@ -90,12 +90,14 @@ More resources can be found [here](https://github.com/tensorlayer) # Installation -## The latest TensorLayerX compatible with the following backend version +- The latest TensorLayerX compatible with the following backend version + | TensorLayerX | TensorFlow | MindSpore | PaddlePaddle|PyTorch| | :-----:| :----: | :----: |:-----:|:----:| | v0.5.8 | v2.4.0 | v1.8.1 | v2.2.0 | v1.10.0 | | v0.5.7 | v2.0.0 | v1.6.1 | v2.0.2 | v1.10.0 | -## Via docker + +- Via docker Docker is an open source application container engine. In the [TensorLayerX Docker Repository](https://hub.docker.com/repository/docker/tensorlayer/tensorlayerx), different versions of TensorLayerX have been installed in docker images. @@ -105,14 +107,13 @@ different versions of TensorLayerX have been installed in docker images. docker pull tensorlayer/tensorlayerx:tagname ``` - -## Via pip for the stable version +- Via pip for the stable version ```bash # install from pypi pip3 install tensorlayerx ``` -## Build from source for the latest version +- Build from source for the latest version ```bash # install from Github pip3 install git+https://github.com/tensorlayer/tensorlayerx.git From 2a927df6c52d99b9b068187ffa5da95948a7a85c Mon Sep 17 00:00:00 2001 From: Hao <10713581+zsdonghao@users.noreply.github.com> Date: Tue, 7 Feb 2023 18:11:24 +0800 Subject: [PATCH 41/46] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 63a54c6..de8e61c 100644 --- a/README.md +++ b/README.md @@ -42,10 +42,11 @@ We have video courses for deep learning, with example codes based on TensorLayer # Multi-backend Design -You can immediately use TensorLayerX to define a model, using your favourite framework in the background, like so: +You can immediately use TensorLayerX to define a model via Pytorch-stype, and switch to any backends easily. + ```python import os -os.environ['TL_BACKEND'] = 'tensorflow' # modify this line, switch to any framework easily! +os.environ['TL_BACKEND'] = 'tensorflow' # modify this line, switch to any backends easily! #os.environ['TL_BACKEND'] = 'mindspore' #os.environ['TL_BACKEND'] = 'paddle' #os.environ['TL_BACKEND'] = 'torch' From af15601429b3ba9693e266e06677354f6363283d Mon Sep 17 00:00:00 2001 From: Hao <10713581+zsdonghao@users.noreply.github.com> Date: Tue, 7 Feb 2023 22:11:52 +0800 Subject: [PATCH 42/46] Update countlines.py --- countlines.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/countlines.py b/countlines.py index 16a9a71..50ea9d4 100644 --- a/countlines.py +++ b/countlines.py @@ -22,7 +22,6 @@ def countlines(start, lines=0, header=True, begin_start=None): print('{:>10} |{:>10} | {:<20}'.format( newlines, lines, reldir_of_thing)) - for thing in os.listdir(start): thing = os.path.join(start, thing) if os.path.isdir(thing): @@ -31,4 +30,4 @@ def countlines(start, lines=0, header=True, begin_start=None): return lines if __name__ == '__main__': - countlines('.') \ No newline at end of file + countlines('.') From 27360e6f5dc7117e185b1f6ad364b6b5e5e4a6e2 Mon Sep 17 00:00:00 2001 From: Hao <10713581+zsdonghao@users.noreply.github.com> Date: Tue, 7 Feb 2023 23:42:24 +0800 Subject: [PATCH 43/46] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index de8e61c..0038527 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ We have video courses for deep learning, with example codes based on TensorLayer - ***Model Zoo***: Provide a series of applications containing classic and SOTA models, covering CV, NLP, RL and other fields. -- ***Deploy***: Support ONNX protocol, model export, import and deployment. +- ***Deployment***: Support ONNX protocol, model export, import and deployment. # Multi-backend Design From 7d58fb9dac1133ca9e86af6a4a31269c97c55028 Mon Sep 17 00:00:00 2001 From: Cheng Lai Date: Wed, 8 Feb 2023 09:23:53 +0800 Subject: [PATCH 44/46] Update docs * TensorLayerX 0.5.8 Release * Update docs * Update README.md * Update README.md --- .dockerignore | 1 + .pyup.yml | 3 --- .readthedocs.yml | 2 +- docker/DockerLint.bat | 4 ++-- docker/Dockerfile | 4 ++-- docs/user/installation.rst | 8 ++++---- setup.cfg | 2 +- tlx | 2 -- 8 files changed, 11 insertions(+), 15 deletions(-) diff --git a/.dockerignore b/.dockerignore index 6b8710a..6858fa7 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1 +1,2 @@ .git +.log diff --git a/.pyup.yml b/.pyup.yml index 6c96920..3b7d941 100644 --- a/.pyup.yml +++ b/.pyup.yml @@ -42,9 +42,6 @@ requirements: # Not necessary, but recommended libraries - requirements/requirements_extra.txt - # Requirements for contrib loggers - - requirements_contrib_loggers.txt - # Requirements for the db - requirements/requirements_db.txt diff --git a/.readthedocs.yml b/.readthedocs.yml index 0752675..8df62b2 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -8,7 +8,7 @@ formats: - pdf python: - version: 3.6 + version: 3.7 requirements_file: requirements/requirements_doc.txt diff --git a/docker/DockerLint.bat b/docker/DockerLint.bat index 3a4b1f8..6a1db20 100644 --- a/docker/DockerLint.bat +++ b/docker/DockerLint.bat @@ -1,4 +1,4 @@ -docker pull hadolint/hadolint:latest -docker run --rm -i hadolint/hadolint hadolint --ignore DL3007 - < Dockerfile +docker pull tensorlayer/tensorlayerx:tagname +docker run --rm -i tensorlayer/tensorlayerx hadolint --ignore DL3007 - < Dockerfile PAUSE; \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile index 2d3b689..1c2c70f 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -24,8 +24,8 @@ RUN echo "Container Tag: ${TF_CONTAINER_VERSION}" \ echo "Building a Nightly Release" \ && apt-get install -y git \ && mkdir /dist/ && cd /dist/ \ - && git clone https://github.com/tensorlayer/tensorlayer.git \ - && cd tensorlayer \ + && git clone https://github.com/tensorlayer/tensorlayerx.git \ + && cd tensorlayerx \ && pip install --disable-pip-version-check --no-cache-dir --upgrade -e .[all]; \ else \ echo "Building Tag Release: $TL_VERSION" \ diff --git a/docs/user/installation.rst b/docs/user/installation.rst index 886798f..29aab5c 100644 --- a/docs/user/installation.rst +++ b/docs/user/installation.rst @@ -4,8 +4,8 @@ Installation ============ -TensorLayerX has some prerequisites that need to be installed first, including -`TensorFlow`_ , `MindSpore `__, `PaddlePaddle `__, `PyTorch `__, numpy and matplotlib. For GPU +TensorLayerX has some prerequisites that need to be installed first, including NumPy, Matplotlib and one of the frameworks ( +`TensorFlow`_ , `MindSpore `__, `PaddlePaddle `__, `PyTorch `__). For GPU support CUDA and cuDNN are required. If you run into any trouble, please check the `TensorFlow installation @@ -13,7 +13,7 @@ instructions `__, `PaddlePaddle installation instructions `__, `PyTorch installation instructions `__, -which cover installing the TensorFlow for a range of operating systems including +which cover installing the frameworks for a range of operating systems including Mac OX, Linux and Windows, or ask for help on `tensorlayer@gmail.com `_ or `FAQ `_. @@ -47,7 +47,7 @@ Alternatively, you can build from the source. # First clone the repository and change the current directory to the newly cloned repository git clone https://github.com/tensorlayer/TensorLayerX.git - cd tensorlayer + cd tensorlayerx python setup.py install This command will run the ``setup.py`` to install TensorLayerX. diff --git a/setup.cfg b/setup.cfg index 1fe0495..b901b86 100644 --- a/setup.cfg +++ b/setup.cfg @@ -12,7 +12,7 @@ exclude = venv, __pycache__, .pytest_cache, - tensorlayer.egg-info, + tensorlayerx.egg-info, build, dist, img diff --git a/tlx b/tlx index 6699c3e..0f3ee24 100644 --- a/tlx +++ b/tlx @@ -9,5 +9,3 @@ done DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" export PYTHONPATH="${DIR}/src:${PYTHONPATH}" - -# python3 -m tensorlayer.cli "$@" From 6180c3b2b1013834c7fe9f68d7a2d2c914de1a5a Mon Sep 17 00:00:00 2001 From: hanjr92 Date: Mon, 13 Feb 2023 18:48:21 +0800 Subject: [PATCH 45/46] fix mindspore dynamic lr --- docs/modules/nn.rst | 4 ++++ .../{tensorlayer_model_load.py => tensorlayerx_model_load.py} | 0 tensorlayerx/optimizers/lr/mindspore_lr.py | 3 ++- 3 files changed, 6 insertions(+), 1 deletion(-) rename examples/basic_tutorials/{tensorlayer_model_load.py => tensorlayerx_model_load.py} (100%) diff --git a/docs/modules/nn.rst b/docs/modules/nn.rst index e19c753..f931906 100644 --- a/docs/modules/nn.rst +++ b/docs/modules/nn.rst @@ -377,6 +377,10 @@ Batch Normalization 3D ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autoclass:: BatchNorm3d +Layer Normalization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. autoclass:: LayerNorm + .. ----------------------------------------------------------- .. Padding Layers .. ----------------------------------------------------------- diff --git a/examples/basic_tutorials/tensorlayer_model_load.py b/examples/basic_tutorials/tensorlayerx_model_load.py similarity index 100% rename from examples/basic_tutorials/tensorlayer_model_load.py rename to examples/basic_tutorials/tensorlayerx_model_load.py diff --git a/tensorlayerx/optimizers/lr/mindspore_lr.py b/tensorlayerx/optimizers/lr/mindspore_lr.py index ed76613..3e89f45 100644 --- a/tensorlayerx/optimizers/lr/mindspore_lr.py +++ b/tensorlayerx/optimizers/lr/mindspore_lr.py @@ -25,10 +25,11 @@ def __init__(self, learning_rate=0.1, last_epoch=-1, verbose=False): self.base_lr = learning_rate self.last_lr = learning_rate self.verbose = verbose + self.cast = P.Cast() def construct(self, global_step): - return self.last_lr + return self.cast(self.last_lr, mstype.float32) def step(self, epoch=None): if epoch is None: From 45c247ec378a02503a819d26859ea187e3e61784 Mon Sep 17 00:00:00 2001 From: Jiarong Han Date: Tue, 14 Feb 2023 11:15:23 +0800 Subject: [PATCH 46/46] Update requirements_doc.txt --- requirements/requirements_doc.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements/requirements_doc.txt b/requirements/requirements_doc.txt index cad416f..e158b90 100644 --- a/requirements/requirements_doc.txt +++ b/requirements/requirements_doc.txt @@ -2,9 +2,10 @@ flake8-docstrings>=1.3,<1.4 pycodestyle>=2.5.0 pydocstyle>=2.1,<3.1 sphinx==2.0.1 +jinja2==3.0.3 sphinx_rtd_theme>=0.4,<0.5 wrapt>=1.11.1 h5py>=2.9 cloudpickle>=0.8.1 tensorflow>=2.0.0 -sphinx-mathjax-offline \ No newline at end of file +sphinx-mathjax-offline