{ "info": { "author": "Wessel Bruinsma", "author_email": "wessel.p.bruinsma@gmail.com", "bugtrack_url": null, "classifiers": [], "description": "# [FDM: Finite Difference Methods](http://github.com/wesselb/fdm)\n\n[![Build](https://travis-ci.org/wesselb/fdm.svg?branch=master)](https://travis-ci.org/wesselb/fdm)\n[![Coverage Status](https://coveralls.io/repos/github/wesselb/fdm/badge.svg?branch=master&service=github)](https://coveralls.io/github/wesselb/fdm?branch=master)\n[![Latest Docs](https://img.shields.io/badge/docs-latest-blue.svg)](https://wesselb.github.io/fdm)\n\nFDM estimates derivatives with finite differences.\n\nSee also [FDM.jl](https://github.com/invenia/FDM.jl).\n\nSee the [docs](https://wesselb.github.io/fdm).\n\n* [Installation](#installation)\n* [Multivariate Derivatives](#multivariate-derivatives)\n - [Gradients](#gradients)\n - [Jacobians](#jacobians)\n - [Jacobian-Vector Products (Directional Derivatives)](#jacobian-vector-products-directional-derivatives)\n - [Hessian-Vector Products](#hessian-vector-products)\n* [Scalar Derivatives](#scalar-derivatives)\n* [Testing Sensitivities in a Reverse-Mode Automatic Differentation Framework](#testing-sensitivities-in-a-reverse-mode-automatic-differentation-framework)\n\n## Installation\n```bash\npip install fdm\n```\n\n## Multivariate Derivatives\n\n```python\nfrom fdm import gradient, jacobian, jvp, hvp\n```\n\nFor the purpose of illustration, let us consider a quadratic function:\n\n```python\n>>> a = np.random.randn(3, 3); a = a @ a.T\n>>> a\narray([[ 3.57224794, 0.22646662, -1.80432262],\n [ 0.22646662, 4.72596213, 3.46435663],\n [-1.80432262, 3.46435663, 3.70938152]])\n \n>>> def f(x):\n... return 0.5 * x @ a @ x\n```\n\nConsider the following input value:\n\n```python\n>>> x = np.array([1.0, 2.0, 3.0])\n```\n\n### Gradients\n\n```python\n>>> grad = gradient(f)\n>>> grad(x)\narray([-1.38778668, 20.07146076, 16.25253519])\n\n>>> a @ x\narray([-1.38778668, 20.07146076, 16.25253519])\n```\n\n### Jacobians\n\n```python\n>>> jac = jacobian(f)\n>>> jac(x)\narray([[-1.38778668, 20.07146076, 16.25253519]])\n\n>>> a @ x\narray([-1.38778668, 20.07146076, 16.25253519])\n```\n\nBut `jacobian` also works for multi-valued functions.\n\n```python\n>>> def f2(x):\n... return a @ x\n\n>>> jac2 = jacobian(f2)\n>>> jac2(x)\narray([[ 3.57224794, 0.22646662, -1.80432262],\n [ 0.22646662, 4.72596213, 3.46435663],\n [-1.80432262, 3.46435663, 3.70938152]])\n \n>>> a\narray([[ 3.57224794, 0.22646662, -1.80432262],\n [ 0.22646662, 4.72596213, 3.46435663],\n [-1.80432262, 3.46435663, 3.70938152]])\n```\n\n### Jacobian-Vector Products (Directional Derivatives)\n\nIn the scalar case, `jvp` computes directional derivatives:\n\n```python\n>>> v = np.array([0.5, 0.6, 0.7]) # A direction\n\n>>> dir_deriv = jvp(f, v) \n>>> dir_deriv(x)\n22.725757753354657\n\n>>> np.sum(grad(x) * v)\n22.72575775335481\n```\n\nIn the multivariate case, `jvp` generalises to Jacobian-vector products:\n\n```python\n>>> prod = jvp(f2, v)\n>>> prod(x)\narray([0.65897811, 5.37386023, 3.77301973])\n\n>>> a @ v\narray([0.65897811, 5.37386023, 3.77301973])\n```\n\n### Hessian-Vector Products\n\n```python\n>>> prod = hvp(f, v)\n>>> prod(x)\narray([[0.6589781 , 5.37386023, 3.77301973]])\n\n>>> 0.5 * (a + a.T) @ v\narray([0.65897811, 5.37386023, 3.77301973])\n```\n\n## Scalar Derivatives\n```python\n>>> from fdm import central_fdm\n```\n\nLet's try to estimate the first derivative of `np.sin` at `1` with a \nsecond-order method, where we know that `np.sin` is well conditioned.\n\n```python\n>>> central_fdm(order=2, deriv=1, condition=1)(np.sin, 1) - np.cos(1) \n4.307577627926662e-10\n```\n\nAnd let's try to estimate the second derivative of `np.sin` at `1` with a \nthird-order method.\n\n```python\n>>> central_fdm(order=3, deriv=2, condition=1)(np.sin, 1) + np.sin(1) \n-1.263876664436836e-07\n```\n\nHm.\nLet's check the accuracy of this third-order method.\nThe step size and accuracy of the method are computed upon calling\n`FDM.estimate()`.\n\n```python\n>>> central_fdm(order=3, deriv=2, condition=1).estimate().acc\n8.733476581980376e-06\n```\n\nWe might want a little more accuracy. Let's check the accuracy of a \nfifth-order method.\n\n```python\n>>> central_fdm(order=5, deriv=2, condition=1).estimate().acc\n7.343652562575155e-10\n```\n\nAnd let's estimate the second derivative of `np.sin` at `1` with a \nfifth-order method.\n\n```python\n>>> central_fdm(order=5, deriv=2, condition=1)(np.sin, 1) + np.sin(1) \n-9.145184609593571e-11\n```\n\nHooray!\n\nFinally, let us verify that increasing the order indeed reliably increases \nthe accuracy.\n\n```python\n>>> for i in range(3, 11):\n... print(central_fdm(order=i, deriv=2, condition=1)(np.sin, 1) + np.sin(1))\n-1.263876664436836e-07\n6.341286606925678e-09\n-9.145184609593571e-11\n2.7335911312320604e-12\n6.588063428125679e-13\n2.142730437526552e-13\n2.057243264630415e-13\n8.570921750106208e-14\n```\n\n## Testing Sensitivities in a Reverse-Mode Automatic Differentation Framework\n\nConsider the function\n\n```python\ndef mul(a, b):\n return a * b\n```\n\nand its sensitivity\n\n```python\ndef s_mul(s_y, y, a, b):\n return s_y * b, a * s_y\n```\n\nThe sensitivity `s_mul` takes in the sensitivity `s_y` of the output `y`, \nthe output `y`, and the arguments of the function `mul`; and returns a tuple \ncontaining the sensitivities with respect to `a` and `b`.\nThen function `check_sensitivity` can be used to assert that the \nimplementation of `s_mul` is correct:\n\n```python\n>>> from fdm import check_sensitivity\n\n>>> check_sensitivity(mul, s_mul, (2, 3)) # Test at arguments `2` and `3`.\n```\n\nSuppose that the implementation were wrong, for example\n\n```python\ndef s_mul_wrong(s_y, y, a, b):\n return s_y * b, b * s_y # Used `b` instead of `a` for the second sensitivity!\n```\n\nThen `check_sensitivity` should throw an `AssertionError`:\n\n```python\n>>> check_sensitivity(mul, s_mul, (2, 3)) \nAssertionError: Sensitivity of argument 2 of function \"mul\" did not match numerical estimate.\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/fdm", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "fdm", "package_url": "https://pypi.org/project/fdm/", "platform": "", "project_url": "https://pypi.org/project/fdm/", "project_urls": { "Homepage": "https://github.com/wesselb/fdm" }, "release_url": "https://pypi.org/project/fdm/0.1.3/", "requires_dist": null, "requires_python": "", "summary": "Compute derivatives with finite-difference methods", "version": "0.1.3" }, "last_serial": 5397123, "releases": { "0.1.2": [ { "comment_text": "", "digests": { "md5": "4381ceddd1e17793ec7a1c5e3cb5df80", "sha256": "3837a7ebb5f55a9a613a30851d1fabb90cca347f196464ce0dd4f7c5f7f24ed6" }, "downloads": -1, "filename": "fdm-0.1.2.tar.gz", "has_sig": false, "md5_digest": "4381ceddd1e17793ec7a1c5e3cb5df80", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10162, "upload_time": "2019-06-12T19:57:22", "url": "https://files.pythonhosted.org/packages/bd/68/d6beaea69d99431bcd14760d4c35af5cb021bd102e50f2d1aecbbf34f215/fdm-0.1.2.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "e364dfdce61f13665d8c744f794cc651", "sha256": "3d0f10656aca471687b3b4e985576815b726624c2fbe32454e858e9042d2d1da" }, "downloads": -1, "filename": "fdm-0.1.3.tar.gz", "has_sig": false, "md5_digest": "e364dfdce61f13665d8c744f794cc651", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10319, "upload_time": "2019-06-13T17:58:03", "url": "https://files.pythonhosted.org/packages/94/89/c267b0171ab9c17e3869fd2582909c8f28133ee8dfaff87ae8522167e014/fdm-0.1.3.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "e364dfdce61f13665d8c744f794cc651", "sha256": "3d0f10656aca471687b3b4e985576815b726624c2fbe32454e858e9042d2d1da" }, "downloads": -1, "filename": "fdm-0.1.3.tar.gz", "has_sig": false, "md5_digest": "e364dfdce61f13665d8c744f794cc651", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10319, "upload_time": "2019-06-13T17:58:03", "url": "https://files.pythonhosted.org/packages/94/89/c267b0171ab9c17e3869fd2582909c8f28133ee8dfaff87ae8522167e014/fdm-0.1.3.tar.gz" } ] }