Skip to content

Commit

Permalink
Merge pull request #18 from null-a/cholesky
Browse files Browse the repository at this point in the history
Add backwards pass for cholesky.
  • Loading branch information
dritchie committed May 22, 2017
2 parents c636abb + 25f373d commit 76ecbfa
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 0 deletions.
1 change: 1 addition & 0 deletions ad/README.md
Expand Up @@ -62,6 +62,7 @@ adnn comes with a large number of built-in AD primitives:
- **`ad.tensor.inverse(x)`**: Returns the inverse of the matrix `x`.
- **`ad.tensor.determinant(x)`**: Returns the determinant of the matrix `x`.
- **`ad.tensor.dot(x, y)`**: Returns the inner product of the matrices `x` and `y`.
- **`ad.tensor.cholesky(x)`**: Returns the [Cholesky decomposition](https://en.wikipedia.org/wiki/Cholesky_decomposition) of the matrix `x`.
- **Miscellaneous**
- **`ad.tensor.softmax(x)`**: Compute the [Softmax](https://en.wikipedia.org/wiki/Softmax_function) function for a tensor `x`.

Expand Down
30 changes: 30 additions & 0 deletions ad/functions.js
Expand Up @@ -274,6 +274,36 @@ fns.tensor.dot = func.newBinaryFunction({
}
});

// Smith, Stephen P. "Differentiation of the Cholesky algorithm."
// Journal of Computational and Graphical Statistics 4.2 (1995):
// 134-147.
fns.tensor.cholesky = func.newUnaryFunction({
OutputType: Tensor,
name: 'cholesky',
forward: function(x) {
return x.cholesky();
},
backward: function(x) {
var i, j, k;
var L = this;
var dL = this.dx.tril();
var n = L.x.dims[0];
for (k = n - 1; k >= 0; k--) {
for (j = k + 1; j < n; j++) {
for (i = j; i < n; i++) {
dL.data[i * n + k] -= dL.data[i * n + j] * L.x.data[j * n + k];
dL.data[j * n + k] -= dL.data[i * n + j] * L.x.data[i * n + k];
}
}
for (j = k + 1; j < n; j++) {
dL.data[j * n + k] /= L.x.data[k * n + k];
dL.data[k * n + k] -= dL.data[j * n + k] * L.x.data[j * n + k];
}
dL.data[k * n + k] /= 2 * L.x.data[k * n + k];
}
x.dx.addeq(dL);
}
});

// Tensor reductions -----------------------------------------------------

Expand Down
16 changes: 16 additions & 0 deletions tensor.js
Expand Up @@ -510,6 +510,22 @@ Tensor.prototype.cholesky = function() {
return L;
};

// Return a copy of a matrix with the elements above the main diagonal
// zeroed.
Tensor.prototype.tril = function() {
var a = this;
assert.ok((a.rank === 2) && (a.dims[0] === a.dims[1]),
'tril is only defined for square matrices.');

var n = a.dims[0];
var ret = new Tensor([n, n]);
for (var i = 0; i < n; i++) {
for (var j = 0; j <= i; j++) {
ret.data[i * n + j] = a.data[i * n + j];
}
}
return ret;
};

module.exports = Tensor;

Expand Down

0 comments on commit 76ecbfa

Please sign in to comment.