serizba / cppflow

Run TensorFlow models in C++ without installation and without Bazel
https://serizba.github.io/cppflow/
MIT License
788 stars 178 forks source link

Using a vector of strings as input for Universal Sentence Encoder model #101

Closed JohnMrziglod closed 3 years ago

JohnMrziglod commented 3 years ago

Amazing library! Thank you very much for creating it.

I am trying to use cppflow with the Universal Sentence Encoder model. Unfortunately, I am not sure how to pass a vector of strings to the model. This is the code I use:

#include <iostream>

#include "cppflow/cppflow.h"

int main() {
    std::string input_string = "This is a test";
    auto inputs = cppflow::tensor(input_string);

    // Load the model
    cppflow::model model("path/to/encoder");

    // Run
    auto output = model({{"serving_default_inputs", inputs}}, {{"StatefulPartitionedCall_1"}});

    // Show the predicted class
    std::cout << output << std::endl;
}

This fails with

terminate called after throwing an instance of 'std::runtime_error'
  what():  {{function_node __inference_pruned_2009}} {{function_node __inference_pruned_2009}} input must be a vector, g
ot shape: []
         [[{{node text_preprocessor/tokenize/StringSplit/StringSplit}}]]
         [[StatefulPartitionedCall_1/StatefulPartitionedCall/StatefulPartitionedCall/StatefulPartitionedCall]]

How do I pass a vector of strings to this model?

serizba commented 3 years ago

Hi @JohnMrziglod

You are feeding the model with a tensor with shape=[], that is, a scalar. But the model requires a vector shape=[-1]. You can convert the scalar into a vector with the cppflow::reshape method. Note the difference between both:

std::cout << cppflow::tensor(std::string("hello")) << std::endl;
// (tensor: shape=[], data="hello")
std::cout << cppflow::reshape(cppflow::tensor(std::string("hello")), {-1}) << std::endl;
// (tensor: shape=[1], data=["hello"])

If you need a vector with multiple strings, you can use cppflow::concat:

auto s1 = cppflow::tensor(std::string("hello"));
auto s2 = cppflow::tensor(std::string("hello"));
auto s3 = cppflow::tensor(std::string("hello"));

std::cout << cppflow::concat(0, {s1, s2, s3});
// (tensor: shape=[3], data=["hello" "hello" "hello"])

Hope it helps!

JohnMrziglod commented 3 years ago

Amazing, thank you!