Question

J'essaie de calculer la conversion d'un script R en Java en utilisant le apache.commons.math bibliothèque.Puis-je utiliser org.apache.commons.math.analysis.interpolation.LoessInterpolator au lieu de R lœss ?Je n'arrive pas à obtenir le même résultat.

MODIFIER.

voici un programme Java qui crée un tableau aléatoire (x, y) et calcule le loess avec LoessInterpolator ou en appelant R.A la fin, les résultats sont imprimés.

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

compilation et exécution :

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

sortir:

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

les valeurs de sortie pour y ne sont clairement pas les mêmes entre R et Java ;La colonne Y.R a l'air bien (elle est proche de la colonne Y d'origine).Comment dois-je changer cela pour obtenir Y.java ~ Y.R ?

Était-ce utile?

La solution

Vous devez modifier les valeurs par défaut de trois paramètres d'entrée pour rendre les versions Java et R identiques :

  1. Le Java LoessInterpolator effectue uniquement une régression polynomiale locale linéaire, mais R prend en charge l'option linéaire (degré = 1), quadratique (degré = 2) et une étrange option degré = 0.Il faut donc préciser degree=1 dans R pour être identique à Java.

  2. LoessInterpolator par défaut, nombre d'itérations DEFAULT_ROBUSTNESS_ITERS=2, mais R par défaut iterations=4.Vous devez donc définir control = loess.control(iterations=X) dans R (X est le nombre d'itérations).

  3. Valeurs par défaut de LoessInterpolator DEFAULT_BANDWIDTH=0.3 mais R par défaut span=0.75.

Autres conseils

Je ne peux pas parler de la mise en œuvre Java, mais lowess a un certain nombre de paramètres qui contrôlent la bande passante de l'ajustement.Sauf si vous vous ajustez avec les mêmes paramètres de contrôle, vous devez vous attendre à ce que les résultats diffèrent.Ma recommandation Chaque fois que les gens sont des données de lissage consiste à tracer les données d'origine ainsi qu'à l'ajustement et à déterminer vous-même quels paramètres de contrôle donnent votre compromis désiré entre la fidélité aux données et le détecteur de bruit).

Ici, nous avons deux problèmes.Premièrement, si vous tracez les données que vous générez, elles semblent presque aléatoires et l'ajustement généré par le loess dans R est très médiocre, par ex.

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

plot of the data generated by the Java code above with a loess fit generated by R

Ensuite, dans votre script R, vous écrivez les résidus et non les prédictions, donc dans cette ligne

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

tu dois changer residuals(T2) à predict(T2) par exemple.

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

C'était donc un pur hasard dans votre exemple de code que les deux premières lignes de résidus générés par R semblaient bien correspondre.

Pour moi, si j'essaie d'adapter des données plus appropriées, Java et R renvoient des résultats similaires mais pas identiques.J'ai également trouvé que les résultats étaient plus proches si je n'ajustais pas la valeur par défaut robustesseIter paramètres.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top