{ "info": { "author": "Wessel Bruinsma", "author_email": "wessel.p.bruinsma@gmail.com", "bugtrack_url": null, "classifiers": [], "description": "# [Varz](http://github.com/wesselb/varz)\n\n[![CI](https://github.com/wesselb/varz/workflows/CI/badge.svg?branch=master)](https://github.com/wesselb/varz/actions?query=workflow%3ACI)\n[![Coverage Status](https://coveralls.io/repos/github/wesselb/varz/badge.svg?branch=master&service=github)](https://coveralls.io/github/wesselb/varz?branch=master)\n[![Latest Docs](https://img.shields.io/badge/docs-latest-blue.svg)](https://wesselb.github.io/varz)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n\nPainless optimisation of constrained variables in AutoGrad, TensorFlow, PyTorch, and JAX\n\n* [Requirements and Installation](#requirements-and-installation)\n* [Manual](#manual)\n - [Basics](#basics)\n - [Naming](#naming)\n - [Constrained Variables](#constrained-variables)\n - [Automatic Naming of Variables](#automatic-naming-of-variables)\n - [Sequential Specification](#sequential-specification)\n - [Parametrised Specification](#parametrised-specification)\n - [Namespaces](#namespaces)\n - [Structlike Specification](#structlike-specification)\n - [Optimisers](#optimisers)\n - [PyTorch Specifics](#pytorch-specifics)\n - [Getting and Setting Latent Representations of Variables as a Vector](#getting-and-setting-latent-representations-of-variables-as-a-vector)\n - [Getting Variables from a Source](#get-variables-from-a-source)\n * [Examples](#examples)\n - [Minimise a Function Using L-BFGS-B in AutoGrad](#minimise-a-function-using-l-bfgs-b-in-autograd)\n - [Minimise a Function Using L-BFGS-B in TensorFlow](#minimise-a-function-using-l-bfgs-b-in-tensorflow)\n - [Minimise a Function Using L-BFGS-B in PyTorch](#minimise-a-function-using-l-bfgs-b-in-pytorch)\n - [Minimise a Function Using L-BFGS-B in JAX](#minimise-a-function-using-l-bfgs-b-in-jax)\n - [Tracking the Learning Curve in JAX](#tracking-the-learning-curve-in-jax)\n \n## Requirements and Installation\n\nSee [the instructions here](https://gist.github.com/wesselb/4b44bf87f3789425f96e26c4308d0adc).\nThen simply\n\n```bash\npip install varz\n```\n\n## Manual\n\n### Basics\n```python\nfrom varz import Vars\n```\n\nTo begin with, create a *variable container* of the right data type.\nFor use with AutoGrad, use a `np.*` data type;\nfor use with PyTorch, use a `torch.*` data type;\nfor use with TensorFlow, use a `tf.*` data type;\nand for use with JAX, use a `jnp.*` data type.\nIn this example we'll use AutoGrad.\n\n```python\n>>> vs = Vars(np.float64)\n```\n\nNow a variable can be created by requesting it, giving it an initial value and\na name.\n \n```python\n>>> vs.unbounded(np.random.randn(2, 2), name=\"x\")\narray([[ 1.04404354, -1.98478763],\n [ 1.14176728, -3.2915562 ]])\n```\n\nIf the same variable is created again, because a variable with the name `x` \nalready exists, the existing variable will be returned, even if you again pass it an\ninitial value.\n\n```python\n>>> vs.unbounded(np.random.randn(2, 2), name=\"x\")\narray([[ 1.04404354, -1.98478763],\n [ 1.14176728, -3.2915562 ]])\n\n>>> vs.unbounded(name=\"x\")\narray([[ 1.04404354, -1.98478763],\n [ 1.14176728, -3.2915562 ]])\n```\n\nAlternatively, indexing syntax may be used to get the existing variable `x`.\nThis asserts that a variable with the name `x` already exists and will throw a\n`KeyError` otherwise.\n\n```python\n>>> vs[\"x\"]\narray([[ 1.04404354, -1.98478763],\n [ 1.14176728, -3.2915562 ]])\n \n>>> vs[\"y\"]\nKeyError: 'y'\n```\n\nThe value of `x` can be changed by assigning it a different value.\n\n```python\n>>> vs.assign(\"x\", np.random.randn(2, 2))\narray([[ 1.43477728, 0.51006941],\n [-0.74686452, -1.05285767]])\n```\n\nBy default, assignment is non-differentiable and _overwrites_ data.\nThe variable can be deleted by passing its name to `vs.delete`:\n\n```python\n>>> vs.delete(\"x\")\n\n>>> vs[\"x\"]\nKeyError: 'x'\n```\n\nWhen a variable is first created, you can set the keyword argument `visible`\nto `False` if you want to make the variable invisible to the\nvariable-aggregating operations [`vs.get_latent_vars`](#constrained-variables)\nand\n[`vs.get_latent_vector`](#getting-and-setting-latent-representations-of-variables-as-a-vector).\nThese variable-aggregating operations are used in optimisers to get the intended\ncollection of variable to optimise.\nTherefore, setting `visible` to `False` will prevent a variable from being\noptimised.\n\nFinally, a variable container can be copied with `vs.copy()`.\nCopies are lightweight and _share their variables with the originals_.\nAs a consequence, however, assignment in a copy will also mutate the original.\n[Differentiable assignment, however, will not.](#differentiable-assignment)\n\n\n### Naming\n\nVariables may be organised by naming them hierarchically using `.`s. \nFor example, you could name like `group1.bar`, `group1.foo`, and `group2.bar`.\nThis is helpful for extracting collections of variables, where wildcards may \nbe used to match names.\nFor example, `*.bar` would match `group1.bar` and `group2.bar`, and \n`group1.*` would match `group1.bar` and `group1.foo`.\nSee also [here](#getting-and-setting-latent-representations-of-variables-as-a-vector).\n\nThe names of all variables can be obtained with `Vars.names`, and variables can \nbe printed with `Vars.print`.\n\nExample:\n\n```python\n>>> vs = Vars(np.float64)\n\n>>> vs.unbounded(1, name=\"x1\")\narray(1.)\n\n>>> vs.unbounded(2, name=\"x2\")\narray(2.)\n\n>>> vs.unbounded(3, name=\"y\")\narray(3.)\n\n>>> vs.names\n['x1', 'x2', 'y']\n\n>>> vs.print()\nx1: 1.0\nx2: 2.0\ny: 3.0\n```\n\n### Constrained Variables\n\n* **Unbounded variables:**\n A variable that is unbounded can be created using\n `Vars.unbounded` or `Vars.ubnd`.\n\n ```python\n >>> vs.ubnd(name=\"normal_variable\")\n 0.016925610008314832\n ```\n\n* **Positive variables:**\n A variable that is constrained to be *positive* can be created using\n `Vars.positive` or `Vars.pos`.\n\n ```python\n >>> vs.pos(name=\"positive_variable\")\n 0.016925610008314832\n ```\n\n* **Bounded variables:**\n A variable that is constrained to be *bounded* can be created using\n `Vars.bounded` or `Vars.bnd`.\n\n ```python\n >>> vs.bnd(name=\"bounded_variable\", lower=1, upper=2)\n 1.646772663807718\n ```\n \n* **Lower-triangular matrix:**\n A matrix variable that is constrained to be *lower triangular* can be\n created using `Vars.lower_triangular` or `Vars.tril`. Either an\n initialisation or a shape of square matrix must be given.\n \n ```python\n >>> vs.tril(shape=(2, 2), name=\"lower_triangular\")\n array([[ 2.64204459, 0. ],\n [-0.14055559, -1.91298679]])\n ```\n \n* **Positive-definite matrix:**\n A matrix variable that is contrained to be *positive definite* can be\n created using `Vars.positive_definite` or `Vars.pd`. Either an\n initialisation or a shape of square matrix must be given.\n \n ```python\n >>> vs.pd(shape=(2, 2), name=\"positive_definite\")\n array([[ 1.64097496, -0.52302151],\n [-0.52302151, 0.32628302]])\n ```\n \n* **Orthogonal matrix:**\n A matrix variable that is constrained to be *orthogonal* can be created using\n `Vars.orthogonal` or `Vars.orth`. Either an initialisation or a\n shape of square matrix must be given.\n \n ```python\n >>> vs.orth(shape=(2, 2), name=\"orthogonal\")\n array([[ 0.31290403, -0.94978475],\n [ 0.94978475, 0.31290403]])\n ```\n\nThese constrained variables are created by transforming some *latent \nunconstrained representation* to the desired constrained space.\nThe latent variables can be obtained using `Vars.get_latent_vars`.\n\n```python\n>>> vs.get_latent_vars(\"positive_variable\", \"bounded_variable\")\n[array(-4.07892742), array(-0.604883)]\n```\n\nTo illustrate the use of wildcards, the following is equivalent:\n\n```python\n>>> vs.get_latent_vars(\"*_variable\")\n[array(-4.07892742), array(-0.604883)]\n```\n\nVariables can be excluded by prepending a dash:\n\n```python\n>>> vs.get_latent_vars(\"*_variable\", \"-bounded_*\")\n[array(-4.07892742)]\n```\n\n### Automatic Naming of Variables\n\nTo parametrise functions, a common pattern is the following:\n\n```python\ndef objective(vs):\n x = vs.unbounded(5, name=\"x\")\n y = vs.unbounded(10, name=\"y\")\n \n return (x * y - 5) ** 2 + x ** 2\n```\n\nThe names for `x` and `y` are necessary, because otherwise new variables will\n be created and initialised every time `objective` is run.\nVarz offers two ways to not having to specify a name for every variable: \nsequential and parametrised specification.\n\n#### Sequential Specification\n\nSequential specification can be used if, upon execution of `objective`, \nvariables are always obtained in the *same order*.\nThis means that variables can be identified with their position in this order\nand hence be named accordingly.\nTo use sequential specification, decorate the function with `sequential`.\n\nExample:\n\n```python\nfrom varz import sequential\n\n@sequential\ndef objective(vs):\n x = vs.unbounded(5) # Initialise to 5.\n y = vs.unbounded() # Initialise randomly.\n \n return (x * y - 5) ** 2 + x ** 2\n```\n\n```python\n>>> vs = Vars(np.float64)\n\n>>> objective(vs)\n68.65047879833773\n\n>>> objective(vs) # Running the objective again reuses the same variables.\n68.65047879833773\n\n>>> vs.names\n['var0', 'var1']\n\n>>> vs.print()\nvar0: 5.0 # This is `x`.\nvar1: -0.3214 # This is `y`.\n```\n\n#### Parametrised Specification\n\nSequential specification still suffers from boilerplate code like\n`x = vs.unbounded(5)` and `y = vs.unbounded()`.\nThis is the problem that parametrised specification addresses, which allows \nyou to specify variables as *arguments to your function*.\nImport `from varz.spec import parametrised`.\nTo indicate that an argument of the function is a variable, as opposed to a \nregular argument, the argument's type hint must be set accordingly, as follows:\n\n* **Unbounded variables:**\n ```python\n @parametrised\n def f(vs, x: Unbounded):\n ...\n ```\n\n* **Positive variables:**\n ```python\n @parametrised\n def f(vs, x: Positive):\n ...\n ```\n\n* **Bounded variables:**\n The following two specifications are possible. The former uses the\n default bounds and the latter uses specified bounds.\n \n ```python\n @parametrised\n def f(vs, x: Bounded):\n ...\n ```\n \n ```python\n @parametrised\n def f(vs, x: Bounded(lower=1, upper=10)):\n ...\n ```\n \n* **Lower-triangular variables:**\n ```python\n @parametrised\n def f(vs, x: LowerTriangular(shape=(2, 2))):\n ...\n ```\n\n* **Positive-definite variables:**\n ```python\n @parametrised\n def f(vs, x: PositiveDefinite(shape=(2, 2))):\n ...\n ```\n \n* **Orthogonal variables:**\n ```python\n @parametrised\n def f(vs, x: Orthogonal(shape=(2, 2))):\n ...\n ```\n \nAs can be seen from the above, the variable container must also be an argument \nof the function, because that is where the variables will be obtained from.\nA variable can be given an initial value in the way you would expect:\n```python\n@parametrised\ndef f(vs, x: Unbounded = 5):\n ...\n```\n\nVariable arguments and regular arguments can be mixed.\nIf `f` is called, variable arguments must not be specified, because they \nwill be obtained automatically.\nRegular arguments, however, must be specified.\n\nTo use parametrised specification, decorate the function with `parametrised`.\n\nExample:\n\n```python\nfrom varz import parametrised, Unbounded, Bounded\n\n@parametrised\ndef objective(vs, x: Unbounded, y: Bounded(lower=1, upper=3) = 2, option=None):\n print(\"Option:\", option)\n return (x * y - 5) ** 2 + x ** 2\n```\n\n```python\n>>> vs = Vars(np.float64)\n\n>>> objective(vs)\nOption: None\n9.757481795615316\n\n>>> objective(vs, \"other\")\nOption: other\n9.757481795615316\n\n>>> objective(vs, option=\"other\")\nOption: other\n9.757481795615316\n\n>>> objective(vs, x=5) # This is not valid, because `x` will be obtained automatically from `vs`.\nValueError: 1 keyword argument(s) not parsed: x.\n\n>>> vs.print()\nx: 1.025\ny: 2.0\n```\n\n#### Namespaces\n\nNamespaces can be used to group all variables in a function together.\n\nExample:\n\n```python\nfrom varz import namespace\n\n@namespace(\"test\")\ndef objective(vs):\n x = vs.unbounded(5, name=\"x\")\n y = vs.unbounded(name=\"y\")\n \n return x + y\n```\n\n```python\n>>> vs = Vars(np.float64)\n\n>>> objective(vs)\n6.12448906632577\n\n>>> vs.names\n['test.x', 'test.y']\n\n>>> vs.print()\ntest.x: 5.0\ntest.y: 1.124\n```\n\nYou can combine namespace with other specification methods:\n\n```python\nfrom varz import namespace\n\n@namespace(\"test\")\n@sequential\ndef objective(vs):\n x = vs.unbounded(5)\n y = vs.unbounded()\n \n return x + y\n```\n\n```python\n>>> vs = Vars(np.float64)\n\n>>> objective(vs)\n4.812730329303665\n\n>>> vs.names\n['test.var0', 'test.var1']\n\n>>> vs.print()\ntest.var0: 5.0\ntest.var1: -0.1873\n```\n\n#### Structlike Specification\n\nFor any variable container `vs`, `vs.struct` gives an object which you can treat like\nnested struct, list, or dictionary to automatically generate variable names.\nFor example, `vs.struct.model[\"a\"].variance.positive()` would be equivalent to\n`vs.positive(name=\"model[a].variance\")`.\nAfter variables have been defined in this way, they also be extracted via `vs.struct`:\n`vs.struct.model[\"a\"].variance()` would be equivalent to `vs[\"model[a].variance\"]`.\n\nExample:\n\n```python\ndef objective(vs):\n params = vs.struct\n \n x = params.x.unbounded()\n y = params.y.unbounded()\n \n for model_params, model in zip(params.models, [object(), object(), object()]):\n model_params.specific_parameter1.positive()\n model_params.specific_parameter2.positive()\n \n return x + y\n```\n\n```python\n>>> vs = Vars(np.float64)\n\n>>> objective(vs)\n-0.08322955725015702\n\n>>> vs.names\n['x',\n 'y',\n 'models[0].specific_parameter1',\n 'models[0].specific_parameter2',\n 'models[1].specific_parameter1',\n 'models[1].specific_parameter2',\n 'models[2].specific_parameter1',\n 'models[2].specific_parameter2']\n\n>>> vs.print()\nx: -0.8963\ny: 0.8131\nmodels[0].specific_parameter1: 0.01855\nmodels[0].specific_parameter2: 0.6644\nmodels[1].specific_parameter1: 0.3542\nmodels[1].specific_parameter2: 0.3642\nmodels[2].specific_parameter1: 0.5807\nmodels[2].specific_parameter2: 0.5977\n\n>>> vs.struct.models[0].specific_parameter1()\n0.018551827512328086\n\n>>> vs.struct.models[0].specific_parameter2()\n0.6643533007198247\n```\n\nThere are a few methods available for convenient manipulation of the variable struct.\nIn the following, let `params = vs.struct`.\n\n* _Go up a directory_:\n `params.a.b.c.up()` goes up one directory and gives `params.a.b`.\n If you want to be sure about which directory you are going up, you can pass\n the name of the directory you want to go up as an argument:\n `params.a.b.c.up(\"c\")` will give the intended result, but\n `params.a.b.c.up(\"b\")` will result in an assertion error.\n* _Get all variables in a path_:\n `params.a.all()` gives the regex `a.*`.\n* _Check if a variable exists_:\n `bool(params.a)` gives `True` if `a` is a defined variable and `False`\n otherwise.\n* _Assign a value to a variable_:\n `params.a.assign(1)` assigns `1` to `a`.\n* _Delete a variable_:\n `params.a.delete()` deletes `a`.\n\n\n### Optimisers\n\nThe following optimisers are available:\n\n```\nvarz.{autograd,tensorflow,torch,jax}.minimise_l_bfgs_b (L-BFGS-B)\nvarz.{autograd,tensorflow,torch,jax}.minimise_adam (ADAM)\n```\n\nThe L-BFGS-B algorithm is recommended for deterministic objectives and ADAM\nis recommended for stochastic objectives.\n\nSee the examples for an illustration of how these optimisers can\nbe used.\nSome commonly used keyword arguments are as follows:\n\n| Keyword Argument | Description |\n| - | - |\n| `iters` | Number of iterations |\n| `trace` | Show progress |\n| `jit` | Use a JIT to compile the gradient |\n\nSee the API for a detailed description of the keyword arguments that these\noptimisers accept.\n\n### PyTorch Specifics\n\nAll the variables held by a container can be detached from the current \ncomputation graph with `Vars.detach` .\nTo make a copy of the container with detached versions of the variables, use\n`Vars.copy` with `detach=True` instead.\nWhether variables require gradients can be configured with `Vars.requires_grad`.\nBy default, no variable requires a gradient.\n\n### Getting and Setting Latent Representations of Variables as a Vector\n\nIt may be desirable to get the latent representations of a collection of \nvariables as a single vector, e.g. when feeding them to an optimiser.\nThis can be achieved with `Vars.get_latent_vector`.\n\n```python\n>>> vs.get_latent_vector(\"x\", \"*_variable\")\narray([0.12500578, -0.21510423, -0.61336039, 1.23074066, -4.07892742,\n -0.604883])\n```\n\nSimilarly, to update the latent representation of a collection of variables,\n`Vars.set_latent_vector` can be used.\n\n```python\n>>> vs.set_latent_vector(np.ones(6), \"x\", \"*_variable\")\n[array([[1., 1.],\n [1., 1.]]), array(1.), array(1.)]\n\n>>> vs.get_latent_vector(\"x\", \"*_variable\")\narray([1., 1., 1., 1., 1., 1.])\n```\n\n#### Differentiable Assignment\nBy default, `Vars.set_latent_vector` will overwrite the variables, just like\n`Vars.assign`.\nThis has as an unfortunate consequence that you cannot differentiate with respect to\nthe assigned values.\nTo be able to differentiable with respect to the assigned values, set the keyword\n`differentiable=True` in the call to `Vars.set_latent_vector`.\nUnlike regular assignment, if the variable container is a copy of some original,\ndifferentiable assignment will not mutate the variables in the original.\n\n### Get Variables from a Source\n\nThe keyword argument `source` can set to a tensor from which the latent \nvariables will be obtained.\n\nExample:\n\n```python\n>>> vs = Vars(np.float32, source=np.array([1, 2, 3, 4, 5]))\n\n>>> vs.unbounded()\narray(1., dtype=float32)\n\n>>> vs.unbounded(shape=(3,))\narray([2., 3., 4.], dtype=float32)\n\n>>> vs.pos()\n148.41316\n\n>>> np.exp(5).astype(np.float32)\n148.41316\n```\n\n## GPU Support\nTo create and optimise variables on a GPU,\n[set the active device to a GPU](https://github.com/wesselb/lab#devices).\nThe easiest way of doing this is to `import lab as B` and\n`B.set_global_device(\"gpu:0\")`.\n\n## Examples\n\n### Minimise a Function Using L-BFGS-B in AutoGrad\n\n```python\nimport autograd.numpy as np\nfrom varz.autograd import Vars, minimise_l_bfgs_b\n\ntarget = 5.0 \n\n\ndef objective(vs):\n # Get a variable named \"x\", which must be positive, initialised to 10.\n x = vs.pos(10.0, name=\"x\") \n return (x ** 0.5 - target) ** 2 \n```\n\n```python\n>>> vs = Vars(np.float64)\n\n>>> minimise_l_bfgs_b(objective, vs)\n3.17785950743424e-19 # Final objective function value.\n\n>>> vs['x'] - target ** 2\n-5.637250666268301e-09\n```\n\n### Minimise a Function Using L-BFGS-B in TensorFlow\n\n```python\nimport tensorflow as tf\nfrom varz.tensorflow import Vars, minimise_l_bfgs_b\n\ntarget = 5.0\n\n\ndef objective(vs):\n # Get a variable named \"x\", which must be positive, initialised to 10.\n x = vs.pos(10.0, name=\"x\") \n return (x ** 0.5 - target) ** 2 \n```\n\n```python\n>>> vs = Vars(tf.float64)\n\n>>> minimise_l_bfgs_b(objective, vs)\n3.17785950743424e-19 # Final objective function value.\n\n>>> vs['x'] - target ** 2\n\n\n>>> vs = Vars(tf.float64)\n\n>>> minimise_l_bfgs_b(objective, vs, jit=True) # Speed up optimisation with TF's JIT!\n3.17785950743424e-19\n```\n\n### Minimise a Function Using L-BFGS-B in PyTorch\n\n```python\nimport torch\nfrom varz.torch import Vars, minimise_l_bfgs_b\n\ntarget = torch.tensor(5.0, dtype=torch.float64)\n\n\ndef objective(vs):\n # Get a variable named \"x\", which must be positive, initialised to 10.\n x = vs.pos(10.0, name=\"x\") \n return (x ** 0.5 - target) ** 2 \n```\n\n```python\n>>> vs = Vars(torch.float64)\n\n>>> minimise_l_bfgs_b(objective, vs)\narray(3.17785951e-19) # Final objective function value.\n\n>>> vs[\"x\"] - target ** 2\ntensor(-5.6373e-09, dtype=torch.float64)\n\n>>> vs = Vars(torch.float64)\n\n>>> minimise_l_bfgs_b(objective, vs, jit=True) # Speed up optimisation with PyTorch's JIT!\narray(3.17785951e-19)\n```\n\n### Minimise a Function Using L-BFGS-B in JAX\n\n```python\nimport jax.numpy as jnp\nfrom varz.jax import Vars, minimise_l_bfgs_b\n\ntarget = 5.0\n\n\ndef objective(vs):\n # Get a variable named \"x\", which must be positive, initialised to 10.\n x = vs.pos(10.0, name=\"x\") \n return (x ** 0.5 - target) ** 2 \n```\n\n```python\n>>> vs = Vars(jnp.float64)\n\n>>> minimise_l_bfgs_b(objective, vs)\narray(3.17785951e-19) # Final objective function value.\n\n>>> vs[\"x\"] - target ** 2\n-5.637250666268301e-09\n\n>>> vs = Vars(jnp.float64)\n\n>>> minimise_l_bfgs_b(objective, vs, jit=True) # Speed up optimisation with Jax's JIT!\narray(3.17785951e-19)\n```\n\n### Tracking the Learning Curve in JAX\n```python\nimport jax.numpy as jnp\nfrom varz.jax import Vars, minimise_l_bfgs_b\n\ntarget = 5.0\n\n\ndef objective(vs, prev_x):\n # Get a variable named \"x\", which must be positive, initialised to 10.\n x = vs.pos(10.0, name=\"x\")\n # In addition to the objective function value, also return `x` so that \n # we can log it.\n return (x ** 0.5 - target) ** 2, x \n\n\nobjs = []\nxs = []\n\n\ndef callback(obj, x):\n objs.append(obj)\n xs.append(x)\n # Return a dictionary of extra information to show in the progress display.\n return {\"x\": x}\n```\n\n```python\n>>> vs = Vars(jnp.float64)\n\n>>> minimise_l_bfgs_b(objective, (vs, 0), trace=True, callback=callback)\nMinimisation of \"objective\":\n Iteration 1/1000:\n Time elapsed: 0.0 s\n Time left: 19.0 s\n Objective value: 0.04567\n x: 27.18\n Iteration 6/1000:\n Time elapsed: 0.1 s\n Time left: 7.4 s\n Objective value: 4.520e-04\n x: 24.99\n Done!\nTermination message:\n CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL\n(array(3.17785951e-19), DeviceArray(24.99999999, dtype=float64))\n\n>>> vs[\"x\"] - target ** 2\nDeviceArray(-5.63725067e-09, dtype=float64)\n\n>>> objs\n[array(3.3772234),\n array(0.04567386),\n array(0.03582296),\n array(0.00014534),\n array(5.18203996e-07),\n array(6.81622668e-12),\n array(3.17785951e-19)]\n\n>>> xs\n[DeviceArray(10., dtype=float64),\n DeviceArray(27.18281828, dtype=float64),\n DeviceArray(23.14312757, dtype=float64),\n DeviceArray(24.87958747, dtype=float64),\n DeviceArray(25.00719916, dtype=float64),\n DeviceArray(24.99997389, dtype=float64),\n DeviceArray(24.99999999, dtype=float64)]\n```\n\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/wesselb/varz", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "varz", "package_url": "https://pypi.org/project/varz/", "platform": null, "project_url": "https://pypi.org/project/varz/", "project_urls": { "Homepage": "https://github.com/wesselb/varz" }, "release_url": "https://pypi.org/project/varz/0.7.5/", "requires_dist": null, "requires_python": ">=3.6", "summary": "Painless variables in PyTorch and TensorFlow", "version": "0.7.5", "yanked": false, "yanked_reason": null }, "last_serial": 13524795, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "7790a446c6bda587b2478a44299aa29f", "sha256": "16b3f94f89720661e0a7d3f597b2f2f560daa16c8cf0de2417a04de654a98c51" }, "downloads": -1, "filename": "varz-0.1.0.tar.gz", "has_sig": false, "md5_digest": "7790a446c6bda587b2478a44299aa29f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15342, "upload_time": "2019-06-13T16:58:40", "upload_time_iso_8601": "2019-06-13T16:58:40.753522Z", "url": "https://files.pythonhosted.org/packages/cb/fc/047b84ac1aeab39d8a5a595d88005e289467e552efbb7f3b09b7e9ec857e/varz-0.1.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "3b4092121a8e32ed047d0dd9265ad7c6", "sha256": "16f05576c5056858366e8458d12a1b311e54c527f112acc2c8d2a1cfcc1b76b1" }, "downloads": -1, "filename": "varz-0.1.1.tar.gz", "has_sig": false, "md5_digest": "3b4092121a8e32ed047d0dd9265ad7c6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15411, "upload_time": "2019-06-13T18:01:34", "upload_time_iso_8601": "2019-06-13T18:01:34.810276Z", "url": "https://files.pythonhosted.org/packages/3c/fa/2623fdf0ac28cac995e29792508c0119c5f8454e3422ab17c4d6550f5493/varz-0.1.1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "4552b37c588975e374a4416f096e51a1", "sha256": "2b7ba495c436eaefbcc41f3f4d62ccb23d9ddeadccd448b2c0cfd97f9d54cf5e" }, "downloads": -1, "filename": "varz-0.2.0.tar.gz", "has_sig": false, "md5_digest": "4552b37c588975e374a4416f096e51a1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15583, "upload_time": "2019-07-09T22:38:24", "upload_time_iso_8601": "2019-07-09T22:38:24.812886Z", "url": "https://files.pythonhosted.org/packages/40/cf/96c891fa4f7a3ad4f8b5ebbbedbd1267db64c62fc377984490df817699c5/varz-0.2.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "42336cbb45c1d33d2630bdb46ebd93f3", "sha256": "48203d5f557b5ea9338e662c58e92b6a535919fdf37267781f2acf2b73e45e8c" }, "downloads": -1, "filename": "varz-0.3.0.tar.gz", "has_sig": false, "md5_digest": "42336cbb45c1d33d2630bdb46ebd93f3", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.5", "size": 16946, "upload_time": "2019-10-29T22:07:50", "upload_time_iso_8601": "2019-10-29T22:07:50.715781Z", "url": "https://files.pythonhosted.org/packages/43/3f/f6b10dc0af9657aebb8793f95142ed695c6197c58b705235c3b662539865/varz-0.3.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.3.1": [ { "comment_text": "", "digests": { "md5": "10736faeb033cfef8ec3052d998949d8", "sha256": "7aea224e32f1df9d6ef4312881d043a20148884548188cf46cc300d6b5526261" }, "downloads": -1, "filename": "varz-0.3.1.tar.gz", "has_sig": false, "md5_digest": "10736faeb033cfef8ec3052d998949d8", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 18742, "upload_time": "2019-11-06T00:37:35", "upload_time_iso_8601": "2019-11-06T00:37:35.131987Z", "url": "https://files.pythonhosted.org/packages/b0/20/c4a033b0a8e38955103b9c4974472a5aab9548cd5aa92a91878dc80fd2c2/varz-0.3.1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.4.0": [ { "comment_text": "", "digests": { "md5": "f19814ff0c7549a8efcbd412de155b26", "sha256": "fb0b9f4e65bfd5ec19d8f39ac0cba27e118b7327c938f0710760c4011135c8cb" }, "downloads": -1, "filename": "varz-0.4.0.tar.gz", "has_sig": false, "md5_digest": "f19814ff0c7549a8efcbd412de155b26", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 22928, "upload_time": "2019-11-07T16:22:37", "upload_time_iso_8601": "2019-11-07T16:22:37.866536Z", "url": "https://files.pythonhosted.org/packages/74/f4/c3c1da90ab72c9fb6e3f0918b8437288373ddc2a3ca931430349657d9634/varz-0.4.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.4.1": [ { "comment_text": "", "digests": { "md5": "664de356b252a68b16ccc0d45f8e008d", "sha256": "8cf9fa72a5be813b43d421d5eb12b8de62aba4b39eda76b04510c265dbad1b32" }, "downloads": -1, "filename": "varz-0.4.1.tar.gz", "has_sig": false, "md5_digest": "664de356b252a68b16ccc0d45f8e008d", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 25562, "upload_time": "2020-01-03T13:24:32", "upload_time_iso_8601": "2020-01-03T13:24:32.782966Z", "url": "https://files.pythonhosted.org/packages/6c/d3/4030369fc86225f62bec9c7b603f3a7a8d45d26560cd1edf0d5dc000b154/varz-0.4.1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.4.2": [ { "comment_text": "", "digests": { "md5": "ea322bca83d02897eed0d3120cdc145e", "sha256": "4cddc1ecdd54c3b1b4529c48d496855e75406fc7877052ab573874ebf972a30d" }, "downloads": -1, "filename": "varz-0.4.2.tar.gz", "has_sig": false, "md5_digest": "ea322bca83d02897eed0d3120cdc145e", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 25715, "upload_time": "2020-01-04T15:43:09", "upload_time_iso_8601": "2020-01-04T15:43:09.326642Z", "url": "https://files.pythonhosted.org/packages/c0/d5/6735ae95110788be4d80fc4cfd0d3433cbc7a6c3c67618960d1f0175b679/varz-0.4.2.tar.gz", "yanked": false, "yanked_reason": null } ], "0.4.3": [ { "comment_text": "", "digests": { "md5": "16f8469769c345c9ca0c564123a0eebf", "sha256": "43e92069ad3c276f3a0a8f053c10babff58cb5d469c071919a310a9635b627b1" }, "downloads": -1, "filename": "varz-0.4.3.tar.gz", "has_sig": false, "md5_digest": "16f8469769c345c9ca0c564123a0eebf", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 25750, "upload_time": "2020-01-18T18:02:31", "upload_time_iso_8601": "2020-01-18T18:02:31.788882Z", "url": "https://files.pythonhosted.org/packages/d5/e2/02cfb67e9ee94133bc0cfe08ccd890605ffe8eef1911e0582ed60cc4ec4b/varz-0.4.3.tar.gz", "yanked": false, "yanked_reason": null } ], "0.5.0": [ { "comment_text": "", "digests": { "md5": "34d0433f0f2c67c127accf27e3593342", "sha256": "27b860d0961b61d89fbc2bde9809606e315865def9987147bc09e08238ae93f7" }, "downloads": -1, "filename": "varz-0.5.0.tar.gz", "has_sig": false, "md5_digest": "34d0433f0f2c67c127accf27e3593342", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 27242, "upload_time": "2020-12-05T19:42:32", "upload_time_iso_8601": "2020-12-05T19:42:32.935493Z", "url": "https://files.pythonhosted.org/packages/64/4a/2f2bde36d42110457068783006d04368531a0965b03e589cc90a89a659e1/varz-0.5.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.5.1": [ { "comment_text": "", "digests": { "md5": "94ba2477129b4bfb951404cffc61bba1", "sha256": "2f97a3b8cb25c0eef19e18b14ecec3bf3a1e4f906457b896204be0eebed84b5a" }, "downloads": -1, "filename": "varz-0.5.1.tar.gz", "has_sig": false, "md5_digest": "94ba2477129b4bfb951404cffc61bba1", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 27396, "upload_time": "2021-01-14T13:24:58", "upload_time_iso_8601": "2021-01-14T13:24:58.428414Z", "url": "https://files.pythonhosted.org/packages/ce/ad/29cf2f4cead817365935e0801c545e02f958f7ac715abd11ea41ce67ca08/varz-0.5.1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.5.2": [ { "comment_text": "", "digests": { "md5": "1059dfba60aeb119783a75ff152e8c6e", "sha256": "5e918079ec9a5e23ced60ce3dab72461b58240391ed896ad6dad954b50b99752" }, "downloads": -1, "filename": "varz-0.5.2.tar.gz", "has_sig": false, "md5_digest": "1059dfba60aeb119783a75ff152e8c6e", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 27398, "upload_time": "2021-01-14T14:48:20", "upload_time_iso_8601": "2021-01-14T14:48:20.271872Z", "url": "https://files.pythonhosted.org/packages/ed/60/3d34d79ec6a840956dccd212120df000ddf69b4ed1fd59b83c794d302c3b/varz-0.5.2.tar.gz", "yanked": false, "yanked_reason": null } ], "0.5.3": [ { "comment_text": "", "digests": { "md5": "3f2ca9406db7c5bf26fdf57f3ddb45cf", "sha256": "5fcaa29c3085cad1bec2404169a3af125e9785c50ba813ff51148a19ef6ff8c4" }, "downloads": -1, "filename": "varz-0.5.3.tar.gz", "has_sig": false, "md5_digest": "3f2ca9406db7c5bf26fdf57f3ddb45cf", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 27739, "upload_time": "2021-01-24T15:58:23", "upload_time_iso_8601": "2021-01-24T15:58:23.743129Z", "url": "https://files.pythonhosted.org/packages/2f/b9/188a49b6fb8448251c540a05c52ad99805e3381057c79515669d0f525801/varz-0.5.3.tar.gz", "yanked": false, "yanked_reason": null } ], "0.6.0": [ { "comment_text": "", "digests": { "md5": "ad49fb1e38ff4dbcc047cae782a79843", "sha256": "f69b4b0a30e943f8805e38231da2e346045a8d82edcb3bfd1dab82e2910e44da" }, "downloads": -1, "filename": "varz-0.6.0.tar.gz", "has_sig": false, "md5_digest": "ad49fb1e38ff4dbcc047cae782a79843", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 27908, "upload_time": "2021-04-22T07:33:13", "upload_time_iso_8601": "2021-04-22T07:33:13.471015Z", "url": "https://files.pythonhosted.org/packages/66/42/97d6509baabb3eaae91fa8fb98cfdfcf81b6416aeb721b7cb5da41bdb669/varz-0.6.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.6.1": [ { "comment_text": "", "digests": { "md5": "a1409dfd6d2779e84d7f1916cf6056d5", "sha256": "7b5e7746dc598b510d09de3707e1896e147967fb5f2082d2dac432af1dda4e8b" }, "downloads": -1, "filename": "varz-0.6.1.tar.gz", "has_sig": false, "md5_digest": "a1409dfd6d2779e84d7f1916cf6056d5", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 27853, "upload_time": "2021-04-26T12:02:32", "upload_time_iso_8601": "2021-04-26T12:02:32.372159Z", "url": "https://files.pythonhosted.org/packages/4e/ee/81dce9b6a37ea909805074bec9fdd3aabfc033a30dd645cba46792a93132/varz-0.6.1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.6.2": [ { "comment_text": "", "digests": { "md5": "a57d7584b86c5e93a1be57f6cdf2c9d2", "sha256": "5e605f12135e75e8cff04cde2811981f7fffcc776920d9c4b8b29c717d3ada76" }, "downloads": -1, "filename": "varz-0.6.2.tar.gz", "has_sig": false, "md5_digest": "a57d7584b86c5e93a1be57f6cdf2c9d2", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 27854, "upload_time": "2021-04-27T10:58:51", "upload_time_iso_8601": "2021-04-27T10:58:51.811624Z", "url": "https://files.pythonhosted.org/packages/ad/60/4099faeb8f968d6ac44bc90e3f9412683576cce944af896ae40ec4a23b9b/varz-0.6.2.tar.gz", "yanked": false, "yanked_reason": null } ], "0.6.3": [ { "comment_text": "", "digests": { "md5": "3d507f6f334ca2043889c47ae0ee6011", "sha256": "88aba6bc13e2e0a0a75324c619c4c8e34cfaef42deb3b3119965b32c77efe7c2" }, "downloads": -1, "filename": "varz-0.6.3.tar.gz", "has_sig": false, "md5_digest": "3d507f6f334ca2043889c47ae0ee6011", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 27941, "upload_time": "2021-05-18T12:22:00", "upload_time_iso_8601": "2021-05-18T12:22:00.080959Z", "url": "https://files.pythonhosted.org/packages/a4/86/241575f615df85a8e35c4daf6abdaf3dfdc44875d046f003273b291d22c2/varz-0.6.3.tar.gz", "yanked": false, "yanked_reason": null } ], "0.6.4": [ { "comment_text": "", "digests": { "md5": "cae3b0030e1e1abf5f5e1a70a4d11330", "sha256": "28ae37047f73d5f90f87dd8863f6dbaf29ccf80a8be686f8f1a312a8a534af62" }, "downloads": -1, "filename": "varz-0.6.4.tar.gz", "has_sig": false, "md5_digest": "cae3b0030e1e1abf5f5e1a70a4d11330", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 27628, "upload_time": "2021-06-21T14:38:39", "upload_time_iso_8601": "2021-06-21T14:38:39.675719Z", "url": "https://files.pythonhosted.org/packages/c1/a3/f63b9ff0c9ba8e71d80054bc5f280e84a8378959566b319dff1e312f0fb8/varz-0.6.4.tar.gz", "yanked": false, "yanked_reason": null } ], "0.7.0": [ { "comment_text": "", "digests": { "md5": "c2f5a9966934f4cd54dc08314247a854", "sha256": "ad47513559e43cacde13fcf4ef0e02318cd6e62d3d3ab64bc815a1c084985006" }, "downloads": -1, "filename": "varz-0.7.0.tar.gz", "has_sig": false, "md5_digest": "c2f5a9966934f4cd54dc08314247a854", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 31257, "upload_time": "2021-06-22T16:17:54", "upload_time_iso_8601": "2021-06-22T16:17:54.423524Z", "url": "https://files.pythonhosted.org/packages/02/99/62c5041aa4125821fae7c182e2c0ca602a8aa6a05a78c5d3a0e4c065049e/varz-0.7.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.7.1": [ { "comment_text": "", "digests": { "md5": "c874c66a0f375e33ef50350374d26296", "sha256": "dafccb30b4d5371203d8589a0baf66c9e295ec46e501e4c700426345cc8a58fa" }, "downloads": -1, "filename": "varz-0.7.1.tar.gz", "has_sig": false, "md5_digest": "c874c66a0f375e33ef50350374d26296", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 31630, "upload_time": "2021-07-14T09:55:33", "upload_time_iso_8601": "2021-07-14T09:55:33.552523Z", "url": "https://files.pythonhosted.org/packages/a6/36/b0606136517f2b0fe5a0b7bd085e6ca4c40a7ce59fd520bb03d82fd9919a/varz-0.7.1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.7.2": [ { "comment_text": "", "digests": { "md5": "25f5dc88a9d028ace84c0d4a7e66f938", "sha256": "173deac93610d21962945d52a2ca8877d71377943c00d8aaf77cf18c5e0ab35f" }, "downloads": -1, "filename": "varz-0.7.2.tar.gz", "has_sig": false, "md5_digest": "25f5dc88a9d028ace84c0d4a7e66f938", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 31652, "upload_time": "2021-07-14T10:09:21", "upload_time_iso_8601": "2021-07-14T10:09:21.711387Z", "url": "https://files.pythonhosted.org/packages/bd/5d/d1b52ec1daff028b0ef2da892346a43299dd970361c2c5d0c8ec20c3b78b/varz-0.7.2.tar.gz", "yanked": false, "yanked_reason": null } ], "0.7.3": [ { "comment_text": "", "digests": { "md5": "4e95dff626467223038edeed895c1f9a", "sha256": "0b9fa00d6095b504551ea43ed2c7ba8f6d6b412358b30cab72ac5c3b6c511cce" }, "downloads": -1, "filename": "varz-0.7.3.tar.gz", "has_sig": false, "md5_digest": "4e95dff626467223038edeed895c1f9a", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 37788, "upload_time": "2021-08-28T14:51:08", "upload_time_iso_8601": "2021-08-28T14:51:08.011547Z", "url": "https://files.pythonhosted.org/packages/74/b1/595863a032049498a96f88e642200e209b5fdc04192272a85fa1b7ac6193/varz-0.7.3.tar.gz", "yanked": false, "yanked_reason": null } ], "0.7.4": [ { "comment_text": "", "digests": { "md5": "30eca724f10204d45b81a23aa12a2137", "sha256": "774a032fe13c91551e2610904692071bc6ca782c984f8a158ca5b999074c3828" }, "downloads": -1, "filename": "varz-0.7.4.tar.gz", "has_sig": false, "md5_digest": "30eca724f10204d45b81a23aa12a2137", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 40055, "upload_time": "2021-09-29T10:48:01", "upload_time_iso_8601": "2021-09-29T10:48:01.072872Z", "url": "https://files.pythonhosted.org/packages/67/50/e59236fcbb87570f801b0c3ffb9a50d9c97d38df07b0c0985fa2d56a312c/varz-0.7.4.tar.gz", "yanked": false, "yanked_reason": null } ], "0.7.5": [ { "comment_text": "", "digests": { "md5": "d2c1c08b7db75511692b74e821695326", "sha256": "b5055b43c798be9609946bcc60dad954366536e8fd96bd0cd4f816183387a996" }, "downloads": -1, "filename": "varz-0.7.5.tar.gz", "has_sig": false, "md5_digest": "d2c1c08b7db75511692b74e821695326", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 42480, "upload_time": "2022-04-15T13:11:35", "upload_time_iso_8601": "2022-04-15T13:11:35.255419Z", "url": "https://files.pythonhosted.org/packages/c3/3d/38c770167eebe57e6869b5036b94b50c7483fb727d52b20aca4da64b5cef/varz-0.7.5.tar.gz", "yanked": false, "yanked_reason": null } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "d2c1c08b7db75511692b74e821695326", "sha256": "b5055b43c798be9609946bcc60dad954366536e8fd96bd0cd4f816183387a996" }, "downloads": -1, "filename": "varz-0.7.5.tar.gz", "has_sig": false, "md5_digest": "d2c1c08b7db75511692b74e821695326", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 42480, "upload_time": "2022-04-15T13:11:35", "upload_time_iso_8601": "2022-04-15T13:11:35.255419Z", "url": "https://files.pythonhosted.org/packages/c3/3d/38c770167eebe57e6869b5036b94b50c7483fb727d52b20aca4da64b5cef/varz-0.7.5.tar.gz", "yanked": false, "yanked_reason": null } ], "vulnerabilities": [] }