21 #define TRACE(A,B) (((A).array()*(B).transpose().array()).sum())
23 using namespace shogun;
24 using namespace Eigen;
38 m_features = features;
63 SG_DEBUG(
"Entering CLMNN::train().\n")
66 CLMNNImpl::check_training_setup(m_features, m_labels, init_transform);
76 MatrixXd L = Map<MatrixXd>(init_transform.
matrix, init_transform.
num_rows,
79 SG_DEBUG(
"Finding target nearest neighbors.\n")
82 SG_DEBUG(
"Summing outer products for (sub-)gradient initialization.\n")
83 MatrixXd gradient = (1-m_regularization)*CLMNNImpl::sum_outer_products(x, target_nn);
90 ImpostorsSetType exact_impostors, cur_impostors, prev_impostors;
96 m_statistics->resize(m_maxiter);
105 cur_impostors = CLMNNImpl::find_impostors(x,y,L,target_nn,iter,m_correction);
106 SG_DEBUG(
"Found %d impostors in the current set.\n", cur_impostors.size())
110 CLMNNImpl::update_gradient(x, gradient, cur_impostors, prev_impostors, m_regularization);
113 CLMNNImpl::gradient_step(L, gradient, stepsize, m_diagonal);
118 obj[iter] =
TRACE(L.transpose()*L,gradient) + m_regularization*cur_impostors.size();
121 CLMNNImpl::correct_stepsize(stepsize, obj, iter);
124 stop = CLMNNImpl::check_termination(stepsize, obj, iter, m_maxiter, m_stepsize_threshold, m_obj_threshold);
129 prev_impostors = cur_impostors;
132 m_statistics->set(iter-1, obj[iter-1], stepsize, cur_impostors.
size());
134 SG_DEBUG(
"iteration=%d, objective=%.4f, #impostors=%4d, stepsize=%.4E\n",
135 iter, obj[iter-1], cur_impostors.
size(), stepsize)
139 m_statistics->resize(iter);
146 SG_DEBUG(
"Leaving CLMNN::train().\n")
151 return m_linear_transform;
160 Map<const MatrixXd> map_linear_transform(m_linear_transform.matrix,
161 m_linear_transform.num_rows, m_linear_transform.num_cols);
163 MatrixXd M = map_linear_transform.transpose()*map_linear_transform;
166 for (
index_t i = 0; i < M.rows(); i++)
167 for (
index_t j = 0; j < M.cols(); j++)
168 mahalanobis_matrix(i,j) = M(i,j);
186 REQUIRE(k>0,
"The number of target neighbors per example must be larger than zero\n");
192 return m_regularization;
197 m_regularization = regularization;
207 REQUIRE(stepsize>0,
"The step size used in gradient descent must be larger than zero\n")
208 m_stepsize = stepsize;
213 return m_stepsize_threshold;
219 "The threshold for the step size must be larger than zero\n")
220 m_stepsize_threshold = stepsize_threshold;
230 REQUIRE(maxiter>0,
"The number of maximum iterations must be larger than zero\n")
241 m_correction = correction;
246 return m_obj_threshold;
252 "The threshold for the objective must be larger than zero\n")
253 m_obj_threshold = obj_threshold;
263 m_diagonal = diagonal;
274 SG_ADD(&m_linear_transform,
"linear_transform",
280 SG_ADD(&m_k, "k", "Number of target neighbours per example",
282 SG_ADD(&m_regularization, "regularization", "Regularization",
284 SG_ADD(&m_stepsize, "stepsize", "Step size in gradient descent",
286 SG_ADD(&m_stepsize_threshold, "stepsize_threshold", "Step size threshold",
288 SG_ADD(&m_maxiter, "maxiter", "Maximum number of iterations",
290 SG_ADD(&m_correction, "correction",
292 SG_ADD(&m_obj_threshold, "obj_threshold", "Objective threshold",
295 SG_ADD((
CSGObject**) &m_statistics, "statistics", "Training statistics",
301 m_regularization = 0.5;
303 m_stepsize_threshold = 1e-22;
306 m_obj_threshold = 1e-9;
322 return "LMNNStatistics";
327 REQUIRE(size > 0,
"The new size in CLMNNStatistics::resize must be larger than zero."
328 " Given value is %d.\n", size);
331 stepsize.resize_vector(size);
332 num_impostors.resize_vector(size);
336 uint32_t num_impostors_iter)
338 REQUIRE(iter >= 0 && iter < obj.
vlen,
"The iteration index in CLMNNStatistics::set "
339 "must be larger or equal to zero and less than the size (%d). Given valu is %d.\n", obj.
vlen, iter);
341 obj[iter] = obj_iter;
342 stepsize[iter] = stepsize_iter;
343 num_impostors[iter] = num_impostors_iter;
346 void CLMNNStatistics::init()
350 SG_ADD(&num_impostors,
"num_impostors",
"Number of impostors at each iteration",