Конференция "Основная" » Аппроксимация методом наименьших квадратов [D7]
 
  • Marser © (09.04.08 15:00) [0]
    Имеется табличное представление некой функции. Требуется найти коэффициенты для её аналитического представления в виде гиперболической:
    f(t)=a+b/t


    и логарифмической:
    f(t)=a+b*ln(t)

    Проблема в том, что пока в Рунете не удалось найти ничего по этим функциям. С линейной и полиномиальной аппроксимацией проблем не было, а вот здесь...

    Буду рад методикам и особенно рад готовым решениям.
  • MBo © (09.04.08 15:11) [1]
    замена переменных
    x = 1/t
    и
    x=ln(t)
    сводит задачу к линейной
  • Marser © (09.04.08 15:21) [2]
    Т.е. скормить функции линейной аппроксимации для ряда t1..tn значения 1/t1..1/tn ?
    Кстати, такая мысль у меня мелькала в голове, и TUser посказывал в аське...
  • Семеныч (09.04.08 15:53) [3]
    > Marser ©   (09.04.08 15:21) [2]

    Да. Определяется формула, сводящая задачу к линейной; по ней делается пересчет табличных значений; решается линейная задача; если надо, то полученные коэффициенты пересчитываются на исходную функцию.
  • Jeer © (09.04.08 16:03) [4]
    В общих словах:

    type
     TFuncRegress = function(value: TFloat): TFloat;

       TransX: TFuncRegress;
       TransY: TFuncRegress;
       TransA: TFuncRegress;
       TransB: TFuncRegress;

    function LinearTransform(value: TFloat): TFloat;
    begin
     Result := value;
    end;

    function BackTransform(value: TFloat): TFloat;
    begin
     Result := 1 / value;
    end;

    function LnTransform(value: TFloat): TFloat;
    begin
     Result := Ln(Value);
    end;

    procedure TRegression.SetRegression(idx: integer);
    begin
     Clear;
     fRegType := idx;
     case idx of
    // y = a + b * x
       0: begin
           TransX := @LinearTransform;
           TransY := @LinearTransform;
           TransA := @LinearTransform;
           TransB := @LinearTransform;
         end;
    // y = a + b * x^2
       1: begin
           TransX := @ParabolicTransform;
           TransY := @LinearTransform;
           TransA := @LinearTransform;
           TransB := @LinearTransform;
         end;
    // y = a + b * x^3
       2: begin
           TransX := @CubicTransform;
           TransY := @LinearTransform;
           TransA := @LinearTransform;
           TransB := @LinearTransform;
         end;
    // y = a + b / x
       3: begin
           TransX := @BackTransform;
           TransY := @LinearTransform;
           TransA := @LinearTransform;
           TransB := @LinearTransform;
         end;
    // y = 1 / (a + b * x)
       4: begin
           TransX := @LinearTransform;
           TransY := @BackTransform;
           TransA := @LinearTransform;
           TransB := @LinearTransform;
         end;
    // y = a*b^x
       5: begin
           TransX := @LinearTransform;
           TransY := @LgTransform;
           TransA := @DecTransform;
           TransB := @LinearTransform;
         end;

    // y = a*exp(b^x)
       6: begin
           TransX := @LinearTransform;
           TransY := @LnTransform;
           TransA := @ExpTransform;
           TransB := @LinearTransform;
         end;

    // y = a*10(b^x)
       7: begin
           TransX := @LinearTransform;
           TransY := @LgTransform;
           TransA := @Power10Transform;
           TransB := @LinearTransform;
         end;

    // y = 1 / ( A + B * exp(-x))
       8: begin
           TransX := @ExpNegTransform;
           TransY := @BackTransform;
           TransA := @LinearTransform;
           TransB := @LinearTransform;
         end;

    // y = ( A + B * Ln(x))
       9: begin
           TransX := @LnTransform;
           TransY := @LinearTransform;
           TransA := @LinearTransform;
           TransB := @LinearTransform;
         end;

    // y =  A * exp ( B / x)
       10: begin
           TransX := @BackTransform;
           TransY := @LnTransform;
           TransA := @ExpTransform;
           TransB := @LinearTransform;
         end;

    // y =  A *  x ^5
       11: begin
           TransX := @PowerX5Transform;
           TransY := @LinearTransform;
           TransA := @LinearTransform;
           TransB := @LinearTransform;
         end;

     end;
    end; // SetRegression

    function TRegression.Next(const X: TFloat; const Y: TFloat = 0): TFloat;
    begin
     if fCount = 0 then begin
       fFirstX := X;
       fFirstY := Y;
     end;
     fLastX := X;
     fLastY := Y;

     if X >= fMaxX then fMaxX := X;
     if X < fMinX then fMinX := X;

     if Y >= fMaxY then fMaxY := Y;
     if Y < fMinY then fMinY := Y;

     Result := Add(TransX(X), TransY(Y));

     Inc(fCount);

    end {Next value};

    function TRegression.Add(const X: TFloat; const Y: TFloat = 0): TFloat;
    begin
     fSumX := fSumX + X;
     fSumY := fSumY + Y;
     fSumXX := fSumXX + X * X;
     fSumYY := fSumYY + Y * Y;
     fSumXY := fSumXY + X * Y;
     Result := fSumY;
    end {Add value};

    procedure TRegression.GetCoeff;
    var Qx, Qy, Qxy, Qz: TFloat;
    begin
     Qz := fSumY * fSumXX - fSumX * fSumXY;
     Qxy := fCount * fSumXY - fSumX * fSumY;
     Qx := fCount * fSumXX - sqr(fSumX);
     Qy := fCount * fSumYY - sqr(fSumY);

     fA := TransA(Qz / Qx);
     fB := TransB(Qxy / Qx);
     fR := Qxy / sqrt(Qx * Qy);
    end;

    function TRegression.Calc(value: TFloat): TFloat;
    begin
     Result := 0.0;
     case fRegType of
       0: Result := fA + fB * Value; // y = A + B * x
       1: Result := fA + fB * Value * Value; // y = A + B * x^2
       2: Result := fA + fB * Value * Value * Value; // y = A + B * x^3
       3: Result := fA + fB / Value; // y = A + B / x
       4: Result := 1 / (fA + fB * Value); // y = 1 / (A + B * x)
       5: Result := fA * Power(fB, Value); // y = A * B ^ x
       6: Result := fA * Exp(fB * Value); // y = A * exp( B * x )
       7: Result := fA * power(10, fB * Value); // y = A * 10^( B * x )
       8: Result := 1 / (fA + fB * exp(-Value)); // y = 1 / (A + B * exp(-x))
       9: Result := fA + fB * Ln(Value); // y =  (A + B * Ln(-x))
       10: Result := fA * Exp(fB / Value); // y =  A * exp (B / x)
       11: Result := fA + fB * Value * Value * Value * Value * Value;
     end;
    end;
  • Jeer © (09.04.08 16:20) [5]
    Как это выглядит:
    http://slil.ru/25670910
  • Marser © (09.04.08 18:08) [6]
    Спасибо, Сергей! Насколько я мог понять по:

    function LinearTransform(value: TFloat): TFloat;
    begin
    Result := value;
    end;

    function BackTransform(value: TFloat): TFloat;
    begin
    Result := 1 / value;
    end;

    function LnTransform(value: TFloat): TFloat;
    begin
    Result := Ln(Value);
    end;



    Вы используете тот же принцип замены?
  • Jeer © (09.04.08 18:21) [7]
    Так другого, вроде, и не дано:)

    Пример на функции y = a*x/(b+x)

    Преобразуем к a/y - b/x - 1 = 0
    т.к. на реальных данных нуля не будет, то минимизируем сумму кв.
    d^2 = sum(a/Yi - b/Xi - 1)^2
    Для минимума надо чтобы производные по a и b были равны 0
    Откуда
    a*sum(1/Yi^2) - b*sum(1/(Xi*Yi) = sum(1/Yi)
    a*sum(1/(Xi*Yi)) - b*sum(1/Xi^2) = sum(1/Xi)

    Решение дает a и b

    Надо учитывать, что вследствии нелинейных преобразований качество на больших шумовых сигналах может оказаться неудовлетворительным.
  • Marser © (09.04.08 18:45) [8]

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

    Ясно. У меня данные из другой области. Спасибо вам!
 
Конференция "Основная" » Аппроксимация методом наименьших квадратов [D7]
Есть новые Нет новых   [134487   +52][b:0][p:0.001]