float corr(Eigen::MatrixXf& v1, Eigen::MatrixXf& v2) { Eigen::MatrixXf v1c = centerMatrix(v1); Eigen::MatrixXf v2c = centerMatrix(v2); float v1Norm = v1c.col(0).norm(); float v2Norm = v2c.col(0).norm(); if (v1Norm == 0.0 || v2Norm == 0.0) { return 0.0; } float v1v2 = v1c.col(0).dot(v2c.col(0)); return v1v2 / (v1Norm * v2Norm); }
DenseSymmetricMatrix compute_centered_kernel_matrix(RandomAccessIterator begin, RandomAccessIterator end, KernelCallback callback) { timed_context context("Constructing kPCA centered kernel matrix"); DenseSymmetricMatrix kernel_matrix(end-begin,end-begin); for (RandomAccessIterator i_iter=begin; i_iter!=end; ++i_iter) { for (RandomAccessIterator j_iter=i_iter; j_iter!=end; ++j_iter) { DefaultScalarType k = callback(*i_iter,*j_iter); kernel_matrix(i_iter-begin,j_iter-begin) = k; kernel_matrix(j_iter-begin,i_iter-begin) = k; } } centerMatrix(kernel_matrix); return kernel_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); }
SparseWeightMatrix hessian_weight_matrix(RandomAccessIterator begin, RandomAccessIterator end, const Neighbors& neighbors, PairwiseCallback callback, const IndexType target_dimension) { timed_context context("Hessian weight matrix computation"); const IndexType k = neighbors[0].size(); SparseTriplets sparse_triplets; sparse_triplets.reserve(k*k*(end-begin)); const IndexType dp = target_dimension*(target_dimension+1)/2; #pragma omp parallel shared(begin,end,neighbors,callback,sparse_triplets) default(none) { IndexType index_iter; DenseMatrix gram_matrix = DenseMatrix::Zero(k,k); DenseMatrix Yi(k,1+target_dimension+dp); 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); DenseSelfAdjointEigenSolver sae_solver; sae_solver.compute(gram_matrix); Yi.col(0).setConstant(1.0); Yi.block(0,1,k,target_dimension).noalias() = sae_solver.eigenvectors().rightCols(target_dimension); IndexType ct = 0; for (IndexType j=0; j<target_dimension; ++j) { for (IndexType p=0; p<target_dimension-j; ++p) { Yi.col(ct+p+1+target_dimension).noalias() = Yi.col(j+1).cwiseProduct(Yi.col(j+p+1)); } ct += ct + target_dimension - j; } for (IndexType i=0; i<static_cast<IndexType>(Yi.cols()); i++) { for (IndexType j=0; j<i; j++) { ScalarType r = Yi.col(i).dot(Yi.col(j)); Yi.col(i) -= r*Yi.col(j); } ScalarType norm = Yi.col(i).norm(); Yi.col(i) *= (1.f / norm); } for (IndexType i=0; i<dp; i++) { ScalarType colsum = Yi.col(1+target_dimension+i).sum(); if (colsum > 1e-4) Yi.col(1+target_dimension+i).array() /= colsum; } // reuse gram matrix storage m'kay? gram_matrix.noalias() = Yi.rightCols(dp)*(Yi.rightCols(dp).transpose()); for (IndexType i=0; i<k; ++i) { for (IndexType j=0; j<k; ++j) { SparseTriplet hessian_triplet(current_neighbors[i],current_neighbors[j],gram_matrix(i,j)); local_triplets.push_back(hessian_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); }