Given data as a symbol, I want to add noise.
This is given: data <- mx.symbol.Variable("data")
How can I do this? noise <- mx.symbol.random_normal(shape=???)
To do this: data_noisy <- data + noise
I've found (but didn't helped)
I've tried:
data <- mx.symbol.random_normal(shape=mx.symbol.infer.shape(data))Error in symbol$infer.shape(list(...)) : symbol.cc:165: RCheck failed: HasName(kwargs) Need to pass parameters in key=value style.
data <- mx.symbol.random_normal(shape=dim(data))Error in mx.varg.symbol.random_normal(list(...)) : ./base.h:271: RCheck failed: TYPEOF(val) == INTSXP || TYPEOF(val) == REALSXP Only accept integer vectors or simple types
3.data <- mx.symbol.random_normal(shape=data$infer.shape)
Error in mx.varg.symbol.random_normal(list(...)) : Cannot convert object to an environment: [type=closure; target=ENVSXP].
data <- mx.symbol.random_normal(shape=data$infer.shape())Error in data$infer.shape() : could not find valid method
data <- mx.symbol.random_normal(shape=mx.symbol.infer.shape(symbol=data, data = mx.symbol.zeros_like(data)))Error in symbol$infer.shape(list(...)) : Not compatible with requested type: [type=S4; target=integer].
There's typically no need to specify shape of data input when building the symbolic network. This will typically will be set at training time when the model is bind and the shapes infered from what the iterator provides as input data. This allows the same network to be trained with different batch sizes.
For the random noise, the shapes can be infered so there's no need to specify it. For example:
data <- mx.symbol.Variable("data")
noise <- mx.symbol.random_normal(loc=0, scale=1, name = "noise")
data_noise <- data + noise
graph.viz(data_noise, shape=c(2:3))
To infer the shape for a given data input shape, you need to pass the required input shapes as a list: data_noise$infer.shape(list(data=2:3)). This provides the shapes of each arguments in the network. To get the output shapes of each operator, you can use: data_noise$get.internals()$infer.shape(list(data=2:3))$out.shapes
Only the data shape is required to get the shapes of the overall network. Other shapes for data can be specified: the same model could be reused if the batch size or number of input features were different.
Graph can confirm: graph.viz(data_noise, shape=c(2:3))

You can finally validate that the noise layer operates as expected and generates new random noise at each batch iteration:
exec <- mxnet:::mx.symbol.bind(symbol = total, ctx = mx.cpu(),
arg.arrays = list(data=data.array), aux.arrays = NULL,
grad.reqs = c("null"))
mx.exec.forward(exec, is.train = T)
exec$outputs
[,1] [,2] [,3]
[1,] -0.9185634 -0.7457144 -1.2080863
[2,] 2.0088325 0.2863084 0.5604595
mx.exec.forward(exec, is.train = T)
exec$outputs
[,1] [,2] [,3]
[1,] 1.8140212 -1.5227430 -2.515245
[2,] 0.9697598 -0.5285375 -1.889090
Made my day. Thanks for the clear and comprehensive answer.
And, in addition, an example how to use mx.symbol.bind().
Most helpful comment
There's typically no need to specify shape of data input when building the symbolic network. This will typically will be set at training time when the model is bind and the shapes infered from what the iterator provides as input data. This allows the same network to be trained with different batch sizes.
For the random noise, the shapes can be infered so there's no need to specify it. For example:
To infer the shape for a given data input shape, you need to pass the required input shapes as a list:
data_noise$infer.shape(list(data=2:3)). This provides the shapes of each arguments in the network. To get the output shapes of each operator, you can use:data_noise$get.internals()$infer.shape(list(data=2:3))$out.shapesOnly the data shape is required to get the shapes of the overall network. Other shapes for data can be specified: the same model could be reused if the batch size or number of input features were different.
Graph can confirm:

graph.viz(data_noise, shape=c(2:3))You can finally validate that the noise layer operates as expected and generates new random noise at each batch iteration:
[1,] -0.9185634 -0.7457144 -1.2080863
[2,] 2.0088325 0.2863084 0.5604595
[1,] 1.8140212 -1.5227430 -2.515245
[2,] 0.9697598 -0.5285375 -1.889090