You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@systemml.apache.org by mb...@apache.org on 2017/12/02 02:40:16 UTC

systemml git commit: [SYSTEMML-2035] Fix result correctness sparse maxpooling_backward

Repository: systemml
Updated Branches:
  refs/heads/master f53fcc8af -> 4d7606574


[SYSTEMML-2035] Fix result correctness sparse maxpooling_backward

So far all maxpooling backward tests ran exclusively against dense data,
which has hidden result correctness issues of sparse-dense maxpooling
backward operations and incorrect R comparison results in the presence
of duplicate values. This patch addresses these correctness issues by
explicitly correcting for unseen zero values.


Project: http://git-wip-us.apache.org/repos/asf/systemml/repo
Commit: http://git-wip-us.apache.org/repos/asf/systemml/commit/4d760657
Tree: http://git-wip-us.apache.org/repos/asf/systemml/tree/4d760657
Diff: http://git-wip-us.apache.org/repos/asf/systemml/diff/4d760657

Branch: refs/heads/master
Commit: 4d760657456cc06450ce9fc3d01ccf1e63b124eb
Parents: f53fcc8
Author: Matthias Boehm <mb...@gmail.com>
Authored: Fri Dec 1 18:35:43 2017 -0800
Committer: Matthias Boehm <mb...@gmail.com>
Committed: Fri Dec 1 18:35:43 2017 -0800

----------------------------------------------------------------------
 .../runtime/matrix/data/LibMatrixDNNHelper.java |  24 ++--
 .../functions/tensor/PoolBackwardTest.java      | 119 ++++++++-----------
 .../scripts/functions/tensor/PoolBackwardTest.R |  18 +--
 .../functions/tensor/PoolBackwardTest.dml       |  16 ++-
 4 files changed, 84 insertions(+), 93 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/systemml/blob/4d760657/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixDNNHelper.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixDNNHelper.java b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixDNNHelper.java
index be8a833..7b749dd 100644
--- a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixDNNHelper.java
+++ b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixDNNHelper.java
@@ -20,6 +20,7 @@ package org.apache.sysml.runtime.matrix.data;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.BitSet;
 import java.util.concurrent.Callable;
 
 import org.apache.sysml.hops.OptimizerUtils;
@@ -421,10 +422,12 @@ public class LibMatrixDNNHelper {
 		
 		int [] tensorIndexes = new int[3];
 		
-		int start_index_h = params.start_indexes_h[p];
-		int end_index_h = params.end_indexes_h[p];
-		int start_index_w = params.start_indexes_w[q];
-		int end_index_w = params.end_indexes_w[q];
+		int start_h = params.start_indexes_h[p];
+		int end_h = params.end_indexes_h[p];
+		int start_w = params.start_indexes_w[q];
+		int end_w = params.end_indexes_w[q];
+		int numVals = (end_h-start_h)*(end_w-start_w);
+		BitSet bmap = new BitSet(numVals);
 		
 		int maxIndex = -1; 
 		double maxVal = -Double.MAX_VALUE;
@@ -446,17 +449,24 @@ public class LibMatrixDNNHelper {
 					continue;
 				int h = tensorIndexes[1];
 				int w = tensorIndexes[2];
-				if(h >= start_index_h && h < end_index_h && w >= start_index_w && w < end_index_w) {
+				if(h >= start_h && h < end_h && w >= start_w && w < end_w) {
 					double val = performReluBackward && avals[j] < 0 ? 0 : avals[j]; 
 					if(maxVal < val) {
 						maxIndex = inputOffset +  h*params.W + w;
 						maxVal = val;
 					}
+					bmap.set((h-start_h)*(end_w-start_w) + (w-start_w));
 				}
 			}
 		}
-		else {
-			maxIndex = inputOffset;
+		
+		//correction for 0 maximum and subset of evaluated entries
+		int firstMiss = bmap.nextClearBit(0);
+		if( firstMiss < numVals && maxVal<0 ) {
+			int lh = firstMiss/(end_w-start_w)+start_h;
+			int lw = firstMiss%(end_w-start_w)+start_w;
+			maxIndex = inputOffset + lh * params.W + lw;
+			maxVal = 0;
 		}
 		return maxIndex;
 	}

http://git-wip-us.apache.org/repos/asf/systemml/blob/4d760657/src/test/java/org/apache/sysml/test/integration/functions/tensor/PoolBackwardTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/sysml/test/integration/functions/tensor/PoolBackwardTest.java b/src/test/java/org/apache/sysml/test/integration/functions/tensor/PoolBackwardTest.java
index 54fda03..ca3a19a 100644
--- a/src/test/java/org/apache/sysml/test/integration/functions/tensor/PoolBackwardTest.java
+++ b/src/test/java/org/apache/sysml/test/integration/functions/tensor/PoolBackwardTest.java
@@ -32,7 +32,6 @@ import org.junit.Test;
 
 public class PoolBackwardTest extends AutomatedTestBase
 {
-	
 	private final static String TEST_NAME = "PoolBackwardTest";
 	private final static String TEST_DIR = "functions/tensor/";
 	private final static String TEST_CLASS_DIR = TEST_DIR + PoolBackwardTest.class.getSimpleName() + "/";
@@ -40,157 +39,133 @@ public class PoolBackwardTest extends AutomatedTestBase
 	
 	@Override
 	public void setUp() {
-		addTestConfiguration(TEST_NAME, new TestConfiguration(TEST_CLASS_DIR, TEST_NAME, 
-				new String[] {"B"}));
+		addTestConfiguration(TEST_NAME, new TestConfiguration(TEST_CLASS_DIR, TEST_NAME, new String[] {"B"}));
 	}
 	
 	@Test
-	public void testMaxPool2DBackwardDense1() 
-	{
+	public void testMaxPool2DBackwardDense1() {
 		int numImg = 1; int imgSize = 4; int numChannels = 1;  int stride = 2; int pad = 0; int poolSize1 = 2; int poolSize2 = 2;
 		runPoolTest(ExecType.CP, imgSize, numImg, numChannels, stride, pad, poolSize1, poolSize2, "max", false, false);
 	}
 	
 	@Test
-	public void testMaxPool2DBackwardDense2() 
-	{
+	public void testMaxPool2DBackwardDense2() {
 		int numImg = 3; int imgSize = 6; int numChannels = 3;  int stride = 1; int pad = 0; int poolSize1 = 2; int poolSize2 = 2;
 		runPoolTest(ExecType.CP, imgSize, numImg, numChannels, stride, pad, poolSize1, poolSize2, "max", false, false);
 	}
 	
 	@Test
-	public void testMaxPool2DBackwardDense3() 
-	{
+	public void testMaxPool2DBackwardDense3() {
 		int numImg = 2; int imgSize = 7; int numChannels = 2;  int stride = 2; int pad = 0; int poolSize1 = 3; int poolSize2 = 3;
 		runPoolTest(ExecType.CP, imgSize, numImg, numChannels, stride, pad, poolSize1, poolSize2, "max", false, false);
 	}
 	
 	@Test
-	public void testMaxPool2DBackwardSparse1() 
-	{
+	public void testMaxPool2DBackwardSparse1() {
 		int numImg = 1; int imgSize = 4; int numChannels = 1;  int stride = 2; int pad = 0; int poolSize1 = 2; int poolSize2 = 2;
 		runPoolTest(ExecType.CP, imgSize, numImg, numChannels, stride, pad, poolSize1, poolSize2, "max", true, false);
 	}
 	
 	@Test
-	public void testMaxPool2DBackwardSparse2() 
-	{
+	public void testMaxPool2DBackwardSparse2() {
 		int numImg = 3; int imgSize = 6; int numChannels = 3;  int stride = 1; int pad = 0; int poolSize1 = 2; int poolSize2 = 2;
 		runPoolTest(ExecType.CP, imgSize, numImg, numChannels, stride, pad, poolSize1, poolSize2, "max", true, false);
 	}
 	
 	@Test
-	public void testMaxPool2DBackwardSparse3() 
-	{
+	public void testMaxPool2DBackwardSparse3() {
 		int numImg = 2; int imgSize = 7; int numChannels = 2;  int stride = 2; int pad = 0; int poolSize1 = 3; int poolSize2 = 3;
 		runPoolTest(ExecType.CP, imgSize, numImg, numChannels, stride, pad, poolSize1, poolSize2, "max", true, false);
 	}
 	
 	@Test
-	public void testMaxPool2DBackwardSparse4() 
-	{
+	public void testMaxPool2DBackwardSparse4() {
 		int numImg = 1; int imgSize = 4; int numChannels = 1;  int stride = 2; int pad = 0; int poolSize1 = 2; int poolSize2 = 2;
 		runPoolTest(ExecType.CP, imgSize, numImg, numChannels, stride, pad, poolSize1, poolSize2, "max", true, true);
 	}
 	
 	@Test
-	public void testMaxPool2DBackwardSparse5() 
-	{
+	public void testMaxPool2DBackwardSparse5() {
 		int numImg = 3; int imgSize = 6; int numChannels = 3;  int stride = 1; int pad = 0; int poolSize1 = 2; int poolSize2 = 2;
 		runPoolTest(ExecType.CP, imgSize, numImg, numChannels, stride, pad, poolSize1, poolSize2, "max", true, true);
 	}
 	
 	@Test
-	public void testMaxPool2DBackwardSparse6() 
-	{
+	public void testMaxPool2DBackwardSparse6() {
 		int numImg = 2; int imgSize = 7; int numChannels = 2;  int stride = 2; int pad = 0; int poolSize1 = 3; int poolSize2 = 3;
 		runPoolTest(ExecType.CP, imgSize, numImg, numChannels, stride, pad, poolSize1, poolSize2, "max", true, true);
 	}
 	
 	@Test
-	public void testMaxPool2DBackwardSparse7() 
-	{
+	public void testMaxPool2DBackwardSparse7() {
 		int numImg = 1; int imgSize = 4; int numChannels = 1;  int stride = 2; int pad = 0; int poolSize1 = 2; int poolSize2 = 2;
 		runPoolTest(ExecType.CP, imgSize, numImg, numChannels, stride, pad, poolSize1, poolSize2, "max", false, true);
 	}
 	
 	@Test
-	public void testMaxPool2DBackwardSparse8() 
-	{
+	public void testMaxPool2DBackwardSparse8() {
 		int numImg = 3; int imgSize = 6; int numChannels = 3;  int stride = 1; int pad = 0; int poolSize1 = 2; int poolSize2 = 2;
 		runPoolTest(ExecType.CP, imgSize, numImg, numChannels, stride, pad, poolSize1, poolSize2, "max", false, true);
 	}
 	
 	@Test
-	public void testMaxPool2DBackwardSparse9() 
-	{
+	public void testMaxPool2DBackwardSparse9() {
 		int numImg = 2; int imgSize = 7; int numChannels = 2;  int stride = 2; int pad = 0; int poolSize1 = 3; int poolSize2 = 3;
 		runPoolTest(ExecType.CP, imgSize, numImg, numChannels, stride, pad, poolSize1, poolSize2, "max", false, true);
 	}
 	
-	/**
-	 * 
-	 * @param et
-	 * @param sparse
-	 */
+	@Test
+	public void testMaxPool2DBackwardSparse10() {
+		int numImg = 10; int imgSize = 28; int numChannels = 1;  int stride = 1; int pad = 0; int poolSize1 = 5; int poolSize2 = 5;
+		runPoolTest(ExecType.CP, imgSize, numImg, numChannels, stride, pad, poolSize1, poolSize2, "max", true, false);
+	}
+	
 	public void runPoolTest( ExecType et, int imgSize, int numImg, int numChannels, int stride, 
 			int pad, int poolSize1, int poolSize2, String poolMode, boolean sparse1, boolean sparse2) 
 	{
-		RUNTIME_PLATFORM oldRTP = rtplatform;
-			
+		RUNTIME_PLATFORM platformOld = rtplatform;
+		switch( et ){
+			case MR: rtplatform = RUNTIME_PLATFORM.HADOOP; break;
+			case SPARK: rtplatform = RUNTIME_PLATFORM.SPARK; break;
+			default: rtplatform = RUNTIME_PLATFORM.HYBRID; break;
+		}
 		boolean sparkConfigOld = DMLScript.USE_LOCAL_SPARK_CONFIG;
-		
+		if( rtplatform == RUNTIME_PLATFORM.SPARK )
+			DMLScript.USE_LOCAL_SPARK_CONFIG = true;
+				
 		try
 		{
-			String sparseVal1 = (""+sparse1).toUpperCase();
-			String sparseVal2 = (""+sparse2).toUpperCase();
+			String sparseVal1 = String.valueOf(sparse1).toUpperCase();
+			String sparseVal2 = String.valueOf(sparse2).toUpperCase();
 			TestConfiguration config = getTestConfiguration(TEST_NAME);
-	    if(et == ExecType.SPARK) {
-	    	rtplatform = RUNTIME_PLATFORM.SPARK;
-	    }
-	    else {
-	    	rtplatform = (et==ExecType.MR)? RUNTIME_PLATFORM.HADOOP : RUNTIME_PLATFORM.SINGLE_NODE;
-	    }
-			if( rtplatform == RUNTIME_PLATFORM.SPARK )
-				DMLScript.USE_LOCAL_SPARK_CONFIG = true;
-			
 			loadTestConfiguration(config);
-	        
-			/* This is for running the junit test the new way, i.e., construct the arguments directly */
-			String RI_HOME = SCRIPT_DIR + TEST_DIR;
-			fullDMLScriptName = RI_HOME + TEST_NAME + ".dml";
 			
 			long P = ConvolutionUtils.getP(imgSize, poolSize1, stride, pad);
-			programArgs = new String[]{"-explain", "-args",  "" + imgSize, "" + numImg, 
-					"" + numChannels, "" + poolSize1, "" + poolSize2, 
-					"" + stride, "" + pad, poolMode, 
-					"" + P, "" + P, 
-					output("B"), sparseVal1, sparseVal2};
-			        
-			boolean exceptionExpected = false;
-			int expectedNumberOfJobs = -1;
-			runTest(true, exceptionExpected, null, expectedNumberOfJobs);
+			
+			String RI_HOME = SCRIPT_DIR + TEST_DIR;
+			fullDMLScriptName = RI_HOME + TEST_NAME + ".dml";
+			programArgs = new String[]{"-explain", "-args",  String.valueOf(imgSize), String.valueOf(numImg),
+					String.valueOf(numChannels), String.valueOf(poolSize1), String.valueOf(poolSize2),
+					String.valueOf(stride), String.valueOf(pad), String.valueOf(poolMode),
+					String.valueOf(P), String.valueOf(P), output("B"), sparseVal1, sparseVal2};
 			
 			fullRScriptName = RI_HOME + TEST_NAME + ".R";
-			rCmd = "Rscript" + " " + fullRScriptName + " " + imgSize + " " + numImg + 
-					" " + numChannels + " " + poolSize1 + 
-					" " + poolSize2 + " " + stride + " " + pad + " " +  P + " " + P + " " + expectedDir() +
-					" " + sparseVal1 + " " + sparseVal2; 
+			rCmd = "Rscript" + " " + fullRScriptName + " " + imgSize + " " + numImg + " " + numChannels + 
+					" " + poolSize1 + " " + poolSize2 + " " + stride + " " + pad + " " +  P + " " + P + 
+					" " + expectedDir() + " " + sparseVal1 + " " + sparseVal2; 
 			
-			// Run comparison R script
+			// run dml and r scripts
+			runTest(true, false, null, -1);
 			runRScript(true);
-			HashMap<CellIndex, Double> bHM = readRMatrixFromFS("B");
 			
+			// compare results
+			HashMap<CellIndex, Double> bHM = readRMatrixFromFS("B");
 			HashMap<CellIndex, Double> dmlfile = readDMLMatrixFromHDFS("B");
-			TestUtils.compareMatrices(dmlfile, bHM, epsilon, "B-DML", "NumPy");
-			
+			TestUtils.compareMatrices(dmlfile, bHM, epsilon, "B-DML", "R");
 		}
-		finally
-		{
-			rtplatform = oldRTP;
+		finally {
+			rtplatform = platformOld;
 			DMLScript.USE_LOCAL_SPARK_CONFIG = sparkConfigOld;
 		}
-		
 	}
-	
 }

http://git-wip-us.apache.org/repos/asf/systemml/blob/4d760657/src/test/scripts/functions/tensor/PoolBackwardTest.R
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/tensor/PoolBackwardTest.R b/src/test/scripts/functions/tensor/PoolBackwardTest.R
index f3133a7..b56331e 100644
--- a/src/test/scripts/functions/tensor/PoolBackwardTest.R
+++ b/src/test/scripts/functions/tensor/PoolBackwardTest.R
@@ -35,15 +35,17 @@ Q=as.integer(args[9])
 x=matrix(seq(1, numImg*numChannels*imgSize*imgSize), numImg, numChannels*imgSize*imgSize, byrow=TRUE)
 dout=matrix(seq(1, numImg*numChannels*P*Q), numImg, numChannels*P*Q, byrow=TRUE)
 if(as.logical(args[11])) {
-	# zero_mask = (x - mean(x)) > 0 
-	# x = x * zero_mask
+	zero_mask = (x - mean(x)*1.5) > 0 
+	x = x * zero_mask
+} else {
+	x = x - mean(x)
 }
 if(as.logical(args[12])) {
-	# zero_mask = (dout - mean(dout)) > 0 
-	# dout = dout * zero_mask
+	zero_mask = (dout - mean(dout)*1.5) > 0 
+	dout = dout * zero_mask
+} else {
+	dout = dout - mean(dout)
 }
-x = x - mean(x)
-dout = dout - mean(dout)
 max_pool_backward <- function(dout, Hout, Wout, X, C,
                     Hin, Win, Hf, Wf, strideh, stridew)
      {
@@ -65,7 +67,8 @@ max_pool_backward <- function(dout, Hout, Wout, X, C,
           win = (wout-1) * stridew + 1
           img_slice_patch = img_slice[hin:(hin+Hf-1), win:(win+Wf-1)]
           max_val = max(img_slice_patch)
-          max_val_ind = (img_slice_patch == max_val)  # max value indicator
+          max_val_ind = matrix(0, nrow(img_slice_patch), ncol(img_slice_patch))
+          max_val_ind[which.max(img_slice_patch)] = 1  # first max value indicator
           # gradient passes through only for the max value in this patch
           dimg_slice_patch = max_val_ind * dout[n, (c-1)*Hout*Wout + (hout-1)*Wout + wout]
           dimg_slice[hin:(hin+Hf-1), win:(win+Wf-1)] =
@@ -82,4 +85,3 @@ max_pool_backward <- function(dout, Hout, Wout, X, C,
 
 output = max_pool_backward(dout, P, Q, x, numChannels, imgSize, imgSize, poolSize1, poolSize2, stride, stride)
 writeMM(as(output,"CsparseMatrix"), paste(args[10], "B", sep=""))
-

http://git-wip-us.apache.org/repos/asf/systemml/blob/4d760657/src/test/scripts/functions/tensor/PoolBackwardTest.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/tensor/PoolBackwardTest.dml b/src/test/scripts/functions/tensor/PoolBackwardTest.dml
index 22f778f..ea0f970 100644
--- a/src/test/scripts/functions/tensor/PoolBackwardTest.dml
+++ b/src/test/scripts/functions/tensor/PoolBackwardTest.dml
@@ -34,15 +34,19 @@ Q = $10
 x=matrix(seq(1, numImg*numChannels*imgSize*imgSize), rows=numImg, cols=numChannels*imgSize*imgSize)
 dout=matrix(seq(1, numImg*numChannels*P*Q), rows=numImg, cols=numChannels*P*Q)
 if($12) {
-	# zero_mask = (x - mean(x)) > 0 
-	# x = x * zero_mask
+	zero_mask = (x - mean(x)*1.5) > 0 
+	x = x * zero_mask
+}
+else {
+	x = x - mean(x)
 }
 if($13) {
-	# zero_mask = (dout - mean(dout)) > 0 
-	# dout = dout * zero_mask
+	zero_mask = (dout - mean(dout)*1.5) > 0 
+	dout = dout * zero_mask
+}
+else {
+	dout = dout - mean(dout)
 }
-x = x - mean(x)
-dout = dout - mean(dout)
 if(poolMode == "max") {
 	output = max_pool_backward(x, dout, stride=[stride, stride], padding=[pad, pad], input_shape=[numImg, numChannels, imgSize, imgSize], pool_size=[poolSize1, poolSize2])
 }