12 #ifndef MLPACK_METHODS_NCA_NCA_SOFTMAX_ERROR_FUNCTION_IMPL_H 13 #define MLPACK_METHODS_NCA_NCA_SOFTMAX_ERROR_FUNCTION_IMPL_H 24 template<
typename MetricType>
26 const arma::mat& dataset,
27 const arma::Row<size_t>& labels,
29 dataset(math::
MakeAlias(const_cast<
arma::mat&>(dataset), false)),
30 labels(math::
MakeAlias(const_cast<
arma::Row<size_t>&>(labels), false)),
36 template<
typename MetricType>
40 arma::Row<size_t> newLabels;
47 dataset = std::move(newDataset);
48 labels = std::move(newLabels);
52 template<
typename MetricType>
56 Precalculate(coordinates);
64 template<
typename MetricType>
67 const size_t batchSize)
71 double denominator = 0;
76 stretchedDataset = coordinates * dataset;
77 for (
size_t i = begin; i < begin + batchSize; ++i)
79 for (
size_t k = 0; k < dataset.n_cols; ++k)
86 double eval = std::exp(-metric.Evaluate(stretchedDataset.unsafe_col(i),
87 stretchedDataset.unsafe_col(k)));
90 if (labels[i] == labels[k])
98 if (denominator == 0.0)
100 Log::Warn <<
"Denominator of p_" << i <<
" is 0!" << std::endl;
104 result += -(numerator / denominator);
111 template<
typename MetricType>
116 Precalculate(coordinates);
131 sum.zeros(stretchedDataset.n_rows, stretchedDataset.n_rows);
132 for (
size_t i = 0; i < stretchedDataset.n_cols; ++i)
134 for (
size_t k = (i + 1); k < stretchedDataset.n_cols; ++k)
137 double eval = exp(-metric.Evaluate(stretchedDataset.unsafe_col(i),
138 stretchedDataset.unsafe_col(k)));
139 double p_ik = 0, p_ki = 0;
140 p_ik = eval / denominators(i);
141 p_ki = eval / denominators(k);
144 arma::vec x_ik = dataset.col(i) - dataset.col(k);
145 arma::mat secondTerm = (x_ik * trans(x_ik));
147 if (labels[i] == labels[k])
148 sum += ((p[i] - 1) * p_ik + (p[k] - 1) * p_ki) * secondTerm;
150 sum += (p[i] * p_ik + p[k] * p_ki) * secondTerm;
155 gradient = -2 * coordinates * sum;
159 template <
typename MetricType>
160 template <
typename GradType>
164 const size_t batchSize)
168 GradType firstTerm, secondTerm;
171 double numerator, denominator;
173 gradient.zeros(coordinates.n_rows, coordinates.n_rows);
176 stretchedDataset = coordinates * dataset;
177 for (
size_t i = begin; i < begin + batchSize; ++i)
182 firstTerm.zeros(coordinates.n_rows, coordinates.n_cols);
183 secondTerm.zeros(coordinates.n_rows, coordinates.n_cols);
185 for (
size_t k = 0; k < dataset.n_cols; ++k)
192 double eval = exp(-metric.Evaluate(stretchedDataset.unsafe_col(i),
193 stretchedDataset.unsafe_col(k)));
198 GradType x_ik = dataset.col(i) - dataset.col(k);
199 if (labels[i] == labels[k])
202 secondTerm += eval * x_ik * trans(x_ik);
209 firstTerm += eval * x_ik * trans(x_ik);
214 if (denominator == 0)
216 Log::Warn <<
"Denominator of p_" << i <<
" is 0!" << std::endl;
223 p = numerator / denominator;
224 firstTerm /= denominator;
225 secondTerm /= denominator;
230 gradient += -2 * coordinates * (p * firstTerm - secondTerm);
234 template<
typename MetricType>
237 return arma::eye<arma::mat>(dataset.n_rows, dataset.n_rows);
240 template<
typename MetricType>
242 const arma::mat& coordinates)
245 if (lastCoordinates.n_rows != coordinates.n_rows ||
246 lastCoordinates.n_cols != coordinates.n_cols)
248 lastCoordinates.set_size(coordinates.n_rows, coordinates.n_cols);
250 else if ((accu(coordinates == lastCoordinates) == coordinates.n_elem) &&
257 lastCoordinates = coordinates;
258 stretchedDataset = coordinates * dataset;
266 p.zeros(stretchedDataset.n_cols);
267 denominators.zeros(stretchedDataset.n_cols);
268 for (
size_t i = 0; i < stretchedDataset.n_cols; ++i)
270 for (
size_t j = (i + 1); j < stretchedDataset.n_cols; ++j)
273 double eval = exp(-metric.Evaluate(stretchedDataset.unsafe_col(i),
274 stretchedDataset.unsafe_col(j)));
277 denominators[i] += eval;
278 denominators[j] += eval;
281 if (labels[i] == labels[j])
293 for (
size_t i = 0; i < stretchedDataset.n_cols; ++i)
295 if (denominators[i] == 0.0)
297 Log::Debug <<
"Denominator of p_{" << i <<
", j} is 0." << std::endl;
300 denominators[i] = std::numeric_limits<double>::infinity();
306 precalculated =
true;
static MLPACK_EXPORT util::NullOutStream Debug
MLPACK_EXPORT is required for global variables, so that they are properly exported by the Windows com...
Definition: log.hpp:79
The "softmax" stochastic neighbor assignment probability function.
Definition: nca_softmax_error_function.hpp:45
Linear algebra utility functions, generally performed on matrices or vectors.
Definition: cv.hpp:1
const arma::mat GetInitialPoint() const
Get the initial point.
Definition: nca_softmax_error_function_impl.hpp:235
void Gradient(const arma::mat &covariance, arma::mat &gradient)
Evaluate the gradient of the softmax function for the given covariance matrix.
Definition: nca_softmax_error_function_impl.hpp:112
static MLPACK_EXPORT util::PrefixedOutStream Warn
Prints warning messages prefixed with [WARN ].
Definition: log.hpp:87
SoftmaxErrorFunction(const arma::mat &dataset, const arma::Row< size_t > &labels, MetricType metric=MetricType())
Initialize with the given kernel; useful when the kernel has some state to store, which is set elsewh...
Definition: nca_softmax_error_function_impl.hpp:25
void Shuffle()
Shuffle the dataset.
Definition: nca_softmax_error_function_impl.hpp:37
Include all of the base components required to write mlpack methods, and the main mlpack Doxygen docu...
void ShuffleData(const MatType &inputPoints, const LabelsType &inputLabels, MatType &outputPoints, LabelsType &outputLabels, const std::enable_if_t<!arma::is_SpMat< MatType >::value > *=0, const std::enable_if_t<!arma::is_Cube< MatType >::value > *=0)
Shuffle a dataset and associated labels (or responses).
Definition: shuffle_data.hpp:28
double Evaluate(const arma::mat &covariance)
Evaluate the softmax function for the given covariance matrix.
Definition: nca_softmax_error_function_impl.hpp:53
void ClearAlias(arma::Mat< ElemType > &mat)
Clear an alias so that no data is overwritten.
Definition: make_alias.hpp:110
arma::Cube< ElemType > MakeAlias(arma::Cube< ElemType > &input, const bool strict=true)
Make an alias of a dense cube.
Definition: make_alias.hpp:24