I rewrote an example available here (link to data in document) https://github.com/dmlc/mxnet/blob/master/example/recommenders/demo1-MF.ipynb
library(mxnet)
DF <- read.delim("./data/ml-100k/u.data", header=F)
names(DF) <- c("user", "item", "score", "time")
max_user<- max(DF$user)
max_item <- max(DF$item)
DF_mat_x <- data.matrix(t(sapply(DF[,1:2], as.numeric)))
DF_y <- DF[,3]
mx.io.arrayiter(DF_mat_x, t(data.matrix(data.frame(score=DF_y))))
k <- 64
## model
user <- mx.symbol.Variable("user")
item <- mx.symbol.Variable("item")
score <- mx.symbol.Variable("label")
## user feature lookup
user1 <- mx.symbol.Embedding(data=user, input_dim = max_user, output_dim = k, name="user1")
## item feature lookup
item1 <- mx.symbol.Embedding(data=item, input_dim = max_item, output_dim = k, name="item1")
## predict by the inner product, which is elementwise product and then sum
pred <- user1 * item1
pred1 <- mx.symbol.sum_axis(pred, axis = 1, name="pred1")
pred2 <- mx.symbol.Flatten(pred1, name="pred2")
## loss layer
pred3 <- mx.symbol.LinearRegressionOutput(data=pred2, label=score, name="pred3")
devices <- mx.cpu()
mx.set.seed(123)
mx.model.FeedForward.create(pred3, X = mx.io.arrayiter(data=DF_mat_x, label=t(data.matrix(data.frame(score=DF_y)))),
ctx=devices, num.round=10, array.batch.size=10,
verbose=T, #array.layout="rowmajor",
initializer=mx.init.uniform(0.07), learning.rate=0.07,
eval.metric=mx.metric.rmse, momentum = 0.9,
epoch.end.callback=mx.callback.log.train.metric(1))
Get error
[19:28:45] /root/mxnet/dmlc-core/include/dmlc/logging.h:235: [19:28:45] src/symbol/symbol.cc:155: Symbol.InferShapeKeyword argument name data not found.
Candidate arguments:
[0]user
[1]user1_weight
[2]item
[3]item1_weight
[4]label
Error in symbol$infer.shape(list(...)) : basic_string::resize
> traceback()
6: stop(list(message = "basic_string::resize", call = symbol$infer.shape(list(...)),
cppstack = NULL))
5: .External(list(name = "CppMethod__invoke_notvoid", address = <pointer: 0x11caef0>,
dll = list(name = "Rcpp", path = "/usr/local/lib/R/site-library/Rcpp/libs/Rcpp.so",
dynamicLookup = TRUE, handle = <pointer: 0x1404520>,
info = <pointer: 0x7f348a598d80>), numParameters = -1L),
<pointer: 0x3835820>, <pointer: 0x3836540>, .pointer, ...)
4: symbol$infer.shape(list(...))
3: mx.symbol.infer.shape(symbol, data = input.shape)
2: mx.model.init.params(symbol, input.shape, initializer, mx.cpu())
1: mx.model.FeedForward.create(pred3, X = mx.io.arrayiter(data = DF_mat_x,
label = t(data.matrix(data.frame(score = DF_y)))), ctx = devices,
num.round = 10, array.batch.size = 10, verbose = T, initializer = mx.init.uniform(0.07),
learning.rate = 0.07, eval.metric = mx.metric.rmse, momentum = 0.9,
epoch.end.callback = mx.callback.log.train.metric(1))
Manually I get data one labels
> X <- mx.io.arrayiter(data=DF_mat_x, label=t(data.matrix(data.frame(score=DF_y))))
> Z <- mxnet:::mx.model.init.iter(X, NULL, batch.size = 120, is.train = TRUE)
> Z$iter.next()
[1] TRUE
> Z$value()
$data
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14]
[1,] 196 186 22 244 166 298 115 253 305 6 62 286 200 210
[2,] 242 302 377 51 346 474 265 465 451 86 257 1014 222 40
[,15] [,16] [,17] [,18] [,19] [,20] [,21] [,22] [,23] [,24] [,25] [,26]
[1,] 224 303 122 194 291 234 119 167 299 291 308 95
[2,] 29 785 387 274 1042 1184 392 486 144 118 1 546
[,27] [,28] [,29] [,30] [,31] [,32] [,33] [,34] [,35] [,36] [,37] [,38]
[1,] 38 102 63 160 50 301 225 290 97 157 181 278
[2,] 95 768 277 234 246 98 193 88 194 274 1081 603
[,39] [,40] [,41] [,42] [,43] [,44] [,45] [,46] [,47] [,48] [,49] [,50]
[1,] 276 7 10 284 201 276 287 246 242 249 99 178
[2,] 796 32 16 304 979 564 327 201 1137 241 4 332
[,51] [,52] [,53] [,54] [,55] [,56] [,57] [,58] [,59] [,60] [,61] [,62]
[1,] 251 81 260 25 59 72 87 290 42 292 115 20
[2,] 100 432 322 181 196 679 384 143 423 515 20 288
[,63] [,64] [,65] [,66] [,67] [,68] [,69] [,70] [,71] [,72] [,73] [,74]
[1,] 201 13 246 138 167 60 57 223 189 243 92 246
[2,] 219 526 919 26 232 427 304 274 512 15 1049 416
[,75] [,76] [,77] [,78] [,79] [,80] [,81] [,82] [,83] [,84] [,85] [,86]
[1,] 194 241 178 254 293 127 225 299 225 276 291 222
[2,] 165 690 248 1444 5 229 237 229 480 54 144 366
[,87] [,88] [,89] [,90] [,91] [,92] [,93] [,94] [,95] [,96] [,97] [,98]
[1,] 267 42 11 95 8 162 87 279 145 119 62 62
[2,] 518 403 111 625 338 25 1016 154 275 1153 498 382
[,99] [,100] [,101] [,102] [,103] [,104] [,105] [,106] [,107] [,108]
[1,] 28 135 32 90 286 293 216 166 250 271
[2,] 209 23 294 382 208 685 144 328 496 132
[,109] [,110] [,111] [,112] [,113] [,114] [,115] [,116] [,117] [,118]
[1,] 160 265 198 42 168 110 58 90 271 62
[2,] 174 118 498 96 151 307 144 648 346 21
[,119] [,120] [,121] [,122] [,123] [,124] [,125] [,126] [,127] [,128]
[1,] 279 237 94 128 298 44 264 194 72 222
[2,] 832 514 789 485 317 195 200 385 195 750
$label
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14]
[1,] 3 3 1 2 1 4 2 5 3 3 2 5 5 3
[,15] [,16] [,17] [,18] [,19] [,20] [,21] [,22] [,23] [,24] [,25] [,26]
[1,] 3 3 5 2 4 2 4 4 4 2 4 2
[,27] [,28] [,29] [,30] [,31] [,32] [,33] [,34] [,35] [,36] [,37] [,38]
[1,] 5 2 4 5 3 4 4 4 3 4 1 5
[,39] [,40] [,41] [,42] [,43] [,44] [,45] [,46] [,47] [,48] [,49] [,50]
[1,] 1 4 4 4 2 3 5 5 5 5 5 3
[,51] [,52] [,53] [,54] [,55] [,56] [,57] [,58] [,59] [,60] [,61] [,62]
[1,] 4 2 4 5 5 2 4 5 5 4 3 1
[,63] [,64] [,65] [,66] [,67] [,68] [,69] [,70] [,71] [,72] [,73] [,74]
[1,] 4 3 4 5 1 5 5 4 4 3 1 3
[,75] [,76] [,77] [,78] [,79] [,80] [,81] [,82] [,83] [,84] [,85] [,86]
[1,] 4 2 4 3 3 5 5 3 5 3 5 4
[,87] [,88] [,89] [,90] [,91] [,92] [,93] [,94] [,95] [,96] [,97] [,98]
[1,] 5 3 4 4 4 4 4 5 2 5 4 3
[,99] [,100] [,101] [,102] [,103] [,104] [,105] [,106] [,107] [,108]
[1,] 4 4 3 5 4 3 4 5 4 5
[,109] [,110] [,111] [,112] [,113] [,114] [,115] [,116] [,117] [,118]
[1,] 5 4 3 5 5 4 4 4 4 3
[,119] [,120] [,121] [,122] [,123] [,124] [,125] [,126] [,127] [,128]
[1,] 3 4 4 3 4 5 5 2 5 5
And the model does not see the data
Original example uses
user = mx.nd.array(user)
item = mx.nd.array(item)
score = mx.nd.array(score)
return mx.io.NDArrayIter(data={'user':user,'item':item},label={'score':score},
batch_size=batch_size, shuffle=True)
How do it properly in R?
UPDATE
New network
data <- mx.symbol.Variable("data")
user <- mx.symbol.transpose(mx.symbol.slice_axis(data=data, axis=0, begin=1, end=2, name="user"))
item <- mx.symbol.transpose(mx.symbol.slice_axis(data=data, axis=0, begin=0, end=1, name="item"))
score <- mx.symbol.Variable("label")
## user feature lookup
user1 <- mx.symbol.Embedding(data=user, input_dim = max_user, output_dim = k, name="user1")
## item feature lookup
item1 <- mx.symbol.Embedding(data=item, input_dim = max_item, output_dim = k, name="item1")
## predict by the inner product, which is elementwise product and then sum
pred <- user1 * item1
pred1 <- mx.symbol.sum_axis(pred, axis = 1, name="pred1")
pred2 <- mx.symbol.Flatten(pred1, name="pred2")
## loss layer
pred3 <- mx.symbol.LinearRegressionOutput(data=pred2, label=score, name="pred3")
X.train.iter <- mx.io.arrayiter(data=DF_mat_x, label=t(data.matrix(data.frame(score=DF_y))))
mx.model.FeedForward.create(pred3, X = X.train.iter ,
ctx=devices, num.round=10, array.batch.size=10,
verbose=T, #array.layout="colmajor",
initializer=mx.init.uniform(0.07), learning.rate=0.07,
eval.metric=mx.metric.rmse, momentum = 0.9,
epoch.end.callback=mx.callback.log.train.metric(1))
Error
Start training with 1 devices
[22:43:54] /root/mxnet/dmlc-core/include/dmlc/logging.h:235: [22:43:54] src/ndarray/ndarray.cc:231: Check failed: from.shape() == to->shape() operands shape mismatch
Error in exec$update.arg.arrays(arg.arrays, match.name, skip.null) :
basic_string::resize
traceback()
6: stop(list(message = "basic_string::resize", call = exec$update.arg.arrays(arg.arrays,
match.name, skip.null), cppstack = NULL))
5: .External(list(name = "CppMethod__invoke_void", address = <pointer: 0x18be2c0>,
dll = list(name = "Rcpp", path = "/usr/local/lib/R/site-library/Rcpp/libs/Rcpp.so",
dynamicLookup = TRUE, handle = <pointer: 0x2a27840>,
info = <pointer: 0x7f021bba2d80>), numParameters = -1L),
<pointer: 0x3c71d10>, <pointer: 0x3c61310>, .pointer, ...)
4: exec$update.arg.arrays(arg.arrays, match.name, skip.null)
3: mx.exec.update.arg.arrays(train.execs[[i]], s, match.name = TRUE)
2: mx.model.train(symbol, ctx, input.shape, params$arg.params, params$aux.params,
begin.round, num.round, optimizer = optimizer, train.data = X,
eval.data = eval.data, metric = eval.metric, epoch.end.callback = epoch.end.callback,
batch.end.callback = batch.end.callback, kvstore = kvstore,
verbose = verbose)
1: mx.model.FeedForward.create(pred3, X = X.train.iter, ctx = devices,
num.round = 10, array.batch.size = 10, verbose = T, initializer = mx.init.uniform(0.07),
learning.rate = 0.07, eval.metric = mx.metric.rmse, momentum = 0.9,
epoch.end.callback = mx.callback.log.train.metric(1))
Model is created, but does not work.
The error
shows that the symbol shape inference in the R code is trying to reference a variable called "data" but only the variables listed above (which you used in your net) are available. See this line: https://github.com/dmlc/mxnet/blob/master/R-package/R/model.R#L264
The Python example uses a subclassed iterator so the symbol variables can be named anything without resulting in the error that you got.
I posted a new issue to change that here: https://github.com/dmlc/mxnet/issues/4462