1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
|
// Copyright (C) 2011 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_ASSIGNMENT_FuNCTION_ABSTRACT_H__
#ifdef DLIB_ASSIGNMENT_FuNCTION_ABSTRACT_H__
#include <vector>
#include "../optimization/max_cost_assignment_abstract.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
class example_feature_extractor
{
/*!
WHAT THIS OBJECT REPRESENTS
This object defines the interface a feature extractor must implement
if it is to be used with the assignment_function defined at the bottom
of this file.
The model used by assignment_function objects is the following.
Given two sets of objects, the Left Hand Set (LHS) and Right Hand Set (RHS),
find a one-to-one mapping M from LHS into RHS such that:
M == argmax_m sum_{l in LHS} match_score(l,m(l))
Where match_score() returns a scalar value indicating how good it is
to say l maps to the RHS element m(l). Additionally, in this model,
m() is allowed to indicate that l doesn't map to anything, and in this
case it is excluded from the sum.
Finally, match_score() is defined as:
match_score(l,r) == dot(w, PSI(l,r))
where l is an element of LHS, r is an element of RHS, and
w is a parameter vector.
Therefore, a feature extractor defines how the PSI() feature vector
is calculated. In particular, PSI() is defined by the get_features()
method of this class.
THREAD SAFETY
Instances of this object should be thread safe, that is, it should
be safe for multiple threads to make concurrent calls to the member
functions of this object.
!*/
public:
// This type should be a dlib::matrix capable of storing column vectors
// or an unsorted sparse vector type as defined in dlib/svm/sparse_vector_abstract.h.
typedef matrix_or_sparse_vector_type feature_vector_type;
// These two typedefs define the types used to represent an element in
// the left hand and right hand sets. You can use any copyable types here.
typedef user_defined_type_1 lhs_element;
typedef user_defined_type_2 rhs_element;
unsigned long num_features(
) const;
/*!
ensures
- returns the dimensionality of the PSI() feature vector.
!*/
void get_features (
const lhs_element& left,
const rhs_element& right,
feature_vector_type& feats
) const;
/*!
ensures
- #feats == PSI(left,right)
(i.e. This function computes a feature vector which, in some sense,
captures information useful for deciding if matching left to right
is "good").
!*/
};
// ----------------------------------------------------------------------------------------
void serialize(
const example_feature_extractor& item,
std::ostream& out
);
/*!
provides serialization support
!*/
void deserialize(
example_feature_extractor& item,
std::istream& in
);
/*!
provides deserialization support
!*/
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename feature_extractor
>
class assignment_function
{
/*!
REQUIREMENTS ON feature_extractor
It must be an object that implements an interface compatible with
the example_feature_extractor discussed above.
WHAT THIS OBJECT REPRESENTS
This object is a tool for solving the optimal assignment problem given a
user defined method for computing the quality of any particular assignment.
To define this precisely, suppose you have two sets of objects, a
Left Hand Set (LHS) and a Right Hand Set (RHS) and you want to
find a one-to-one mapping M from LHS into RHS such that:
M == argmax_m sum_{l in LHS} match_score(l,m(l))
Where match_score() returns a scalar value indicating how good it is
to say l maps to the RHS element m(l). Additionally, in this model,
m() is allowed to indicate that l doesn't map to anything, and in this
case it is excluded from the sum.
Finally, this object supports match_score() functions of the form:
match_score(l,r) == dot(w, PSI(l,r))
where l is an element of LHS, r is an element of RHS, w is a parameter
vector, and PSI() is defined by the feature_extractor template argument.
!*/
public:
typedef typename feature_extractor::lhs_element lhs_element;
typedef typename feature_extractor::rhs_element rhs_element;
typedef std::vector<long> label_type;
typedef label_type result_type;
typedef std::pair<std::vector<lhs_element>, std::vector<rhs_element> > sample_type;
assignment_function(
);
/*!
ensures
- #get_feature_extractor() == feature_extractor()
(i.e. it will have its default value)
- #get_weights().size() == #get_feature_extractor().num_features()
- #get_weights() == 0
- #forces_assignment() == false
!*/
explicit assignment_function(
const matrix<double,0,1>& weights
);
/*!
requires
- feature_extractor().num_features() == weights.size()
ensures
- #get_feature_extractor() == feature_extractor()
(i.e. it will have its default value)
- #get_weights() == weights
- #forces_assignment() == false
!*/
assignment_function(
const matrix<double,0,1>& weights,
const feature_extractor& fe
);
/*!
requires
- fe.num_features() == weights.size()
ensures
- #get_feature_extractor() == fe
- #get_weights() == weights
- #forces_assignment() == false
!*/
assignment_function(
const matrix<double,0,1>& weights,
const feature_extractor& fe,
bool force_assignment
);
/*!
requires
- fe.num_features() == weights.size()
ensures
- #get_feature_extractor() == fe
- #get_weights() == weights
- #forces_assignment() == force_assignment
!*/
const feature_extractor& get_feature_extractor (
) const;
/*!
ensures
- returns the feature extractor used by this object
!*/
const matrix<double,0,1>& get_weights (
) const;
/*!
ensures
- returns the parameter vector (w) associated with this assignment function.
The length of the vector is get_feature_extractor().num_features().
!*/
bool forces_assignment (
) const;
/*!
ensures
- returns true if this object is in the "forced assignment mode" and false
otherwise.
- When deciding how to match LHS to RHS, this object can operate in one of
two modes. In the default mode, this object will indicate that there is
no match for an element of LHS if the best matching element of RHS would
result in a negative match_score(). However, in the "forced assignment mode",
this object will always make the assignment if there is an available
element in RHS, regardless of the match_score().
Another way to understand this distinction is to consider an example.
Suppose LHS and RHS both contain 10 elements. Then in the default mode,
it is possible for this object to indicate that there are anywhere between
0 to 10 matches between LHS and RHS. However, in forced assignment mode
it will always indicate exactly 10 matches.
!*/
result_type operator()(
const std::vector<lhs_element>& lhs,
const std::vector<rhs_element>& rhs
) const
/*!
ensures
- returns a vector ASSIGN such that:
- ASSIGN.size() == lhs.size()
- if (ASSIGN[i] != -1) then
- lhs[i] is predicted to associate to rhs[ASSIGN[i]].
- else
- lhs[i] doesn't associate with anything in rhs.
- All values in ASSIGN which are not equal to -1 are unique.
That is, ASSIGN will never indicate that more than one element
of lhs is assigned to a particular element of rhs.
!*/
result_type operator() (
const sample_type& item
) const;
/*!
ensures
- returns (*this)(item.first, item.second);
!*/
void predict_assignments (
const sample_type& item,
result_type& assignment
) const;
/*!
ensures
- #assignment == (*this)(item)
!*/
void predict_assignments (
const std::vector<lhs_element>& lhs,
const std::vector<rhs_element>& rhs
result_type& assignment
) const;
/*!
ensures
- #assignment == (*this)(lhs,rhs)
!*/
};
// ----------------------------------------------------------------------------------------
template <
typename feature_extractor
>
void serialize (
const assignment_function<feature_extractor>& item,
std::ostream& out
);
/*!
provides serialization support
!*/
// ----------------------------------------------------------------------------------------
template <
typename feature_extractor
>
void deserialize (
assignment_function<feature_extractor>& item,
std::istream& in
);
/*!
provides deserialization support
!*/
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_ASSIGNMENT_FuNCTION_ABSTRACT_H__
|