summaryrefslogtreecommitdiffstats
path: root/ml/dlib/dlib/svm/structural_svm_graph_labeling_problem.h
diff options
context:
space:
mode:
Diffstat (limited to 'ml/dlib/dlib/svm/structural_svm_graph_labeling_problem.h')
-rw-r--r--ml/dlib/dlib/svm/structural_svm_graph_labeling_problem.h542
1 files changed, 0 insertions, 542 deletions
diff --git a/ml/dlib/dlib/svm/structural_svm_graph_labeling_problem.h b/ml/dlib/dlib/svm/structural_svm_graph_labeling_problem.h
deleted file mode 100644
index c677861c9..000000000
--- a/ml/dlib/dlib/svm/structural_svm_graph_labeling_problem.h
+++ /dev/null
@@ -1,542 +0,0 @@
-// Copyright (C) 2012 Davis E. King (davis@dlib.net)
-// License: Boost Software License See LICENSE.txt for the full license.
-#ifndef DLIB_STRUCTURAL_SVM_GRAPH_LAbELING_PROBLEM_Hh_
-#define DLIB_STRUCTURAL_SVM_GRAPH_LAbELING_PROBLEM_Hh_
-
-
-#include "structural_svm_graph_labeling_problem_abstract.h"
-#include "../graph_cuts.h"
-#include "../matrix.h"
-#include "../array.h"
-#include <vector>
-#include <iterator>
-#include "structural_svm_problem_threaded.h"
-#include "../graph.h"
-#include "sparse_vector.h"
-#include <sstream>
-
-// ----------------------------------------------------------------------------------------
-
-namespace dlib
-{
-
-// ----------------------------------------------------------------------------------------
-
- template <
- typename graph_type
- >
- bool is_graph_labeling_problem (
- const dlib::array<graph_type>& samples,
- const std::vector<std::vector<bool> >& labels,
- std::string& reason_for_failure
- )
- {
- typedef typename graph_type::type node_vector_type;
- typedef typename graph_type::edge_type edge_vector_type;
- // The graph must use all dense vectors or all sparse vectors. It can't mix the two types together.
- COMPILE_TIME_ASSERT( (is_matrix<node_vector_type>::value && is_matrix<edge_vector_type>::value) ||
- (!is_matrix<node_vector_type>::value && !is_matrix<edge_vector_type>::value));
-
-
- std::ostringstream sout;
- reason_for_failure.clear();
-
- if (!is_learning_problem(samples, labels))
- {
- reason_for_failure = "is_learning_problem(samples, labels) returned false.";
- return false;
- }
-
- const bool ismat = is_matrix<typename graph_type::type>::value;
-
- // these are -1 until assigned with a value
- long node_dims = -1;
- long edge_dims = -1;
-
- for (unsigned long i = 0; i < samples.size(); ++i)
- {
- if (samples[i].number_of_nodes() != labels[i].size())
- {
- sout << "samples["<<i<<"].number_of_nodes() doesn't match labels["<<i<<"].size().";
- reason_for_failure = sout.str();
- return false;
- }
- if (graph_contains_length_one_cycle(samples[i]))
- {
- sout << "graph_contains_length_one_cycle(samples["<<i<<"]) returned true.";
- reason_for_failure = sout.str();
- return false;
- }
-
- for (unsigned long j = 0; j < samples[i].number_of_nodes(); ++j)
- {
- if (ismat && samples[i].node(j).data.size() == 0)
- {
- sout << "A graph contains an empty vector at node: samples["<<i<<"].node("<<j<<").data.";
- reason_for_failure = sout.str();
- return false;
- }
-
- if (ismat && node_dims == -1)
- node_dims = samples[i].node(j).data.size();
- // all nodes must have vectors of the same size.
- if (ismat && (long)samples[i].node(j).data.size() != node_dims)
- {
- sout << "Not all node vectors in samples["<<i<<"] are the same dimension.";
- reason_for_failure = sout.str();
- return false;
- }
-
- for (unsigned long n = 0; n < samples[i].node(j).number_of_neighbors(); ++n)
- {
- if (ismat && samples[i].node(j).edge(n).size() == 0)
- {
- sout << "A graph contains an empty vector at edge: samples["<<i<<"].node("<<j<<").edge("<<n<<").";
- reason_for_failure = sout.str();
- return false;
- }
- if (min(samples[i].node(j).edge(n)) < 0)
- {
- sout << "A graph contains negative values on an edge vector at: samples["<<i<<"].node("<<j<<").edge("<<n<<").";
- reason_for_failure = sout.str();
- return false;
- }
-
- if (ismat && edge_dims == -1)
- edge_dims = samples[i].node(j).edge(n).size();
- // all edges must have vectors of the same size.
- if (ismat && (long)samples[i].node(j).edge(n).size() != edge_dims)
- {
- sout << "Not all edge vectors in samples["<<i<<"] are the same dimension.";
- reason_for_failure = sout.str();
- return false;
- }
- }
- }
- }
-
- return true;
- }
-
- template <
- typename graph_type
- >
- bool is_graph_labeling_problem (
- const dlib::array<graph_type>& samples,
- const std::vector<std::vector<bool> >& labels
- )
- {
- std::string reason_for_failure;
- return is_graph_labeling_problem(samples, labels, reason_for_failure);
- }
-
-// ----------------------------------------------------------------------------------------
-
- template <
- typename T,
- typename U
- >
- bool sizes_match (
- const std::vector<std::vector<T> >& lhs,
- const std::vector<std::vector<U> >& rhs
- )
- {
- if (lhs.size() != rhs.size())
- return false;
-
- for (unsigned long i = 0; i < lhs.size(); ++i)
- {
- if (lhs[i].size() != rhs[i].size())
- return false;
- }
-
- return true;
- }
-
-// ----------------------------------------------------------------------------------------
-
- inline bool all_values_are_nonnegative (
- const std::vector<std::vector<double> >& x
- )
- {
- for (unsigned long i = 0; i < x.size(); ++i)
- {
- for (unsigned long j = 0; j < x[i].size(); ++j)
- {
- if (x[i][j] < 0)
- return false;
- }
- }
- return true;
- }
-
-// ----------------------------------------------------------------------------------------
-// ----------------------------------------------------------------------------------------
-
- namespace impl
- {
- template <
- typename T,
- typename enable = void
- >
- struct fvect
- {
- // In this case type should be some sparse vector type
- typedef typename T::type type;
- };
-
- template < typename T >
- struct fvect<T, typename enable_if<is_matrix<typename T::type> >::type>
- {
- // The point of this stuff is to create the proper matrix
- // type to represent the concatenation of an edge vector
- // with an node vector.
- typedef typename T::type node_mat;
- typedef typename T::edge_type edge_mat;
- const static long NRd = node_mat::NR;
- const static long NRe = edge_mat::NR;
- const static long NR = ((NRd!=0) && (NRe!=0)) ? (NRd+NRe) : 0;
- typedef typename node_mat::value_type value_type;
-
- typedef matrix<value_type,NR,1, typename node_mat::mem_manager_type, typename node_mat::layout_type> type;
- };
- }
-
-// ----------------------------------------------------------------------------------------
-
- template <
- typename graph_type
- >
- class structural_svm_graph_labeling_problem : noncopyable,
- public structural_svm_problem_threaded<matrix<double,0,1>,
- typename dlib::impl::fvect<graph_type>::type >
- {
- public:
- typedef matrix<double,0,1> matrix_type;
- typedef typename dlib::impl::fvect<graph_type>::type feature_vector_type;
-
- typedef graph_type sample_type;
-
- typedef std::vector<bool> label_type;
-
- structural_svm_graph_labeling_problem(
- const dlib::array<sample_type>& samples_,
- const std::vector<label_type>& labels_,
- const std::vector<std::vector<double> >& losses_,
- unsigned long num_threads = 2
- ) :
- structural_svm_problem_threaded<matrix_type,feature_vector_type>(num_threads),
- samples(samples_),
- labels(labels_),
- losses(losses_)
- {
- // make sure requires clause is not broken
-#ifdef ENABLE_ASSERTS
- std::string reason_for_failure;
- DLIB_ASSERT(is_graph_labeling_problem(samples, labels, reason_for_failure) == true ,
- "\t structural_svm_graph_labeling_problem::structural_svm_graph_labeling_problem()"
- << "\n\t Invalid inputs were given to this function."
- << "\n\t reason_for_failure: " << reason_for_failure
- << "\n\t samples.size(): " << samples.size()
- << "\n\t labels.size(): " << labels.size()
- << "\n\t this: " << this );
- DLIB_ASSERT((losses.size() == 0 || sizes_match(labels, losses) == true) &&
- all_values_are_nonnegative(losses) == true,
- "\t structural_svm_graph_labeling_problem::structural_svm_graph_labeling_problem()"
- << "\n\t Invalid inputs were given to this function."
- << "\n\t labels.size(): " << labels.size()
- << "\n\t losses.size(): " << losses.size()
- << "\n\t sizes_match(labels,losses): " << sizes_match(labels,losses)
- << "\n\t all_values_are_nonnegative(losses): " << all_values_are_nonnegative(losses)
- << "\n\t this: " << this );
-#endif
-
- loss_pos = 1.0;
- loss_neg = 1.0;
-
- // figure out how many dimensions are in the node and edge vectors.
- node_dims = 0;
- edge_dims = 0;
- for (unsigned long i = 0; i < samples.size(); ++i)
- {
- for (unsigned long j = 0; j < samples[i].number_of_nodes(); ++j)
- {
- node_dims = std::max(node_dims,(long)max_index_plus_one(samples[i].node(j).data));
- for (unsigned long n = 0; n < samples[i].node(j).number_of_neighbors(); ++n)
- {
- edge_dims = std::max(edge_dims, (long)max_index_plus_one(samples[i].node(j).edge(n)));
- }
- }
- }
- }
-
- const std::vector<std::vector<double> >& get_losses (
- ) const { return losses; }
-
- long get_num_edge_weights (
- ) const
- {
- return edge_dims;
- }
-
- void set_loss_on_positive_class (
- double loss
- )
- {
- // make sure requires clause is not broken
- DLIB_ASSERT(loss >= 0 && get_losses().size() == 0,
- "\t void structural_svm_graph_labeling_problem::set_loss_on_positive_class()"
- << "\n\t Invalid inputs were given to this function."
- << "\n\t loss: " << loss
- << "\n\t this: " << this );
-
- loss_pos = loss;
- }
-
- void set_loss_on_negative_class (
- double loss
- )
- {
- // make sure requires clause is not broken
- DLIB_ASSERT(loss >= 0 && get_losses().size() == 0,
- "\t void structural_svm_graph_labeling_problem::set_loss_on_negative_class()"
- << "\n\t Invalid inputs were given to this function."
- << "\n\t loss: " << loss
- << "\n\t this: " << this );
-
- loss_neg = loss;
- }
-
- double get_loss_on_negative_class (
- ) const
- {
- // make sure requires clause is not broken
- DLIB_ASSERT(get_losses().size() == 0,
- "\t double structural_svm_graph_labeling_problem::get_loss_on_negative_class()"
- << "\n\t Invalid inputs were given to this function."
- << "\n\t this: " << this );
-
- return loss_neg;
- }
-
- double get_loss_on_positive_class (
- ) const
- {
- // make sure requires clause is not broken
- DLIB_ASSERT(get_losses().size() == 0,
- "\t double structural_svm_graph_labeling_problem::get_loss_on_positive_class()"
- << "\n\t Invalid inputs were given to this function."
- << "\n\t this: " << this );
-
- return loss_pos;
- }
-
-
- private:
- virtual long get_num_dimensions (
- ) const
- {
- // The psi/w vector will begin with all the edge dims and then follow with the node dims.
- return edge_dims + node_dims;
- }
-
- virtual long get_num_samples (
- ) const
- {
- return samples.size();
- }
-
- template <typename psi_type>
- typename enable_if<is_matrix<psi_type> >::type get_joint_feature_vector (
- const sample_type& sample,
- const label_type& label,
- psi_type& psi
- ) const
- {
- psi.set_size(get_num_dimensions());
- psi = 0;
- for (unsigned long i = 0; i < sample.number_of_nodes(); ++i)
- {
- // accumulate the node vectors
- if (label[i] == true)
- set_rowm(psi, range(edge_dims, psi.size()-1)) += sample.node(i).data;
-
- for (unsigned long n = 0; n < sample.node(i).number_of_neighbors(); ++n)
- {
- const unsigned long j = sample.node(i).neighbor(n).index();
-
- // Don't double count edges. Also only include the vector if
- // the labels disagree.
- if (i < j && label[i] != label[j])
- {
- set_rowm(psi, range(0, edge_dims-1)) -= sample.node(i).edge(n);
- }
- }
- }
- }
-
- template <typename T>
- void add_to_sparse_vect (
- T& psi,
- const T& vect,
- unsigned long offset
- ) const
- {
- for (typename T::const_iterator i = vect.begin(); i != vect.end(); ++i)
- {
- psi.insert(psi.end(), std::make_pair(i->first+offset, i->second));
- }
- }
-
- template <typename T>
- void subtract_from_sparse_vect (
- T& psi,
- const T& vect
- ) const
- {
- for (typename T::const_iterator i = vect.begin(); i != vect.end(); ++i)
- {
- psi.insert(psi.end(), std::make_pair(i->first, -i->second));
- }
- }
-
- template <typename psi_type>
- typename disable_if<is_matrix<psi_type> >::type get_joint_feature_vector (
- const sample_type& sample,
- const label_type& label,
- psi_type& psi
- ) const
- {
- psi.clear();
- for (unsigned long i = 0; i < sample.number_of_nodes(); ++i)
- {
- // accumulate the node vectors
- if (label[i] == true)
- add_to_sparse_vect(psi, sample.node(i).data, edge_dims);
-
- for (unsigned long n = 0; n < sample.node(i).number_of_neighbors(); ++n)
- {
- const unsigned long j = sample.node(i).neighbor(n).index();
-
- // Don't double count edges. Also only include the vector if
- // the labels disagree.
- if (i < j && label[i] != label[j])
- {
- subtract_from_sparse_vect(psi, sample.node(i).edge(n));
- }
- }
- }
- }
-
- virtual void get_truth_joint_feature_vector (
- long idx,
- feature_vector_type& psi
- ) const
- {
- get_joint_feature_vector(samples[idx], labels[idx], psi);
- }
-
- virtual void separation_oracle (
- const long idx,
- const matrix_type& current_solution,
- double& loss,
- feature_vector_type& psi
- ) const
- {
- const sample_type& samp = samples[idx];
-
- // setup the potts graph based on samples[idx] and current_solution.
- graph<double,double>::kernel_1a g;
- copy_graph_structure(samp, g);
- for (unsigned long i = 0; i < g.number_of_nodes(); ++i)
- {
- g.node(i).data = dot(rowm(current_solution,range(edge_dims,current_solution.size()-1)),
- samp.node(i).data);
-
- // Include a loss augmentation so that we will get the proper loss augmented
- // max when we use find_max_factor_graph_potts() below.
- if (labels[idx][i])
- g.node(i).data -= get_loss_for_sample(idx,i,!labels[idx][i]);
- else
- g.node(i).data += get_loss_for_sample(idx,i,!labels[idx][i]);
-
- for (unsigned long n = 0; n < g.node(i).number_of_neighbors(); ++n)
- {
- const unsigned long j = g.node(i).neighbor(n).index();
- // Don't compute an edge weight more than once.
- if (i < j)
- {
- g.node(i).edge(n) = dot(rowm(current_solution,range(0,edge_dims-1)),
- samp.node(i).edge(n));
- }
- }
-
- }
-
- std::vector<node_label> labeling;
- find_max_factor_graph_potts(g, labeling);
-
-
- std::vector<bool> bool_labeling;
- bool_labeling.reserve(labeling.size());
- // figure out the loss
- loss = 0;
- for (unsigned long i = 0; i < labeling.size(); ++i)
- {
- const bool predicted_label = (labeling[i]!= 0);
- bool_labeling.push_back(predicted_label);
- loss += get_loss_for_sample(idx, i, predicted_label);
- }
-
- // compute psi
- get_joint_feature_vector(samp, bool_labeling, psi);
- }
-
- double get_loss_for_sample (
- long sample_idx,
- long node_idx,
- bool predicted_label
- ) const
- /*!
- requires
- - 0 <= sample_idx < labels.size()
- - 0 <= node_idx < labels[sample_idx].size()
- ensures
- - returns the loss incurred for predicting that the node
- samples[sample_idx].node(node_idx) has a label of predicted_label.
- !*/
- {
- const bool true_label = labels[sample_idx][node_idx];
- if (true_label != predicted_label)
- {
- if (losses.size() != 0)
- return losses[sample_idx][node_idx];
- else if (true_label == true)
- return loss_pos;
- else
- return loss_neg;
- }
- else
- {
- // no loss for making the correct prediction.
- return 0;
- }
- }
-
- const dlib::array<sample_type>& samples;
- const std::vector<label_type>& labels;
- const std::vector<std::vector<double> >& losses;
-
- long node_dims;
- long edge_dims;
- double loss_pos;
- double loss_neg;
- };
-
-// ----------------------------------------------------------------------------------------
-
-}
-
-#endif // DLIB_STRUCTURAL_SVM_GRAPH_LAbELING_PROBLEM_Hh_
-
-