趋势线(回归、曲线拟合)java库
Posted
技术标签:
【中文标题】趋势线(回归、曲线拟合)java库【英文标题】:Trend lines ( regression, curve fitting) java library 【发布时间】:2013-07-09 15:38:37 【问题描述】:我正在尝试开发一个应用程序,它可以计算与 excel 相同的趋势线,但适用于更大的数据集。
但我找不到任何计算此类回归的 java 库。对于 linera 模型,我使用的是 Apache Commons 数学,而对于另一个模型,Michael Thomas Flanagan 提供了一个很棒的数值库,但自 1 月以来它不再可用:
http://www.ee.ucl.ac.uk/~mflanaga/java/
你知道在 java 中计算这些回归的任何其他库、代码库吗?最好的,
【问题讨论】:
为什么不推出自己的?至少数学很容易编码,对吧? IOWWhat have you tried?
【参考方案1】:
除了也许WeCouldStealAVa所说的;
commons-math3 库也可以在 maven repository 中找到。
当前版本是3.2,依赖标签是:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>3.2</version>
</dependency>
【讨论】:
【参考方案2】:由于它们都基于线性拟合,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 并指定一个窗口。您可能想要使用另一个答案中建议的插值进行一些平滑处理。
【讨论】:
糟糕 - 切换了 power 和 exp 方法。现在修好了。还添加了对数模型。 我已经很好地尝试了你的代码,但我只是想知道如果我得到 Y 数组,如何绘制一次趋势线。另一件事是,它只适用于 y= x2 + const方程式,或者我可以将其更改为我的方程式,例如 y=4x2+3x+6.4。 是的,使用PolyTrendLine(2)
创建的TrendLine
将估计y=b0+b1*x+b2*x^2
的系数。仔细观察xVector
,您会发现它使用 x^0, x^1, ... x^k 作为 k 度回归的估计量。
只需调用 main() 就可以在图上画线?我在 onCreate() 中尝试了一段代码,但它不会在我的 UI 上绘制任何内容。请看我的问题***.com/questions/22808204/…
maybeWeCouldStealAVan 你怎么能得到 r 的绝对值或平方? | r |或 r^2【参考方案3】:
您可以使用org.apache.commons.math3.analysis.interpolation
中提供的不同类型的interpolators,包括例如LinearInterpolator、LoessInterpolator 和NevilleInterpolator。
【讨论】:
以上是关于趋势线(回归、曲线拟合)java库的主要内容,如果未能解决你的问题,请参考以下文章