fmincon gets very slow after few time

20 ビュー (過去 30 日間)
Miguel Ángel
Miguel Ángel 2021 年 11 月 23 日
編集済み: Matt J 2021 年 11 月 30 日
Hi all,
I am using fmincon for finding endmembers in each pixel of an image. I have a double for loop which goes pixel by pixel applying fmincon. When the code starts, each pixel optimization is pretty fast (miliseconds), but as the run advances it starts getting slower and slower. It does not have to do with memory allocation issues since I do it. Also, if I close Matlab and reopen it, if I continue in the last pixel it gets fast again for the first pixels, but again slower and slower until it takes lime one minute per pixel.
Here the example of code I am using:
maps = single(zeros(rows,columns,3)); % Create empty maps.
cont = 0;
for row = 1:rows
for col = 1:columns
cont = cont + 1;
C_MSE_subt = fmincon( @(x)SAMSID_subtractive(double(squeeze(cube(row,col,:))),E,x'), init_point, [-1 0 0; 0 -1 0; 0 0 -1 ], [0; 0; 0], [1 1 1], 1, [0 0 0], [1 1 1],[],options);
maps(row,col,:) = reshape(C_MSE_subt,1,1,3);
end
end
The optimizatiob function is pretty simple, just calculating a spectrum and comparing it against the one passed as input:
function SAMSID = SAMSID_subtractive(spectra1,E,C)
spectra2 = subtractive_model(E,C);
[~,~,SAMSID]=samsid(spectra1,spectra2);
It would seem normal to me if every pixel behaved slow. But the few first pixels very fast and then get slower and slower... Also I checked RAM and CPU and none of them are busy.
If I change the optimization function it does not get slow. For instance, using MSE instead of SAMSID metric, it is fast from the beggining to the end:
function MSE = mean_squared_error_subtractive(spectra1,E,C)
spectra2 = subtractive_model(E,C);
MSE = sum((spectra1-spectra2).^2) / size(spectra1,1);
Any ideas of why this could happen?
Thanks in advance!
  2 件のコメント
Matt J
Matt J 2021 年 11 月 23 日
What do you mean by "getting slower"? How are you observing changes in speed?
Also, what is samsid()? It does not seem to be a Mathworks-provided function.
Matt J
Matt J 2021 年 11 月 23 日
編集済み: Matt J 2021 年 11 月 23 日
Incidentally, you should get rid of your inequality constraints,
A=[-1 0 0; 0 -1 0; 0 0 -1 ]; b= [0; 0; 0];
They are redundant with your explicit lower bounds lb=[0 0 0] and are just slowing things down.

サインインしてコメントする。

回答 (2 件)

Matt J
Matt J 2021 年 11 月 23 日
I suspect samsid() is just not as smooth or well-conditioned as mse() for some pixels, and therefore takes more iterations to terminate. You can check the fmincon output to see how many iterations are being performed in each pixel and see if it correlates with the slow-down you are observing.
  8 件のコメント
Miguel Ángel
Miguel Ángel 2021 年 11 月 30 日
I did verify. The task manager has always been open with the resources tab selected. No ram variations. I have 64 GB RAM and not even 15 GB are consumed during the whole process.
Functions are local. They are not nested in the same Matlab script, but they are all as .m files in the same folder of the main code.
It is difficult to say whether it is reasonable or not, since in order to check this I would need to get the entire map and post-process it a bit to get the final presence map. But I only got barely 10 lines of it after more than three days of run. SAMSID metric is a combination of sam and sid metrics. The first one is an angle, and samsid takes the sine of this angle which is bounded in [0, 1]. SID is the spectral information divergence which has no upper bound (the lower the more similar the spectra are). SAMSID multiplies sine(sam)*sid, so also has no bounds.
Matt J
Matt J 2021 年 11 月 30 日
編集済み: Matt J 2021 年 11 月 30 日
Functions are local. They are not nested in the same Matlab script, but they are all as .m files in the same folder of the main code.
If so, they are neither local nor nested.

サインインしてコメントする。


Matt J
Matt J 2021 年 11 月 23 日
A few more performance optimizations that you should consider:
maps = zeros(rows,columns,3,'single'); %<------ post conversion to single is unnecessary
cube=double(cube); %<----pre-cast the whole array to double
cont = 0;
for row = 1:rows
for col = 1:columns
cont = cont + 1;
tmp=squeeze(cube(row,col,:)); %<------ avoid doing this in every function call
C_MSE_subt = fmincon( @(x)SAMSID_subtractive(tmp,E,x'), init_point, [], [], [1 1 1], 1, [0 0 0], [1 1 1],[],options);
maps(row,col,:) = reshape(C_MSE_subt,1,1,3);
init_point(:)=C_MSE_subt(:); %<----- the previous solution might be very close to the next one
end
end
  1 件のコメント
Miguel Ángel
Miguel Ángel 2021 年 11 月 26 日
Thanks for all valuable tips. I implemented them all:
cube = double(cube);
SAMSID = zeros(rows,columns,'single'); % Create empty SAMSID map.
ti = SAMSID; % Create empty optimization time map.
flag = SAMSID;
iter = SAMSID;
cont = 0;
for row = 1:rows
for col = 1:columns
cont = cont + 1;
clc, disp(['Generating pigments map: ' num2str(cont/num_pixels*100) '%...'])
tmp = squeeze(cube(row,col,:));
tic
[C_SAMSID_subt,SAMSID(row,col),flag(row,col),output] = fmincon( @(x)SAMSID_subtractive(tmp,E,x'), init_point, [], [], [1 1 1], 1, [0 0 0], [1 1 1],[],options);
ti(row,col) = toc;
iter(row,col) = output.iterations;
maps(row,col,:) = reshape(C_SAMSID_subt,1,1,3);
init_pont(:) = C_SAMSID_subt(:);
end
end

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeIntroduction to Installation and Licensing についてさらに検索

製品


リリース

R2020a

Community Treasure Hunt

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

Start Hunting!

Translated by