Vowpal Wabbit 9 is the first major release in over 6 years! There are a number of usability improvements, new reductions, bug fixes and internal improvements here. The Python package has undergone a bit of a modernization with a more understandable module structure, naming and types. Most changes should be non breaking for standard use cases. See here for the migration guide. There is still improvement to be made with Python but this is a good first step towards a more usable package.
This release includes some breaking changes detailed below. Please review them to see if they affect you.
In the past if VW was not able to open an input file it would print a message and continue. This usually meant it would fall back to reading from standard input leading to unintuitive behavior. VW will now treat failure to open an input file as an error, produce the appropriate error message and exit.
Python 2.7 and 3.5 are no longer supported. The last release where they were available was 8.11.0. Details on the Python support matrix can be found here. Dropping support for these also allows us to begin to introduce new features such as type hints.
To align with PEP8 and be more consistent we renamed the following modules.
We did as much as we could to keep the old names accessible. Unfortunately, since some operating systems are case insensitive renaming the
DFtoVW module causes some issues. There may be some ways of importing
vowpalwabbit.DFtoVW that broke in this migration on some operating systems or setups.
For example, the following will be broken and must be changed.
from vowpalwabbit.DFtoVW import DFtoVW # Change to -> from vowpalwabbit.dftovw import DFtoVW
Most of the core objects from
vowpalwabbit.pyvw are now accessible in the root module.
For example the following can now be done:
from vowpalwabbit import Workspace workspace = Workspace(quiet=True) workspace.learn('1 | a b c') print(workspace.predict('| b c'))
See the docs for what is in the root module.
save_resumeis now the default for model saving and loading
We have seen confusion around the old default behavior that required a flag to be supplied to continue training from a model. We decided (after a call for comment) that it makes more sense for the default behavior of VW be to support continuing training when saving and loading a model. This new model is slightly larger, but more flexible. If the previous behavior is required,
--predict_only_model is available. You may want this if you are using the model file in an inference only setup or you have tooling which requires this format.
This will change the format of any readable models by default because more information is saved. If you depend on that format please keep in mind this change.
-q: has been removed. This is different to
-q ::, which certainly has not been removed.
-q: may have been added by mistake. It has never actually done anything and is confusing when it is so similar to the very important
-q option. It has been deprecated for some time and is now removed.
There is no breaking change if you were using
pyvw.Example.get_label. There is only a change if you directly constructed any label objects.
Label objects in Python have had their
from_example functions changed.
__init__ no longer accepts a
pyvw.Example object and just accepts that label’s state.
from_example is now a static factory function.
When resuming training a model from a file in the past VW did not remember the learning rate and
power_t used in initial training. VW will not use the same values when the model is loaded. The values can be overridden by supplying a new value on the command line when resuming.
A number of fixes were made to the way features are counted which results in different counts in run results, especially around shared examples. This is technically a bug fix but is listed under breaking changes just as an informative notice in case this surprises anyone. Relevant PRs:
The following sets of changes are internal breaking changes. These should not affect you unless you depend on any of the C++ code structure. These changes have been marked in the past.
VW’s output has been cleaned up in this release. During default operation VW produces two different streams of output. The driver which contains some initial information, progressive validation and results. The logger which produces info, warning and error information. In the past logging information was not produced in a consistent way. Logging information now has a consistent format and can be controlled.
--quiet- Works the same as before but can be explained as turning off both the driver and log output streams
--driver_output_off- Will just turn off the driver but leave logging on
stderr) - Direct driver output to the specified location
stdout) - Direct logging output to the specified location. Or, if
compatis chosen the output location will be what it was in 8.11. Past versions were not consistent about output location and this was added if any user depended on that behavior. log_output
info) - Log level to enable.
If an option is passed which is definitely not used by any enabled reduction VW will now issue a warning.
vw --epsilon 0.5
[warning] Option 'epsilon' depends on another option (or combination of options) which was not supplied. Possible combinations of options which would enable this option are: cb_explore_pdf warm_cb bag, cb_explore_adf cb_explore_adf, cover cb_explore_adf, first cb_explore_adf, synthcover cb_explore_adf, rnd cb_explore_adf, softmax cb_explore_adf cb_explore
This is the first release which includes the new documentation site. We plan on iterating on this and converging documentation over time. The tutorials are now hosted here and redirect from their old locations. The Python based tutorials and examples have links at the top of the page to make the content interactive in the browser. Try it out!
Now that Python 2 is no longer supported we were able to add type hints to the Python code base. These typehints are also checked for each commit in CI. They make the documentation much clearer too.
Thanks to @odidev the Python package now includes AArch64 binary wheels for Linux.
vowpalwabbit.pyvw have been renamed to match PEP8. The old names are still accessible but are deprecated.
FreeGrad is a new base learner described in this paper. It can be tried where coin or gradient descent may have been used before.
AutoML is a new reduction whose primary goal is to provide users with a hands-off method to get an optimal learning configuration without prior experience using VW or an in-depth understanding of their dataset. A “configuration” is a general term which can be extended to any aspect of VW (enabled reduction, # of passes, etc…) but as of now a configuration will specify the set of namespace interactions used in a contextual bandit problem. More specifically, a configuration specifies a set of interactions which will be excluded from the default configuration -q :: (All quadratic interactions).
VW’s learning algorithm attempts to minimize loss, and the contextual bandit input format specifically calls for cost. However, in the setting on reinforcement learning and contextual bandits it is common to use reward in a label for a data point. And for rewards the agent wishes to maximize reward. Accidentally supplying a reward in place of a cost for contextual bandit label in VW will result in incorrect learning as minimizing this value is the opposite of what is intended.
This reduction tracks incoming labels and determines whether they are rewards or costs. Note that because positive value are assumed to be rewards and negative values costs, if your dataset is labelled such that positive values are still costs but are used to penalize the learner then this automatic translation will not work.
The reduction builds a CI around the baseline action and use it instead of the policy as the greedy action if its lower bound is higher than the policy expected reward.
An experimental new feature which allows interactions to be specified as the entire namespace name instead of just the first character was added. It is specified with the option:
--experimental_full_name_interactions <arg>. The value of
<arg> is the list of namespaces in the interaction separated by
|. For example to interaction two namespaces
--experimental_full_name_interactions Action|Access. This new feature allows interactions between namespaces where the first character is the same. In the past that would have needed to be achieved through prefixing the namespaces with a unique character.
Thanks to @mathcass the Python package includes the CLI tool. There are a few limitations to using this compared to the executable itself which are important to know.
stdinof the process)
--argscannot be used
One of the RLOS projects in 2021 was around privacy preserving learning and was worked on by @manavsinghal157. The feature implements aggregated learning by saving only those features that have seen a minimum threshold of users.
Note: this feature is available behind a compiler flag and is still experimental. See wiki page for instructions.
Previously labels had to be 1-indexed for the
csoaa_ldf reductions. Now these reductions can use 0-indexed labels, and report 0-indexed predictions. VW will dynamically detect the indexing of the examples, but you can also set it explicitly with
--indexing 0 or
A huge thank you and welcome to all of the new contributors since the last release:
And of course thank you to existing contributors: