2012-07-04 12 views
5

Math Commons CurveFitter'i bir veri kümesine bir işlevi sığdırmak için nasıl kullanırım? CurveFitter'i LevenbergMarquardtOptimizer ve ParametricUnivariateFunction ile birlikte kullanmam söylendi, ancak ParametricUnivariateFunction gradyanında ve değer yöntemlerinde ne yazacağımı bilmiyorum. Ayrıca, yazdıktan sonra, takılan fonksiyon parametrelerini nasıl alabilirim? Benim fonksiyonu:Java Math Commons CurveFitter nasıl kullanılır?

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

cevap

11

Yani, bu bir eski sorudur, ama son zamanlarda aynı sorunu koştum ve onu anlamaya posta listeleri ve Apache Commons Matematik kaynak koduna defterleri zorunda sona erdi.

Bu API derece kötü belgelenmiştir, ancak Apache Ortak Math (3.3+) ait akım versiyonunda, birden parametrelerle tek bir değişken olduğunu varsayarak, iki bölüm vardır: (işlev uyması için hangi uygular ParametricUnivariateFunction) ve eğri tesisatçısı (AbstractCurveFitter'i genişletir).

Fonksiyon

  • public double value(double t, double... parameters)
    • Kişisel denklemini sığdır. Bu, fnc mantığınızı nereye koyacağınızdır.
    • public double[] gradient(double t, double... parameters)
    • her parametre ile ilgili olarak yukarıda kısmi türevi bir dizi döner. This calculator, (benim gibi) hesap makinenizde paslandığınız takdirde yararlı olabilir, ancak herhangi bir iyi bilgisayar cebiri sistemi bu değerleri hesaplayabilir.

Tesisatçısı Eğri

  • protected LeastSquaresProblem getProblem(Collection<WeightedObservedPoint> points)
    • Setleri kadar Demirbaş bok bir grup ve tesisatçısı kullanmak için en küçük kareler problemi döndürür. Hepsini bir araya getirirsek

aşağıda bir örnek, belirli durumlarda çözüm: Biliyorum

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

Ben noktaları toplama hakkında karıştı. Onlara X_value yok mu? Hedef neden sadece Y değerini içeriyor? –

+0

Ayrıca, parametreler üzerinde kısıtlamalar nasıl ekleyebilirim (örneğin, f (x) = c * ln (a * x) parametresinin her zaman pozitif olması gerekir)? –

1

bu soru bayağı eski ve i80and bu yanıtlayan mükemmel bir iş yaptı, ama sadece düşünülmektedir türevleri veya Apache Math ile kısmi türevleri hesaplamak için oldukça kolay bir yol olduğunu ekleyiniz (bu yüzden Jacobian Matrix için kendi farklılığınızı yapmak zorunda değilsiniz). DerivativeStructure.

DerivativeStructure sınıfını kullanmak i80and bireyin cevabı genişletme:

//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)); 
    } 
} 

Ve o kadar.Bunun kullanmak için oldukça dolambaçlı/kafa karıştırıcı sınıf olduğunu biliyorum, ama (bu kadar uzun zaman önce başıma) elle kısmi türevleri elde etmek zahmetli olacağını çok karmaşık denklemleri uğraşırken kesinlikle kullanışlı oluyor, ya Kısmi türevleri türetmek istediğinizde ikinci veya üçüncü sıraya söyleyin. ikinci, üçüncü, vesaire sipariş türevlerinin kullanılması durumunda

, yapmanız gereken her şeyi bu:

// 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) 

Umarım, bu bazen birilerine yardımcı olur.