2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




 
 Градиентный метод с дроблением шага
Сообщение09.04.2016, 23:31 
Я считаю, что он у меня не удался
+Считает правильные значения из некоторых начальных точек
-В процедуре дробления (partition), эпсилон нельзя брать больше половины, хотя в теории написано, что можно брать от 0 до 1.
-Даже если он считает правильно - слишком много итераций он на это тратит (больше 1000)
?Какой лучше брать критерий остановки?
?Какой лучше брать начальный лямбда?
Код (C):
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#include <stdio.h>
#include <math.h>
#define M 10000
double a = 1.0, b = 1.0, c = 1.0;
double abs(double x)
{
    return x < 0 ? -x : x;
}
double f(double x1, double x2)
{
        return a*x1 + x2 + 4*sqrt(1 + b*x1*x1 + c*x2*x2);
}
double df_dx1(double x1, double x2)
{
    return a + 4 * b * x1 / sqrt(1 + b*x1*x1 + c*x2*x2);
}
double df_dx2(double x1, double x2)
{
    return 1 + 4 * c * x2 / sqrt(1 + b*x1*x1 + c*x2*x2);
}
double partition(double lambda, double (*f)(double, double), double x1, double x2)
{
   double delta = 0.5, eps = 0.25;//константа дробления и оценки
   double dx1   = df_dx1(x1, x2), dx2 = df_dx2(x1, x2);
   double a       = abs(dx1 + dx2);
   while(f(x1 - lambda * dx1,  x2 - lambda * dx2) >  f(x1, x2) - eps * lambda * a * a )
           lambda *= delta;
   return lambda;
}
double GradientWithPartitions(double (*f)(double, double), double x01, double x02, double eps)
{
   FILE *out;
   double x1 = x01, x2 = x02, lambda, xp1, xp2;
   int it = 0;
   lambda = 0.001; //magic, начальный шаг, взят с потолка
   out = fopen("out.txt", "w");
   do
   {
           lambda = partition(lambda, f, x1, x2);
          ++it;
           xp1 = x1;
           xp2 = x2;
            x1 -= lambda * df_dx1(x1, x2);
           x2 -= lambda * df_dx2(x1, x2);
   }while(sqrt( df_dx1(x1, x2)*df_dx1(x1, x2) + df_dx2(x1, x2)*df_dx2(x1, x2) ) > eps && it < M);

   printf("# %i iterations \n", it);
   printf("Optimum achieved on (%lf, %lf)\n", x1, x2);
   printf("Optimum achieved on (%lf, %lf)\n", -1/sqrt(14.0), -1/sqrt(14.0));
   return f(x1, x2);
}

int main(void)
{
        double opt = GradientWithPartitions(f, 0, 0, 0.1);
        printf("%.10lf : %.10lf \n", opt, sqrt(14.0));
        return 0;
}

Прошу специалистов взглянуть.
http://www.machinelearning.ru/wiki/inde ... 0%BA%D0%B0

 
 
 
 Re: Градиентный метод с дроблением шага
Сообщение19.04.2016, 13:55 
Эх, где же специалисты по градиентным методам?
Я, конечно, могу углубиться в чтение дополнительной литературы, но вопросы-то довольно простые:
Нормально ли для градиентного метода с дроблением шага для точности 0.01 делать пару тысяч итераций?
Эпсилон в процедуре дробления ведет себя странно (см. код и пред пост), в чем неточность?
В источнике берутся нормы градиента, но какие не сказано, возможно в этом все дело?

 
 
 [ Сообщений: 2 ] 


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group