memoized_coduals

Shows that it is possible to implement reverse mode autodiff using a variation on the dual numbers called the codual numbers

https://github.com/wlad-svennik/memoized_coduals

Science Score: 44.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
    Found CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
  • Academic publication links
  • Academic email domains
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (6.1%) to scientific vocabulary

Keywords

autodiff automatic-differentiation dual-numbers plt research
Last synced: 6 months ago · JSON representation ·

Repository

Shows that it is possible to implement reverse mode autodiff using a variation on the dual numbers called the codual numbers

Basic Info
  • Host: GitHub
  • Owner: wlad-svennik
  • Language: Python
  • Default Branch: main
  • Homepage:
  • Size: 9.77 KB
Statistics
  • Stars: 3
  • Watchers: 4
  • Forks: 0
  • Open Issues: 0
  • Releases: 0
Topics
autodiff automatic-differentiation dual-numbers plt research
Created about 4 years ago · Last pushed about 4 years ago
Metadata Files
Readme Citation

README.md

The dual numbers can do efficient autodiff!

The codual numbers are a simple method of doing automatic differentiation in reverse mode. They contrast with the dual numbers which provide an easy way of doing automatic differentiation in forward mode. The difference between the two modes is that sometimes one is faster than the other.

The folklore appears to be that forward mode autodiff is easy to implement because it can be done using the beautiful algebra of dual numbers, while the same is assumed to not be the case for reverse mode. This repository presents a counterargument that a variant of the dual numbers called the codual numbers can be used to represent an implementation of reverse mode autodiff that is just as elegant and terse as can be done for forward mode. This idea was first suggested by Sandro Magi (pseudonym: Naasking).

This implementation of the codual numbers differs from Sandro Magis by using simple memoisation to eliminate the exponential worst-case behaviour he encountered. In Magis original implementation, this idea seems obscured, largely because the code was more effectful and therefore the opportunity for memoisation was less apparent. The memoisation is achieved using only one additional line of code!

This implementation should be simpler and more transparent than Magis, I hope. It also suggests that Magis reasoning behind the term codual numbers is perhaps misleading.

Definition of dual number and codual number

The codual numbers are the set

\\mathbb R \\times \\mathbb R,

while the codual numbers are a subset of

\\mathbb R \\times \\mathbb R ^ {\\mathbb R}

where the second component is always a linear map.

A notation thats used to write a dual number is a + b \\varepsilon, which stands for (a,b). Formally, \\varepsilon^2 = 0 while \\varepsilon \\neq 0.

The codual numbers may be represented using exactly the same notation as the dual numbers. They are no different than the dual numbers, except in how theyre represented on a computer! Using lambda calculus notation (which I assume you are familiar with) any dual number (a,b) can be turned into the codual number (a, \\lambda k. \\,kb), and conversely every codual number (a,B) can be turned into the dual number (a,B(1)). The difference is merely one of data structure; we need a closure to represent the codual numbers.

The definition of an operation on the codual numbers can be inferred from its definition on the dual numbers. We demonstrate this using multiplication. For dual numbers, we may define multiplication by:

(a,a') \\times (b,b') = (ab, ab' + ba').

For the codual numbers, we may use the correspondence (a,b') \\mapsto (a, \\lambda k. \\,kb) to get:

(a,A) \\times (b,B) = (ab, \\lambda k. \\,k\\cdot(a\\cdot B(1) + b\\cdot A(1))),

where by \\cdot, we mean multiplication of real numbers. Using the fact that A and B are linear maps, we can rearrange this to:

(a,A) \\times (b,B) = (ab, \\lambda k. \\,B(ak) + A(bk))).

This is precisely how we define multiplication of codual numbers in the code.

Relationship with other autodiff strategies

It appears that there are three ways of doing reverse-mode autodiff, which correspond directly to the three stages of solving a problem using dynamic programming. See the table below:

IdeaExampleCorresponding autodiff algorithm
Unmemoised recursionExhibit AUnmemoised coduals
Memoised recursion, or
top-down dynamic programming
Exhibit BMemoised coduals
Bottom-up dynamic programmingExhibit CTape-based autodiff

This suggests that the tape-based approach can be derived from the coduals.

Exhibit A:

python def fib(n): if n == 0 or n == 1: return n else: return fib(n-1) + fib(n-2) Exhibit B:

```python from functools import cache

@cache def fib(n): if n == 0 or n == 1: return n else: return fib(n-1) + fib(n-2) ``` Exhibit C:

python def fib(n): a, b = 0, 1 for _ in range(n): a, b = b, a + b return a

Owner

  • Name: wlad
  • Login: wlad-svennik
  • Kind: user

Citation (CITATION.cff)

cff-version: 1.2.0
message: "If you use this software, please cite it as below."
authors:
- family-names: "Anon."
  given-names: "Anon."
  orcid: "https://orcid.org/0000-0001-7654-2031"
title: "memoized_coduals"
version: 1.0.0
doi: 10.5281/zenodo.1234
date-released: 2022-01-17
url: "https://github.com/wlad-svennik/memoized_coduals"

GitHub Events

Total
Last Year