SparseWeightMatrix hlle_weight_matrix(RandomAccessIterator begin, RandomAccessIterator end, const Neighbors& neighbors, PairwiseCallback callback, unsigned int target_dimension) { timed_context context("KLTSA weight matrix computation"); const unsigned int k = neighbors[0].size(); SparseTriplets sparse_triplets; sparse_triplets.reserve(k*k*(end-begin)); RandomAccessIterator iter_begin = begin, iter_end = end; DenseMatrix gram_matrix = DenseMatrix::Zero(k,k); DenseVector col_means(k), row_means(k); DenseVector rhs = DenseVector::Ones(k); DenseMatrix G = DenseMatrix::Zero(k,target_dimension+1); RandomAccessIterator iter; for (iter=iter_begin; iter!=iter_end; ++iter) { const LocalNeighbors& current_neighbors = neighbors[iter-begin]; for (unsigned int i=0; i<k; ++i) { for (unsigned int j=i; j<k; ++j) { DefaultScalarType kij = callback(begin[current_neighbors[i]],begin[current_neighbors[j]]); gram_matrix(i,j) = kij; gram_matrix(j,i) = kij; } } for (unsigned int i=0; i<k; ++i) { col_means[i] = gram_matrix.col(i).mean(); row_means[i] = gram_matrix.row(i).mean(); } DefaultScalarType grand_mean = gram_matrix.mean(); gram_matrix.array() += grand_mean; gram_matrix.rowwise() -= col_means.transpose(); gram_matrix.colwise() -= row_means; DefaultDenseSelfAdjointEigenSolver sae_solver; sae_solver.compute(gram_matrix); G.col(0).setConstant(1/sqrt(DefaultScalarType(k))); G.rightCols(target_dimension).noalias() = sae_solver.eigenvectors().rightCols(target_dimension); gram_matrix = G * G.transpose(); sparse_triplets.push_back(SparseTriplet(iter-begin,iter-begin,1e-8)); for (unsigned int i=0; i<k; ++i) { sparse_triplets.push_back(SparseTriplet(current_neighbors[i],current_neighbors[i],1.0)); for (unsigned int j=0; j<k; ++j) sparse_triplets.push_back(SparseTriplet(current_neighbors[i],current_neighbors[j], -gram_matrix(i,j))); } } SparseWeightMatrix weight_matrix(end-begin,end-begin); weight_matrix.setFromTriplets(sparse_triplets.begin(),sparse_triplets.end()); return weight_matrix; };
SparseWeightMatrix kltsa_weight_matrix(RandomAccessIterator begin, RandomAccessIterator end, const Neighbors& neighbors, PairwiseCallback callback, unsigned int target_dimension, DefaultScalarType shift, bool partial_eigendecomposer=false) { timed_context context("KLTSA weight matrix computation"); const unsigned int k = neighbors[0].size(); SparseTriplets sparse_triplets; sparse_triplets.reserve((k*k+k+1)*(end-begin)); RandomAccessIterator iter; RandomAccessIterator iter_begin = begin, iter_end = end; DenseMatrix gram_matrix = DenseMatrix::Zero(k,k); DenseVector col_means(k), row_means(k); DenseVector rhs = DenseVector::Ones(k); DenseMatrix G = DenseMatrix::Zero(k,target_dimension+1); G.col(0).setConstant(1/sqrt(DefaultScalarType(k))); DefaultDenseSelfAdjointEigenSolver solver; RESTRICT_ALLOC; //#pragma omp parallel for private(iter,gram_matrix,G) for (iter=iter_begin; iter<iter_end; ++iter) { const LocalNeighbors& current_neighbors = neighbors[iter-begin]; for (unsigned int i=0; i<k; ++i) { for (unsigned int j=i; j<k; ++j) { DefaultScalarType kij = callback(begin[current_neighbors[i]],begin[current_neighbors[j]]); gram_matrix(i,j) = kij; gram_matrix(j,i) = kij; } } col_means = gram_matrix.colwise().mean(); DefaultScalarType grand_mean = gram_matrix.mean(); gram_matrix.array() += grand_mean; gram_matrix.rowwise() -= col_means.transpose(); gram_matrix.colwise() -= col_means; UNRESTRICT_ALLOC; if (partial_eigendecomposer) { G.rightCols(target_dimension).noalias() = eigen_embedding<DenseMatrix,DenseMatrixOperation>(ARPACK,gram_matrix,target_dimension,0).first; } else { solver.compute(gram_matrix); G.rightCols(target_dimension).noalias() = solver.eigenvectors().rightCols(target_dimension); } RESTRICT_ALLOC; gram_matrix.noalias() = G * G.transpose(); sparse_triplets.push_back(SparseTriplet(iter-begin,iter-begin,shift)); for (unsigned int i=0; i<k; ++i) { sparse_triplets.push_back(SparseTriplet(current_neighbors[i],current_neighbors[i],1.0)); for (unsigned int j=0; j<k; ++j) sparse_triplets.push_back(SparseTriplet(current_neighbors[i],current_neighbors[j], -gram_matrix(i,j))); } } UNRESTRICT_ALLOC; SparseWeightMatrix weight_matrix(end-begin,end-begin); weight_matrix.setFromTriplets(sparse_triplets.begin(),sparse_triplets.end()); return weight_matrix; }
SparseWeightMatrix tangent_weight_matrix(RandomAccessIterator begin, RandomAccessIterator end, const Neighbors& neighbors, PairwiseCallback callback, const IndexType target_dimension, const ScalarType shift, const bool partial_eigendecomposer=false) { timed_context context("KLTSA weight matrix computation"); const IndexType k = neighbors[0].size(); SparseTriplets sparse_triplets; sparse_triplets.reserve((k*k+2*k+1)*(end-begin)); #pragma omp parallel shared(begin,end,neighbors,callback,sparse_triplets) default(none) { IndexType index_iter; DenseMatrix gram_matrix = DenseMatrix::Zero(k,k); DenseVector rhs = DenseVector::Ones(k); DenseMatrix G = DenseMatrix::Zero(k,target_dimension+1); G.col(0).setConstant(1/sqrt(static_cast<ScalarType>(k))); DenseSelfAdjointEigenSolver solver; SparseTriplets local_triplets; local_triplets.reserve(k*k+2*k+1); #pragma omp for nowait for (index_iter=0; index_iter<static_cast<IndexType>(end-begin); index_iter++) { const LocalNeighbors& current_neighbors = neighbors[index_iter]; for (IndexType i=0; i<k; ++i) { for (IndexType j=i; j<k; ++j) { ScalarType kij = callback.kernel(begin[current_neighbors[i]],begin[current_neighbors[j]]); gram_matrix(i,j) = kij; gram_matrix(j,i) = kij; } } centerMatrix(gram_matrix); //UNRESTRICT_ALLOC; #ifdef TAPKEE_WITH_ARPACK if (partial_eigendecomposer) { G.rightCols(target_dimension).noalias() = eigendecomposition<DenseMatrix,DenseMatrixOperation>(Arpack,gram_matrix,target_dimension,0).first; } else #endif { solver.compute(gram_matrix); G.rightCols(target_dimension).noalias() = solver.eigenvectors().rightCols(target_dimension); } //RESTRICT_ALLOC; gram_matrix.noalias() = G * G.transpose(); SparseTriplet diagonal_triplet(index_iter,index_iter,shift); local_triplets.push_back(diagonal_triplet); for (IndexType i=0; i<k; ++i) { SparseTriplet neighborhood_diagonal_triplet(current_neighbors[i],current_neighbors[i],1.0); local_triplets.push_back(neighborhood_diagonal_triplet); for (IndexType j=0; j<k; ++j) { SparseTriplet tangent_triplet(current_neighbors[i],current_neighbors[j],-gram_matrix(i,j)); local_triplets.push_back(tangent_triplet); } } #pragma omp critical { copy(local_triplets.begin(),local_triplets.end(),back_inserter(sparse_triplets)); } local_triplets.clear(); } } return sparse_matrix_from_triplets(sparse_triplets, end-begin, end-begin); }