{"action":"created","issue":{"url":"https://api.github.com/repos/dmlc/mxnet/issues/1843","repository_url":"https://api.github.com/repos/dmlc/mxnet","labels_url":"https://api.github.com/repos/dmlc/mxnet/issues/1843/labels{/name}","comments_url":"https://api.github.com/repos/dmlc/mxnet/issues/1843/comments","events_url":"https://api.github.com/repos/dmlc/mxnet/issues/1843/events","html_url":"https://github.com/dmlc/mxnet/pull/1843","id":148122283,"number":1843,"title":"Sequential Container Module","user":{"login":"pluskid","id":3542,"avatar_url":"https://avatars.githubusercontent.com/u/3542?v=3","gravatar_id":"","url":"https://api.github.com/users/pluskid","html_url":"https://github.com/pluskid","followers_url":"https://api.github.com/users/pluskid/followers","following_url":"https://api.github.com/users/pluskid/following{/other_user}","gists_url":"https://api.github.com/users/pluskid/gists{/gist_id}","starred_url":"https://api.github.com/users/pluskid/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pluskid/subscriptions","organizations_url":"https://api.github.com/users/pluskid/orgs","repos_url":"https://api.github.com/users/pluskid/repos","events_url":"https://api.github.com/users/pluskid/events{/privacy}","received_events_url":"https://api.github.com/users/pluskid/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":13,"created_at":"2016-04-13T17:00:08Z","updated_at":"2016-04-14T22:25:58Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/dmlc/mxnet/pulls/1843","html_url":"https://github.com/dmlc/mxnet/pull/1843","diff_url":"https://github.com/dmlc/mxnet/pull/1843.diff","patch_url":"https://github.com/dmlc/mxnet/pull/1843.patch"},"body":"Chain multiple modules.\r\n\r\nIs there any easy way to tell whether a `Symbol` contains a loss function? Currently I am asking the user to explicitly specify `take_labels=True`.\r\n\r\nBTW: @tqchen While running the example `sequential_module.py`, I run into the following segfaults. However, when I re-run it, I cannot reproduce it again. Do you have anything in mind what/where might be some potential bug here? Thanks!\r\n\r\n```\r\n[12:52:15] src/io/iter_mnist.cc:91: MNISTIter: load 60000 images, shuffle=1, shape=(100,784)\r\n[12:52:16] src/io/iter_mnist.cc:91: MNISTIter: load 10000 images, shuffle=1, shape=(100,784)\r\nINFO:root:Epoch[0] Train-accuracy=0.130850\r\nINFO:root:Epoch[0] Time cost=1.362\r\nINFO:root:Epoch[0] Validation-accuracy=0.225300\r\nProcess 6707 stopped\r\n* thread #2: tid = 0x2b387, 0x00000001035a14de libmxnet.so`mshadow::Stream<mshadow::gpu>::Wait() + 30, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)\r\n    frame #0: 0x00000001035a14de libmxnet.so`mshadow::Stream<mshadow::gpu>::Wait() + 30\r\nlibmxnet.so`mshadow::Stream<mshadow::gpu>::Wait:\r\n->  0x1035a14de <+30>: movq   (%rdi), %rdi\r\n    0x1035a14e1 <+33>: callq  0x1038ae9e6               ; symbol stub for: cudaStreamSynchronize\r\n    0x1035a14e6 <+38>: movl   %eax, %r15d\r\n    0x1035a14e9 <+41>: testl  %r15d, %r15d\r\n(lldb) bt\r\n* thread #2: tid = 0x2b387, 0x00000001035a14de libmxnet.so`mshadow::Stream<mshadow::gpu>::Wait() + 30, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)\r\n  * frame #0: 0x00000001035a14de libmxnet.so`mshadow::Stream<mshadow::gpu>::Wait() + 30\r\n    frame #1: 0x0000000103745d40 libmxnet.so`mxnet::GraphExecutor::GetOpExecEntry(unsigned int)::'lambda'(mxnet::RunContext, mxnet::engine::CallbackOnComplete)::operator()(mxnet::RunContext, mxnet::engine::CallbackOnComplete) const + 928\r\n    frame #2: 0x000000010374577d libmxnet.so`std::__1::__function::__func<mxnet::GraphExecutor::GetOpExecEntry(unsigned int)::'lambda'(mxnet::RunContext, mxnet::engine::CallbackOnComplete), std::__1::allocator<mxnet::GraphExecutor::GetOpExecEntry(unsigned int)::'lambda'(mxnet::RunContext, mxnet::engine::CallbackOnComplete)>, void (mxnet::RunContext, mxnet::engine::CallbackOnComplete)>::operator()(mxnet::RunContext&&, mxnet::engine::CallbackOnComplete&&) + 45\r\n    frame #3: 0x00000001035abce7 libmxnet.so`mxnet::engine::ThreadedEngine::ExecuteOprBlock(mxnet::RunContext, mxnet::engine::OprBlock*) + 279\r\n    frame #4: 0x00000001035ae71e libmxnet.so`std::__1::__function::__func<mxnet::engine::ThreadedEnginePerDevice::PushToExecute(mxnet::engine::OprBlock*, bool)::'lambda'()::operator()() const::'lambda'(), std::__1::allocator<mxnet::engine::ThreadedEnginePerDevice::PushToExecute(mxnet::engine::OprBlock*, bool)::'lambda'()::operator()() const::'lambda'()>, void ()>::operator()() + 62\r\n    frame #5: 0x00000001035ac1b8 libmxnet.so`void* std::__1::__thread_proxy<std::__1::tuple<std::__1::function<void ()> > >(void*) + 104\r\n    frame #6: 0x00007fff96e5699d libsystem_pthread.dylib`_pthread_body + 131\r\n    frame #7: 0x00007fff96e5691a libsystem_pthread.dylib`_pthread_start + 168\r\n    frame #8: 0x00007fff96e54351 libsystem_pthread.dylib`thread_start + 13\r\n```"},"comment":{"url":"https://api.github.com/repos/dmlc/mxnet/issues/comments/210183666","html_url":"https://github.com/dmlc/mxnet/pull/1843#issuecomment-210183666","issue_url":"https://api.github.com/repos/dmlc/mxnet/issues/1843","id":210183666,"user":{"login":"pluskid","id":3542,"avatar_url":"https://avatars.githubusercontent.com/u/3542?v=3","gravatar_id":"","url":"https://api.github.com/users/pluskid","html_url":"https://github.com/pluskid","followers_url":"https://api.github.com/users/pluskid/followers","following_url":"https://api.github.com/users/pluskid/following{/other_user}","gists_url":"https://api.github.com/users/pluskid/gists{/gist_id}","starred_url":"https://api.github.com/users/pluskid/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pluskid/subscriptions","organizations_url":"https://api.github.com/users/pluskid/orgs","repos_url":"https://api.github.com/users/pluskid/repos","events_url":"https://api.github.com/users/pluskid/events{/privacy}","received_events_url":"https://api.github.com/users/pluskid/received_events","type":"User","site_admin":false},"created_at":"2016-04-14T22:25:58Z","updated_at":"2016-04-14T22:25:58Z","body":"@piiswrong Thanks for the suggestion about non-linear chaining. I was thinking about it. I tried to add a `rewiring` dict parameter for each module to be added that allow complicated re-mapping of input-output between two chained modules. But it soon become very complicated. I decided to keep it simple like this mainly because I want to avoid implementing a whole imperative computation graph system.\r\n\r\nI think we are not advocating everything to be written in imperative way as what Torch does. Instead, main thing should still be in symbolic computation graph, which already had very non-linear \"chaining\". The imperative API is mainly used when one need complicated training logics, and then one can call those `forward`, `update` manually. With this philosophy, the primary goal of `SequentialModule` is actually as an example of how those intermediate level API could be used to operate multiple modules.\r\n\r\nIt just happens to be a `BaseModule` subclass (therefore high-level APIs like `fit` can be borrowed directly). It could do some interesting things like data-parallelism + model parallelism at the same time (as @mli mentioned the other day) -- I will add a simple example. But in general I think we might want to avoid it being abused."}}