Нелинейные (взвешенные) оценки наименьших квадратов параметров нелинейной модели - PullRequest
0 голосов
/ 27 ноября 2018

Я пытаюсь подогнать экспоненциальные данные с помощью сигмоидальной функции (4PL) со следующей формулой:

y = a + (k-a) /(1 + exp((v-x)/c)

Хотя с RI получаются хорошие результаты, с использованием C # и фреймворка Accord.Net я очень плохоfit.

Вот мой код:

var nls = new NonlinearLeastSquares()
{
    NumberOfParameters = 4,

    StartValues = new[] {0d, 40000d, 35d,1d }

    Function = (parameters, input) =>
    {
        return parameters[0] + ((parameters[1] - parameters[0]) / ( 1 + 
        Math.Exp((parameters[2] - input[0] )/parameters[3]) ) );
    },

    Gradient = (parameters, input, result) =>
    {
        result[0] = 1 - ( 1 / (1 + Math.Exp((parameters[2] - input[0]) / 
                    parameters[3]))); // d/da
        result[1] = 1 / (1 + Math.Exp((parameters[2] - input[0]) / 
                    parameters[3])); // d/dk
        result[2] = -((parameters[1] - parameters[0])* 
                    Math.Exp((parameters[2] - input[0]) / parameters[3])) / 
                    parameters[3]*Math.Pow(1 + Math.Exp((parameters[2] - 
                    input[0]) / parameters[3]),2); // d/dv
        result[3] = ((parameters[1] - parameters[0]) * (parameters[2] - 
                    input[0]) * Math.Exp((parameters[2] - input[0]) / 
                    parameters[3])) / Math.Pow(parameters[3], 2) * 
                    Math.Pow(1 + Math.Exp((parameters[2] - input[0]) / 
                    parameters[3]), 2); // d/dc
  },

  Algorithm = new LevenbergMarquardt()
  {
      MaxIterations = 100,
      Tolerance = 0
   }
};

var regression = nls.Learn(inputs, outputs);

// The solution will be at:
double a = regression.Coefficients[0];
double k = regression.Coefficients[1];
double v = regression.Coefficients[2];
double c = regression.Coefficients[3];

Я застрял с этой проблемой, любая помощь будет очень признателен,

1 Ответ

0 голосов
/ 07 декабря 2018

Для тех, кому интересно, я нашел решение.

Проблема заключалась в градиентах результата [2] (d / dv) и результата [3] (d / dc).

В знаменателе отсутствовали скобки.

    result[2] = -((parameters[1] - parameters[0])* 
                Math.Exp((parameters[2] - input[0]) / parameters[3])) / 
                (parameters[3]*Math.Pow(1 + Math.Exp((parameters[2] - 
                input[0]) / parameters[3]),2)); // d/dv
    result[3] = ((parameters[1] - parameters[0]) * (parameters[2] - 
                input[0]) * Math.Exp((parameters[2] - input[0]) / 
                parameters[3])) / (Math.Pow(parameters[3], 2) * 
                Math.Pow(1 + Math.Exp((parameters[2] - input[0]) / 
                parameters[3]), 2)); // d/dc
...