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
 | 
			
		||||
	Vector e = -b_;
 | 
			
		||||
  string j; Matrix Aj;
 | 
			
		||||
  FOREACH_PAIR(j, Aj, As_) e += Vector(Aj * x[j]);
 | 
			
		||||
  FOREACH_PAIR(j, Aj, As_) e += Aj * x[j];
 | 
			
		||||
 | 
			
		||||
  // transpose
 | 
			
		||||
  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 {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,6 +58,13 @@ public:
 | 
			
		|||
		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 */
 | 
			
		||||
	GaussianFactor(const std::string& key1, const Matrix& A1,
 | 
			
		||||
			const std::string& key2, const Matrix& A2,
 | 
			
		||||
| 
						 | 
				
			
			@ -207,6 +214,20 @@ public:
 | 
			
		|||
	boost::tuple<std::list<int>, std::list<int>, std::list<double> >
 | 
			
		||||
		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
 | 
			
		||||
	/* ************************************************************************* */
 | 
			
		||||
| 
						 | 
				
			
			@ -243,13 +264,6 @@ public:
 | 
			
		|||
	 */
 | 
			
		||||
	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
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
  	 * @param x: VectorConfig specifying where to calculate gradient
 | 
			
		||||
  	 * @return gradient, as a VectorConfig as well
 | 
			
		||||
  	 */
 | 
			
		||||
  	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));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
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
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue