You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mxnet.apache.org by lx...@apache.org on 2017/07/07 15:58:34 UTC

[21/50] [abbrv] incubator-mxnet-test git commit: [R] fix concat for symbol and NDArray. close #6650 (#6696)

[R] fix concat for symbol and NDArray. close #6650 (#6696)



Project: http://git-wip-us.apache.org/repos/asf/incubator-mxnet-test/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mxnet-test/commit/bfb79bd2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mxnet-test/tree/bfb79bd2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mxnet-test/diff/bfb79bd2

Branch: refs/heads/master
Commit: bfb79bd2d7adf2fdde8266fe62565f6b3ff6ec40
Parents: aec0460
Author: Qiang Kou (KK) <qk...@qkou.info>
Authored: Thu Jun 29 19:17:54 2017 -0700
Committer: GitHub <no...@github.com>
Committed: Thu Jun 29 19:17:54 2017 -0700

----------------------------------------------------------------------
 Jenkinsfile                             |   2 +
 R-package/R/symbol.R                    |  40 +++++++++-
 R-package/src/export.cc                 |   2 +-
 R-package/src/ndarray.cc                |  10 ++-
 R-package/src/symbol.cc                 |   8 ++
 R-package/src/symbol.h                  |   6 ++
 R-package/tests/testthat/test_ndarray.R | 106 +++++++++++++++++++++------
 R-package/tests/testthat/test_symbol.R  |  57 ++++++++++----
 8 files changed, 190 insertions(+), 41 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mxnet-test/blob/bfb79bd2/Jenkinsfile
----------------------------------------------------------------------
diff --git a/Jenkinsfile b/Jenkinsfile
index cd6ab31..881fef5 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -277,6 +277,7 @@ stage('Unit Test') {
         init_git()
         unpack_lib('cpu')
         timeout(time: max_time, unit: 'MINUTES') {
+          sh "${docker_run} cpu rm -rf .Renviron"
           sh "${docker_run} cpu mkdir -p /workspace/ut-r-cpu/site-library"
           sh "${docker_run} cpu make rpkg USE_BLAS=openblas R_LIBS=/workspace/ut-r-cpu/site-library"
           sh "${docker_run} cpu R CMD INSTALL --library=/workspace/ut-r-cpu/site-library mxnet_current_r.tar.gz"
@@ -291,6 +292,7 @@ stage('Unit Test') {
         init_git()
         unpack_lib('gpu')
         timeout(time: max_time, unit: 'MINUTES') {
+          sh "${docker_run} cpu rm -rf .Renviron"
           sh "${docker_run} gpu mkdir -p /workspace/ut-r-gpu/site-library"
           sh "${docker_run} gpu make rpkg USE_BLAS=openblas R_LIBS=/workspace/ut-r-gpu/site-library"
           sh "${docker_run} gpu R CMD INSTALL --library=/workspace/ut-r-gpu/site-library mxnet_current_r.tar.gz"

http://git-wip-us.apache.org/repos/asf/incubator-mxnet-test/blob/bfb79bd2/R-package/R/symbol.R
----------------------------------------------------------------------
diff --git a/R-package/R/symbol.R b/R-package/R/symbol.R
index 091a646..f222c55 100644
--- a/R-package/R/symbol.R
+++ b/R-package/R/symbol.R
@@ -32,14 +32,32 @@ mx.symbol.Group <- function(...) {
 #' @return out The result mx.symbol
 #' 
 #' @export
-mx.symbol.Concat <- function(data, num.args, dim = NULL, name = NULL) {
+mx.symbol.concat <- function(data, num.args, dim = NULL, name = NULL) {
   data[['num.args']] <- num.args
   
   if(!is.null(dim)) data[['dim']] <- dim
   
   if(!is.null(name)) data[['name']] <- name
   
-  mx.varg.symbol.Concat(data)
+  mx.varg.symbol.concat(data)
+}
+
+#' Perform an feature concat on channel dim (dim 1) over all the inputs.
+#' 
+#' @param data  list, required
+#'     List of tensors to concatenate
+#' @param num.args  int, required
+#'     Number of inputs to be concated.
+#' @param dim  int, optional, default='1'
+#'     the dimension to be concated.
+#' @param name  string, optional
+#'     Name of the resulting symbol.
+#' @return out The result mx.symbol
+#' 
+#' @export
+mx.symbol.Concat <- function(data, num.args, dim = NULL, name = NULL) {
+  warning("mx.symbol.Concat is deprecated. Use mx.symbol.concat instead.")
+  mx.symbol.concat(data, num.args, dim, name)
 }
 
 #' Save an mx.symbol object
@@ -123,6 +141,24 @@ mx.apply <- function(x, ...) {
   x$apply(list(...))
 }
 
+#' Get a symbol that contains all the internals
+#' @param x The input symbol
+#'
+#' @export
+internals <- function(x) {
+  if (!is.MXSymbol(x)) stop("only for MXSymbol type")
+  x$get.internals()
+}
+
+#' Gets a new grouped symbol whose output contains inputs to output nodes of the original symbol.
+#' @param x The input symbol
+#'
+#' @export
+children <- function(x) {
+  if (!is.MXSymbol(x)) stop("only for MXSymbol type")
+  x$get.children()
+}
+
 #' Get the outputs of a symbol.
 #' @param x The input symbol
 #'

http://git-wip-us.apache.org/repos/asf/incubator-mxnet-test/blob/bfb79bd2/R-package/src/export.cc
----------------------------------------------------------------------
diff --git a/R-package/src/export.cc b/R-package/src/export.cc
index ed8f4bc..0e77c1c 100644
--- a/R-package/src/export.cc
+++ b/R-package/src/export.cc
@@ -93,7 +93,7 @@ void Exporter::Export(const std::string& path) {
     std::string fname = Rcpp::as<std::string>(func_names[i]);
     // skip internal functions
     if (fname.find("internal.") != std::string::npos) continue;
-    if (fname == "mx.varg.symbol.Concat") continue;
+    if (fname == "mx.varg.symbol.Concat" || fname == "mx.varg.symbol.concat") continue;
     Rcpp::List func_info(scope->get_function(fname));
     std::string docstr = Rcpp::as<std::string>(func_info[2]);
     if (docstr.find("@export") == std::string::npos) continue;

http://git-wip-us.apache.org/repos/asf/incubator-mxnet-test/blob/bfb79bd2/R-package/src/ndarray.cc
----------------------------------------------------------------------
diff --git a/R-package/src/ndarray.cc b/R-package/src/ndarray.cc
index c2bfe0c..d270a30 100644
--- a/R-package/src/ndarray.cc
+++ b/R-package/src/ndarray.cc
@@ -398,10 +398,16 @@ SEXP NDArrayFunction::operator() (SEXP* args) {
   std::vector<const char*> param_vals;
   std::vector<NDArrayHandle> out_args;
 
-
   for (mx_uint i = 0; i < arg_names_.size() - 1; ++i) {
     if (arg_nd_array_[i]) {
-      nd_args.push_back(NDArray(args[i])->handle);
+      if (TYPEOF(args[i]) == 22) {
+        nd_args.push_back(NDArray(args[i])->handle);
+      } else if (TYPEOF(args[i]) == 19) {
+        Rcpp::List data_lst = Rcpp::as<Rcpp::List>(args[i]);
+        for (size_t k = 0; k < data_lst.size(); k++) {
+          nd_args.push_back(NDArray((SEXP)data_lst[k])->handle);
+        }
+      }
     } else {
       if (args[i] != R_NilValue) {
         param_keys.push_back(arg_names_[i].c_str());

http://git-wip-us.apache.org/repos/asf/incubator-mxnet-test/blob/bfb79bd2/R-package/src/symbol.cc
----------------------------------------------------------------------
diff --git a/R-package/src/symbol.cc b/R-package/src/symbol.cc
index aa901ff..b5d6eca 100644
--- a/R-package/src/symbol.cc
+++ b/R-package/src/symbol.cc
@@ -134,6 +134,12 @@ Symbol::RObjectType Symbol::GetInternals() const {
   return Symbol::RObject(out);
 }
 
+Symbol::RObjectType Symbol::GetChildren() const {
+  SymbolHandle out;
+  MX_CALL(MXSymbolGetChildren(handle_, &out));
+  return Symbol::RObject(out);
+}
+
 Symbol::RObjectType Symbol::GetOutput(mx_uint index) const {
   SymbolHandle out;
   MX_CALL(MXSymbolGetOutput(handle_, index - 1, &out));
@@ -344,6 +350,8 @@ void Symbol::InitRcppModule() {
               "List the auxiliary state names of the symbol")
       .method("get.internals", &Symbol::GetInternals,
               "Get a symbol that contains all the internals")
+      .method("get.children", &Symbol::GetChildren,
+              "Get a symbol that contains all the children")
       .method("get.output", &Symbol::GetOutput,
               "Get index-th output symbol of current one")
       .method("[[", &Symbol::GetOutput,

http://git-wip-us.apache.org/repos/asf/incubator-mxnet-test/blob/bfb79bd2/R-package/src/symbol.h
----------------------------------------------------------------------
diff --git a/R-package/src/symbol.h b/R-package/src/symbol.h
index a361bdf..4bfdebf 100644
--- a/R-package/src/symbol.h
+++ b/R-package/src/symbol.h
@@ -70,6 +70,12 @@ class Symbol {
    */
   RObjectType GetInternals() const;
   /*!
+   * \brief Gets a new grouped symbol whose output contains
+   *     inputs to output nodes of the original symbol.
+   * \return The children of the symbol.
+   */
+  RObjectType GetChildren() const;
+  /*!
    * \brief Get index-th outputs of the symbol.
    * \param symbol The symbol
    * \param index the Index of the output.

http://git-wip-us.apache.org/repos/asf/incubator-mxnet-test/blob/bfb79bd2/R-package/tests/testthat/test_ndarray.R
----------------------------------------------------------------------
diff --git a/R-package/tests/testthat/test_ndarray.R b/R-package/tests/testthat/test_ndarray.R
index a6b85da..e574ea7 100644
--- a/R-package/tests/testthat/test_ndarray.R
+++ b/R-package/tests/testthat/test_ndarray.R
@@ -6,34 +6,39 @@ test_that("element-wise calculation for vector", {
   x = 1:10
   mat = mx.nd.array(as.array(x), mx.cpu(0))
   expect_equal(x, as.array(mat))
-  expect_equal(x+1, as.array(mat+1))
-  expect_equal(x-10, as.array(mat-10))
-  expect_equal(x*20, as.array(mat*20))
-  expect_equal(x/3, as.array(mat/3), tolerance = 1e-5)
-  expect_equal(-1-x, as.array(-1-mat))
-  expect_equal(-5/x, as.array(-5/mat), tolerance = 1e-5)
-  expect_equal(x+x, as.array(mat+mat))
-  expect_equal(x/x, as.array(mat/mat))
-  expect_equal(x*x, as.array(mat*mat))
-  expect_equal(x-x, as.array(mat-mat))
-  expect_equal(as.array(1-mat), as.array(1-mat))
+  expect_equal(x + 1, as.array(mat + 1))
+  expect_equal(x - 10, as.array(mat - 10))
+  expect_equal(x * 20, as.array(mat * 20))
+  expect_equal(x / 3, as.array(mat / 3), tolerance = 1e-5)
+  expect_equal(-1 - x, as.array(-1 - mat))
+  expect_equal(-5 / x, as.array(-5 / mat), tolerance = 1e-5)
+  expect_equal(x + x, as.array(mat + mat))
+  expect_equal(x / x, as.array(mat / mat))
+  expect_equal(x * x, as.array(mat * mat))
+  expect_equal(x - x, as.array(mat - mat))
+  expect_equal(as.array(1 - mat), as.array(1 - mat))
+  
+  x <- runif(10,-10, 10)
+  nd = mx.nd.array(as.array(x))
+  expect_equal(sqrt(abs(x)), as.array(mx.nd.sqrt(mx.nd.abs(nd))), tolerance = 1e-6)
+  expect_equal(x ^ 2, as.array(mx.nd.square(nd)), tolerance = 1e-6)
 })
 
-test_that("element-wise calculation for matrix", {  
+test_that("element-wise calculation for matrix", {
   x = matrix(1:4, 2, 2)
   mat = mx.nd.array(as.array(x), mx.cpu(0))
   expect_equal(x, as.array(mat))
-  expect_equal(x+1, as.array(mat+1))
-  expect_equal(x-10, as.array(mat-10))
-  expect_equal(x*20, as.array(mat*20))
-  expect_equal(x/3, as.array(mat/3), tolerance = 1e-5)
-  expect_equal(-1-x, as.array(-1-mat))
-  expect_equal(-5/x, as.array(-5/mat), tolerance = 1e-5)
-  expect_equal(x+x, as.array(mat+mat))
-  expect_equal(x/x, as.array(mat/mat))
-  expect_equal(x*x, as.array(mat*mat))
-  expect_equal(x-x, as.array(mat-mat))
-  expect_equal(as.array(1-mat), as.array(1-mat))
+  expect_equal(x + 1, as.array(mat + 1))
+  expect_equal(x - 10, as.array(mat - 10))
+  expect_equal(x * 20, as.array(mat * 20))
+  expect_equal(x / 3, as.array(mat / 3), tolerance = 1e-5)
+  expect_equal(-1 - x, as.array(-1 - mat))
+  expect_equal(-5 / x, as.array(-5 / mat), tolerance = 1e-5)
+  expect_equal(x + x, as.array(mat + mat))
+  expect_equal(x / x, as.array(mat / mat))
+  expect_equal(x * x, as.array(mat * mat))
+  expect_equal(x - x, as.array(mat - mat))
+  expect_equal(as.array(1 - mat), as.array(1 - mat))
 })
 
 test_that("ndarray ones, zeros, save and load", {
@@ -48,3 +53,58 @@ test_that("ndarray ones, zeros, save and load", {
   expect_equal(as.array(mat), as.array(mat2[[1]]))
   file.remove('temp.mat')
 })
+
+test_that("ndarray concatenate", {
+  shapes <- matrix(c(2, 3, 4, 2, 2, 2, 4, 2, 2, 1, 4, 2), nrow = 3, byrow = TRUE)
+  array_r <- apply(shapes, 2, function(s) { runif(s, -10, 10) })
+  array_nd <- apply(array_r, 1, function(s) { mx.nd.array(matrix(s, nrow = 1)) })
+  array_nd_concat <- mx.nd.concat(data = array_nd, num_args = 3, dim = 1)
+  expect_equal(array_r, as.matrix(array_nd_concat), tolerance = 1e-6)
+  
+  x1 <- mx.nd.array(c(1:24))
+  x2 <- mx.nd.array(c(25:48))
+  x3 <- mx.nd.concat(data = c(x1, x2), num_args = 2, dim = 0)
+  expect_equal(c(1:48), as.array(x3))
+  expect_equal(dim(x3), 48)
+  
+  x1 <- array(1:24, dim = c(4, 3, 2))
+  x2 <- array(25:48, dim = c(4, 3, 2))
+  x3 <- c(1:4, 25:28, 5:8, 29:32, 9:12, 33:36, 13:16, 37:40, 17:20, 41:44, 21:24, 45:48)
+  y1 <- mx.nd.array(x1)
+  y2 <- mx.nd.array(x2)
+  y3 <- mx.nd.concat(data = c(y1, y2), num_args = 2, dim = 2)
+  expect_equal(dim(y3), c(8, 3, 2))
+  expect_equal(as.array(y3), array(x3, dim = c(8, 3, 2)))
+})
+
+test_that("ndarray clip", {
+  nd <- mx.nd.array(runif(10,-10, 10))
+  nd2 <- mx.nd.clip(nd,-2, 3)
+  arr <- as.array(nd2)
+  expect_equal(arr >= -2 | arr <= 3, rep(TRUE, length(arr)))
+})
+
+test_that("ndarray dot", {
+  a <- matrix(runif(12), nrow = 3)
+  b <- matrix(runif(20), nrow = 4)
+  c <- a %*% b
+  
+  A <- mx.nd.array(t(a))
+  B <- mx.nd.array(t(b))
+  C <- mx.nd.dot(A, B)
+  
+  expect_equal(c, t(as.matrix(C)), tolerance = 1e-6)
+})
+
+test_that("ndarray crop", {
+  x <- mx.nd.ones(c(2, 3, 4))
+  y <- mx.nd.crop(x, begin = c(0, 0, 0), end = c(2, 1, 3))
+  expect_equal(array(1, dim = c(2, 1, 3)), as.array(y))
+  
+  z <- mx.nd.zeros(c(2, 1, 3))
+  x <- mxnet:::mx.nd.internal.crop.assign(x, z, begin = c(0, 0, 0), end = c(2, 1, 3))
+  arr_x <- array(1, dim = dim(x))
+  arr_x[c(1:2), 1 , c(1:3)] <- 0
+  
+  expect_equal(as.array(x), arr_x)
+})
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-mxnet-test/blob/bfb79bd2/R-package/tests/testthat/test_symbol.R
----------------------------------------------------------------------
diff --git a/R-package/tests/testthat/test_symbol.R b/R-package/tests/testthat/test_symbol.R
index be38762..656d146 100644
--- a/R-package/tests/testthat/test_symbol.R
+++ b/R-package/tests/testthat/test_symbol.R
@@ -4,17 +4,17 @@ context("symbol")
 
 test_that("basic symbol operation", {
   data = mx.symbol.Variable('data')
-  net1 = mx.symbol.FullyConnected(data=data, name='fc1', num_hidden=10)
-  net1 = mx.symbol.FullyConnected(data=net1, name='fc2', num_hidden=100)
+  net1 = mx.symbol.FullyConnected(data = data, name = 'fc1', num_hidden = 10)
+  net1 = mx.symbol.FullyConnected(data = net1, name = 'fc2', num_hidden = 100)
   
   expect_equal(arguments(net1), c('data', 'fc1_weight', 'fc1_bias', 'fc2_weight', 'fc2_bias'))
   expect_equal(outputs(net1), 'fc2_output')
   
-  net2 = mx.symbol.FullyConnected(name='fc3', num_hidden=10)
-  net2 = mx.symbol.Activation(data=net2, act_type='relu')
-  net2 = mx.symbol.FullyConnected(data=net2, name='fc4', num_hidden=20)
+  net2 = mx.symbol.FullyConnected(name = 'fc3', num_hidden = 10)
+  net2 = mx.symbol.Activation(data = net2, act_type = 'relu')
+  net2 = mx.symbol.FullyConnected(data = net2, name = 'fc4', num_hidden = 20)
   
-  composed = mx.apply(net2, fc3_data=net1, name='composed')
+  composed = mx.apply(net2, fc3_data = net1, name = 'composed')
   
   expect_equal(arguments(composed), c('data', 'fc1_weight', 'fc1_bias', 'fc2_weight', 'fc2_bias', 'fc3_weight', 'fc3_bias', 'fc4_weight', 'fc4_bias'))
   expect_equal(outputs(composed), 'composed_output')
@@ -25,17 +25,35 @@ test_that("basic symbol operation", {
 
 test_that("symbol internal", {
   data = mx.symbol.Variable('data')
-  oldfc = mx.symbol.FullyConnected(data=data, name='fc1', num_hidden=10)
-  net1 = mx.symbol.FullyConnected(data=oldfc, name='fc2', num_hidden=100)
+  oldfc = mx.symbol.FullyConnected(data = data, name = 'fc1', num_hidden = 10)
+  net1 = mx.symbol.FullyConnected(data = oldfc, name = 'fc2', num_hidden = 100)
   
   expect_equal(arguments(net1), c("data", "fc1_weight", "fc1_bias", "fc2_weight", "fc2_bias"))
   
-  internal = net1$get.internals()
+  internal = internals(net1)
   fc1 = internal[[match("fc1_output", internal$outputs)]]
   
   expect_equal(arguments(fc1), arguments(oldfc))
 })
 
+test_that("symbol children", {
+  data = mx.symbol.Variable('data')
+  oldfc = mx.symbol.FullyConnected(data = data,
+                                   name = 'fc1',
+                                   num_hidden = 10)
+  net1 = mx.symbol.FullyConnected(data = oldfc, name = 'fc2', num_hidden = 100)
+  
+  expect_equal(outputs(children(net1)), c('fc1_output', 'fc2_weight', 'fc2_bias'))
+  expect_equal(outputs(children(children(net1))), c('data', 'fc1_weight', 'fc1_bias'))
+  
+  net2 = net1$get.children()
+  expect_equal(net2[[match('fc2_weight', net2$outputs)]]$arguments, 'fc2_weight')
+  
+  data = mx.symbol.Variable('data')
+  sliced = mx.symbol.SliceChannel(data, num_outputs = 3, name = 'slice')
+  expect_equal(outputs(children(sliced)), 'data')
+})
+
 test_that("symbol infer type", {
   num_hidden = 128
   num_dim    = 64
@@ -43,10 +61,10 @@ test_that("symbol infer type", {
   
   data = mx.symbol.Variable('data')
   prev = mx.symbol.Variable('prevstate')
-  x2h  = mx.symbol.FullyConnected(data=data, name='x2h', num_hidden=num_hidden)
-  h2h  = mx.symbol.FullyConnected(data=prev, name='h2h', num_hidden=num_hidden)
+  x2h  = mx.symbol.FullyConnected(data = data, name = 'x2h', num_hidden = num_hidden)
+  h2h  = mx.symbol.FullyConnected(data = prev, name = 'h2h', num_hidden = num_hidden)
   
-  out  = mx.symbol.Activation(data=mx.symbol.elemwise_add(x2h, h2h), name='out', act_type='relu')
+  out  = mx.symbol.Activation(data = mx.symbol.elemwise_add(x2h, h2h), name = 'out', act_type = 'relu')
   
   # shape inference will fail because information is not available for h2h
   ret = mx.symbol.infer.shape(out, data = c(num_dim, num_sample))
@@ -56,7 +74,7 @@ test_that("symbol infer type", {
 
 test_that("symbol save/load", {
   data <- mx.symbol.Variable("data")
-  fc1 <- mx.symbol.FullyConnected(data, num_hidden=1)
+  fc1 <- mx.symbol.FullyConnected(data, num_hidden = 1)
   lro <- mx.symbol.LinearRegressionOutput(fc1)
   mx.symbol.save(lro, "tmp_r_sym.json")
   data2 = mx.symbol.load("tmp_r_sym.json")
@@ -78,3 +96,16 @@ test_that("symbol attributes access", {
   expect_equal(y$attributes$`__shape__`, str)
 })
 
+test_that("symbol concat", {
+  s1 <- mx.symbol.Variable("data1")
+  s2 <- mx.symbol.Variable("data2")
+  s3 <- mx.symbol.concat(data = c(s1, s2), num.args = 2, name = "concat")
+  expect_equal(outputs(s3), "concat_output")
+  expect_equal(outputs(children(s3)), c("data1", "data2"))
+  expect_equal(arguments(s3), c("data1", "data2"))
+  
+  s4 <- mx.symbol.Concat(data = c(s1, s2), num.args = 2, name = "concat")
+  expect_equal(outputs(s3), outputs(s4))
+  expect_equal(outputs(children(s3)), outputs(children(s4)))
+  expect_equal(arguments(s3), arguments(s4))
+})