135 lines
4.4 KiB
C++
135 lines
4.4 KiB
C++
// Copyright (C) 2012 Davis E. King (davis@dlib.net)
|
|
// License: Boost Software License See LICENSE.txt for the full license.
|
|
#ifndef DLIB_CHINESE_WHISPErS_Hh_
|
|
#define DLIB_CHINESE_WHISPErS_Hh_
|
|
|
|
#include "chinese_whispers_abstract.h"
|
|
#include <vector>
|
|
#include "../rand.h"
|
|
#include "../graph_utils/edge_list_graphs.h"
|
|
|
|
namespace dlib
|
|
{
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
inline unsigned long chinese_whispers (
|
|
const std::vector<ordered_sample_pair>& edges,
|
|
std::vector<unsigned long>& labels,
|
|
const unsigned long num_iterations,
|
|
dlib::rand& rnd
|
|
)
|
|
{
|
|
// make sure requires clause is not broken
|
|
DLIB_ASSERT(is_ordered_by_index(edges),
|
|
"\t unsigned long chinese_whispers()"
|
|
<< "\n\t Invalid inputs were given to this function"
|
|
);
|
|
|
|
labels.clear();
|
|
if (edges.size() == 0)
|
|
return 0;
|
|
|
|
std::vector<std::pair<unsigned long, unsigned long> > neighbors;
|
|
find_neighbor_ranges(edges, neighbors);
|
|
|
|
// Initialize the labels, each node gets a different label.
|
|
labels.resize(neighbors.size());
|
|
for (unsigned long i = 0; i < labels.size(); ++i)
|
|
labels[i] = i;
|
|
|
|
|
|
for (unsigned long iter = 0; iter < neighbors.size()*num_iterations; ++iter)
|
|
{
|
|
// Pick a random node.
|
|
const unsigned long idx = rnd.get_random_64bit_number()%neighbors.size();
|
|
|
|
// Count how many times each label happens amongst our neighbors.
|
|
std::map<unsigned long, double> labels_to_counts;
|
|
const unsigned long end = neighbors[idx].second;
|
|
for (unsigned long i = neighbors[idx].first; i != end; ++i)
|
|
{
|
|
labels_to_counts[labels[edges[i].index2()]] += edges[i].distance();
|
|
}
|
|
|
|
// find the most common label
|
|
std::map<unsigned long, double>::iterator i;
|
|
double best_score = -std::numeric_limits<double>::infinity();
|
|
unsigned long best_label = labels[idx];
|
|
for (i = labels_to_counts.begin(); i != labels_to_counts.end(); ++i)
|
|
{
|
|
if (i->second > best_score)
|
|
{
|
|
best_score = i->second;
|
|
best_label = i->first;
|
|
}
|
|
}
|
|
|
|
labels[idx] = best_label;
|
|
}
|
|
|
|
|
|
// Remap the labels into a contiguous range. First we find the
|
|
// mapping.
|
|
std::map<unsigned long,unsigned long> label_remap;
|
|
for (unsigned long i = 0; i < labels.size(); ++i)
|
|
{
|
|
const unsigned long next_id = label_remap.size();
|
|
if (label_remap.count(labels[i]) == 0)
|
|
label_remap[labels[i]] = next_id;
|
|
}
|
|
// now apply the mapping to all the labels.
|
|
for (unsigned long i = 0; i < labels.size(); ++i)
|
|
{
|
|
labels[i] = label_remap[labels[i]];
|
|
}
|
|
|
|
return label_remap.size();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
inline unsigned long chinese_whispers (
|
|
const std::vector<sample_pair>& edges,
|
|
std::vector<unsigned long>& labels,
|
|
const unsigned long num_iterations,
|
|
dlib::rand& rnd
|
|
)
|
|
{
|
|
std::vector<ordered_sample_pair> oedges;
|
|
convert_unordered_to_ordered(edges, oedges);
|
|
std::sort(oedges.begin(), oedges.end(), &order_by_index<ordered_sample_pair>);
|
|
|
|
return chinese_whispers(oedges, labels, num_iterations, rnd);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
inline unsigned long chinese_whispers (
|
|
const std::vector<sample_pair>& edges,
|
|
std::vector<unsigned long>& labels,
|
|
const unsigned long num_iterations = 100
|
|
)
|
|
{
|
|
dlib::rand rnd;
|
|
return chinese_whispers(edges, labels, num_iterations, rnd);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
inline unsigned long chinese_whispers (
|
|
const std::vector<ordered_sample_pair>& edges,
|
|
std::vector<unsigned long>& labels,
|
|
const unsigned long num_iterations = 100
|
|
)
|
|
{
|
|
dlib::rand rnd;
|
|
return chinese_whispers(edges, labels, num_iterations, rnd);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
}
|
|
|
|
#endif // DLIB_CHINESE_WHISPErS_Hh_
|
|
|