Convergence of lsqisotonic (in mdscale)
1 次查看(过去 30 天)
显示 更早的评论
Hi, I am trying to figure out why lsqisotonic does not converge in mdscale (in both stress and sstress criterions) after many hours on a powerful machine. I changed the code a bit to print the number of non-monotonic blocks, and it seems to get stuck at some point.
Is convergence guaranteed? Is there any approaches to speed-up / run this method in parallel?
I would appreciate if someone could direct me to an explanation of this method in laymen's terms. I am new to MDS, so please be gentle.
Here is the part that gets stuck:
diffs = diff(yhat);
while any(diffs<0) % If all blocks are monotonic, then we're done.
diffs = diff(yhat);
% Otherwise, merge blocks of non-increasing fitted values, and set the
% fitted value within each block equal to a constant, the weighted mean
% of values in that block.
idx = cumsum([1; (diffs>0)]);
sumyhat = accumarray(idx,w.*yhat);
w = accumarray(idx,w);
yhat = sumyhat ./ w;
block = idx(block);
display(horzcat(num2str(sum(diffs<0)),' non monotonic blocks left. magnitude=',num2str(norm(yhat))))
end
Command window:
...
10 non monotonic blocks left. magnitude=118.9195
10 non monotonic blocks left. magnitude=118.9161
10 non monotonic blocks left. magnitude=118.9127
10 non monotonic blocks left. magnitude=118.9093
10 non monotonic blocks left. magnitude=118.9059
10 non monotonic blocks left. magnitude=118.9026
10 non monotonic blocks left. magnitude=118.8992
10 non monotonic blocks left. magnitude=118.8958
10 non monotonic blocks left. magnitude=118.8924
10 non monotonic blocks left. magnitude=118.8891
10 non monotonic blocks left. magnitude=118.8857
10 non monotonic blocks left. magnitude=118.8823
10 non monotonic blocks left. magnitude=118.8789
10 non monotonic blocks left. magnitude=118.8756
10 non monotonic blocks left. magnitude=118.8722
10 non monotonic blocks left. magnitude=118.8688
10 non monotonic blocks left. magnitude=118.8655
10 non monotonic blocks left. magnitude=118.8621
10 non monotonic blocks left. magnitude=118.8588
10 non monotonic blocks left. magnitude=118.8554
10 non monotonic blocks left. magnitude=118.852
0 个评论
回答(2 个)
Peter Perkins
2011-10-27
Shay, it kind of impossible to say what's going on here without knowing what's in the data. At each loop iteration, the lines
idx = ...
...
yhat = ...
ought to be merging the runs of decreasing values, and decreasing the lengths of yhat and block. That seems to not be happening, but you'll have to look at some of those vectors to really figure out why the call to accumarray doesn't seem to be "accumulating". Look at [yhat(:) diffs(:) idx(:)] perhaps. It may simply be that you have some kind of garbage in your data that you're not mentioning.
3 个评论
Peter Perkins
2011-10-28
Shay, now that I look at your output, it's not even clear from what you've said that the loop itself is running for a large number of iterations, or whether it is just being called a large number of times. There's just not enough information here to get very far.
If it is the former, which is how I interpreted your "getting stuck", then what you would hope to see is that at each iteration of that loop, the number of elements where diffs<0 decreases until there are none. If you look at [yhat(:) diffs(:) idx(:)] as I suggested, just before the first call to accumarray, you should see that runs of decreasing yhat values are all assigned the same index, and that the next time around that set of yhat values are all the same -- setting yhat values within one block is what the last four lines of that loop do. Actually, I guess you'd have to look at [0; diffs(:)] to make it the right length.
This algorithm does nothing more than find runs of decreasing values, and replace them with their mean.
But you should make sure that it really is getting stuck in that loop, and that the problem is not that outer optimization is just taking a lot of steps. This is after all a _very_ high dimensional optimization.
Yun Wang
2017-10-30
编辑:Yun Wang
2017-11-2
I replaced the part of the code that gets stuck with the following code:
n = length(yhat);
b = 0; bstart = zeros(1,n); bend = zeros(1,n);
for i = 1:n
b = b + 1;
yhat(b) = yhat(i);
w(b) = w(i);
bstart(b) = i; bend(b) = i;
while b > 1 && yhat(b) < yhat(b-1)
yhat(b-1) = (yhat(b-1) * w(b-1) + yhat(b) * w(b)) / (w(b-1) + w(b));
w(b-1) = w(b-1) + w(b);
bend(b-1) = bend(b);
b = b - 1;
end
end
idx = zeros(1,n);
for i = 1:b
idx(bstart(i) : bend(i)) = i;
end
block = idx(block);
This code segments merges blocks in a O(n), non-iterative fashion. The original implementation is O(n) in each iteration and therefore O(n^2) in total, which is why it can get stuck.
You can download the updated lsqisotonic function here: https://www.mathworks.com/matlabcentral/fileexchange/64933-lsqisotonic-x-y-w-
0 个评论
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Introduction to Installation and Licensing 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!