2014-11-06

Eclipse で Commons Math を試す (2)

Cmmons Math を利用した、前回の記事で紹介したサンプルをベースに、データや重回帰分析でフィッティングした多項式をプロットできるようにしました。使用したライブラリは Nebula Visualization Widgets の XY Graph です。

GUI の部分を無理矢理くっつけた、やっつけ感が満載のサンプルではありますが、期待どおりのプロットを表示してくれます。読み込む 100,000 組の xy が対になっているデータは、前回と同様、fdata01.zip (fdata01.txt) を使います。

List: MulRegGuiTest.java
package commonsmathtest;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

import org.apache.commons.math3.stat.regression.OLSMultipleLinearRegression;
import org.eclipse.draw2d.LightweightSystem;
import org.eclipse.nebula.visualization.xygraph.dataprovider.CircularBufferDataProvider;
import org.eclipse.nebula.visualization.xygraph.figures.Trace;
import org.eclipse.nebula.visualization.xygraph.figures.Trace.TraceType;
import org.eclipse.nebula.visualization.xygraph.figures.XYGraph;
import org.eclipse.nebula.visualization.xygraph.figures.Trace.PointStyle;
import org.eclipse.nebula.visualization.xygraph.util.XYGraphMediaFactory;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class MulRegGuiTest {
    Shell shell;

    private File file;
    private int m = 100000, n = 5;
    private double[][] X;
    private double[] y;
    private double[] c;
    
    public MulRegGuiTest(Display display, File file) {
        this.file = file;

        // multiple regression analysis
        calcMulReg();

        // GUI
        shell = new Shell(display);
        shell.setText("MulRegGuiTest");
        shell.setSize(800, 400);

        shell.setLayout(new FillLayout());

        initUI();

        shell.setLocation(100, 100);
        shell.open();

        // event loop
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
    }

    private void calcMulReg() {
        X = new double[m][n];
        y = new double[m];

        try (BufferedReader br = new BufferedReader(new FileReader(file))) {
            String str;
            int i = 0;

            while ((str = br.readLine()) != null) {
                double xValue = Double.parseDouble(str.substring(0, 6));
                y[i] = Double.parseDouble(str.substring(6, 20));
                for (int j = 0; j < n; j++) {
                    X[i][j] = Math.pow(xValue, (double) j);
                }
                i++;
            }
            br.close();
        } catch (FileNotFoundException e) {
            System.out.println(e);
        } catch (IOException e) {
            System.out.println(e);
        }

        OLSMultipleLinearRegression regression = new OLSMultipleLinearRegression();
        regression.setNoIntercept(true);
        regression.newSampleData(y, X);

        c = regression.estimateRegressionParameters();
        // double[] residuals = regression.estimateResiduals();
        // double[][] parametersVariance = regression.estimateRegressionParametersVariance();
        // double regressandVariance = regression.estimateRegressandVariance();
        double rSquared = regression.calculateRSquared();
        // double sigma = regression.estimateRegressionStandardError();

        // Result
        System.out.println("# of DATA\t" + m);
        System.out.println("Coefficients");
        for (int j = 0; j < n; j++) {
            System.out.println("C(" + j + ") =  " + c[j]);
        }
        System.out.println("R-squared = " + rSquared);
    }

    private void initUI() {
        // use LightweightSystem to create the bridge between SWT and draw2D
        LightweightSystem lws = new LightweightSystem(shell);

        // create a new XY Graph.
        XYGraph xyGraph = new XYGraph();
        xyGraph.setTitle("Mulreg Example");

        xyGraph.primaryXAxis.setTitle("x axis");
        xyGraph.primaryYAxis.setTitle("y axis");

        xyGraph.primaryXAxis.setShowMajorGrid(true);
        xyGraph.primaryYAxis.setShowMajorGrid(true);

        // set it as the content of LightwightSystem
        lws.setContents(xyGraph);

        xyGraph.primaryXAxis.setAutoScale(true);
        xyGraph.primaryYAxis.setAutoScale(true);

        // create a trace data provider, which will provide the data to the trace.
        CircularBufferDataProvider traceDataProvider1 = new CircularBufferDataProvider(false);
        CircularBufferDataProvider traceDataProvider2 = new CircularBufferDataProvider(false);
        traceDataProvider1.setBufferSize(m);
        traceDataProvider2.setBufferSize(m);

        for (int i = 0; i < m; i++) {
            traceDataProvider1.setCurrentXData(X[i][1]);
            traceDataProvider1.setCurrentYData(y[i]);

            traceDataProvider2.setCurrentXData(X[i][1]);
            traceDataProvider2.setCurrentYData(linearCoupling(i));
        }

        // create the trace for raw data
        Trace trace1 = new Trace("data", xyGraph.primaryXAxis, xyGraph.primaryYAxis, traceDataProvider1);

        // set trace property for raw data
        trace1.setTraceType(TraceType.POINT);
        trace1.setPointStyle(PointStyle.CIRCLE);
        trace1.setPointSize(1);

        // add the trace to xyGraph
        xyGraph.addTrace(trace1);

        // create the trace for regression
        Trace trace2 = new Trace("fitting", xyGraph.primaryXAxis, xyGraph.primaryYAxis, traceDataProvider2);

        // set trace property for regression
        trace2.setPointStyle(PointStyle.NONE);
        trace2.setTraceColor(XYGraphMediaFactory.getInstance().getColor(XYGraphMediaFactory.COLOR_RED));;
        trace2.setLineWidth(2);

        // add the trace to xyGraph
        xyGraph.addTrace(trace2);
    }

    private double linearCoupling(int i) {
        double y = 0;
        for (int j = 0; j < n; j++) {
            y = y + c[j] * X[i][j];
        }
        return y;
    }

    public static void main(String[] args) {
        File readFile = new File("/home/bitwalk/ドキュメント/fdata01.txt");

        Display display = new Display();
        new MulRegGuiTest(display, readFile);
        display.dispose();
    }
}

実行例

重回帰分析をするために用意したサンプルは人為的に作ったものですので、プロットしても面白味がありません。しかし、100,000 程度のデータ数でも簡単にプロットできることが確認できたので、もっと応用範囲を広げてみようと思います。

 

0 件のコメント: