/** * @file IntersectionKernelFunction.cpp * @brief The intersection kernel function as distance measure between two histograms interpreted as vectors (Implementation) * @author Alexander Freytag * @date 08-12-2011 (dd-mm-yyyy) */ #include "IntersectionKernelFunction.h" #include using namespace NICE; template double IntersectionKernelFunction::measureDistance ( const std::vector & a, const std::vector & b ) { int size( (int) a.size()); if ((int) b.size() < size) size = (int) b.size(); double distance(0.0); for (int i = 0; i < size; i++) { if ( a[i] < b[i]) distance += (double) a[i]; else distance += (double) b[i]; } return distance; } template NICE::Matrix IntersectionKernelFunction::computeKernelMatrix ( const std::vector > & X ) { NICE::Matrix K; K.resize((int) X.size(), (int) X.size()); double valTmp; for (int i = 0; i < (int) X.size(); i++) { for (int j = i; j < (int) X.size(); j++) { valTmp = measureDistance(X[i],X[j]); //Kernel matrix has to be symmetric K(i,j) = valTmp; //kernel-matrix has to be symmetric, but avoid adding twice the value to the main-diagonal if ( i != j) K(j,i) = valTmp; } } return K; } template NICE::Matrix IntersectionKernelFunction::computeKernelMatrix ( const std::vector > & X , const double & noise) { NICE::Matrix K(computeKernelMatrix(X)); for (int i = 0; i < (int) X.size(); i++) K(i,i) += noise; return K; } template NICE::Matrix IntersectionKernelFunction::computeKernelMatrix ( const NICE::FeatureMatrixT & X , const double & noise) { NICE::Matrix K; K.resize(X.get_n(), X.get_n()); K.set(0.0); //run over every dimension and add the corresponding min-values to the entries in the kernel matrix for (int dim = 0; dim < X.get_d(); dim++) { const std::multimap< double, typename SortedVectorSparse::dataelement> & nonzeroElements = X.getFeatureValues(dim).nonzeroElements(); //compute the min-values (similarities) between every pair in this dimension, zero elements do not influence this SortedVectorSparse::const_elementpointer it1 = nonzeroElements.begin(); for (; it1 != nonzeroElements.end(); it1++) { int i(it1->second.first); SortedVectorSparse::const_elementpointer it2 = it1; for (; it2 != nonzeroElements.end(); it2++) { int j(it2->second.first); double val(std::min(it1->second.second, it2->second.second)); K(i,j) += val; //kernel-matrix has to be symmetric, but avoid adding twice the value to the main-diagonal if ( i != j) K(j,i) += val; } // for-j-loop } // for-i-loop }//dim-loop //add noise on the main diagonal for (int i = 0; i < (int) X.get_n(); i++) K(i,i) += noise; return K; } template std::vector IntersectionKernelFunction::computeKernelVector ( const std::vector > & X , const std::vector & xstar) { std::vector kstar; kstar.resize((int) X.size()); for (int i = 0; i < (int) X.size(); i++) { kstar[i] = measureDistance(X[i], xstar); } return kstar; } template IntersectionKernelFunction::IntersectionKernelFunction() { } template IntersectionKernelFunction::~IntersectionKernelFunction() { } template double IntersectionKernelFunction::measureDistance ( const NICE::SparseVector & a, const NICE::SparseVector & b ) { double distance(0.0); for (NICE::SparseVector::const_iterator itA = a.begin(); itA != a.end(); itA++) { NICE::SparseVector::const_iterator itB = b.find(itA->first); if (itB != b.end()) distance += std::min(itA->second , itB->second); } return distance; } template NICE::Matrix IntersectionKernelFunction::computeKernelMatrix ( const std::vector & X , const double & noise) { std::cerr << "compute Kernel Matrix with vector of sparse vectors called " << std::endl; NICE::Matrix K; std::cerr << "NICE::Matrix initialized" << std::endl; std::cerr << "now perform the resize to: "<< X.size() << std::endl; K.resize(X.size(), X.size()); std::cerr << "NICE::matrix set to size : " << X.size() << std::endl; K.set(0.0); std::cerr << "set entries to zero" << std::endl; std::cerr << "compute Kernel Matrix" << std::endl; for (int i = 0; i < X.size(); i++) { std::cerr << i << " / " << X.size() << std::endl; for (int j = i; j < X.size(); j++) { K(i,j) = measureDistance(X[i],X[j]); if (i!=j) K(j,i) = K(i,j); } } std::cerr << "compute kernel matrix done" << std::endl; //add noise on the main diagonal for (int i = 0; i < (int) X.size(); i++) K(i,i) += noise; return K; } template NICE::Vector IntersectionKernelFunction::computeKernelVector ( const std::vector & X , const NICE::SparseVector & xstar) { NICE::Vector kstar; kstar.resize((int) X.size()); if (X.size() > 0) { for (int i = 0; i < (int) X.size(); i++) { kstar[i] = measureDistance(X[i], xstar); } } return kstar; } template void IntersectionKernelFunction::sayYourName() { std::cerr << "I'm the Intersection Kernel." << std::endl; }