2015-11-20 4 views
1

Итак, я написал следующий код MATLAB в качестве упражнения для градиентный спуск. Я, очевидно, выбрал функцию, которая имеет минимум в (0,0), но алгоритм бросает меня на (-3,3).градиентный спуск сценарий MATLAB

я не узнал, что переключение между xGrad и yGrad на линии: [xGrad,yGrad] = gradient(f); дает правильную сходимость, несмотря на то, что xGrad, yGrad являются приблизительно 2*X, 2*Y, как ожидалось. Я предполагаю, что я перевернутое что-то здесь, но я пытался выяснить, что это какое-то время, и я не понимаю, так что я надеялся, что кто-то может заметить свою ошибку ...

dx=.01; 
dy=.01; 
x=-3:dx:3; 
y=-3:dy:3; 
[X,Y]=meshgrid(x,y); 

f=X.^2+Y.^2; 

lr = .1; %learning rate 
eps = 1e-10; %epsilon threshold 
tooMuch = 1e5; %limit iterations 
p = [.1 1]; %starting point 
[~, idx] = min(abs(x-p(1))); %index of closest value 
[~, idy] = min(abs(y-p(2))); %index of closest value 
p = [x(idx) y(idy)]; %closest point to start 
[xGrad,yGrad] = gradient(f); %partial derivatives of f 
xGrad = xGrad/dx; %scale correction 
yGrad = yGrad/dy; %scale correction 

for i=1:tooMuch %prevents too many iterations  
    fGrad = [ xGrad(idx,idy) , yGrad(idx,idy) ]; %gradient's definition 
    pTMP = p(end,:) - lr*fGrad; %gradient descent's core 
    [~, idx] = min(abs(x-pTMP(1))); %index of closest value 
    [~, idy] = min(abs(y-pTMP(2))); %index of closest value 
    p = [p;x(idx) y(idy)]; %add the new point 
    if sqrt(sum((p(end,:)-p(end-1,:)).^2)) < eps %check conversion 
     break 
    end 
end 

Спасибо любому, кто помогает

изменить: исправлены опечатки и сделали код более четким. Он по-прежнему делает то же самое и имеет ту же проблему

+3

Тангенциальный комментарий: Это необычно, чтобы прекомпретировать градиент на сетке, подобной этому. Я думаю, вы не должны работать на сетке. Это значительно упростит код, а также будет более правильным и даст лучшие результаты. – littleO

+0

Я показываю это в конце как диаграмма стрелки (используя «колчан»), но если вы можете показать мне способ более градиента вычислить, я буду счастлив (возможно, по ссылке на некоторую документацию) –

+0

Я предполагаю, что это в основном для учебных целей. Для такой проблемы нет необходимости выстраивать все. Вы можете отслеживать x_val и y_val без индексов, сеток и т. Д. ... и вычислять градиент, беря частные производные самостоятельно: 'fGrad = [2 * x_val, 2 * y_val]'.Для многих функций вы можете автоматически вычислять градиент автоматически с помощью автоматического дифференцирования (для этого есть несколько пакетов). –

ответ

1

В конце концов я Жду» t выяснить, что было не так с предыдущим методом, но вот альтернативный сценарий для градиента приличный, который я использовал для s AME вопрос:

syms x y 
f = -20*(x/2-x^2-y^5)*exp(-x^2-y^2); %cost function 
% f = x^2+y^2; %simple test function 

g = gradient(f, [x, y]); 
lr = .01; %learning rate 
eps = 1e-10; %convergence threshold 
tooMuch = 1e3; %iterations' limit 
p = [1.5 -1]; %starting point 
for i=1:tooMuch %prevents too many iterations 
    pGrad = [subs(g(1),[x y],p(end,:)) subs(g(2),[x y],p(end,:))]; %computes gradient 
    pTMP = p(end,:) - lr*pGrad; %gradient descent's core 
    p = [p;double(pTMP)]; %adds the new point 
    if sum((p(end,:)-p(end-1,:)).^2) < eps %checks convergence 
     break 
    end 
end 
v = -3:.1:3; %desired axes 
[X, Y] = meshgrid(v,v); 
contour(v,v,subs(f,[x y],{X,Y})) %draws the contour lines 
hold on 
quiver(v,v,subs(g(1), [x y], {X,Y}),subs(g(2), [x y], {X,Y})) %draws the gradient directions 
plot(p(:,1),p(:,2)) %draws the route 
hold off 
suptitle(['gradient descent route from ',mat2str(round(p(1,:),3)),' with \eta=',num2str(lr)]) 
if i<tooMuch 
    title(['converged to ',mat2str(round(p(end,:),3)),' after ',mat2str(i),' steps']) 
else 
    title(['stopped at ',mat2str(round(p(end,:),3)),' without converging']) 
end 

лишь некоторые из результатов

enter image description here

enter image description here

В последнем случае вы можете видеть, что это не сходится, но это не проблема с градиентом спуск, только слишком высокая скорость обучения (поэтому он несколько раз пропускает минимальную точку).

приветствуется использовать его.

+0

Пока мы ждем 48-часового льготного периода, после которого вы можете принять свой собственный ответ, рассмотрите возможность загрузки изображений непосредственно в Stack Overflow. Таким образом, ваш ответ будет оставаться полным, пока SO вокруг. –

+0

О, хорошо, я думал об эффективности использования пространства. –

+0

Это хороший момент, но распад ссылок - это скорее проблема :) Это также причина, по которой ссылки не принимаются. –

1

X-матрица, возвращаемая meshgrid, имеет возрастающие значения X в столбцах, а не в строках! Например [X, Y] = meshgrid(-1:1, 1:3) возвращает

 [-1 0 1;   [1 1 1; 
X = -1 0 1;  Y = 2 2 2; 
    = -1 0 1];   3 3 3]; 

Обратите внимание, как х-индекс должен быть помещен в колонку X или Y, а Y-индекс должен быть помещен в ряд. В частности, ваша линия:

fGrad = [ xGrad(idx,idy) , yGrad(idx,idy) ]; %gradient's definition 

вместо этого следует:

fGrad = [ xGrad(idy,idx) , yGrad(idy,idx) ]; %gradient's definition 

Переменной idy должны индексировать ряд и idx переменных должна индексировать колонок

+0

Я могу понять, почему я написал это неправильно, но когда я попробовал ваше решение, он все равно не работал (это было на 'X.^2 + Y.^2', но не на' -20 * (X/2- X.^2-Y.^5) * exp (-X.^2-Y.^2) ') –

+0

Я думаю, что проблема заключается не в проблеме прямого кодирования, а в более сложных проблемах с численной оптимизацией. Эта проблема [глубоко не выпуклая] (http://www.mattgunn.com/delme_opt.png), если вы не наложили на нее никаких ограничений. –

+0

Если вы посмотрите на график, на нем есть локальные минимумы. –

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