-
Имеется табличное представление некой функции. Требуется найти коэффициенты для её аналитического представления в виде гиперболической: f(t)=a+b/t и логарифмической: f(t)=a+b*ln(t) Проблема в том, что пока в Рунете не удалось найти ничего по этим функциям. С линейной и полиномиальной аппроксимацией проблем не было, а вот здесь... Буду рад методикам и особенно рад готовым решениям.
-
замена переменных x = 1/t и x=ln(t) сводит задачу к линейной
-
Т.е. скормить функции линейной аппроксимации для ряда t1..tn значения 1/t1..1/tn ? Кстати, такая мысль у меня мелькала в голове, и TUser посказывал в аське...
-
> Marser © (09.04.08 15:21) [2]
Да. Определяется формула, сводящая задачу к линейной; по ней делается пересчет табличных значений; решается линейная задача; если надо, то полученные коэффициенты пересчитываются на исходную функцию.
-
В общих словах:
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;
-
-
Спасибо, Сергей! Насколько я мог понять по: 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; Вы используете тот же принцип замены?
-
Так другого, вроде, и не дано:)
Пример на функции 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
Надо учитывать, что вследствии нелинейных преобразований качество на больших шумовых сигналах может оказаться неудовлетворительным.
-
> Надо учитывать, что вследствии нелинейных преобразований > качество на больших шумовых сигналах может оказаться неудовлетворительным. >
Ясно. У меня данные из другой области. Спасибо вам!
|