gradient descent (with fixed nr. of iterations, choosing optimal step size)
parent
299fcf1e04
commit
726858145a
|
@ -363,7 +363,7 @@ void GaussianFactor::addGradientContribution(const VectorConfig& x, VectorConfig
|
||||||
// calculate the value of the factor
|
// calculate the value of the factor
|
||||||
Vector e = -b_;
|
Vector e = -b_;
|
||||||
string j; Matrix Aj;
|
string j; Matrix Aj;
|
||||||
FOREACH_PAIR(j, Aj, As_) e += Vector(Aj * x[j]);
|
FOREACH_PAIR(j, Aj, As_) e += Aj * x[j];
|
||||||
|
|
||||||
// transpose
|
// transpose
|
||||||
Vector et = trans(e);
|
Vector et = trans(e);
|
||||||
|
@ -376,6 +376,24 @@ void GaussianFactor::addGradientContribution(const VectorConfig& x, VectorConfig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
// Creates a factor on step-size, given initial estimate and direction d, e.g.
|
||||||
|
// Factor |A1*x+A2*y-b|/sigma -> |A1*(x0+alpha*dx)+A2*(y0+alpha*dy)-b|/sigma
|
||||||
|
// -> |(A1*dx+A2*dy)*alpha-(b-A1*x0-A2*y0)|/sigma
|
||||||
|
/* ************************************************************************* */
|
||||||
|
GaussianFactor::shared_ptr GaussianFactor::alphaFactor(const VectorConfig& x,
|
||||||
|
const VectorConfig& d) const {
|
||||||
|
size_t m = b_.size();
|
||||||
|
Vector A = zero(m); Vector b = b_;
|
||||||
|
string j; Matrix Aj;
|
||||||
|
FOREACH_PAIR(j, Aj, As_) {
|
||||||
|
A += Aj * d[j];
|
||||||
|
b -= Aj * x[j];
|
||||||
|
}
|
||||||
|
shared_ptr factor(new GaussianFactor("alpha",Matrix_(A),b,sigmas_));
|
||||||
|
return factor;
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,13 @@ public:
|
||||||
As_.insert(make_pair(key1, A1));
|
As_.insert(make_pair(key1, A1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Construct unary factor with vector of sigmas*/
|
||||||
|
GaussianFactor(const std::string& key1, const Matrix& A1,
|
||||||
|
const Vector& b, const Vector& sigmas) :
|
||||||
|
b_(b), sigmas_(sigmas) {
|
||||||
|
As_.insert(make_pair(key1, A1));
|
||||||
|
}
|
||||||
|
|
||||||
/** Construct binary factor */
|
/** Construct binary factor */
|
||||||
GaussianFactor(const std::string& key1, const Matrix& A1,
|
GaussianFactor(const std::string& key1, const Matrix& A1,
|
||||||
const std::string& key2, const Matrix& A2,
|
const std::string& key2, const Matrix& A2,
|
||||||
|
@ -207,6 +214,20 @@ public:
|
||||||
boost::tuple<std::list<int>, std::list<int>, std::list<double> >
|
boost::tuple<std::list<int>, std::list<int>, std::list<double> >
|
||||||
sparse(const Ordering& ordering, const Dimensions& variables) const;
|
sparse(const Ordering& ordering, const Dimensions& variables) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add gradient contribution to gradient config g
|
||||||
|
* @param x: confif at which to evaluate gradient
|
||||||
|
* @param g: I/O parameter, evolving gradient
|
||||||
|
*/
|
||||||
|
void addGradientContribution(const VectorConfig& x, VectorConfig& g) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a GaussianFactor on one variable 'alpha' (step size), in direction d
|
||||||
|
* @param x: starting point for search
|
||||||
|
* @param d: search direction
|
||||||
|
*/
|
||||||
|
shared_ptr alphaFactor(const VectorConfig& x, const VectorConfig& d) const;
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
// MUTABLE functions. FD:on the path to being eradicated
|
// MUTABLE functions. FD:on the path to being eradicated
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
@ -243,13 +264,6 @@ public:
|
||||||
*/
|
*/
|
||||||
void append_factor(GaussianFactor::shared_ptr f, size_t m, size_t pos);
|
void append_factor(GaussianFactor::shared_ptr f, size_t m, size_t pos);
|
||||||
|
|
||||||
/**
|
|
||||||
* Add gradient contribution to gradient config g
|
|
||||||
* @param x: confif at which to evaluate gradient
|
|
||||||
* @param g: I/O parameter, evolving gradient
|
|
||||||
*/
|
|
||||||
void addGradientContribution(const VectorConfig& x, VectorConfig& g) const;
|
|
||||||
|
|
||||||
}; // GaussianFactor
|
}; // GaussianFactor
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
|
@ -209,3 +209,33 @@ VectorConfig GaussianFactorGraph::gradient(const VectorConfig& x) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
VectorConfig GaussianFactorGraph::optimalUpdate(const VectorConfig& x,
|
||||||
|
const VectorConfig& d) const {
|
||||||
|
|
||||||
|
// create a new graph on step-size
|
||||||
|
GaussianFactorGraph alphaGraph;
|
||||||
|
BOOST_FOREACH(sharedFactor factor,factors_) {
|
||||||
|
sharedFactor alphaFactor = factor->alphaFactor(x,d);
|
||||||
|
alphaGraph.push_back(alphaFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// solve it for optimal step-size alpha
|
||||||
|
GaussianConditional::shared_ptr gc = alphaGraph.eliminateOne("alpha");
|
||||||
|
double alpha = gc->get_d()(0);
|
||||||
|
|
||||||
|
// return updated estimate by stepping in direction d
|
||||||
|
return x.exmap(d.scale(alpha));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
VectorConfig GaussianFactorGraph::gradientDescent(const VectorConfig& x0) const {
|
||||||
|
VectorConfig x = x0;
|
||||||
|
int K = 10*x.size();
|
||||||
|
for (int k=0;k<K;k++) {
|
||||||
|
VectorConfig g = gradient(x);
|
||||||
|
x = optimalUpdate(x,g);
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
|
|
@ -162,8 +162,24 @@ namespace gtsam {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate Gradient of 0.5*|Ax-b| for a given config
|
* Calculate Gradient of 0.5*|Ax-b| for a given config
|
||||||
|
* @param x: VectorConfig specifying where to calculate gradient
|
||||||
|
* @return gradient, as a VectorConfig as well
|
||||||
*/
|
*/
|
||||||
VectorConfig gradient(const VectorConfig& x) const;
|
VectorConfig gradient(const VectorConfig& x) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take an optimal step in direction d by calculating optimal step-size
|
||||||
|
* @param x: starting point for search
|
||||||
|
* @param d: search direction
|
||||||
|
*/
|
||||||
|
VectorConfig optimalUpdate(const VectorConfig& x0, const VectorConfig& d) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find solution using gradient descent
|
||||||
|
* @param x0: VectorConfig specifying initial estimate
|
||||||
|
* @return solution
|
||||||
|
*/
|
||||||
|
VectorConfig gradientDescent(const VectorConfig& x0) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -565,6 +565,22 @@ TEST( GaussianFactorGraph, gradient )
|
||||||
CHECK(assert_equal(zero,actual2));
|
CHECK(assert_equal(zero,actual2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
TEST( GaussianFactorGraph, gradientDescent )
|
||||||
|
{
|
||||||
|
// Expected solution
|
||||||
|
Ordering ord;
|
||||||
|
ord += "x2","l1","x1";
|
||||||
|
GaussianFactorGraph fg = createGaussianFactorGraph();
|
||||||
|
VectorConfig expected = fg.optimize(ord); // destructive
|
||||||
|
|
||||||
|
// Do gradient descent
|
||||||
|
GaussianFactorGraph fg2 = createGaussianFactorGraph();
|
||||||
|
VectorConfig zero = createZeroDelta();
|
||||||
|
VectorConfig actual = fg2.gradientDescent(zero);
|
||||||
|
CHECK(assert_equal(expected,actual,1e-2));
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
// Tests ported from ConstrainedGaussianFactorGraph
|
// Tests ported from ConstrainedGaussianFactorGraph
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
Loading…
Reference in New Issue