Using automatic differentiation (dlgradient) for Euler's Method (gradient descent)

4 visualizzazioni (ultimi 30 giorni)
I am trying to use automatic differentiation to approach several optimization problems that I usually solve using gradient descent techniques such as Euler's Method. dlgradient works well as a drop-in solution sometimes, but it sometimes fails even in some simple cases that use only basic arithmetic operations. For instance, I have the following toy problem, which is a much simpler version of a problem I actually want to solve (but still fails):
I have a 2D matrix. I define a binary mask of the same size, and I want to use gradient descent to fill the pixels inside of the mask with 1s (yes, I know I can do this with 1 line of code :) ). I have defined three cost functions (below), and only the first one (cost1) works as I would expect. Is there an issue with cost2 and cost3 that I am missing?
I = sum((x(:)),1:2);
cost1 = -sum(x.*msk,1:2);
cost2 = -sum(abs(x.*msk),1:2);
cost3 = -sum(x.*msk./I,1:2);
For reference, here is the full code:
% Use autograd to try to put pixels inside of a mask
% Generate Grids
x = -100:99;
y = x(:);
R = sqrt(x.^2+y.^2);
msk = R<7;
msk = msk-mean(msk(:));
% msk = (msk-.5)*2;
% Random starting guess
randn('seed',0);
zprand = randn(size(msk));
% Starting Guess
zp = dlarray(1*(zprand));
clc
% Loop
mns=[];
mxs=[];
mns = mean(extractdata(zp(:)).*(msk(:)<=0));
mxs = mean(extractdata(zp(:)).*(msk(:)>0));
N = 20;
for i = 1:N
% Calculate Gradient
[fval,grad] = dlfeval(@autodiff,zp,msk);
% Follow Gradient
zp = zp-.25*grad;
% Store mean within different regions of the mask
mns(i+1) = mean(extractdata(zp(:)).*(msk(:)<=0));
mxs(i+1) = mean(extractdata(zp(:)).*(msk(:)>0));
% Plot
figure(1);
imagesc(extractdata(zp));
colorbar
title(i)
drawnow
end
% Plot Progression
figure(2);
plot(1:N+1,mns,1:N+1,mxs)
% Functions
% Gradient
function [y,dydx] = autodiff(zp,msk)
y = costFunction(zp,msk);
dydx = dlgradient(y,zp);
end
% Cost Function
function cost1 = costFunction(x,msk)
I = sum((x(:)),1:2);
cost1 = -sum(x.*msk,1:2);
cost2 = -sum(abs(x.*msk),1:2);
cost3 = -sum(x.*msk./I,1:2);
% cost4 = sum(abs(zp-msk).^2,1:2);
end

Risposte (1)

Altaïr
Altaïr il 12 Feb 2025
Modificato: Altaïr il 12 Feb 2025
It sounds like the goal is to set the pixels inside the mask to 1 and those outside to 0. Here are a few adjustments that can be made to achieve this:
1. Remove the line msk = msk - mean(msk(:)); as it drives the pixels towards normalized values rather than exactly 1 or 0.
2. Ensure that the means are calculated only for the relevant pixels by changing the following lines:
mns = mean(extractdata(zp(msk <= 0))); % Update mean for pixels outside mask
mxs = mean(extractdata(zp(msk > 0))); % Update mean for pixels inside mask
Update the equations for mxs(i+1) and mns(i+1) accordingly.
3. It's preferable for the cost function to be convex with a unique minimum. The minimum should correspond to the 2D matrix elements matching the desired image msk. An example cost function is:
cost1 = sum((x - msk).^2, 1:2);
This cost function becomes zero when the current image x matches the desired image msk elementwise.
Also, remember to modify the plotting line for the second figure accordingly. For x defined as an integer array going -10 to 10 (i.e. x=-10:10), the figures are as follows after 20 iterations:
I have attached the modified code for reference. For further verification, the result can be checked using fmincon. Here are some useful links for more information:

Prodotti


Release

R2021b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by