2013-07-11 22 views
11

Büyük ölçekli grafikler için, aynı eğilim çizgilerini hesaplayacak bir uygulama geliştirmeye çalışıyorum.Trend çizgileri (regresyon, eğri uydurma) java kitaplığı

enter image description here

Ama böyle regresyon hesaplar herhangi bir java kütüphanesi bulmak mümkün değilim. Linera modeli için ben Apache Commons matematik kullanıyorum ve diğeri için Michael Thomas Flanagan'a büyük bir sayısal kütüphane vardı ama Ocak beri artık mevcuttur:

http://www.ee.ucl.ac.uk/~mflanaga/java/

Başka kütüphaneleri biliyor musunuz java'da bu regresyonları hesaplamak için kod depoları. En İyi,

+0

Neden kendi rulo değil? En azından matematiğin kod yazması kolay değil mi? IOW 'Ne denediniz? – Shark

cevap

30

Tüm bunlar doğrusal uyarlara dayalı olduğundan, OLSMultipleLinearRegression doğrusal, polinom, üstel, logaritmik ve güç trend çizgileri için gereken her şeydir.

Sorunuz bana indirip commons matematik regresyon araçları ile oynamak için bir bahane verdi ve ben birlikte bazı trend çizgisi araçları koydu:

bir arayüz: regresyon için

public interface TrendLine { 
    public void setValues(double[] y, double[] x); // y ~ f(x) 
    public double predict(double x); // get a predicted y for a given x 
} 

Bir soyut sınıf tabanlı trend çizgileri: polinom veya lineer modelleri için

public abstract class OLSTrendLine implements TrendLine { 

    RealMatrix coef = null; // will hold prediction coefs once we get values 

    protected abstract double[] xVector(double x); // create vector of values from x 
    protected abstract boolean logY(); // set true to predict log of y (note: y must be positive) 

    @Override 
    public void setValues(double[] y, double[] x) { 
     if (x.length != y.length) { 
      throw new IllegalArgumentException(String.format("The numbers of y and x values must be equal (%d != %d)",y.length,x.length)); 
     } 
     double[][] xData = new double[x.length][]; 
     for (int i = 0; i < x.length; i++) { 
      // the implementation determines how to produce a vector of predictors from a single x 
      xData[i] = xVector(x[i]); 
     } 
     if(logY()) { // in some models we are predicting ln y, so we replace each y with ln y 
      y = Arrays.copyOf(y, y.length); // user might not be finished with the array we were given 
      for (int i = 0; i < x.length; i++) { 
       y[i] = Math.log(y[i]); 
      } 
     } 
     OLSMultipleLinearRegression ols = new OLSMultipleLinearRegression(); 
     ols.setNoIntercept(true); // let the implementation include a constant in xVector if desired 
     ols.newSampleData(y, xData); // provide the data to the model 
     coef = MatrixUtils.createColumnRealMatrix(ols.estimateRegressionParameters()); // get our coefs 
    } 

    @Override 
    public double predict(double x) { 
     double yhat = coef.preMultiply(xVector(x))[0]; // apply coefs to xVector 
     if (logY()) yhat = (Math.exp(yhat)); // if we predicted ln y, we still need to get y 
     return yhat; 
    } 
} 

bir uygulama:

(. Yapıcısı çağrılırken doğrusal modeller için, sadece 1 olarak derecesini ayarlamak)

public class PolyTrendLine extends OLSTrendLine { 
    final int degree; 
    public PolyTrendLine(int degree) { 
     if (degree < 0) throw new IllegalArgumentException("The degree of the polynomial must not be negative"); 
     this.degree = degree; 
    } 
    protected double[] xVector(double x) { // {1, x, x*x, x*x*x, ...} 
     double[] poly = new double[degree+1]; 
     double xi=1; 
     for(int i=0; i<=degree; i++) { 
      poly[i]=xi; 
      xi*=x; 
     } 
     return poly; 
    } 
    @Override 
    protected boolean logY() {return false;} 
} 

Üstel ve güç modelleri daha da basittir:

(not: şimdi günlük y tahmin ediyoruz - bu önemli. Bunların her ikisi de) pozitif y için uygundur

public class ExpTrendLine extends OLSTrendLine { 
    @Override 
    protected double[] xVector(double x) { 
     return new double[]{1,x}; 
    } 

    @Override 
    protected boolean logY() {return true;} 
} 

ve

public class PowerTrendLine extends OLSTrendLine { 
    @Override 
    protected double[] xVector(double x) { 
     return new double[]{1,Math.log(x)}; 
    } 

    @Override 
    protected boolean logY() {return true;} 

} 

Ve bir günlük modeli:

, ln değil y y x günlüğünü alır ancak tahmin

()

public class LogTrendLine extends OLSTrendLine { 
    @Override 
    protected double[] xVector(double x) { 
     return new double[]{1,Math.log(x)}; 
    } 

    @Override 
    protected boolean logY() {return false;} 
} 

Ve bu gibi kullanabilirsiniz:

Sadece eğilim çizgileri istedi beri onlarla bittiğinde
public static void main(String[] args) { 
    TrendLine t = new PolyTrendLine(2); 
    Random rand = new Random(); 
    double[] x = new double[1000*1000]; 
    double[] err = new double[x.length]; 
    double[] y = new double[x.length]; 
    for (int i=0; i<x.length; i++) { x[i] = 1000*rand.nextDouble(); } 
    for (int i=0; i<x.length; i++) { err[i] = 100*rand.nextGaussian(); } 
    for (int i=0; i<x.length; i++) { y[i] = x[i]*x[i]+err[i]; } // quadratic model 
    t.setValues(y,x); 
    System.out.println(t.predict(12)); // when x=12, y should be... , eg 143.61380202745192 
} 

, ben ols modelleri görevden ama vb hareketli ortalamasını kullanarak uygulamalar için

, hareketli, uyum iyiliği bazı veriler tutmak isteyebilirsiniz medyan, vs, commons matematik ile sopa gibi görünüyor. DescriptiveStatistics'u deneyin ve bir pencere belirtin. Başka bir cevapta önerildiği gibi enterpolasyon kullanarak biraz düzleştirme yapmak isteyebilirsiniz.

+0

Oops - güç ve exp yöntemlerini değiştirdi. Şimdi sabit. Ayrıca bir logaritmik model ekledi. – maybeWeCouldStealAVan

+0

Kodunuzu iyi denedim ama sadece Y dizisini alırsam bir eğilim çizgisinin nasıl çizileceğini bilmek istedim. Bir başka şey ise, sadece y = x2 + const denklemi için çalışıyor mu? benim denklemime göre y = 4x2 + 3x + 6.4. –

+0

Evet, 'PolyLrendLine (2)' ile oluşturulan 'TrendLine '' y = b0 + b1 * x + b2 * x^2' için katsayıları tahmin edecektir. Bir xVector'a yakından bakın ve k-derece regresyon için x^0, x^1, ... x^k kestiricileri olarak kullandığını göreceksiniz. – maybeWeCouldStealAVan

3

Örneğin, LinearInterpolator, LoessInterpolator ve NevilleInterpolator dahil olmak üzere org.apache.commons.math3.analysis.interpolation numaralı interpolators farklı türlerini kullanabilirsiniz.

2

BelkiWeCouldStealAVa'nın söylediklerine ek olarak;

Commons-math3 kitaplığı maven repository da kullanılabilir.

Güncel sürüm 3.2 ve bağımlılık etikettir:

<dependency> 
     <groupId>org.apache.commons</groupId> 
     <artifactId>commons-math3</artifactId> 
     <version>3.2</version> 
    </dependency>