diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..c6905e08 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "daily" + - package-ecosystem: "pip" + directory: "/docs/" + schedule: + interval: "weekly" + target-branch: "docs" \ No newline at end of file diff --git a/.github/workflows/tox_run.yml b/.github/workflows/tox_run.yml index 533f2112..db6e7cf4 100644 --- a/.github/workflows/tox_run.yml +++ b/.github/workflows/tox_run.yml @@ -74,9 +74,29 @@ jobs: run: | python -m pip install --upgrade pip pip install tox - - name: Python 3.10 + - name: Test with tox run: tox -e py310 + py311: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.11"] + fail-fast: false + + steps: + - uses: actions/checkout@v1 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install tox + - name: Test with tox + run: tox -e py311 + minimum_numpy: runs-on: ubuntu-latest strategy: @@ -96,3 +116,18 @@ jobs: pip install tox - name: Test vs Minimum Python/Numpy run: tox -e min_numpy + + check-repo-format: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Python 3.9 + uses: actions/setup-python@v4 + with: + python-version: 3.9 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install tox tox-gh-actions + - name: Test with tox + run: tox -e enforce-format \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..105214c6 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,13 @@ +repos: +- repo: https://github.com/psf/black + rev: 22.10.0 + hooks: + - id: black +- repo: https://github.com/PyCQA/flake8 + rev: 6.0.0 + hooks: + - id: flake8 +- repo: https://github.com/pre-commit/mirrors-isort + rev: v5.10.1 + hooks: + - id: isort \ No newline at end of file diff --git a/README.md b/README.md index 649d9e84..218063e2 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Documentation Status](https://readthedocs.org/projects/mygrad/badge/?version=latest)](https://mygrad.readthedocs.io/en/latest/?badge=latest) [![Automated tests status](https://github.com/rsokl/MyGrad/workflows/Tests/badge.svg)](https://github.com/rsokl/MyGrad/actions?query=workflow%3ATests+branch%3Amaster) [![PyPi version](https://img.shields.io/pypi/v/mygrad.svg)](https://pypi.python.org/pypi/mygrad) -![Python version support](https://img.shields.io/badge/python-3.7%20‐%203.10-blue.svg) +![Python version support](https://img.shields.io/badge/python-3.7%20‐%203.11-blue.svg) # [MyGrad's Documentation](https://mygrad.readthedocs.io/en/latest/) diff --git a/docs/source/changes.rst b/docs/source/changes.rst index 83114214..62cc2657 100644 --- a/docs/source/changes.rst +++ b/docs/source/changes.rst @@ -6,6 +6,18 @@ This is a record of all past mygrad releases and what went into them, in reverse chronological order. All previous releases should still be available on pip. +.. _v2.2.0: + +-------------------- +2.2.0rc - 2022-XX-XX +-------------------- + +- MyGrad is now tested against Python 3.11. (:pull:`411`) +- `mygrad.bool8` has been removed. Use `mygrad.bool_` instead. (:pull:`411`) +- Adds ufunc support for `resolve_dtypes`. (:pull:`411`) +- Modifies automatic differentiation framework to be simpler and more memory efficient. In the future, MyGrad will be able to expose an API akin to `torch.autograd.grad _`. (:pull:`407`) +- MyGrad's CI now enforces formatting and spell check requirements on all pull requests. (:pull:`411`) + .. _v2.1.0: ------------------ diff --git a/docs/source/conf.py b/docs/source/conf.py index 287f09d8..92405988 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -78,6 +78,16 @@ # The name of the Pygments (syntax highlighting) style to use. pygments_style = None +_repo = "https://github.com/rsokl/MyGrad/" +extlinks = { + "commit": (_repo + "commit/%s", "commit %s"), + "gh-file": (_repo + "blob/master/%s", "%s"), + "gh-link": (_repo + "%s", "%s"), + "issue": (_repo + "issues/%s", "issue #%s"), + "pull": (_repo + "pull/%s", "pull request #%s"), + "plymi": ("https://www.pythonlikeyoumeanit.com/%s", "%s"), + "hydra": ("https://hydra.cc/docs/%s", "%s"), +} # -- Options for HTML output ------------------------------------------------- diff --git a/setup.cfg b/setup.cfg index 6abce67a..c80670e6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -9,8 +9,8 @@ line_length = 88 src_paths=src/mygrad,tests [flake8] -exclude = docs/*, src/mygrad/__init__.py, src/mygrad/numpy_compat/__init__.py - +extend-ignore = F811,D1,D205,D209,D213,D400,D401,D999,D202,E203,E501,W503,E721,F403,F405 +exclude = .git,__pycache__,docs,old,build,dis,tests/annotations/*, tests/test_py310.py,versioneer.py,docs/*, src/mygrad/__init__.py, src/mygrad/numpy_compat/__init__.py,src/mygrad/nnet/__init__.py [versioneer] VCS = git @@ -26,8 +26,12 @@ omit = src/mygrad/_version.py src/mygrad/computational_graph.py +[codespell] +skip = *.po,*.ts,**/_version.py, +ignore-words-list = ND,nd,nin,dout + [tox:tox] -envlist = py37,py38,py39,format,min_numpy +envlist = py37,py38,py39,,format,min_numpy [gh-actions] python = @@ -35,13 +39,15 @@ python = 3.8: py38 3.9: py39 3.10: py310 + 3.11: py311 [testenv] deps = pytest hypothesis scipy -commands = pytest --hypothesis-profile ci \ + pytest-xdist +commands = pytest -n auto --hypothesis-profile ci \ {posargs} extras = rnn @@ -50,15 +56,22 @@ extras = rnn deps = numpy==1.20 {[testenv]deps} basepython = python3.7 -commands = pytest --hypothesis-profile ci \ +commands = pytest -n auto --hypothesis-profile ci \ {posargs} extras = [testenv:py310] # exclude numba dependency for now deps = pytest + pytest-xdist hypothesis scipy -commands = pytest --hypothesis-profile ci \ +commands = pytest -n auto --hypothesis-profile ci \ + {posargs} +extras = + +[testenv:py311] # exclude numba dependency for now +deps = {[testenv:py310]deps} +commands = pytest -n auto --hypothesis-profile ci \ {posargs} extras = @@ -70,7 +83,7 @@ basepython = python3.7 deps = {[testenv]deps} coverage pytest-cov -commands = pytest --cov-report term-missing --cov-config=setup.cfg --cov-fail-under=100 --cov=mygrad tests +commands = pytest -n auto --cov-report term-missing --cov-config=setup.cfg --cov-fail-under=100 --cov=mygrad tests [testenv:format] @@ -89,7 +102,23 @@ pip_pre = true deps = pytest hypothesis scipy + pytest-xdist basepython = python3.8 -commands = pytest --hypothesis-profile ci \ +commands = pytest -n auto --hypothesis-profile ci \ {posargs} extras = + + +[testenv:enforce-format] +skip_install=true +basepython=python3.9 +deps=black + isort + flake8 + pytest + codespell +commands= + black src/ tests/ --diff --check + isort src/ tests/ --diff --check + flake8 src/ tests/ + codespell src/ docs/ \ No newline at end of file diff --git a/src/mygrad/__init__.py b/src/mygrad/__init__.py index fec278c2..5e9bd813 100644 --- a/src/mygrad/__init__.py +++ b/src/mygrad/__init__.py @@ -32,9 +32,9 @@ from mygrad.tensor_manip.tiling.funcs import * from mygrad.tensor_manip.transpose_like.funcs import * from mygrad.ufuncs._ufunc_creators import ufunc -from ._io import load, save from . import random +from ._io import load, save from ._version import get_versions __version__ = get_versions()["version"] diff --git a/src/mygrad/_dtype_mirrors.py b/src/mygrad/_dtype_mirrors.py index aee2b9fd..61f629ae 100644 --- a/src/mygrad/_dtype_mirrors.py +++ b/src/mygrad/_dtype_mirrors.py @@ -1,7 +1,7 @@ import numpy __all__ = [ - "bool8", + "bool_", "int8", "int16", "int32", @@ -21,7 +21,8 @@ "longdouble", ] -bool8 = numpy.bool8 + +bool_ = numpy.bool_ int8 = numpy.int8 int16 = numpy.int16 int32 = numpy.int32 diff --git a/src/mygrad/_utils/__init__.py b/src/mygrad/_utils/__init__.py index 01920d6a..8f7d86a7 100644 --- a/src/mygrad/_utils/__init__.py +++ b/src/mygrad/_utils/__init__.py @@ -18,7 +18,7 @@ if TYPE_CHECKING: # pragma: no cover from mygrad import Tensor - from mygrad.operation_base import Operation + from mygrad.operation_base import Operation # noqa: F401 __all__ = [ "collect_all_operations_and_clear_grads", diff --git a/src/mygrad/_utils/duplicating_graph.py b/src/mygrad/_utils/duplicating_graph.py index b37103a0..e3b9d13d 100644 --- a/src/mygrad/_utils/duplicating_graph.py +++ b/src/mygrad/_utils/duplicating_graph.py @@ -191,7 +191,7 @@ def __iter__(self) -> Iterator[Node]: yield from self._yield_children(self.base.placeholder) def get_path_to_base(self, tensor: "Tensor") -> List[Node]: - """ Returns [leaf, (parent), ..., base]""" + """Returns [leaf, (parent), ..., base]""" path = [] node = self[tensor] while node.parent is not None: @@ -201,7 +201,7 @@ def get_path_to_base(self, tensor: "Tensor") -> List[Node]: return path def restore_old_graph(self): - """ Reroute graph back to original tensors.""" + """Reroute graph back to original tensors.""" # call tuple to ensure iteration is completed # before information gets deleted / mutated for node in tuple(self): diff --git a/src/mygrad/_utils/graph_tracking.py b/src/mygrad/_utils/graph_tracking.py index 758941ee..fc9491d5 100644 --- a/src/mygrad/_utils/graph_tracking.py +++ b/src/mygrad/_utils/graph_tracking.py @@ -2,7 +2,7 @@ Provides user interface for suspending computational graph tracking and back-propagation """ from functools import wraps -from typing import Callable, TypeVar, Any, cast, Optional +from typing import Any, Callable, TypeVar, cast import numpy as np diff --git a/src/mygrad/computational_graph.py b/src/mygrad/computational_graph.py index ea0c1f92..fdc1f8ae 100644 --- a/src/mygrad/computational_graph.py +++ b/src/mygrad/computational_graph.py @@ -97,7 +97,7 @@ def build_graph( def _add_node(node, graph, op_id=None, **kwargs): - """ Recursively traces computational graph and adds nodes to Digraph. """ + """Recursively traces computational graph and adds nodes to Digraph.""" node_id = str(id(node)) node_lab = repr(node) if kwargs["names"] is not None: diff --git a/src/mygrad/linalg/__init__.py b/src/mygrad/linalg/__init__.py index 50fb42c6..eb87ebf6 100644 --- a/src/mygrad/linalg/__init__.py +++ b/src/mygrad/linalg/__init__.py @@ -1 +1 @@ -from .funcs import norm +from .funcs import norm # noqa: F401 diff --git a/src/mygrad/linalg/funcs.py b/src/mygrad/linalg/funcs.py index 5852dc23..08b9598a 100644 --- a/src/mygrad/linalg/funcs.py +++ b/src/mygrad/linalg/funcs.py @@ -4,7 +4,6 @@ import numpy as np from numpy.core.einsumfunc import _parse_einsum_input -import mygrad as mg from mygrad.math.misc.funcs import absolute from mygrad.math.sequential.funcs import max as mg_max, min as mg_min from mygrad.tensor_base import Tensor, implements_numpy_override @@ -105,7 +104,7 @@ def norm( References ---------- - .. [1] Retrived from: https://numpy.org/doc/stable/reference/generated/numpy.linalg.norm.html + .. [1] Retrieved from: https://numpy.org/doc/stable/reference/generated/numpy.linalg.norm.html .. [2] G. H. Golub and C. F. Van Loan, *Matrix Computations*, Baltimore, MD, Johns Hopkins University Press, 1985, pg. 15 @@ -118,7 +117,7 @@ def norm( >>> l2_norms Tensor([3.74165739, 1. ]) - The presence of the elementwise absolute values in the norm operation means that zero-valued entries in any of + The presence of the elementwise absolute values in the norm operation means that zero-valued entries in any of input vectors have an undefined derivative. When `nan_to_num=False` is specified these derivatives will be reported as `nan`, otherwise they will be made to be 0.0. diff --git a/src/mygrad/linalg/ops.py b/src/mygrad/linalg/ops.py index 4ee398ff..9deac1bb 100644 --- a/src/mygrad/linalg/ops.py +++ b/src/mygrad/linalg/ops.py @@ -329,7 +329,7 @@ def backward_var(self, grad: np.ndarray, index: int, **kwargs) -> np.ndarray: if out.size: # if out.size is 0, then this produces div-by-zero _norm = self._norm / np.sum( - out ** self.ord, axis=self.axis, keepdims=True + out**self.ord, axis=self.axis, keepdims=True ) else: _norm = +self._norm diff --git a/src/mygrad/math/arithmetic/ops.py b/src/mygrad/math/arithmetic/ops.py index 3c35a9e5..ae7420d2 100644 --- a/src/mygrad/math/arithmetic/ops.py +++ b/src/mygrad/math/arithmetic/ops.py @@ -61,7 +61,7 @@ def backward_var(self, grad, index, **kwargs): if index == 0: # backprop through a return grad / b.data else: # broadcast through b - return -grad * a.data / (b.data ** 2) + return -grad * a.data / (b.data**2) class Power(BinaryUfunc): @@ -73,7 +73,7 @@ def backward_var(self, grad, index, **kwargs): if index == 0: return grad * y * (x ** np.where(y, (y - 1), 1)) else: - return grad * (x ** y) * np.log(np.where(x, x, 1)) + return grad * (x**y) * np.log(np.where(x, x, 1)) # Unary Ops @@ -84,7 +84,7 @@ class Reciprocal(UnaryUfunc): def backward_var(self, grad, index, **kwargs): (a,) = self.variables - return -grad * np.reciprocal(a.data ** 2) + return -grad * np.reciprocal(a.data**2) class Square(UnaryUfunc): @@ -124,7 +124,7 @@ def backward_var(self, grad, index, **kwargs): class MultiplySequence(Operation): - """ Performs f(a, b, ..., z) = a * b * ... * z""" + """Performs f(a, b, ..., z) = a * b * ... * z""" def __call__(self, *input_vars: "Tensor") -> np.ndarray: self.variables = input_vars diff --git a/src/mygrad/math/hyperbolic_trig/ops.py b/src/mygrad/math/hyperbolic_trig/ops.py index a01409a8..af16b64d 100644 --- a/src/mygrad/math/hyperbolic_trig/ops.py +++ b/src/mygrad/math/hyperbolic_trig/ops.py @@ -42,7 +42,7 @@ def backward_var(self, grad, index, **kwargs): class Csch(Operation): - """ f(a) -> csch(a) """ + """f(a) -> csch(a)""" def __call__(self, a): self.variables = (a,) @@ -54,7 +54,7 @@ def backward_var(self, grad, index, **kwargs): class Sech(Operation): - """ f(a) -> sech(a) """ + """f(a) -> sech(a)""" def __call__(self, a): self.variables = (a,) @@ -66,7 +66,7 @@ def backward_var(self, grad, index, **kwargs): class Coth(Operation): - """ f(a) -> coth(a) """ + """f(a) -> coth(a)""" def __call__(self, a): self.variables = (a,) @@ -82,7 +82,7 @@ class Arcsinh(UnaryUfunc): def backward_var(self, grad, index, **kwargs): (a,) = self.variables - return grad / np.sqrt(1 + a.data ** 2) + return grad / np.sqrt(1 + a.data**2) class Arccosh(UnaryUfunc): @@ -90,7 +90,7 @@ class Arccosh(UnaryUfunc): def backward_var(self, grad, index, **kwargs): (a,) = self.variables - return grad / np.sqrt(a.data ** 2 - 1) + return grad / np.sqrt(a.data**2 - 1) class Arctanh(UnaryUfunc): @@ -98,11 +98,11 @@ class Arctanh(UnaryUfunc): def backward_var(self, grad, index, **kwargs): (a,) = self.variables - return grad / (1 - a.data ** 2) + return grad / (1 - a.data**2) class Arccsch(Operation): - """ f(a) -> arccsch(a) """ + """f(a) -> arccsch(a)""" def __call__(self, a): self.variables = (a,) @@ -110,11 +110,11 @@ def __call__(self, a): def backward_var(self, grad, index, **kwargs): (a,) = self.variables - return -grad / (np.abs(a.data) * np.sqrt(1 + a.data ** 2)) + return -grad / (np.abs(a.data) * np.sqrt(1 + a.data**2)) class Arccoth(Operation): - """ f(a) -> arccoth(a) """ + """f(a) -> arccoth(a)""" def __call__(self, a): self.variables = (a,) @@ -122,4 +122,4 @@ def __call__(self, a): def backward_var(self, grad, index, **kwargs): (a,) = self.variables - return grad / (1 - a.data ** 2) + return grad / (1 - a.data**2) diff --git a/src/mygrad/math/misc/funcs.py b/src/mygrad/math/misc/funcs.py index c54cbc0d..85750e25 100644 --- a/src/mygrad/math/misc/funcs.py +++ b/src/mygrad/math/misc/funcs.py @@ -817,7 +817,7 @@ def _multi_matmul_chain_order(arrays): n = len(arrays) # p stores the dimensions of the matrices # Example for p: A_{10x100}, B_{100x5}, C_{5x50} --> p = [10, 100, 5, 50] - # Using -2 to generalize for shapes that are more than 2 dimmensions + # Using -2 to generalize for shapes that are more than 2 dimensions p = [a.shape[-2] for a in arrays] + [arrays[-1].shape[-1]] # m is a matrix of costs of the subproblems # m[i,j]: min number of scalar multiplications needed to compute A_{i..j} diff --git a/src/mygrad/math/misc/ops.py b/src/mygrad/math/misc/ops.py index 6af7be3f..49658224 100644 --- a/src/mygrad/math/misc/ops.py +++ b/src/mygrad/math/misc/ops.py @@ -38,7 +38,7 @@ class Cbrt(UnaryUfunc): def backward_var(self, grad, index, **kwargs): (a,) = self.variables - return grad / (3 * np.cbrt(a.data ** 2)) + return grad / (3 * np.cbrt(a.data**2)) class _MaxMin(BinaryUfunc, ABC): diff --git a/src/mygrad/math/trigonometric/ops.py b/src/mygrad/math/trigonometric/ops.py index d97693fc..ce3e7e74 100644 --- a/src/mygrad/math/trigonometric/ops.py +++ b/src/mygrad/math/trigonometric/ops.py @@ -30,7 +30,7 @@ def backward_var(self, grad, index, **kwargs): def _dsinc(x): x = x * np.pi - return (x * np.cos(x) - np.sin(x)) / x ** 2 + return (x * np.cos(x) - np.sin(x)) / x**2 class Sinc(Operation): @@ -109,7 +109,7 @@ class Arcsin(UnaryUfunc): def backward_var(self, grad, index, **kwargs): # d arcsin / dx at x = -1, 1 returns 0, not NaN (a,) = self.variables - return np.select([np.abs(a.data) != 1], [grad / np.sqrt(1 - a.data ** 2)]) + return np.select([np.abs(a.data) != 1], [grad / np.sqrt(1 - a.data**2)]) class Arccos(UnaryUfunc): @@ -118,7 +118,7 @@ class Arccos(UnaryUfunc): def backward_var(self, grad, index, **kwargs): # d arccos / dx at x = -1, 1 returns 0, not NaN (a,) = self.variables - return np.select([np.abs(a.data) != 1], [-grad / np.sqrt(1 - a.data ** 2)]) + return np.select([np.abs(a.data) != 1], [-grad / np.sqrt(1 - a.data**2)]) class Arctan(UnaryUfunc): @@ -126,7 +126,7 @@ class Arctan(UnaryUfunc): def backward_var(self, grad, index, **kwargs): (a,) = self.variables - return grad / (1 + a.data ** 2) + return grad / (1 + a.data**2) class Arccsc(Operation): @@ -140,7 +140,7 @@ def backward_var(self, grad, index, **kwargs): # d arccsc / dx at x = -1, 1 returns 0, not NaN (a,) = self.variables return np.select( - [np.abs(a.data) != 1], [-grad / (np.abs(a.data) * np.sqrt(a.data ** 2 - 1))] + [np.abs(a.data) != 1], [-grad / (np.abs(a.data) * np.sqrt(a.data**2 - 1))] ) @@ -155,7 +155,7 @@ def backward_var(self, grad, index, **kwargs): # d arcsec / dx at x = -1, 1 returns 0, not NaN (a,) = self.variables return np.select( - [np.abs(a.data) != 1], [grad / (np.abs(a.data) * np.sqrt(a.data ** 2 - 1))] + [np.abs(a.data) != 1], [grad / (np.abs(a.data) * np.sqrt(a.data**2 - 1))] ) @@ -174,7 +174,7 @@ def __call__(self, a): def backward_var(self, grad, index, **kwargs): (a,) = self.variables - return -grad / (1 + a.data ** 2) + return -grad / (1 + a.data**2) class Arctan2(BinaryUfunc): @@ -187,7 +187,7 @@ def __init__(self): def backward_var(self, grad, index, **kwargs): a, b = self.variables if self.cached_denom is None: - self.cached_denom = a.data ** 2 + b.data ** 2 + self.cached_denom = a.data**2 + b.data**2 if index == 0: return grad * b.data / self.cached_denom diff --git a/src/mygrad/nnet/activations/selu.py b/src/mygrad/nnet/activations/selu.py index 8be1c6fc..a1be3eba 100644 --- a/src/mygrad/nnet/activations/selu.py +++ b/src/mygrad/nnet/activations/selu.py @@ -4,7 +4,7 @@ from mygrad import Tensor from mygrad.operation_base import Operation -from mygrad.typing import ArrayLike, Real +from mygrad.typing import ArrayLike __all__ = ["selu"] diff --git a/src/mygrad/nnet/initializers/he_normal.py b/src/mygrad/nnet/initializers/he_normal.py index b71ed47a..b3aea242 100644 --- a/src/mygrad/nnet/initializers/he_normal.py +++ b/src/mygrad/nnet/initializers/he_normal.py @@ -42,7 +42,7 @@ def he_normal(*shape, gain=1, dtype=np.float32, constant=None): where :math:`a` is the slope of the rectifier following this layer, which is incorporated using the `gain` variable above. - The guidance put forward in that paper is that this initialization procedure should be prefered + The guidance put forward in that paper is that this initialization procedure should be preferred over the ``mygrad.nnet.initializers.glorot_*`` functions especially when rectifiers (e.g. ReLU, PReLU, leaky_relu) in very deep (> 1-20 or so layer) networks. diff --git a/src/mygrad/nnet/initializers/he_uniform.py b/src/mygrad/nnet/initializers/he_uniform.py index d6247b06..00348463 100644 --- a/src/mygrad/nnet/initializers/he_uniform.py +++ b/src/mygrad/nnet/initializers/he_uniform.py @@ -42,7 +42,7 @@ def he_uniform(*shape, gain=1, dtype=np.float32, constant=None): where :math:`a` is the slope of the rectifier following this layer, which is incorporated using the `gain` variable above. - The guidance put forward in that paper is that this initialization procedure should be prefered + The guidance put forward in that paper is that this initialization procedure should be preferred over the ``mygrad.nnet.initializers.glorot_*`` functions especially when rectifiers (e.g. ReLU, PReLU, leaky_relu) in very deep (> 1-20 or so layer) networks. diff --git a/src/mygrad/nnet/layers/batchnorm.py b/src/mygrad/nnet/layers/batchnorm.py index eae21e94..3e887b2b 100644 --- a/src/mygrad/nnet/layers/batchnorm.py +++ b/src/mygrad/nnet/layers/batchnorm.py @@ -1,4 +1,4 @@ -from typing import Optional, Tuple, Union +from typing import Optional import numpy as np diff --git a/src/mygrad/nnet/layers/gru.py b/src/mygrad/nnet/layers/gru.py index 53d61364..f9679592 100644 --- a/src/mygrad/nnet/layers/gru.py +++ b/src/mygrad/nnet/layers/gru.py @@ -45,7 +45,7 @@ def d_tanh(f): # pragma: no cover """ Calculates the derivative of a tanh function """ - return 1 - f ** 2 + return 1 - f**2 @njit diff --git a/src/mygrad/nnet/losses/focal_loss.py b/src/mygrad/nnet/losses/focal_loss.py index 552c2753..fcf55086 100644 --- a/src/mygrad/nnet/losses/focal_loss.py +++ b/src/mygrad/nnet/losses/focal_loss.py @@ -67,7 +67,7 @@ def __call__(self, class_probs, targets, alpha, gamma): one_m_pc = np.clip(1 - pc, a_min=0, a_max=1) log_pc = np.log(pc) - one_m_pc_gamma = one_m_pc ** gamma + one_m_pc_gamma = one_m_pc**gamma loss = -(alpha * one_m_pc_gamma * log_pc) if not _tracking.TRACK_GRAPH: diff --git a/src/mygrad/tensor_base.py b/src/mygrad/tensor_base.py index 68566fb4..ab2e4865 100644 --- a/src/mygrad/tensor_base.py +++ b/src/mygrad/tensor_base.py @@ -202,7 +202,7 @@ def tensor( ndmin : int, optional Specifies the minimum number of dimensions that the resulting - tensor should have. Ones will be pre-pended to the shape as + tensor should have. Ones will be prepended to the shape as needed to meet this requirement. Returns @@ -820,7 +820,7 @@ def __init__( self._grad = None # type: Union[None, np.ndarray] # track all operations that this tensor participates in - self._ops = set() # type: Set[WeakRef[Operation]] + self._ops: Set[WeakRef[Operation]] = set() # base points to the initial tensor that owns the memory of this # tensor @@ -1908,7 +1908,7 @@ def shape(self, newshape: Union[int, Shape]): del out # although `self` is a view of placeholder, placeholder - # is stricly an internal tensor, we won't expose it as + # is strictly an internal tensor, we won't expose it as # base graph.base.placeholder._view_children.append(self) base = graph.base.placeholder.base diff --git a/src/mygrad/tensor_manip/array_shape/ops.py b/src/mygrad/tensor_manip/array_shape/ops.py index b6115889..b7cf5aeb 100644 --- a/src/mygrad/tensor_manip/array_shape/ops.py +++ b/src/mygrad/tensor_manip/array_shape/ops.py @@ -18,8 +18,9 @@ class _PreservesOrder(Operation): - """Base class for operations that preserve an array's size + """Base class for operations that preserve an array's size and flat-iteration element ordering""" + def backward_var(self, grad: np.ndarray, index: int, **kwargs) -> np.ndarray: (a,) = self.variables return np.reshape(grad, a.shape) diff --git a/src/mygrad/typing/_array_like.py b/src/mygrad/typing/_array_like.py index 7b9d521c..0df89850 100644 --- a/src/mygrad/typing/_array_like.py +++ b/src/mygrad/typing/_array_like.py @@ -34,7 +34,6 @@ class ImplementsArray: def __array__(self, dtype: None = ...) -> np.ndarray: ... - else: # pragma: no cover class ImplementsArray(Protocol): diff --git a/src/mygrad/ufuncs/_ufunc_creators.py b/src/mygrad/ufuncs/_ufunc_creators.py index 4f4cc44b..9ac312be 100644 --- a/src/mygrad/ufuncs/_ufunc_creators.py +++ b/src/mygrad/ufuncs/_ufunc_creators.py @@ -388,33 +388,34 @@ def reduceat( for type_code in op.numpy_ufunc.types if _permitted_type_str(type_code) ] - out = MetaBuilder( - decorated_func.__name__, - (object,), - ( - { - "_wrapped_op": op, - "at": at, - "accumulate": accumulate, - "reduce": reduce, - "reduceat": reduceat, - "outer": outer, - "signature": op.numpy_ufunc.signature, - "identity": op.numpy_ufunc.identity, - "nargs": op.numpy_ufunc.nargs, - "nin": op.numpy_ufunc.nin, - "nout": op.numpy_ufunc.nout, - "ntypes": len(types), - "types": types, - "_decorated_func": decorated_func, - "__name__": decorated_func.__name__, - "__qualname__": decorated_func.__name__, - "__signature__": signature(decorated_func), - "__annotations__": get_type_hints(decorated_func), - "__doc__": decorated_func.__doc__, - } - ), - ) + + _namespace = { + "_wrapped_op": op, + "at": at, + "accumulate": accumulate, + "reduce": reduce, + "reduceat": reduceat, + "outer": outer, + "signature": op.numpy_ufunc.signature, + "identity": op.numpy_ufunc.identity, + "nargs": op.numpy_ufunc.nargs, + "nin": op.numpy_ufunc.nin, + "nout": op.numpy_ufunc.nout, + "ntypes": len(types), + "types": types, + "_decorated_func": decorated_func, + "__name__": decorated_func.__name__, + "__qualname__": decorated_func.__name__, + "__signature__": signature(decorated_func), + "__annotations__": get_type_hints(decorated_func), + "__doc__": decorated_func.__doc__, + } + try: + _namespace["resolve_dtypes"] = op.numpy_ufunc.resolve_dtypes + except AttributeError: # pragma: no cover + pass + + out = MetaBuilder(decorated_func.__name__, (object,), _namespace) ufunc.register(out) return out diff --git a/tests/custom_strategies/__init__.py b/tests/custom_strategies/__init__.py index 0096f2c9..df8b5e48 100644 --- a/tests/custom_strategies/__init__.py +++ b/tests/custom_strategies/__init__.py @@ -591,7 +591,7 @@ def _factors(n: int) -> List[int]: {1, 2, 4}""" if not isinstance(n, int) and 0 <= n: raise ValueError(f"n={n} must be a non-negative integer") - gen = ([i, n // i] for i in range(1, int(n ** 0.5) + 1) if n % i == 0) + gen = ([i, n // i] for i in range(1, int(n**0.5) + 1) if n % i == 0) return sorted(set(sum(gen, []))) diff --git a/tests/custom_strategies/test_strategies.py b/tests/custom_strategies/test_strategies.py index 1b73a51c..a05f0c50 100644 --- a/tests/custom_strategies/test_strategies.py +++ b/tests/custom_strategies/test_strategies.py @@ -326,5 +326,5 @@ def test_can_infer_Shape(shape: Shape): @given(no_value()) def test_no_value(x): from mygrad.operation_base import _NoValue - assert x is _NoValue + assert x is _NoValue diff --git a/tests/linalg/test_einsum.py b/tests/linalg/test_einsum.py index 11b97c2f..04f5b909 100644 --- a/tests/linalg/test_einsum.py +++ b/tests/linalg/test_einsum.py @@ -104,7 +104,7 @@ def test_merge_mappings(): @given(optimize=bool_strat()) def test_einsum_static_fwd(optimize): - """ Check all einsum examples from numpy doc""" + """Check all einsum examples from numpy doc""" a = mg.arange(25).reshape(5, 5) b = mg.arange(5) c = mg.arange(6).reshape(2, 3) @@ -152,7 +152,7 @@ def test_einsum_static_fwd(optimize): @given(optimize=bool_strat()) def test_einsum_static_bkwd(optimize): - """ Check all einsum examples from numpy doc""" + """Check all einsum examples from numpy doc""" a = np.arange(25).reshape(5, 5) b = np.arange(5) c = np.arange(6).reshape(2, 3) diff --git a/tests/linalg/test_multi_matmul.py b/tests/linalg/test_multi_matmul.py index 5c93b994..737b1915 100644 --- a/tests/linalg/test_multi_matmul.py +++ b/tests/linalg/test_multi_matmul.py @@ -3,12 +3,12 @@ import hypothesis.extra.numpy as hnp import hypothesis.strategies as st -import mygrad.math.misc.funcs import numpy as np import pytest from hypothesis import given import mygrad as mg +import mygrad.math.misc.funcs from tests.wrappers.uber import backprop_test_factory, fwdprop_test_factory diff --git a/tests/linalg/test_norm.py b/tests/linalg/test_norm.py index 85cc1db0..06b66fd6 100644 --- a/tests/linalg/test_norm.py +++ b/tests/linalg/test_norm.py @@ -47,33 +47,32 @@ def manual_norm(x, ord=None, axis=None, keepdims=False): def manual_norm_2(x, ord=None, axis=None, keepdims=False): - return np.sqrt(np.sum(x ** 2, axis=axis, keepdims=keepdims)) + return np.sqrt(np.sum(x**2, axis=axis, keepdims=keepdims)) +@pytest.mark.filterwarnings("ignore:divide by zero") @given( st.integers(-2, 2).filter(lambda x: x != 0) | st.sampled_from([-np.inf, np.inf, "fro", "nuc"]) ) def test_matrix_norm_raises(ord): with pytest.raises(NotImplementedError): - t = mg.arange(4.0).reshape((2, 2)) + t = mg.arange(1, 5.0).reshape((2, 2)) + 1 mg.linalg.norm(t, ord=ord) with pytest.raises(NotImplementedError): - t = mg.arange(12.0).reshape((3, 2, 2)) + t = mg.arange(1, 13.0).reshape((3, 2, 2)) + 1 mg.linalg.norm(t, ord=ord, axis=(0, 1)) +@pytest.mark.filterwarnings("ignore:divide by zero") def test_ord_0_raises(): with pytest.raises(NotImplementedError): - t = mg.arange(4.0) + t = mg.arange(1, 4.0) mg.linalg.norm(t, ord=0) -def test_manual_norm_with_tuple_axis(): - pass - - +@pytest.mark.filterwarnings("ignore:divide by zero") @settings(max_examples=1000) @fwdprop_test_factory( mygrad_func=mg.linalg.norm, @@ -86,6 +85,7 @@ def test_norm_fwd(): pass +@pytest.mark.filterwarnings("ignore:divide by zero") @backprop_test_factory( mygrad_func=mg.linalg.norm, true_func=manual_norm_2, @@ -100,6 +100,7 @@ def test_norm_bkwd_ord_2(): pass +@pytest.mark.filterwarnings("ignore:divide by zero") @pytest.mark.parametrize("ord", [-1.0, 0.5, 1.0, 1.25, 1.5, 2.0, 2.5, -np.inf, np.inf]) @given( x=hnp.arrays( @@ -131,6 +132,7 @@ def test_norm_backward(x, data, ord): assert_allclose(t1.grad, t2.grad, atol=1e-7, rtol=1e-7) +@pytest.mark.filterwarnings("ignore:divide by zero") @pytest.mark.parametrize("ord", [-1.0, 0.5, 1.0, 1.25, 1.5, 2.0, 2.5, -np.inf, np.inf]) @given( x=hnp.arrays( @@ -164,6 +166,7 @@ def test_norm_backward_1d(x, data, ord): assert_allclose(t1.grad, t2.grad, atol=1e-7, rtol=1e-7) +@pytest.mark.filterwarnings("ignore:divide by zero") def test_nan_to_num_behavior(): x = mg.tensor([[1.0, 2.0, 3.0], [1.0, 0.0, 0.0]]) y = x.copy() diff --git a/tests/math/binary/test_binary_funcs.py b/tests/math/binary/test_binary_funcs.py index 84aa886b..cd7d94c1 100644 --- a/tests/math/binary/test_binary_funcs.py +++ b/tests/math/binary/test_binary_funcs.py @@ -7,7 +7,7 @@ import hypothesis.strategies as st import numpy as np import pytest -from hypothesis import given, assume +from hypothesis import assume, given from numpy.testing import assert_allclose from tests.custom_strategies import tensors @@ -20,17 +20,17 @@ def inplace_op(inplace_target, other, constant=False, *, op_name: str): op_name = "__" + op_name + "__" - # hack to make broadcastable shapes work for inplace op: - x = inplace_target.copy() + # hack to make broadcastable shapes work for inplace op: + _ = inplace_target.copy() check = False - + if np.broadcast(inplace_target, other).shape != inplace_target.shape: inplace_target, other = other, inplace_target check = True - + if check and np.broadcast(inplace_target, other).shape != inplace_target.shape: assume(False) - + # touch so that it doesn't look like the input # was mutated inplace_target = +inplace_target @@ -103,7 +103,7 @@ def iop_bkwd(): ) ) def test_x_pow_0_special_case(t): - y = t ** 0 + y = t**0 y.backward() assert_allclose(y.data, np.ones_like(t)) assert_allclose(t.grad, np.zeros_like(t)) @@ -118,7 +118,7 @@ def test_x_pow_0_special_case(t): ) ) def test_0_pow_y_special_case(t): - y = 0 ** t + y = 0**t y.backward() assert_allclose(y.data, np.zeros_like(t)) assert_allclose(t.grad, np.zeros_like(t)) diff --git a/tests/math/sequence/test_sequential_funcs.py b/tests/math/sequence/test_sequential_funcs.py index 0a9bbf08..d3be0aa2 100644 --- a/tests/math/sequence/test_sequential_funcs.py +++ b/tests/math/sequence/test_sequential_funcs.py @@ -21,7 +21,7 @@ def axis_arg(*arrs, min_dim=0): - """ Wrapper for passing valid-axis search strategy to test factory""" + """Wrapper for passing valid-axis search strategy to test factory""" if arrs[0].ndim: return valid_axes(arrs[0].ndim, min_dim=min_dim) else: @@ -38,7 +38,7 @@ def single_axis_arg(*arrs): def keepdims_arg(*arrs): - """ Wrapper for passing keep-dims strategy to test factory""" + """Wrapper for passing keep-dims strategy to test factory""" return st.booleans() @@ -49,6 +49,8 @@ def ddof_arg(*arrs): return st.integers(0, min_side - 1) if min_side else st.just(0) +@pytest.mark.filterwarnings("ignore:Degrees of freedom") +@pytest.mark.filterwarnings("ignore:divide by zero") @fwdprop_test_factory( mygrad_func=amax, true_func=np.amax, @@ -168,14 +170,14 @@ def test_mean_bkwd(): pass +@pytest.mark.filterwarnings("ignore:Degrees of freedom") +@pytest.mark.filterwarnings("ignore:invalid value encountered") @fwdprop_test_factory( mygrad_func=var, true_func=np.var, num_arrays=1, kwargs=dict(axis=axis_arg, keepdims=keepdims_arg, ddof=ddof_arg), ) -@pytest.mark.filterwarnings("ignore: Degrees of freedom") -@pytest.mark.filterwarnings("ignore: invalid value encountered in true_divide") def test_var_fwd(): pass @@ -261,14 +263,14 @@ def test_var_no_axis_bkwrd(x: mg.Tensor): assert np.all(x.grad == mg.zeros_like(x)) +@pytest.mark.filterwarnings("ignore:Degrees of freedom") +@pytest.mark.filterwarnings("ignore:invalid value encountered") @fwdprop_test_factory( mygrad_func=std, true_func=np.std, num_arrays=1, kwargs=dict(axis=axis_arg, keepdims=keepdims_arg, ddof=ddof_arg), ) -@pytest.mark.filterwarnings("ignore: Degrees of freedom") -@pytest.mark.filterwarnings("ignore: invalid value encountered in true_divide") def test_std_fwd(): pass diff --git a/tests/nnet/activations/test_softmax.py b/tests/nnet/activations/test_softmax.py index f57c4cb2..f1a99eda 100644 --- a/tests/nnet/activations/test_softmax.py +++ b/tests/nnet/activations/test_softmax.py @@ -6,8 +6,8 @@ from mygrad import Tensor from mygrad.nnet.activations import logsoftmax, softmax -from tests.utils.checkers import is_float_arr from tests.custom_strategies import valid_axes +from tests.utils.checkers import is_float_arr from tests.wrappers.uber import backprop_test_factory, fwdprop_test_factory log_largest = np.log(np.finfo(np.float64).max) diff --git a/tests/nnet/initializers/test_dirac.py b/tests/nnet/initializers/test_dirac.py index c8ce8df7..ae220bfe 100644 --- a/tests/nnet/initializers/test_dirac.py +++ b/tests/nnet/initializers/test_dirac.py @@ -1,12 +1,11 @@ -from hypothesis import given -import hypothesis.strategies as st import hypothesis.extra.numpy as hnp +import hypothesis.strategies as st import numpy as np import pytest +from hypothesis import given from mygrad import Tensor from mygrad.nnet.initializers import dirac -from mygrad.nnet.layers.conv import conv_nd @given(shape=hnp.array_shapes(max_dims=1)) diff --git a/tests/nnet/initializers/test_glorot_normal.py b/tests/nnet/initializers/test_glorot_normal.py index 1aee589e..6e31485a 100644 --- a/tests/nnet/initializers/test_glorot_normal.py +++ b/tests/nnet/initializers/test_glorot_normal.py @@ -33,7 +33,7 @@ def test_glorot_normal_input_validation(shape): 1, 5 / 3, np.sqrt(2), - np.sqrt(2 / (1.01 ** 2)), + np.sqrt(2 / (1.01**2)), ) # most activations, tanh, relu, leaky diff --git a/tests/nnet/initializers/test_glorot_uniform.py b/tests/nnet/initializers/test_glorot_uniform.py index be2c6368..98fc4aee 100644 --- a/tests/nnet/initializers/test_glorot_uniform.py +++ b/tests/nnet/initializers/test_glorot_uniform.py @@ -15,7 +15,7 @@ def test_glorot_normal_input_validation(shape): _array_shapes = ((10_000, 100), (1000, 100, 10), (10, 10, 10, 10, 10, 10)) -_valid_gains = (1, 5 / 3, np.sqrt(2), np.sqrt(2 / (1.01 ** 2))) +_valid_gains = (1, 5 / 3, np.sqrt(2), np.sqrt(2 / (1.01**2))) @given(shape=st.sampled_from(_array_shapes), gain=st.sampled_from(_valid_gains)) diff --git a/tests/nnet/initializers/test_he_normal.py b/tests/nnet/initializers/test_he_normal.py index 7df46e9c..6d0ec629 100644 --- a/tests/nnet/initializers/test_he_normal.py +++ b/tests/nnet/initializers/test_he_normal.py @@ -23,7 +23,7 @@ def test_glorot_normal_input_validation(shape): 1, 5 / 3, np.sqrt(2), - np.sqrt(2 / (1.01 ** 2)), + np.sqrt(2 / (1.01**2)), ) # most activations, tanh, relu, leaky diff --git a/tests/nnet/initializers/test_he_uniform.py b/tests/nnet/initializers/test_he_uniform.py index 92fc3d33..ddaf310f 100644 --- a/tests/nnet/initializers/test_he_uniform.py +++ b/tests/nnet/initializers/test_he_uniform.py @@ -15,7 +15,7 @@ def test_he_uniform_input_validation(shape): _array_shapes = ((10000, 100), (1000, 100, 10), (10, 10, 10, 10, 10, 10)) -_valid_gains = (1, 5 / 3, np.sqrt(2), np.sqrt(2 / (1.01 ** 2))) +_valid_gains = (1, 5 / 3, np.sqrt(2), np.sqrt(2 / (1.01**2))) @given(shape=st.sampled_from(_array_shapes), gain=st.sampled_from(_valid_gains)) diff --git a/tests/nnet/initializers/test_uniform.py b/tests/nnet/initializers/test_uniform.py index 0fe88e42..14a1b5b3 100644 --- a/tests/nnet/initializers/test_uniform.py +++ b/tests/nnet/initializers/test_uniform.py @@ -2,7 +2,7 @@ import hypothesis.strategies as st import numpy as np import pytest -from hypothesis import assume, given +from hypothesis import given from mygrad import Tensor from mygrad.nnet.initializers import uniform diff --git a/tests/nnet/layers/test_conv.py b/tests/nnet/layers/test_conv.py index 2b1d01b2..fa8eef10 100644 --- a/tests/nnet/layers/test_conv.py +++ b/tests/nnet/layers/test_conv.py @@ -378,7 +378,7 @@ def test_conv_ND_fwd(data, shape, num_filters, num_batch, num_channel): num_channel=st.integers(1, 3), ) def test_conv_ND_bkwd(data, shape, num_filters, num_batch, num_channel): - """ Test conv-backprop 1D-3D with various strides and dilations.""" + """Test conv-backprop 1D-3D with various strides and dilations.""" img_shape = (num_batch, num_channel) + shape padding = data.draw( diff --git a/tests/state_testing/test_simple_graph_state.py b/tests/state_testing/test_simple_graph_state.py index 74e690ea..1c96cb30 100644 --- a/tests/state_testing/test_simple_graph_state.py +++ b/tests/state_testing/test_simple_graph_state.py @@ -35,7 +35,7 @@ def __init__(self): # created via the unit test (through `create_node` or `fuse_nodes`) # `Node` is the naive implementation of `Tensor` that we are checking # against - self.node_list = [] # type: List[Tuple[Node, Tensor]] + self.node_list: List[Tuple[Node, Tensor]] = [] self.str_to_tensor_op = {"add": add, "multiply": multiply} self.str_to_node_op = {"add": _add, "multiply": _multiply} self.raised = False diff --git a/tests/tensor_base/test_astype.py b/tests/tensor_base/test_astype.py index 423de900..617409ea 100644 --- a/tests/tensor_base/test_astype.py +++ b/tests/tensor_base/test_astype.py @@ -14,7 +14,7 @@ @given( - tensor=tensors(dtype=real_types), + tensor=tensors(dtype=real_types, elements=st.integers(0, 1)), dest_type=real_types, data=st.data(), ) diff --git a/tests/tensor_base/test_backward.py b/tests/tensor_base/test_backward.py index 200e054b..cb4e6bd1 100644 --- a/tests/tensor_base/test_backward.py +++ b/tests/tensor_base/test_backward.py @@ -41,7 +41,7 @@ def test_simple_behavior(): @given( tensor=tensors( dtype=hnp.floating_dtypes(endianness="="), - fill=st.just(0), + elements=st.just(0), constant=False, shape=hnp.array_shapes(min_dims=0, min_side=0, max_dims=3), ), @@ -58,6 +58,7 @@ def test_tensor_backward_produces_grad_of_correct_dtype_and_shape( max_side=min(tensor.shape, default=0), max_dims=tensor.ndim, ), + elements=st.just(0), ) grad = data.draw( diff --git a/tests/tensor_base/test_chainrule.py b/tests/tensor_base/test_chainrule.py index e7afd020..26a935e4 100644 --- a/tests/tensor_base/test_chainrule.py +++ b/tests/tensor_base/test_chainrule.py @@ -116,7 +116,7 @@ def test_chainrule_scalar( _check_grad(x, 1 + 2 * z.data * f.data * y.data) _check_grad(y, 2 * z.data * f.data * x.data) - _check_grad(z, f.data ** 2 + z.data * 2 * f.data) + _check_grad(z, f.data**2 + z.data * 2 * f.data) @given(st.booleans()) @@ -187,8 +187,8 @@ def test_linear_graph( v4.backward(grad) # check fwd-pass produces reliable math - assert v2.data == v1_val ** 2 - assert v3.data == np.exp(v1_val ** 2) + assert v2.data == v1_val**2 + assert v3.data == np.exp(v1_val**2) assert v4.data == 2 * v3.data # check that constant propagates through graph reliably @@ -261,7 +261,7 @@ def test_fanout_graph( v5.backward(grad) # check fwd-pass produces reliable math - assert v2.data == v1_val ** 2 + assert v2.data == v1_val**2 assert v3.data == np.exp(v1_val) assert v4.data == 2 * v1_val assert v5.data == v2.data * v3.data * v4.data @@ -360,7 +360,7 @@ def test_interesting_graph( note(f"v5: {v5}") # check fwd-pass produces reliable math - assert v3.data == v1_val ** 2 + assert v3.data == v1_val**2 assert v4.data == (v2_val * v3.data) assert v5.data == (v4.data * v3.data) @@ -387,7 +387,7 @@ def test_interesting_graph( _check_grad(v3, v3_grad) # dL/d2 = dL/d4 * p4/p2 - v2_grad = None if (v5.constant or v4.constant) else grad * v3.data ** 2 + v2_grad = None if (v5.constant or v4.constant) else grad * v3.data**2 _check_grad(v2, v2_grad) # dL/d1 = dL/d3 * p3/p1 @@ -397,7 +397,7 @@ def test_interesting_graph( else ( 2 * grad * v1.data * v4.data if v4.constant - else grad * 4 * v1.data ** 3 * v2.data + else grad * 4 * v1.data**3 * v2.data ) ) _check_grad(v1, v1_grad) @@ -473,7 +473,7 @@ def test_dynamic_interesting_graph( note(f"dead_leaf: {dead_leaf}") # check fwd-pass produces reliable math - assert v3.data == v1_val ** 2 + assert v3.data == v1_val**2 assert v4.data == (v1_val * v2_val * v3.data) assert v5.data == (v4.data * v3.data * v1_val) assert dead_leaf.data == dangling_site.data * 3.0 @@ -502,7 +502,7 @@ def test_dynamic_interesting_graph( _check_grad(v3, v3_grad) v2_grad = ( - None if (v5.constant or v4.constant) else grad * v3.data ** 2 * v1.data ** 2 + None if (v5.constant or v4.constant) else grad * v3.data**2 * v1.data**2 ) _check_grad(v2, v2_grad) diff --git a/tests/tensor_base/test_dtype_init.py b/tests/tensor_base/test_dtype_init.py index 8721b8f9..da857e55 100644 --- a/tests/tensor_base/test_dtype_init.py +++ b/tests/tensor_base/test_dtype_init.py @@ -16,16 +16,19 @@ def arrays_or_tensors(*args, **kwargs): generic_data = st.sampled_from([0, 0.0, [0], [0.0]]) | arrays_or_tensors( dtype=hnp.floating_dtypes() | hnp.integer_dtypes(), shape=hnp.array_shapes(min_dims=0, min_side=0), + elements=st.just(0), ) integer_data = st.sampled_from([0, [0]]) | arrays_or_tensors( dtype=hnp.integer_dtypes(), shape=hnp.array_shapes(min_dims=0, min_side=0), + elements=st.just(0), ) float_data = st.sampled_from([0.0, [0.0]]) | arrays_or_tensors( dtype=hnp.floating_dtypes(), shape=hnp.array_shapes(min_dims=0, min_side=0), + elements=st.just(0), ) integer_dtypes = st.sampled_from([int, "int32"]) | hnp.integer_dtypes() diff --git a/tests/tensor_base/test_memory_locking.py b/tests/tensor_base/test_memory_locking.py index d2dd5ac0..7c28ce6b 100644 --- a/tests/tensor_base/test_memory_locking.py +++ b/tests/tensor_base/test_memory_locking.py @@ -136,6 +136,7 @@ def test_dereferencing_tensor_restores_data_writeability( ) +@pytest.mark.filterwarnings("ignore:leak") @pytest.mark.xfail( condition=not COVERAGE_MODE, reason="documented state leak for edge case" ) diff --git a/tests/tensor_base/test_no_null_grad_semantics.py b/tests/tensor_base/test_no_null_grad_semantics.py index 7816fe8d..b2abb335 100644 --- a/tests/tensor_base/test_no_null_grad_semantics.py +++ b/tests/tensor_base/test_no_null_grad_semantics.py @@ -1,8 +1,5 @@ -from typing import Callable - import hypothesis.strategies as st import numpy as np -import pytest from hypothesis import given, note from numpy.testing import assert_array_equal @@ -23,9 +20,9 @@ def test_backprop_clears_graph(x: Tensor): for num_fwd_pass in range(2): note(f"Forward-pass iteration: {num_fwd_pass}") y = 2 * x - f = y + x ** 2 + f = y + x**2 f[...] = f[...] - x ** 3 # no-op + x**3 # no-op f.backward() if not x.constant: assert_array_equal( diff --git a/tests/tensor_base/test_op_wrapper.py b/tests/tensor_base/test_op_wrapper.py index ce068af7..07acc448 100644 --- a/tests/tensor_base/test_op_wrapper.py +++ b/tests/tensor_base/test_op_wrapper.py @@ -24,7 +24,7 @@ def dummy(a, b, constant=False): @pytest.mark.parametrize("y_const", [True, False]) @pytest.mark.parametrize("op_const", [True, False]) def test_constant_arg(x_const: bool, y_const: bool, op_const: bool): - """ test that the `constant` arg works as intended in Tensor._op""" + """test that the `constant` arg works as intended in Tensor._op""" x = Tensor(1.0, constant=x_const) y = Tensor(1.0, constant=y_const) out = dummy(x, y, constant=op_const) diff --git a/tests/tensor_base/test_operator_override.py b/tests/tensor_base/test_operator_override.py index 76f99653..79ea1350 100644 --- a/tests/tensor_base/test_operator_override.py +++ b/tests/tensor_base/test_operator_override.py @@ -10,7 +10,6 @@ import mygrad as mg from mygrad import Tensor -from mygrad.math.misc.ops import MatMul from mygrad.math.arithmetic.ops import ( Add, Divide, @@ -20,6 +19,7 @@ Square, Subtract, ) +from mygrad.math.misc.ops import MatMul from mygrad.operation_base import Operation @@ -40,7 +40,7 @@ def divide(x, y): def power(x, y): - return x ** y + return x**y def matmul(x, y): diff --git a/tests/tensor_base/test_placeholder_copy.py b/tests/tensor_base/test_placeholder_copy.py index b7d0575d..5b022752 100644 --- a/tests/tensor_base/test_placeholder_copy.py +++ b/tests/tensor_base/test_placeholder_copy.py @@ -45,7 +45,7 @@ def test_placeholder_tensor(x: mg.Tensor, data: st.DataObject): assert x.grad is None if not y.constant: - assert_allclose(y.grad, 4 * x.data ** 3, atol=1e-7) + assert_allclose(y.grad, 4 * x.data**3, atol=1e-7) if not placeholder.constant: - assert_allclose(placeholder.grad, 6 * x.data ** 2) + assert_allclose(placeholder.grad, 6 * x.data**2) diff --git a/tests/tensor_base/test_pow_special_cases.py b/tests/tensor_base/test_pow_special_cases.py index 7cb6915d..72ef6328 100644 --- a/tests/tensor_base/test_pow_special_cases.py +++ b/tests/tensor_base/test_pow_special_cases.py @@ -1,6 +1,5 @@ from functools import partial -import hypothesis.extra.numpy as hnp import hypothesis.strategies as st import numpy as np import pytest @@ -9,7 +8,6 @@ import mygrad as mg from mygrad.math.arithmetic.ops import Positive, Square from tests.custom_strategies import tensors -from tests.utils.checkers import expected_constant from tests.utils.wrappers import adds_constant_arg from ..wrappers.uber import backprop_test_factory, fwdprop_test_factory @@ -17,7 +15,7 @@ @adds_constant_arg def custom_pow(x, p): - return x ** p + return x**p @adds_constant_arg @@ -33,7 +31,7 @@ def any_scalar(*args, p): @given(x=tensors(elements=st.floats(-10, 10)), p=st.sampled_from([2, 3])) def test_special_pow_propagate_constant(x, p): - y = x ** p + y = x**p assert y.constant is x.constant diff --git a/tests/tensor_base/test_tensor.py b/tests/tensor_base/test_tensor.py index 95f5875c..637d4b0e 100644 --- a/tests/tensor_base/test_tensor.py +++ b/tests/tensor_base/test_tensor.py @@ -1,5 +1,3 @@ -from typing import Optional - import hypothesis.extra.numpy as hnp import hypothesis.strategies as st import numpy as np @@ -48,7 +46,9 @@ def test_input_constant_checking(constant): @given( x=hnp.arrays( - shape=hnp.array_shapes(min_dims=0, min_side=0), dtype=hnp.floating_dtypes() + shape=hnp.array_shapes(min_dims=0, min_side=0), + dtype=hnp.floating_dtypes(), + elements=st.just(0), ), dtype=hnp.floating_dtypes(), copy=st.booleans(), diff --git a/tests/tensor_ops/test_setitem.py b/tests/tensor_ops/test_setitem.py index e4756432..153af227 100644 --- a/tests/tensor_ops/test_setitem.py +++ b/tests/tensor_ops/test_setitem.py @@ -1,4 +1,3 @@ -from functools import wraps from typing import Callable import hypothesis.extra.numpy as hnp diff --git a/tests/test_duplicating_graph.py b/tests/test_duplicating_graph.py index bbeb7f7b..15df37b0 100644 --- a/tests/test_duplicating_graph.py +++ b/tests/test_duplicating_graph.py @@ -130,7 +130,7 @@ class GraphDuplicationCompare(RuleBasedStateMachine): def __init__(self): super().__init__() self.base = mg.arange(6.0) - self.node_list = [id(self.base)] # type: List[int] + self.node_list: List[int] = [id(self.base)] self.parent_child_pairs = set() nodes = Bundle("nodes") diff --git a/tests/test_in_place_semantics.py b/tests/test_in_place_semantics.py index eacc91e0..9a729f93 100644 --- a/tests/test_in_place_semantics.py +++ b/tests/test_in_place_semantics.py @@ -252,7 +252,7 @@ def test_mutation_doesnt_corrupt_upstream_op(inplace_on_view: bool, x: Tensor): z.backward() # dz/dx = 6 * x ** 2 - assert_allclose(z, x.data ** 4, atol=1e-7) + assert_allclose(z, x.data**4, atol=1e-7) assert_array_equal(view, y) assert_allclose(z.grad, np.ones_like(y), atol=1e-7) assert_allclose(x.grad, 4 * np.asarray(x) ** 3, atol=1e-7) diff --git a/tests/test_operation_base.py b/tests/test_operation_base.py index 56a2b5ab..fbc6f358 100644 --- a/tests/test_operation_base.py +++ b/tests/test_operation_base.py @@ -8,7 +8,7 @@ import mygrad as mg from mygrad import Tensor from mygrad.errors import InvalidGradient -from mygrad.operation_base import BinaryUfunc, Operation, UnaryUfunc +from mygrad.operation_base import Operation from tests.utils.errors import does_not_raise diff --git a/tests/test_tensor_creation.py b/tests/test_tensor_creation.py index 4971f260..7f70e228 100644 --- a/tests/test_tensor_creation.py +++ b/tests/test_tensor_creation.py @@ -6,7 +6,7 @@ import hypothesis.strategies as st import numpy as np import pytest -from hypothesis import assume, given, infer, settings +from hypothesis import assume, given, infer, note, settings from numpy.testing import assert_array_equal import mygrad as mg @@ -41,9 +41,11 @@ def check_tensor_array(tensor, array, data_compare=True): assert tensor.dtype is array.dtype -def clamp(val, min_=0.1): +def clamp(val, min_=0.1, max_=None): if val is not _NoValue: val = max(val, min_) + if max_ is not None: + val = min(val, max_) return val @@ -85,6 +87,11 @@ def test_arange_like_against_numpy_equivalent( stop = clamp(stop) step = clamp(step) + if numpy_func is np.logspace: + start = clamp(start, max_=3) + stop = clamp(stop, max_=3) + step = clamp(step) + if as_kwargs: inputs = SmartSignature( start=start, stop=stop, step=step, dtype=dtype, axis=axis @@ -259,7 +266,11 @@ def test_astensor_with_incompat_constant_still_passes_array_ref( @given( - t=tensors(dtype=hnp.floating_dtypes(), include_grad=st.booleans()), + t=tensors( + dtype=hnp.floating_dtypes(), + include_grad=st.booleans(), + elements=st.floats(-10, 10, width=16), + ), in_graph=st.booleans(), dtype=st.none() | hnp.floating_dtypes(), constant=st.none() | st.booleans(), @@ -336,6 +347,7 @@ def test_as_tensor( general_arrays = hnp.arrays( shape=hnp.array_shapes(min_side=0, min_dims=0), dtype=hnp.floating_dtypes() | hnp.integer_dtypes(), + elements=st.integers(-2, 2), ) @@ -356,6 +368,9 @@ class NotSet: ndmin=not_set | st.integers(-6, 6), ) def test_tensor_mirrors_array(arr_like, dtype, copy, constant, ndmin): + if isinstance(arr_like, np.ndarray): + note(f"arr_like.dtype: {arr_like.dtype}") + kwargs = {} for name, var_ in [("dtype", dtype), ("copy", copy), ("ndmin", ndmin)]: if var_ is not NotSet: @@ -365,6 +380,7 @@ def test_tensor_mirrors_array(arr_like, dtype, copy, constant, ndmin): arr = np.array(arr_like, **kwargs) except (ValueError, OverflowError): assume(False) + return tensor_like = ( Tensor(arr_like.copy(), constant=constant) @@ -377,11 +393,15 @@ def test_tensor_mirrors_array(arr_like, dtype, copy, constant, ndmin): assert tens.dtype == arr.dtype assert tens.shape == arr.shape assert np.shares_memory(tens, tensor_like) is np.shares_memory(arr, arr_like) - assert (tens is tensor_like) is (arr is arr_like) - assert (tens.base is tensor_like) is (arr.base is arr_like) - if tens.base is None: - # sometimes numpy makes internal views; mygrad should never do this - assert arr.base is not arr_like + + if arr.dtype.byteorder != ">": + # condition due to https://github.com/numpy/numpy/issues/22897 + + assert (tens is tensor_like) is (arr is arr_like) + assert (tens.base is tensor_like) is (arr.base is arr_like) + if tens.base is None: + # sometimes numpy makes internal views; mygrad should never do this + assert arr.base is not arr_like @given( diff --git a/tests/test_utils.py b/tests/test_utils.py index 09b0d2cd..2fda4df2 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -65,7 +65,7 @@ def test_reduce_broadcast_shape_consistency(shapes: hnp.BroadcastableShapes): ) ) def test_bad_gradient_dimensionality(shapes: Tuple[Tuple[int, ...], Tuple[int, ...]]): - """ test that grad.dim < len(var_shape) raises ValueError""" + """test that grad.dim < len(var_shape) raises ValueError""" var_shape = shapes[0] grad = np.empty(shapes[1]) with raises(ValueError): @@ -78,7 +78,7 @@ def test_bad_gradient_dimensionality(shapes: Tuple[Tuple[int, ...], Tuple[int, . ) ) def test_broadcast_scalar(grad): - """ test when grad was broadcasted from a scalar""" + """test when grad was broadcasted from a scalar""" assert_allclose(reduce_broadcast(grad, tuple()), grad.sum()) @@ -88,7 +88,7 @@ def test_broadcast_scalar(grad): ) ) def test_reduce_broadcast_same_shape(grad): - """ test when no broadcasting occurred""" + """test when no broadcasting occurred""" var_shape = grad.shape reduced_grad = reduce_broadcast(grad=grad, var_shape=var_shape) assert_allclose(actual=reduced_grad, desired=grad) @@ -96,7 +96,7 @@ def test_reduce_broadcast_same_shape(grad): @given(var_shape=hnp.array_shapes(min_side=2), data=st.data()) def test_reduce_broadcast_nokeepdim(var_shape, data): - """ example broadcasting: (2, 3) -> (5, 2, 3)""" + """example broadcasting: (2, 3) -> (5, 2, 3)""" grad_shape = data.draw( broadcastable_shapes( shape=var_shape, @@ -117,7 +117,7 @@ def test_reduce_broadcast_nokeepdim(var_shape, data): @given(var_shape=hnp.array_shapes(), data=st.data()) def test_reduce_broadcast_keepdim(var_shape, data): - """ example broadcasting: (2, 1, 4) -> (2, 5, 4)""" + """example broadcasting: (2, 1, 4) -> (2, 5, 4)""" grad = data.draw( hnp.arrays( dtype=float, diff --git a/tests/test_view_semantics.py b/tests/test_view_semantics.py index d5c87bb3..18d5ac80 100644 --- a/tests/test_view_semantics.py +++ b/tests/test_view_semantics.py @@ -20,7 +20,7 @@ def test_simple_view_grad_reflects_base_grad(view_pre_or_post_backward: str): view = base[:2] assert view.base is base - (base ** 2).backward() + (base**2).backward() if view_pre_or_post_backward == "post": view = base[:2] @@ -42,7 +42,7 @@ def test_simple_view_grad_reflects_nulled_base_grad(view_pre_or_post_backward: s if view_pre_or_post_backward == "pre": view = base[:2] - (base ** 2).backward() + (base**2).backward() if view_pre_or_post_backward == "post": view = base[:2] @@ -78,7 +78,7 @@ def test_nulling_base_grad_reflects_in_view(view_pre_or_post_backward): if view_pre_or_post_backward == "pre": view = base[...][:2] - (base ** 2).backward() + (base**2).backward() if view_pre_or_post_backward == "post": view = base[...][:2] @@ -96,8 +96,8 @@ def test_nulling_base_grad_reflects_in_view(view_pre_or_post_backward): def test_simple_view_becomes_disconnected_from_base_via_clear_graph2(): base = mg.Tensor([1.0, 2.0, 3.0]) view = base[:2] - (view ** 2).backward() # disconnects `view` from `base` - (base ** 3).backward() + (view**2).backward() # disconnects `view` from `base` + (base**3).backward() assert view.base is base assert np.any(view.grad != base.grad[:2]) diff --git a/tests/ufuncs/test_dtype.py b/tests/ufuncs/test_dtype.py index 052bdde2..2f261293 100644 --- a/tests/ufuncs/test_dtype.py +++ b/tests/ufuncs/test_dtype.py @@ -29,15 +29,12 @@ def test_dtype_casts_correctly(ufunc, dest_dtype): check_consistent_grad_dtype(out, x) -simple_arr_likes = ( - tensors( - dtype=st.sampled_from([np.float64, np.float32, int]), - shape=st.sampled_from([(1,), (1, 1)]), - elements=st.just(1), - constant=st.booleans(), - ) - | st.just([1]) -) +simple_arr_likes = tensors( + dtype=st.sampled_from([np.float64, np.float32, int]), + shape=st.sampled_from([(1,), (1, 1)]), + elements=st.just(1), + constant=st.booleans(), +) | st.just([1]) @pytest.mark.parametrize("ufunc", ufuncs) diff --git a/tests/utils/checkers.py b/tests/utils/checkers.py index bd7a3cf6..edacb45f 100644 --- a/tests/utils/checkers.py +++ b/tests/utils/checkers.py @@ -1,13 +1,13 @@ from typing import Optional, Union +import numpy as np + import mygrad import mygrad as mg -import numpy as np from mygrad import Tensor -from mygrad.operation_base import _NoValueType, _NoValue +from mygrad.operation_base import _NoValue, _NoValueType from mygrad.tensor_base import CONSTANT_ONLY_DTYPES from mygrad.typing import ArrayLike, DTypeLike, DTypeLikeReals - from tests.utils.errors import InternalTestError @@ -75,4 +75,4 @@ def expected_constant( def is_float_arr(arr: Union[np.ndarray, mygrad.Tensor]) -> bool: - return issubclass(arr.dtype.type, np.floating) \ No newline at end of file + return issubclass(arr.dtype.type, np.floating) diff --git a/tests/utils/errors.py b/tests/utils/errors.py index 0843e0cf..07dda00f 100644 --- a/tests/utils/errors.py +++ b/tests/utils/errors.py @@ -18,4 +18,4 @@ def does_not_raise(): >>> with (pytest.raises(AttributeError) if not isinstance(x, str) else does_not_raise()): ... x.lower() """ - yield \ No newline at end of file + yield diff --git a/tests/utils/numerical_gradient.py b/tests/utils/numerical_gradient.py index b21b1e11..20080143 100644 --- a/tests/utils/numerical_gradient.py +++ b/tests/utils/numerical_gradient.py @@ -106,7 +106,9 @@ def gen_bkwd_diff(i): return grads -def numerical_gradient(f, *args, back_grad, vary_ind=None, h=1e-20, kwargs=None) -> Tuple[Optional[np.ndarray], ...]: +def numerical_gradient( + f, *args, back_grad, vary_ind=None, h=1e-20, kwargs=None +) -> Tuple[Optional[np.ndarray], ...]: """Computes numerical partial derivatives of f(x0, x1, ...) in each of its variables, using the central difference method. This is a "fast" method - it varies entire arrays at once. Thus @@ -237,7 +239,8 @@ def numerical_gradient_full( kwargs = {} args = tuple(i.astype(np.complex128) for i in args) - grads = [None] * len(args) # type: List[Optional[np.ndarray]] + grads: List[Optional[np.ndarray]] = [None] * len(args) + if isinstance(vary_ind, int): vary_ind = [vary_ind] diff --git a/tests/utils/stateful.py b/tests/utils/stateful.py index 4b1cf5b0..93d4cec9 100644 --- a/tests/utils/stateful.py +++ b/tests/utils/stateful.py @@ -4,4 +4,4 @@ def clear_all_mem_locking_state(): mem._views_waiting_for_unlock.clear() mem._array_tracker.clear() - mem._array_counter.clear() \ No newline at end of file + mem._array_counter.clear() diff --git a/tests/utils/test_dtype_and_constant_checking.py b/tests/utils/test_dtype_and_constant_checking.py index fdf3afe7..a11b2ba4 100644 --- a/tests/utils/test_dtype_and_constant_checking.py +++ b/tests/utils/test_dtype_and_constant_checking.py @@ -14,8 +14,8 @@ import mygrad as mg from mygrad.typing import DTypeLikeReals from tests.custom_strategies import real_dtypes -from tests.utils.errors import InternalTestError from tests.utils.checkers import check_dtype_consistency, expected_constant +from tests.utils.errors import InternalTestError @given(dest_dtype=real_dtypes, as_tensor=st.booleans()) diff --git a/tests/utils/test_utils.py b/tests/utils/test_utils.py index efd8f20a..ec9f3025 100644 --- a/tests/utils/test_utils.py +++ b/tests/utils/test_utils.py @@ -22,15 +22,15 @@ def test_is_float_arr(): def unary_func(x): - return x ** 2 + return x**2 def binary_func(x, y): - return x * y ** 2 + return x * y**2 def ternary_func(x, y, z): - return z * x * y ** 2 + return z * x * y**2 @given( @@ -65,13 +65,13 @@ def test_finite_difference_no_broadcast(data, x): assert_allclose(dx, grad * 2 * x, atol=atol, rtol=rtol) dx, dy = numerical_gradient(binary_func, x, y, back_grad=grad) - assert_allclose(dx, grad * y ** 2, atol=atol, rtol=rtol) + assert_allclose(dx, grad * y**2, atol=atol, rtol=rtol) assert_allclose(dy, grad * 2 * x * y, atol=atol, rtol=rtol) dx, dy, dz = numerical_gradient(ternary_func, x, y, z, back_grad=grad) - assert_allclose(dx, grad * z * y ** 2, atol=atol, rtol=rtol) + assert_allclose(dx, grad * z * y**2, atol=atol, rtol=rtol) assert_allclose(dy, grad * z * 2 * x * y, atol=atol, rtol=rtol) - assert_allclose(dz, grad * x * y ** 2, atol=atol, rtol=rtol) + assert_allclose(dz, grad * x * y**2, atol=atol, rtol=rtol) @given( @@ -106,13 +106,13 @@ def test_numerical_gradient_no_broadcast(data, x): assert_allclose(dx, grad * 2 * x, atol=atol, rtol=rtol) dx, dy = numerical_gradient(binary_func, x, y, back_grad=grad) - assert_allclose(dx, grad * y ** 2, atol=atol, rtol=rtol) + assert_allclose(dx, grad * y**2, atol=atol, rtol=rtol) assert_allclose(dy, grad * 2 * x * y, atol=atol, rtol=rtol) dx, dy, dz = numerical_gradient(ternary_func, x, y, z, back_grad=grad) - assert_allclose(dx, grad * z * y ** 2, atol=atol, rtol=rtol) + assert_allclose(dx, grad * z * y**2, atol=atol, rtol=rtol) assert_allclose(dy, grad * z * 2 * x * y, atol=atol, rtol=rtol) - assert_allclose(dz, grad * x * y ** 2, atol=atol, rtol=rtol) + assert_allclose(dz, grad * x * y**2, atol=atol, rtol=rtol) @given( @@ -125,7 +125,7 @@ def test_numerical_gradient_x_broadcast(x, y, grad): # broadcast x dx, dy = numerical_gradient(binary_func, x, y, back_grad=grad) - assert_allclose(dx, (grad * y ** 2).sum(axis=0), atol=atol, rtol=rtol) + assert_allclose(dx, (grad * y**2).sum(axis=0), atol=atol, rtol=rtol) assert_allclose(dy, grad * 2 * x * y, atol=atol, rtol=rtol) @@ -139,7 +139,7 @@ def test_numerical_gradient_y_broadcast(x, y, grad): # broadcast x dx, dy = numerical_gradient(binary_func, x, y, back_grad=grad) - assert_allclose(dx, grad * y ** 2, atol=atol, rtol=rtol) + assert_allclose(dx, grad * y**2, atol=atol, rtol=rtol) assert_allclose(dy, (grad * 2 * x * y).sum(axis=0), atol=atol, rtol=rtol) @@ -153,7 +153,7 @@ def test_numerical_gradient_xy_broadcast(x, y, grad): # broadcast x dx, dy = numerical_gradient(binary_func, x, y, back_grad=grad) - x_grad = (grad * y ** 2).sum(axis=1, keepdims=True) + x_grad = (grad * y**2).sum(axis=1, keepdims=True) y_grad = (grad * 2 * x * y).sum(axis=0, keepdims=True) assert_allclose(dx, x_grad, atol=atol, rtol=rtol) assert_allclose(dy, y_grad, atol=atol, rtol=rtol) @@ -168,4 +168,3 @@ def test_numerical_gradient_vary_each(x, grad): (dx,) = numerical_gradient_full(lambda y: y[::-1], x, back_grad=np.array(grad)) x_grad = grad[::-1] assert_allclose(actual=dx, desired=x_grad, atol=atol, rtol=rtol) - diff --git a/tests/utils/wrappers.py b/tests/utils/wrappers.py index eca6c7e5..48fa6124 100644 --- a/tests/utils/wrappers.py +++ b/tests/utils/wrappers.py @@ -2,9 +2,8 @@ from typing import Callable from mygrad import Tensor - -from tests.utils.stateful import clear_all_mem_locking_state from tests.utils.checkers import expected_constant +from tests.utils.stateful import clear_all_mem_locking_state def clears_mem_state(fn: Callable) -> Callable: @@ -31,4 +30,4 @@ def wrapper(*args, constant=None, **kwargs): ) return out - return wrapper \ No newline at end of file + return wrapper diff --git a/tests/wrappers/uber.py b/tests/wrappers/uber.py index 00434383..f998ebbb 100644 --- a/tests/wrappers/uber.py +++ b/tests/wrappers/uber.py @@ -210,7 +210,7 @@ def __init__( assert num_arrays > 0 - self.op = mygrad_func # type: Operation + self.op: Operation = mygrad_func self.true_func = true_func self.index_to_bnds = index_to_bnds @@ -690,7 +690,7 @@ def wrapper(shapes: hnp.BroadcastableShapes, data: st.DataObject): ) # list of drawn arrays to feed to functions - arrs = data.draw( + arrs: List[Tensor] = data.draw( st.tuples( *( self.arrays(i).map(Tensor) @@ -699,7 +699,7 @@ def wrapper(shapes: hnp.BroadcastableShapes, data: st.DataObject): ) ).map(list), label="arrays", - ) # type: List[Tensor] + ) if callable(self.kwargs): kwargs = data.draw(self.kwargs(*arrs), label="kwargs")