Added the basis training for the local expansion of the leaf nodes.

This commit is contained in:
Dongryeol Lee
2008-05-19 17:29:29 +00:00
parent b6ae9bc873
commit cc8a692a9a
3 changed files with 81 additions and 5 deletions
@@ -28,7 +28,7 @@ void MatrixFactorizedFarFieldExpansion<TKernelAux>::AccumulateCoeffs
// query samples taken from the stratification.
Matrix sample_kernel_matrix;
int num_reference_samples = (int) sqrt(end - begin);
int num_query_samples = (int) query_leaf_nodes->size();
int num_query_samples = query_leaf_nodes->size();
// Allocate a temporary space for holding the indices of the
// reference points, from which the outgoing skeleton will be
@@ -27,10 +27,10 @@ class MatrixFactorizedLocalExpansion {
*/
Vector coeffs_;
/** @brief The incoming representation: the pseudo-distribution
* which is defined only for leaf nodes.
/** @brief The evaluation operator: the pseudo-distribution which is
* defined only for leaf nodes.
*/
Vector *incoming_representation_;
Matrix *evaluation_operator_;
/** @brief The query point indices that form the incoming skeleton,
* the pseudo-points that represent the query point
@@ -67,7 +67,7 @@ class MatrixFactorizedLocalExpansion {
OT_DEF(MatrixFactorizedLocalExpansion) {
OT_MY_OBJECT(coeffs_);
OT_PTR_NULLABLE(incoming_representation_);
OT_PTR_NULLABLE(evaluation_operator_);
OT_MY_OBJECT(incoming_skeleton_);
OT_MY_OBJECT(local_to_local_translation_begin_);
OT_MY_OBJECT(local_to_local_translation_count_);
@@ -80,7 +80,83 @@ void MatrixFactorizedLocalExpansion<TKernelAux>::TrainBasisFunctions
(const Matrix &query_set, int begin, int end, const Matrix *reference_set,
const ArrayList<Tree *> *reference_leaf_nodes) {
// The sample kernel matrix is |Q| by S where |Q| is the number of
// query points in the query node and S is the number of reference
// samples taken from the stratification.
Matrix sample_kernel_matrix;
int num_reference_samples = reference_leaf_nodes->size();
int num_query_samples = (int) sqrt(end - begin);
// Allocate a temporary space for holding the indices of the query
// points, from which the incoming skeleton will be chosen.
ArrayList<index_t> tmp_incoming_skeleton;
tmp_incoming_skeleton.Init(num_query_samples);
for(index_t q = 0; q < num_query_samples; q++) {
// Choose a random query point and record its index.
index_t random_query_point_index = math::RandInt(begin, end);
tmp_incoming_skeleton[r] = random_query_point_index;
}
// Sort the chosen query indices and eliminate duplicates...
qsort(tmp_incoming_skeleton.begin(), tmp_incoming_skeleton.size(),
sizeof(index_t), &qsort_compar_);
remove_duplicates_in_sorted_array_(tmp_incoming_skeleton);
num_query_samples = tmp_incoming_skeleton.size();
// After determining the number of query samples to take,
// allocate the space for the sample kernel matrix to be computed.
sample_kernel_matrix.Init(num_query_samples, num_reference_samples);
for(index_t r = 0; r < num_reference_samples; r++) {
// Choose a random reference point from the current reference strata...
index_t random_reference_point_index =
math::RandInt(((*reference_leaf_nodes)[r])->begin(),
((*reference_leaf_nodes)[r])->end());
const double *reference_point =
reference_set.GetColumnPtr(random_reference_point_index);
for(index_t c = 0; c < num_query_samples; c++) {
// The current query point
const double *query_point =
query_set->GetColumnPtr(tmp_incoming_skeleton[c]);
// Compute the pairwise distance and the kernel value.
double squared_distance =
la::DistanceSqEuclidean(reference_set.n_rows(), reference_point,
query_point);
sample_kernel_matrix.set
(c, r, (ka_->kernel_).EvalUnnormOnSq(squared_distance));
} // end of iterating over each sample query strata...
} // end of iterating over each reference point...
// CUR-decompose the sample kernel matrix.
Matrix c_mat, u_mat, r_mat;
ArrayList<index_t> column_indices, row_indices;
CURDecomposition::Compute(sample_kernel_matrix, &c_mat, &u_mat, &r_mat,
&column_indices, &row_indices);
// The incoming skeleton is constructed from the sampled rows in the
// matrix factorization.
incoming_skeleton_ = new ArrayList<index_t>();
incoming_skeleton_->Init(row_indices.size());
for(index_t s = 0; s < row_indices.size(); s++) {
(*incoming_skeleton_)[s] = tmp_incoming_skeleton[row_incides[s]];
}
// Compute the evaluation operator, which is the product of the C
// and the U factor appropriately scaled by the row scaled R factor.
la::MulInit(c_mat, u_mat, evaluation_operator_);
for(index_t i = 0; i < r_mat.n_rows(); i++) {
double scaling_factor =
(sample_kernel_matrix.get(row_indices[i], 0) < DBL_EPSILON) ?
0:r_mat.get(i, 0) / sample_kernel_matrix.get(row_indices[i], 0);
la::Scale(evaluation_operator_->n_rows(), scaling_factor,
evaluation_operator_->GetColumnPtr(i));
}
}
template<typename TKernelAux>