We have talked about this many times before!
The stumbling block for me is figuring out how
we'd do matrix indexing, which should return an
autodiff var.
On 7/8/13 1:03 AM, Ben Goodrich wrote:
> On Sunday, July 7, 2013 9:08:45 PM UTC-4, Matt Hoffman wrote:
>
> My question is: is this an inherent limitation of the current agrad
> architecture (which is focused on scalars)? If so, should we consider
> revamping the architecture to handle matrices? How much of a colossal
> pain would this be? I only ask because the potential payoffs* seem so
> large.
Yes, they're really big for the matrix multiply part of
the program. It may even be a speedup for derivatives if
we can calculate the partials using matrix ops, too.
> I agree that there is no shortage of potential payoffs, and I've always thought that we should be using Eigen as much as
> possible. My latest thought along the lines you describe would be for Stan to extend the
> Eigen::Matrix<double,Dynamic,Dynamic> class so that a Stan::Matrix<double,N,K> instance would either include a pointer
> to a separate Eigen::Matrix<double,N,K> instance that contained the corresponding adjoints or just included a
> Eigen::Matrix<double,N,K> of adjoints as a member of the Stan::Matrix subclass.
This should be pretty easy for forward-mode, but I
still don't see a clear path to doing it with reverse-mode.
Extending Eigen::Matrix would be problematic because
the results of any operation defined for Eigen::Matrix
would be Eigen::Matrix unless we override everything.
Another option would be to generalize var and vari, which
holds the objects as members rather than extending one and
adding another. It should be pretty easy for fvar.
template <typename T>
struct var {
vari<T>* vi_;
}
template <typename T>
struct vari {
const T val_;
T adj_;
}
Instead of directly using vari, chainable is what's used
on auto-diff stack for reverse mode, so there's some flexibility.
> But Bob and Marcus would be the ones who
> would know how much of a pain that would be to integrate into Stan.
What I can't sort out is how to do indexing. We need to
support the following two methods for indexing, and similarly
for other slices like rows and columns.
var& operator()(int,int);
var& operator()(int);
where the returned references do the right thing.
We could maybe define a specialized new var as a view.
But then we have to figure out how to allow that to
support all the usual operations, so I can write something
like:
exp(sigma[1])
where sigma is a vector. The value for sigma[1] can be
some kind of placeholder, but then we need to define exp()
for that type or somehow figure out how to generalize the definitions.
And once we've done all this, unless we specialize all the
expression templates, we're still back to inefficient compound
operations.
I think the way forward would be to just get it working as a demo
outside of the context of Stan.
- Bob