Finished the pruning rule
This commit is contained in:
@@ -1,7 +1,11 @@
|
||||
/** @file local_linear_krylov.h
|
||||
*
|
||||
* This implementation can handle only non-negative training target
|
||||
* values and points that lie the positive quadrant.
|
||||
*
|
||||
* @author Dongryeol Lee (dongryel@cc.gatech.edu)
|
||||
* @see local_linear_krylov_main.cc
|
||||
*
|
||||
* @bug No known bugs.
|
||||
*/
|
||||
|
||||
@@ -62,7 +66,12 @@ class LocalLinearKrylov {
|
||||
|
||||
/** @brief The data weighted by the target values. */
|
||||
Vector sum_targets_weighted_by_data_;
|
||||
|
||||
|
||||
/** @brief The 1-norm of the vector containing the target values
|
||||
* weighted by the data.
|
||||
*/
|
||||
double l1_norm_sum_targets_weighted_by_data_;
|
||||
|
||||
/** @brief The bounding box for the solution vectors. */
|
||||
DHrectBound<2> bound_for_solutions_;
|
||||
|
||||
@@ -91,6 +100,8 @@ class LocalLinearKrylov {
|
||||
postponed_right_hand_sides_u_.Init(dimension + 1);
|
||||
sum_targets_weighted_by_data_.Init(dimension + 1);
|
||||
bound_for_solutions_.Init(dimension + 1);
|
||||
|
||||
l1_norm_sum_targets_weighted_by_data_ = 0;
|
||||
}
|
||||
|
||||
/** @brief Computing the statistics for a leaf node involves
|
||||
@@ -120,6 +131,9 @@ class LocalLinearKrylov {
|
||||
|
||||
////////// Private Member Variables //////////
|
||||
|
||||
/** @brief The required relative error. */
|
||||
double relative_error_;
|
||||
|
||||
/** @brief The module holding the list of parameters. */
|
||||
struct datanode *module_;
|
||||
|
||||
@@ -196,6 +210,10 @@ class LocalLinearKrylov {
|
||||
*/
|
||||
int num_finite_difference_prunes_;
|
||||
|
||||
/** @brief Temporary variable for holding newly refined lower bound.
|
||||
*/
|
||||
Vector new_right_hand_sides_l_;
|
||||
|
||||
/** @brief Temporary variable for holding lower bound change made
|
||||
* during a prune.
|
||||
*/
|
||||
@@ -212,6 +230,18 @@ class LocalLinearKrylov {
|
||||
|
||||
////////// Private Member Functions //////////
|
||||
|
||||
/** @brief Compute the L1 norm of the given vector.
|
||||
*/
|
||||
double L1Norm_(Vector &v) {
|
||||
|
||||
double norm = 0;
|
||||
|
||||
for(index_t i = 0; i < v.length(); i++) {
|
||||
norm += fabs(v[i]);
|
||||
}
|
||||
return norm;
|
||||
}
|
||||
|
||||
/** @brief Determine which of the node to expand first.
|
||||
*/
|
||||
void BestNodePartners_(Tree *nd, Tree *nd1, Tree *nd2, Tree **partner1,
|
||||
@@ -231,7 +261,7 @@ class LocalLinearKrylov {
|
||||
}
|
||||
|
||||
bool PrunableRightHandSides_(Tree *qnode, Tree *rnode, DRange &dsqd_range,
|
||||
DRange &kernel_value_range);
|
||||
DRange &kernel_value_range, double &used_error);
|
||||
|
||||
/** @brief The base-case exhaustive computation for dual-tree based
|
||||
* computation of B^T W(q) Y.
|
||||
@@ -324,6 +354,9 @@ class LocalLinearKrylov {
|
||||
regression_estimates_.SetZero();
|
||||
num_finite_difference_prunes_ = 0;
|
||||
|
||||
// Set relative error.
|
||||
relative_error_ = fx_param_double(module_, "relative_error", 0.01);
|
||||
|
||||
// The computation proceeds in three phases:
|
||||
//
|
||||
// Phase 1: Compute B^T W(q) Y vector for each query point.
|
||||
@@ -397,6 +430,7 @@ class LocalLinearKrylov {
|
||||
right_hand_sides_u_.Init(row_length_, qset_.n_cols());
|
||||
solution_vectors_.Init(row_length_, qset_.n_cols());
|
||||
regression_estimates_.Init(qset_.n_cols());
|
||||
new_right_hand_sides_l_.Init(row_length_);
|
||||
right_hand_sides_l_change_.Init(row_length_);
|
||||
right_hand_sides_e_change_.Init(row_length_);
|
||||
right_hand_sides_u_change_.Init(row_length_);
|
||||
|
||||
@@ -49,7 +49,7 @@ int main(int argc, char *argv[]) {
|
||||
// Declare local linear krylov object.
|
||||
LocalLinearKrylov<GaussianKernel> local_linear;
|
||||
local_linear.Init(queries, references, reference_targets,
|
||||
queries_equal_references, local_linear_module);
|
||||
queries_equal_references, local_linear_module);
|
||||
local_linear.Compute();
|
||||
|
||||
// Finalize FastExec and print output results.
|
||||
|
||||
@@ -6,9 +6,51 @@
|
||||
|
||||
template<typename TKernel>
|
||||
bool LocalLinearKrylov<TKernel>::PrunableRightHandSides_
|
||||
(Tree *qnode, Tree *rnode, DRange &dsqd_range, DRange &kernel_value_range) {
|
||||
(Tree *qnode, Tree *rnode, DRange &dsqd_range, DRange &kernel_value_range,
|
||||
double &used_error) {
|
||||
|
||||
// try pruning after bound refinement: first compute distance/kernel
|
||||
// value bounds
|
||||
dsqd_range.lo = qnode->bound().MinDistanceSq(rnode->bound());
|
||||
dsqd_range.hi = qnode->bound().MaxDistanceSq(rnode->bound());
|
||||
kernel_value_range = kernel_.RangeUnnormOnSq(dsqd_range);
|
||||
|
||||
// Compute the vector component lower and upper bound changes. This
|
||||
// assumes that the maximum kernel value is 1.
|
||||
la::ScaleOverwrite(kernel_value_range.lo,
|
||||
rnode->stat().sum_targets_weighted_by_data_,
|
||||
&right_hand_sides_l_change_);
|
||||
la::ScaleOverwrite(0.5 * (kernel_value_range.lo +
|
||||
kernel_value_range.hi),
|
||||
rnode->stat().sum_targets_weighted_by_data_,
|
||||
&right_hand_sides_e_change_);
|
||||
la::ScaleOverwrite((kernel_value_range.hi - 1.0),
|
||||
rnode->stat().sum_targets_weighted_by_data_,
|
||||
&right_hand_sides_u_change_);
|
||||
|
||||
// Refine the lower bound based on the current postponed lower bound
|
||||
// change and the newly gained refinement due to comparing the
|
||||
// current query and reference node pair.
|
||||
la::AddOverwrite(qnode->stat().right_hand_sides_l_,
|
||||
qnode->stat().postponed_right_hand_sides_l_,
|
||||
&new_right_hand_sides_l_);
|
||||
la::AddTo(right_hand_sides_l_change_, &new_right_hand_sides_l_);
|
||||
|
||||
// Compute the L1 norm of the most refined lower bound.
|
||||
double l1_norm_new_right_hand_sides_l_ = L1Norm_(new_right_hand_sides_l_);
|
||||
|
||||
// Compute the allowed amount of error for pruning the given query
|
||||
// and reference pair.
|
||||
double allowed_err =
|
||||
(relative_error_ * (rnode->stat().l1_norm_sum_targets_weighted_by_data_) *
|
||||
l1_norm_new_right_hand_sides_l_) /
|
||||
(rroot_->stat().l1_norm_sum_targets_weighted_by_data_);
|
||||
|
||||
used_error = 0.5 * kernel_value_range.width() *
|
||||
(rnode->stat().l1_norm_sum_targets_weighted_by_data_);
|
||||
|
||||
return true;
|
||||
// check pruning condition
|
||||
return (used_error <= allowed_err);
|
||||
}
|
||||
|
||||
template<typename TKernel>
|
||||
@@ -95,13 +137,17 @@ void LocalLinearKrylov<TKernel>::DualtreeRightHandSidesBase_
|
||||
template<typename TKernel>
|
||||
void LocalLinearKrylov<TKernel>::DualtreeRightHandSidesCanonical_
|
||||
(Tree *qnode, Tree *rnode) {
|
||||
|
||||
|
||||
// Total amount of used error
|
||||
double used_error;
|
||||
|
||||
// temporary variable for holding distance/kernel value bounds
|
||||
DRange dsqd_range;
|
||||
DRange kernel_value_range;
|
||||
|
||||
// try finite difference pruning first
|
||||
if(PrunableRightHandSides_(qnode, rnode, dsqd_range, kernel_value_range)) {
|
||||
if(PrunableRightHandSides_(qnode, rnode, dsqd_range, kernel_value_range,
|
||||
used_error)) {
|
||||
la::AddTo(right_hand_sides_l_change_,
|
||||
&(qnode->stat().postponed_right_hand_sides_l_));
|
||||
la::AddTo(right_hand_sides_e_change_,
|
||||
|
||||
Reference in New Issue
Block a user