GMMExpectationMaximization::Real GMMExpectationMaximization::gauss(const VectorX & mean, const MatrixX & cov,const VectorX & pt) const { Real det = cov.determinant(); uint dim = mean.size(); // check that the covariance matrix is invertible if (std::abs(det) < std::pow(m_epsilon,dim) * 0.1) return 0.0; // the gaussian has approximately zero width: the probability of any point falling into it is approximately 0. // else, compute pdf MatrixX inverse_cov = cov.inverse(); VectorX dist = pt - mean; Real exp = - (dist.dot(inverse_cov * dist)) / 2.0; Real den = std::sqrt(std::pow(2.0 * M_PI,dim) * std::abs(det)); return std::exp(exp) / den; }
bool cpu_linesearch(VectorX &xk, VectorX &z, cpu_cost_function *cpucf, floatdouble &fk, VectorX &gk, size_t &evals, const VectorX &gkm1, const floatdouble &fkm1, lbfgs::status &stat, floatdouble &step, size_t maxEvals) { const floatdouble c1 = 1e-4f; const floatdouble c2 = 0.9f; const floatdouble alpha_0 = 0.0; const floatdouble phi_0 = fk; const floatdouble phi_prime_0 = z.dot(gk); if (phi_prime_0 >= 0.0) { stat = lbfgs::LBFGS_LINE_SEARCH_FAILED; return false; } const floatdouble alpha_max = 1e8; floatdouble alpha = 1.0; floatdouble alpha_old = 0.0; bool second_iter = false; floatdouble alpha_low, alpha_high; floatdouble phi_low, phi_high; floatdouble phi_prime_low, phi_prime_high; for (;;) { xk += (alpha - alpha_old) * z; cpucf->cpu_f_gradf(xk.data(), &fk, gk.data()); ++evals; const floatdouble phi_alpha = fk; const floatdouble phi_prime_alpha = z.dot(gk); const bool armijo_violated = (phi_alpha > phi_0 + c1 * alpha * phi_prime_0 || (second_iter && phi_alpha >= phi_0)); const bool strong_wolfe = (std::abs(phi_prime_alpha) <= -c2 * phi_prime_0); // If both Armijo and Strong Wolfe hold, we're done if (!armijo_violated && strong_wolfe) { step = alpha; return true; } if (evals >= maxEvals) { stat = lbfgs::LBFGS_REACHED_MAX_EVALS; return false; } // If Armijio condition is violated, we've bracketed a viable minimum // Interval is [alpha_0, alpha] if (armijo_violated) { alpha_low = alpha_0; alpha_high = alpha; phi_low = phi_0; phi_high = phi_alpha; phi_prime_low = phi_prime_0; phi_prime_high = phi_prime_alpha; break; } // If the directional derivative at alpha is positive, we've bracketed a viable minimum // Interval is [alpha, alpha_0] if (phi_prime_alpha >= 0) { alpha_low = alpha; alpha_high = alpha_0; phi_low = phi_alpha; phi_high = phi_0; phi_prime_low = phi_prime_alpha; phi_prime_high = phi_prime_0; break; } // Else look to the "right" of alpha for a viable minimum floatdouble alpha_new = alpha + 4 * (alpha - alpha_old); alpha_old = alpha; alpha = alpha_new; if (alpha > alpha_max) { stat = lbfgs::LBFGS_LINE_SEARCH_FAILED; return false; } second_iter = true; } // The minimum is now bracketed in [alpha_low, alpha_high] // Find it... size_t tries = 0; const size_t minTries = 10; while (true) { tries++; alpha_old = alpha; // Quadratic interpolation: // Least-squares fit a parabola to (alpha_low, phi_low), // (alpha_high, phi_high) with gradients phi_prime_low and // phi_prime_high and select the minimum of that parabola as // the new alpha alpha = 0.5f * (alpha_low + alpha_high); alpha += (phi_high - phi_low) / (phi_prime_low - phi_prime_high); if (alpha < alpha_low || alpha > alpha_high) alpha = 0.5f * (alpha_low + alpha_high); xk += (alpha - alpha_old) * z; cpucf->cpu_f_gradf(xk.data(), &fk, gk.data()); ++evals; const floatdouble phi_j = fk; const floatdouble phi_prime_j = z.dot(gk); const bool armijo_violated = (phi_j > phi_0 + c1 * alpha * phi_prime_0 || phi_j >= phi_low); const bool strong_wolfe = (std::abs(phi_prime_j) <= -c2 * phi_prime_0); if (!armijo_violated && strong_wolfe) { // The Armijo and Strong Wolfe conditions hold step = alpha; break; } else if (std::abs(alpha_high - alpha_low) < 1e-5 && tries > minTries) { // The search interval has become too small stat = lbfgs::LBFGS_LINE_SEARCH_FAILED; return false; } else if (armijo_violated) { alpha_high = alpha; phi_high = phi_j; phi_prime_high = phi_prime_j; } else { if (phi_prime_j * (alpha_high - alpha_low) >= 0) { alpha_high = alpha_low; phi_high = phi_low; phi_prime_high = phi_prime_low; } alpha_low = alpha; phi_low = phi_j; phi_prime_low = phi_prime_j; } if (evals >= maxEvals) { stat = lbfgs::LBFGS_REACHED_MAX_EVALS; return false; } } return true; }