Строка трендов (регрессия, кривая) java library

Я пытаюсь разработать приложение, которое будет вычислять те же линии тренда, которые превосходят, но для больших наборов данных.

enter image description here

Но я не могу найти какую-либо библиотеку java, которая вычисляет такие регрессии. Для модели linera я использую математику Apache Commons, а для другой была отличная цифровая библиотека от Майкла Томаса Фланагана, но с января этого года больше не доступна:

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

Знаете ли вы какие-либо другие библиотеки, репозитории кода для вычисления этих регрессий в java. Лучший,

Ответ 1

Поскольку все они основаны на линейных привязках, OLSMultipleLinearRegression - это все, что вам нужно для линейных, полиномиальных, экспоненциальных, логарифмических и силовых трендовых линий.

Ваш вопрос дал мне повод для загрузки и игры с инструментами регрессионной математики, и я собрал некоторые инструменты линии тренда:

Интерфейс:

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
}

Абстрактный класс для линий тренда на основе регрессии:

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

Реализация для полиномиальных или линейных моделей:

(Для линейных моделей просто задайте степень 1 при вызове конструктора.)

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

Экспоненциальные и силовые модели еще проще:

(примечание: мы прогнозируем log y сейчас - это важно. Оба они подходят только для положительных y)

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

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

и

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

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

}

И модель журнала:

(который берет журнал x, но предсказывает y, а не 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;}
}

И вы можете использовать его следующим образом:

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
}

Поскольку вы просто хотели линии тренда, я уволил модели ols, когда я закончил с ними, но вы можете захотеть сохранить некоторые данные о хорошей пригодности и т.д.

Для реализаций, использующих скользящую среднюю, движущуюся медианную и т.д., похоже, что вы можете придерживаться общепринятой математики. Попробуйте DescriptiveStatistics и укажите окно. Возможно, вы захотите выполнить сглаживание, используя интерполяцию, как предложено в другом ответе.

Ответ 2

Вы можете использовать различные интерполяторы, доступные в org.apache.commons.math3.analysis.interpolation, включая, например, LinearInterpolator, LoessInterpolator и NevilleInterpolator.

Ответ 3

В дополнение к тому, что, может быть, сказал WeTouldStealAVa;

Библиотека commons-math3 также доступна в репозитории maven.

Текущая версия 3.2, а тег зависимостей:

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