Index: ml/src/main/java/org/apache/hama/ml/math/DenseDoubleMatrix.java =================================================================== --- ml/src/main/java/org/apache/hama/ml/math/DenseDoubleMatrix.java (revision 1493881) +++ ml/src/main/java/org/apache/hama/ml/math/DenseDoubleMatrix.java (working copy) @@ -778,4 +778,37 @@ return a.subtract(b).sum(); } + @Override + /** + * {@inheritDoc} + */ + public DoubleMatrix apply(DoubleFunction fun) { + for (int r = 0; r < this.numRows; ++r) { + for (int c = 0; c < this.numColumns; ++c) { + this.set(r, c, fun.calculate(this.get(r, c))); + } + } + return this; + } + + @Override + /** + * {@inheritDoc} + */ + public DoubleMatrix apply(DoubleMatrix other, DoubleDoubleFunction fun) { + if (this.numRows != other.getRowCount() + || this.numColumns != other.getColumnCount()) { + throw new IllegalArgumentException( + "Cannot apply double double function to matrices with different sizes."); + } + + for (int r = 0; r < this.numRows; ++r) { + for (int c = 0; c < this.numColumns; ++c) { + this.set(r, c, fun.calculate(this.get(r, c), other.get(r, c))); + } + } + + return this; + } + } Index: ml/src/main/java/org/apache/hama/ml/math/DenseDoubleVector.java =================================================================== --- ml/src/main/java/org/apache/hama/ml/math/DenseDoubleVector.java (revision 1493881) +++ ml/src/main/java/org/apache/hama/ml/math/DenseDoubleVector.java (working copy) @@ -100,11 +100,34 @@ vector[index] = value; } + /** + * {@inheritDoc} + */ + @Override + public DoubleVector apply(DoubleFunction func) { + for (int i = 0; i < vector.length; i++) { + this.vector[i] = func.calculate(vector[i]); + } + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public DoubleVector apply(DoubleVector other, DoubleDoubleFunction func) { + for (int i = 0; i < vector.length; i++) { + this.vector[i] = func.calculate(vector[i], other.get(i)); + } + return this; + } + /* * (non-Javadoc) * @see de.jungblut.math.DoubleVector#apply(de.jungblut.math.function. * DoubleVectorFunction) */ + @Deprecated @Override public DoubleVector apply(DoubleVectorFunction func) { DenseDoubleVector newV = new DenseDoubleVector(this.vector); @@ -119,6 +142,7 @@ * @see de.jungblut.math.DoubleVector#apply(de.jungblut.math.DoubleVector, * de.jungblut.math.function.DoubleDoubleVectorFunction) */ + @Deprecated @Override public DoubleVector apply(DoubleVector other, DoubleDoubleVectorFunction func) { DenseDoubleVector newV = (DenseDoubleVector) deepCopy(); Index: ml/src/main/java/org/apache/hama/ml/math/DoubleDoubleFunction.java =================================================================== --- ml/src/main/java/org/apache/hama/ml/math/DoubleDoubleFunction.java (revision 0) +++ ml/src/main/java/org/apache/hama/ml/math/DoubleDoubleFunction.java (working copy) @@ -0,0 +1,43 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hama.ml.math; + +/** + * A double double function takes two arguments. + * A vector or matrix can apply the double function to each element. + * + */ +public abstract class DoubleDoubleFunction { + + /** + * Apply the function to elements to two given arguments. + * @param x1 + * @param x2 + * @return The result based on the calculation on two arguments. + */ + public abstract double calculate(double x1, double x2); + + /** + * Apply the derivative of this function to two given arguments. + * @param x1 + * @param x2 + * @return The result based on the calculation on two arguments. + */ + public abstract double calculateDerivative(double x1, double x2); + +} Index: ml/src/main/java/org/apache/hama/ml/math/DoubleDoubleFunctions.java =================================================================== --- ml/src/main/java/org/apache/hama/ml/math/DoubleDoubleFunctions.java (revision 0) +++ ml/src/main/java/org/apache/hama/ml/math/DoubleDoubleFunctions.java (working copy) @@ -0,0 +1,83 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hama.ml.math; + +/** + * DoubleDoubleFunctions contains the commonly used DoubleDoubleFunction. + * + */ +public class DoubleDoubleFunctions { + + /** + * Square error cost function. + * + *
+ * cost(x1, x2) = 0.5 * (x1 - x2) ˆ 2 + *+ */ + public final static DoubleDoubleFunction SQUARED_ERROR = new DoubleDoubleFunction() { + + @Override + public double calculate(double target, double actual) { + double diff = target - actual; + return 0.5 * diff * diff; + } + + @Override + public double calculateDerivative(double target, double actual) { + return target - actual; + } + + }; + + /** + * The cross entropy cost function. + * + *
+ * cost(t, y) = - t * log(y) - (1 - t) * log(1 - y), + * where t denotes the target value, y denotes the estimated value. + *+ */ + public final static DoubleDoubleFunction CROSS_ENTROPY = new DoubleDoubleFunction() { + + @Override + public double calculate(double target, double actual) { + return -target * Math.log(actual) - (1 - target) * Math.log(1 - actual); + } + + @Override + public double calculateDerivative(double target, double actual) { + double adjustedTarget = target; + double adjustedActual = actual; + if (adjustedActual == 1) { + adjustedActual = 0.999; + } else if (actual == 0) { + adjustedActual = 0.001; + } + if (adjustedTarget == 1) { + adjustedTarget = 0.999; + } else if (adjustedTarget == 0) { + adjustedTarget = 0.001; + } + return -adjustedTarget / adjustedActual + (1 - adjustedTarget) + / (1 - adjustedActual); + } + + }; + +} Index: ml/src/main/java/org/apache/hama/ml/math/DoubleDoubleVectorFunction.java =================================================================== --- ml/src/main/java/org/apache/hama/ml/math/DoubleDoubleVectorFunction.java (revision 1493881) +++ ml/src/main/java/org/apache/hama/ml/math/DoubleDoubleVectorFunction.java (working copy) @@ -20,7 +20,10 @@ /** * A function that can be applied to two double vectors via {@link DoubleVector} * #apply({@link DoubleVector} v, {@link DoubleDoubleVectorFunction} f); + * + * This class will be replaced by {@link DoubleDoubleFunction} */ +@Deprecated public interface DoubleDoubleVectorFunction { /** Index: ml/src/main/java/org/apache/hama/ml/math/DoubleFunction.java =================================================================== --- ml/src/main/java/org/apache/hama/ml/math/DoubleFunction.java (revision 0) +++ ml/src/main/java/org/apache/hama/ml/math/DoubleFunction.java (working copy) @@ -0,0 +1,41 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hama.ml.math; + +/** + * A double double function takes two arguments. + * A vector or matrix can apply the double function to each element. + * + */ +public abstract class DoubleFunction { + + /** + * Apply the function to element. + * @param elem The element that the function apply to. + * @return The result after applying the function. + */ + public abstract double calculate(double value); + + /** + * Apply the gradient of the function. + * @param elem + * @return + */ + public abstract double calculateDerivative(double value); + +} Index: ml/src/main/java/org/apache/hama/ml/math/DoubleFunctions.java =================================================================== --- ml/src/main/java/org/apache/hama/ml/math/DoubleFunctions.java (revision 0) +++ ml/src/main/java/org/apache/hama/ml/math/DoubleFunctions.java (working copy) @@ -0,0 +1,65 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hama.ml.math; + +/** + * DoubleFunctions contains the common used DoubleFunction + * + */ +public final class DoubleFunctions { + + /** + * Tanh function. + * + */ + public final static DoubleFunction TANH = new DoubleFunction() { + + @Override + public double calculate(double value) { + return Math.tanh(value); + } + + @Override + public double calculateDerivative(double value) { + return 1 - value * value; + } + + }; + + /** + * The Sigmoid function + * + *
+ * f(x) = 1 / (1 + e^{-x})
+ *
+ */
+ public final static DoubleFunction SIGMOID = new DoubleFunction() {
+
+ @Override
+ public double calculate(double value) {
+ return 1.0 / (1 + Math.exp(-value));
+ }
+
+ @Override
+ public double calculateDerivative(double value) {
+ return value * (1 - value);
+ }
+
+ };
+
+}
Index: ml/src/main/java/org/apache/hama/ml/math/DoubleMatrix.java
===================================================================
--- ml/src/main/java/org/apache/hama/ml/math/DoubleMatrix.java (revision 1493881)
+++ ml/src/main/java/org/apache/hama/ml/math/DoubleMatrix.java (working copy)
@@ -184,4 +184,25 @@
*/
public DoubleMatrix slice(int rowOffset, int rowMax, int colOffset, int colMax);
+ /**
+ * Apply a double function f(x) onto each element of the matrix. After
+ * applying, each element of the current matrix will be changed from x to
+ * f(x).
+ *
+ * @param fun The function.
+ * @return The matrix itself, supply for chain operation.
+ */
+ public DoubleMatrix apply(DoubleFunction fun);
+
+ /**
+ * Apply a double double function f(x, y) onto each pair of the current matrix
+ * elements and given matrix. After applying, each element of the current
+ * matrix will be changed from x to f(x, y).
+ *
+ * @param other The matrix contributing the second argument of the function.
+ * @param fun The function that takes two arguments.
+ * @return The matrix itself, supply for chain operation.
+ */
+ public DoubleMatrix apply(DoubleMatrix other, DoubleDoubleFunction fun);
+
}
Index: ml/src/main/java/org/apache/hama/ml/math/DoubleVector.java
===================================================================
--- ml/src/main/java/org/apache/hama/ml/math/DoubleVector.java (revision 1493881)
+++ ml/src/main/java/org/apache/hama/ml/math/DoubleVector.java (working copy)
@@ -66,6 +66,7 @@
* @param func the function to apply.
* @return a new vector with the applied function.
*/
+ @Deprecated
public DoubleVector apply(DoubleVectorFunction func);
/**
@@ -76,9 +77,29 @@
* @param func the function to apply on this and the other vector.
* @return a new vector with the result of the function of the two vectors.
*/
+ @Deprecated
public DoubleVector apply(DoubleVector other, DoubleDoubleVectorFunction func);
/**
+ * Apply a given {@link DoubleVectorFunction} to this vector and return a new
+ * one.
+ *
+ * @param func the function to apply.
+ * @return a new vector with the applied function.
+ */
+ public DoubleVector apply(DoubleFunction func);
+
+ /**
+ * Apply a given {@link DoubleDoubleVectorFunction} to this vector and the
+ * other given vector.
+ *
+ * @param other the other vector.
+ * @param func the function to apply on this and the other vector.
+ * @return a new vector with the result of the function of the two vectors.
+ */
+ public DoubleVector apply(DoubleVector other, DoubleDoubleFunction func);
+
+ /**
* Adds the given {@link DoubleVector} to this vector.
*
* @param v the other vector.
Index: ml/src/main/java/org/apache/hama/ml/math/DoubleVectorFunction.java
===================================================================
--- ml/src/main/java/org/apache/hama/ml/math/DoubleVectorFunction.java (revision 1493881)
+++ ml/src/main/java/org/apache/hama/ml/math/DoubleVectorFunction.java (working copy)
@@ -20,7 +20,10 @@
/**
* A function that can be applied to a double vector via {@link DoubleVector}
* #apply({@link DoubleVectorFunction} f);
+ *
+ * This class will be replaced by {@link DoubleFunction}
*/
+@Deprecated
public interface DoubleVectorFunction {
/**
Index: ml/src/main/java/org/apache/hama/ml/perception/Sigmoid.java
===================================================================
--- ml/src/main/java/org/apache/hama/ml/perception/Sigmoid.java (revision 1493881)
+++ ml/src/main/java/org/apache/hama/ml/perception/Sigmoid.java (working copy)
@@ -27,7 +27,7 @@
public class Sigmoid extends SquashingFunction {
@Override
- public double calculate(int index, double value) {
+ public double calculate(double value) {
return 1.0 / (1 + Math.exp(-value));
}
Index: ml/src/main/java/org/apache/hama/ml/perception/SmallMultiLayerPerceptron.java
===================================================================
--- ml/src/main/java/org/apache/hama/ml/perception/SmallMultiLayerPerceptron.java (revision 1493881)
+++ ml/src/main/java/org/apache/hama/ml/perception/SmallMultiLayerPerceptron.java (working copy)
@@ -199,8 +199,8 @@
prevNeuronIdx, neuronIdx) * intermediateResult[prevNeuronIdx];
}
// calculate via squashing function
- results[neuronIdx + offset] = this.squashingFunction.calculate(0,
- results[neuronIdx + offset]);
+ results[neuronIdx + offset] = this.squashingFunction
+ .calculate(results[neuronIdx + offset]);
}
return results;
Index: ml/src/main/java/org/apache/hama/ml/perception/SquashingFunction.java
===================================================================
--- ml/src/main/java/org/apache/hama/ml/perception/SquashingFunction.java (revision 1493881)
+++ ml/src/main/java/org/apache/hama/ml/perception/SquashingFunction.java (working copy)
@@ -17,19 +17,19 @@
*/
package org.apache.hama.ml.perception;
-import org.apache.hama.ml.math.DoubleVectorFunction;
+import org.apache.hama.ml.math.DoubleFunction;
/**
* The squashing function to activate the neurons.
*
*/
-public abstract class SquashingFunction implements DoubleVectorFunction {
+public abstract class SquashingFunction extends DoubleFunction {
/**
* Calculates the result with a given index and value of a vector.
*/
@Override
- public abstract double calculate(int index, double value);
+ public abstract double calculate(double value);
/**
* Apply the gradient descent to each of the elements in vector.
Index: ml/src/main/java/org/apache/hama/ml/perception/Tanh.java
===================================================================
--- ml/src/main/java/org/apache/hama/ml/perception/Tanh.java (revision 1493881)
+++ ml/src/main/java/org/apache/hama/ml/perception/Tanh.java (working copy)
@@ -20,11 +20,12 @@
/**
* The hyperbolic tangent function. It is used as a squashing function in
* multi-layer perceptron.
+ *
*/
public class Tanh extends SquashingFunction {
@Override
- public double calculate(int index, double value) {
+ public double calculate(double value) {
return Math.tanh(value);
}
Index: ml/src/test/java/org/apache/hama/ml/math/TestDenseDoubleMatrix.java
===================================================================
--- ml/src/test/java/org/apache/hama/ml/math/TestDenseDoubleMatrix.java (revision 0)
+++ ml/src/test/java/org/apache/hama/ml/math/TestDenseDoubleMatrix.java (working copy)
@@ -0,0 +1,88 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hama.ml.math;
+
+import static org.junit.Assert.assertArrayEquals;
+
+import org.junit.Test;
+
+/**
+ * Test case for {@link DenseDoubleMatrix}
+ *
+ */
+public class TestDenseDoubleMatrix {
+
+ @Test
+ public void testDoubleFunction() {
+ double[][] values = new double[][] { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
+
+ double[][] result = new double[][] { { 2, 3, 4 }, { 5, 6, 7 }, { 8, 9, 10 } };
+
+ DenseDoubleMatrix mat = new DenseDoubleMatrix(values);
+ mat.apply(new DoubleFunction() {
+
+ @Override
+ public double calculate(double value) {
+ return value + 1;
+ }
+
+ @Override
+ public double calculateDerivative(double value) {
+ throw new UnsupportedOperationException();
+ }
+
+ });
+
+ double[][] actual = mat.getValues();
+ for (int i = 0; i < actual.length; ++i) {
+ assertArrayEquals(result[i], actual[i], 0.0001);
+ }
+ }
+
+ @Test
+ public void testDoubleDoubleFunction() {
+ double[][] values1 = new double[][] { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
+ double[][] values2 = new double[][] { { 2, 3, 4 }, { 5, 6, 7 },
+ { 8, 9, 10 } };
+ double[][] result = new double[][] { { 3, 5, 7 }, { 9, 11, 13 },
+ { 15, 17, 19 } };
+
+ DenseDoubleMatrix mat1 = new DenseDoubleMatrix(values1);
+ DenseDoubleMatrix mat2 = new DenseDoubleMatrix(values2);
+
+ mat1.apply(mat2, new DoubleDoubleFunction() {
+
+ @Override
+ public double calculate(double x1, double x2) {
+ return x1 + x2;
+ }
+
+ @Override
+ public double calculateDerivative(double x1, double x2) {
+ throw new UnsupportedOperationException();
+ }
+
+ });
+
+ double[][] actual = mat1.getValues();
+ for (int i = 0; i < actual.length; ++i) {
+ assertArrayEquals(result[i], actual[i], 0.0001);
+ }
+ }
+
+}
Index: ml/src/test/java/org/apache/hama/ml/math/TestDenseDoubleVector.java
===================================================================
--- ml/src/test/java/org/apache/hama/ml/math/TestDenseDoubleVector.java (revision 0)
+++ ml/src/test/java/org/apache/hama/ml/math/TestDenseDoubleVector.java (working copy)
@@ -0,0 +1,80 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hama.ml.math;
+
+import static org.junit.Assert.assertArrayEquals;
+
+import org.junit.Test;
+
+/**
+ * Testcase for {@link DenseDoubleVector}
+ *
+ */
+public class TestDenseDoubleVector {
+
+ @Test
+ public void testApplyDoubleFunction() {
+ double[] values = new double[] { 1, 2, 3, 4, 5 };
+ double[] result = new double[] { 2, 3, 4, 5, 6 };
+
+ DoubleVector vec1 = new DenseDoubleVector(values);
+
+ vec1.apply(new DoubleFunction() {
+
+ @Override
+ public double calculate(double value) {
+ return value + 1;
+ }
+
+ @Override
+ public double calculateDerivative(double value) {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ });
+
+ assertArrayEquals(result, vec1.toArray(), 0.0001);
+ }
+
+ @Test
+ public void testApplyDoubleDoubleFunction() {
+ double[] values1 = new double[] { 1, 2, 3, 4, 5, 6 };
+ double[] values2 = new double[] { 7, 8, 9, 10, 11, 12 };
+ double[] result = new double[] { 8, 10, 12, 14, 16, 18 };
+
+ DoubleVector vec1 = new DenseDoubleVector(values1);
+ DoubleVector vec2 = new DenseDoubleVector(values2);
+
+ vec1.apply(vec2, new DoubleDoubleFunction() {
+
+ @Override
+ public double calculate(double x1, double x2) {
+ return x1 + x2;
+ }
+
+ @Override
+ public double calculateDerivative(double x1, double x2) {
+ throw new UnsupportedOperationException("Not supported");
+ }
+
+ });
+
+ assertArrayEquals(result, vec1.toArray(), 0.0001);
+
+ }
+}