Linie trendu (regresja, dopasowanie krzywych) biblioteka java
Próbuję opracować aplikację, która obliczałaby te same linie trendu, co excel, ale dla większych zbiorów danych.
Ale nie jestem w stanie znaleźć żadnej biblioteki Javy, która oblicza takie regresje. Dla modelu linera używam Apache Commons math, a dla drugiego była świetna biblioteka numeryczna od Michaela Thomasa Flanagana, ale od stycznia nie jest już dostępna:
Http://www.ee.ucl.ac.uk/~mflanaga / java /
Czy wiesz wszelkie inne biblioteki, repozytoria kodu do obliczania tych regresji w Javie. Best,
3 answers
Ponieważ wszystkie są oparte na dopasowaniach liniowych, OLSMultipleLinearRegression jest wszystkim, czego potrzebujesz dla liniowych, wielomianowych, wykładniczych, logarytmicznych i linii trendu mocy.
Twoje pytanie dało mi pretekst, aby pobrać i pobawić się narzędziami regresji matematycznej commons, a ja zebrałem kilka narzędzi linii trendu:
Interfejs:
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
}
Abstrakcyjna klasa dla linii trendów opartych na regresji:
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;
}
}
Implementacja dla modeli wielomianowych lub liniowych:
(dla liniowych modele, wystarczy ustawić stopień na 1 podczas wywoływania konstruktora.)
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;}
}
Modele wykładnicze i potęgowe są jeszcze łatwiejsze:
(UWAGA: przewidujemy teraz log y -- to ważne. Oba są odpowiednie tylko dla dodatniego y)
public class ExpTrendLine extends OLSTrendLine {
@Override
protected double[] xVector(double x) {
return new double[]{1,x};
}
@Override
protected boolean logY() {return true;}
}
I
public class PowerTrendLine extends OLSTrendLine {
@Override
protected double[] xVector(double x) {
return new double[]{1,Math.log(x)};
}
@Override
protected boolean logY() {return true;}
}
I model dziennika:
(który przyjmuje log x, ale przewiduje y, nie ln y)
public class LogTrendLine extends OLSTrendLine {
@Override
protected double[] xVector(double x) {
return new double[]{1,Math.log(x)};
}
@Override
protected boolean logY() {return false;}
}
I możesz go używać tak:
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
}
Ponieważ chciałeś tylko linii trendów, odrzuciłem modele ols, gdy zostało zrobione z nimi, ale możesz chcieć zachować pewne dane na temat dopasowania itp.
Dla implementacji wykorzystujących średnią ruchomą, medianę ruchomą itp., wygląda na to, że możesz trzymać się matematyki commons. Spróbuj DescriptiveStatistics i określ okno. Możesz zrobić wygładzanie, używając interpolacji, jak sugerowano w innej odpowiedzi.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-14 00:38:54
Możesz używać różnych typów interpolatorów dostępnych w org.apache.commons.math3.analysis.interpolation
, w tym np. LinearInterpolator, LoessInterpolator i NevilleInterpolator.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-13 09:55:50
Oprócz tego, co maybeWeCouldStealAVa powiedział;
Biblioteka commons-math3 jest również dostępna w Maven repozytorium .
Aktualna wersja to 3.2, A znacznik zależności To:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>3.2</version>
</dependency>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-01 22:23:27