我正在创建java项目,它接收两个数组并计算线性回归。
我有4个类,一个是构造函数(RegressionModel),一个执行数学公式(Math1)并包含所有公式,一个计算类(FinalLinearRegressionModel),它扩展构造函数类,我初始化一个超级构造函数和使用这些值来创建调用我的Math类的方法。最后,我有我的测试器类调用FinalLinearRegressionModel并从那里进行计算。
这是解决这个问题的正确方法吗?或者我应该将我在FinalLinearRegressionModel中的方法放入我的RegressionModel中,因此我不需要扩展我的构造函数,因为我没有在构造函数中添加任何实例变量?这是我的课程:
public class RegressionModel {
public static final double[] DEFAULT_X = new double[0];
public static final double[] DEFAULT_Y = new double[0];
public static final boolean DEFAULT_ISCALCULATED = false;
public double [] xValues;
public double [] yValues;
public boolean isCalculated;
public RegressionModel()
{
xValues = DEFAULT_X;
yValues = DEFAULT_Y;
isCalculated = DEFAULT_ISCALCULATED;
}
public RegressionModel(double[] x, double[] y)
{
if(x == null || y == null)
{
System.out.println("Fatal Error creating regression model.");
System.exit(0);
}
else if(x.length == 0 || y.length == 0)
{
System.out.println("Fatal Error one or more zero lengths.");
System.exit(0);
}
else if(x.length != y.length)
{
System.out.println("Fatal Error array lengths are not equal.");
}
else
{
xValues = x;
yValues = y;
isCalculated = false;
}
}
public double[] getXValues()
{
return this.xValues;
}
public double[] getYValues()
{
return this.yValues;
}
}
public class Math1 extends RegressionModel {
public static double covariance(double[] x, double[] y)
{
double meanX;
double meanY;
double covariance;
meanX = mean(x);
meanY = mean(y);
covariance = 0;
for(int index = 0; index < x.length; index++)
{
covariance += (x[index] - meanX) * (y[index] - meanY);
}
covariance /= (x.length -1);
return covariance;
}
public static double mean(double[] values)
{
double sum;
sum = 0.0;
for(int index = 0; index < values.length; index++)
{
sum += values[index];
}
return sum / values.length;
}
public static double xxBar(double[] x)
{
double xxbar;
xxbar = 0.0;
for(int index = 0; index < x.length; index++)
{
xxbar += (x[index] - mean(x)) * (x[index] - mean(x));
}
return xxbar;
}
public static double yyBar(double[] y)
{
double yybar;
yybar = 0.0;
for(int index = 0; index < y.length; index++)
{
yybar += ((y[index] - mean(y)) * (y[index] = mean(y)));
}
return yybar;
}
public static double xyBar(double[] x, double[] y)
{
double xybar;
xybar = 0.0;
for(int index = 0; index < x.length; index++)
{
xybar += ((x[index] - mean(x)) * (y[index] - mean(y)));
}
return xybar;
}
public static double beta1(double[] x, double[] y)
{
return xyBar(x,y)/xxBar(x);
}
public static double beta0(double[] x, double[] y)
{
return mean(y) - beta1(x,y) * mean(x);
}
public static double sumOfSquaresDueToRegression(double[] y)
{
double meanY;
meanY = mean(y);
double sumOfSquaredDeviations = 0.0;
for(int index = 0; index < y.length; index++)
{
sumOfSquaredDeviations += (Math.pow(y[index] - meanY, 2));
}
return sumOfSquaredDeviations;
}
public static double sumOfSquaresTotal(double[] y)
{
double sumOfSquaresTotal;
sumOfSquaresTotal = 0.0;
for(int index = 0; index < y.length; index++)
{
sumOfSquaresTotal += (Math.pow(y[index] - mean(y), 2));
}
return sumOfSquaresTotal;
}
public static double degreesOfFreedom(double[] x)
{
return x.length - 2;
}
public static double fit(double[] x, double[] y)
{
double fit;
fit = 0.0;
for(int index = 0; index < x.length; index++)
{
fit = beta1(x,y) * x[index] + beta0(x,y);
}
return fit;
}
public static double r2(double[] y)
{
return sumOfSquaresDueToRegression(y) / yyBar(y);
}
public static double sumOfSquaresDueToError(double[] x, double[] y)
{
double sumOfSquaresError;
sumOfSquaresError = 0.0;
for(int index = 0; index < y.length; index++)
{
sumOfSquaresError += (Math.pow(y[index] - beta1(x,y), 2));
}
return sumOfSquaresError;
}
}
public class FinalLinearRegressionModel extends RegressionModel{
public double b0;
public FinalLinearRegressionModel(double[] x, double[] y)
{
super(x,y);
}
public double computeb0()
{
return b0 = Math1.beta0(xValues,yValues);
}
}
public class Test {
public static void main(String args[])
{
double[] x = {2, 3, 4, 5, 6, 8, 10, 11};
double[] y = {21.05, 23.51, 24.23, 27.71, 30.86, 45.85, 52.12, 55.98};
FinalLinearRegressionModel regression1;
regression1 = new FinalLinearRegressionModel(x,y);
System.out.println(regression1.computeb0());
}
}
答案 0 :(得分:0)
将computeb0()
方法移至RegressionModel
并删除FinalLinearRegressionModel
。
为什么Math1
会延长RegressionModel
?所有方法都是静态的,因此它不会使用RegressionModel的任何实例字段。
接下来,computeb0
方法的返回看起来很奇怪:
return b0 = Math1.beta0(xValues,yValues);
返回赋值的结果,我认为这恰好是正确的答案,但这不是java编程中常见的习惯用法,并且会使阅读代码的其他人感到困惑。
b0 = Math1.beta0(xValues,yValues);
return b0;
你想要什么
更好的是根本不将b0保存到实例值。没有必要
return Math1.beta0(xValues,yValues);
最后,正如Commenter Chief Two Pencils所提到的,在构造函数中调用System.exit()
是不好的形式。你应该抛出异常:
//don't need else keyword in this case
if(x == null || y == null)
{
throw new NullPointerException("x and y can not be null");
}
if(x.length == 0 || y.length == 0)
{
throw new IllegalArgumentException("one or more zero lengths.");
}
if(x.length != y.length)
{
throw new IllegalArgumentException("array lengths are not equal.");
}
答案 1 :(得分:0)
RegressionModel
代表你的顶点。它们可能已存储为Vertice
的数组,但您为double []
和x
选择了单独的y
,这也很好。
但是我的建议是因为你的模型非常简单,不会引入任何新的优步版本。您的数组或列表的模型。让它成为现实。 List
或数组。也许更好:将Vertice实现为实际的Vertice
类,这样您就可以将模型表示为List<Vertice>
或Vertice []
。您可以在static
中添加Vertice
辅助方法,以便从List
数组中创建double []
或数组。
import java.util.Arrays;
import java.util.List;
public class Vertice {
final public double x;
final public double y;
public Vertice(double x,double y) {
this.x = x;
this.y = y;
}
static public Vertice [] arrayFrom(double [] xs,double [] ys) {
// Allow to below automatically throw a NullPointerException without explicitly checking
if (xs.length != ys.length) throw new IllegalArgumentException("Arrays of diferent size: "+xs.length+" != "+ys.length);
Vertice [] vs = new Vertice[xs.length];
for (int i=0;i<xs.length;i++) vs[i] = new Vertice(xs[i],ys[i]);
return vs;
}
static public List listFrom(double [] xs,double [] ys) {
return Arrays.asList(arrayFrom(xs,ys));
}
}
消失了RegressionModel
。正如@dkatzel所解释的那样,也不需要将模型扩展到Math1
,因为它只包含计算。而实际可能是&#39;模型&#39;这可能意味着您的数学模型,因此您的RegressionModel
不再用于表示您的顶点,您现在可以直接将Math
重命名为RegressionModel
。
乍一看 - 早期的建议 - 看起来很干净,但很可能会遇到需要不太优雅的解决方案的问题。示例avg(double[])
现在需要分别为avgX(List<Vertice>)
和avgY(List<Vertice>)
。
但是,嘿,现在进入Stream
的世界并进行并行处理。也许你可以重构一切以利用Java 8:
import java.util.List;
public class RegressionApp {
public static void main(String args[])
{
double[] x = {2, 3, 4, 5, 6, 8, 10, 11};
double[] y = {21.05, 23.51, 24.23, 27.71, 30.86, 45.85, 52.12, 55.98};
List<Vertice> v = Vertice.listFrom(x, y);
RegressionModel regression1 = v.stream().parallel()
.collect(RegressionModel.summarize());;
System.out.println(regression1.b0);
}
}
那不是什么东西吗?
这可能会有很多工作要做 - 但我不能不提及它。