Files
secondo/Algebras/ImageSimilarity/fast_kmeans/kernel_kmeans.cpp
2026-01-23 17:03:45 +08:00

144 lines
3.7 KiB
C++

/*
----
This file is NOT part of SECONDO.
Authors: Greg Hamerly and Jonathan Drake
Feedback: hamerly@cs.baylor.edu
See: http://cs.baylor.edu/~hamerly/software/kmeans.php
Copyright 2014
----
//paragraph [1] Title: [{\Large \bf \begin{center}] [\end{center}}]
//[TOC] [\tableofcontents]
[1] Declarations for the kernel kmeans algorithm
1 Declarations for the kernel kmeans algorithm
*/
/* Authors: Greg Hamerly and Jonathan Drake
* Feedback: hamerly@cs.baylor.edu
* See: http://cs.baylor.edu/~hamerly/software/kmeans.php
* Copyright 2014
*/
#include "kernel_kmeans.h"
#include <cassert>
KernelKmeans::KernelKmeans(Kernel const *k) : kernel(*k) {
#ifdef USE_THREADS
convergenceLock = NULL;
#endif
}
void KernelKmeans::initialize(Dataset const *aX, unsigned short aK,
unsigned short *initialAssignment, int aNumThreads) {
Kmeans::initialize(aX, aK, initialAssignment, aNumThreads);
cc.resize(k);
memberships.clear();
memberships.resize(k);
#ifdef USE_THREADS
convergenceLock = new pthread_mutex_t;
pthread_mutex_init(convergenceLock, NULL);
clusterLocks.resize(k);
for (int j = 0; j < k; ++j) {
pthread_mutex_init(&clusterLocks[j], NULL);
}
#endif
}
void KernelKmeans::free() {
Kmeans::free();
cc.clear();
memberships.clear();
#ifdef USE_THREADS
if (convergenceLock) {
pthread_mutex_destroy(convergenceLock);
delete convergenceLock;
convergenceLock = NULL;
}
#endif
}
double KernelKmeans::centerCenterInnerProductGeneral(
std::vector<unsigned int> const &members1,
std::vector<unsigned int> const &members2) const {
double s = 0.0;
std::vector<unsigned int>::const_iterator i, j;
if (&members1 == &members2) {
for (i = members1.begin(); i != members1.end(); ++i) {
s += kernel(x->data + *i * d, x->data + *i * d, d);
for (j = i + 1; j != members1.end(); ++j) {
s += 2.0 * kernel(x->data + *i * d, x->data + *j * d, d);
}
}
} else {
for (i = members1.begin(); i != members1.end(); ++i) {
for (j = members2.begin(); j != members2.end(); ++j) {
s += kernel(x->data + *i * d, x->data + *j * d, d);
}
}
}
size_t n = members1.size() * members2.size();
if (n > 0) { s /= n; }
return s;
}
double KernelKmeans::pointCenterInnerProductGeneral(int i,
std::vector<unsigned int> const &members) const {
double s = 0.0;
std::vector<unsigned int>::const_iterator j;
for (j = members.begin(); j != members.end(); ++j) {
s += kernel(x->data + i * d, x->data + *j * d, d);
}
size_t n = members.size();
if (n > 0) { s /= n; }
return s;
}
void KernelKmeans::computeMemberships(int threadId,
std::vector<std::vector<unsigned int> > *membershipResult,
std::vector<double> *ccResult) {
std::vector<std::vector<unsigned int> > threadMemberships(k);
if (threadId == 0) {
for (int j = 0; j < k; ++j) {
membershipResult->at(j).clear();
}
}
synchronizeAllThreads();
for (int i = start(threadId); i < end(threadId); ++i) {
threadMemberships[assignment[i]].push_back(i);
}
synchronizeAllThreads();
for (int j = 0; j < k; ++j) {
lockCluster(j);
std::copy(threadMemberships[j].begin(),
threadMemberships[j].end(),
std::back_insert_iterator<std::vector<unsigned int> >(
membershipResult->at(j)));
unlockCluster(j);
}
synchronizeAllThreads();
for (int j = 0; j < k; ++j) {
if (j % numThreads == threadId) {
ccResult->at(j) = centerCenterInnerProductGeneral(
membershipResult->at(j), membershipResult->at(j));
}
}
}