2012-07-04 7 views
5

डेटा के एक सेट में फ़ंक्शन फिट करने के लिए मैथ कॉमन्स कर्वफिटर का उपयोग कैसे करूं? मुझे लेवेनबर्ग मारवार्डट ऑप्टीमाइज़र और पैरामैट्रिक यूनिवर्सेट फ़ंक्शन के साथ वक्रफिटर का उपयोग करने के लिए कहा गया था, लेकिन मुझे नहीं पता कि पैरामैट्रिक यूनिवर्सेट फ़ंक्शन ढाल और मूल्य विधियों में क्या लिखना है। इसके अलावा, उन्हें लिखने के बाद, फिट फ़ंक्शन पैरामीटर कैसे प्राप्त करें? मेरे समारोह:जावा मैथ कॉमन्स वक्रफिटर का उपयोग कैसे करें?

public static double fnc(double t, double a, double b, double c){ 
    return a * Math.pow(t, b) * Math.exp(-c * t); 
} 

उत्तर

11

तो, यह एक पुराने सवाल है, लेकिन मैं हाल ही में एक ही मुद्दे में भाग गया, और मेलिंग सूची और अपाचे कॉमन्स मठ स्रोत कोड में तल्लीन यह पता लगाने के लिए होने समाप्त हो गया।

यह API उल्लेखनीय खराब प्रलेखित है, लेकिन वर्तमान अपाचे आम मठ (3.3+) के संस्करण में, वहाँ दो हिस्से हैं, यह मानते हुए आप एक से अधिक पैरामीटर के साथ एक एकल चर है: समारोह के साथ फिट करने के लिए (जो लागू ParametricUnivariateFunction) और वक्र फिटर (जो सार CururFitter फैलाता है)।

समारोह फिट

  • public double value(double t, double... parameters)
    • आपका समीकरण। यह वह जगह है जहां आप अपना fnc तर्क डाल देंगे।
  • public double[] gradient(double t, double... parameters)
    • प्रत्येक मानकों के संबंध में ऊपर का आंशिक व्युत्पन्न की एक सरणी देता है। This calculator सहायक हो सकता है अगर (मेरे जैसा) आप अपने कैलकुस पर जंगली हैं, लेकिन कोई भी अच्छा कंप्यूटर बीजगणित प्रणाली इन मानों की गणना कर सकती है।

वक्र फिटर

  • protected LeastSquaresProblem getProblem(Collection<WeightedObservedPoint> points)
    • सेट अप बॉयलरप्लेट बकवास का एक समूह है, और फिटर का उपयोग करने के लिए एक कम से कम वर्गों समस्या देता है।

यह सब एक साथ रखें, अपने विशिष्ट मामले में एक उदाहरण समाधान है:

import java.util.*; 
import org.apache.commons.math3.analysis.ParametricUnivariateFunction; 
import org.apache.commons.math3.fitting.AbstractCurveFitter; 
import org.apache.commons.math3.fitting.leastsquares.LeastSquaresBuilder; 
import org.apache.commons.math3.fitting.leastsquares.LeastSquaresProblem; 
import org.apache.commons.math3.fitting.WeightedObservedPoint; 
import org.apache.commons.math3.linear.DiagonalMatrix; 

class MyFunc implements ParametricUnivariateFunction { 
    public double value(double t, double... parameters) { 
     return parameters[0] * Math.pow(t, parameters[1]) * Math.exp(-parameters[2] * t); 
    } 

    // Jacobian matrix of the above. In this case, this is just an array of 
    // partial derivatives of the above function, with one element for each parameter. 
    public double[] gradient(double t, double... parameters) { 
     final double a = parameters[0]; 
     final double b = parameters[1]; 
     final double c = parameters[2]; 

     return new double[] { 
      Math.exp(-c*t) * Math.pow(t, b), 
      a * Math.exp(-c*t) * Math.pow(t, b) * Math.log(t), 
      a * (-Math.exp(-c*t)) * Math.pow(t, b+1) 
     }; 
    } 
} 

public class MyFuncFitter extends AbstractCurveFitter { 
    protected LeastSquaresProblem getProblem(Collection<WeightedObservedPoint> points) { 
     final int len = points.size(); 
     final double[] target = new double[len]; 
     final double[] weights = new double[len]; 
     final double[] initialGuess = { 1.0, 1.0, 1.0 }; 

     int i = 0; 
     for(WeightedObservedPoint point : points) { 
      target[i] = point.getY(); 
      weights[i] = point.getWeight(); 
      i += 1; 
     } 

     final AbstractCurveFitter.TheoreticalValuesFunction model = new 
      AbstractCurveFitter.TheoreticalValuesFunction(new MyFunc(), points); 

     return new LeastSquaresBuilder(). 
      maxEvaluations(Integer.MAX_VALUE). 
      maxIterations(Integer.MAX_VALUE). 
      start(initialGuess). 
      target(target). 
      weight(new DiagonalMatrix(weights)). 
      model(model.getModelFunction(), model.getModelFunctionJacobian()). 
      build(); 
    } 

    public static void main(String[] args) { 
     MyFuncFitter fitter = new MyFuncFitter(); 
     ArrayList<WeightedObservedPoint> points = new ArrayList<WeightedObservedPoint>(); 

     // Add points here; for instance, 
     WeightedObservedPoint point = new WeightedObservedPoint(1.0, 
      1.0, 
      1.0); 
     points.add(point); 

     final double coeffs[] = fitter.fit(points); 
     System.out.println(Arrays.toString(coeffs)); 
    } 
} 
+1

मैं अंक संग्रह के बारे में उलझन में हूं। क्या उनके पास कोई X_value नहीं है ?? लक्ष्य में केवल वाई-मान क्यों होता है? –

+0

इसके अलावा मैं पैरामीटर पर बाधाओं को कैसे जोड़ूं (उदाहरण के लिए कि f (x) = c * ln (a * x) में पैरामीटर हमेशा सकारात्मक होना चाहिए)? –

1

मैं जानता हूँ कि इस सवाल का बहुत पुराना है और i80and इस का जवाब दे एक उत्कृष्ट काम किया है, लेकिन मैं सिर्फ करने के लिए सोचा जोड़ें (भविष्य में एसओ -र्स के लिए) कि अपाचे मैथ के साथ डेरिवेटिव्स या आंशिक डेरिवेटिव्स की गणना करने का एक बहुत आसान तरीका है (इसलिए आपको जैकोबियन मैट्रिक्स के लिए अपना खुद का अंतर नहीं करना है)। यह DerivativeStructure है।

DerivativeStructure वर्ग का उपयोग करने के i80and के जवाब का विस्तार:

//Everything stays the same except for the Jacobian Matrix 

import java.util.*; 
import org.apache.commons.math3.analysis.ParametricUnivariateFunction; 
import org.apache.commons.math3.fitting.AbstractCurveFitter; 
import org.apache.commons.math3.fitting.leastsquares.LeastSquaresBuilder; 
import org.apache.commons.math3.fitting.leastsquares.LeastSquaresProblem; 
import org.apache.commons.math3.fitting.WeightedObservedPoint; 
import org.apache.commons.math3.linear.DiagonalMatrix; 
import org.apache.commons.math3.analysis.differentiation.DerivativeStructure; 

class MyFunc implements ParametricUnivariateFunction { 
    public double value(double t, double... parameters) { 
     return parameters[0] * Math.pow(t, parameters[1]) * Math.exp(-parameters[2] * t); 
    } 

    // Jacobian matrix of the above. In this case, this is just an array of 
    // partial derivatives of the above function, with one element for each parameter. 
    public double[] gradient(double t, double... parameters) { 
     final double a = parameters[0]; 
     final double b = parameters[1]; 
     final double c = parameters[2]; 

     // Jacobian Matrix Edit 

     // Using Derivative Structures... 
     // constructor takes 4 arguments - the number of parameters in your 
     // equation to be differentiated (3 in this case), the order of 
     // differentiation for the DerivativeStructure, the index of the 
     // parameter represented by the DS, and the value of the parameter itself 
     DerivativeStructure aDev = new DerivativeStructure(3, 1, 0, a); 
     DerivativeStructure bDev = new DerivativeStructure(3, 1, 1, b); 
     DerivativeStructure cDev = new DerivativeStructure(3, 1, 2, c); 

     // define the equation to be differentiated using another DerivativeStructure 
     DerivativeStructure y = aDev.multiply(DerivativeStructure.pow(t, bDev)) 
       .multiply(cDev.negate().multiply(t).exp()); 

     // then return the partial derivatives required 
     // notice the format, 3 arguments for the method since 3 parameters were 
     // specified first order derivative of the first parameter, then the second, 
     // then the third 
     return new double[] { 
       y.getPartialDerivative(1, 0, 0), 
       y.getPartialDerivative(0, 1, 0), 
       y.getPartialDerivative(0, 0, 1) 
     }; 

    } 
} 

public class MyFuncFitter extends AbstractCurveFitter { 
    protected LeastSquaresProblem getProblem(Collection<WeightedObservedPoint> points) { 
     final int len = points.size(); 
     final double[] target = new double[len]; 
     final double[] weights = new double[len]; 
     final double[] initialGuess = { 1.0, 1.0, 1.0 }; 

     int i = 0; 
     for(WeightedObservedPoint point : points) { 
      target[i] = point.getY(); 
      weights[i] = point.getWeight(); 
      i += 1; 
     } 

     final AbstractCurveFitter.TheoreticalValuesFunction model = new 
       AbstractCurveFitter.TheoreticalValuesFunction(new MyFunc(), points); 

     return new LeastSquaresBuilder(). 
       maxEvaluations(Integer.MAX_VALUE). 
       maxIterations(Integer.MAX_VALUE). 
       start(initialGuess). 
       target(target). 
       weight(new DiagonalMatrix(weights)). 
       model(model.getModelFunction(), model.getModelFunctionJacobian()). 
       build(); 
    } 

    public static void main(String[] args) { 
     MyFuncFitter fitter = new MyFuncFitter(); 
     ArrayList<WeightedObservedPoint> points = new ArrayList<WeightedObservedPoint>(); 

     // Add points here; for instance, 
     WeightedObservedPoint point = new WeightedObservedPoint(1.0, 
       1.0, 
       1.0); 
     points.add(point); 

     final double coeffs[] = fitter.fit(points); 
     System.out.println(Arrays.toString(coeffs)); 
    } 
} 

और बस हो गया।मुझे पता है कि यह एक बहुत ही जटिल/भ्रमित वर्ग का उपयोग करने के लिए है, लेकिन यह निश्चित रूप से काम में आता है जब आप बहुत ही जटिल समीकरणों से निपट रहे हैं जो हाथ से आंशिक डेरिवेटिव प्राप्त करने में परेशानी होगी (यह मेरे साथ बहुत पहले नहीं हुआ), या जब आप आंशिक डेरिवेटिव प्राप्त करना चाहते हैं तो दूसरे या तीसरे क्रम में कहें।

दूसरा, तीसरा, वगैरह आदेश डेरिवेटिव के मामले में, तुम सब करना होगा:

// specify the required order as the second argument, say second order so 2 
DerivativeStructure aDev = new DerivativeStructure(3, 2, 0, a);   
DerivativeStructure bDev = new DerivativeStructure(3, 2, 1, b); 
DerivativeStructure cDev = new DerivativeStructure(3, 2, 2, c); 

// and then specify the order again here 
y.getPartialDerivative(2, 0, 0), 
y.getPartialDerivative(0, 2, 0), 
y.getPartialDerivative(0, 0, 2) 

उम्मीद है, यह किसी को कुछ समय मदद करता है।

संबंधित मुद्दे