diff --git a/README.md b/README.md index 968632477..fc1b3f734 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ Here is a table of algorithms, the figure, name of the algorithm in the book and | 14.14 | Rejection-Sampling | `rejection_sampling` | [`probability.py`][probability] | Done | Included | | 14.15 | Likelihood-Weighting | `likelihood_weighting` | [`probability.py`][probability] | Done | Included | | 14.16 | Gibbs-Ask | `gibbs_ask` | [`probability.py`][probability] | Done | Included | -| 15.4 | Forward-Backward | `forward_backward` | [`probability.py`][probability] | Done | | +| 15.4 | Forward-Backward | `forward_backward` | [`probability.py`][probability] | Done | Included | | 15.6 | Fixed-Lag-Smoothing | `fixed_lag_smoothing` | [`probability.py`][probability] | Done | | | 15.17 | Particle-Filtering | `particle_filtering` | [`probability.py`][probability] | Done | | | 16.9 | Information-Gathering-Agent | | | | | diff --git a/probability.ipynb b/probability.ipynb index 2fd1c9dae..58bfe9122 100644 --- a/probability.ipynb +++ b/probability.ipynb @@ -11,10 +11,8 @@ }, { "cell_type": "code", - "execution_count": 1, - "metadata": { - "collapsed": true - }, + "execution_count": 6, + "metadata": {}, "outputs": [], "source": [ "from probability import *\n", @@ -34,10 +32,8 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, + "execution_count": 7, + "metadata": {}, "outputs": [], "source": [ "%psource ProbDist" @@ -45,7 +41,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -54,7 +50,7 @@ "0.75" ] }, - "execution_count": 2, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } @@ -74,7 +70,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -83,7 +79,7 @@ "'?'" ] }, - "execution_count": 3, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -95,7 +91,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -104,7 +100,7 @@ "(0.125, 0.375, 0.5)" ] }, - "execution_count": 4, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -122,16 +118,16 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "['high', 'medium', 'low']" + "['low', 'medium', 'high']" ] }, - "execution_count": 5, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -149,7 +145,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -158,7 +154,7 @@ "(50, 114, 64)" ] }, - "execution_count": 6, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -173,7 +169,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -182,7 +178,7 @@ "(0.21929824561403508, 0.5, 0.2807017543859649)" ] }, - "execution_count": 7, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -201,7 +197,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -210,7 +206,7 @@ "'Cat: 0.219, Dog: 0.5, Mice: 0.281'" ] }, - "execution_count": 8, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } @@ -233,7 +229,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -242,7 +238,7 @@ "(8, 10)" ] }, - "execution_count": 9, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } @@ -264,10 +260,8 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, + "execution_count": 16, + "metadata": {}, "outputs": [], "source": [ "%psource JointProbDist" @@ -284,7 +278,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 17, "metadata": {}, "outputs": [ { @@ -293,7 +287,7 @@ "P(['X', 'Y'])" ] }, - "execution_count": 10, + "execution_count": 17, "metadata": {}, "output_type": "execute_result" } @@ -314,7 +308,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 18, "metadata": {}, "outputs": [ { @@ -323,7 +317,7 @@ "(0.2, 0.5)" ] }, - "execution_count": 11, + "execution_count": 18, "metadata": {}, "output_type": "execute_result" } @@ -344,7 +338,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 19, "metadata": {}, "outputs": [ { @@ -353,7 +347,7 @@ "[1, 0]" ] }, - "execution_count": 12, + "execution_count": 19, "metadata": {}, "output_type": "execute_result" } @@ -381,10 +375,8 @@ }, { "cell_type": "code", - "execution_count": 13, - "metadata": { - "collapsed": true - }, + "execution_count": 20, + "metadata": {}, "outputs": [], "source": [ "full_joint = JointProbDist(['Cavity', 'Toothache', 'Catch'])\n", @@ -407,9 +399,118 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 21, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "

\n", + "\n", + "
def enumerate_joint(variables, e, P):\n",
+       "    """Return the sum of those entries in P consistent with e,\n",
+       "    provided variables is P's remaining variables (the ones not in e)."""\n",
+       "    if not variables:\n",
+       "        return P[e]\n",
+       "    Y, rest = variables[0], variables[1:]\n",
+       "    return sum([enumerate_joint(rest, extend(e, Y, y), P)\n",
+       "                for y in P.values(Y)])\n",
+       "
\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "psource(enumerate_joint)" ] @@ -423,7 +524,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 22, "metadata": {}, "outputs": [ { @@ -432,7 +533,7 @@ "0.19999999999999998" ] }, - "execution_count": 15, + "execution_count": 22, "metadata": {}, "output_type": "execute_result" } @@ -453,7 +554,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 23, "metadata": {}, "outputs": [ { @@ -462,7 +563,7 @@ "0.12" ] }, - "execution_count": 16, + "execution_count": 23, "metadata": {}, "output_type": "execute_result" } @@ -485,7 +586,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 24, "metadata": {}, "outputs": [ { @@ -494,7 +595,7 @@ "0.6" ] }, - "execution_count": 17, + "execution_count": 24, "metadata": {}, "output_type": "execute_result" } @@ -512,9 +613,124 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 25, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "

\n", + "\n", + "
def enumerate_joint_ask(X, e, P):\n",
+       "    """Return a probability distribution over the values of the variable X,\n",
+       "    given the {var:val} observations e, in the JointProbDist P. [Section 13.3]\n",
+       "    >>> P = JointProbDist(['X', 'Y'])\n",
+       "    >>> P[0,0] = 0.25; P[0,1] = 0.5; P[1,1] = P[2,1] = 0.125\n",
+       "    >>> enumerate_joint_ask('X', dict(Y=1), P).show_approx()\n",
+       "    '0: 0.667, 1: 0.167, 2: 0.167'\n",
+       "    """\n",
+       "    assert X not in e, "Query variable must be distinct from evidence"\n",
+       "    Q = ProbDist(X)  # probability distribution for X, initially empty\n",
+       "    Y = [v for v in P.variables if v != X and v not in e]  # hidden variables.\n",
+       "    for xi in P.values(X):\n",
+       "        Q[xi] = enumerate_joint(Y, extend(e, X, xi), P)\n",
+       "    return Q.normalize()\n",
+       "
\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "psource(enumerate_joint_ask)" ] @@ -528,7 +744,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 26, "metadata": {}, "outputs": [ { @@ -537,7 +753,7 @@ "(0.6, 0.39999999999999997)" ] }, - "execution_count": 19, + "execution_count": 26, "metadata": {}, "output_type": "execute_result" } @@ -549,6 +765,59 @@ "(ans[True], ans[False])" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Forward-Backward" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Forward-Backward computes posterior probabilities of a sequence of states given a sequence of observations.\n", + "\n", + "We use our umbrella problem to demonstrate the working of forward-backward algorithm. First, we define some variables needed for the algorithm including the prior distribution and evidence." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [], + "source": [ + "umbrella_prior = [0.5, 0.5]\n", + "umbrella_transition = [[0.7, 0.3], [0.3, 0.7]]\n", + "umbrella_sensor = [[0.9, 0.2], [0.1, 0.8]]\n", + "umbrellaHMM = HiddenMarkovModel(umbrella_transition, umbrella_sensor)\n", + "umbrella_evidence = [T, T, F, T, T]\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we pass these variables to our function to see its output:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[0.37454353070020885, 0.6254564692997912], [0.8669704849997415, 0.13302951500025856], [0.8189715306448175, 0.18102846935518252], [0.29952909228489805, 0.700470907715102], [0.790174824393553, 0.20982517560644703], [0.7745321691459525, 0.22546783085404742], [0.18635882675052207, 0.8136411732494779]]\n" + ] + } + ], + "source": [ + "print(forward_backward(umbrellaHMM, umbrella_evidence, umbrella_prior))" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -1503,7 +1772,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.3" + "version": "3.6.4" }, "widgets": { "state": {},