Dobiasd / frugally-deep

A lightweight header-only library for using Keras (TensorFlow) models in C++.
MIT License
1.06k stars 236 forks source link

Test fails during load #135

Closed nicochidt closed 5 years ago

nicochidt commented 5 years ago

Hi Tobias, thanks for this great library!

I'm having problems with a model and I'm not sure how to debug it.

I'm using the functional API with the following layer types: Dense, Conv1D, Concatenate, Embedding and Flatten. The conversion of the model runs without any problem, but when I'm loading in it I get the following error:

Running test 1 of 1 ... libc++abi.dylib: terminating with uncaught exception of type std::runtime_error: size_dim_5, size_dim_4, height and width dimension must be 1, but shape is '[(1, 1, 1, 200, 20)]'

I can set false to the test, but then I get the exception when running a prediction.

I've run it with lldb and the problem seems to be a mismatch in the output layer dimension (which is supposed to have 2 neurons). The described shape [(1,1,1,200,20)] matches one of the inputs' shape (I'm using 5 input tensors).

I'm not really sure how to debug this. Any idea?

The Keras model and the fdeep conversion can be found in this file.

I'm using the last commit of this repo. Keras and Tensorflor versions:

Using TensorFlow backend.
2.2.4

$ python3 -c 'import tensorflow as tf; print(tf.__version__)'
1.12.0

Thanks in advance!

Dobiasd commented 5 years ago

Hi Nicolás,

first, thanks for this excellent error report.

I was able to reproduce the error quickly:

Loading json ... done. elapsed time: 0.023336 s
Running test 1 of 1 ... terminate called after throwing an instance of 'std::runtime_error'
  what():  size_dim_5, size_dim_4, height and width dimension must be 1, but shape is '[(1, 1, 1, 200, 20)]'

I'll try to find out what is going wrong.

If possible, could you provide a minimal Python example, creating your model architecture?

nicochidt commented 5 years ago

Hi Tobias,

Thanks for your prompt reply. This piece of code is the one that is generating the model. It's not a complete example since there is a lot of preprocessing going on before training the model.

Hopefully, random weights would do it.

Dobiasd commented 5 years ago

Thanks a lot. Yes, I was able to reproduce the issue from scratch with your code. Will dive into it and let you know.

Dobiasd commented 5 years ago

Just reduced the model further and further. In the end it also happened with such a minimal model:

inp = Input(shape=(3, 4), dtype=np.uint8)
x = inp
x = Embedding(5, 6)(x)
model = Model(inputs=[inp], outputs=[x])
Running test 1 of 1 ... terminate called after throwing an instance of 'std::runtime_error'
what():  size_dim_5, size_dim_4, height and width dimension must be 1, but shape is '[(1, 1, 1, 3, 4)]'

The reason is, the fdeep-embedding layer only accepts flattened input tensors


In your model, you have the following two lines of code:

xc = Reshape((url_word_size*word_char_size,))(word_char_input)
xc = Embedding(102, 32)(word_char_input)

I guess that's an error, and actually you wanted that:

xc = Reshape((url_word_size*word_char_size,))(word_char_input)
xc = Embedding(102, 32)(xc)

right?

However, if I change this, we run into a different error (in convert_model.py):

tensorflow.python.framework.errors_impl.InvalidArgumentError: indices[0,670] = 255 is not in [0, 102)
         [[{{node embedding_3/embedding_lookup}}]]

The problem seems to be, the generator (in convert_model.py) for the test-run values not handling multiple embedding layers in one model correctly.

A workaround might be to not produce any test cases when converting:

convert_model.py model.h5 model.json --no-tests

Of course not nice, but then at least you can load the model in C++.

The actual prediction step may still be another issue. I'll dig deeper into it.

Dobiasd commented 5 years ago

The tensorflow.python.framework.errors_impl.InvalidArgumentError also happens with with minimal example:

inp = Input(shape=(3, 4), dtype=np.uint8)
x = Reshape((12,))(inp)
x = Embedding(50, 10)(x)
model = Model(inputs=[inp], outputs=[x])

So the Reshape in front of Embedding, i.e., Embedding not being the first layer, is not handled correctly. I'll check if I can fix convert_model.py.

Dobiasd commented 5 years ago

OK, currently I can support generating test data for models with embedding layers only if the embedding layers are positioned directly at an input node of the computational graph. I just commited a change to convert_model.py that checks this precondition and produces a meaningful error if it is not fulfilled.

In the case of your model we can achieve this condition by a minor change, i.e., removing the Reshape layer in front of the Embedding layer, like so:

word_char_input = Input(shape=(url_word_size * word_char_size,), dtype=np.uint8)
....
xc = Embedding(102, 32)(word_char_input)

Your full get_model code now should look like this: https://gist.github.com/Dobiasd/d38ad8001ad9e9de4cd896cc19759ba4


Now, conversion works, but when loading (+testing) the model in C++, we run into:

Loading json ... done. elapsed time: 0.015960 s
Running test 1 of 1 ... terminate called after throwing an instance of 'std::runtime_error'
  what():  Invalid input value count.

I'll also investigate what this is about.

Thanks for challanging the library with such a demanding model architecture. :)

Dobiasd commented 5 years ago

I thought it was a bug in concatenate_tensor5s. However the change only made your model work, but broke everything else, so I reverted it.

So I'm still working on it, and will let you know when fixed.

Dobiasd commented 5 years ago

Seems to have something to do with the concatenate layer. The following minimal model raises a similar error in C++:

inp1 = Input(shape=(3, 7))
inp2 = Input(shape=(3, 7))
x = Concatenate(axis=1)([inp1, inp2])
model = Model(inputs=[inp1, inp2], outputs=[x])
terminate called after throwing an instance of 'std::runtime_error'
  what():  Wrong output size. Is (1, 1, 2, 3, 7), should be (1, 1, 1, 6, 7)
nicochidt commented 5 years ago

Thank you so much for your quick and detailed explanation.

Indeed that was a typo in the model. I've changed it and converted with --no-tests flag without any problem.

Nevertheless, the prediction step is failing with the following error:

libc++abi.dylib: terminating with uncaught exception of type std::runtime_error: Invalid input value count.

Just in case, this error is not related to the number of input tensors (in that case the error is: invalid number of input tensors for this model: 5 required but 4 provided).

I've run this on lldb and the exception seems to be very deep in the library. In case this helps somehow, this is the backtrace of it:

* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
  * frame #0: 0x00007fff77a2d23e libsystem_kernel.dylib`__pthread_kill + 10
    frame #1: 0x00007fff77ae3c1c libsystem_pthread.dylib`pthread_kill + 285
    frame #2: 0x00007fff779961c9 libsystem_c.dylib`abort + 127
    frame #3: 0x00007fff75016231 libc++abi.dylib`abort_message + 231
    frame #4: 0x00007fff750163b5 libc++abi.dylib`default_terminate_handler() + 241
    frame #5: 0x00007fff76821c8f libobjc.A.dylib`_objc_terminate() + 105
    frame #6: 0x00007fff75021dfe libc++abi.dylib`std::__terminate(void (*)()) + 8
    frame #7: 0x00007fff75021be2 libc++abi.dylib`__cxxabiv1::failed_throw(__cxxabiv1::__cxa_exception*) + 27
    frame #8: 0x00007fff75014bb9 libc++abi.dylib`__cxa_throw + 113
    frame #9: 0x000000010000a547 teststoi`fdeep::internal::raise_error(msg="Invalid input value count.") at common.hpp:57:5
    frame #10: 0x000000010000a357 teststoi`fdeep::internal::assertion(cond=false, error="Invalid input value count.") at common.hpp:64:9
    frame #11: 0x0000000100085788 teststoi`std::__1::vector<float, std::__1::allocator<float> > fdeep::internal::dense_layer::apply_impl(this=0x00007ffeefbfd008, input_part=size=720) const::'lambda'(auto const&)::operator()<std::__1::vector<float, std::__1::allocator<float> > >(auto const&) const at dense_layer.hpp:63:17
    frame #12: 0x000000010008567b teststoi`std::__1::back_insert_iterator<std::__1::vector<std::__1::vector<float, std::__1::allocator<float> >, std::__1::allocator<std::__1::vector<float, std::__1::allocator<float> > > > > std::__1::transform<std::__1::__wrap_iter<std::__1::vector<float, std::__1::allocator<float> > const*>, std::__1::back_insert_iterator<std::__1::vector<std::__1::vector<float, std::__1::allocator<float> >, std::__1::allocator<std::__1::vector<float, std::__1::allocator<float> > > > >, fdeep::internal::dense_layer::apply_impl(__first=__wrap_iter<const std::__1::vector<float, std::__1::allocator<float> > *> @ 0x00007ffeefbfd020, __last=__wrap_iter<const std::__1::vector<float, std::__1::allocator<float> > *> @ 0x00007ffeefbfd018, __result=back_insert_iterator<std::__1::vector<std::__1::vector<float, std::__1::allocator<float> >, std::__1::allocator<std::__1::vector<float, std::__1::allocator<float> > > > > @ 0x00007ffeefbfd010, __op=(anonymous class) @ 0x00007ffeefbfd008) const::'lambda'(auto const&)>(auto, auto, std::__1::back_insert_iterator<std::__1::vector<std::__1::vector<float, std::__1::allocator<float> >, std::__1::allocator<std::__1::vector<float, std::__1::allocator<float> > > > >, fdeep::internal::dense_layer::apply_impl(std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > const&) const::'lambda'(auto const&)) at algorithm:1963:21
    frame #13: 0x00000001000855b3 teststoi`auto fplus::internal::transform<std::__1::vector<std::__1::vector<float, std::__1::allocator<float> >, std::__1::allocator<std::__1::vector<float, std::__1::allocator<float> > > >, fdeep::internal::dense_layer::apply_impl(std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > const&) const::'lambda'(auto const&), std::__1::vector<std::__1::vector<float, std::__1::allocator<float> >, std::__1::allocator<std::__1::vector<float, std::__1::allocator<float> > > > >((null)=fplus::internal::create_new_container_t @ 0x00007ffeefbfd0d8, f=(anonymous class) @ 0x00007ffeefbfd0d0, xs=size=1) const::'lambda'(auto const&), std::__1::vector<std::__1::vector<float, std::__1::allocator<float> >, std::__1::allocator<std::__1::vector<float, std::__1::allocator<float> > > > const&) at container_common.hpp:584:5
    frame #14: 0x00000001000854cf teststoi`std::__1::vector<std::__1::vector<float, std::__1::allocator<float> >, std::__1::allocator<std::__1::vector<float, std::__1::allocator<float> > > > fplus::transform<fdeep::internal::dense_layer::apply_impl(f=(anonymous class) @ 0x00007ffeefbfd118, xs=size=1) const::'lambda'(auto const&), std::__1::vector<std::__1::vector<float, std::__1::allocator<float> >, std::__1::allocator<std::__1::vector<float, std::__1::allocator<float> > > > const&, std::__1::vector<std::__1::vector<float, std::__1::allocator<float> >, std::__1::allocator<std::__1::vector<float, std::__1::allocator<float> > > > >(auto, std::__1::vector<std::__1::vector<float, std::__1::allocator<float> >, std::__1::allocator<std::__1::vector<float, std::__1::allocator<float> > > > const&) at container_common.hpp:612:12
    frame #15: 0x00000001000848be teststoi`fdeep::internal::dense_layer::apply_impl(this=0x0000000100c00038, inputs=size=1) const at dense_layer.hpp:60:43
    frame #16: 0x00000001000371b2 teststoi`fdeep::internal::layer::apply(this=0x0000000100c00038, input=size=1) const at layer.hpp:55:29
    frame #17: 0x00000001000459a4 teststoi`fdeep::internal::apply_layer(layer=0x0000000100c00038, inputs=size=1) at layer.hpp:101:18
    frame #18: 0x00000001000450d7 teststoi`fdeep::internal::node::get_output(this=0x0000000100809780, layers=size=41, output_cache=size=32, layer=0x0000000100c00038) const at node.hpp:64:16
    frame #19: 0x00000001000373e6 teststoi`fdeep::internal::layer::get_output(this=0x0000000100c00038, layers=size=41, output_cache=size=32, node_idx=0, tensor_idx=0) const at layer.hpp:72:34
    frame #20: 0x0000000100046a88 teststoi`fdeep::internal::get_layer_output(layers=size=41, output_cache=size=32, layer=std::__1::shared_ptr<fdeep::internal::layer>::element_type @ 0x0000000100c00038 strong=2 weak=1, node_idx=0, tensor_idx=0) at layer.hpp:96:19
    frame #21: 0x00000001000468e9 teststoi`fdeep::internal::node::get_output(this=0x00007ffeefbfd7d0, conn=0x0000000100a084f8) const::'lambda'(fdeep::internal::node_connection const&)::operator()(fdeep::internal::node_connection const&) const at node.hpp:60:20
    frame #22: 0x0000000100045c82 teststoi`std::__1::back_insert_iterator<std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > > std::__1::transform<std::__1::__wrap_iter<fdeep::internal::node_connection const*>, std::__1::back_insert_iterator<std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > >, fdeep::internal::node::get_output(__first=__wrap_iter<const fdeep::internal::node_connection *> @ 0x00007ffeefbfd7f0, __last=__wrap_iter<const fdeep::internal::node_connection *> @ 0x00007ffeefbfd7e8, __result=back_insert_iterator<std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > > @ 0x00007ffeefbfd7e0, __op=(anonymous class) @ 0x00007ffeefbfd7d0) const::'lambda'(fdeep::internal::node_connection const&)>(std::__1::__wrap_iter<fdeep::internal::node_connection const*>, std::__1::__wrap_iter<fdeep::internal::node_connection const*>, std::__1::back_insert_iterator<std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > >, fdeep::internal::node::get_output(std::__1::vector<std::__1::shared_ptr<fdeep::internal::layer>, std::__1::allocator<std::__1::shared_ptr<fdeep::internal::layer> > > const&, std::__1::map<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long>, std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> >, std::__1::less<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long> >, std::__1::allocator<std::__1::pair<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long> const, std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > > > >&, fdeep::internal::layer const&) const::'lambda'(fdeep::internal::node_connection const&)) at algorithm:1963:21
    frame #23: 0x0000000100045aff teststoi`std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > fplus::internal::transform<std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> >, fdeep::internal::node::get_output((null)=fplus::internal::create_new_container_t @ 0x00007ffeefbfd8b8, f=(anonymous class) @ 0x00007ffeefbfd8a8, xs=size=4) const::'lambda'(fdeep::internal::node_connection const&), std::__1::vector<fdeep::internal::node_connection, std::__1::allocator<fdeep::internal::node_connection> > >(fplus::internal::reuse_container_bool_t<bool, false>, fdeep::internal::node::get_output(std::__1::vector<std::__1::shared_ptr<fdeep::internal::layer>, std::__1::allocator<std::__1::shared_ptr<fdeep::internal::layer> > > const&, std::__1::map<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long>, std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> >, std::__1::less<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long> >, std::__1::allocator<std::__1::pair<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long> const, std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > > > >&, fdeep::internal::layer const&) const::'lambda'(fdeep::internal::node_connection const&), std::__1::vector<fdeep::internal::node_connection, std::__1::allocator<fdeep::internal::node_connection> > const&) at container_common.hpp:584:5
    frame #24: 0x00000001000459ff teststoi`std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > fplus::transform<fdeep::internal::node::get_output(f=(anonymous class) @ 0x00007ffeefbfd900, xs=size=4) const::'lambda'(fdeep::internal::node_connection const&), std::__1::vector<fdeep::internal::node_connection, std::__1::allocator<fdeep::internal::node_connection> > const&, std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > >(fdeep::internal::node::get_output(std::__1::vector<std::__1::shared_ptr<fdeep::internal::layer>, std::__1::allocator<std::__1::shared_ptr<fdeep::internal::layer> > > const&, std::__1::map<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long>, std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> >, std::__1::less<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long> >, std::__1::allocator<std::__1::pair<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long> const, std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > > > >&, fdeep::internal::layer const&) const::'lambda'(fdeep::internal::node_connection const&), std::__1::vector<fdeep::internal::node_connection, std::__1::allocator<fdeep::internal::node_connection> > const&) at container_common.hpp:612:12
    frame #25: 0x00000001000450c3 teststoi`fdeep::internal::node::get_output(this=0x0000000100a06d00, layers=size=41, output_cache=size=32, layer=0x0000000100a08268) const at node.hpp:65:13
    frame #26: 0x00000001000373e6 teststoi`fdeep::internal::layer::get_output(this=0x0000000100a08268, layers=size=41, output_cache=size=32, node_idx=0, tensor_idx=0) const at layer.hpp:72:34
    frame #27: 0x0000000100046a88 teststoi`fdeep::internal::get_layer_output(layers=size=41, output_cache=size=32, layer=std::__1::shared_ptr<fdeep::internal::layer>::element_type @ 0x0000000100a08268 strong=2 weak=1, node_idx=0, tensor_idx=0) at layer.hpp:96:19
    frame #28: 0x00000001000468e9 teststoi`fdeep::internal::node::get_output(this=0x00007ffeefbfdcc0, conn=0x0000000100b05620) const::'lambda'(fdeep::internal::node_connection const&)::operator()(fdeep::internal::node_connection const&) const at node.hpp:60:20
    frame #29: 0x0000000100045c82 teststoi`std::__1::back_insert_iterator<std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > > std::__1::transform<std::__1::__wrap_iter<fdeep::internal::node_connection const*>, std::__1::back_insert_iterator<std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > >, fdeep::internal::node::get_output(__first=__wrap_iter<const fdeep::internal::node_connection *> @ 0x00007ffeefbfdce0, __last=__wrap_iter<const fdeep::internal::node_connection *> @ 0x00007ffeefbfdcd8, __result=back_insert_iterator<std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > > @ 0x00007ffeefbfdcd0, __op=(anonymous class) @ 0x00007ffeefbfdcc0) const::'lambda'(fdeep::internal::node_connection const&)>(std::__1::__wrap_iter<fdeep::internal::node_connection const*>, std::__1::__wrap_iter<fdeep::internal::node_connection const*>, std::__1::back_insert_iterator<std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > >, fdeep::internal::node::get_output(std::__1::vector<std::__1::shared_ptr<fdeep::internal::layer>, std::__1::allocator<std::__1::shared_ptr<fdeep::internal::layer> > > const&, std::__1::map<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long>, std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> >, std::__1::less<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long> >, std::__1::allocator<std::__1::pair<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long> const, std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > > > >&, fdeep::internal::layer const&) const::'lambda'(fdeep::internal::node_connection const&)) at algorithm:1963:21
    frame #30: 0x0000000100045aff teststoi`std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > fplus::internal::transform<std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> >, fdeep::internal::node::get_output((null)=fplus::internal::create_new_container_t @ 0x00007ffeefbfdda8, f=(anonymous class) @ 0x00007ffeefbfdd98, xs=size=1) const::'lambda'(fdeep::internal::node_connection const&), std::__1::vector<fdeep::internal::node_connection, std::__1::allocator<fdeep::internal::node_connection> > >(fplus::internal::reuse_container_bool_t<bool, false>, fdeep::internal::node::get_output(std::__1::vector<std::__1::shared_ptr<fdeep::internal::layer>, std::__1::allocator<std::__1::shared_ptr<fdeep::internal::layer> > > const&, std::__1::map<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long>, std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> >, std::__1::less<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long> >, std::__1::allocator<std::__1::pair<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long> const, std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > > > >&, fdeep::internal::layer const&) const::'lambda'(fdeep::internal::node_connection const&), std::__1::vector<fdeep::internal::node_connection, std::__1::allocator<fdeep::internal::node_connection> > const&) at container_common.hpp:584:5
    frame #31: 0x00000001000459ff teststoi`std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > fplus::transform<fdeep::internal::node::get_output(f=(anonymous class) @ 0x00007ffeefbfddf0, xs=size=1) const::'lambda'(fdeep::internal::node_connection const&), std::__1::vector<fdeep::internal::node_connection, std::__1::allocator<fdeep::internal::node_connection> > const&, std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > >(fdeep::internal::node::get_output(std::__1::vector<std::__1::shared_ptr<fdeep::internal::layer>, std::__1::allocator<std::__1::shared_ptr<fdeep::internal::layer> > > const&, std::__1::map<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long>, std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> >, std::__1::less<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long> >, std::__1::allocator<std::__1::pair<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long> const, std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > > > >&, fdeep::internal::layer const&) const::'lambda'(fdeep::internal::node_connection const&), std::__1::vector<fdeep::internal::node_connection, std::__1::allocator<fdeep::internal::node_connection> > const&) at container_common.hpp:612:12
    frame #32: 0x00000001000450c3 teststoi`fdeep::internal::node::get_output(this=0x0000000100b04900, layers=size=41, output_cache=size=32, layer=0x0000000100b04da8) const at node.hpp:65:13
    frame #33: 0x00000001000373e6 teststoi`fdeep::internal::layer::get_output(this=0x0000000100b04da8, layers=size=41, output_cache=size=32, node_idx=0, tensor_idx=0) const at layer.hpp:72:34
    frame #34: 0x0000000100046a88 teststoi`fdeep::internal::get_layer_output(layers=size=41, output_cache=size=32, layer=std::__1::shared_ptr<fdeep::internal::layer>::element_type @ 0x0000000100b04da8 strong=2 weak=1, node_idx=0, tensor_idx=0) at layer.hpp:96:19
    frame #35: 0x00000001000468e9 teststoi`fdeep::internal::node::get_output(this=0x00007ffeefbfe1b0, conn=0x0000000100b048d0) const::'lambda'(fdeep::internal::node_connection const&)::operator()(fdeep::internal::node_connection const&) const at node.hpp:60:20
    frame #36: 0x0000000100045c82 teststoi`std::__1::back_insert_iterator<std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > > std::__1::transform<std::__1::__wrap_iter<fdeep::internal::node_connection const*>, std::__1::back_insert_iterator<std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > >, fdeep::internal::node::get_output(__first=__wrap_iter<const fdeep::internal::node_connection *> @ 0x00007ffeefbfe1d0, __last=__wrap_iter<const fdeep::internal::node_connection *> @ 0x00007ffeefbfe1c8, __result=back_insert_iterator<std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > > @ 0x00007ffeefbfe1c0, __op=(anonymous class) @ 0x00007ffeefbfe1b0) const::'lambda'(fdeep::internal::node_connection const&)>(std::__1::__wrap_iter<fdeep::internal::node_connection const*>, std::__1::__wrap_iter<fdeep::internal::node_connection const*>, std::__1::back_insert_iterator<std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > >, fdeep::internal::node::get_output(std::__1::vector<std::__1::shared_ptr<fdeep::internal::layer>, std::__1::allocator<std::__1::shared_ptr<fdeep::internal::layer> > > const&, std::__1::map<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long>, std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> >, std::__1::less<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long> >, std::__1::allocator<std::__1::pair<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long> const, std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > > > >&, fdeep::internal::layer const&) const::'lambda'(fdeep::internal::node_connection const&)) at algorithm:1963:21
    frame #37: 0x0000000100045aff teststoi`std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > fplus::internal::transform<std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> >, fdeep::internal::node::get_output((null)=fplus::internal::create_new_container_t @ 0x00007ffeefbfe298, f=(anonymous class) @ 0x00007ffeefbfe288, xs=size=1) const::'lambda'(fdeep::internal::node_connection const&), std::__1::vector<fdeep::internal::node_connection, std::__1::allocator<fdeep::internal::node_connection> > >(fplus::internal::reuse_container_bool_t<bool, false>, fdeep::internal::node::get_output(std::__1::vector<std::__1::shared_ptr<fdeep::internal::layer>, std::__1::allocator<std::__1::shared_ptr<fdeep::internal::layer> > > const&, std::__1::map<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long>, std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> >, std::__1::less<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long> >, std::__1::allocator<std::__1::pair<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long> const, std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > > > >&, fdeep::internal::layer const&) const::'lambda'(fdeep::internal::node_connection const&), std::__1::vector<fdeep::internal::node_connection, std::__1::allocator<fdeep::internal::node_connection> > const&) at container_common.hpp:584:5
    frame #38: 0x00000001000459ff teststoi`std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > fplus::transform<fdeep::internal::node::get_output(f=(anonymous class) @ 0x00007ffeefbfe2e0, xs=size=1) const::'lambda'(fdeep::internal::node_connection const&), std::__1::vector<fdeep::internal::node_connection, std::__1::allocator<fdeep::internal::node_connection> > const&, std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > >(fdeep::internal::node::get_output(std::__1::vector<std::__1::shared_ptr<fdeep::internal::layer>, std::__1::allocator<std::__1::shared_ptr<fdeep::internal::layer> > > const&, std::__1::map<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long>, std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> >, std::__1::less<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long> >, std::__1::allocator<std::__1::pair<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long> const, std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > > > >&, fdeep::internal::layer const&) const::'lambda'(fdeep::internal::node_connection const&), std::__1::vector<fdeep::internal::node_connection, std::__1::allocator<fdeep::internal::node_connection> > const&) at container_common.hpp:612:12
    frame #39: 0x00000001000450c3 teststoi`fdeep::internal::node::get_output(this=0x0000000100b03f20, layers=size=41, output_cache=size=32, layer=0x0000000100b04408) const at node.hpp:65:13
    frame #40: 0x00000001000373e6 teststoi`fdeep::internal::layer::get_output(this=0x0000000100b04408, layers=size=41, output_cache=size=32, node_idx=0, tensor_idx=0) const at layer.hpp:72:34
    frame #41: 0x00000001000ea812 teststoi`fdeep::internal::model_layer::apply_impl(this=0x00007ffeefbfe650, conn=0x0000000100b04a30) const::'lambda'(fdeep::internal::node_connection const&)::operator()(fdeep::internal::node_connection const&) const at model_layer.hpp:68:56
    frame #42: 0x00000001000ea6f2 teststoi`std::__1::back_insert_iterator<std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > > std::__1::transform<std::__1::__wrap_iter<fdeep::internal::node_connection const*>, std::__1::back_insert_iterator<std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > >, fdeep::internal::model_layer::apply_impl(__first=__wrap_iter<const fdeep::internal::node_connection *> @ 0x00007ffeefbfe670, __last=__wrap_iter<const fdeep::internal::node_connection *> @ 0x00007ffeefbfe668, __result=back_insert_iterator<std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > > @ 0x00007ffeefbfe660, __op=(anonymous class) @ 0x00007ffeefbfe650) const::'lambda'(fdeep::internal::node_connection const&)>(std::__1::__wrap_iter<fdeep::internal::node_connection const*>, std::__1::__wrap_iter<fdeep::internal::node_connection const*>, std::__1::back_insert_iterator<std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > >, fdeep::internal::model_layer::apply_impl(std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > const&) const::'lambda'(fdeep::internal::node_connection const&)) at algorithm:1963:21
    frame #43: 0x00000001000ea61f teststoi`std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > fplus::internal::transform<std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> >, fdeep::internal::model_layer::apply_impl((null)=fplus::internal::create_new_container_t @ 0x00007ffeefbfe738, f=(anonymous class) @ 0x00007ffeefbfe728, xs=size=1) const::'lambda'(fdeep::internal::node_connection const&), std::__1::vector<fdeep::internal::node_connection, std::__1::allocator<fdeep::internal::node_connection> > >(fplus::internal::reuse_container_bool_t<bool, false>, fdeep::internal::model_layer::apply_impl(std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > const&) const::'lambda'(fdeep::internal::node_connection const&), std::__1::vector<fdeep::internal::node_connection, std::__1::allocator<fdeep::internal::node_connection> > const&) at container_common.hpp:584:5
    frame #44: 0x00000001000ea27f teststoi`std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > fplus::transform<fdeep::internal::model_layer::apply_impl(f=(anonymous class) @ 0x00007ffeefbfe780, xs=size=1) const::'lambda'(fdeep::internal::node_connection const&), std::__1::vector<fdeep::internal::node_connection, std::__1::allocator<fdeep::internal::node_connection> > const&, std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > >(fdeep::internal::model_layer::apply_impl(std::__1::vector<fdeep::internal::tensor5, std::__1::allocator<fdeep::internal::tensor5> > const&) const::'lambda'(fdeep::internal::node_connection const&), std::__1::vector<fdeep::internal::node_connection, std::__1::allocator<fdeep::internal::node_connection> > const&) at container_common.hpp:612:12
    frame #45: 0x00000001000e9472 teststoi`fdeep::internal::model_layer::apply_impl(this=0x0000000100b04028, inputs=size=5) const at model_layer.hpp:71:16
    frame #46: 0x00000001000371b2 teststoi`fdeep::internal::layer::apply(this=0x0000000100b04028, input=size=5) const at layer.hpp:55:29
    frame #47: 0x0000000100006f66 teststoi`fdeep::model::predict(this=0x00007ffeefbff2d8, inputs=size=5) const at model.hpp:35:44
    frame #48: 0x000000010000520e teststoi`main(argc=3, argv=0x00007ffeefbff6e8) at test-fdeep-functional.cpp:207:31
    frame #49: 0x00007fff778eded9 libdyld.dylib`start + 1
    frame #50: 0x00007fff778eded9 libdyld.dylib`start + 1

Once again, thank you very much for your help.

nicochidt commented 5 years ago

I didn't hit the problem you are describing, maybe is related to the same problem you are mentioning but is raising the exception in a different place.

Dobiasd commented 5 years ago

It seems to be the same problem. Concatenate in frugally-deep is not behaving correctly for rank-2 tensors and axis 1.

In my minimal example it manifests as incorrect output shape of the model (because concatenate is the last layer). In your case you hit it, because the input shape for the dense layer (coming after concatenate) is incorrect.

I've already added the needed cases to the unit tests (which are not failing), and I will commit when this is fixed.

Dobiasd commented 5 years ago

Just fixed the Concatenate layer.

@nicochidt Your model, at least with the modification of not having Reshape before Embedding, is now fully working, including test cases. :tada:

Dobiasd commented 5 years ago

If you encounter any additional problems, please let me know.

And again, thanks for helping to improve the library with your good test case and reporting. :+1:

nicochidt commented 5 years ago

I've just checked and it's fully functional.

You are amazing. Best open source response ever. How can I buy you a beer?

Dobiasd commented 5 years ago

Thanks a lot. :blush:

I always enjoy learning for what purpose my library is actually used. So if you can tell me (and it's not a company secret or alike), I'd be happy with knowing your use case as a beer substitute. :slightly_smiling_face:

nicochidt commented 5 years ago

We are running different classifiers on mobile devices as part of an intrusion prevention system. Recently, we started to use neural networks for a few of them (malware and phishing detection mostly).

It's an awesome tool and I thank you one more time for coding it.