2015-11-26 2 views
2

EDIT: Код, который я вставил, слишком длинный. Basicaly Я не знаю, как работать со вторым кодом. Если я знаю, как вычислять альфу из второго кода, я думаю, что моя проблема будет решена. Я пробовал много входных аргументов для второго кода, но он не работает!Ошибка при оценке функции

Я написал следующий код для решения выпуклой задачи оптимизации с использованием градиента спускается метод:

function [optimumX,optimumF,counter,gNorm,dx] = grad_descent() 

x0 = [3 3]';%'// 
terminationThreshold = 1e-6; 
maxIterations = 100; 
dxMin = 1e-6; 

gNorm = inf; x = x0; counter = 0; dx = inf; 

% ************************************ 
f = @(x1,x2) 4.*x1.^2 + 2.*x1.*x2 +8.*x2.^2 + 10.*x1 + x2; 
%alpha = 0.01; 
% ************************************ 

figure(1); clf; ezcontour(f,[-5 5 -5 5]); axis equal; hold on 

f2 = @(x) f(x(1),x(2)); 

% gradient descent algorithm: 
while and(gNorm >= terminationThreshold, and(counter <= maxIterations, dx >= dxMin)) 
    g = grad(x); 
    gNorm = norm(g); 

    alpha = linesearch_strongwolfe(f,-g, x0, 1); 

    xNew = x - alpha * g; 
    % check step 
    if ~isfinite(xNew) 
     display(['Number of iterations: ' num2str(counter)]) 
     error('x is inf or NaN') 
    end 
    % ************************************** 
    plot([x(1) xNew(1)],[x(2) xNew(2)],'ko-') 
    refresh 
    % ************************************** 

    counter = counter + 1; 
    dx = norm(xNew-x); 
    x = xNew; 
end 
optimumX = x; 
optimumF = f2(optimumX); 
counter = counter - 1; 

% define the gradient of the objective 
function g = grad(x) 
g = [(8*x(1) + 2*x(2) +10) 
    (2*x(1) + 16*x(2) + 1)]; 
end 

end 

Как вы можете видеть, я закомментировал alpha = 0.01; части. Я хочу рассчитать alpha с помощью другого кода. Вот код (этот код не мой)

function alphas = linesearch_strongwolfe(f,d,x0,alpham) 

alpha0 = 0; 
alphap = alpha0; 
c1 = 1e-4; 
c2 = 0.5; 
alphax = alpham*rand(1); 
[fx0,gx0] = feval(f,x0,d); 
fxp = fx0; 
gxp = gx0; 
i=1; 

while (1 ~= 2) 
    xx = x0 + alphax*d; 
    [fxx,gxx] = feval(f,xx,d); 
    if (fxx > fx0 + c1*alphax*gx0) | ((i > 1) & (fxx >= fxp)), 
    alphas = zoom(f,x0,d,alphap,alphax); 
    return; 
    end 
    if abs(gxx) <= -c2*gx0, 
    alphas = alphax; 
    return; 
    end 
    if gxx >= 0, 
    alphas = zoom(f,x0,d,alphax,alphap); 
    return; 
    end 
    alphap = alphax; 
    fxp = fxx; 
    gxp = gxx; 
    alphax = alphax + (alpham-alphax)*rand(1); 
    i = i+1; 
end 

function alphas = zoom(f,x0,d,alphal,alphah) 
c1 = 1e-4; 
c2 = 0.5; 
[fx0,gx0] = feval(f,x0,d); 

while (1~=2), 
    alphax = 1/2*(alphal+alphah); 
    xx = x0 + alphax*d; 
    [fxx,gxx] = feval(f,xx,d); 
    xl = x0 + alphal*d; 
    fxl = feval(f,xl,d); 
    if ((fxx > fx0 + c1*alphax*gx0) | (fxx >= fxl)), 
     alphah = alphax; 
    else 
     if abs(gxx) <= -c2*gx0, 
     alphas = alphax; 
     return; 
     end 
     if gxx*(alphah-alphal) >= 0, 
     alphah = alphal; 
     end 
     alphal = alphax; 
    end 
end 

Но я получаю эту ошибку:

Error in linesearch_strongwolfe (line 11) [fx0,gx0] = feval(f,x0,d);

Как вы можете видеть, что я написал ф функции и ее градиент вручную. linesearch_strongwolfe (е, д, х0, alpham) принимает функцию е, градиент F, вектор x0 и постоянную alpham. что-то не так с моим объявлением f? Этот код работает отлично, если я положил обратно alpha = 0.01;

+0

Можете ли вы уменьшить код, возможно, просто используйте фиктивный пример для параметров в 'linesearch_strongwolfe (f, d, x0, alpham)', чтобы воспроизвести ошибку? Не зная, что у нас будет с трудом помогать вам ... – lhcgeneva

+0

@lhcgeneva Я привел пример в конце сообщения, надеюсь, что это помогает. Я думаю, что с моей функцией что-то не так. Может быть, я не признал это правильно. – bido

+0

Ну, если feval не работает вне функции, он не будет работать внутри. Что такое f? – lhcgeneva

ответ

2

Как я это вижу:

x0 = [3; 3]; %2-element column vector 
g = grad(x0); %2-element column vector 
f = @(x1,x2) 4.*x1.^2 + 2.*x1.*x2 +8.*x2.^2 + 10.*x1 + x2; 
linesearch_strongwolfe(f,-g, x0, 1); %passing variables 

внутри функции:

[fx0,gx0] = feval(f,x0,-g); %variable names substituted with input vars 

Это в эффект вызова

[fx0,gx0] = f(x0,-g); 

но f(x0,-g)- это одиночный двухэлементный вектор-столбец с этими входами. Приведение вывода к двум переменным не будет работать.

Вы должны либо определить f в качестве надлежащего имени функции (так же, как grad) для вывода 2-х переменных (по одному для каждого компонента), или изменить код linesearch_strongwolfe вернуть одну переменную, затем нарежьте, что в 2-х отдельных переменных после этого.


Если вы испытываете очень редкого вида лени и не хотите, чтобы определить функцию с именем, вы все еще можете использовать анонимную функцию за счет дублирования кода для двух компонентов (по крайней мере, я не могли придумать более чистый раствор):

f = @(x1,x2) deal(4.*x1(1)^2 + 2.*x1(1)*x2(1) +8.*x2(1)^2 + 10.*x1(1) + x2(1),... 
        4.*x1(2)^2 + 2.*x1(2)*x2(2) +8.*x2(2)^2 + 10.*x1(2) + x2(2)); 

[fx0,gx0] = f(x0,-g); %now works fine 

до тех пор, пока у вас всегда есть 2 выходных переменных. Обратите внимание, что это больше похоже на доказательство концепции, поскольку это уродливое, неэффективное и очень восприимчивое к опечаткам.

Смежные вопросы