dyeung Ответов: 3

Солвер, чтобы соответствовать 2Д распределение Гаусса


Привет,

Я использую C# и решатель, чтобы соответствовать 2D-Гауссу. Используя смоделированные данные (без шума) с различными сигмами, интенсивностями и центром, он работал идеально. Однако с реальными данными он работает только около 50% времени, хотя все тестовые данные представляют собой изображения примерно одинакового качества и приблизительно одинаковые Сигмы для обоих x и y. могу ли я отправить код, чтобы кто-то, у кого больше опыта, мог увидеть, что я сделал неправильно.

Изображения имеют размер около 100x100 с разрешением 5 мм и сигмами около 7 мм как для x, так и для Y.

Когда это не удалось, он потерпел неудачу со значениями сигм и интенсивности, близкими к 0.0.

Это такая простая проблема, я не думаю, что решатель не может справиться с ней, и данные совсем не так шумны. Это должно быть что-то тонкое, что я не построил модель должным образом.

Я был бы очень признателен, если бы кто-нибудь мог помочь.

Спасибо,

Даниил

Вот основной код
var solver = SolverContext.GetContext();
            solver.ClearModel();
            var model = solver.CreateModel();
                 
            var decisionsA = Spot_Params.Spot_ParamsA.Select(
                it => new Decision(Domain.RealNonnegative, it.Key));
            model.AddDecisions(decisionsA.ToArray());
            var decisionsB = Spot_Params.Spot_ParamsB.Select(
                it => new Decision(Domain.Real, it.Key));
            model.AddDecisions(decisionsB.ToArray());
          
            var objective = new SumTermBuilder(gaussMatrix.Data_1D.Count());
            var sx = model.Decisions.ElementAt(0);           
            var sy = model.Decisions.ElementAt(1);           
            var sf = model.Decisions.ElementAt(2);            
            var cx = model.Decisions.ElementAt(3);            
            var cy = model.Decisions.ElementAt(4);           

            var sx_sq_2_inv = 1.0 / (sx * sx * 2.0);
            var sy_sq_2_inv = 1.0 / (sy * sy * 2.0);
                      
            int n = 0;
            for (int j = 0; j < gaussMatrix.Nrow; j++)
            {
                var dy = gaussMatrix.Ypos[j] - cy;

                for (int i = 0; i < gaussMatrix.Ncol; i++)
                {                              
                    var dx = gaussMatrix.Xpos[i] - cx;
                    var v = (dx * dx) * sx_sq_2_inv + (dy * dy) * sy_sq_2_inv;                  
                    var value = sf * Model.Exp(-v);
                    var diff = gaussMatrix.Data_1D[n++] - value;

                    objective.Add(diff * diff);
                }
            }

            model.AddGoal("OptimizedSpotParams", GoalKind.Minimize, objective.ToTerm());
                      
            // Extract fitted parameters
          
            var spot_params = fittedParams.Spot_Params;
            Solution solution;
            solution = await Task.Run(() => solver.Solve());


Что я уже пробовал:

Просмотр кода и входных данных. Не видел ничего явно неправильного

3 Ответов

Рейтинг:
2

Gerry Schmitz

Цитата:
Когда это не удалось, он потерпел неудачу со значениями сигм и интенсивности, близкими к 0.0.


Продолжайте тестирование и выясните, "где" он терпит неудачу; "близко к" хорошо только в лошадиных ботинках.


Рейтинг:
2

Patrice T

Цитата:
Это такая простая проблема, я не думаю, что решатель не может справиться с ней, и данные совсем не так шумны. Это должно быть что-то тонкое, что я не построил модель должным образом.

ваш код работает в зависимости от данных, и без этих данных мы не можем найти, что не так.

Ваш код ведет себя не так, как вы ожидаете, или вы не понимаете, почему !

Существует почти универсальное решение: запускайте свой код на отладчике шаг за шагом, проверяйте переменные.
Отладчик здесь, чтобы показать вам, что делает ваш код, и ваша задача-сравнить с тем, что он должен делать.
В отладчике нет никакой магии, он не знает, что должен делать ваш код, он не находит ошибок, он просто помогает вам, показывая, что происходит. Когда код не делает того, что ожидается, вы близки к ошибке.
Чтобы увидеть, что делает ваш код: просто установите точку останова и посмотрите, как работает ваш код, отладчик позволит вам выполнять строки 1 на 1 и проверять переменные по мере их выполнения.

Отладчик - Википедия, свободная энциклопедия[^]

Освоение отладки в Visual Studio 2010 - руководство для начинающих[^]
Базовая отладка с помощью Visual Studio 2010 - YouTube[^]

Отладка кода C# в Visual Studio - YouTube[^]

Отладчик здесь только для того, чтобы показать вам, что делает ваш код, и ваша задача-сравнить его с тем, что он должен делать.


dyeung

Одна вещь, которую я потенциально делаю неправильно, заключается в том, что я предполагаю, что переменные, определенные в словаре, находятся в том порядке, в котором я добавил. Как уже было предупреждено, порядок хэш-таблицы недетерминирован. Однако при использовании отладчика переменные sx, sy и т. д. действительно соединялись с ожидаемыми ключами. Может быть, во время выполнения это не обязательно так.

Попытаюсь изменить код, чтобы назначить переменную с помощью "ключей" вместо этого, и посмотреть, поможет ли это.

Даниил

dyeung

Этот вопрос не был связан со словарем. Проблема сохраняется даже при добавлении решений одно за другим, чтобы быть уверенным в точном порядке. Не помочь.

dyeung

Кто-нибудь может показать мне, как добавить ограничение в модель? Например, такое, что решение sx ("SigmaX") должно быть больше 1. Оптимизация не остановится после добавления ограничения:

модель.AddConstraint("sx_min", "SigmaX > 1.0");

Рейтинг:
2

dyeung

Спасибо за ответ.
Я прошел через отладчик. Но оптимизирующий код не показывает вам фактический запуск, за исключением "переменных", определенных без фактических значений, поэтому нет никакого способа (насколько я знаю) выяснить, что происходит во время оптимизации.

Данные и код очень просты. Могу ли я предоставить кому-то zip-файл, чтобы попробовать его?

У меня есть данные, которые работают, и данные, которые терпят неудачу.

Спасибо,

Даниил