{ "cells": [ { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "# CS 237 Spring 2019\n", "# Author: Alina Ene (aene@bu.edu)\n", "# Used in L26" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "# imports\n", "import numpy as np\n", "from numpy.random import randint\n", "import matplotlib.pyplot as plt\n", "plt.style.use('seaborn')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# CS 237: Reservoir sampling\n", "\n", "This notebook provides a brief introduction to data streams and randomized algorithms. Specifically, we will study the problem of sampling an item uniformly at random from a data stream. The algorithm we will describe is called reservoir sampling and it is an important tool in Computer Science and beyond (see [this wikipedia page](https://en.wikipedia.org/wiki/Reservoir_sampling))." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Data streams\n", "\n", "A data stream is an extremely long sequence of items that you can only read only once, in order. A good example of a data stream is the sequence of packets that pass through a router. Here we will assume that we can get the stream items one by one by calling:\n", "\n", "```\n", "x = next_stream_element() # returns next element in the stream\n", "```\n", "\n", "Here is a small example of a stream that we will use as a test case." ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [], "source": [ "# example stream: 1, 2, 3, ..., 100\n", "N = 0\n", "maxN = 100\n", "\n", "def stream_initialize():\n", " global N\n", " N = 0\n", "\n", "def next_stream_element():\n", " global N, maxN\n", " if N == maxN:\n", " return '#'\n", " N = N + 1\n", " return N\n", "\n", "# try a longer stream (change maxN)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Data stream algorithms\n", "\n", "Data stream algorithms must process each item in the stream quickly, using very little memory; there is simply too much data to store, and it arrives too quickly for any complex computations. Every data stream algorithm looks roughly like this:\n", "\n", "```\n", "def do_something_interesting():\n", " while True:\n", " x = next_stream_element() # returns next element in the stream\n", " if x == '#' # end of stream marker\n", " break\n", " do something interesting with x\n", " return something\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Reservoir sampling algorithm\n", "\n", "The algorithmic task that we want to solve is the following:\n", " > Choose one item uniformly at random from a data stream, **without knowing the length of the stream in advance**\n", "\n", "We now describe an algorithm for this task. Note that the algorithm processes each item very quickly: it spends O(1) time per stream element. It also uses very little memory: it stores only one stream item and a counter that counts the number of stream items that have arrived so far." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "# reservoir sampling algorithm\n", "def stream_sample():\n", " n = 0 # number of stream items seen so far\n", " s = 0 # sampled item\n", " while True:\n", " x = next_stream_element() # get next stream item\n", " if x == '#': # end of stream\n", " break\n", " n = n + 1\n", " r = randint(1, n + 1) # replace s with x with probability 1/n\n", " if r == n: \n", " s = x\n", " return s" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "90\n" ] } ], "source": [ "# trial run on the example stream above\n", "stream_initialize()\n", "print(stream_sample())" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "Let us now test the algorithm. We will perform 10000 trial runs of the reservoir sampling algorithm on the example stream (see above) and plot the empirical distribution of the sampled item. Note that, if the algorithm is correct, the theoretical distribution is uniform over the data stream, i.e., each item has probability 1/n of being sampled, where n is the length of the stream." ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [], "source": [ "# test the reservoir sampling algorithm\n", "def test(num_trials = 100000):\n", " count = {}\n", " x = []\n", " for i in range(num_trials):\n", " stream_initialize()\n", " s = stream_sample()\n", " if s in count:\n", " count[s] = count[s] + 1\n", " else:\n", " x.append(s)\n", " count[s] = 1\n", "\n", " # empirical probabilities \n", " y = [count[s] / num_trials for s in x]\n", " \n", " # plot the probabilities\n", " plt.figure(figsize=(18,5))\n", " plt.bar(x,y)\n", " plt.xlabel(\"Item\")\n", " plt.ylabel(\"Probability\")\n", " plt.plot(x,[1.0/len(x) for i in x], label='1/n', c='r')\n", " plt.title(\"Probability of sampling each item\",fontsize=20)\n", " plt.legend(loc=2)\n", " plt.show()" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "image/png": "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cuVKNWrUSNLvIdegQYOUl5en7t2768Ybb9TJkye1ceNGTZ06VcXFxXrggQck/R44PP7449q+fbtuv/12DRo0SKdPn9bHH3+s3bt367333nN4LS5evFh5eXnq1auXIiIitGnTJr366qs6c+aMPUgrj5K5Vt5++23l5+frscces4+rK+nrhef3zJkz6tOnj3766Sdt3LhRjz76qLp166ZPP/1UPXr0UH5+vtauXavhw4drw4YNF/2OAQC4IQMAABf5+9//blitVmPVqlWlbt+7d68RFBRkBAcHG7/++qthGIaxatUqw2q1GhEREca5c+cc2j/44IOG1Wo1kpOTHda/++67htVqNR588EH7uvHjxxtWq9WIiooyTp8+bV//6aefGoGBgcZ9991nX7do0aJS9/vjjz8aLVu2NMLDw+3rSuoLCgoyvv76a/v6o0ePGuHh4UZISIhx5swZ+zqr1WrEx8fb2z3wwAOG1Wots03JMZYsWWJf99lnnxlWq9WYPHmyQ40ff/yxYbVajWXLlpV2iq/q3O3evduwWq3GjBkzytynYRjGgAEDjJCQECM7O9u+Ljs72wgPDzc6dOhg2Gw2wzCu7ByXHP/Pf/6zwzleuXKlYbVaDavVamzdutW+Pi0tzbBarcbTTz9tX1cy9kJDQ40jR47Y12dkZBhBQUFGZGSkUVRU5ND2k08+sbfr2rWrERYWZl8ueU7CwsKMw4cP29cfPXrUaNGihdG5c2f7ug0bNhhWq9V44oknjIKCAvv6ZcuW2es/evRomed16tSppT6vKSkphtVqNZ566in7uueff96wWq3Gzp07Hdru2bPHsFqtDmP9X//6l/3x+fn59vUffvihYbVajRdeeMGhvyEhIcbBgwft7U6cOGEEBwcbbdu2NYqLi8vsQ8lr8D//+Y993R/P65X2teS56tq1q/01ZBiG8cwzz9if7xMnTtjXz58/37Barca7775bZq0AAPfAFRQAAJdLSUnR8ePH7ctFRUU6dOiQPv30UxUVFWnSpEmqX7++w2M6d+6s6667zr584sQJ7d69W23bttXgwYMd2sbGxur999/X7t27dezYMd100032bU888YTq1q3rsN/w8HDt2LHD3rZjx47y9/dX//79HfZ744036uabby711ol7773XfgWGJN1000168MEHNWfOHKWkpJQ6Kei1aN++vZo2baoNGzboueeeU40aNSRJa9euVY0aNdS7d+9LPvZqz115GIah8+fP6z//+Y/atWsnSfL19dV7770nf39/eXh4SNJVneOwsDCHcxwaGipJatasmbp06WJf37p1a0lyGGMlHnjgAQUEBDi07d27t9auXauMjAyFhYVdUX/vvvtu3XLLLfblm266Sc2bN1dmZqby8/NVs2ZNffDBB5Kk8ePH258nSbr//vu1dOlSHTp0qMxjFBUVafXq1frTn/6koUOHOmyLjIxUaGioPvnkE+Xk5MjX11f33nuvgoOD9Ze//MWhbXBwsGrVquVwm8RHH30kSZo0aZK8vb3t6/v06aP//ve/CgwMdNhHr169HL5hpnHjxmrRooXS09N15syZa56n5Er7WiI6Olr+/v725dDQUK1bt059+vRxuFIiODhYUuljAwDgfggoAAAut3nzZm3evNm+XKNGDdWtW1fh4eEaOnRoqZfa//EbPf7zn/9IksO8ABcKDQ3V119/rczMTIcP2SUfai8UHBysHTt22NsGBQUpKChIubm52rNnj44cOaLDhw/r66+/1pEjRy6aX+BS+23VqpUkKTMzs9Qar4WHh4f69u2rN954Qzt37lSXLl3022+/afv27YqIiCjzg+LVnrvyuO+++zRlyhTFxcUpMDBQERER6ty5s8LCwuTp+b+prq7mHF8YBEiyB1Z/rLFmzZqSVOrXgpaEJhcKDg7W2rVrlZmZecUBRWm30fj5+dmPX7NmTe3bt09169Z1CEYkydPTU23atLlsQHHo0CGdO3dOxcXFmj9//kXb8/PzVVxcrP379yssLExt27ZV27Zt9dtvv+nbb7/VDz/8oEOHDikjI8PetkRmZqaaNGly0e0OHh4epX7Vb2n9LQn8zp07d80BxZX2tcQfz+3VjA0AgPshoAAAuFxCQsIVX1FQ8sGiRE5OjqT/fRj8o5J71M+fP++w/vrrr7+orY+Pj6TfP2BJv38Imjt3rpKSkpSXlyfp978U33nnnapXr55OnTp10T7Ks19n69+/v9544w2tW7dOXbp00fr161VYWKh+/fqV+birPXflMWTIEF1//fV65513lJ6erv3792vx4sVq3LixJkyYYL+y42rO8YVX0Fzowr/8X05p8w40aNBA0v/Oy5Uo7dglV4kY/39S0NOnT6tZs2alPv6PcymU5uzZs5J+/7rX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I0eOdG6RAAAAAADALbjsWzwAAAAAAADKi4ACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYjoACAAAAAACYzuKqHdtsNk2dOlX79++Xt7e3ZsyYoVtuucW+PTk5WStXrpTFYlF8fLy6du2qrKwsjR07VufPn1ejRo2UkJCg6667Tm+99ZY++ugjSVLnzp315JNPuqpsAAAAAABgApddQZGSkqKCggIlJSVpzJgxmjVrln3bqVOntHTpUq1cuVKJiYmaO3euCgoKtGDBAt1zzz1avny5goKClJSUpKNHj2rt2rVauXKlkpKStGPHDmVmZrqqbAAAAAAAYAKXBRTp6enq1KmTJCkkJET79u2zb9u7d6/atGkjb29v+fn5KSAgQJmZmQ6PiYiI0K5du3TDDTfon//8p7y8vOTp6amioiLVrFnTVWUDAAAAAAATuOwWj5ycHPn6+tqXvby8VFRUJIvFopycHPn5+dm3+fj4KCcnx2G9j4+PsrOzVaNGDdWvX1+GYWj27NkKCgpSs2bNyjx2vXq1ZbF4uaZjTtKwod/lG11he2e1qejjuVsbd6yJ/tM3Z7Rxx5roP31zRht3rIn+039ntHHHmug//XdGG3esqSr3vzJxWUDh6+ur3Nxc+7LNZpPFYil1W25urvz8/Ozra9WqpdzcXPn7+0uS8vPzNWnSJPn4+GjKlCmXPfbp0+ec3BvnatjQT6dOZV/RY8rT3lltKvp47tbGHWui//TNGW3csSb6T9+c0cYda6L/9N8ZbdyxJvpP/53Rxh1rqsr9d0eX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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "test()" ] } ], "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.6.8" } }, "nbformat": 4, "nbformat_minor": 2 }