Comments (12)
from autodiff.
I will start profile example from #37, and that write results here!
from autodiff.
One thing that we need to address is to directly populate the derivatives in the variables itself, instead of collecting these using Derivatives
, which is a std::function
that make a search in a std::unordered_set
for the variable we are fetching the derivative from.
What I mean is to replace this:
var x = 1.0;
var y = 2.0;
var z = 3.0;
var u = f(x, y, z);
Derivatives dud = derivatives(u);
double dudx = dud(x);
double dudy = dud(y);
double dudz = dud(z);
by this:
var x = 1.0;
var y = 2.0;
var z = 3.0;
var u = f(x, y, z);
derivatives(u);
double dudx = x.derivative();
double dudy = y.derivative();
double dudz = z.derivative();
Not sure yet if the method names above are the appropriate ones.
Other things to check is how much dynamic memory allocation we could prevent during the evaluation of the expressions involving var
types (or maybe think about a pool of pre-allocated var
objects from which the variables are taken. With dual
, this is not a concern, because dual
numbers are allocated in the stack, and the expressions optimized with template meta-programming techniques.
Remarking that var
and dual
serve different purposes. var
for gradient computations of scalar functions of multi-variables, and dual
for directional derivatives of both scalar or vector functions, of either single or multi-variables.
from autodiff.
Excellent @supersega ! This shows indeed that we need to get rid of this usage of std::unordered_map
inside Derivatives
type. I think we can save the derivative values in the variables themselves.
from autodiff.
By the way, which profiling software is this?
from autodiff.
This is profiler from visual studio 2017.
from autodiff.
Yes, I think that we can store derivative in var. But I'm not clear how to deal with derivativesx()
.
from autodiff.
I think derivativesx()
(which is to allow higher-order derivatives using var
) could become deprecated, because I think reverse mode is not the best approach for higher-order derivatives. But still, I think there should be an equivalent way for this, which we could think about later.
from autodiff.
Hi, I've come back from vacation and continued working on this issue. I implemented approch with storing derivatives in expression and found that we have boost performance two times.
from autodiff.
from autodiff.
Hi @allanleal and @supersega
I've been thinking about this too -- I have one small idea and one blue sky idea.
- We could move the map to be a member of var, then have popagate run during construction w.r.t an expression. That way, the derivative map is stored
u
, the "assigned-to" variable inu = f(x)
.
This won't save the heap allocations, nor decrease the hashing (the bottleneck in @supersega 's profiling above), but could remove the dependency onstd::function
.
A basic program might look like:
var x = 2.0
var u = f(x) \\ builds Expr tree and propogates derivative info
double dudx = u.derivative(x); \\ value of du/dx(x=2.0);
Let me know what you think and I can push my ideas to my fork.
- My biggest issue with reverse mode is that we often want to update an input variable and find the derivative at the new point (ie. gradient ascent). In the current implementation (as far as I can tell) this involves creating a complete tree of
Expr
variables again, on the heap, then building a newDerivativesMap
using propagate on the var containing theVariableExpr
.
It would be interesting if there was a way of updating input variables using the already-built tree and map! (I guess some form of tree where the leaves know their parents to propagate value information).
from autodiff.
Hi @ludkinm - the reverse mode algorithm does need improvement at the moment (and I think we need minor to small changes to improve significantly from where we are, as you're suggesting that the derivative info is collected from the variable itself, instead from the DerivativesMap
object (like you show in the example).
As to the re-using the expression tree - instead of building a new one each time. This will only work as long as there are no branches in the computation (there could be possibly other conditions too that would demand the full tree reconstruction). Below is an example of a function (pseudo-code) that would need the expression tree to be constructed at each function call (at the current implementation of the reverse algorithm, the re-construction would happen anyway even if there are no branches):
var f(var x) { return (x > 0) ? x**x : x*x*x; }
Consider what happens below:
var x, u;
x = 1.0;
u = f(x); // expression tree constructed for x*x
x = -1.0;
u = f(x); // expression tree constructed for x*x*x
I'm not saying it is not possible to kind of cache the expression tree. It would be great if we could improve further and further the reverse mode as the forward mode (which has received more attention from my side given that this is what I need most. There is a big PR coming in with even more interesting things on the forward mode support (higher-order directional derivatives, Taylor series, etc.).
@supersega has also proposed a new reverse algorithm (via a new number type) which would complement with the existing var
type.
We can all discuss more in-depth ideas perhaps on autodiff`s Gitter Community Channel.
Just thought about something: we could have a ConditionExpr
:
var f(var x) { return condition(x > 0, x**x, x*x*x); }
We should then overload condition
so that if number types are generic (using templates), then condition
would act as the standard ternary operator. That is, condition(x > 0, x**x, x*x*x) === (x > 0)x**x : x*x*x
.
from autodiff.
Related Issues (20)
- Constexpr math functions
- Clang build issues
- Overview and comparison to <cmath>
- Is it possible to use floating point numbers in autodiff?
- Not compiling when function input is Eigen::VectorXd HOT 6
- Pybind11 + Autodiff::VectorXvar gives compiltion error
- A mistake in the definition of NumTraits<autodiff::Dual>. HOT 1
- Build fails on real.py.cxx.o HOT 3
- osx-arm64 / linux-aarch64 build missing on conda-forge HOT 9
- [Feature request] Code generation HOT 2
- Combined gradients HOT 2
- cmake compile error: numbertraits.hpp:70:16 HOT 1
- Directional Cross Derivatives HOT 1
- Is non-const argument in `gradient` necessary? HOT 1
- Dual will not work correctly for complex numbers HOT 3
- How to get the fastest performance of the autodiff. HOT 2
- Having trouble adding autodiff and Eigen to a project HOT 1
- Gitter link on website HOT 2
- Unable to build Python bindings with current master HOT 7
- An unexpected result when getting derivative of simple square function HOT 6
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from autodiff.