Консультация № 187234
30.03.2013, 00:37
82.96 руб.
0 4 1
Здравствуйте! У меня возникли сложности с таким вопросом: для реализация метода поиска минимума
функции нескольких переменных с использованием метода градиентного спуска помогите организовать функцию расчета градиента (g[]) в точке х.
x представлен массивом из 4 значений x1..x4,
функция F(x1..x4) = (x1+7)^2 + 2*(x2-7)^2 + 3*(x3+7)^2 + 4*(x4-7)^2.

полагаю это осуществляется как-то так:

double dFpodX(double x1, double x2, int perem)
{
if (perem == 1)
return {...};
else
return {...};
}

но что-то не преуспел

Обсуждение

Неизвестный
30.03.2013, 07:29
общий
Градиент - это вектор из частных производных по каждой из переменных. Для вычисления частных производных нам нужна только функция и приращения. Делать отдельные методы для каждой производной не стоит. И значения параметров мне непонятны. Особенно perem. Сам градиент можно сделать примерно так:

Код:
double[] Gradient(double[] x, double[] dx)
{
double F = F(x);
double[] Par = (double[])x.Clone();
double[] G = new double[x.Length];
for (int i = 0; i < x.Length; i++)
{
Par[i] += dx[i];
G[i] = (F(Par) - F) / dx[i];
Par[i] = x[i];
}
return G;
}


В новом массиве параметров по очереди меняем координату на x+dx и вычисляем производную. Вообще, dx обычно одинакова для всех. Делают просто константу dx = 0.000001

Для полинома как в задании можно еще и по скорости оптимизировать, но это будет уже не универсальный метод. Если это то, что нужно - оформлю ответом.
Неизвестный
31.03.2013, 15:12
общий
31.03.2013, 17:15
Спасибо, Evgenijm, конечно оформляйте ответом!

полагаю конструкция F(x); (приведенная в вашем коде) подразумевает наличие метода для расчета функции F(x1..x4). приведенной мной выше?

Делают просто константу dx = 0.000001


то есть я могу сделать так:

Код:

double[] Gradient(double[] x)

{
double dx = 0.000001;
double F= Fu(x);

double[] Par = (double[])x.Clone();
double[] G = new double[x.Length];
for (int i = 0; i < x.Length; i++)
{
Par[i] += dx;
G[i] = (Fu(Par) - F) / dx;
Par[i] = x[i];
}
return G;


Неизвестный
01.04.2013, 06:54
общий
F() - это исследуемая функция. Чтобы не зависеть от количества переменных, я сделал все с массивами.
Чтобы объявить константу, надо перед ней поставить ключевое слово const:
const double dx = 0.000001;
Но в данном случае это без разницы: компилятор все равно в обоих случаях сделает одно и то же.

Константы типа dx или eps обычно заводят глобально для всего проекта, чтобы при расчетах не возникали лишние расхождения. dx надо выбирать так, чтобы она была гораздо меньше аргументов и результатов, но при этом не обнуляла промежуточный результат. Здесь я ее от фонаря поставил. Обычно это значение подходит.
Неизвестный
01.04.2013, 07:03
общий
это ответ
Здравствуйте, lexmod!

Градиент - это вектор из частных производных по каждой из переменных. Для вычисления частных производных нам нужна только функция и приращения. Делать отдельные методы для каждой производной не стоит. Сам градиент можно сделать примерно так:

Код:
double[] Gradient(double[] x, double[] dx)
{
double F = F(x);
double[] Par = (double[])x.Clone();
double[] G = new double[x.Length];
for (int i = 0; i < x.Length; i++)
{
Par[i] += dx[i];
G[i] = (F(Par) - F) / dx[i];
Par[i] = x[i];
}
return G;
}



В новом массиве параметров по очереди меняем координату на x+dx и вычисляем производную. Вообще, dx обычно одинакова для всех. Делают просто константу вроде dx = 0.000001. Она должна быть очень маленькой по сравнению со значениями функции, но при этом достаточно большой, чтобы при расчетах не исчезать в 0.

Для полинома как в задании можно еще и по скорости оптимизировать (для каждой производной здесь меняется лишь один элемент полинома), но это будет уже не универсальный метод.
5
Форма ответа