{"action":"created","comment":{"url":"https://api.github.com/repos/dmlc/mxnet/pulls/comments/58311188","id":58311188,"diff_hunk":"@@ -0,0 +1,322 @@\n+require(mxnet)\n+\n+# lstm cell symbol\n+lstm <- function(num.hidden, indata, prev.state, param, seqidx, layeridx, dropout=0) {\n+    if (dropout > 0)\n+        indata <- mx.symbol.Dropout(data=indata, p=dropout)\n+    i2h <- mx.symbol.FullyConnected(data=indata,\n+                                    weight=param$i2h.weight,\n+                                    bias=param$i2h.bias,\n+                                    num.hidden=num.hidden * 4,\n+                                    name=paste0(\"t\", seqidx, \".l\", layeridx, \".i2h\"))\n+    h2h <- mx.symbol.FullyConnected(data=prev.state$h,\n+                                    weight=param$h2h.weight,\n+                                    bias=param$h2h.bias,\n+                                    num.hidden=num.hidden * 4,\n+                                    name=paste0(\"t\", seqidx, \".l\", layeridx, \".h2h\"))\n+    gates <- i2h + h2h\n+    slice.gates <- mx.symbol.SliceChannel(gates, num.outputs=4,\n+                                          name=paste0(\"t\", seqidx, \".l\", layeridx, \".slice\"))\n+\n+    in.gate <- mx.symbol.Activation(slice.gates[[1]], act.type=\"sigmoid\")\n+    in.transform <- mx.symbol.Activation(slice.gates[[2]], act.type=\"tanh\")\n+    forget.gate <- mx.symbol.Activation(slice.gates[[3]], act.type=\"sigmoid\")\n+    out.gate <- mx.symbol.Activation(slice.gates[[4]], act.type=\"sigmoid\")\n+    next.c <- (forget.gate * prev.state$c) + (in.gate * in.transform)\n+    next.h <- out.gate * mx.symbol.Activation(next.c, act.type=\"tanh\")\n+    \n+    return (list(c=next.c, h=next.h))\n+}\n+\n+# unrolled lstm network\n+lstm.unroll <- function(num.lstm.layer, seq.len, input.size,\n+                        num.hidden, num.embed, num.label, dropout=0.) {\n+\n+    embed.weight <- mx.symbol.Variable(\"embed.weight\")\n+    cls.weight <- mx.symbol.Variable(\"cls.weight\")\n+    cls.bias <- mx.symbol.Variable(\"cls.bias\")\n+    param.cells <- list()\n+    last.states <- list()\n+    for (i in 1:num.lstm.layer) {\n+        param.cells[[i]] <- list(i2h.weight = mx.symbol.Variable(paste0(\"l\", i, \".i2h.weight\")),\n+                                 i2h.bias = mx.symbol.Variable(paste0(\"l\", i, \".i2h.bias\")),\n+                                 h2h.weight = mx.symbol.Variable(paste0(\"l\", i, \".h2h.weight\")),\n+                                 h2h.bias = mx.symbol.Variable(paste0(\"l\", i, \".h2h.bias\")))\n+        state <- list(c=mx.symbol.Variable(paste0(\"l\", i, \".init.c\")),\n+                      h=mx.symbol.Variable(paste0(\"l\", i, \".init.h\")))\n+        last.states[[i]] <- state\n+    }\n+\n+    last.hidden <- list()\n+    label <- mx.symbol.Variable(\"label\")\n+    for (seqidx in 1:seq.len) {\n+        # embeding layer\n+        data <- mx.symbol.Variable(paste0(\"t\", seqidx, \".data\"))\n+\n+        hidden <- mx.symbol.Embedding(data=data, weight=embed.weight,\n+                                      input.dim=input.size,\n+                                      output.dim=num.embed,\n+                                      name=paste0(\"t\", seqidx, \".embed\"))\n+        \n+        # stack lstm\n+        for (i in 1:num.lstm.layer) {\n+            if (i==0) {\n+                dp <- 0\n+            }\n+            else {\n+                dp <- dropout\n+            }\n+            next.state <- lstm(num.hidden, indata=hidden,\n+                               prev.state=last.states[[i]],\n+                               param=param.cells[[i]],\n+                               seqidx=seqidx, layeridx=i, \n+                               dropout=dp)\n+            hidden <- next.state$h\n+            last.states[[i]] <- next.state\n+        }\n+        # decoder\n+        if (dropout > 0)  \n+            hidden <- mx.symbol.Dropout(data=hidden, p=dropout)\n+        last.hidden <- c(last.hidden, hidden)\n+    }\n+    last.hidden$dim <- 0\n+    last.hidden$num.args <- seq.len\n+    concat <-mxnet:::mx.varg.symbol.Concat(last.hidden)\n+    fc <- mx.symbol.FullyConnected(data=concat,\n+                                   weight=cls.weight,\n+                                   bias=cls.bias,\n+                                   num.hidden=num.label)\n+    loss.all <- mx.symbol.SoftmaxOutput(data=fc, label=label, name=\"sm\")\n+    unpack.c <- list()\n+    unpack.h <- list()\n+    for (i in 1:num.lstm.layer) {\n+         state <- last.states[[i]]\n+         state <- list(c=mx.symbol.BlockGrad(state$c, name=paste0(\"l\", i, \".last.c\")),\n+                            h=mx.symbol.BlockGrad(state$h, name=paste0(\"l\", i, \".last.h\" )))\n+        last.states[[i]] <- state\n+        unpack.c <- c(unpack.c, state$c)\n+        unpack.h <- c(unpack.h, state$h)\n+    }\n+    list.all <- c(loss.all, unpack.c, unpack.h)\n+\n+    return (mx.symbol.Group(list.all))\n+}\n+\n+is.param.name <- function(name) {\n+    return (grepl('weight$', name) || grepl('bias$', name) || \n+           grepl('gamma$', name) || grepl('beta$', name) )\n+}\n+\n+mx.model.init.params <- function(symbol, input.shape, initializer, ctx) {\n+  if (!is.mx.symbol(symbol)) stop(\"symbol need to be MXSymbol\")\n+  slist <- symbol$infer.shape(input.shape)\n+  if (is.null(slist)) stop(\"Not enough information to get shapes\")\n+  arg.params <- mx.init.create(initializer, slist$arg.shapes, ctx, skip.unknown=TRUE)\n+  aux.params <- mx.init.create(initializer, slist$aux.shapes, ctx, skip.unknown=FALSE)\n+  return(list(arg.params=arg.params, aux.params=aux.params))\n+}\n+\n+# set up rnn model with lstm cells\n+setup.rnn.model <- function(ctx,\n+                            num.lstm.layer, seq.len,\n+                            num.hidden, num.embed, num.label,\n+                            batch.size, input.size,\n+                            initializer=mx.init.uniform(0.01), \n+                            dropout=0) {\n+\n+    rnn.sym <- lstm.unroll(num.lstm.layer=num.lstm.layer,\n+                           num.hidden=num.hidden,\n+                           seq.len=seq.len,\n+                           input.size=input.size,\n+                           num.embed=num.embed,\n+                           num.label=num.label,\n+                           dropout=dropout)\n+    arg.names <- rnn.sym$arguments\n+    input.shapes <- list()\n+    for (name in arg.names) {\n+        if (grepl('init.c$', name) || grepl('init.h$', name)) {\n+            input.shapes[[name]] <- c(num.hidden, batch.size)\n+        }\n+        else if (grepl('data$', name)) {\n+            input.shapes[[name]] <- c(batch.size)\n+        }\n+    }\n+    \n+    params <- mx.model.init.params(rnn.sym, input.shapes, initializer, ctx)\n+\n+    args <- input.shapes\n+    args$symbol <- rnn.sym\n+    args$ctx <- ctx\n+    args$grad.req <- \"add\"\n+    rnn.exec <- do.call(mx.simple.bind, args)\n+\n+    mx.exec.update.arg.arrays(rnn.exec, params$arg.params, match.name=TRUE)\n+    mx.exec.update.aux.arrays(rnn.exec, params$aux.params, match.name=TRUE)\n+\n+    grad.arrays <- list()\n+    for (name in names(rnn.exec$ref.grad.arrays)) {\n+        if (is.param.name(name))\n+            grad.arrays[[name]] <- rnn.exec$ref.arg.arrays[[name]]*0\n+    }\n+    mx.exec.update.grad.arrays(rnn.exec, grad.arrays, match.name=TRUE)\n+\n+    return (list(rnn.exec=rnn.exec, symbol=rnn.sym,\n+                 num.lstm.layer=num.lstm.layer, num.hidden=num.hidden, \n+                 seq.len=seq.len, batch.size=batch.size,\n+                 num.embed=num.embed))\n+\n+}\n+\n+\n+get.rnn.inputs <- function(m, X, begin) {\n+    seq.len <- m$seq.len\n+    batch.size <- m$batch.size\n+    seq.labels <- array(0, dim=c(seq.len*batch.size))\n+    seq.data <- list()\n+    for (seqidx in 1:seq.len) {\n+        idx <- (begin + seqidx - 1) %% dim(X)[2] + 1\n+        next.idx <- (begin + seqidx) %% dim(X)[2] + 1\n+        x <- X[, idx]\n+        y <- X[, next.idx]\n+\n+        seq.data[[paste0(\"t\", seqidx, \".data\")]] <- mx.nd.array(as.array(x))\n+        seq.labels[((seqidx-1)*batch.size+1) : (seqidx*batch.size)] <- y\n+    }\n+    seq.data$label <- mx.nd.array(seq.labels)\n+    return (seq.data)\n+}\n+\n+\n+calc.nll <- function(seq.label.probs, X, begin) {\n+    nll = - sum(log(seq.label.probs)) / length(X[,1])\n+    return (nll)\n+}\n+\n+train.lstm <- function(model, X.train.batch, X.val.batch,\n+                       num.round, update.period,\n+                       optimizer='sgd', half.life=2, max.grad.norm = 5.0, ...) {\n+    X.train.batch.shape <- dim(X.train.batch)\n+    X.val.batch.shape <- dim(X.val.batch)\n+    cat(paste0(\"Training with train.shape=(\", paste0(X.train.batch.shape, collapse=\",\"), \")\"), \"\\n\")\n+    cat(paste0(\"Training with val.shape=(\", paste0(X.val.batch.shape, collapse=\",\"), \")\"), \"\\n\")\n+\n+    m <- model\n+    seq.len <- m$seq.len\n+    batch.size <- m$batch.size\n+    num.lstm.layer <- m$num.lstm.layer\n+    num.hidden <- m$num.hidden\n+\n+    opt <- mx.opt.create(optimizer, rescale.grad=(1/batch.size), ...)\n+\n+    updater <- mx.opt.get.updater(opt, m$rnn.exec$ref.arg.arrays)\n+    epoch.counter <- 0\n+    log.period <- max(as.integer(1000 / seq.len), 1)\n+    last.perp <- 10000000.0\n+\n+    for (iteration in 1:num.round) {\n+        nbatch <- 0\n+        train.nll <- 0\n+        # reset states\n+        init.states <- list()\n+        for (i in 1:num.lstm.layer) {\n+            init.states[[paste0(\"l\", i, \".init.c\")]] <- mx.nd.zeros(c(num.hidden, batch.size))\n+            init.states[[paste0(\"l\", i, \".init.h\")]] <- mx.nd.zeros(c(num.hidden, batch.size))\n+        }\n+        mx.exec.update.arg.arrays(m$rnn.exec, init.states, match.name=TRUE) \n+\n+        tic <- Sys.time()\n+\n+        stopifnot(dim(X.train.batch)[[2]] %% seq.len == 0)\n+        stopifnot(dim(X.val.batch)[[2]] %% seq.len == 0)\n+\n+        for (begin in seq(1, dim(X.train.batch)[2], seq.len)) {\n+            # set rnn input\n+            rnn.input <- get.rnn.inputs(m, X.train.batch, begin=begin)\n+            mx.exec.update.arg.arrays(m$rnn.exec, rnn.input, match.name=TRUE) \n+\n+            mx.exec.forward(m$rnn.exec, is.train=TRUE)\n+            # probability of each label class, used to evaluate nll\n+            seq.label.probs <- mx.nd.choose.element.0index(m$rnn.exec$outputs[[\"sm_output\"]], m$rnn.exec$arg.arrays[[\"label\"]])\n+            mx.exec.backward(m$rnn.exec)\n+            # transfer the states\n+            init.states <- list()\n+            for (i in 1:num.lstm.layer) {\n+                init.states[[paste0(\"l\", i, \".init.c\")]] <- m$rnn.exec$outputs[[paste0(\"l\", i, \".last.c_output\")]]\n+                init.states[[paste0(\"l\", i, \".init.h\")]] <- m$rnn.exec$outputs[[paste0(\"l\", i, \".last.h_output\")]]\n+            }\n+            mx.exec.update.arg.arrays(m$rnn.exec, init.states, match.name=TRUE) \n+            # update epoch counter\n+            epoch.counter <- epoch.counter + 1\n+            if (epoch.counter %% update.period == 0) {\n+\n+                # the gradient of initial c and inital h should be zero\n+                init.grad <- list()\n+                for (i in 1:num.lstm.layer) {\n+                    init.grad[[paste0(\"l\", i, \".init.c\")]] <- m$rnn.exec$ref.arg.arrays[[paste0(\"l\", i, \".init.c\")]]*0\n+                    init.grad[[paste0(\"l\", i, \".init.h\")]] <- m$rnn.exec$ref.arg.arrays[[paste0(\"l\", i, \".init.h\")]]*0\n+                }\n+                mx.exec.update.grad.arrays(m$rnn.exec, init.grad, match.name=TRUE)\n+\n+                arg.blocks <- updater(m$rnn.exec$ref.arg.arrays, m$rnn.exec$ref.grad.arrays)\n+\n+                mx.exec.update.arg.arrays(m$rnn.exec, arg.blocks, skip.null=TRUE)\n+\n+                grad.arrays <- list()\n+                for (name in names(m$rnn.exec$ref.grad.arrays)) {\n+                    if (is.param.name(name))\n+                        grad.arrays[[name]] <- m$rnn.exec$ref.grad.arrays[[name]]*0\n+                }\n+                mx.exec.update.grad.arrays(m$rnn.exec, grad.arrays, match.name=TRUE)\n+\n+            }\n+\n+            train.nll <- train.nll + calc.nll(as.array(seq.label.probs), X.train.batch, begin=begin)\n+\n+            nbatch <- begin + seq.len\n+            if ((epoch.counter %% log.period) == 0) {\n+                cat(paste0(\"Epoch [\", epoch.counter, \n+                           \"] Train: NLL=\", train.nll / nbatch, \n+                           \", Perp=\", exp(train.nll / nbatch), \"\\n\"))\n+            }\n+        }\n+        # end of training loop\n+        toc <- Sys.time()\n+        cat(paste0(\"Iter [\", iteration, \n+                   \"] Train: Time: \", toc - tic,\n+                   \" sec, NLL=\", train.nll / nbatch,","path":"R-package/demo/rnn/lstm.R","position":286,"original_position":286,"commit_id":"11ab148a951935c091e7d0e42956a59fefd22391","original_commit_id":"11ab148a951935c091e7d0e42956a59fefd22391","user":{"login":"thirdwing","id":1547093,"avatar_url":"https://avatars.githubusercontent.com/u/1547093?v=3","gravatar_id":"","url":"https://api.github.com/users/thirdwing","html_url":"https://github.com/thirdwing","followers_url":"https://api.github.com/users/thirdwing/followers","following_url":"https://api.github.com/users/thirdwing/following{/other_user}","gists_url":"https://api.github.com/users/thirdwing/gists{/gist_id}","starred_url":"https://api.github.com/users/thirdwing/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thirdwing/subscriptions","organizations_url":"https://api.github.com/users/thirdwing/orgs","repos_url":"https://api.github.com/users/thirdwing/repos","events_url":"https://api.github.com/users/thirdwing/events{/privacy}","received_events_url":"https://api.github.com/users/thirdwing/received_events","type":"User","site_admin":false},"body":"In R, `toc - tic` will produce an object with type of `difftime`, but we can't guarantee it will be displayed with unit of seconds, so please change it into `as.numeric(toc - tic, units=\"secs\")`.","created_at":"2016-04-03T14:31:25Z","updated_at":"2016-04-03T14:31:25Z","html_url":"https://github.com/dmlc/mxnet/pull/1673#discussion_r58311188","pull_request_url":"https://api.github.com/repos/dmlc/mxnet/pulls/1673","_links":{"self":{"href":"https://api.github.com/repos/dmlc/mxnet/pulls/comments/58311188"},"html":{"href":"https://github.com/dmlc/mxnet/pull/1673#discussion_r58311188"},"pull_request":{"href":"https://api.github.com/repos/dmlc/mxnet/pulls/1673"}}},"pull_request":{"url":"https://api.github.com/repos/dmlc/mxnet/pulls/1673","id":63486883,"html_url":"https://github.com/dmlc/mxnet/pull/1673","diff_url":"https://github.com/dmlc/mxnet/pull/1673.diff","patch_url":"https://github.com/dmlc/mxnet/pull/1673.patch","issue_url":"https://api.github.com/repos/dmlc/mxnet/issues/1673","number":1673,"state":"open","locked":false,"title":"add LSTM in R","user":{"login":"ziyeqinghan","id":9292874,"avatar_url":"https://avatars.githubusercontent.com/u/9292874?v=3","gravatar_id":"","url":"https://api.github.com/users/ziyeqinghan","html_url":"https://github.com/ziyeqinghan","followers_url":"https://api.github.com/users/ziyeqinghan/followers","following_url":"https://api.github.com/users/ziyeqinghan/following{/other_user}","gists_url":"https://api.github.com/users/ziyeqinghan/gists{/gist_id}","starred_url":"https://api.github.com/users/ziyeqinghan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ziyeqinghan/subscriptions","organizations_url":"https://api.github.com/users/ziyeqinghan/orgs","repos_url":"https://api.github.com/users/ziyeqinghan/repos","events_url":"https://api.github.com/users/ziyeqinghan/events{/privacy}","received_events_url":"https://api.github.com/users/ziyeqinghan/received_events","type":"User","site_admin":false},"body":"I  wrote LSTM in R using low level symbol interface according to the implementation of rnn in python. It mainy contains two files:\r\n-  `lstm.R` Functions for building a LSTM Network\r\n- `char_lstm.R` demo how to train a character LSTM by using lstm.R\r\n\r\nMeanwhile, in order to clear the gradient arrays for the argument `rad.req=\"add\"` of function `mx.simple.bind`, I added a function `mx.exec.update.grad.arrays`.\r\n\r\nThe following is part of the \"char LSTM example\" result:\r\n```\r\nEpoch [31] Train: NLL=3.836905475197, Perp=46.3817227414766\r\nEpoch [62] Train: NLL=3.60287136350845, Perp=36.7034722942903\r\n...\r\nEpoch [961] Train: NLL=3.23440136826571, Perp=25.3911672698533\r\nIter [1] Train: Time: 3.10378745794296 sec, NLL=3.22799701509071, Perp=25.2290728760392\r\nIter [1] Val: NLL=2.88174404985709, Perp=17.8453692688881\r\n...\r\nEpoch [20553] Train: NLL=1.44098787073839, Perp=4.22486737903258\r\nIter [21] Train: Time: 3.150696794192 sec, NLL=1.44111800900158, Perp=4.22541723171315\r\nIter [21] Val: NLL=1.55106124501652, Perp=4.71647286090669\r\n```","created_at":"2016-03-20T04:40:16Z","updated_at":"2016-04-03T14:31:25Z","closed_at":null,"merged_at":null,"merge_commit_sha":"dab1e625a86c8120eb02fd391a5995ba6302d1c5","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/dmlc/mxnet/pulls/1673/commits","review_comments_url":"https://api.github.com/repos/dmlc/mxnet/pulls/1673/comments","review_comment_url":"https://api.github.com/repos/dmlc/mxnet/pulls/comments{/number}","comments_url":"https://api.github.com/repos/dmlc/mxnet/issues/1673/comments","statuses_url":"https://api.github.com/repos/dmlc/mxnet/statuses/11ab148a951935c091e7d0e42956a59fefd22391","head":{"label":"ziyeqinghan:lstm","ref":"lstm","sha":"11ab148a951935c091e7d0e42956a59fefd22391","user":{"login":"ziyeqinghan","id":9292874,"avatar_url":"https://avatars.githubusercontent.com/u/9292874?v=3","gravatar_id":"","url":"https://api.github.com/users/ziyeqinghan","html_url":"https://github.com/ziyeqinghan","followers_url":"https://api.github.com/users/ziyeqinghan/followers","following_url":"https://api.github.com/users/ziyeqinghan/following{/other_user}","gists_url":"https://api.github.com/users/ziyeqinghan/gists{/gist_id}","starred_url":"https://api.github.com/users/ziyeqinghan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ziyeqinghan/subscriptions","organizations_url":"https://api.github.com/users/ziyeqinghan/orgs","repos_url":"https://api.github.com/users/ziyeqinghan/repos","events_url":"https://api.github.com/users/ziyeqinghan/events{/privacy}","received_events_url":"https://api.github.com/users/ziyeqinghan/received_events","type":"User","site_admin":false},"repo":{"id":52645889,"name":"mxnet","full_name":"ziyeqinghan/mxnet","owner":{"login":"ziyeqinghan","id":9292874,"avatar_url":"https://avatars.githubusercontent.com/u/9292874?v=3","gravatar_id":"","url":"https://api.github.com/users/ziyeqinghan","html_url":"https://github.com/ziyeqinghan","followers_url":"https://api.github.com/users/ziyeqinghan/followers","following_url":"https://api.github.com/users/ziyeqinghan/following{/other_user}","gists_url":"https://api.github.com/users/ziyeqinghan/gists{/gist_id}","starred_url":"https://api.github.com/users/ziyeqinghan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ziyeqinghan/subscriptions","organizations_url":"https://api.github.com/users/ziyeqinghan/orgs","repos_url":"https://api.github.com/users/ziyeqinghan/repos","events_url":"https://api.github.com/users/ziyeqinghan/events{/privacy}","received_events_url":"https://api.github.com/users/ziyeqinghan/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ziyeqinghan/mxnet","description":"Lightweight, Portable, Flexible Distributed/Mobile Deep Learning with Dynamic, Mutation-aware Dataflow Dep Scheduler; for Python, R, Julia, Go, Javascript and more","fork":true,"url":"https://api.github.com/repos/ziyeqinghan/mxnet","forks_url":"https://api.github.com/repos/ziyeqinghan/mxnet/forks","keys_url":"https://api.github.com/repos/ziyeqinghan/mxnet/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ziyeqinghan/mxnet/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ziyeqinghan/mxnet/teams","hooks_url":"https://api.github.com/repos/ziyeqinghan/mxnet/hooks","issue_events_url":"https://api.github.com/repos/ziyeqinghan/mxnet/issues/events{/number}","events_url":"https://api.github.com/repos/ziyeqinghan/mxnet/events","assignees_url":"https://api.github.com/repos/ziyeqinghan/mxnet/assignees{/user}","branches_url":"https://api.github.com/repos/ziyeqinghan/mxnet/branches{/branch}","tags_url":"https://api.github.com/repos/ziyeqinghan/mxnet/tags","blobs_url":"https://api.github.com/repos/ziyeqinghan/mxnet/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ziyeqinghan/mxnet/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ziyeqinghan/mxnet/git/refs{/sha}","trees_url":"https://api.github.com/repos/ziyeqinghan/mxnet/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ziyeqinghan/mxnet/statuses/{sha}","languages_url":"https://api.github.com/repos/ziyeqinghan/mxnet/languages","stargazers_url":"https://api.github.com/repos/ziyeqinghan/mxnet/stargazers","contributors_url":"https://api.github.com/repos/ziyeqinghan/mxnet/contributors","subscribers_url":"https://api.github.com/repos/ziyeqinghan/mxnet/subscribers","subscription_url":"https://api.github.com/repos/ziyeqinghan/mxnet/subscription","commits_url":"https://api.github.com/repos/ziyeqinghan/mxnet/commits{/sha}","git_commits_url":"https://api.github.com/repos/ziyeqinghan/mxnet/git/commits{/sha}","comments_url":"https://api.github.com/repos/ziyeqinghan/mxnet/comments{/number}","issue_comment_url":"https://api.github.com/repos/ziyeqinghan/mxnet/issues/comments{/number}","contents_url":"https://api.github.com/repos/ziyeqinghan/mxnet/contents/{+path}","compare_url":"https://api.github.com/repos/ziyeqinghan/mxnet/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ziyeqinghan/mxnet/merges","archive_url":"https://api.github.com/repos/ziyeqinghan/mxnet/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ziyeqinghan/mxnet/downloads","issues_url":"https://api.github.com/repos/ziyeqinghan/mxnet/issues{/number}","pulls_url":"https://api.github.com/repos/ziyeqinghan/mxnet/pulls{/number}","milestones_url":"https://api.github.com/repos/ziyeqinghan/mxnet/milestones{/number}","notifications_url":"https://api.github.com/repos/ziyeqinghan/mxnet/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ziyeqinghan/mxnet/labels{/name}","releases_url":"https://api.github.com/repos/ziyeqinghan/mxnet/releases{/id}","deployments_url":"https://api.github.com/repos/ziyeqinghan/mxnet/deployments","created_at":"2016-02-27T02:29:18Z","updated_at":"2016-02-27T02:29:20Z","pushed_at":"2016-04-03T13:04:40Z","git_url":"git://github.com/ziyeqinghan/mxnet.git","ssh_url":"git@github.com:ziyeqinghan/mxnet.git","clone_url":"https://github.com/ziyeqinghan/mxnet.git","svn_url":"https://github.com/ziyeqinghan/mxnet","homepage":"http://mxnet.rtfd.org","size":6557,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"dmlc:master","ref":"master","sha":"c1e49e6241f78bb0fd19446c5bf89bf4ac178b16","user":{"login":"dmlc","id":11508361,"avatar_url":"https://avatars.githubusercontent.com/u/11508361?v=3","gravatar_id":"","url":"https://api.github.com/users/dmlc","html_url":"https://github.com/dmlc","followers_url":"https://api.github.com/users/dmlc/followers","following_url":"https://api.github.com/users/dmlc/following{/other_user}","gists_url":"https://api.github.com/users/dmlc/gists{/gist_id}","starred_url":"https://api.github.com/users/dmlc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dmlc/subscriptions","organizations_url":"https://api.github.com/users/dmlc/orgs","repos_url":"https://api.github.com/users/dmlc/repos","events_url":"https://api.github.com/users/dmlc/events{/privacy}","received_events_url":"https://api.github.com/users/dmlc/received_events","type":"Organization","site_admin":false},"repo":{"id":34864402,"name":"mxnet","full_name":"dmlc/mxnet","owner":{"login":"dmlc","id":11508361,"avatar_url":"https://avatars.githubusercontent.com/u/11508361?v=3","gravatar_id":"","url":"https://api.github.com/users/dmlc","html_url":"https://github.com/dmlc","followers_url":"https://api.github.com/users/dmlc/followers","following_url":"https://api.github.com/users/dmlc/following{/other_user}","gists_url":"https://api.github.com/users/dmlc/gists{/gist_id}","starred_url":"https://api.github.com/users/dmlc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dmlc/subscriptions","organizations_url":"https://api.github.com/users/dmlc/orgs","repos_url":"https://api.github.com/users/dmlc/repos","events_url":"https://api.github.com/users/dmlc/events{/privacy}","received_events_url":"https://api.github.com/users/dmlc/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/dmlc/mxnet","description":"Lightweight, Portable, Flexible Distributed/Mobile Deep Learning with Dynamic, Mutation-aware Dataflow Dep Scheduler; for Python, R, Julia, Go, Javascript and more","fork":false,"url":"https://api.github.com/repos/dmlc/mxnet","forks_url":"https://api.github.com/repos/dmlc/mxnet/forks","keys_url":"https://api.github.com/repos/dmlc/mxnet/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dmlc/mxnet/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dmlc/mxnet/teams","hooks_url":"https://api.github.com/repos/dmlc/mxnet/hooks","issue_events_url":"https://api.github.com/repos/dmlc/mxnet/issues/events{/number}","events_url":"https://api.github.com/repos/dmlc/mxnet/events","assignees_url":"https://api.github.com/repos/dmlc/mxnet/assignees{/user}","branches_url":"https://api.github.com/repos/dmlc/mxnet/branches{/branch}","tags_url":"https://api.github.com/repos/dmlc/mxnet/tags","blobs_url":"https://api.github.com/repos/dmlc/mxnet/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dmlc/mxnet/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dmlc/mxnet/git/refs{/sha}","trees_url":"https://api.github.com/repos/dmlc/mxnet/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dmlc/mxnet/statuses/{sha}","languages_url":"https://api.github.com/repos/dmlc/mxnet/languages","stargazers_url":"https://api.github.com/repos/dmlc/mxnet/stargazers","contributors_url":"https://api.github.com/repos/dmlc/mxnet/contributors","subscribers_url":"https://api.github.com/repos/dmlc/mxnet/subscribers","subscription_url":"https://api.github.com/repos/dmlc/mxnet/subscription","commits_url":"https://api.github.com/repos/dmlc/mxnet/commits{/sha}","git_commits_url":"https://api.github.com/repos/dmlc/mxnet/git/commits{/sha}","comments_url":"https://api.github.com/repos/dmlc/mxnet/comments{/number}","issue_comment_url":"https://api.github.com/repos/dmlc/mxnet/issues/comments{/number}","contents_url":"https://api.github.com/repos/dmlc/mxnet/contents/{+path}","compare_url":"https://api.github.com/repos/dmlc/mxnet/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dmlc/mxnet/merges","archive_url":"https://api.github.com/repos/dmlc/mxnet/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dmlc/mxnet/downloads","issues_url":"https://api.github.com/repos/dmlc/mxnet/issues{/number}","pulls_url":"https://api.github.com/repos/dmlc/mxnet/pulls{/number}","milestones_url":"https://api.github.com/repos/dmlc/mxnet/milestones{/number}","notifications_url":"https://api.github.com/repos/dmlc/mxnet/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dmlc/mxnet/labels{/name}","releases_url":"https://api.github.com/repos/dmlc/mxnet/releases{/id}","deployments_url":"https://api.github.com/repos/dmlc/mxnet/deployments","created_at":"2015-04-30T16:21:15Z","updated_at":"2016-04-03T14:14:44Z","pushed_at":"2016-04-03T13:04:41Z","git_url":"git://github.com/dmlc/mxnet.git","ssh_url":"git@github.com:dmlc/mxnet.git","clone_url":"https://github.com/dmlc/mxnet.git","svn_url":"https://github.com/dmlc/mxnet","homepage":"http://mxnet.rtfd.org","size":9098,"stargazers_count":3132,"watchers_count":3132,"language":"Jupyter Notebook","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1075,"mirror_url":null,"open_issues_count":272,"forks":1075,"open_issues":272,"watchers":3132,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/dmlc/mxnet/pulls/1673"},"html":{"href":"https://github.com/dmlc/mxnet/pull/1673"},"issue":{"href":"https://api.github.com/repos/dmlc/mxnet/issues/1673"},"comments":{"href":"https://api.github.com/repos/dmlc/mxnet/issues/1673/comments"},"review_comments":{"href":"https://api.github.com/repos/dmlc/mxnet/pulls/1673/comments"},"review_comment":{"href":"https://api.github.com/repos/dmlc/mxnet/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/dmlc/mxnet/pulls/1673/commits"},"statuses":{"href":"https://api.github.com/repos/dmlc/mxnet/statuses/11ab148a951935c091e7d0e42956a59fefd22391"}}}}