Finished the pruning rule

This commit is contained in:
Dongryeol Lee
2008-02-04 02:13:35 +00:00
parent 80527d1c5d
commit 59fd0c075c
3 changed files with 87 additions and 7 deletions
@@ -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_,