Initial commit of LinearRegression class

This commit is contained in:
Ziver Koc 2018-03-27 16:39:14 +02:00
parent 3c8c692b16
commit 8050170ee3
5 changed files with 306 additions and 80 deletions

View file

@ -4,7 +4,7 @@ package zutil.math;
* Some basic matrix match functions.
* Matrix definition: double[y][x].
*/
public class MatrixMath {
public class Matrix {
/***********************************************************************
* Scalar
@ -74,71 +74,120 @@ public class MatrixMath {
* Elemental
**********************************************************************/
/**
* Element addition, each element in matrix1 will be
* added with the corresponding element in matrix2.
*
* @return a new matrix with the result
*/
public static double[][] add(double[][] matrix1, double[][] matrix2){
elementalPreCheck(matrix1, matrix2);
double[][] result = new double[matrix1.length][matrix1[0].length];
public static class Elemental {
for (int y=0; y < matrix1.length; ++y) {
for (int x=0; x < matrix1[y].length; ++x){
result[y][x] = matrix1[y][x] + matrix2[y][x];
/**
* Element addition, each element in matrix1 will be
* added with the corresponding element in matrix2.
*
* @return a new matrix with the result
*/
public static double[][] add(double[][] matrix1, double[][] matrix2) {
elementalPreCheck(matrix1, matrix2);
double[][] result = new double[matrix1.length][matrix1[0].length];
for (int y = 0; y < matrix1.length; ++y) {
for (int x = 0; x < matrix1[y].length; ++x) {
result[y][x] = matrix1[y][x] + matrix2[y][x];
}
}
return result;
}
return result;
}
/**
* Element subtraction, each element in matrix1 will be
* subtracted with the corresponding element in matrix2.
*
* @return a new matrix with the result
*/
public static double[][] subtract(double[][] matrix1, double[][] matrix2){
elementalPreCheck(matrix1, matrix2);
double[][] result = new double[matrix1.length][matrix1[0].length];
/**
* Element subtraction, each element in matrix1 will be
* subtracted with the corresponding element in matrix2.
*
* @return a new matrix with the result
*/
public static double[][] subtract(double[][] matrix1, double[][] matrix2) {
elementalPreCheck(matrix1, matrix2);
double[][] result = new double[matrix1.length][matrix1[0].length];
for (int y=0; y < matrix1.length; ++y) {
for (int x=0; x < matrix1[y].length; ++x){
result[y][x] = matrix1[y][x] - matrix2[y][x];
for (int y = 0; y < matrix1.length; ++y) {
for (int x = 0; x < matrix1[y].length; ++x) {
result[y][x] = matrix1[y][x] - matrix2[y][x];
}
}
return result;
}
return result;
}
/**
* Element multiplication, each element in matrix1 will be
* multiplied with the corresponding element in matrix2.
*
* @return a new matrix with the result
*/
public static double[][] elemMultiply(double[][] matrix1, double[][] matrix2){
elementalPreCheck(matrix1, matrix2);
double[][] result = new double[matrix1.length][matrix1[0].length];
/**
* Element multiplication, each element in matrix1 will be
* multiplied with the corresponding element in matrix2.
*
* @return a new matrix with the result
*/
public static double[][] multiply(double[][] matrix1, double[][] matrix2) {
elementalPreCheck(matrix1, matrix2);
double[][] result = new double[matrix1.length][matrix1[0].length];
for (int y=0; y < matrix1.length; ++y) {
for (int x=0; x < matrix1[y].length; ++x){
result[y][x] = matrix1[y][x] * matrix2[y][x];
for (int y = 0; y < matrix1.length; ++y) {
for (int x = 0; x < matrix1[y].length; ++x) {
result[y][x] = matrix1[y][x] * matrix2[y][x];
}
}
return result;
}
return result;
}
private static void elementalPreCheck(double[][] matrix1, double[][] matrix2) {
if (matrix1.length != matrix2.length || matrix1[0].length != matrix2[0].length)
throw new IllegalArgumentException("Matrices need to be of same dimension: " +
"matrix1 " + matrix1.length + "x" + matrix1[0].length + ", " +
"matrix2 " + matrix2.length + "x" + matrix2[0].length + ", ");
/**
* Element exponential, each element in the vector will raised
* to the power of the exp paramter
*
* @return a new vector with the result
*/
public static double[] pow(double[] vector, double exp) {
double[] result = new double[vector.length];
for (int i = 0; i < vector.length; ++i) {
result[i] = Math.pow(vector[i], exp);
}
return result;
}
/**
* Element multiplication, each element in matrix1 will be
* multiplied with the corresponding element in matrix2.
*
* @return a new matrix with the result
*/
public static double[][] pow(double[][] matrix, double exp) {
double[][] result = new double[matrix.length][matrix[0].length];
for (int i = 0; i < matrix.length; ++i) {
result[i] = pow(matrix[i], exp);
}
return result;
}
private static void elementalPreCheck(double[][] matrix1, double[][] matrix2) {
if (matrix1.length != matrix2.length || matrix1[0].length != matrix2[0].length)
throw new IllegalArgumentException("Matrices need to be of same dimension: " +
"matrix1 " + matrix1.length + "x" + matrix1[0].length + ", " +
"matrix2 " + matrix2.length + "x" + matrix2[0].length + ", ");
}
}
/***********************************************************************
* Vector
**********************************************************************/
/**
* Vector subtraction, every element in the first vector will be subtracted
* with the corresponding element in the second vector.
*
* @return a new vector with subtracted elements
*/
public static double[] subtract(double[] vector1, double[] vector2){
vectorPreCheck(vector1, vector2);
double[] result = new double[vector1.length];
for (int i=0; i < result.length; ++i) {
result[i] = vector1[i] - vector2[i];
}
return result;
}
/**
* Matrix Vector multiplication, each element column in the matrix will be
* multiplied with the corresponding element row in the vector.
@ -175,6 +224,24 @@ public class MatrixMath {
return result;
}
/**
* Sums all values in a vector
*
* @return the summed value of all elements in the vector
*/
public static double sum(double[] vector) {
double sum = 0;
for (int i = 0; i < vector.length; i++) {
sum += vector[i];
}
return sum;
}
private static void vectorPreCheck(double[] vector1, double[] vector2) {
if (vector1.length != vector2.length)
throw new IllegalArgumentException("The two vectors need to have the same length: " +
"vector1 " + vector1.length + "x1, vector2 " + vector2.length + "x1");
}
private static void vectorPreCheck(double[][] matrix, double[] vector) {
if (matrix[0].length != vector.length)
throw new IllegalArgumentException("Matrix columns need to have same length as vector length: " +
@ -196,11 +263,10 @@ public class MatrixMath {
matrixPreCheck(matrix1, matrix2);
double[][] result = new double[matrix1.length][matrix2[0].length];
for (int y=0; y < result.length; ++y) {
for (int x=0; x < result[y].length; ++x){
for (int i=0; i<matrix1[0].length; ++i) {
result[y][x] += matrix1[y][i] * matrix2[i][x];
for (int i=0; i < result.length; ++i) {
for (int k=0; k<matrix1[0].length; ++k) {
for (int j=0; j < result[i].length; ++j){
result[i][j] += matrix1[i][k] * matrix2[k][j];
}
}
}
@ -221,6 +287,18 @@ public class MatrixMath {
return result;
}
/**
* Sums all values in a matrix
*
* @return the summed value of all elements
*/
public static double sum(double[][] matrix) {
double sum = 0;
for (int i = 0; i < matrix.length; i++) {
sum += sum(matrix[i]);
}
return sum;
}
private static void matrixPreCheck(double[][] matrix1, double[][] matrix2) {
if (matrix1[0].length != matrix2.length)

View file

@ -0,0 +1,38 @@
package zutil.ml;
import zutil.math.Matrix;
/**
* Implementation of a Linear Regression algorithm for "predicting"
* numerical values depending on specific input
*/
public class LinearRegression {
/**
* Method for calculating a hypothesis value fr a specific input value x.
* <br><br>
* <i>
* h(x) = theta0 * x0 + theta1 * x1 + ... + thetan * xn => transpose(theta) * x
* </i>
*/
protected static double[] calculateHypotesis(double[][] x, double[] theta){
return Matrix.multiply(x, theta);
}
/**
* Linear Regresion cost method.
* <br /><br />
* <i>
* J(O) = 1 / (2 * m) * Σ { ( h(xi) - yi )^2 }
* </i><br>
* m = learning data size (rows)
* @return a number indicating the error rate
*/
protected static double calculateCost(double[][] x, double[] y, double[] theta){
return 1 / (2 * x.length) * Matrix.sum(
Matrix.Elemental.pow(
Matrix.subtract(calculateHypotesis(x, theta), y),
2));
}
}