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

4 ビュー (過去 30 日間)
Michael T
Michael T 2023 年 10 月 25 日
編集済み: Altaïr 2025 年 2 月 12 日
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

回答 (1 件)

Altaïr
Altaïr 2025 年 2 月 12 日
編集済み: Altaïr 2025 年 2 月 12 日
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:

カテゴリ

Help Center および File ExchangeSolver Outputs and Iterative Display についてさらに検索

製品


リリース

R2021b

Community Treasure Hunt

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

Start Hunting!

Translated by