[mlpack-svn] [MLPACK] #303: Interface for stochastic gradient descent

MLPACK Trac trac at coffeetalk-1.cc.gatech.edu
Sat Aug 24 13:38:42 EDT 2013


#303: Interface for stochastic gradient descent
--------------------------------------------------------+-------------------
  Reporter:  sumedhghaisas                              |        Owner:              
      Type:  enhancement                                |       Status:  closed      
  Priority:  major                                      |    Milestone:  mlpack 1.0.7
 Component:  mlpack                                     |   Resolution:  wontfix     
  Keywords:  stochastic gradient descent,C++ interface  |     Blocking:              
Blocked By:                                             |  
--------------------------------------------------------+-------------------
Changes (by rcurtin):

  * status:  new => closed
  * resolution:  => wontfix


Comment:

 Hello Sumedh,

 I think I am understanding your idea correctly: you want to provide a
 parent SGDFunction class, so that a user can overload some of the
 functionality.  Then, a user might not have to overload all of the
 functions.  This is the basic object-oriented class structure idea.

 Unfortunately, inheritance does have costs associated with it.  Each time
 I call SGDFunction::Evaluate(), there is a vtable lookup (basically, a
 pointer dereference) to get to the actual function that refers to whatever
 child class of SGDFunction's Evaluate() function.

 In the SGD method, the Evaluate() function is called millions and millions
 of times, and this means that the vtable lookup penalty actually becomes a
 significant cost.  The C++ technical report from around 2004 has some more
 information on vtable lookup penalties somewhere in it (I don't remember
 where).  So, instead of using inheritance, we use templated types.  This
 means that when SGD calls Evaluate(), there is no vtable lookup, because
 the function is bound statically at compile-time.

 For a user writing a function to plug into SGD, they have to refer to this
 documentation in sgd.hpp (or in the Doxygen documentation):

 {{{
 /**
  * ...
  * For SGD to work, a DecomposableFunctionType template parameter is
 required.
  * This class must implement the following function:
  *
  *   size_t NumFunctions();
  *   double Evaluate(const arma::mat& coordinates, const size_t i);
  *   void Gradient(const arma::mat& coordinates,
  *                 const size_t i,
  *                 arma::mat& gradient);
  *
  * NumFunctions() should return the number of functions (\f$n\f$), and in
 the
  * other two functions, the parameter i refers to which individual
 function (or
  * gradient) is being evaluated.  So, for the case of a data-dependent
 function,
  * such as NCA (see mlpack::nca::NCA), NumFunctions() should return the
 number
  * of points in the dataset, and Evaluate(coordinates, 0) will evaluate
 the
  * objective function on the first point in the dataset (presumably, the
 dataset
  * is held internally in the DecomposableFunctionType).
  */
 }}}

 Unfortunately, because C++11 Concepts were not a feature that was included
 in the new language standard, we don't have any way to "enforce" that
 someone writing a DecomposableFunctionType class will actually implement
 all of the methods they need.  The template-based approach we use instead
 gives horribly long, terrifying compiler messages.  But there's not really
 anything we can do about it and it's the price we have to pay to get the
 extra performance by avoiding the vtable lookup.  If you want to do more
 reading, a term to look for would be "policy-based design".

 Thanks,

 Ryan

-- 
Ticket URL: <http://trac.research.cc.gatech.edu/fastlab/ticket/303#comment:1>
MLPACK <www.fast-lab.org>
MLPACK is an intuitive, fast, and scalable C++ machine learning library developed at Georgia Tech.


More information about the mlpack-svn mailing list