{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This notebook demonstrates the most basic capabilities of the pyvw python->VW interface. The inferface (unlike the rest of VW :P) is extensively documented, so if you are confused, look at the python docs!\n",
    "\n",
    "Any pyvw application needs to begin by importing `pyvw`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from __future__ import print_function\n",
    "from vowpalwabbit import pyvw"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "One we've imported pyvw, we can initialize VW either by passing a command line string (e.g., \"--quiet -q ab --l2 0.01\") or, in a more python-friendly manner, providing those as named arguments. Here we do the latter."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "vw = pyvw.vw(quiet=True, q='ab', l2=0.01)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "VW objects can do a lot, but the most important thing the can do is create examples and train/predict on those examples.\n",
    "\n",
    "One way to create an example is to pass a string. This is the equivalent of a string in a VW file. For instance:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "ex = vw.example('1 |a two features |b more features here')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As promised there is documentation; for instance:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on method learn in module vowpalwabbit.pyvw:\n",
      "\n",
      "learn() method of vowpalwabbit.pyvw.example instance\n",
      "    Learn on this example (and before learning, automatically\n",
      "    call setup_example if the example hasn't yet been setup).\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(ex.learn)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's run that learn function and get a prediction:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "current prediction = 0.8230039477348328\n"
     ]
    }
   ],
   "source": [
    "ex.learn()\n",
    "print('current prediction =', ex.get_updated_prediction())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here, `get_updated_prediction` retrieves the prediction made internally during learning. The \"updated\" aspect means \"if I were to make a prediction on this example *after* this call to `learn`, what would that prediction be?\"\n",
    "\n",
    "Okay, so the prediction isn't quite where we want it yet. Let's learn a few more times and then print the prediction."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "current prediction = 0.9992850422859192\n"
     ]
    }
   ],
   "source": [
    "ex.learn() ; ex.learn() ; ex.learn() ; ex.learn()\n",
    "print('current prediction =', ex.get_updated_prediction())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This is now quite a bit closer to what is desired.\n",
    "\n",
    "Now let's create a new example using the other form of example creation: python dictionaries. Here, you must provide a dictionary that maps namespaces (eg, 'a' and 'b') to lists of features. Features can either be strings (eg `\"foo\"`), or pairs of string/floats (eg `(\"foo\", 0.5)`). We'll create an example that's similar, but not identical to, the previous example to see how well VW has generalized.\n",
    "\n",
    "Note that in this setup there is no label provided, which means that this will be considered a test example."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "ex2 = vw.example({ 'a': ['features'], 'b': ['more', 'features', 'there'] })"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Given this example, we execute `learn`. But since it's a test example (no label), this will only make a prediction!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "current prediction = 0.4984472393989563\n"
     ]
    }
   ],
   "source": [
    "ex2.learn()\n",
    "print('current prediction =', ex2.get_simplelabel_prediction())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Because this is a test example, we can get the raw prediction with `get_simplelabel_prediction()`. This is `simplelabel` because it's a regression problem. If we were doing, for instance, One-Against-All multiclass prediction, we would use `get_multiclass_prediction`, etc.\n",
    "\n",
    "This prediction is only about half of what we want, but we're also missing a number of features.\n",
    "\n",
    "Let's now give this example a label and train on it a few times:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "current prediction = -1.4838640689849854\n"
     ]
    }
   ],
   "source": [
    "ex2.set_label_string('-2.0')\n",
    "ex2.learn() ; ex2.learn() ; ex2.learn() ; ex2.learn() ; ex2.learn()\n",
    "print('current prediction =', ex2.get_simplelabel_prediction())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we can go back and see how this has affected the prediction behavior on the original example `ex`. We do this first by removing the label and then calling `learn` to make a prediction."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "current prediction = -0.5934292078018188\n"
     ]
    }
   ],
   "source": [
    "ex.set_label_string('')\n",
    "ex.learn()\n",
    "print('current prediction =', ex.get_simplelabel_prediction())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Clearly this has had an impact on the prediction for the first example. Let's put the label back and then iterate between learning on `ex` and `ex2`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ex prediction = 0.6259561777114868\n",
      "ex2 prediction = -1.4387876987457275\n",
      "ex prediction = 0.7280516624450684\n",
      "ex2 prediction = -1.52095365524292\n",
      "ex prediction = 0.7903025150299072\n",
      "ex2 prediction = -1.5942585468292236\n",
      "ex prediction = 0.8319660425186157\n",
      "ex2 prediction = -1.6564759016036987\n",
      "ex prediction = 0.8618472218513489\n",
      "ex2 prediction = -1.7080860137939453\n",
      "ex prediction = 0.8843045234680176\n",
      "ex2 prediction = -1.7504198551177979\n",
      "ex prediction = 0.9017017483711243\n",
      "ex2 prediction = -1.784990668296814\n",
      "ex prediction = 0.9154171943664551\n",
      "ex2 prediction = -1.813109278678894\n",
      "ex prediction = 0.9263675212860107\n",
      "ex2 prediction = -1.835953950881958\n",
      "ex prediction = 0.935177206993103\n",
      "ex2 prediction = -1.8545048236846924\n"
     ]
    }
   ],
   "source": [
    "ex.set_label_string('1')\n",
    "for i in range(10):\n",
    "    ex.learn()\n",
    "    ex2.learn()\n",
    "    print('ex prediction =', ex.get_updated_prediction())\n",
    "    print('ex2 prediction =', ex2.get_updated_prediction())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "After a handful of updates, we can see that the prediction for `ex` is going back toward `1.0` and for `ex2` back toward `-2.0`.\n",
    "\n",
    "Now that we're done, it's safest to tell VW that we're done with these examples and that it can garbage collect them. (This should happen by default when they pass out of scope per Python's build in garbage collector, but that may not run soon enough if you're manipulating large numbers of examples at once!)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "ex.finish()\n",
    "ex2.finish()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally, when we're done with VW entirely, or perhaps want to start up a new VW instance, it's good behavior to close out any old ones. This is especially important if we wanted to save a model to disk: calling `vw.finish()` tells it to write the file. You can add `f='mymodel'` to the initialization line of the `vw` object if you want to play around with this!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "vw.finish()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This is the end of the intro. For more, look at `test.py` in the `python` directory of the VW distribution; this contains some more examples. For even more, look at the python docs in `pyvw.py`, for instance `help(pyvw.vw)` and so on!\n",
    "\n",
    "Happy VW-Pythoning!"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
