vowpal_wabbit icon indicating copy to clipboard operation
vowpal_wabbit copied to clipboard

Vowpal Wabbit C API getting 0 as prediction

Open 0110G opened this issue 2 years ago • 11 comments

Describe the bug

I am trying to write a C program that loads a trained vw model and returns predictions in real time. For this, I am using libvw_c_wrapper and using methods described here.

The model was trained and saved with following configurations in python:

vw = vowpalwabbit.Workspace(
    "--cats "
    + str(num_actions)
    + "  --bandwidth "
    + str(bandwidth)
    + " --min_value {} --max_value {} --json --chain_hash --coin --epsilon 0.1".format(min_val, max_val)

And saved as: vw.save('nadwwadw.model')

This is my C program (vw_client.c):

#include "/Users/../C_VW_Test/vwdll.h"
#include <stdio.h>

int main()
{
    VW_HANDLE vw;
    char vw_arg[] = "-i nadwwadw.model";
    vw = VW_InitializeA(vw_arg);

    char vw_example[] = "ca | ";

    for (int i=0; i<1000 ; i++) {
        VW_EXAMPLE example = VW_ReadExampleA(vw, vw_example);
        
        float pred = VW_Predict(vw, example);
        printf("VW_Predict: %f\n", pred);
    }


    return 0;

}

and compile using gcc vw_client.c -L. -lvw_c_wrapper -o test

When I load this model in jupyter notebook as new_vw = vowpalwabbit.Workspace("-i nadwwadw.model") and make predictions as new_vw.predict("ca | "), I get the output as (0.2624061703681946, 230.43333435058594).

However, my C code returns prediction as 0.00000 even for all iterations.

My requirements involve only predictions for now.

Can someone please help me understand

  1. Why am i getting different results in C and how do I solve it?
  2. Am I using the correct dylib/so file? If no, steps to build the correct one.

Thanks in Advance

How to reproduce

Described above

Version

9.0.1

OS

MacOS

Language

C

Additional context

No response

0110G avatar Jun 30 '22 10:06 0110G

The function VW_Predict returns the scalar prediction, however, you need the pdf value prediction produced by continuous actions. Unfortunately this is not available from the C API you referenced.

The reason Python works is it automatically determines what prediction type is returned by a given VW workspace and returns the correct type.

jackgerrits avatar Jun 30 '22 13:06 jackgerrits

In that case can you suggest any alternative. Even a C++ solution would work

0110G avatar Jun 30 '22 13:06 0110G

So a C++ solution would look something like this (I haven't tested it):

auto* ws = VW::initialize("-i nadwwadw.model");
auto* ex = VW::read_example(*ws, "ca | ");
ws->predict(*ex);
auto& prediction = ex->pred.pdf_value;
VW::finish_example(*ex);
VW::finish(*ws);

jackgerrits avatar Jun 30 '22 13:06 jackgerrits

Can you please provide some documentation/pointers on required .so/.a/.dylib and steps to build them inorder to use the above mentioned solution.

0110G avatar Jul 01 '22 10:07 0110G

It's a bit out of date so may need some tweaking but generally speaking this is an example of what it may look like to have a C++ project depend on VW. Do note that when using the C++ interface directly some aspects of the API can change between releases. It does not have the same stability as the Python interface or command line. That being said we do our best to consider if a change is user facing and communicate accordingly in release notes and versioning.

https://github.com/lokitoth/vw_use_demo

jackgerrits avatar Jul 01 '22 15:07 jackgerrits

I plan to add cats support in C Wrapper API, I did the following for a basic code check:

  1. Added VW_DLL_PUBLIC void VW_CALLING_CONV Print() {printf("Random\n");} in vowpal_wabbit/vowpalwabbit/c_wrapper/src/vwdll.cc

  2. Added VW_DLL_PUBLIC void VW_CALLING_CONV Print(); in vowpal_wabbit/vowpalwabbit/c_wrapper/include/vw/c_wrapper/vwdll.h

  3. Build using cd vowpal_wabbit -> cmake -S . -B build -> cd build -> make vw_c_wrapper

  4. Add dylib Try to run Print() in code mentioned in C issue using same method. However I get the following error:

dyld: lazy symbol binding failed: Symbol not found: _Print
  Referenced from: /Users/bhavya.sa/Desktop/C_VW_Test/./a.out
  Expected in: /usr/local/lib/libvw_c_wrapper.dylib

dyld: Symbol not found: _Print
  Referenced from: /Users/bhavya.sa/Desktop/C_VW_Test/./a.out
  Expected in: /usr/local/lib/libvw_c_wrapper.dylib

zsh: abort      ./a.out

0110G avatar Jul 04 '22 10:07 0110G

[Update] https://github.com/VowpalWabbit/vowpal_wabbit/pull/4021

I was able to solve the issue by making changes mentioned in above pull request and building the exact same way. Before running, add the lib_vw_c_wrapper.dylib to $LD_LIBRARY_PATH variable: ```export LD_LIBRARY_PATH=<path_to_lib_vw_c_wrapper>:LD_LIBRARY_PATH

0110G avatar Jul 04 '22 10:07 0110G

Is there any way we can read json format using C/C++ APIs for cats mode ?

0110G avatar Jul 04 '22 13:07 0110G

@jackgerrits

0110G avatar Jul 05 '22 06:07 0110G

Provided the VW instance has been initialized to use --json, then you can look at how Python reads text input: https://github.com/VowpalWabbit/vowpal_wabbit/blob/d00835a4f3edee4f30195da92a7021a7f663fd03/python/pylibvw.cc#L560

jackgerrits avatar Jul 05 '22 13:07 jackgerrits

Support for the CATS pdf value prediction type was merged in this PR: https://github.com/VowpalWabbit/vowpal_wabbit/pull/4021

jackgerrits avatar Jul 08 '22 19:07 jackgerrits

Closing as I think this is resolved now. Please feel free to open a new issue if you face issues.

jackgerrits avatar Aug 22 '22 14:08 jackgerrits