2009-08-31 15 views
10

Ich bin auf der Suche nach einer nichtlinearen Kurvenanpassungsroutine (wahrscheinlich am wahrscheinlichsten in R oder Python zu finden, aber ich bin offen für andere Sprachen), die x, y Daten und passe eine Kurve an.Finden einer Kurve, um Daten zu entsprechen

Ich sollte in der Lage sein, als eine Zeichenfolge den Typ des Ausdrucks anzugeben, den ich anpassen möchte.

Beispiele:

"A+B*x+C*x*x" 
"(A+B*x+C*x*x)/(D*x+E*x*x)" 
"sin(A+B*x)*exp(C+D*x)+E+F*x" 

Was aus diesem Ich würde die Werte für die Konstanten (A, B, C, etc.) Und hoffentlich Statistiken über die Fitness des Spiels zumindest bekommen.

Es gibt kommerzielle Programme, um dies zu tun, aber ich erwartete, in der Lage zu sein, etwas zu finden, das so häufig ist, passend zu einem gewünschten Ausdruck in einer Sprachbibliothek heutzutage. Ich vermute, dass SciPy's Optimierungskram dazu in der Lage ist, aber ich kann nicht sehen, dass es mir erlaubt, eine Gleichung zu definieren. Ebenso kann ich anscheinend nicht genau finden, was ich in R. will.

Ist, was ich da draußen suche, oder muss ich meine eigenen rollen? Ich hasse es zu tun, wenn es da ist und ich habe nur Schwierigkeiten, es zu finden.

Edit: Ich möchte dies für ein bisschen mehr Kontrolle über den Prozess als ich von LAB Fit bekommen. Das LAB Fit UI ist schrecklich. Ich möchte auch in der Lage sein, den Bereich in mehrere Teile zu zerlegen und verschiedene Kurven für die verschiedenen Teile des Sortiments zu haben. Am Ende muss das Ergebnis in der Lage sein, eine LUT mit linearer Interpolation (Geschwindigkeit) zu schlagen, oder ich bin nicht interessiert.

In meiner aktuellen Reihe von Problemen habe ich trig Funktionen oder exp() und ich muss sie 352.800 mal pro Sekunde in Echtzeit ausführen (und verwenden Sie nur einen Bruchteil der CPU). Also zeichne ich die Kurve und verwende die Daten, um den Kurvenanpasser zu fahren, um weniger teure Annäherungen zu erhalten. In den alten Tagen waren LUTs fast immer die Lösung, aber heutzutage ist es manchmal schneller, die Speicher-Lookups zu überspringen und eine Annäherung durchzuführen.

+0

Ist dir klar, dass dies eine wirklich schlechte Idee ist, statistisch gesehen? Wenn Sie nur eine flexible Anpassung an Ihre Daten wünschen, verwenden Sie ein flexibles Modell wie Löss, Splines oder generalisierte additive Modelle. – hadley

+0

Selbst wenn ich den Bereich in kleinere Bereiche unterteile, muss ich vorsichtig sein. Ich habe Zugriff auf alle möglichen Interpolatoren für Audiodaten, aber für mich sind sie im Allgemeinen viel zu rechenintensiv. Im Allgemeinen, wenn ich anfangen muss, die Reihe in Stücke zu brechen, bin ich besser dran mit einer LUT. Approximationen von Kurven sind in DSP-Anwendungen immer noch ziemlich nützlich. – Nosredna

Antwort

8

Um Ihre Frage in einem allgemeinen Sinne (in Bezug auf Parameterschätzung in R) zu beantworten, ohne die Besonderheiten der Gleichungen zu berücksichtigen, auf die Sie hingewiesen haben, denke ich, dass Sie nach nls() oder optim() suchen ...'nls' ist meine erste Wahl, da es Fehlerschätzungen für jeden geschätzten Parameter liefert und wenn es fehlschlägt, verwende 'optim'. Wenn Sie Ihre x, y Variablen:

out <- tryCatch(nls(y ~ A+B*x+C*x*x, data = data.frame(x,y), 
       start = c(A=0,B=1,C=1)) , 
       error=function(e) 
       optim(c(A=0,B=1,C=1), function(p,x,y) 
         sum((y-with(as.list(p),A + B*x + C*x^2))^2), x=x, y=y)) 

auf die Koeffizienten zu bekommen, so etwas wie

getcoef <- function(x) if(class(x)=="nls") coef(x) else x$par 
getcoef(out) 

Wenn Sie die Standardfehler im Fall von 'nls' wollen,

summary(out)$parameters 

Die Hilfedateien und R-Hilfe-Mailinglistenbeiträge enthalten viele Diskussionen bezüglich spezifischer Minimierungsalgorithmen, die von jedem implementiert sind (der Standard, der in jedem obigen Beispielfall verwendet wird) und deren Angemessenheit für das spezifische f Ordnung der vorliegenden Gleichung. Bestimmte Algorithmen können Box-Constraints verarbeiten, und eine andere Funktion namens constrOptim() behandelt eine Menge linearer Constraints. Diese Website kann auch helfen:

http://cran.r-project.org/web/views/Optimization.html

+0

Kann ich die Formel als Zeichenfolgen eingeben? – Nosredna

+1

ja - etwas wie as.formula (einfügen ("y", "A + B * x + C * x^2", sep = "~")) sollte es tun. – hatmatrix

+0

das war im Fall nls, in optimis so etwas wie eval (parse (text = sprintf ("Summe ((y-% s)^2)", "A + B * x + C * x^2"))) sollte funktionieren (die Sprintf-Konstruktion wird angezeigt, damit Sie die Formel einfügen können, die Sie wünschen). – hatmatrix

1

Check out GNU Octave - zwischen seinem polyfit() und dem nichtlinearen Constraints Solver sollte es möglich sein, etwas für Ihr Problem passendes zu konstruieren.

+0

Ich benutze Octave manchmal. Ich werde sehen, was ich herausfinden kann. – Nosredna

8

Ihr erstes Modell ist eigentlich linear in den drei Parametern und kann in R mit

fit <- lm(y ~ x + I(x^2), data=X) 

welche erhalten Sie Ihre drei Parameter passen.

Das zweite Modell kann auch Startwerte mit den üblichen Einschränkungen des Habens Verwendung nls() in R passen werden, um usw. Die statistischen Probleme bei der Optimierung sind nicht unbedingt die gleiche wie die numerischen Probleme - man kann nicht einfach Optimieren Sie jede funktionale Form, egal welche Sprache Sie wählen.

+3

Obwohl es besser wäre mit 'y ~ poly (x, 2)' oder 'y ~ ns (x, 2)' – hadley

1

Wahrscheinlich werden Sie keine einzige Routine mit der Flexibilität finden, die in Ihren Beispielen enthalten ist (Polynome und rationale Funktionen mit der gleichen Routine), geschweige denn eine, die eine Zeichenkette analysiert, um herauszufinden, welche Gleichung passt .

Ein Polynom-Fitter der kleinsten Quadrate wäre für Ihr erstes Beispiel geeignet. (Es liegt an Ihnen, welches Grad-Polynom zu verwenden ist - quadradisch, kubisch, quartal usw.). Für eine rationale Funktion, wie in Ihrem zweiten Beispiel, müssen Sie möglicherweise eine eigene Rolle erstellen, wenn Sie keine geeignete Bibliothek finden.Denken Sie auch daran, dass ein Polynom mit ausreichend hohem Grad verwendet werden kann, um Ihre "echte" Funktion zu approximieren, solange Sie nicht über die Grenzen des Datensatzes extrapolieren müssen, zu dem Sie passen.

Wie andere bemerkt haben, gibt es andere, verallgemeinerte Algorithmen zur Parameterschätzung, die sich ebenfalls als nützlich erweisen könnten. Aber diese Algorithmen sind nicht ganz "plug and play": Sie erfordern normalerweise, dass Sie einige Hilfsroutinen schreiben und eine Liste von Anfangswerten für die Modellparameter angeben. Es ist möglich, dass diese Arten von Algorithmen divergieren oder in einem lokalen Minimum oder Maximum hängen bleiben, um eine unglückliche Wahl von Anfangsparameterschätzungen zu treffen.

+0

Wenn ich die kommerziellen Produkte verwende, habe ich normalerweise keine Idee_, was am besten funktioniert. LAB Fit wird mehrere hundert Gleichungen ausprobieren, um zu sehen, was in dem von mir angegebenen Bereich am besten zu den Daten passt. – Nosredna

+0

Ich habe diesen Anwendungsfall nicht berücksichtigt - wenn Sie sich in einem frühen Stadium des Charakters eines Datensatzes befinden, ist es sinnvoll, mehrere Funktionsfamilien zu testen (linear, polynomisch, Potenzgesetz, periodisch ...) um zu sehen, wie eine gute Passform aussehen könnte. Ich werde meine Antwort entsprechend bearbeiten. –

+0

"Es ist möglich, dass diese Art von Algorithmen divergieren ..." Ja, ich gehe davon aus, dass die kommerziellen Programme einfach ausweichen, wenn dies bei der Überprüfung aller Optionen geschieht. Sie können mit Anfangswerten spielen, wenn Sie jeweils einen Ausdruck auswählen. – Nosredna

1

In R ist das ziemlich einfach.

Die integrierte Methode heißt optim(). Es nimmt als Argumente einen Startvektor potentieller Parameter und dann eine Funktion an. Sie müssen Ihre eigene Fehlerfunktion erstellen, aber das ist wirklich einfach.

Dann rufen Sie es = optim wie (1, err_fn)

wo err_fn ist

err_fn = function(A) { 
    diff = 0; 
    for(i in 1:data_length){ 
     x = eckses[i]; 
     y = data[i]; 
     model_y = A*x; 
     diff = diff + (y - model_y)^2 
    } 
    return(diff); 
} 

Dies ist nur vorausgesetzt, dass Sie einen Vektor von x und y-Werte in eckses und Daten haben. Ändern Sie die Zeile "model_y" nach eigenem Ermessen, fügen Sie sogar weitere Parameter hinzu.

Es funktioniert auf nichtlineare gerade gut, ich verwende es für vierdimensionale e^x Kurven und es ist sehr schnell. Die Ausgabedaten enthalten den Fehlerwert am Ende der Anpassung, der ein Maß dafür ist, wie gut er passt, gegeben als Summe der quadrierten Differenzen (in meinem err_fn).

EDIT: Wenn Sie das Modell als Zeichenfolge aufnehmen müssen, können Sie Ihre Benutzerschnittstelle diesen ganzen Modellanpassungsprozess als ein R-Skript erstellen und laden, um auszuführen. R kann Text aus STDIN oder aus einer Datei aufnehmen. Daher sollte es nicht zu schwierig sein, das String-Äquivalent dieser Funktion zu erstellen, und sie muss automatisch optimal ausgeführt werden.

+0

Aber warum nicht nls() in R? –

+0

Ich benutze nls nicht aus zwei Gründen, erstens, ich mag es, die Fehlerfunktion in Handarbeit zu machen, um optimiert zu werden, und zweitens bin ich nicht wirklich alles, was ich mit R erlebt habe. Also macht nls genau das, was ich oben geschrieben habe ? Ordentlich. – Karl

+0

Mein ultimatives Ziel ist es, eine Liste von Strings zu übergeben und den Code auszuprobieren, um die beste Lösung zu finden. – Nosredna

1

Wenn Sie Einschränkungen für Ihre Koeffizienten haben und wissen, dass es eine bestimmte Art von Funktion gibt, die Sie an Ihre Daten anpassen möchten, und diese Funktion ist unordentlich, wenn Standard-Regressionsmethoden oder andere Kurvenanpassungsmethoden gewonnen werden. t Arbeit, hast du genetische Algorithmen in Betracht gezogen?

Sie sind nicht meine erste Wahl, aber wenn Sie versuchen, die Koeffizienten der zweiten Funktion, die Sie erwähnten, zu finden, dann würden vielleicht GAs funktionieren --- vor allem, wenn Sie nicht standardmäßige Metriken zur Bewertung der besten Anpassung verwenden. zum Beispiel, wenn Sie die Koeffizienten von "(A + Bx + Cx^2)/(Dx + Ex^2)" so finden möchten, dass die Summe der quadratischen Differenzen zwischen Ihrer Funktion und den Daten minimal ist und Einige Einschränkungen für die Bogenlänge der resultierenden Funktion, dann könnte ein stochastischer Algorithmus ein guter Weg sein, sich diesem zu nähern.

einige Vorbehalte: 1) stochastische Algorithmen werden die beste Lösung nicht garantieren, aber sie werden oft sehr nah sein. 2) Sie müssen auf die Stabilität des Algorithmus achten. Wenn Sie sich auf der Stufe befinden, an der Sie eine Funktion aus einem Bereich von Funktionen finden möchten, die am besten zu Ihren Daten passen (z. B. werden Sie das zweite Modell nicht auf Ihre Daten anwenden.)), können auch genetische Programmiertechniken helfen.

+0

Das ist eine interessante Idee. Ich werde darüber nachdenken. Offensichtlich wäre es langsam. Die kommerziellen Programme durchlaufen Hunderte von Gleichungsformen in Sekunden. – Nosredna

+0

Ja, ein weiterer Nachteil ist, dass stochastische Algorithmen langsam sein können. Auf der anderen Seite ist es möglich, außerhalb der Menge, die kommerzielle Programme durchlaufen, eine Gleichung zu erhalten. indem man einem genetischen Programm erlaubt, durch * Klassen * von Funktionen (mit Operationen an diesen Funktionen) zu suchen, wie Potenzfunktionen, Exponentialfunktionen, Logarithmen, Triggerfunktionen, pdfs/cdfs usw., ist es möglich, eine Lösung zu finden, die nicht durch eine feste gegeben ist Satz von Gleichungsformen. aber wiederum auf der Unterseite erfordert dies eine vernünftige Front-Coding-Anstrengung, die sich möglicherweise nicht lohnt. –

+0

Ich bin immer bereit für ein quixotisches Abenteuer. – Nosredna