{ "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Factor Graphs" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "\n", "### Preliminaries\n", "\n", "- Goal \n", " - Introduction to Forney-style factor graphs and message passing algorithms\n", "- Materials \n", " - Mandatory\n", " - These lecture notes \n", " - [Loeliger, 2007](./files/Loeliger-2007-The-factor-graph-approach-to-model-based-signal-processing.pdf), pp. 1295-1300 (until section IV)\n", " - Optional\n", " - [Video lecture](https://www.youtube.com/watch?v=Fv2YbVg9Frc&t=31) by Frederico Wadehn (ETH Zurich) (**highly recommended**)\n", " \n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Why Factor Graphs?\n", "\n", "- A probabilistic inference task gets its computational load mainly through the need for marginalization (i.e., computing integrals). E.g., for a generative model $p(x_1,x_2,x_3,x_4,x_5)$, the inference task $p(x_2|x_3)$ is given by \n", "\n", "$$\\begin{align*}\n", "p(x_2|x_3) = \\frac{\\int p(x_1,x_2,x_3,x_4,x_5) \\, \\mathrm{d}x_1 \\mathrm{d}x_4 \\mathrm{d}x_5}{\\int p(x_1,x_2,x_3,x_4,x_5) \\, \\mathrm{d}x_1 \\mathrm{d}x_2 \\mathrm{d}x_4 \\mathrm{d}x_5}\n", "\\end{align*}$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- Since these computations suffer from the \"curse of dimensionality\", we often need to solve a simpler problem in order to get an answer. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- Factor graphs provide an computationally efficient approach to solving inference problems **if the generative distribution can be factorized**. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- Factorization helps. For instance, if $p(x_1,x_2,x_3,x_4,x_5) = p(x_1)p(x_2,x_3)p(x_4)p(x_5|x_4)$, then\n", "$$\\begin{align*}\n", "p(x_2|x_3) &= \\frac{\\int p(x_1)p(x_2,x_3)p(x_4)p(x_5|x_4) \\, \\mathrm{d}x_1 \\mathrm{d}x_4 \\mathrm{d}x_5}{\\int p(x_1)p(x_2,x_3)p(x_4)p(x_5|x_4) \\, \\mathrm{d}x_1 \\mathrm{d}x_2 \\mathrm{d}x_4 \\mathrm{d}x_5} \n", " = \\frac{p(x_2,x_3)}{\\int p(x_2,x_3) \\mathrm{d}x_2}\n", "\\end{align*}$$\n", "which is computationally much cheaper than the general case above." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- In this lesson, we discuss how computationally efficient inference in factorized probability distributions can be automated." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Factor Graph Construction Rules\n", "\n", "- Consider a function \n", "$$\n", "f(x_1,x_2,x_3,x_4,x_5) = f_a(x_1,x_2,x_3) \\cdot f_b(x_3,x_4,x_5) \\cdot f_c(x_4)\n", "$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- The factorization of this function can be graphically represented by a **Forney-style Factor Graph** (FFG):\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- An FFG is an **undirected** graph subject to the following construction rules ([Forney, 2001](http://ieeexplore.ieee.org/xpl/login.jsp?tp=&arnumber=910573&url=http%3A%2F%2Fieeexplore.ieee.org%2Fiel5%2F18%2F19638%2F00910573.pdf%3Farnumber%3D910573))\n", "\n", " 1. A **node** for every factor;\n", " 1. An **edge** (or **half-edge**) for every variable;\n", " 1. Node $g$ is connected to edge $x$ **iff** variable $x$ appears in factor $g$." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Some FFG Terminology\n", "\n", "- $f$ is called the **global function** and $f_\\bullet$ are the **factors**. \n", "\n", "- A **configuration** is an assigment of values to all variables.\n", "\n", "- The **configuration space** is the set of all configurations, i.e., the domain of $f$\n", "\n", "- A configuration $\\omega=(x_1,x_2,x_3,x_4,x_5)$ is said to be **valid** iff $f(\\omega) \\neq 0$\n", " " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Equality Nodes for Branching Points\n", "\n", "\n", "- Note that a variable can appear in maximally two factors in an FFG (since an edge has only two end points)." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- Consider the factorization (where $x_2$ appears in three factors) \n", "\n", "$$\n", " f(x_1,x_2,x_3,x_4) = f_a(x_1,x_2)\\cdot f_b(x_2,x_3) \\cdot f_c(x_2,x_4)\n", "$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- For the factor graph representation, we will instead consider the function $g$, defined as\n", "$$\\begin{align*}\n", " g(x_1,x_2&,x_2^\\prime,x_2^{\\prime\\prime},x_3,x_4) \n", " = f_a(x_1,x_2)\\cdot f_b(x_2^\\prime,x_3) \\cdot f_c(x_2^{\\prime\\prime},x_4) \\cdot f_=(x_2,x_2^\\prime,x_2^{\\prime\\prime})\n", "\\end{align*}$$\n", " where \n", "$$\n", "f_=(x_2,x_2^\\prime,x_2^{\\prime\\prime}) \\triangleq \\delta(x_2-x_2^\\prime)\\, \\delta(x_2-x_2^{\\prime\\prime})\n", "$$\n", "\n", " \n", " " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Equality Nodes for Branching Points, cont'd\n", "\n", "- Note that through introduction of auxiliary variables $X_2^\\prime$ and $X_2^{\\prime\\prime}$ each variable in $g$ appears in maximally two factors. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- The constraint $f_=(x,x^\\prime,x^{\\prime\\prime})$ enforces that $X=X^\\prime=X^{\\prime\\prime}$ **for every valid configuration**." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- Since $f$ is a marginal of $g$, i.e., \n", "$$\n", "f(x_1,x_2,x_3,x_4) = \\int g(x_1,x_2,x_2^\\prime,x_2^{\\prime\\prime},x_3,x_4)\\, \\mathrm{d}x_2^\\prime \\mathrm{d}x_2^{\\prime\\prime}\n", "$$\n", "it follows that any inference problem on $f$ can be executed by a corresponding inference problem on $g$, e.g.,\n", "$$\\begin{align*}\n", "f(x_1 \\mid x_2) &\\triangleq \\frac{\\int f(x_1,x_2,x_3,x_4) \\,\\mathrm{d}x_3 \\mathrm{d}x_4 }{ \\int f(x_1,x_2,x_3,x_4) \\,\\mathrm{d}x_1 \\mathrm{d}x_3 \\mathrm{d}x_4} \\\\\n", " &= \\frac{\\int g(x_1,x_2,x_2^\\prime,x_2^{\\prime\\prime},x_3,x_4) \\,\\mathrm{d}x_2^\\prime \\mathrm{d}x_2^{\\prime\\prime} \\mathrm{d}x_3 \\mathrm{d}x_4 }{ \\int g(x_1,x_2,x_2^\\prime,x_2^{\\prime\\prime},x_3,x_4) \\,\\mathrm{d}x_1 \\mathrm{d}x_2^\\prime \\mathrm{d}x_2^{\\prime\\prime} \\mathrm{d}x_3 \\mathrm{d}x_4} \\\\\n", " &\\triangleq g(x_1 \\mid x_2)\n", "\\end{align*}$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- $\\Rightarrow$ **Any factorization of a global function $f$ can be represented by a Forney-style Factor Graph**." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Probabilistic Models as Factor Graphs\n", "\n", "- FFGs can be used to express conditional independence (factorization) in probabilistic models. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- For example, the (previously shown) graph for \n", "$f_a(x_1,x_2,x_3) \\cdot f_b(x_3,x_4,x_5) \\cdot f_c(x_4)$ \n", "could represent the probabilistic model\n", "$$\n", "p(x_1,x_2,x_3,x_4,x_5) = p(x_1,x_2|x_3) \\cdot p(x_3,x_5|x_4) \\cdot p(x_4)\n", "$$\n", "where we identify \n", "$$\\begin{align*}\n", "f_a(x_1,x_2,x_3) &= p(x_1,x_2|x_3) \\\\\n", "f_b(x_3,x_4,x_5) &= p(x_3,x_5|x_4) \\\\\n", "f_c(x_4) &= p(x_4)\n", "\\end{align*}$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- This is the graph\n", "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Inference by Closing Boxes\n", "\n", "- Factorizations provide opportunities to cut on the amount of needed computations when doing inference. In what follows, we will use FFGs to process these opportunities in an automatic way (i.e., by message passing). " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- Assume we wish to compute the marginal\n", "$$\n", "\\bar{f}(x_3) = \\sum_{x_1,x_2,x_4,x_5,x_6,x_7}f(x_1,x_2,\\ldots,x_7)\n", "$$\n", "where $f$ is factorized as given by the following FFG\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- Due to the factorization, we can decompose this sum by the **distributive law** as\n", "$$\\begin{align*}\n", "\\bar{f}(x_3) = & \\underbrace{ \\left( \\sum_{x_1,x_2} f_a(x_1)\\,f_b(x_2)\\,f_c(x_1,x_2,x_3)\\right) }_{\\overrightarrow{\\mu}_{X_3}(x_3)} \\\\\n", " & \\underbrace{ \\cdot\\left( \\sum_{x_4,x_5} f_d(x_4)\\,f_e(x_3,x_4,x_5) \\cdot \\underbrace{ \\left( \\sum_{x_6,x_7} f_f(x_5,x_6,x_7)\\,f_g(x_7)\\right) }_{\\overleftarrow{\\mu}_{X_5}(x_5)} \\right) }_{\\overleftarrow{\\mu}_{X_3}(x_3)}\n", "\\end{align*}$$\n", "which is computationally (much) lighter than executing the full sum $\\sum_{x_1,\\ldots,x_7}f(x_1,x_2,\\ldots,x_7)$\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- Messages may flow in both directions on any edge (here on $X_3$). We often draw _directed edges_ in a FFG in order to distinguish forward messages $\\overrightarrow{\\mu}_\\bullet(\\cdot)$ (in the same direction as the arrow of the edge) from backward messages $\\overleftarrow{\\mu}_\\bullet(\\cdot)$ (in opposite direction). With directed edges, the FFG looks as follows: \n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- Crucially, drawing arrows on edges is only meant as a notational convenience. Technically, an FFG is an undirected graph. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- Note that $\\overleftarrow{\\mu}_{X_5}(x_5)$ is obtained by multiplying all enclosed factors ($f_f$, $f_g$) by the green dashed box, followed by marginalization over all enclosed variables ($x_6$, $x_7$). " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- This is the **Closing the Box**-rule, which is a general recipe for marginalization of hidden variables and leads to a new factor with outgoing (sum-product) message \n", "$$ \\mu_{\\text{SP}} = \\sum_{ \\stackrel{ \\textrm{enclosed} }{ \\textrm{variables} } } \\;\\prod_{\\stackrel{ \\textrm{enclosed} }{ \\textrm{factors} }}\n", "$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Evaluating the closing-the-box rule for individual nodes\n", " \n", "\n", "- First, closing a box around the **terminal nodes** leads to $\\overrightarrow{\\mu}_{X_1}(x_1) \\triangleq f_a(x_1)$, $\\overrightarrow{\\mu}_{X_2}(x_2) \\triangleq f_b(x_2)$ etc. \n", " - So, the message out of a terminal node is the factor itself.\n", " - (Exercise) Derive now that the message coming from the open end of a half-edge always equals $1$. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- The messages from **internal nodes** evaluate to:\n", "$$\\begin{align*}\n", "\\overrightarrow{\\mu}_{X_3}(x_3) &= \\sum_{x_1,x_2} f_a(x_1) \\,f_b(x_2) \\,f_c(x_1,x_2,x_3) \\\\\n", " &= \\sum_{x_1,x_2} \\overrightarrow{\\mu}_{X_1}(x_1) \\overrightarrow{\\mu}_{X_2}(x_2) \\,f_c(x_1,x_2,x_3) \\\\\n", "\\overleftarrow{\\mu}_{X_5}(x_5) &= \\sum_{x_6,x_7} f_f(x_5,x_6,x_7)\\,f_g(x_7) \\\\\n", " &= \\sum_{x_6,x_7} \\overrightarrow{\\mu}_{X_7}(x_7)\\, f_f(x_5,x_6,x_7) \\\\\n", "\\end{align*}$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- Crucially, all message update rules can be computed from information that is **locally available** at each node." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Sum-Product Algorithm\n", "\n", "- (**Sum-Product update rule**). This recursive pattern for computing messages applies generally and is called the **Sum-Product update rule**, which is really just a special case of the closing-the-box rule: For any node, the outgoing message is obtained by taking the product of all incoming messages and the node function, followed by summing out (marginalization) all incoming variables. What is left (the outgoing message) is a function of the outgoing variable only: \n", "\n", "$$ \\boxed{\n", "\\overrightarrow{\\mu}_{Y}(y) = \\sum_{x_1,\\ldots,x_n} \\overrightarrow{\\mu}_{X_1}(x_1)\\cdots \\overrightarrow{\\mu}_{X_n}(x_n) \\,f(y,x_1,\\ldots,x_n) }\n", "$$\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- (**Sum-Product Theorem**). If the factor graph for a function $f$ has **no cycles**, then the marginal $\\bar{f}(x_3) = \\sum_{x_1,x_2,x_4,x_5,x_6,x_7}f(x_1,x_2,\\ldots,x_7)$ is given by the Sum-Product Theorem:\n", "\n", "$$ \\boxed{\n", "\\bar{f}(x_3) = \\overrightarrow{\\mu}_{X_3}(x_3)\\cdot \\overleftarrow{\\mu}_{X_3}(x_3)}\n", "$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- (**Sum-Product Algorithm**). If folows that the marginal $\\bar{f}(x_3) = \\sum_{x_1,x_2,x_4,x_5,x_6,x_7}f(x_1,x_2,\\ldots,x_7)$ can be efficiently computed through sum-product messages. Executing inference through SP message passing is called the **Sum-Product Algorithm**." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- (Exercise) Verfiy for yourself that all maginals in a cycle-free graph (a tree) can be computed exactly by starting with messages at the terminals and working towards the root of the tree." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Processing Observations in a Factor Graph\n", "\n", " - Terminal nodes can be used describe **observed variables**, e.g., use a factor $$f_Y(y) = \\delta(y-3)$$ to terminate the edge for variable $Y$ if $y=3$ is observed.\n", " " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ " \n", " ##### Example\n", " \n", " - Consider a generative model \n", "$$p(x,y_1,y_2) = p(x)\\,p(y_1|x)\\,p(y_2|x) .$$ \n", " - This model expresses the assumption that $Y_1$ and $Y_2$ are independent measurements of $X$.\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ " \n", "- Assume that we are interested in the posterior for $X$ after observing $Y_1= \\hat y_1$ and $Y_2= \\hat y_2$. The posterior for $X$ can be inferred by applying the sum-product algorithm to the following graph:\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ " - (Note that) we usually draw terminal nodes for observed variables in the graph by smaller solid-black squares. This is just to help the visualization of the graph, since the computational rules are no different than for other nodes. " ] }, { "cell_type": "markdown", "metadata": { "collapsed": true, "slideshow": { "slide_type": "fragment" } }, "source": [ "- (Exercise) Can you draw the messages that infer $p(x\\,|\\,y_1,y_2)$?" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "#### CODE EXAMPLE\n", "\n", "We'll use ForneyLab, a factor graph toolbox for Julia, to build the above graph, and perform sum-product message passing to infer the posterior $p(x|y_1,y_2)$. We assume $p(y_1|x)$ and $p(y_2|x)$ to be Gaussian likelihoods with known variances:\n", "$$\\begin{align*}\n", " p(y_1\\,|\\,x) &= \\mathcal{N}(y_1\\,|\\,x, v_{y1}) \\\\\n", " p(y_2\\,|\\,x) &= \\mathcal{N}(y_2\\,|\\,x, v_{y2})\n", "\\end{align*}$$\n", "Under this model, the posterior is given by:\n", "$$\\begin{align*}\n", " p(x\\,|\\,y_1,y_2) &\\propto \\overbrace{p(y_1\\,|\\,x)\\,p(y_2\\,|\\,x)}^{\\text{likelihood}}\\,\\overbrace{p(x)}^{\\text{prior}} \\\\\n", " &=\\mathcal{N}(x\\,|\\,\\hat{y}_1, v_{y1})\\, \\mathcal{N}(x\\,|\\,\\hat{y}_2, v_{y2}) \\, \\mathcal{N}(x\\,|\\,m_x, v_x) \n", "\\end{align*}$$\n", "so we can validate the answer by solving the Gaussian multiplication manually." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Sum-product message passing result: p(x|y1,y2) = 𝒩(m=1.14, v=0.57)\n", "\n", "Manual result: p(x|y1,y2) = N(m=1.14, V=0.57)\n" ] } ], "source": [ "using ForneyLab # version 0.7.1\n", "\n", "# Data\n", "y1_hat = 1.0\n", "y2_hat = 2.0\n", "\n", "# Construct the factor graph\n", "fg = FactorGraph()\n", "@RV x ~ GaussianMeanVariance(constant(0.0), constant(4.0), id=:x) # Node p(x)\n", "@RV y1 ~ GaussianMeanVariance(x, constant(1.0)) # Node p(y1|x)\n", "@RV y2 ~ GaussianMeanVariance(x, constant(2.0)) # Node p(y2|x)\n", "Clamp(y1, y1_hat) # Terminal (clamp) node for y1\n", "Clamp(y2, y2_hat) # Terminal (clamp) node for y2\n", "# draw(fg) # draw the constructed factor graph\n", "\n", "# Perform sum-product message passing\n", "eval(parse(sumProductAlgorithm(x, name=\"_algo1\"))) # Automatically derives a message passing schedule\n", "x_marginal = step_algo1!(Dict())[:x] # Execute algorithm and collect marginal distribution of x\n", "println(\"Sum-product message passing result: p(x|y1,y2) = $(x_marginal)\")\n", "\n", "# Calculate mean and variance of p(x|y1,y2) manually by multiplying 3 Gaussians (see lesson 4 for details)\n", "v = 1 / (1/4 + 1/1 + 1/2)\n", "m = v * (0/4 + y1_hat/1.0 + y2_hat/2.0)\n", "println(\"Manual result: p(x|y1,y2) = N(m=$(round(m,2)), V=$(round(v,2)))\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Example: SP Messages for the Equality Node\n", "\n", "- Let´s compute the SP messages for the **equality node** $f_=(x,y,z) = \\delta(z-x)\\delta(z-y)$: \n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "$$\\begin{align*}\n", "\\overrightarrow{\\mu}_{Z}(z) &= \\int \\overrightarrow{\\mu}_{X}(x) \\overrightarrow{\\mu}_{Y}(y) \\,\\delta(z-x)\\delta(z-y) \\,\\mathrm{d}x \\mathrm{d}y \\\\\n", " &= \\overrightarrow{\\mu}_{X}(z) \\int \\overrightarrow{\\mu}_{Y}(y) \\,\\delta(z-y) \\,\\mathrm{d}y \\\\\n", " &= \\overrightarrow{\\mu}_{X}(z) \\overrightarrow{\\mu}_{Y}(z) \n", "\\end{align*}$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- By symmetry, this also implies (for the same equality node) that\n", "\n", "$$\\begin{align*}\n", "\\overleftarrow{\\mu}_{X}(x) &= \\overrightarrow{\\mu}_{Y}(x) \\overleftarrow{\\mu}_{Z}(x) \\quad \\text{and} \\\\\n", "\\overleftarrow{\\mu}_{Y}(y) &= \\overrightarrow{\\mu}_{X}(y) \\overleftarrow{\\mu}_{Z}(y)\\,.\n", "\\end{align*}$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- Let us now consider the case of Gaussian messages $\\overrightarrow{\\mu}_{X}(x) = \\mathcal{N}(\\overrightarrow{m}_X,\\overrightarrow{V}_X)$, $\\overrightarrow{\\mu}_{Y}(y) = \\mathcal{N}(\\overrightarrow{m}_Y,\\overrightarrow{V}_Y)$ and $\\overrightarrow{\\mu}_{Z}(z) = \\mathcal{N}(\\overrightarrow{m}_Z,\\overrightarrow{V}_Z)$. Let´s also define the precision matrices $\\overrightarrow{W}_X \\triangleq \\overrightarrow{V}_X^{-1}$ and similarly for $Y$ and $Z$. Then applying the SP update rule leads to multiplication of two Gaussian distributions, resulting in \n", "\n", "$$\\begin{align*}\n", "\\overrightarrow{W}_Z &= \\overrightarrow{W}_X + \\overrightarrow{W}_Y \\\\ \n", "\\overrightarrow{W}_Z \\overrightarrow{m}_z &= \\overrightarrow{W}_X \\overrightarrow{m}_X + \\overrightarrow{W}_Y \\overrightarrow{m}_Y\n", "\\end{align*}$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- It follows that **message passing through an equality node is similar to applying Bayes rule**, i.e., fusion of two information sources. Does this make sense?" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### (OPTIONAL SLIDE) Example: SP Messages for the Addition Nodes\n", "\n", "- Next, consider an **addition node** $f_+(x,y,z) = \\delta(z-x-y)$: \n", "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "$$\\begin{align*}\n", "\\overrightarrow{\\mu}_{Z}(z) &= \\int \\overrightarrow{\\mu}_{X}(x) \\overrightarrow{\\mu}_{Y}(y) \\,\\delta(z-x-y) \\,\\mathrm{d}x \\mathrm{d}y \\\\\n", " &= \\int \\overrightarrow{\\mu}_{X}(z) \\overrightarrow{\\mu}_{Y}(z-x) \\,\\mathrm{d}x \\,, \n", "\\end{align*}$$\n", "i.e., $\\overrightarrow{\\mu}_{Z}$ is the convolution of the messages $\\overrightarrow{\\mu}_{X}$ and $\\overrightarrow{\\mu}_{Y}$." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- Of course, for Gaussian messages, these update rules evaluate to\n", "\n", "$$\\begin{align*}\n", "\\overrightarrow{m}_Z = \\overrightarrow{m}_X + \\overrightarrow{m}_Y \\,,\\,\\text{and}\\,\\,\\overrightarrow{V}_z = \\overrightarrow{V}_X + \\overrightarrow{V}_Y \\,.\n", "\\end{align*}$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "-
Exercise: For the same summation node, work out the SP update rule for the *backward* message $\\overleftarrow{\\mu}_{X}(x)$ as a function of $\\overrightarrow{\\mu}_{Y}(y)$ and $\\overleftarrow{\\mu}_{Z}(z)$? And further refine the answer for Gaussian messages.
" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### (OPTIONAL SLIDE) Example: SP Messages for Multiplication Nodes\n", "\n", "- Next, let us consider a **multiplication** by a fixed (invertable matrix) gain $f_A(x,y) = \\delta(y-Ax)$\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "$$\\begin{align*}\n", "\\overrightarrow{\\mu}_{Y}(y) = \\int \\overrightarrow{\\mu}_{X}(x) \\,\\delta(y-Ax) \\,\\mathrm{d}x = \\overrightarrow{\\mu}_{X}(A^{-1}y) \\,.\n", "\\end{align*}$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- For a Gaussian message input message $\\overrightarrow{\\mu}_{X}(x) = \\mathcal{N}(\\overrightarrow{m}_{X},\\overrightarrow{V}_{X})$, the output message is also Gaussian with \n", "$$\\begin{align*}\n", "\\overrightarrow{m}_{Y} = A\\overrightarrow{m}_{X} \\,,\\,\\text{and}\\,\\,\n", "\\overrightarrow{V}_{Y} = A\\overrightarrow{V}_{X}A^T\n", "\\end{align*}$$\n", "since \n", "$$\\begin{align*}\n", "\\overrightarrow{\\mu}_{Y}(y) &= \\overrightarrow{\\mu}_{X}(A^{-1}y) \\\\\n", " &\\propto \\exp \\left( -\\frac{1}{2} \\left( A^{-1}y - \\overrightarrow{m}_{X}\\right)^T \\overrightarrow{V}_{X}^{-1} \\left( A^{-1}y - \\overrightarrow{m}_{X}\\right)\\right) \\\\\n", " &= \\exp \\left( -\\frac{1}{2} \\left( y - A\\overrightarrow{m}_{X}\\right)^T A^{-T}\\overrightarrow{V}_{X}^{-1} A \\left( y - A\\overrightarrow{m}_{X}\\right)\\right) \\\\\n", " &\\propto \\mathcal{N}(A\\overrightarrow{m}_{X},A\\overrightarrow{V}_{X}A^T) \\,.\n", "\\end{align*}$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "-
Excercise: Proof that, for the same factor $\\delta(y-Ax)$ and Gaussian messages, the (backward) sum-product message $\\overleftarrow{\\mu}_{X}$ is given by \n", "$$\\begin{align*}\n", "\\overleftarrow{\\xi}_{X} &= A^T\\overleftarrow{\\xi}_{Y} \\\\\n", "\\overleftarrow{W}_{X} &= A^T\\overleftarrow{W}_{Y}A\n", "\\end{align*}$$\n", "where $\\overleftarrow{\\xi}_X \\triangleq \\overleftarrow{W}_X \\overleftarrow{m}_X$ and $\\overleftarrow{W}_{X} \\triangleq \\overleftarrow{V}_{X}^{-1}$ (and similarly for $Y$).
" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "#### CODE EXAMPLE\n", "\n", "Let's calculate the Gaussian forward and backward messages for the addition node in ForneyLab. " ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Forward message on Z: 𝒩(m=3.00, v=2.00)\n", "Backward message on X: 𝒩(m=1.00, v=2.00)\n" ] } ], "source": [ "# Forward message towards Z\n", "fg = FactorGraph()\n", "@RV x ~ GaussianMeanVariance(constant(1.0), constant(1.0), id=:x) \n", "@RV y ~ GaussianMeanVariance(constant(2.0), constant(1.0), id=:y)\n", "@RV z = x + y; z.id = :z\n", "\n", "eval(parse(sumProductAlgorithm(z, name=\"_z_fwd\")))\n", "msg_forward_Z = step_z_fwd!(Dict())[:z]\n", "print(\"Forward message on Z: $(msg_forward_Z)\")\n", "\n", "# Backward message towards X\n", "fg = FactorGraph()\n", "@RV x = Variable(id=:x)\n", "@RV y ~ GaussianMeanVariance(constant(2.0), constant(1.0), id=:y)\n", "@RV z = x + y\n", "GaussianMeanVariance(z, constant(3.0), constant(1.0), id=:z) \n", "\n", "eval(parse(sumProductAlgorithm(x, name=\"_x_bwd\")))\n", "msg_backward_X = step_x_bwd!(Dict())[:x]\n", "print(\"Backward message on X: $(msg_backward_X)\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "#### CODE EXAMPLE\n", "\n", "In the same way we can also investigate the forward and backward messages for the gain node " ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Forward message on Y: 𝒩(m=4.00, v=16.00)\n" ] } ], "source": [ "# Forward message towards Y\n", "fg = FactorGraph()\n", "@RV x ~ GaussianMeanVariance(constant(1.0), constant(1.0), id=:x)\n", "@RV y = constant(4.0) * x; y.id = :y\n", "\n", "eval(parse(sumProductAlgorithm(y, name=\"_y_fwd\")))\n", "msg_forward_Y = step_y_fwd!(Dict())[:y]\n", "print(\"Forward message on Y: $(msg_forward_Y)\")" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Backward message on X: 𝒩(m=0.50, v=0.06)\n" ] } ], "source": [ "# Backward message towards X\n", "fg = FactorGraph()\n", "x = Variable(id=:x)\n", "@RV y = constant(4.0) * x\n", "GaussianMeanVariance(y, constant(2.0), constant(1.0))\n", "\n", "eval(parse(sumProductAlgorithm(x, name=\"_x_fwd2\")))\n", "msg_backward_X = step_x_fwd2!(Dict())[:x]\n", "print(\"Backward message on X: $(msg_backward_X)\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Example: Bayesian Linear Regression\n", "\n", "- Recall: the goal of regression is to estimate an unknown function from a set of (noisy) function values." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- Assume we want to estimate some function $f: \\mathbb{R}^D \\rightarrow \\mathbb{R}$ from data set $D = \\{(x_1,y_1), \\ldots, (x_N,y_N)\\}$, where $y_i = f(x_i) + \\epsilon_i$." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- We will assume a linear model with white Gaussian noise adn a Gaussian prior on the coefficients $w$:\n", "$$\\begin{align*}\n", " y_i &= w^T x_i + \\epsilon_i \\\\\n", " \\epsilon_i &\\sim \\mathcal{N}(0, \\sigma^2) \\\\ \n", " w &\\sim \\mathcal{N}(0,\\Sigma)\n", "\\end{align*}$$\n", "or equivalently\n", "$$\\begin{align*}\n", "p(D,w) &= \\overbrace{p(w)}^{\\text{weight prior}} \\prod_{i=1}^N \\overbrace{p(y_i\\,|\\,x_i,w,\\epsilon_i)}^{\\text{regression model}} \\overbrace{p(\\epsilon_i)}^{\\text{noise model}} \\\\\n", " &= \\mathcal{N}(w\\,|\\,0,\\Sigma) \\prod_{i=1}^N \\delta(y_i - w^T x_i - \\epsilon_i) \\mathcal{N}(\\epsilon_i\\,|\\,0,\\sigma^2) \n", "\\end{align*}$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- We are interested in inferring the posterior $p(w|D)$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- Here's the factor graph for this model\n", "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "#### CODE EXAMPLE\n", "\n", "Let's build the factor graph in Julia (with the FFG toolbox ForneyLab)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "image/png": "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maIRI0ZoxowZ6tSpk7xery5cuKDly5eHuzwE0Jdffqlbb71ViYmJevTRR9WtWzdt27ZNr732mr73ve9p48aN4S4RLXTw4EENGDBA/fr100033aQ//elPeu211xq9HrmkpETDhw9XYmKi8vPzVVFRoRUrVqhfv37asWOH2rQx8OI6Hwz76KOPfCaTyffMM8/Ur1VXV/vMZrNvzJgxYawMwbBt2zbfuXPnGqy53W5fhw4dfDabLUxVIRRmzJjhs1qtvgkTJvhuvfXWcJeDIDh16pTvhhtu8E2dOjXcpSAEli1b5ouLi/Pt27evwfqDDz7oi4uL8504cSJMlcFfZ8+e9R09etTn8/l8O3fu9JlMJt/vfve7Ruf96Ec/8iUkJPi+/PLL+jWn0+kzmUy+V155xdA9aedogfXr16tNmzaaM2dO/Vr79u01e/Zsbdu2TSUlJWGsDoGWlpbW6P+Zms1mDRkyhHHvUWzLli3asGGDnn322XCXgiB6/fXX9fXXX2vZsmWSpH/84x/y8Re0UauiokKS1LNnzwbrN9xwg+Li4tSuXbtwlIUAaNu2baPv9Uo2bNigyZMnq3fv3vVr99xzjywWi9auXWvonoToFtizZ48sFos6derUYH306NH1xxH9jh49qu7du4e7DATBhQsXlJeXpzlz5mjIkCHhLgdB9P7776tLly46fPiwBg0apE6dOqlLly768Y9/rDNnzoS7PATYhAkT5PP59PDDD2vv3r368ssv9eabb+qll15Sfn4+k4ej3JEjR/T1119r1KhRjY6NHj1au3fvNnQ9QnQLlJaWKjk5udF6cnKyfD6fjhw5EoaqEEp2u10lJSV64IEHwl0KguDFF1/UoUOHtHTp0nCXgiBzu906d+6cvve972nSpEnasGGDZs+erZdeekkPP/xwuMtDgKWnp2vp0qV677339O1vf1s33nijcnJylJeXp5UrV4a7PARZaWmpJF01w5WVlencuXPNvh5jv1ugqqpK7du3b7TeoUOH+uOIXvv379e8efM0ZsyYRg8soPUrKyvTU089pSeffFLdunULdzkIstOnT6uqqko/+tGPtGrVKknS97//fZ05c0Yvv/yyfvGLXyglJSXMVSKQ+vfvr/Hjx2vq1Knq1q2bNm3apGXLlumGG27Qj3/843CXhyC6mM+aynBt27Zt1vUI0S3QsWPHK/41X3V1df1xRKejR48qKytLiYmJWrdu3RWnYaJ1e/zxx5WUlKR58+aFuxSEwMXf15f/rVJOTo5+85vfaNu2bYToKPLGG29o7ty58ng89buR3//+91VTU6OFCxcqOztbiYmJYa4SwXLxf++BynC0c7RAcnJy/V8JXOriWq9evUJdEkLg1KlTysjI0KlTp1RYWKgbbrgh3CUhwDwej1555RXl5eWppKREBw8e1IEDB1RdXa1z587p4MGDKi8vD3eZCKCLv6+vv/76Buv/v707CGnyDeA4/jP+dZEYGF46TLaghMmYq0PQwYYdbUHmOghRmHhZQ4IuQRAyImGngTiSWIfokuXQOnTQwDpsYzQkIhyLQWxBh1VCBMncOjmQFfwf/+q79v9+YJfngfGD9/J73+d532fzBSWud2uZnp6W1+ttWM73+/368eOH8Z5Y/F02r/ufOlxHR8e/fgotUaK3xePxKJfL6fv371vGk8mk2tra5PF4LEqG3fLz508NDAwon8/r+fPnOnbsmNWRsAtKpZJqtZpCoZAcDoccDoecTqdSqZRWV1fldDrZJ91ijh8/LkkNX1XafLels7NzzzNh93z+/FkbGxsN45v7YCuVyl5Hwh46fPiwOjs7lclkGubS6bRxf6NEb8OFCxdUqVR07969+tj6+roePHigkydPbvlsCv5+1WpVgUBAqVRKs7Oz9a+woPX09PRobm5Oc3NzSiQS9Z/L5VJXV5cSiYRGRkasjokdFAgEVKvVdP/+/S3jMzMz2r9/v06fPm1NMOyKo0ePKpvNKp/Pbxl/9OgRJ5P+TwwODurZs2dbbpwXFxeVy+UUCASM/osTC7fp4sWLSiQSGh8fr59YmMlktLS0pFOnTlkdDztofHxc0WhUfr9fQ0NDDfPDw8MWpMJe8vl8KpfLnFjYoq5evap4PK6hoSH19fXp5cuXevLkiW7evMnKQ4t59eqV+vv71dHRoWAwqEOHDmlhYUEvXrzQ6OioYrGY1RHxH0xNTenbt28qlUqKxWI6f/68ent7JUmhUEgHDx5UsViU1+uVzWarn1gYiURkt9uVTqeNtnNQordpfX1dt27d0sOHD/X161e53W6Fw2GdOXPG6mjYYT6fT8vLy3+c/93SIFqLz+fTly9ftLKyYnUU7IKNjQ3duXNH8Xhcnz59UldXl4LBoK5du2Z1NOyCTCaj27dvK5vNqlwuy+Fw6PLly7px44b27WOB/m/mcDj08ePH384VCgXZ7XZJ0vv373X9+nW9fv1aBw4c0MDAgCKRiPH2LUo0AAAAYIhbLgAAAMAQJRoAAAAwRIkGAAAADFGiAQAAAEOUaAAAAMAQJRoAAAAwRIkGAAAADFGiAQAAAEOUaAAAAMAQJRoAAAAwRIkGAAAADFGiAQAAAEOUaAAAAMAQJRoAAAAwRIkGAAAADFGiAQAAAEOUaABAXaFQkNvtVnd3tz58+KC1tTVNTk5aHQsAmk5brVarWR0CANAcxsbG1NfXp2q1qjdv3ujdu3d6+vSp2tvbrY4GAE2FEg0AqFtbW5PNZpMkTU5O6ty5c+ru7rY4FT++aXwAAADqSURBVAA0H0o0AKDB3bt3dfbsWblcLqujAEBT+sfqAACA5jIxMaHh4WEdOXLE6igA0LR4sRAAUBcOh3Xp0qV6gV5YWFA+n7c4FQA0H7ZzAAAkSdFoVG/fvpXNZtOJEydULBaVTCY1OztrdTQAaDps5wAAqFAoqL29XTMzM5qfn9eVK1fk9Xr1+PFjq6MBQFPiSTQAAABgiD3RAAAAgCFKNAAAAGCIEg0AAAAYokQDAAAAhijRAAAAgCFKNAAAAGCIEg0AAAAYokQDAAAAhijRAAAAgCFKNAAAAGCIEg0AAAAYokQDAAAAhn4BHK79K0/NKuUAAAAASUVORK5CYII=", "text/plain": [ "PyPlot.Figure(PyObject )" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "PyObject " ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "using PyPlot\n", "include(\"scripts/innerproduct_node.jl\");\n", "\n", "# Parameters\n", "Σ = 1e5 * eye(3) # Covariance matrix of prior on w\n", "σ2 = 2.0 # Noise variance\n", "\n", "# Generate data set\n", "w = [1.0; 2.0; 0.25]\n", "N = 30\n", "z = 10.0*rand(N)\n", "x_train = [[1.0; z; z^2] for z in z] # Feature vector x = [1.0; z; z^2]\n", "f(x) = (w'*x)[1]\n", "y_train = map(f, x_train) + sqrt(σ2)*randn(N) # y[i] = w' * x[i] + ϵ\n", "scatter(z, y_train); xlabel(L\"z\"); ylabel(L\"f([1.0, z, z^2]) + \\epsilon\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "#### CODE EXAMPLE\n", "\n", "Perform sum-product message passing and plot result (mean of posterior)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAtEAAAItCAYAAAD/mSZlAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAPYQAAD2EBqD+naQAAIABJREFUeJzs3XlwXeWd5/+3dsnad13t+2pLsvYF2xVi4g5gshEThxDodOGku9PNkK6a+Q0puru6iu6pX7pxZqp/1TOdpLshgAlO2BdjZBtjW9LVerVYsq0FyVqtfd+udO/vj8AdFJkGYdlXlj6vKhdwztE53++hqPro4TnP42C1Wq2IiIiIiMjn5mjvAkREREREbjcK0SIiIiIi66QQLSIiIiKyTgrRIiIiIiLrpBAtIiIiIrJOCtEiIiIiIuukEC0iIiIisk4K0SIiIiIi66QQLSIiIiKyTgrRIiIiIiLrtOVD9B//8R/j6Oh43T9OTk4MDAzYri0vL+eOO+7A09MTg8HAY489xuzsrB2rFxEREZHNyMFqtVrtXcTNZDQa6ejoWHXMarXywx/+kPj4eBobGwEwmUyUlJSQnp7OkSNH6O3t5Wc/+xl33nknb731lj1KFxEREZFNytneBdxshYWFFBYWrjp24cIF5ubmePDBB23HnnjiCQICAjh79iyenp4AxMTEcOTIEcrKyti/f/8trVtERERENq8tP53jep5//nkcHR05fPgwANPT05SVlfHQQw/ZAjTA97//fTw9PXnppZfsVaqIiIiIbELbLkQvLy9z/PhxSktLiY6OBqCpqYnl5WVyc3NXXevi4kJ2djb19fX2KFVERERENqltF6JPnDjB6OjoqqkcAwMDODg4YDAY1lxvMBjo7++/lSWKiIiIyCa37UL0Cy+8gKurK9/+9rdtx+bn5wFwc3Nbc727u7vtvIiIiIgIbIMPCz9pdnaW119/nT/6oz/C39/fdtzDwwOAxcXFNT+zsLBgO389IyMjvPvuu8TGxv6n14mIiIiIfczPz9PV1cWBAwcICgrakHtuqxD9yiuvMD8/v2oqB/x+yobVal21ZvTHBgYGCA8P/9R7vvvuu3zve9/b8FpFREREZGM999xza3LgF7WtQvTzzz+Pl5cXBw8eXHV8586dODs7U1NTw/333287bjabMZlMPPDAA596z9jYWOD3/1LS0tJuSt1b0eOPP87Ro0ftXcZtR+9t/fTOvhi9t/XTO/ti9N7WT+9s/VpbW/ne975ny20bYduE6JGREU6dOsWDDz6Iu7v7qnM+Pj7s37+f5557jieffNK2zN2zzz7L7Owshw4d+tT7fjyFIy0tjZycnJvXwBbj6+ur9/UF6L2tn97ZF6P3tn56Z1+M3tv66Z19cRs59XbbhOgXX3yRlZWVTx3Cf+qppygtLWXv3r0cOXKEnp4enn76aQ4cOMBdd911i6sVERERkc1s26zO8cILLxAaGsqXv/zl657fvXs3ZWVl7Nixg5/85Cf88pe/5NFHH+X48eO3uFIRERER2ey2zUh0eXn5Z15TUlLCuXPnbkE1IiIiInI72zYj0bK5fLzluqyP3tv66Z19MXpv66d39sXova2f3tnm4GC1Wq32LuJ2VldXR25uLrW1tZrkLyIiIrIJ3Yy8ppFoEREREZF1UogWEREREVknhWgRERERkXVSiBYRERERWSeFaBERERGRdVKIFhERERFZJ4VoEREREZF1UogWEREREVknhWgRERERkXVSiBYRERERWSeFaBERERGRdVKIFhERERFZJ4VoEREREZF1UogWEREREVknhWgRERERkXVSiBYRERERWSeFaBERERGRdVKIFhERERFZJ4VoEREREZF1UogWEREREVknhWgRERERkXVSiBYRERERWSeFaBERERGRdVKIFhERERFZJ4VoEREREZF1UogWEREREVknhWgRERERkXVSiBYRERERWSeFaBERERGRdVKIFhERERFZJ4VoEREREZF1UogWEREREVknhWgRERERkXVSiBYRERERWSeFaBERERGRdVKIFhERERFZJ4VoEREREZF1UogWEREREVknhWgRERERkXVSiBYRERERWSeFaBERERGRdVKIFhERERFZJ4VoEREREZF1UogWEREREVmnbROi6+rquO+++wgMDMTT05Ndu3bxz//8z6uuKS8v54477sDT0xODwcBjjz3G7OysnSoWERERkc3K2d4F3AonT57kvvvuIycnh7/+67/Gy8uLjo4Oent7bdeYTCb2799Peno6R48epbe3l5/97Ge0t7fz1ltv2bF6EREREdlstnyInp6e5uGHH+bgwYMcP378U6974oknCAgI4OzZs3h6egIQExPDkSNHKCsrY//+/beqZBERERHZ5Lb8dI7nn3+eoaEhnnrqKQDm5uawWq2rrpmenqasrIyHHnrIFqABvv/97+Pp6clLL710S2sWERER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trYWCoUC/fr1Q1RUVLs56nfD9Z6JiIgebDt27MCOHTtuamtoaOj0+zBEXzds2DBkZ2fDbDbfFNxOnjwJmUyGYcOG3fHzmzZtQkpKyv0us0dQqVT47W9/i+bmZhQXF6O0tBQ2mw1BQUEYPnw4wsLC4OXlJXWZRERE1A3dahDz3LlzGDFiRKfe5/a/jz9gZs6cCafTiS1btrjb7HY7tm/fjlGjRnFljk5kNptx6tQpHDlyBHq9HuHh4UhLS8OYMWPQt29fBmgiIiLyeByJvi41NRWzZs3Ciy++iKqqKveOhXq9Htu2bZO6vB5FoVDA5XJx1JmIiIi6LYboG/z73//G2rVrkZmZibq6OiQnJ2P//v0YM2aM1KX1KEqlktuoExERUbfGEH0DHx8fbNy4ERs3bpS6FCIiIiLyYJwTTUREREQkEkM0EREREZFIDNFERERERCIxRBMRERERicQQTUREREQkEkM0EREREZFIDNFERERERCIxRBMRERERicQQTUREREQkEkM0EREREZFIDNFERERERCIxRBMRERERicQQTUREREQkEkM0EREREZFIDNFERERERCIxRBMRERERicQQTUREREQkEkM0EREREZFIDNFERERERCIxRBMRERERicQQTUREREQkEkM0EREREZFIDNFERERERCIxRBMRERERicQQTUREREQkEkM0EREREZFIDNFERERERCIxRBMRERERicQQTUREREQkEkM0EREREZFIDNFERERERCIxRBMRERERicQQTUREREQkEkM0EREREZFIDNFERERERCIxRBMRERERicQQTUREREQkEkM0EREREZFIDNFERERERCIxRBMRERERicQQTUREREQkEkM0EREREZFIDNFERERERCIxRBMRERERicQQTUREREQkEkM0EREREZFIPTpEV1ZW4i9/+QsmTpwIf39/yOVyHD169LbnHz9+HGPHjoVKpUJYWBhWrFgBi8XShRUTERERUXfQo0P0zz//jDfeeAMVFRVITk6GTCa77bm5ublIT09HS0sLNm3ahCVLlmDLli2YPXt2F1ZMRERERN1Bjw7RI0eOhNFoxOXLl7Fy5co7nrtmzRoEBQXhu+++w9KlS7Fu3Tq8//77OHjwILKysrqo4gfHjh07pC6hW2K/icc+uzfsN/HYZ/eG/SYe+8wz9OgQrVKpEBgYeNfzmpqakJWVhfnz50OlUrnbFyxYAJVKhc8+++x+lvlA4l8A94b9Jh777N6w38Rjn90b9pt47DPP0KNDdEdduHABTqcTI0aMuKldoVBg2LBhyMnJkagyIiIiIvJEDNEADAYDZDIZwsLC2h0LCwtDRUWFBFURERERkafylrqAjhIEAXa7vUPnKpVKUde2Wq23/Zyvr6/7OBERERER0I1C9NGjRzFhwoS7nieTyZCfn4/ExMQOX9vPzw8AYLPZ2h1raWlxH7+VtoCdn5/f4fsR0NDQgHPnzkldRrfDfhOPfXZv2G/isc/uDftNPPaZeG05rTMHRrtNiB4wYAC2b9/eoXNvNS3jbucLggCDwdDumMFgQHh4+G0/W1xcDAB45plnRN2T0G4OOnUM+0089tm9Yb+Jxz67N+w38dhn96a4uBhjxozplGt1mxAdGhqKBQsW3JdrDxkyBN7e3jh79ixmzpzpbnc4HMjNzcWcOXNu+9mMjAxkZmYiOjr6jiPWRERERCQNq9WK4uJiZGRkdNo1u02Ivp/8/f2Rnp6OzMxMrF271r3M3ccffwyLxXLHDVeCg4Px9NNPd1WpRERERHQPOmsEuo1MEAShU6/oYV599VXIZDLk5eXh008/xaJFixATEwMAeOmll9zn5eTkYMyYMRg4cCCWLl2K0tJSvP3220hLS8OBAwekKp+IiIiIPFCPD9FyufyW233LZDI4nc6b2o4fP47Vq1fj3Llz6N27N+bMmYPXXnvtpg1YiIiIiIh6fIgmIiIiIups3GyFiIiIiEgkhuhOdOTIESxevBj9+/eHSqVCXFwclixZgsrKSqlL8wh2ux2rV69GREQEevXqhVGjRiErK0vqsjza2bNnsWzZMgwZMgRqtRpRUVGYM2cOCgoKpC6tW9mwYQPkcjmSk5OlLsXjnTt3DtOnT4dWq4VKpUJSUhLef/99qcvyWIWFhXjqqafQr18/qFQqDBw4EOvXr+cmXddZLBa88sormDx5MrRaLeRyOT7++ONbnnv58mVMmjQJvXv3hlarxYIFC1BbW9vFFXuGjvSbIAjYvn07ZsyYgcjISKjVaiQlJWHDhg233PeipxPzXWvjdDoxaNAgyOVyvP3226LvydU5OtHq1atRV1eHWbNmISEhAb/88gvee+897N+/H7m5uejTp4/UJUpq4cKF2L17N1auXIn4+Hhs374dU6ZMQXZ2NkaPHi11eR5p48aNOH78OGbNmoXk5GRUVlbivffeQ0pKCk6dOoVBgwZJXaLHKy8vx1//+leo1WqpS/F4X3/9NaZPn46UlBS8/PLLUKvVKCoqQllZmdSleaSysjI89NBD0Gg0eOGFFxAUFIQTJ07glVdewblz57Bnzx6pS5RcbW0t1q9fj6ioKAwbNgzZ2dm3PK+8vBzjxo2DRqPB66+/jqamJrzxxhu4ePEiTp8+DW/vByuudKTfmpubsWjRIjzyyCN47rnn0KdPH/f378iRIzh8+HDXFy6hjn7XbvTuu++itLT0lu/OdYhAneb7779v13b06FFBJpMJa9eulaAiz3Hq1ClBJpMJb7/9trutpaVFiI+PF8aMGSNhZZ7txIkTgsPhuKmtoKBA8PX1FebPny9RVd3LnDlzhPT0dCEtLU1ISkqSuhyP1djYKOh0OmHmzJlSl9JtbNiwQZDL5UJ+fv5N7QsXLhTkcrlQX18vUWWew263C1VVVYIgCMLZs2cFmUwmfPTRR+3Oe+655wSVSiWUlZW527KysgSZTCZs3bq1y+r1FB3pN7vdLpw4caLdZ9etWyfI5XLh8OHDXVKrp+jod61NVVWVEBgYKLz66quCTCYT3nrrLdH35HSOTjR27Nh2bePGjUNQUNADvy34rl274O3tjSVLlrjblEolFi9ejBMnTqC8vFzC6jzXqFGj2o3AxMfHY/DgwQ/8d6ojjh49it27d+Odd96RuhSP98knn6C6uhobNmwAcG2US+B753fU1NQEAO1+ZdTpdJDL5fDx8ZGiLI+iUCg69Cvs7t27MXXqVERERLjbfvOb3yAxMRGfffbZ/SzRI3Wk3xQKBUaNGtWu/Xe/+x0EQXjgnhEd/a61+ctf/oKBAwf+qr0+GKLvM4vFArPZjODgYKlLkVRubi4SExPb/aSemprqPk4dV1VV9cB/p+7G5XJh+fLlWLJkCQYPHix1OR7v8OHD8Pf3R2lpKQYMGAC1Wg1/f388//zzD+T8yo5IS0uDIAhYtGgRzp8/j7KyMuzcuRMffPABVqxYwV1sO6iiogLV1dUYOXJku2OpqanIycmRoKruy2AwAACfEXdw+vRpfPzxx3jnnXfufSoHGKLvu02bNsHhcOCpp56SuhRJGQwGhIWFtWsPCwuDIAioqKiQoKruKTMzE+Xl5Q/8d+puNm/ejJKSEqxfv17qUrqFgoICOBwOzJgxA5MnT8bu3buxePFifPDBB1i0aJHU5XmkjIwMrF+/Ht988w2GDx+OyMhIzJs3D8uXL8ebb74pdXndRlvou90zwmQyweFwdHVZ3dbf/vY3BAQEYPLkyVKX4rFeeOEFzJ071z2Qd68erJn6IgiCALvd3qFzlUrlLduPHj2KdevWYc6cORg/fnxnltftWK3WW/aTr6+v+zjd3eXLl7Fs2TKMGTMGCxYskLocj2UymfDKK6/g5ZdfRlBQkNTldAtmsxlWqxXPPfccNm3aBAB44oknYLPZsGXLFqxbtw5xcXESV+l5oqOjMX78eMycORNBQUHYv38/NmzYAJ1Oh+eff17q8rqFtr//7/aMUCgUXVpXd/Taa6/hyJEj2Lx5M/z9/aUuxyNt27YNeXl5nfLiL0P0bRw9ehQTJky463kymQz5+flITEy8qf3y5ct48sknkZycjK1bt96vMrsNPz+/W/4k3NLS4j5Od1ZVVYXHH38cGo0Gn3/++a/6Caqne+mll6DVarFs2TKpS+k22v4b/O9fOObNm4cPP/wQJ06cYIj+L59++imWLl2KwsJC9yjqE088gdbWVqxevRpz586FRqORuErP1/bd4zPi19m5cyfWrl2LP/7xj1i6dKnU5XikpqYmrFmzBqtWrUJ4ePivvh5D9G0MGDAA27dv79C5//0TVGlpKR577DFoNBrs37+f24bjWh/daspG2894nfFl7skaGxsxadIkNDY24tixY9DpdFKX5LEKCwuxdetW/P3vf3e/sCoIAlpaWuBwOKDX6+Hv789w81/Cw8Nx6dIlhIaG3tTe9qJOXV2dFGV5tM2bNyMlJaXdM2D69On46KOPkJOTg4kTJ0pUXffR1n9tz4MbGQwGBAUFcRT6Lr755hssXLgQ06ZNw+bNm6Uux2O98cYbcDgcmD17NvR6PYBrmQ249necXq9HeHh4h79vDNG3ERoaek8/l5tMJjz22GNwOp3Izs5u90B6ULWt2Wg2m296ufDkyZOQyWQYNmyYhNV5NpvNhqlTp6KwsBCHDx9G//79pS7Jo5WXl0MQBCxfvhwvvPBCu+OxsbFYsWLFPS2s35ONGDECWVlZKC8vR0JCgru97X9+Q0JCpCrNY1VVVd1yulDb/F2n09nVJXVL4eHhCAkJwdmzZ9sdO336NJ8Pd3Hq1Ck8+eSTSE1Nxc6dOyGX83W32yktLUVdXV27PRZkMhk2bNiA1157DTk5OR3emIs93Ymam5sxefJkGAwGHDhwALGxsVKX5DFmzpwJp9OJLVu2uNvsdju2b9+OUaNG3bSsEf1/LpcLs2fPxqlTp7Br165f/RLEg2DIkCHYs2cP9uzZg71797r/GTx4MKKiorB3714sXrxY6jI9zuzZsyEIAv71r3/d1L5161YoFAqkpaVJU5gHS0xMRE5ODgoLC29q/89//sMdMkX6/e9/j6+++uqm5U4PHz6MK1euYPbs2RJW5tny8/MxdepUxMbGYt++fbd9R4uuWbFiRbtnw5YtWyAIAp599lns3bsXMTExHb4eR6I70bx583DmzBksXrwYeXl5yMvLcx9Tq9WYMWOGhNVJKzU1FbNmzcKLL76Iqqoq946Fer0e27Ztk7o8j/XnP/8Z+/btw/Tp01FbW4tPPvnkpuO/Zn3Lnkqr1WL69Ont2jdt2gSZTIZp06ZJUJXnGzZsGBYtWoRt27bB4XBg/Pjx+Pbbb/HFF19gzZo1nEJ0C//zP/+DgwcPYuzYsVi2bBm0Wi327duHQ4cOYcmSJeyz6/7xj3+gvr7eHZC//PJL90/oy5cvR+/evbFmzRrs2rULaWlpWLFiBZqamvDmm29i6NCh+MMf/iBh9dK5W7/JZDJkZGSgvr4eq1atwldffXXT5+Pi4m65jnRPdrc+GzZsWLtfNtqmdQwePFj880H09ix0W9HR0YJcLr/lPzExMVKXJzmbzSasWrVKCA8PF/z8/ISHH35Y+Oabb6Quy6OlpaXd9jsll8ulLq9bSUtLE5KTk6Uuw6M5nU5h3bp1QkxMjKBUKoXExETh3Xfflbosj3bmzBnh8ccfF8LDwwWlUikMGDBAeP3114XW1lapS/MYd3o26vV693mXLl0SJk2aJKjVaiEoKEhYsGCBUF1dLWHl0rpbvxUXF9/x+fDss89K/Ufoch39rt2orR/vZcdCmSBwSyoiIiIiIjE4J5qIiIiISCSGaCIiIiIikRiiiYiIiIhEYogmIiIiIhKJIZqIiIiISCSGaCIiIiIikRiiiYiIiIhEYogmIiIiIhKJIZqIiIiISCSGaCIiIiIikRiiiYiIiIhEYogmIiIiIhKJIZqIiIiISCSGaCIiIiIikRiiiYiIiIhEYogmIiIiIhKJIZqIiNyuXr2K5ORkDBgwAEVFRWhoaMDGjRulLouIyOPIBEEQpC6CiIg8w5/+9CeMHz8eLpcL586dQ15eHnbv3g2VSiV1aUREHoUhmoiI3BoaGhAQEAAA2LhxI2bMmIEBAwZIXBURkedhiCYionZef/11TJs2DYMHD5a6FCIij+QtdQFERORZ1q1bh6effhpxcXFSl0JE5LH4YiEREbm9+uqrWLBggTtA79u3D4WFhRJXRUTkeTidg4iIAADvvvsuLly4gICAAIwcORJlZWU4efIkdu3aJXVpREQeh9M5iIgIV69ehUqlwtatW/Hll1/i2WefRUpKCj7//HOpSyMi8kgciSYiIiIiEolzoomIiIiIRGKIJiIiIiISiSGaiIiIiEgkhmgiIiIiIpEYoomIiIiIRGKIJiIiIiISiSGaiIiIiEgkhmgiIiIiIpEYoomIiIiIRGKIJiIiIiISiSGaiIiIiEgkhmgiIiIiIpH+H6KVsZGPy2eBAAAAAElFTkSuQmCC", "text/plain": [ "PyPlot.Figure(PyObject )" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Posterior distribution of w: 𝒩(m=[0.91, 2.26, 0.21], v=[[0.83, -0.32, 0.03][-0.32, 0.16, -0.02][0.03, -0.02, 1.59e-03]])\n", "\n" ] } ], "source": [ "# Build factorgraph\n", "fg = FactorGraph()\n", "@RV w ~ GaussianMeanVariance(constant(zeros(3)), constant(Σ, id=:Σ), id=:w) # p(w)\n", "for t=1:N\n", " x_t = Variable(id=:x_*t)\n", " d_t = Variable(id=:d_*t) # d=w'*x\n", " DotProduct(d_t, x_t, w) # p(f|w,x)\n", " @RV y_t ~ GaussianMeanVariance(d_t, constant(σ2, id=:σ2_*t), id=:y_*t) # p(y|d)\n", " placeholder(x_t, :x, index=t, dims=(3,))\n", " placeholder(y_t, :y, index=t);\n", "end\n", "\n", "# Build and run message passing algorithm\n", "eval(parse(sumProductAlgorithm(w)))\n", "data = Dict(:x => x_train, :y => y_train)\n", "w_posterior_dist = step!(data)[:w]\n", "\n", "# Plot result\n", "println(\"Posterior distribution of w: $(w_posterior_dist)\")\n", "scatter(z, y_train); xlabel(L\"z\"); ylabel(L\"f([1.0, z, z^2]) + \\epsilon\");\n", "z_test = collect(0:0.2:12)\n", "x_test = [[1.0; z; z^2] for z in z_test]\n", "for sample=1:10\n", " w = ForneyLab.sample(w_posterior_dist)\n", " f_est(x) = (w'*x)[1]\n", " plot(z_test, map(f_est, x_test), \"k-\", alpha=0.3);\n", "end" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Homework Exercises \n", "\n", "- (Ex.1) Reflect on the fact that we now have methods for both marginalization and processing observations in FFGs. In principle, we are sufficiently equipped to do inference in probabilistic models through message passing. Draw the graph for $$p(x_1,x_2,x_3)=f_a(x_1)\\cdot f_b(x_1,x_2)\\cdot f_c(x_2,x_3)$$ and show which boxes need to be closed for computing $p(x_1|x_2)$." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- (Ex.2) Consider a variable $X$ with measurements $D=\\{x_1,x_2\\}$. We assume the following model for $X$:\n", "$$\\begin{align*}\n", "p(D,\\theta) &= p(\\theta)\\cdot \\prod_{n=1}^2 p(x_n|\\theta) \\\\\n", "p(\\theta) &= \\mathcal{N}(\\theta \\mid 0,1) \\\\\n", "p(x_n \\mid\\theta) &= \\mathcal{N}(x_n \\mid \\theta,1)\n", "\\end{align*}$$\n", " - Draw the factor graph and infer $\\theta$ through the Sum-Product Algorithm. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Inference in Linear Gaussian Models by Sum-Product Message Passing\n", "\n", "- The foregoing message update rules can be extended to all scenarios involving additions, fixed-gain multiplications and branching (equality nodes), thus creating a completely **automatable inference framework** for factorized linear Gaussian models." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- The update rules for elementary and important node types can be put in a Table (see **Tables 1 through 6** in [Loeliger, 2007](./files/Loeliger-2007-The-factor-graph-approach-to-model-based-signal-processing.pdf))." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- If the update rules for all node types in a graph have been tabulated, then inference by message passing comes down to a set of table-lookup operations. This also works for large graphs (where 'manual' inference becomes intractable)." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- If the graph contains no cycles, the Sum-Product Algorithm computes **exact** marginals for all hidden variables." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- If the graph contains cycles, we have in principle an infinite tree without terminals. In this case, the SP Algorithm is not guaranteed to find exact marginals. In practice, if we apply the SP algorithm for just a few iterations we often find satisfying approximate marginals. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "The cell below loads the style file\n" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "slideshow": { "slide_type": "skip" } }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "open(\"../../styles/aipstyle.html\") do f display(\"text/html\", readstring(f)) end\n" ] } ], "metadata": { "celltoolbar": "Slideshow", "kernelspec": { "display_name": "Julia 0.6.2", "language": "julia", "name": "julia-0.6" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", "version": "0.6.2" } }, "nbformat": 4, "nbformat_minor": 1 }