Cmmons Math a. は 、Apache のトッププロジェクトである Apache Commons にある Apache Commons#Commons Proper に属する、数学と統計学の軽量コンポーネントです b.。Apache License Version 2.0 に従って配布されています。いろいろなコンポーネントを利用できますが、ここでは、多項式係数を最小二乗法で求めてみます。
なお、最初に扱うサンプルは、以前 NetBeans IDE で試したもの c. と同じものを Eclipse 上でも試し、その上で SWT と組み合わせて視覚化したいと考えています。ただ、大量のデータをそのままプロットできるかどうか…。まずは、NetBeans IDE で試した時のおさらいをします。当時使用したデータファイルのリンク先に不具合があるので、今回、新たにデータの格納先を 4shared に確保しました。
使用環境
- OS : CentOS 7 (Linux)
- JDK : java-1.7.0-openjdk-1.7.0.71-2.5.3.1.el7_0.x86_64
- IDE : Eclipse Luna Service Release 1 (4.4.1)
サンプル
100,000 組の x と y が対になっているデータ fdata01.zip (fdata01.txt) を使って、c.、次の 4 次の多項式でフィッティングするために、その係数 c0, c1, c2, c3, c4 を最小二乗法で求めます。
y = c0 + c1x + c2x2 + c3x3 + c4x4
以下が Commons Math を利用したサンプルプログラムです。なお、使用した Commons Math は Version 3.3 です。なお、Java 1.5 以上が必要です。
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;
public class CommonsMathTest {
public static void main(String[] args) {
int m = 100000, n = 5;
double X[][], y[];
X = new double[m][n];
y = new double[m];
File file = new File("/home/bitwalk/ドキュメント/fdata01.txt");
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);
double[] 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);
}
}
実行例を以下に示しました。ここでは R2 (決定係数)も計算しています。
run:
# of DATA 100000
Coefficients
C(0) = 37.76585776133077
C(1) = 0.049683847037500665
C(2) = 6.988983959854228E-6
C(3) = -4.217424916004811E-7
C(4) = 2.686562674530102E-10
R-squared = 0.7654053656031088
小数点以下が全て前回と全く同じになっているというわけではなく、ほんの僅かな違いが確認できますが、無視して良いでしょう。さて、これをプロットできるか、次回試してみます。
参考サイト
- Commons Math: The Apache Commons Mathematics Library
- Apache Commons Math
- bitWalk's: NetBeans IDE で Commons Math を試す
- The Commons Math User Guide - Statistics 1.5 Multiple linear regression
- bitWalk's workshop - CommonsMath