12

我正在尝试使用apache.commons.math库计算将 R 脚本转换为 java。我可以使用org.apache.commons.math.analysis.interpolation.LoessInterpolator代替R loess吗?我无法得到相同的结果。

编辑

这是一个 java 程序,它创建一个随机数组 (x,y) 并使用 LoessInterpolator 或调用 R 计算黄土。最后,打印结果。

import java.io.*;
import java.util.Random;

import org.apache.commons.math.analysis.interpolation.LoessInterpolator;


public class TestLoess
    {
    private String RScript="/usr/local/bin/Rscript";
    private static class ConsummeInputStream
        extends Thread
        {
        private InputStream in;
        ConsummeInputStream(InputStream in)
            {
            this.in=in;
            }
        @Override
        public void run()
            {
            try
                {
                int c;
                while((c=this.in.read())!=-1) 
                    System.err.print((char)c);
                }
            catch(IOException err)
                {
                err.printStackTrace();
                }
            }
        }
    TestLoess()
        {

        }
    private void run() throws Exception
        {
        int num=100;
        Random rand=new Random(0L);
        double x[]=new double[num];
        double y[]=new double[x.length];
        for(int i=0;i< x.length;++i)
            {
            x[i]=rand.nextDouble()+(i>0?x[i-1]:0);
            y[i]=Math.sin(i)*100;
            }
        LoessInterpolator loessInterpolator=new LoessInterpolator(
            0.75,//bandwidth,
            2//robustnessIters

            );
        double y2[]=loessInterpolator.smooth(x, y);

        Process proc=Runtime.getRuntime().exec(
            new String[]{RScript,"-"}
            );
        ConsummeInputStream errIn=new ConsummeInputStream(proc.getErrorStream());
        BufferedReader stdin=new BufferedReader(new InputStreamReader(proc.getInputStream()));
        PrintStream out=new PrintStream(proc.getOutputStream());
        errIn.start();
        out.print("T<-as.data.frame(matrix(c(");
        for(int i=0;i< x.length;++i)
            {
            if(i>0) out.print(',');
            out.print(x[i]+","+y[i]);
            }
        out.println("),ncol=2,byrow=TRUE))");
        out.println("colnames(T)<-c('x','y')");
        out.println("T2<-loess(y ~ x, T)");
        out.println("write.table(residuals(T2),'',col.names= F,row.names=F,sep='\\t')");
        out.flush();
        out.close();
        double y3[]=new double[x.length];
        for(int i=0;i< y3.length;++i)
            {
            y3[i]=Double.parseDouble(stdin.readLine());
            }
        System.out.println("X\tY\tY.java\tY.R");
        for(int i=0;i< y3.length;++i)
            {
            System.out.println(""+x[i]+"\t"+y[i]+"\t"+y2[i]+"\t"+y3[i]);
            }
        }

    public static void main(String[] args)
        throws Exception
        {
        new TestLoess().run();
        }
    }

编译和执行:

javac -cp commons-math-2.2.jar TestLoess.java && java -cp commons-math-2.2.jar:. TestLoess

输出:

X   Y   Y.java  Y.R
0.730967787376657   0.0 6.624884763714674   -12.5936186703287
0.9715042030481429  84.14709848078965   6.5263049649584 71.9725380029913
1.6089216283982513  90.92974268256818   6.269100654071115   79.839773167581
2.159358633515885   14.112000805986721  6.051308261720918   3.9270340708818
2.756903911313087   -75.68024953079282  5.818424835586378   -84.9176311089431
3.090122310789737   -95.89242746631385  5.689740879461759   -104.617807889069
3.4753114955304554  -27.941549819892586 5.541837854229562   -36.0902352062634
4.460153035730264   65.6986598718789    5.168028655980764   58.9472823439219
5.339335553602744   98.93582466233818   4.840314399516663   93.3329030534449
6.280584733084859   41.21184852417566   4.49531113985498    36.7282165788057
6.555538699120343   -54.40211108893698  4.395343460231256   -58.5812856445538
6.68443584999412    -99.99902065507035  4.348559404444451   -104.039069260889
6.831037507640638   -53.657291800043495 4.295400167908642   -57.5419313320511
6.854275630124528   42.016703682664094  4.286978656933373   38.1564179414478
7.401015387322993   99.06073556948704   4.089252482141094   95.7504087842369
8.365502247999844   65.02878401571168   3.7422883733498726  62.5865641279576
8.469992934250815   -28.790331666506532 3.704793544880599   -31.145867173504
9.095139297716374   -96.13974918795569  3.4805388562453574  -98.0047896609079
9.505935493207435   -75.09872467716761  3.3330472034239405  -76.6664588290508

y 的输出值在 R 和 Java 之间显然不一样;Y.R 列看起来不错(它接近原始 Y 列)。我应该如何改变它以获得 Y.java ~ YR ?

4

3 回答 3

5

您需要更改三个输入参数的默认值以使 Java 和 R 版本相同:

  1. Java LoessInterpolator 只做线性局部多项式回归,但 R 支持线性(degree=1)、二次(degree=2)和奇怪的 degree=0 选项。因此,您需要degree=1在 R 中指定与 Java 相同。

  2. LoessInterpolator 默认迭代次数DEFAULT_ROBUSTNESS_ITERS=2,但 R 默认iterations=4。所以你需要control = loess.control(iterations=X)在R中设置(X是迭代次数)。

  3. LoessInterpolator 默认值DEFAULT_BANDWIDTH=0.3,但 R 默认值span=0.75

于 2014-07-21T22:08:41.130 回答
4

我不能代表 java 实现,但lowess有许多参数可以控制适合的带宽。除非您使用相同的控制参数进行拟合,否则您应该期望结果会有所不同。每当人们对数据进行平滑处理时,我的建议是绘制原始数据和拟合图,并自行决定哪些控制参数会在数据保真度和平滑(也称为噪声消除)之间产生所需的折衷。

于 2012-10-03T11:19:31.867 回答
1

这里有两个问题。首先,如果你绘制你正在生成的数据,它看起来几乎是随机的,并且由 R 中的 loess 生成的拟合非常差,例如

plot(T$x, T$y)
lines(T$s, T2$fitted, col="blue", lwd=3)

上面 Java 代码生成的数据与 R 生成的黄土拟合图

然后在你的 R 脚本中,你写的是残差而不是预测,所以在这一行

out.println("write.table(residuals(T2),'',
   col.names= F,row.names=F,sep='\\t')");

您需要更改residuals(T2)predict(T2)例如

out.println("write.table(predict(T2),'',
   col.names= F,row.names=F,sep='\\t')");

因此,在您的代码示例中,R 生成的前几行残差看起来很合适,这纯属偶然。

对我来说,如果我尝试拟合一些更合适的数据,那么 Java 和 R 会返回相似但不相同的结果。我还发现如果我不调整默认的robustnessIter设置,结果会更接近。

于 2014-08-01T12:38:49.723 回答