首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >趋势线(回归,曲线拟合) java库

趋势线(回归,曲线拟合) java库
EN

Stack Overflow用户
提问于 2013-07-11 19:26:16
回答 3查看 20.9K关注 0票数 14

我正在尝试开发一个应用程序,它可以计算出与excel相同的趋势线,但适用于更大的数据集。

但是我找不到任何可以计算这种回归的java库。对于linera模型,我使用了Apache Commons的数学模型,而对于另一个模型,Michael Thomas Flanagan提供了一个很好的数值库,但自1月份以来,它已经不再可用:

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

你知道在java中有没有其他的库,代码库来计算这些回归。最好的

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-07-14 06:20:05

因为它们都是基于线性拟合的,所以对于线性、多项式、指数、对数和幂等趋势线,OLSMultipleLinearRegression就是您所需要的。

你的问题给了我一个下载和使用commons数学回归工具的借口,我把一些趋势线工具放在一起:

一个接口:

代码语言:javascript
复制
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
}

基于回归的趋势线的抽象类:

代码语言:javascript
复制
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。)

代码语言:javascript
复制
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)

代码语言:javascript
复制
public class ExpTrendLine extends OLSTrendLine {
    @Override
    protected double[] xVector(double x) {
        return new double[]{1,x};
    }

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

代码语言:javascript
复制
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)

代码语言:javascript
复制
public class LogTrendLine extends OLSTrendLine {
    @Override
    protected double[] xVector(double x) {
        return new double[]{1,Math.log(x)};
    }

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

你可以这样使用它:

代码语言:javascript
复制
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模型时,我把它们去掉了,但你可能想保留一些关于拟合优度的数据,等等。

对于使用移动平均、移动中值等的实现,看起来你可以坚持使用commons数学。尝试DescriptiveStatistics并指定一个窗口。你可能想要做一些平滑,使用插值,如另一个答案所建议的。

票数 38
EN

Stack Overflow用户

发布于 2013-07-13 17:55:51

您可以使用org.apache.commons.math3.analysis.interpolation中提供的不同类型的interpolators,例如,LinearInterpolator、LoessInterpolator和NevilleInterpolator。

票数 4
EN

Stack Overflow用户

发布于 2013-10-02 06:04:33

除了maybeWeCouldStealAVa所说的;

commons-math3库在maven repository中也可用。

当前版本为3.2,依赖标签为:

代码语言:javascript
复制
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-math3</artifactId>
        <version>3.2</version>
    </dependency>
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17592139

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档