Commit 79d99b85 authored by Davis King's avatar Davis King

Improved line_search() behavior for functions without continuous derivatives.

Also made the bracketing phase more efficient.
parent ea5f89c6
...@@ -127,7 +127,8 @@ namespace dlib ...@@ -127,7 +127,8 @@ namespace dlib
double f0, double f0,
double d0, double d0,
double f1, double f1,
double d1 double d1,
double limit = 1
) )
{ {
const double n = 3*(f1 - f0) - 2*d0 - d1; const double n = 3*(f1 - f0) - 2*d0 - d1;
...@@ -161,8 +162,8 @@ namespace dlib ...@@ -161,8 +162,8 @@ namespace dlib
else else
x = x2; x = x2;
// now make sure the minimum is within the allowed range of (0,1) // now make sure the minimum is within the allowed range of [0,limit]
return put_in_range(0,1,x); return put_in_range(0,limit,x);
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -305,8 +306,9 @@ namespace dlib ...@@ -305,8 +306,9 @@ namespace dlib
// the book Practical Methods of Optimization by R. Fletcher. The sectioning // the book Practical Methods of Optimization by R. Fletcher. The sectioning
// phase is an implementation of 2.6.4 from the same book. // phase is an implementation of 2.6.4 from the same book.
// tau1 > 1. Controls the alpha jump size during the search // 1 < tau1a < tau1b. Controls the alpha jump size during the search
const double tau1 = 9; const double tau1a = 2.0;
const double tau1b = 9;
// it must be the case that 0 < tau2 < tau3 <= 1/2 for the algorithm to function // it must be the case that 0 < tau2 < tau3 <= 1/2 for the algorithm to function
// correctly but the specific values of tau2 and tau3 aren't super important. // correctly but the specific values of tau2 and tau3 aren't super important.
...@@ -390,34 +392,28 @@ namespace dlib ...@@ -390,34 +392,28 @@ namespace dlib
break; break;
} }
if (mu <= 2*alpha - last_alpha)
{
last_alpha = alpha;
alpha = mu;
}
else
{
const double temp = alpha;
double first = 2*alpha - last_alpha;
const double temp = alpha;
// Pick a larger range [first, last]. We will pick the next alpha in that
// range.
double first = alpha + tau1a*(alpha - last_alpha);
double last; double last;
if (mu > 0) if (mu > 0)
last = std::min(mu, alpha + tau1*(alpha - last_alpha)); last = std::min(mu, alpha + tau1b*(alpha - last_alpha));
else else
last = std::max(mu, alpha + tau1*(alpha - last_alpha)); last = std::max(mu, alpha + tau1b*(alpha - last_alpha));
// pick a point between first and last by doing some kind of interpolation // pick a point between first and last by doing some kind of interpolation
if (last_alpha < alpha) if (last_alpha < alpha)
alpha = last_alpha + (alpha-last_alpha)*poly_min_extrap(last_val, last_val_der, val, val_der); alpha = last_alpha + (alpha-last_alpha)*poly_min_extrap(last_val, last_val_der, val, val_der, 1e10);
else else
alpha = alpha + (last_alpha-alpha)*poly_min_extrap(val, val_der, last_val, last_val_der); alpha = alpha + (last_alpha-alpha)*poly_min_extrap(val, val_der, last_val, last_val_der, 1e10);
alpha = put_in_range(first,last,alpha); alpha = put_in_range(first,last,alpha);
last_alpha = temp; last_alpha = temp;
}
last_val = val; last_val = val;
last_val_der = val_der; last_val_der = val_der;
...@@ -461,6 +457,13 @@ namespace dlib ...@@ -461,6 +457,13 @@ namespace dlib
{ {
if (std::abs(val_der) <= thresh) if (std::abs(val_der) <= thresh)
return alpha; return alpha;
// If we are optimizing a function that doesn't have continuous first
// derivatives then val_der might not ever go below thresh. So check if it
// looks like the first derivative is discontinuous and stop if so. The
// current alpha is plenty good enough in this case.
const double second_der = std::abs(a_val_der-b_val_der)/std::abs(a-b);
if (second_der > 1e5)
return alpha;
if ( (b-a)*val_der >= 0) if ( (b-a)*val_der >= 0)
{ {
......
...@@ -91,7 +91,8 @@ namespace dlib ...@@ -91,7 +91,8 @@ namespace dlib
double f0, double f0,
double d0, double d0,
double f1, double f1,
double d1 double d1,
double limit = 1
); );
/*! /*!
ensures ensures
...@@ -100,7 +101,7 @@ namespace dlib ...@@ -100,7 +101,7 @@ namespace dlib
- c(1) == f1 - c(1) == f1
- derivative of c(x) at x==0 is d0 - derivative of c(x) at x==0 is d0
- derivative of c(x) at x==1 is d1 - derivative of c(x) at x==1 is d1
- returns the point in the range [0,1] that minimizes the polynomial c(x) - returns the point in the range [0,limit] that minimizes the polynomial c(x)
!*/ !*/
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment