├── .gitignore ├── 1.PROBABILITY_DISTRIBUTIONS ├── 1.1 Binary_Variables.ipynb ├── 1.2 Multinomial_Variables.ipynb ├── 1.3 The_Gaussian_Distribution.ipynb ├── 1.4 Conditional_and_Marginal_Gaussian_Distributions.ipynb └── Untitled.ipynb ├── 2.LINEAR_MODELS_FOR_REGRESSION ├── .DS_Store ├── Bayesian_Linear_Regression.ipynb ├── Linear_Basis_Function_Models.ipynb ├── Old_Faithful_Geyser_Experiment.ipynb ├── faithful.csv └── pics │ ├── .DS_Store │ ├── linear_model.png │ └── linear_model2.png ├── LICENSE ├── README.md ├── figaro_2.11-4.1.0.0.jar ├── jsci-1.2.jar ├── p1.Figaro_intro ├── .DS_Store ├── 1.figaro_helloworld.ipynb ├── 2.basic_element.ipynb └── figaro_concept.png └── p2.Figaro_dependent_model ├── .DS_Store ├── 1.use_bayesian_net_to_diagnose_printer.ipynb ├── print_result_summary.jpeg └── printer_state.jpeg /.gitignore: -------------------------------------------------------------------------------- 1 | .ipynb_checkpoints -------------------------------------------------------------------------------- /1.PROBABILITY_DISTRIBUTIONS/1.4 Conditional_and_Marginal_Gaussian_Distributions.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "$$\n", 8 | "A=\\left(\n", 9 | "\\begin{matrix}\n", 10 | "1&2&3&\\\\\n", 11 | "3&4&4&\\\\\n", 12 | "5&4&4&\n", 13 | "\\end{matrix}\n", 14 | "\\right)\n", 15 | "$$" 16 | ] 17 | }, 18 | { 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "$$\n", 23 | "x=\\left(\n", 24 | "\\begin{matrix}\n", 25 | "x_a\\\\\n", 26 | "x_b\n", 27 | "\\end{matrix}\n", 28 | "\\right)\n", 29 | "$$\n", 30 | "\n", 31 | "$$\n", 32 | "\\mu=\\left(\n", 33 | "\\begin{matrix}\n", 34 | "\\mu_a\\\\\n", 35 | "\\mu_b\n", 36 | "\\end{matrix}\n", 37 | "\\right)\n", 38 | "$$\n", 39 | "\n", 40 | "$$\n", 41 | "\\Sigma=\\left(\n", 42 | "\\begin{matrix}\n", 43 | "\\Sigma_{aa}&\\Sigma_{ab}\\\\\n", 44 | "\\Sigma_{ba}&\\Sigma_{bb}\n", 45 | "\\end{matrix}\n", 46 | "\\right)\n", 47 | "$$" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": null, 53 | "metadata": { 54 | "collapsed": true 55 | }, 56 | "outputs": [], 57 | "source": [] 58 | } 59 | ], 60 | "metadata": { 61 | "kernelspec": { 62 | "display_name": "Python 2", 63 | "language": "python", 64 | "name": "python2" 65 | }, 66 | "language_info": { 67 | "codemirror_mode": { 68 | "name": "ipython", 69 | "version": 2 70 | }, 71 | "file_extension": ".py", 72 | "mimetype": "text/x-python", 73 | "name": "python", 74 | "nbconvert_exporter": "python", 75 | "pygments_lexer": "ipython2", 76 | "version": "2.7.5" 77 | } 78 | }, 79 | "nbformat": 4, 80 | "nbformat_minor": 0 81 | } 82 | -------------------------------------------------------------------------------- /2.LINEAR_MODELS_FOR_REGRESSION/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonding1354/PRML_Notes/83612257ee4523034421f3e9810972eceb4f2ebb/2.LINEAR_MODELS_FOR_REGRESSION/.DS_Store -------------------------------------------------------------------------------- /2.LINEAR_MODELS_FOR_REGRESSION/Bayesian_Linear_Regression.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 11, 6 | "metadata": { 7 | "collapsed": true 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "import numpy as np\n", 12 | "import tensorflow as tf\n", 13 | "from edward.models import Normal\n", 14 | "import edward as ed\n", 15 | "import matplotlib.pyplot as plt\n", 16 | "%matplotlib inline\n", 17 | "plt.style.use('ggplot')" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": 3, 23 | "metadata": { 24 | "collapsed": false 25 | }, 26 | "outputs": [], 27 | "source": [ 28 | "def build_toy_dataset(N, w, noise_std=0.1):\n", 29 | " D = len(w)\n", 30 | " x = np.random.randn(N, D)\n", 31 | " y = np.dot(x, w) + np.random.normal(0, noise_std, size=N)\n", 32 | " return x, y\n", 33 | "\n", 34 | "N = 40 # number of data points\n", 35 | "D = 10 # number of features\n", 36 | "\n", 37 | "w_true = np.random.randn(D)\n", 38 | "X_train, y_train = build_toy_dataset(N, w_true)\n", 39 | "X_test, y_test = build_toy_dataset(N, w_true)" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": 6, 45 | "metadata": { 46 | "collapsed": false 47 | }, 48 | "outputs": [], 49 | "source": [ 50 | "X = tf.placeholder(tf.float32, [N, D])\n", 51 | "w = Normal(mu=tf.zeros(D), sigma=tf.ones(D))\n", 52 | "b = Normal(mu=tf.zeros(1), sigma=tf.ones(1))\n", 53 | "y = Normal(mu=ed.dot(X, w) + b, sigma=tf.ones(N))" 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": 7, 59 | "metadata": { 60 | "collapsed": true 61 | }, 62 | "outputs": [], 63 | "source": [ 64 | "qw = Normal(mu=tf.Variable(tf.random_normal([D])),\n", 65 | " sigma=tf.nn.softplus(tf.Variable(tf.random_normal([D]))))\n", 66 | "qb = Normal(mu=tf.Variable(tf.random_normal([1])),\n", 67 | " sigma=tf.nn.softplus(tf.Variable(tf.random_normal([1]))))" 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": 8, 73 | "metadata": { 74 | "collapsed": false 75 | }, 76 | "outputs": [ 77 | { 78 | "name": "stdout", 79 | "output_type": "stream", 80 | "text": [ 81 | "Iteration 1 [ 0%]: Loss = 510.198\n", 82 | "Iteration 25 [ 10%]: Loss = 77.018\n", 83 | "Iteration 50 [ 20%]: Loss = 60.631\n", 84 | "Iteration 75 [ 30%]: Loss = 61.767\n", 85 | "Iteration 100 [ 40%]: Loss = 59.794\n", 86 | "Iteration 125 [ 50%]: Loss = 59.856\n", 87 | "Iteration 150 [ 60%]: Loss = 59.953\n", 88 | "Iteration 175 [ 70%]: Loss = 58.999\n", 89 | "Iteration 200 [ 80%]: Loss = 60.209\n", 90 | "Iteration 225 [ 90%]: Loss = 61.159\n", 91 | "Iteration 250 [100%]: Loss = 60.342\n" 92 | ] 93 | } 94 | ], 95 | "source": [ 96 | "inference = ed.KLqp({w: qw, b: qb}, data={X: X_train, y: y_train})\n", 97 | "inference.run(n_samples=5, n_iter=250)" 98 | ] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "execution_count": 9, 103 | "metadata": { 104 | "collapsed": true 105 | }, 106 | "outputs": [], 107 | "source": [ 108 | "def visualise(X_data, y_data, w, b, n_samples=10):\n", 109 | " w_samples = w.sample(n_samples)[0].eval()\n", 110 | " b_samples = b.sample(n_samples).eval()\n", 111 | " plt.scatter(X_data[:, 0], y_data)\n", 112 | " plt.ylim([-10, 10])\n", 113 | " inputs = np.linspace(-8, 8, num=400)\n", 114 | " for ns in range(n_samples):\n", 115 | " output = inputs * w_samples[ns] + b_samples[ns]\n", 116 | " plt.plot(inputs, output)" 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": 14, 122 | "metadata": { 123 | "collapsed": false 124 | }, 125 | "outputs": [ 126 | { 127 | "data": { 128 | "image/png": "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\nUYjf8Eqf2gAAAABJRU5ErkJggg==\n", 129 | "text/plain": [ 130 | "" 131 | ] 132 | }, 133 | "metadata": {}, 134 | "output_type": "display_data" 135 | } 136 | ], 137 | "source": [ 138 | "# Visualize samples from the prior.\n", 139 | "visualise(X_train, y_train, w, b)" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": 19, 145 | "metadata": { 146 | "collapsed": false 147 | }, 148 | "outputs": [ 149 | { 150 | "data": { 151 | "image/png": "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\n", 152 | "text/plain": [ 153 | "" 154 | ] 155 | }, 156 | "metadata": {}, 157 | "output_type": "display_data" 158 | } 159 | ], 160 | "source": [ 161 | "# Visualize samples from the posterior.\n", 162 | "visualise(X_train, y_train, qw, qb)" 163 | ] 164 | }, 165 | { 166 | "cell_type": "code", 167 | "execution_count": null, 168 | "metadata": { 169 | "collapsed": true 170 | }, 171 | "outputs": [], 172 | "source": [] 173 | } 174 | ], 175 | "metadata": { 176 | "kernelspec": { 177 | "display_name": "Python [Root]", 178 | "language": "python", 179 | "name": "Python [Root]" 180 | }, 181 | "language_info": { 182 | "codemirror_mode": { 183 | "name": "ipython", 184 | "version": 3 185 | }, 186 | "file_extension": ".py", 187 | "mimetype": "text/x-python", 188 | "name": "python", 189 | "nbconvert_exporter": "python", 190 | "pygments_lexer": "ipython3", 191 | "version": "3.5.2" 192 | } 193 | }, 194 | "nbformat": 4, 195 | "nbformat_minor": 0 196 | } 197 | -------------------------------------------------------------------------------- /2.LINEAR_MODELS_FOR_REGRESSION/Linear_Basis_Function_Models.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## 1. 线性基函数模型\n", 8 | "用于回归问题的线性模型可以如下式表示:" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "![](./pics/linear_model.png)\n", 16 | "![](./pics/linear_model2.png)\n", 17 | "基函数可以表示在预处理过程或特征提取过程之中的特征转换。" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": null, 23 | "metadata": { 24 | "collapsed": true 25 | }, 26 | "outputs": [], 27 | "source": [] 28 | } 29 | ], 30 | "metadata": { 31 | "anaconda-cloud": {}, 32 | "kernelspec": { 33 | "display_name": "Python [Root]", 34 | "language": "python", 35 | "name": "Python [Root]" 36 | }, 37 | "language_info": { 38 | "codemirror_mode": { 39 | "name": "ipython", 40 | "version": 3 41 | }, 42 | "file_extension": ".py", 43 | "mimetype": "text/x-python", 44 | "name": "python", 45 | "nbconvert_exporter": "python", 46 | "pygments_lexer": "ipython3", 47 | "version": "3.5.2" 48 | } 49 | }, 50 | "nbformat": 4, 51 | "nbformat_minor": 0 52 | } 53 | -------------------------------------------------------------------------------- /2.LINEAR_MODELS_FOR_REGRESSION/faithful.csv: -------------------------------------------------------------------------------- 1 | "","eruptions","waiting" 2 | "1",3.6,79 3 | "2",1.8,54 4 | "3",3.333,74 5 | "4",2.283,62 6 | "5",4.533,85 7 | "6",2.883,55 8 | "7",4.7,88 9 | "8",3.6,85 10 | "9",1.95,51 11 | "10",4.35,85 12 | "11",1.833,54 13 | "12",3.917,84 14 | "13",4.2,78 15 | "14",1.75,47 16 | "15",4.7,83 17 | "16",2.167,52 18 | "17",1.75,62 19 | "18",4.8,84 20 | "19",1.6,52 21 | "20",4.25,79 22 | "21",1.8,51 23 | "22",1.75,47 24 | "23",3.45,78 25 | "24",3.067,69 26 | "25",4.533,74 27 | "26",3.6,83 28 | "27",1.967,55 29 | "28",4.083,76 30 | "29",3.85,78 31 | "30",4.433,79 32 | "31",4.3,73 33 | "32",4.467,77 34 | "33",3.367,66 35 | "34",4.033,80 36 | "35",3.833,74 37 | "36",2.017,52 38 | "37",1.867,48 39 | "38",4.833,80 40 | "39",1.833,59 41 | "40",4.783,90 42 | "41",4.35,80 43 | "42",1.883,58 44 | "43",4.567,84 45 | "44",1.75,58 46 | "45",4.533,73 47 | "46",3.317,83 48 | "47",3.833,64 49 | "48",2.1,53 50 | "49",4.633,82 51 | "50",2,59 52 | "51",4.8,75 53 | "52",4.716,90 54 | "53",1.833,54 55 | "54",4.833,80 56 | "55",1.733,54 57 | "56",4.883,83 58 | "57",3.717,71 59 | "58",1.667,64 60 | "59",4.567,77 61 | "60",4.317,81 62 | "61",2.233,59 63 | "62",4.5,84 64 | "63",1.75,48 65 | "64",4.8,82 66 | "65",1.817,60 67 | "66",4.4,92 68 | "67",4.167,78 69 | "68",4.7,78 70 | "69",2.067,65 71 | "70",4.7,73 72 | "71",4.033,82 73 | "72",1.967,56 74 | "73",4.5,79 75 | "74",4,71 76 | "75",1.983,62 77 | "76",5.067,76 78 | "77",2.017,60 79 | "78",4.567,78 80 | "79",3.883,76 81 | "80",3.6,83 82 | "81",4.133,75 83 | "82",4.333,82 84 | "83",4.1,70 85 | "84",2.633,65 86 | "85",4.067,73 87 | "86",4.933,88 88 | "87",3.95,76 89 | "88",4.517,80 90 | "89",2.167,48 91 | "90",4,86 92 | "91",2.2,60 93 | "92",4.333,90 94 | "93",1.867,50 95 | "94",4.817,78 96 | "95",1.833,63 97 | "96",4.3,72 98 | "97",4.667,84 99 | "98",3.75,75 100 | "99",1.867,51 101 | "100",4.9,82 102 | "101",2.483,62 103 | "102",4.367,88 104 | "103",2.1,49 105 | "104",4.5,83 106 | "105",4.05,81 107 | "106",1.867,47 108 | "107",4.7,84 109 | "108",1.783,52 110 | "109",4.85,86 111 | "110",3.683,81 112 | "111",4.733,75 113 | "112",2.3,59 114 | "113",4.9,89 115 | "114",4.417,79 116 | "115",1.7,59 117 | "116",4.633,81 118 | "117",2.317,50 119 | "118",4.6,85 120 | "119",1.817,59 121 | "120",4.417,87 122 | "121",2.617,53 123 | "122",4.067,69 124 | "123",4.25,77 125 | "124",1.967,56 126 | "125",4.6,88 127 | "126",3.767,81 128 | "127",1.917,45 129 | "128",4.5,82 130 | "129",2.267,55 131 | "130",4.65,90 132 | "131",1.867,45 133 | "132",4.167,83 134 | "133",2.8,56 135 | "134",4.333,89 136 | "135",1.833,46 137 | "136",4.383,82 138 | "137",1.883,51 139 | "138",4.933,86 140 | "139",2.033,53 141 | "140",3.733,79 142 | "141",4.233,81 143 | "142",2.233,60 144 | "143",4.533,82 145 | "144",4.817,77 146 | "145",4.333,76 147 | "146",1.983,59 148 | "147",4.633,80 149 | "148",2.017,49 150 | "149",5.1,96 151 | "150",1.8,53 152 | "151",5.033,77 153 | "152",4,77 154 | "153",2.4,65 155 | "154",4.6,81 156 | "155",3.567,71 157 | "156",4,70 158 | "157",4.5,81 159 | "158",4.083,93 160 | "159",1.8,53 161 | "160",3.967,89 162 | "161",2.2,45 163 | "162",4.15,86 164 | "163",2,58 165 | "164",3.833,78 166 | "165",3.5,66 167 | "166",4.583,76 168 | "167",2.367,63 169 | "168",5,88 170 | "169",1.933,52 171 | "170",4.617,93 172 | "171",1.917,49 173 | "172",2.083,57 174 | "173",4.583,77 175 | "174",3.333,68 176 | "175",4.167,81 177 | "176",4.333,81 178 | "177",4.5,73 179 | "178",2.417,50 180 | "179",4,85 181 | "180",4.167,74 182 | "181",1.883,55 183 | "182",4.583,77 184 | "183",4.25,83 185 | "184",3.767,83 186 | "185",2.033,51 187 | "186",4.433,78 188 | "187",4.083,84 189 | "188",1.833,46 190 | "189",4.417,83 191 | "190",2.183,55 192 | "191",4.8,81 193 | "192",1.833,57 194 | "193",4.8,76 195 | "194",4.1,84 196 | "195",3.966,77 197 | "196",4.233,81 198 | "197",3.5,87 199 | "198",4.366,77 200 | "199",2.25,51 201 | "200",4.667,78 202 | "201",2.1,60 203 | "202",4.35,82 204 | "203",4.133,91 205 | "204",1.867,53 206 | "205",4.6,78 207 | "206",1.783,46 208 | "207",4.367,77 209 | "208",3.85,84 210 | "209",1.933,49 211 | "210",4.5,83 212 | "211",2.383,71 213 | "212",4.7,80 214 | "213",1.867,49 215 | "214",3.833,75 216 | "215",3.417,64 217 | "216",4.233,76 218 | "217",2.4,53 219 | "218",4.8,94 220 | "219",2,55 221 | "220",4.15,76 222 | "221",1.867,50 223 | "222",4.267,82 224 | "223",1.75,54 225 | "224",4.483,75 226 | "225",4,78 227 | "226",4.117,79 228 | "227",4.083,78 229 | "228",4.267,78 230 | "229",3.917,70 231 | "230",4.55,79 232 | "231",4.083,70 233 | "232",2.417,54 234 | "233",4.183,86 235 | "234",2.217,50 236 | "235",4.45,90 237 | "236",1.883,54 238 | "237",1.85,54 239 | "238",4.283,77 240 | "239",3.95,79 241 | "240",2.333,64 242 | "241",4.15,75 243 | "242",2.35,47 244 | "243",4.933,86 245 | "244",2.9,63 246 | "245",4.583,85 247 | "246",3.833,82 248 | "247",2.083,57 249 | "248",4.367,82 250 | "249",2.133,67 251 | "250",4.35,74 252 | "251",2.2,54 253 | "252",4.45,83 254 | "253",3.567,73 255 | "254",4.5,73 256 | "255",4.15,88 257 | "256",3.817,80 258 | "257",3.917,71 259 | "258",4.45,83 260 | "259",2,56 261 | "260",4.283,79 262 | "261",4.767,78 263 | "262",4.533,84 264 | "263",1.85,58 265 | "264",4.25,83 266 | "265",1.983,43 267 | "266",2.25,60 268 | "267",4.75,75 269 | "268",4.117,81 270 | "269",2.15,46 271 | "270",4.417,90 272 | "271",1.817,46 273 | "272",4.467,74 274 | -------------------------------------------------------------------------------- /2.LINEAR_MODELS_FOR_REGRESSION/pics/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonding1354/PRML_Notes/83612257ee4523034421f3e9810972eceb4f2ebb/2.LINEAR_MODELS_FOR_REGRESSION/pics/.DS_Store -------------------------------------------------------------------------------- /2.LINEAR_MODELS_FOR_REGRESSION/pics/linear_model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonding1354/PRML_Notes/83612257ee4523034421f3e9810972eceb4f2ebb/2.LINEAR_MODELS_FOR_REGRESSION/pics/linear_model.png -------------------------------------------------------------------------------- /2.LINEAR_MODELS_FOR_REGRESSION/pics/linear_model2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonding1354/PRML_Notes/83612257ee4523034421f3e9810972eceb4f2ebb/2.LINEAR_MODELS_FOR_REGRESSION/pics/linear_model2.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Jason Ding 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PRML_Notes 2 | 3 | ##项目概要 4 | 该项目是关于机器学习经典书籍《Pattern Recognition and Machine Learning》的学习笔记,用python实现了书籍中的大部分实例,希望帮助大家更好的理解抽象的概念和复杂的公式。 5 | 6 | ##内容目录 7 | 8 | ### 1. 概率分布(Probability Distribution) 9 | * [1.1 Binary_Variables](http://nbviewer.ipython.org/github/jasonding1354/PRML_Notes/blob/master/1.PROBABILITY_DISTRIBUTIONS/1.1%20Binary_Variables.ipynb)——二元变量、伯努利分布、二项式分布、Beta分布作为二项式分布的先验概率分布 10 | * [1.2 Multinomial_Variables](http://nbviewer.ipython.org/github/jasonding1354/PRML_Notes/blob/master/1.PROBABILITY_DISTRIBUTIONS/1.2%20Multinomial_Variables.ipynb)——多项式分布、狄利克雷分布 11 | * [1.3 The_Gaussian_Distribution](http://nbviewer.ipython.org/github/jasonding1354/PRML_Notes/blob/master/1.PROBABILITY_DISTRIBUTIONS/1.3%20The_Gaussian_Distribution.ipynb)——高斯分布、高斯分布的几何解释 12 | 13 | 14 | ### p1. Figaro库的介绍 15 | Figaro是一个构造概率性模型的Scala库。在Figaro中,该模型由任意数量的数据结构(称作“元素”)组成。每个元素代表在您的情境中可取任意数量值的一个变量。这些数据结构用Scala实现,您可以用这些数据结构编写Scala程序创建模型。可以通过关于元素值的信息提供证据,也可以指定希望在查询中了解的元素。至于推理算法,您可以选择一个Figaro内建推理算法并应用到模型上,根据证据回答您的查询。推理算法以Scala实现,其调用就是一个Scala函数调用。推理结果是查询元素不同值的概率。 16 | 17 | ![](http://write.epubit.com.cn/api/storage/getbykey/screenshow?key=170396812d6f8339a94a) 18 | * [Figaro的hello world程序](http://nbviewer.jupyter.org/github/jasonding1354/PRML_Notes/blob/master/p1.Figaro_intro/1.figaro_helloworld.ipynb) 19 | * [Figaro的基本元素介绍](http://nbviewer.jupyter.org/github/jasonding1354/PRML_Notes/blob/master/p1.Figaro_intro/2.basic_element.ipynb) 介绍使用Figaro的元素定义常见的概率分布 20 | 21 | ### p2. 使用Figaro编写概率程序 22 | * [使用贝叶斯网络模型进行打印机故障原因的诊断](http://nbviewer.jupyter.org/github/jasonding1354/PRML_Notes/blob/master/p2.Figaro_dependent_model/1.use_bayesian_net_to_diagnose_printer.ipynb) 23 | * []() 24 | -------------------------------------------------------------------------------- /figaro_2.11-4.1.0.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonding1354/PRML_Notes/83612257ee4523034421f3e9810972eceb4f2ebb/figaro_2.11-4.1.0.0.jar -------------------------------------------------------------------------------- /jsci-1.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonding1354/PRML_Notes/83612257ee4523034421f3e9810972eceb4f2ebb/jsci-1.2.jar -------------------------------------------------------------------------------- /p1.Figaro_intro/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonding1354/PRML_Notes/83612257ee4523034421f3e9810972eceb4f2ebb/p1.Figaro_intro/.DS_Store -------------------------------------------------------------------------------- /p1.Figaro_intro/1.figaro_helloworld.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": { 7 | "collapsed": false 8 | }, 9 | "outputs": [ 10 | { 11 | "data": { 12 | "text/plain": [] 13 | }, 14 | "metadata": {}, 15 | "output_type": "display_data" 16 | } 17 | ], 18 | "source": [ 19 | "classpath.addPath(\"../figaro_2.11-4.1.0.0.jar\")" 20 | ] 21 | }, 22 | { 23 | "cell_type": "code", 24 | "execution_count": 3, 25 | "metadata": { 26 | "collapsed": false 27 | }, 28 | "outputs": [ 29 | { 30 | "data": { 31 | "text/plain": [ 32 | "\u001b[32mimport \u001b[36mcom.cra.figaro.language.{Flip, Select}\u001b[0m\n", 33 | "\u001b[32mimport \u001b[36mcom.cra.figaro.library.compound.If\u001b[0m\n", 34 | "\u001b[32mimport \u001b[36mcom.cra.figaro.algorithm.factored.VariableElimination\u001b[0m" 35 | ] 36 | }, 37 | "metadata": {}, 38 | "output_type": "display_data" 39 | } 40 | ], 41 | "source": [ 42 | "import com.cra.figaro.language.{Flip, Select}\n", 43 | "import com.cra.figaro.library.compound.If\n", 44 | "import com.cra.figaro.algorithm.factored.VariableElimination // 变量消除算法" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": 4, 50 | "metadata": { 51 | "collapsed": false 52 | }, 53 | "outputs": [ 54 | { 55 | "data": { 56 | "text/plain": [ 57 | "\u001b[36msunnyToday\u001b[0m: \u001b[32mcom\u001b[0m.\u001b[32mcra\u001b[0m.\u001b[32mfigaro\u001b[0m.\u001b[32mlanguage\u001b[0m.\u001b[32mAtomicFlip\u001b[0m = Flip(0.2)\n", 58 | "\u001b[36mgreetingToday\u001b[0m: \u001b[32mIf\u001b[0m[\u001b[32mString\u001b[0m] = If(Flip(0.2), Select(0.6 -> Hello, world!, 0.4 -> Howdy, universe!), Select(0.2 -> Hello, world!, 0.8 -> Oh no, not again))\n", 59 | "\u001b[36msunnyTomorrow\u001b[0m: \u001b[32mIf\u001b[0m[\u001b[32mBoolean\u001b[0m] = If(Flip(0.2), Flip(0.8), Flip(0.05))\n", 60 | "\u001b[36mgreetingTomorrow\u001b[0m: \u001b[32mIf\u001b[0m[\u001b[32mString\u001b[0m] = If(If(Flip(0.2), Flip(0.8), Flip(0.05)), Select(0.6 -> Hello, world!, 0.4 -> Howdy, universe!), Select(0.2 -> Hello, world!, 0.8 -> Oh no, not again))" 61 | ] 62 | }, 63 | "metadata": {}, 64 | "output_type": "display_data" 65 | } 66 | ], 67 | "source": [ 68 | "// 定义模型\n", 69 | "val sunnyToday = Flip(0.2)\n", 70 | "val greetingToday = If(sunnyToday,\n", 71 | " Select(0.6 -> \"Hello, world!\", 0.4 -> \"Howdy, universe!\"),\n", 72 | " Select(0.2 -> \"Hello, world!\", 0.8 -> \"Oh no, not again\"))\n", 73 | "val sunnyTomorrow = If(sunnyToday, Flip(0.8), Flip(0.05))\n", 74 | "val greetingTomorrow = If(sunnyTomorrow,\n", 75 | " Select(0.6 -> \"Hello, world!\", 0.4 -> \"Howdy, universe!\"),\n", 76 | " Select(0.2 -> \"Hello, world!\", 0.8 -> \"Oh no, not again\"))" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": 5, 82 | "metadata": { 83 | "collapsed": false 84 | }, 85 | "outputs": [ 86 | { 87 | "data": { 88 | "text/plain": [ 89 | "defined \u001b[32mfunction \u001b[36mpredict\u001b[0m" 90 | ] 91 | }, 92 | "metadata": {}, 93 | "output_type": "display_data" 94 | } 95 | ], 96 | "source": [ 97 | "// 用推测算法预测今天的问候语\n", 98 | "def predict() {\n", 99 | " val result = VariableElimination.probability(greetingToday, \"Hello, world!\")\n", 100 | " println(\"Today's greeting is \\\"Hello, world!\\\" \" +\n", 101 | " \"with probability \" + result + \".\")\n", 102 | "}" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": 6, 108 | "metadata": { 109 | "collapsed": false 110 | }, 111 | "outputs": [ 112 | { 113 | "data": { 114 | "text/plain": [ 115 | "defined \u001b[32mfunction \u001b[36minfer\u001b[0m" 116 | ] 117 | }, 118 | "metadata": {}, 119 | "output_type": "display_data" 120 | } 121 | ], 122 | "source": [ 123 | "// 根据今天的问候语是hello world,使用推理算法推理今天的天气\n", 124 | "def infer() {\n", 125 | " greetingToday.observe(\"Hello, world!\")\n", 126 | " val result = VariableElimination.probability(sunnyToday, true)\n", 127 | " println(\"If today's greeting is \\\"Hello, world!\\\", today's \" +\n", 128 | " \"weather is sunny with probability \" + result + \".\")\n", 129 | "}" 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": 7, 135 | "metadata": { 136 | "collapsed": false 137 | }, 138 | "outputs": [ 139 | { 140 | "data": { 141 | "text/plain": [ 142 | "defined \u001b[32mfunction \u001b[36mlearnAndPredict\u001b[0m" 143 | ] 144 | }, 145 | "metadata": {}, 146 | "output_type": "display_data" 147 | } 148 | ], 149 | "source": [ 150 | "// 从今天的问候语是hello world这一观测中学习,用推理算法预测明天的问候语\n", 151 | "def learnAndPredict() {\n", 152 | " greetingToday.observe(\"Hello, world!\")\n", 153 | " val result = VariableElimination.probability(greetingTomorrow, \"Hello, world!\")\n", 154 | " println(\"If today's greeting is \\\"Hello, world!\\\", \" +\n", 155 | " \"tomorrow's greeting will be \\\"Hello, world!\\\" \" +\n", 156 | " \"with probability \" + result + \".\")\n", 157 | "}" 158 | ] 159 | }, 160 | { 161 | "cell_type": "code", 162 | "execution_count": 8, 163 | "metadata": { 164 | "collapsed": false 165 | }, 166 | "outputs": [ 167 | { 168 | "name": "stdout", 169 | "output_type": "stream", 170 | "text": [ 171 | "Today's greeting is \"Hello, world!\" with probability 0.27999999999999997.\n", 172 | "If today's greeting is \"Hello, world!\", today's weather is sunny with probability 0.4285714285714285.\n", 173 | "If today's greeting is \"Hello, world!\", tomorrow's greeting will be \"Hello, world!\" with probability 0.3485714285714286.\n" 174 | ] 175 | }, 176 | { 177 | "data": { 178 | "text/plain": [] 179 | }, 180 | "metadata": {}, 181 | "output_type": "display_data" 182 | } 183 | ], 184 | "source": [ 185 | "// 执行所有任务\n", 186 | "predict()\n", 187 | "infer()\n", 188 | "learnAndPredict()" 189 | ] 190 | }, 191 | { 192 | "cell_type": "markdown", 193 | "metadata": { 194 | "collapsed": true 195 | }, 196 | "source": [ 197 | "### Figaro的关键概念及其组合\n", 198 | "![](./figaro_concept.png)\n", 199 | "Figaro模型用来表达一般知识。您以证据的形式提供关于某种情况的具体知识。查询告诉系统您所感兴趣的发现。Figaro推理算法取得证据并用模型提供查询的答案。\n", 200 | "Figaro的查询通过指明目标元素和您想知道的有关情况指明。您使用某种算法,按照证据找出有关目标元素的信息。通常,您必须实例化某种算法,运行并在之后清理。我已经提供了使用默认设置执行所有步骤的简单方法。在运行算法之后,您可以获得查询的答案。这些算法最常采取目标元素的各种取值概率。有时候,它们没有告诉您概率,而是得出每个目标元素的最可能取值。对于每个目标元素,答案告诉您最高概率的取值。" 201 | ] 202 | }, 203 | { 204 | "cell_type": "code", 205 | "execution_count": null, 206 | "metadata": { 207 | "collapsed": true 208 | }, 209 | "outputs": [], 210 | "source": [] 211 | } 212 | ], 213 | "metadata": { 214 | "anaconda-cloud": {}, 215 | "kernelspec": { 216 | "display_name": "Scala 2.11", 217 | "language": "scala211", 218 | "name": "scala211" 219 | }, 220 | "language_info": { 221 | "codemirror_mode": "text/x-scala", 222 | "file_extension": ".scala", 223 | "mimetype": "text/x-scala", 224 | "name": "scala211", 225 | "pygments_lexer": "scala", 226 | "version": "2.11.8" 227 | } 228 | }, 229 | "nbformat": 4, 230 | "nbformat_minor": 0 231 | } 232 | -------------------------------------------------------------------------------- /p1.Figaro_intro/2.basic_element.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": { 7 | "collapsed": false 8 | }, 9 | "outputs": [ 10 | { 11 | "data": { 12 | "text/plain": [] 13 | }, 14 | "metadata": {}, 15 | "output_type": "display_data" 16 | } 17 | ], 18 | "source": [ 19 | "classpath.addPath(\"../jsci-1.2.jar\")\n", 20 | "classpath.addPath(\"../figaro_2.11-4.1.0.0.jar\")" 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "metadata": {}, 26 | "source": [ 27 | "[Figaro快速教程](http://www.epubit.com.cn/book/onlinechapter/51552)" 28 | ] 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "metadata": {}, 33 | "source": [ 34 | "### 1. 离散分布(离散原子元素)" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": 2, 40 | "metadata": { 41 | "collapsed": false 42 | }, 43 | "outputs": [ 44 | { 45 | "data": { 46 | "text/plain": [ 47 | "\u001b[32mimport \u001b[36mcom.cra.figaro.language._\u001b[0m\n", 48 | "\u001b[32mimport \u001b[36mcom.cra.figaro.algorithm.factored.VariableElimination\u001b[0m" 49 | ] 50 | }, 51 | "metadata": {}, 52 | "output_type": "display_data" 53 | } 54 | ], 55 | "source": [ 56 | "import com.cra.figaro.language._\n", 57 | "import com.cra.figaro.algorithm.factored.VariableElimination" 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": 3, 63 | "metadata": { 64 | "collapsed": false 65 | }, 66 | "outputs": [ 67 | { 68 | "name": "stdout", 69 | "output_type": "stream", 70 | "text": [ 71 | "0.2\n", 72 | "0.8\n" 73 | ] 74 | }, 75 | { 76 | "data": { 77 | "text/plain": [ 78 | "\u001b[36msunnyToday\u001b[0m: \u001b[32mAtomicFlip\u001b[0m = Flip(0.2)" 79 | ] 80 | }, 81 | "metadata": {}, 82 | "output_type": "display_data" 83 | } 84 | ], 85 | "source": [ 86 | "// Flip 伯努利分布\n", 87 | "val sunnyToday = Flip(0.2)\n", 88 | "println(VariableElimination.probability(sunnyToday, true))\n", 89 | "println(VariableElimination.probability(sunnyToday, false))" 90 | ] 91 | }, 92 | { 93 | "cell_type": "code", 94 | "execution_count": 4, 95 | "metadata": { 96 | "collapsed": false 97 | }, 98 | "outputs": [ 99 | { 100 | "name": "stdout", 101 | "output_type": "stream", 102 | "text": [ 103 | "0.30000000000000004\n" 104 | ] 105 | }, 106 | { 107 | "data": { 108 | "text/plain": [ 109 | "\u001b[36mgreeting\u001b[0m: \u001b[32mAtomicSelect\u001b[0m[\u001b[32mString\u001b[0m] = Select(0.6 -> Hello, world!, 0.3 -> Howdy, universe!, 0.1 -> Oh no, not again)" 110 | ] 111 | }, 112 | "metadata": {}, 113 | "output_type": "display_data" 114 | } 115 | ], 116 | "source": [ 117 | "// Select 离散分布\n", 118 | "val greeting = Select(0.6 -> \"Hello, world!\", 0.3 -> \"Howdy, universe!\", 0.1 -> \"Oh no, not again\")\n", 119 | "println(VariableElimination.probability(greeting, \"Howdy, universe!\"))" 120 | ] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "execution_count": 5, 125 | "metadata": { 126 | "collapsed": false 127 | }, 128 | "outputs": [ 129 | { 130 | "data": { 131 | "text/plain": [ 132 | "\u001b[32mimport \u001b[36mcom.cra.figaro.library.atomic.discrete.Binomial\u001b[0m\n", 133 | "\u001b[36mnumSunnyDaysInWeek\u001b[0m: \u001b[32mcom\u001b[0m.\u001b[32mcra\u001b[0m.\u001b[32mfigaro\u001b[0m.\u001b[32mlibrary\u001b[0m.\u001b[32matomic\u001b[0m.\u001b[32mdiscrete\u001b[0m.\u001b[32mAtomicBinomial\u001b[0m = Binomial(7, 0.2)" 134 | ] 135 | }, 136 | "metadata": {}, 137 | "output_type": "display_data" 138 | } 139 | ], 140 | "source": [ 141 | "// Binomial 二项分布\n", 142 | "import com.cra.figaro.library.atomic.discrete.Binomial\n", 143 | "\n", 144 | "val numSunnyDaysInWeek = Binomial(7, 0.2)" 145 | ] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "execution_count": 6, 150 | "metadata": { 151 | "collapsed": false 152 | }, 153 | "outputs": [ 154 | { 155 | "name": "stdout", 156 | "output_type": "stream", 157 | "text": [ 158 | "0.3670016\n" 159 | ] 160 | }, 161 | { 162 | "data": { 163 | "text/plain": [] 164 | }, 165 | "metadata": {}, 166 | "output_type": "display_data" 167 | } 168 | ], 169 | "source": [ 170 | "println(VariableElimination.probability(numSunnyDaysInWeek, 1))\n", 171 | "//java.lang.NoClassDefFoundError: JSci/maths/ExtraMath" 172 | ] 173 | }, 174 | { 175 | "cell_type": "markdown", 176 | "metadata": {}, 177 | "source": [ 178 | "### 2. 连续分布(连续原子元素)" 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "execution_count": 7, 184 | "metadata": { 185 | "collapsed": false 186 | }, 187 | "outputs": [ 188 | { 189 | "data": { 190 | "text/plain": [ 191 | "\u001b[32mimport \u001b[36mcom.cra.figaro.library.atomic.continuous.Normal\u001b[0m\n", 192 | "\u001b[36mtemperature\u001b[0m: \u001b[32mcom\u001b[0m.\u001b[32mcra\u001b[0m.\u001b[32mfigaro\u001b[0m.\u001b[32mlibrary\u001b[0m.\u001b[32matomic\u001b[0m.\u001b[32mcontinuous\u001b[0m.\u001b[32mAtomicNormal\u001b[0m = Normal(40.0, 100.0)" 193 | ] 194 | }, 195 | "metadata": {}, 196 | "output_type": "display_data" 197 | } 198 | ], 199 | "source": [ 200 | "// 正态分布\n", 201 | "import com.cra.figaro.library.atomic.continuous.Normal\n", 202 | "val temperature = Normal(40, 100)" 203 | ] 204 | }, 205 | { 206 | "cell_type": "code", 207 | "execution_count": 8, 208 | "metadata": { 209 | "collapsed": false 210 | }, 211 | "outputs": [ 212 | { 213 | "name": "stdout", 214 | "output_type": "stream", 215 | "text": [ 216 | "0.1607999999999988\n" 217 | ] 218 | }, 219 | { 220 | "data": { 221 | "text/plain": [ 222 | "\u001b[32mimport \u001b[36mcom.cra.figaro.algorithm.sampling.Importance\u001b[0m\n", 223 | "defined \u001b[32mfunction \u001b[36mgreaterThan50\u001b[0m" 224 | ] 225 | }, 226 | "metadata": {}, 227 | "output_type": "display_data" 228 | } 229 | ], 230 | "source": [ 231 | "import com.cra.figaro.algorithm.sampling.Importance\n", 232 | "def greaterThan50(d: Double) = d > 50\n", 233 | "println(Importance.probability(temperature, greaterThan50 _))" 234 | ] 235 | }, 236 | { 237 | "cell_type": "code", 238 | "execution_count": 9, 239 | "metadata": { 240 | "collapsed": false 241 | }, 242 | "outputs": [ 243 | { 244 | "data": { 245 | "text/plain": [ 246 | "\u001b[32mimport \u001b[36mcom.cra.figaro.library.atomic.continuous.Uniform\u001b[0m\n", 247 | "\u001b[36mtemperature2\u001b[0m: \u001b[32mcom\u001b[0m.\u001b[32mcra\u001b[0m.\u001b[32mfigaro\u001b[0m.\u001b[32mlibrary\u001b[0m.\u001b[32matomic\u001b[0m.\u001b[32mcontinuous\u001b[0m.\u001b[32mAtomicUniform\u001b[0m = Uniform(10.0, 70.0)" 248 | ] 249 | }, 250 | "metadata": {}, 251 | "output_type": "display_data" 252 | } 253 | ], 254 | "source": [ 255 | "// 均匀分布\n", 256 | "import com.cra.figaro.library.atomic.continuous.Uniform\n", 257 | "val temperature2 = Uniform(10, 70)" 258 | ] 259 | }, 260 | { 261 | "cell_type": "code", 262 | "execution_count": 10, 263 | "metadata": { 264 | "collapsed": false 265 | }, 266 | "outputs": [ 267 | { 268 | "data": { 269 | "text/plain": [ 270 | "\u001b[36mres9\u001b[0m: \u001b[32mDouble\u001b[0m = \u001b[32m0.33569999999997957\u001b[0m" 271 | ] 272 | }, 273 | "metadata": {}, 274 | "output_type": "display_data" 275 | } 276 | ], 277 | "source": [ 278 | "Importance.probability(temperature2, greaterThan50 _)" 279 | ] 280 | }, 281 | { 282 | "cell_type": "markdown", 283 | "metadata": {}, 284 | "source": [ 285 | "### 3. 复合元素" 286 | ] 287 | }, 288 | { 289 | "cell_type": "markdown", 290 | "metadata": {}, 291 | "source": [ 292 | "#### 3.1 If" 293 | ] 294 | }, 295 | { 296 | "cell_type": "code", 297 | "execution_count": 11, 298 | "metadata": { 299 | "collapsed": false 300 | }, 301 | "outputs": [ 302 | { 303 | "data": { 304 | "text/plain": [ 305 | "\u001b[32mimport \u001b[36mcom.cra.figaro.library.compound.If\u001b[0m\n", 306 | "\u001b[36msunnyToday\u001b[0m: \u001b[32mAtomicFlip\u001b[0m = Flip(0.2)\n", 307 | "\u001b[36mgreetingToday\u001b[0m: \u001b[32mcom\u001b[0m.\u001b[32mcra\u001b[0m.\u001b[32mfigaro\u001b[0m.\u001b[32mlibrary\u001b[0m.\u001b[32mcompound\u001b[0m.\u001b[32mIf\u001b[0m[\u001b[32mString\u001b[0m] = If(Flip(0.2), Select(0.6 -> Hello, world!, 0.4 -> Howdy, universe!), Select(0.2 -> Hello, world!, 0.8 -> Oh no, not again))" 308 | ] 309 | }, 310 | "metadata": {}, 311 | "output_type": "display_data" 312 | } 313 | ], 314 | "source": [ 315 | "// If随机过程,首先检查测试结果,如果测试值是true则生成then子句的值,否则生成else子句的值\n", 316 | "import com.cra.figaro.library.compound.If\n", 317 | "\n", 318 | "val sunnyToday = Flip(0.2)\n", 319 | "val greetingToday = If(sunnyToday, \n", 320 | " Select(0.6 -> \"Hello, world!\", 0.4 -> \"Howdy, universe!\"),\n", 321 | " Select(0.2 -> \"Hello, world!\", 0.8 -> \"Oh no, not again\"))" 322 | ] 323 | }, 324 | { 325 | "cell_type": "code", 326 | "execution_count": 12, 327 | "metadata": { 328 | "collapsed": false 329 | }, 330 | "outputs": [ 331 | { 332 | "name": "stdout", 333 | "output_type": "stream", 334 | "text": [ 335 | "0.27999999999999997\n" 336 | ] 337 | }, 338 | { 339 | "data": { 340 | "text/plain": [] 341 | }, 342 | "metadata": {}, 343 | "output_type": "display_data" 344 | } 345 | ], 346 | "source": [ 347 | "println(VariableElimination.probability(greetingToday, \"Hello, world!\"))" 348 | ] 349 | }, 350 | { 351 | "cell_type": "code", 352 | "execution_count": 13, 353 | "metadata": { 354 | "collapsed": false 355 | }, 356 | "outputs": [ 357 | { 358 | "name": "stdout", 359 | "output_type": "stream", 360 | "text": [ 361 | "0.6\n" 362 | ] 363 | }, 364 | { 365 | "data": { 366 | "text/plain": [] 367 | }, 368 | "metadata": {}, 369 | "output_type": "display_data" 370 | } 371 | ], 372 | "source": [ 373 | "sunnyToday.observe(true)\n", 374 | "println(VariableElimination.probability(greetingToday, \"Hello, world!\"))" 375 | ] 376 | }, 377 | { 378 | "cell_type": "code", 379 | "execution_count": 14, 380 | "metadata": { 381 | "collapsed": false 382 | }, 383 | "outputs": [ 384 | { 385 | "name": "stdout", 386 | "output_type": "stream", 387 | "text": [ 388 | "0.2\n" 389 | ] 390 | }, 391 | { 392 | "data": { 393 | "text/plain": [] 394 | }, 395 | "metadata": {}, 396 | "output_type": "display_data" 397 | } 398 | ], 399 | "source": [ 400 | "sunnyToday.observe(false)\n", 401 | "println(VariableElimination.probability(greetingToday, \"Hello, world!\"))" 402 | ] 403 | }, 404 | { 405 | "cell_type": "markdown", 406 | "metadata": {}, 407 | "source": [ 408 | "#### 3.2 Dist" 409 | ] 410 | }, 411 | { 412 | "cell_type": "code", 413 | "execution_count": 15, 414 | "metadata": { 415 | "collapsed": false 416 | }, 417 | "outputs": [ 418 | { 419 | "data": { 420 | "text/plain": [ 421 | "\u001b[36mgoodMood\u001b[0m: \u001b[32mAtomicDist\u001b[0m[\u001b[32mBoolean\u001b[0m] = Dist(0.2 -> Flip(0.6), 0.8 -> Flip(0.2))" 422 | ] 423 | }, 424 | "metadata": {}, 425 | "output_type": "display_data" 426 | } 427 | ], 428 | "source": [ 429 | "// Dist, 它选择一组元素中的一个而不是选择一组值中的一个\n", 430 | "val goodMood = Dist(0.2 -> Flip(0.6), 0.8 -> Flip(0.2))" 431 | ] 432 | }, 433 | { 434 | "cell_type": "code", 435 | "execution_count": 16, 436 | "metadata": { 437 | "collapsed": false 438 | }, 439 | "outputs": [ 440 | { 441 | "name": "stdout", 442 | "output_type": "stream", 443 | "text": [ 444 | "0.28\n" 445 | ] 446 | }, 447 | { 448 | "data": { 449 | "text/plain": [] 450 | }, 451 | "metadata": {}, 452 | "output_type": "display_data" 453 | } 454 | ], 455 | "source": [ 456 | "// print 0.28 = 0.2*0.6 + 0.8*0.2\n", 457 | "println(VariableElimination.probability(goodMood, true))" 458 | ] 459 | }, 460 | { 461 | "cell_type": "markdown", 462 | "metadata": {}, 463 | "source": [ 464 | "#### 3.3 原子元素的复合版本" 465 | ] 466 | }, 467 | { 468 | "cell_type": "code", 469 | "execution_count": 17, 470 | "metadata": { 471 | "collapsed": false 472 | }, 473 | "outputs": [ 474 | { 475 | "name": "stdout", 476 | "output_type": "stream", 477 | "text": [ 478 | "0.2602000000000055\n" 479 | ] 480 | }, 481 | { 482 | "data": { 483 | "text/plain": [ 484 | "\u001b[36msunnyTodayProbability\u001b[0m: \u001b[32mcom\u001b[0m.\u001b[32mcra\u001b[0m.\u001b[32mfigaro\u001b[0m.\u001b[32mlibrary\u001b[0m.\u001b[32matomic\u001b[0m.\u001b[32mcontinuous\u001b[0m.\u001b[32mAtomicUniform\u001b[0m = Uniform(0.0, 0.5)\n", 485 | "\u001b[36msunnyToday\u001b[0m: \u001b[32mFlip\u001b[0m = Flip(Uniform(0.0, 0.5))" 486 | ] 487 | }, 488 | "metadata": {}, 489 | "output_type": "display_data" 490 | } 491 | ], 492 | "source": [ 493 | "// 晴天的概率不确定\n", 494 | "val sunnyTodayProbability = Uniform(0, 0.5)\n", 495 | "val sunnyToday = Flip(sunnyTodayProbability)\n", 496 | "println(Importance.probability(sunnyToday, true))" 497 | ] 498 | }, 499 | { 500 | "cell_type": "code", 501 | "execution_count": 18, 502 | "metadata": { 503 | "collapsed": false 504 | }, 505 | "outputs": [ 506 | { 507 | "name": "stdout", 508 | "output_type": "stream", 509 | "text": [ 510 | "0.1654999999999983\n" 511 | ] 512 | }, 513 | { 514 | "data": { 515 | "text/plain": [ 516 | "\u001b[36mtempMean\u001b[0m: \u001b[32mcom\u001b[0m.\u001b[32mcra\u001b[0m.\u001b[32mfigaro\u001b[0m.\u001b[32mlibrary\u001b[0m.\u001b[32matomic\u001b[0m.\u001b[32mcontinuous\u001b[0m.\u001b[32mAtomicNormal\u001b[0m = Normal(40.0, 9.0)\n", 517 | "\u001b[36mtempVariance\u001b[0m: \u001b[32mAtomicSelect\u001b[0m[\u001b[32mDouble\u001b[0m] = Select(0.5 -> 80.0, 0.5 -> 105.0)\n", 518 | "\u001b[36mtemperature\u001b[0m: \u001b[32mcom\u001b[0m.\u001b[32mcra\u001b[0m.\u001b[32mfigaro\u001b[0m.\u001b[32mlibrary\u001b[0m.\u001b[32matomic\u001b[0m.\u001b[32mcontinuous\u001b[0m.\u001b[32mCompoundNormal\u001b[0m = Normal(Normal(40.0, 9.0), Select(0.5 -> 80.0, 0.5 -> 105.0))" 519 | ] 520 | }, 521 | "metadata": {}, 522 | "output_type": "display_data" 523 | } 524 | ], 525 | "source": [ 526 | "// 均值和方差都不确定\n", 527 | "val tempMean = Normal(40, 9)\n", 528 | "val tempVariance = Select(0.5 -> 80.0, 0.5 -> 105.0)\n", 529 | "val temperature = Normal(tempMean, tempVariance)\n", 530 | "println(Importance.probability(temperature, (d: Double) => d > 50))" 531 | ] 532 | }, 533 | { 534 | "cell_type": "markdown", 535 | "metadata": {}, 536 | "source": [ 537 | "### 4. Apply和Chain构建更复杂的模型" 538 | ] 539 | }, 540 | { 541 | "cell_type": "markdown", 542 | "metadata": {}, 543 | "source": [ 544 | "#### 4.1 Apply\n", 545 | "Apply以一个元素和一个Scala函数作为参数,它代表将Scala函数应用到该元素值以获得新值的过程。" 546 | ] 547 | }, 548 | { 549 | "cell_type": "code", 550 | "execution_count": 19, 551 | "metadata": { 552 | "collapsed": false 553 | }, 554 | "outputs": [ 555 | { 556 | "data": { 557 | "text/plain": [ 558 | "\u001b[36msunnyDaysInMonth\u001b[0m: \u001b[32mcom\u001b[0m.\u001b[32mcra\u001b[0m.\u001b[32mfigaro\u001b[0m.\u001b[32mlibrary\u001b[0m.\u001b[32matomic\u001b[0m.\u001b[32mdiscrete\u001b[0m.\u001b[32mAtomicBinomial\u001b[0m = Binomial(30, 0.2)\n", 559 | "defined \u001b[32mfunction \u001b[36mgetQuality\u001b[0m\n", 560 | "\u001b[36mmonthQuality\u001b[0m: \u001b[32mApply1\u001b[0m[\u001b[32mInt\u001b[0m, \u001b[32mString\u001b[0m] = Apply(Binomial(30, 0.2), )" 561 | ] 562 | }, 563 | "metadata": {}, 564 | "output_type": "display_data" 565 | } 566 | ], 567 | "source": [ 568 | "val sunnyDaysInMonth = Binomial(30, 0.2)\n", 569 | "def getQuality(i: Int): String =\n", 570 | " if(i > 10) \"good\"; else if (i > 5) \"average\"; else \"poor\"\n", 571 | "val monthQuality = Apply(sunnyDaysInMonth, getQuality)" 572 | ] 573 | }, 574 | { 575 | "cell_type": "code", 576 | "execution_count": 20, 577 | "metadata": { 578 | "collapsed": false 579 | }, 580 | "outputs": [ 581 | { 582 | "name": "stdout", 583 | "output_type": "stream", 584 | "text": [ 585 | "0.025616255335326694\n" 586 | ] 587 | }, 588 | { 589 | "data": { 590 | "text/plain": [] 591 | }, 592 | "metadata": {}, 593 | "output_type": "display_data" 594 | } 595 | ], 596 | "source": [ 597 | "println(VariableElimination.probability(monthQuality, \"good\"))" 598 | ] 599 | }, 600 | { 601 | "cell_type": "markdown", 602 | "metadata": {}, 603 | "source": [ 604 | "Apply元素定义随机过程,它首先生成第一个元素参数的值,然后,该过程取得第二个函数参数,并将其应用到生成的值。" 605 | ] 606 | }, 607 | { 608 | "cell_type": "markdown", 609 | "metadata": {}, 610 | "source": [ 611 | "#### 4.2 Chain\n", 612 | "Chain用于将元素链接为一个模型,模型中的元素依赖于另一个元素,那个元素又依赖其他的元素,以此类推。这和概率的链式法则相关。\n", 613 | "Chain和Apply之间的差别是**Apply中的函数返回常规的Scala值,而Chain中的函数返回一个元素。**" 614 | ] 615 | }, 616 | { 617 | "cell_type": "code", 618 | "execution_count": 21, 619 | "metadata": { 620 | "collapsed": false 621 | }, 622 | "outputs": [ 623 | { 624 | "data": { 625 | "text/plain": [ 626 | "\u001b[36mgoodMood\u001b[0m: \u001b[32mChain\u001b[0m[\u001b[32mString\u001b[0m, \u001b[32mBoolean\u001b[0m] = Chain(Apply(Binomial(30, 0.2), ), )" 627 | ] 628 | }, 629 | "metadata": {}, 630 | "output_type": "display_data" 631 | } 632 | ], 633 | "source": [ 634 | "val goodMood = Chain(monthQuality, (s: String) =>\n", 635 | " if(s == \"good\") Flip(0.9)\n", 636 | " else if (s == \"average\") Flip(0.6)\n", 637 | " else Flip(0.1))" 638 | ] 639 | }, 640 | { 641 | "cell_type": "code", 642 | "execution_count": 22, 643 | "metadata": { 644 | "collapsed": false 645 | }, 646 | "outputs": [ 647 | { 648 | "name": "stdout", 649 | "output_type": "stream", 650 | "text": [ 651 | "0.3939286578054374\n" 652 | ] 653 | }, 654 | { 655 | "data": { 656 | "text/plain": [] 657 | }, 658 | "metadata": {}, 659 | "output_type": "display_data" 660 | } 661 | ], 662 | "source": [ 663 | "println(VariableElimination.probability(goodMood, true))" 664 | ] 665 | }, 666 | { 667 | "cell_type": "markdown", 668 | "metadata": {}, 669 | "source": [ 670 | "### 5. 条件和约束指定证据" 671 | ] 672 | }, 673 | { 674 | "cell_type": "markdown", 675 | "metadata": {}, 676 | "source": [ 677 | "#### 5.1 观测值" 678 | ] 679 | }, 680 | { 681 | "cell_type": "code", 682 | "execution_count": 23, 683 | "metadata": { 684 | "collapsed": false 685 | }, 686 | "outputs": [ 687 | { 688 | "data": { 689 | "text/plain": [] 690 | }, 691 | "metadata": {}, 692 | "output_type": "display_data" 693 | } 694 | ], 695 | "source": [ 696 | "greetingToday.observe(\"Hello, world!\")" 697 | ] 698 | }, 699 | { 700 | "cell_type": "code", 701 | "execution_count": 24, 702 | "metadata": { 703 | "collapsed": false 704 | }, 705 | "outputs": [ 706 | { 707 | "name": "stdout", 708 | "output_type": "stream", 709 | "text": [ 710 | "Warning: you are using a factored algorithm with continuous or infinite elements. The element will be sampled 15 times\n", 711 | "0.23561405398220533\n" 712 | ] 713 | }, 714 | { 715 | "data": { 716 | "text/plain": [] 717 | }, 718 | "metadata": {}, 719 | "output_type": "display_data" 720 | } 721 | ], 722 | "source": [ 723 | "println(VariableElimination.probability(sunnyToday, true))" 724 | ] 725 | }, 726 | { 727 | "cell_type": "code", 728 | "execution_count": 25, 729 | "metadata": { 730 | "collapsed": false 731 | }, 732 | "outputs": [ 733 | { 734 | "data": { 735 | "text/plain": [] 736 | }, 737 | "metadata": {}, 738 | "output_type": "display_data" 739 | } 740 | ], 741 | "source": [ 742 | "greetingToday.unobserve()" 743 | ] 744 | }, 745 | { 746 | "cell_type": "code", 747 | "execution_count": 26, 748 | "metadata": { 749 | "collapsed": false 750 | }, 751 | "outputs": [ 752 | { 753 | "name": "stdout", 754 | "output_type": "stream", 755 | "text": [ 756 | "0.23561405398220536\n" 757 | ] 758 | }, 759 | { 760 | "data": { 761 | "text/plain": [] 762 | }, 763 | "metadata": {}, 764 | "output_type": "display_data" 765 | } 766 | ], 767 | "source": [ 768 | "println(VariableElimination.probability(sunnyToday, true))" 769 | ] 770 | }, 771 | { 772 | "cell_type": "markdown", 773 | "metadata": {}, 774 | "source": [ 775 | "#### 5.2 条件\n", 776 | "observe指定元素的特定值,条件指定一个布尔函数。" 777 | ] 778 | }, 779 | { 780 | "cell_type": "markdown", 781 | "metadata": {}, 782 | "source": [ 783 | "``` scala\n", 784 | "val sunnyDaysInMonth = Binomial(30, 0.2)\n", 785 | "def getQuality(i: Int): String =\n", 786 | " if(i > 10) \"good\"; else if (i > 5) \"average\"; else \"poor\"\n", 787 | "val monthQuality = Apply(sunnyDaysInMonth, getQuality)\n", 788 | "val goodMood = Chain(monthQuality, (s: String) =>\n", 789 | " if(s == \"good\") Flip(0.9)\n", 790 | " else if (s == \"average\") Flip(0.6)\n", 791 | " else Flip(0.1))\n", 792 | "```" 793 | ] 794 | }, 795 | { 796 | "cell_type": "code", 797 | "execution_count": 27, 798 | "metadata": { 799 | "collapsed": false 800 | }, 801 | "outputs": [ 802 | { 803 | "name": "stdout", 804 | "output_type": "stream", 805 | "text": [ 806 | "0.3939286578054374\n" 807 | ] 808 | }, 809 | { 810 | "data": { 811 | "text/plain": [] 812 | }, 813 | "metadata": {}, 814 | "output_type": "display_data" 815 | } 816 | ], 817 | "source": [ 818 | "println(VariableElimination.probability(goodMood, true))" 819 | ] 820 | }, 821 | { 822 | "cell_type": "code", 823 | "execution_count": 30, 824 | "metadata": { 825 | "collapsed": false 826 | }, 827 | "outputs": [ 828 | { 829 | "name": "stdout", 830 | "output_type": "stream", 831 | "text": [ 832 | "0.6597344078195808\n" 833 | ] 834 | }, 835 | { 836 | "data": { 837 | "text/plain": [] 838 | }, 839 | "metadata": {}, 840 | "output_type": "display_data" 841 | } 842 | ], 843 | "source": [ 844 | "// 规定sunnyDaysInMonth必须大于8,好心情的概率明显上升\n", 845 | "sunnyDaysInMonth.setCondition((i: Int) => i > 8)\n", 846 | "println(VariableElimination.probability(goodMood, true))" 847 | ] 848 | }, 849 | { 850 | "cell_type": "code", 851 | "execution_count": 31, 852 | "metadata": { 853 | "collapsed": false 854 | }, 855 | "outputs": [ 856 | { 857 | "name": "stdout", 858 | "output_type": "stream", 859 | "text": [ 860 | "0.9\n" 861 | ] 862 | }, 863 | { 864 | "data": { 865 | "text/plain": [] 866 | }, 867 | "metadata": {}, 868 | "output_type": "display_data" 869 | } 870 | ], 871 | "source": [ 872 | "// sunnyDaysInMonth必须比3的倍数大2,排除9和10等等情况的可能\n", 873 | "sunnyDaysInMonth.addCondition((i: Int) => i % 3 == 2)\n", 874 | "println(VariableElimination.probability(goodMood, true))" 875 | ] 876 | }, 877 | { 878 | "cell_type": "code", 879 | "execution_count": 32, 880 | "metadata": { 881 | "collapsed": false 882 | }, 883 | "outputs": [ 884 | { 885 | "name": "stdout", 886 | "output_type": "stream", 887 | "text": [ 888 | "0.3939286578054374\n" 889 | ] 890 | }, 891 | { 892 | "data": { 893 | "text/plain": [] 894 | }, 895 | "metadata": {}, 896 | "output_type": "display_data" 897 | } 898 | ], 899 | "source": [ 900 | "sunnyDaysInMonth.removeConditions()\n", 901 | "println(VariableElimination.probability(goodMood, true))" 902 | ] 903 | }, 904 | { 905 | "cell_type": "markdown", 906 | "metadata": {}, 907 | "source": [ 908 | "#### 5.3 约束\n", 909 | "约束是从一个元素值到Double类型的函数,约束改变不同状态的概率。" 910 | ] 911 | }, 912 | { 913 | "cell_type": "code", 914 | "execution_count": 33, 915 | "metadata": { 916 | "collapsed": false 917 | }, 918 | "outputs": [ 919 | { 920 | "data": { 921 | "text/plain": [] 922 | }, 923 | "metadata": {}, 924 | "output_type": "display_data" 925 | } 926 | ], 927 | "source": [ 928 | "// 表示为goodMood为true的可能性只是false的一半\n", 929 | "goodMood.addConstraint((b: Boolean) => if(b) 0.5; else 1.0)" 930 | ] 931 | }, 932 | { 933 | "cell_type": "code", 934 | "execution_count": 34, 935 | "metadata": { 936 | "collapsed": false 937 | }, 938 | "outputs": [ 939 | { 940 | "name": "stdout", 941 | "output_type": "stream", 942 | "text": [ 943 | "0.24527469450215497\n" 944 | ] 945 | }, 946 | { 947 | "data": { 948 | "text/plain": [] 949 | }, 950 | "metadata": {}, 951 | "output_type": "display_data" 952 | } 953 | ], 954 | "source": [ 955 | "println(VariableElimination.probability(goodMood, true))" 956 | ] 957 | }, 958 | { 959 | "cell_type": "markdown", 960 | "metadata": {}, 961 | "source": [ 962 | "作为连接元素的约束" 963 | ] 964 | }, 965 | { 966 | "cell_type": "code", 967 | "execution_count": 35, 968 | "metadata": { 969 | "collapsed": false 970 | }, 971 | "outputs": [ 972 | { 973 | "data": { 974 | "text/plain": [ 975 | "\u001b[36mresult1\u001b[0m: \u001b[32mAtomicFlip\u001b[0m = Flip(0.4)\n", 976 | "\u001b[36mresult2\u001b[0m: \u001b[32mAtomicFlip\u001b[0m = Flip(0.4)\n", 977 | "\u001b[36mresult3\u001b[0m: \u001b[32mAtomicFlip\u001b[0m = Flip(0.4)" 978 | ] 979 | }, 980 | "metadata": {}, 981 | "output_type": "display_data" 982 | } 983 | ], 984 | "source": [ 985 | "// 定义三场比赛的结果\n", 986 | "val result1 = Flip(0.4)\n", 987 | "val result2 = Flip(0.4)\n", 988 | "val result3 = Flip(0.4)" 989 | ] 990 | }, 991 | { 992 | "cell_type": "code", 993 | "execution_count": 36, 994 | "metadata": { 995 | "collapsed": false 996 | }, 997 | "outputs": [ 998 | { 999 | "data": { 1000 | "text/plain": [ 1001 | "\u001b[36mallWins\u001b[0m: \u001b[32mApply3\u001b[0m[\u001b[32mBoolean\u001b[0m, \u001b[32mBoolean\u001b[0m, \u001b[32mBoolean\u001b[0m, \u001b[32mBoolean\u001b[0m] = Apply(Flip(0.4), Flip(0.4), Flip(0.4), )" 1002 | ] 1003 | }, 1004 | "metadata": {}, 1005 | "output_type": "display_data" 1006 | } 1007 | ], 1008 | "source": [ 1009 | "val allWins = Apply(result1, result2, result3,\n", 1010 | " (w1: Boolean, w2: Boolean, w3: Boolean) => w1 && w2 && w3)" 1011 | ] 1012 | }, 1013 | { 1014 | "cell_type": "code", 1015 | "execution_count": 37, 1016 | "metadata": { 1017 | "collapsed": false 1018 | }, 1019 | "outputs": [ 1020 | { 1021 | "name": "stdout", 1022 | "output_type": "stream", 1023 | "text": [ 1024 | "0.06400000000000002\n" 1025 | ] 1026 | }, 1027 | { 1028 | "data": { 1029 | "text/plain": [] 1030 | }, 1031 | "metadata": {}, 1032 | "output_type": "display_data" 1033 | } 1034 | ], 1035 | "source": [ 1036 | "println(VariableElimination.probability(allWins, true))" 1037 | ] 1038 | }, 1039 | { 1040 | "cell_type": "code", 1041 | "execution_count": 38, 1042 | "metadata": { 1043 | "collapsed": false 1044 | }, 1045 | "outputs": [ 1046 | { 1047 | "data": { 1048 | "text/plain": [ 1049 | "defined \u001b[32mfunction \u001b[36mmakeStreaky\u001b[0m" 1050 | ] 1051 | }, 1052 | "metadata": {}, 1053 | "output_type": "display_data" 1054 | } 1055 | ], 1056 | "source": [ 1057 | "def makeStreaky(r1: Element[Boolean], r2: Element[Boolean]) {\n", 1058 | " val pair = Apply(r1, r2, (b1: Boolean, b2: Boolean) => (b1, b2))\n", 1059 | " pair.setConstraint((bb: (Boolean, Boolean)) =>\n", 1060 | " if(bb._1 == bb._2) 1.0; else 0.5)\n", 1061 | "}" 1062 | ] 1063 | }, 1064 | { 1065 | "cell_type": "code", 1066 | "execution_count": 39, 1067 | "metadata": { 1068 | "collapsed": false 1069 | }, 1070 | "outputs": [ 1071 | { 1072 | "name": "stdout", 1073 | "output_type": "stream", 1074 | "text": [ 1075 | "0.11034482758620692\n" 1076 | ] 1077 | }, 1078 | { 1079 | "data": { 1080 | "text/plain": [] 1081 | }, 1082 | "metadata": {}, 1083 | "output_type": "display_data" 1084 | } 1085 | ], 1086 | "source": [ 1087 | "// 由于描述了相邻比赛的连续性,使得比赛全胜的概率增加\n", 1088 | "makeStreaky(result1, result2)\n", 1089 | "makeStreaky(result2, result3)\n", 1090 | "println(VariableElimination.probability(allWins, true))" 1091 | ] 1092 | } 1093 | ], 1094 | "metadata": { 1095 | "kernelspec": { 1096 | "display_name": "Scala 2.11", 1097 | "language": "scala211", 1098 | "name": "scala211" 1099 | }, 1100 | "language_info": { 1101 | "codemirror_mode": "text/x-scala", 1102 | "file_extension": ".scala", 1103 | "mimetype": "text/x-scala", 1104 | "name": "scala211", 1105 | "pygments_lexer": "scala", 1106 | "version": "2.11.8" 1107 | } 1108 | }, 1109 | "nbformat": 4, 1110 | "nbformat_minor": 0 1111 | } 1112 | -------------------------------------------------------------------------------- /p1.Figaro_intro/figaro_concept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonding1354/PRML_Notes/83612257ee4523034421f3e9810972eceb4f2ebb/p1.Figaro_intro/figaro_concept.png -------------------------------------------------------------------------------- /p2.Figaro_dependent_model/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonding1354/PRML_Notes/83612257ee4523034421f3e9810972eceb4f2ebb/p2.Figaro_dependent_model/.DS_Store -------------------------------------------------------------------------------- /p2.Figaro_dependent_model/1.use_bayesian_net_to_diagnose_printer.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": { 7 | "collapsed": false 8 | }, 9 | "outputs": [ 10 | { 11 | "data": { 12 | "text/plain": [] 13 | }, 14 | "metadata": {}, 15 | "output_type": "display_data" 16 | } 17 | ], 18 | "source": [ 19 | "classpath.addPath(\"../jsci-1.2.jar\")\n", 20 | "classpath.addPath(\"../figaro_2.11-4.1.0.0.jar\")" 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "metadata": {}, 26 | "source": [ 27 | "### 打印机模型的贝叶斯网络结构\n", 28 | "![](./printer_state.jpeg)\n", 29 | "### 系统诊断模型中的网络结构\n", 30 | "![](./print_result_summary.jpeg)" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": 7, 36 | "metadata": { 37 | "collapsed": false 38 | }, 39 | "outputs": [ 40 | { 41 | "data": { 42 | "text/plain": [ 43 | "\u001b[32mimport \u001b[36mcom.cra.figaro.language._\u001b[0m\n", 44 | "\u001b[32mimport \u001b[36mcom.cra.figaro.library.compound._\u001b[0m" 45 | ] 46 | }, 47 | "metadata": {}, 48 | "output_type": "display_data" 49 | } 50 | ], 51 | "source": [ 52 | "import com.cra.figaro.language._\n", 53 | "import com.cra.figaro.library.compound._" 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": 5, 59 | "metadata": { 60 | "collapsed": false 61 | }, 62 | "outputs": [ 63 | { 64 | "data": { 65 | "text/plain": [ 66 | "\u001b[36mprinterPowerButtonOn\u001b[0m: \u001b[32mAtomicFlip\u001b[0m = Flip(0.95)\n", 67 | "\u001b[36mtonerLevel\u001b[0m: \u001b[32mAtomicSelect\u001b[0m[\u001b[32mSymbol\u001b[0m] = Select(0.7 -> 'high, 0.2 -> 'low, 0.1 -> 'out)\n", 68 | "\u001b[36mtonerLowIndicatorOn\u001b[0m: \u001b[32mIf\u001b[0m[\u001b[32mBoolean\u001b[0m] = If(Flip(0.95), Chain(Select(0.7 -> 'high, 0.2 -> 'low, 0.1 -> 'out), ), Constant(false))\n", 69 | "\u001b[36mpaperFlow\u001b[0m: \u001b[32mAtomicSelect\u001b[0m[\u001b[32mSymbol\u001b[0m] = Select(0.6 -> 'smooth, 0.2 -> 'uneven, 0.2 -> 'jammed)\n", 70 | "\u001b[36mpaperJamIndicatorOn\u001b[0m: \u001b[32mIf\u001b[0m[\u001b[32mBoolean\u001b[0m] = If(Flip(0.95), Chain(Select(0.6 -> 'smooth, 0.2 -> 'uneven, 0.2 -> 'jammed), ), Constant(false))\n", 71 | "\u001b[36mprinterState\u001b[0m: \u001b[32mApply3\u001b[0m[\u001b[32mBoolean\u001b[0m, \u001b[32mSymbol\u001b[0m, \u001b[32mSymbol\u001b[0m, \u001b[32mSymbol\u001b[0m] = Apply(Flip(0.95), Select(0.7 -> 'high, 0.2 -> 'low, 0.1 -> 'out), Select(0.6 -> 'smooth, 0.2 -> 'uneven, 0.2 -> 'jammed), )" 72 | ] 73 | }, 74 | "metadata": {}, 75 | "output_type": "display_data" 76 | } 77 | ], 78 | "source": [ 79 | "// 打印机模型\n", 80 | "val printerPowerButtonOn = Flip(0.95)\n", 81 | "val tonerLevel = Select(0.7 -> 'high, 0.2 -> 'low, 0.1 -> 'out)\n", 82 | "val tonerLowIndicatorOn = \n", 83 | " If(printerPowerButtonOn,\n", 84 | " CPD(tonerLevel,\n", 85 | " 'high -> Flip(0.2),\n", 86 | " 'low -> Flip(0.6),\n", 87 | " 'out -> Flip(0.99)),\n", 88 | " Constant(false))\n", 89 | "val paperFlow = Select(0.6 -> 'smooth, 0.2 -> 'uneven, 0.2 -> 'jammed)\n", 90 | " \n", 91 | "val paperJamIndicatorOn =\n", 92 | " If(printerPowerButtonOn, \n", 93 | " CPD(paperFlow,\n", 94 | " 'smooth -> Flip(0.1),\n", 95 | " 'uneven -> Flip(0.3),\n", 96 | " 'jammed -> Flip(0.99)),\n", 97 | " Constant(false))\n", 98 | "\n", 99 | "val printerState = \n", 100 | " Apply(printerPowerButtonOn, tonerLevel, paperFlow,\n", 101 | " (power: Boolean, toner: Symbol, paper: Symbol) => {\n", 102 | " if(power) {\n", 103 | " if(toner == 'high && paper == 'smooth) 'good\n", 104 | " else if(toner == 'out || paper == 'jammed) 'out\n", 105 | " else 'poor\n", 106 | " } else 'out\n", 107 | " })" 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": 8, 113 | "metadata": { 114 | "collapsed": false 115 | }, 116 | "outputs": [ 117 | { 118 | "data": { 119 | "text/plain": [ 120 | "\u001b[36msoftwareState\u001b[0m: \u001b[32mAtomicSelect\u001b[0m[\u001b[32mSymbol\u001b[0m] = Select(0.8 -> 'correct, 0.15 -> 'glitchy, 0.05 -> 'crashed)\n", 121 | "\u001b[36mnetworkState\u001b[0m: \u001b[32mAtomicSelect\u001b[0m[\u001b[32mSymbol\u001b[0m] = Select(0.7 -> 'up, 0.2 -> 'intermittent, 0.1 -> 'down)\n", 122 | "\u001b[36muserCommandCorrect\u001b[0m: \u001b[32mAtomicFlip\u001b[0m = Flip(0.65)\n", 123 | "\u001b[36mnumPrintedPages\u001b[0m: \u001b[32mRichCPD4\u001b[0m[\u001b[32mBoolean\u001b[0m, \u001b[32mSymbol\u001b[0m, \u001b[32mSymbol\u001b[0m, \u001b[32mSymbol\u001b[0m, \u001b[32mSymbol\u001b[0m] = Chain(Apply(Flip(0.65), Select(0.7 -> 'up, 0.2 -> 'intermittent, 0.1 -> 'down), Select(0.8 -> 'correct, 0.15 -> 'glitchy, 0.05 -> 'crashed), Apply(Flip(0.95), Select(0.7 -> 'high, 0.2 -> 'low, 0.1 -> 'out), Select(0.6 -> 'smooth, 0.2 -> 'uneven, 0.2 -> 'jammed), ), ), )\n", 124 | "\u001b[36mprintsQuickly\u001b[0m: \u001b[32mChain\u001b[0m[(\u001b[32mSymbol\u001b[0m, \u001b[32mSymbol\u001b[0m), \u001b[32mBoolean\u001b[0m] = Chain(Apply(Select(0.7 -> 'up, 0.2 -> 'intermittent, 0.1 -> 'down), Select(0.8 -> 'correct, 0.15 -> 'glitchy, 0.05 -> 'crashed), ), )\n", 125 | "\u001b[36mgoodPrintQuality\u001b[0m: \u001b[32mCPD1\u001b[0m[\u001b[32mSymbol\u001b[0m, \u001b[32mBoolean\u001b[0m] = Chain(Apply(Flip(0.95), Select(0.7 -> 'high, 0.2 -> 'low, 0.1 -> 'out), Select(0.6 -> 'smooth, 0.2 -> 'uneven, 0.2 -> 'jammed), ), )\n", 126 | "\u001b[36mprintResultSummary\u001b[0m: \u001b[32mApply3\u001b[0m[\u001b[32mSymbol\u001b[0m, \u001b[32mBoolean\u001b[0m, \u001b[32mBoolean\u001b[0m, \u001b[32mSymbol\u001b[0m] = Apply(Chain(Apply(Flip(0.65), Select(0.7 -> 'up, 0.2 -> 'intermittent, 0.1 -> 'down), Select(0.8 -> 'correct, 0.15 -> 'glitchy, 0.05 -> 'crashed), Apply(Flip(0.95), Select(0.7 -> 'high, 0.2 -> 'low, 0.1 -> 'out), Select(0.6 -> 'smooth, 0.2 -> 'uneven, 0.2 -> 'jammed), ), ), ), Chain(Apply(Select(0.7 -> 'up, 0.2 -> 'intermittent, 0.1 -> 'down), Select(0.8 -> 'correct, 0.15 -> 'glitchy, 0.05 -> 'crashed), ), ), Chain(Apply(Flip(0.95), Select(0.7 -> 'high, 0.2 -> 'low, 0.1 -> 'out), Select(0.6 -> 'smooth, 0.2 -> 'uneven, 0.2 -> 'jammed), ), ), )" 127 | ] 128 | }, 129 | "metadata": {}, 130 | "output_type": "display_data" 131 | } 132 | ], 133 | "source": [ 134 | "// 打印机故障模型\n", 135 | "val softwareState = \n", 136 | " Select(0.8 -> 'correct, 0.15 -> 'glitchy, 0.05 -> 'crashed)\n", 137 | "val networkState = \n", 138 | " Select(0.7 -> 'up, 0.2 -> 'intermittent, 0.1 -> 'down)\n", 139 | "val userCommandCorrect = Flip(0.65)\n", 140 | "\n", 141 | "val numPrintedPages = \n", 142 | " RichCPD(userCommandCorrect, networkState,\n", 143 | " softwareState, printerState,\n", 144 | " (*, *, *, OneOf('out)) -> Constant('zero),\n", 145 | " (*, *, OneOf('crashed), *) -> Constant('zero),\n", 146 | " (*, OneOf('down), *, *) -> Constant('zero),\n", 147 | " (OneOf(false), *, *, *) -> Select(0.3 -> 'zero, 0.6 -> 'some, 0.1 -> 'all),\n", 148 | " (OneOf(true), *, *, *) -> Select(0.01 -> 'zero, 0.01 -> 'some, 0.98 -> 'all))\n", 149 | "\n", 150 | "val printsQuickly = \n", 151 | " Chain(networkState, softwareState,\n", 152 | " (network: Symbol, software: Symbol) => \n", 153 | " if(network == 'down || software == 'crashed)\n", 154 | " Constant(false)\n", 155 | " else if(network == 'intermittent || software == 'glitchy)\n", 156 | " Flip(0.5)\n", 157 | " else Flip(0.9))\n", 158 | "\n", 159 | "val goodPrintQuality =\n", 160 | " CPD(printerState,\n", 161 | " 'good -> Flip(0.95),\n", 162 | " 'poor -> Flip(0.3),\n", 163 | " 'out -> Constant(false))\n", 164 | "\n", 165 | "val printResultSummary = \n", 166 | " Apply(numPrintedPages, printsQuickly, goodPrintQuality,\n", 167 | " (pages: Symbol, quickly: Boolean, quality: Boolean) =>\n", 168 | " if(pages == 'zero) 'none\n", 169 | " else if(pages == 'some || !quickly == !quality) 'poor\n", 170 | " else 'excellent)" 171 | ] 172 | }, 173 | { 174 | "cell_type": "code", 175 | "execution_count": 9, 176 | "metadata": { 177 | "collapsed": false 178 | }, 179 | "outputs": [ 180 | { 181 | "data": { 182 | "text/plain": [ 183 | "\u001b[32mimport \u001b[36mcom.cra.figaro.algorithm.factored.VariableElimination\u001b[0m" 184 | ] 185 | }, 186 | "metadata": {}, 187 | "output_type": "display_data" 188 | } 189 | ], 190 | "source": [ 191 | "import com.cra.figaro.algorithm.factored.VariableElimination" 192 | ] 193 | }, 194 | { 195 | "cell_type": "code", 196 | "execution_count": 10, 197 | "metadata": { 198 | "collapsed": false 199 | }, 200 | "outputs": [ 201 | { 202 | "name": "stdout", 203 | "output_type": "stream", 204 | "text": [ 205 | "Prior probability the printer power button is on = 0.95\n" 206 | ] 207 | }, 208 | { 209 | "data": { 210 | "text/plain": [ 211 | "\u001b[36manswerWithNoEvidence\u001b[0m: \u001b[32mDouble\u001b[0m = \u001b[32m0.95\u001b[0m" 212 | ] 213 | }, 214 | "metadata": {}, 215 | "output_type": "display_data" 216 | } 217 | ], 218 | "source": [ 219 | "// 1. 没有数据时,打印机电源按钮开启的先验概率\n", 220 | "val answerWithNoEvidence = VariableElimination.probability(printerPowerButtonOn, true)\n", 221 | "println(\"Prior probability the printer power button is on = \" + answerWithNoEvidence)" 222 | ] 223 | }, 224 | { 225 | "cell_type": "code", 226 | "execution_count": 11, 227 | "metadata": { 228 | "collapsed": false 229 | }, 230 | "outputs": [ 231 | { 232 | "name": "stdout", 233 | "output_type": "stream", 234 | "text": [ 235 | "Probability the printer power button is on given a poor result = 1.0\n" 236 | ] 237 | }, 238 | { 239 | "data": { 240 | "text/plain": [ 241 | "\u001b[36manswerIfPrintResultPoor\u001b[0m: \u001b[32mDouble\u001b[0m = \u001b[32m1.0\u001b[0m" 242 | ] 243 | }, 244 | "metadata": {}, 245 | "output_type": "display_data" 246 | } 247 | ], 248 | "source": [ 249 | "// 2. 如果打印结果不佳,但是不是用户想要的结果\n", 250 | "printResultSummary.observe('poor)\n", 251 | "val answerIfPrintResultPoor = VariableElimination.probability(printerPowerButtonOn, true)\n", 252 | "println(\"Probability the printer power button is on given a poor result = \" + answerIfPrintResultPoor)" 253 | ] 254 | }, 255 | { 256 | "cell_type": "code", 257 | "execution_count": 12, 258 | "metadata": { 259 | "collapsed": false 260 | }, 261 | "outputs": [ 262 | { 263 | "name": "stdout", 264 | "output_type": "stream", 265 | "text": [ 266 | "Probability the printer power button is on given empty result = 0.8959173432160786\n" 267 | ] 268 | }, 269 | { 270 | "data": { 271 | "text/plain": [ 272 | "\u001b[36manswerIfPrintResultNone\u001b[0m: \u001b[32mDouble\u001b[0m = \u001b[32m0.8959173432160786\u001b[0m" 273 | ] 274 | }, 275 | "metadata": {}, 276 | "output_type": "display_data" 277 | } 278 | ], 279 | "source": [ 280 | "// 3. 什么都没有打印进行查询\n", 281 | "printResultSummary.observe('none)\n", 282 | "val answerIfPrintResultNone = VariableElimination.probability(printerPowerButtonOn, true)\n", 283 | "println(\"Probability the printer power button is on given empty result = \" + answerIfPrintResultNone)" 284 | ] 285 | }, 286 | { 287 | "cell_type": "code", 288 | "execution_count": 14, 289 | "metadata": { 290 | "collapsed": false 291 | }, 292 | "outputs": [ 293 | { 294 | "name": "stdout", 295 | "output_type": "stream", 296 | "text": [ 297 | "Probability the printer power button is on given out printer state = 0.8417721518987341\n", 298 | "Probability the printer power button is on given out printer state and empty result = 0.841772151898734\n" 299 | ] 300 | }, 301 | { 302 | "data": { 303 | "text/plain": [ 304 | "\u001b[36manswerIfPrinterStateOut\u001b[0m: \u001b[32mDouble\u001b[0m = \u001b[32m0.8417721518987341\u001b[0m\n", 305 | "\u001b[36manswerIfPrinterStateOutAndResultNone\u001b[0m: \u001b[32mDouble\u001b[0m = \u001b[32m0.841772151898734\u001b[0m" 306 | ] 307 | }, 308 | "metadata": {}, 309 | "output_type": "display_data" 310 | } 311 | ], 312 | "source": [ 313 | "// 4. printer power button on --> printer state --> print result summary路径上,如果观测到printer state时被阻塞\n", 314 | "// 已知打印机状态为停机,得知打印结果为空并没有改变打印机电源按钮开启的概率。\n", 315 | "// 因为在Printer State给定的情况下,Print Result Summary条件独立于Printer Power Button on\n", 316 | "printResultSummary.unobserve()\n", 317 | "printerState.observe('out)\n", 318 | "val answerIfPrinterStateOut = VariableElimination.probability(printerPowerButtonOn, true)\n", 319 | "println(\"Probability the printer power button is on given \" + \"out printer state = \" + answerIfPrinterStateOut)\n", 320 | "\n", 321 | "printResultSummary.observe('none)\n", 322 | "val answerIfPrinterStateOutAndResultNone = VariableElimination.probability(printerPowerButtonOn, true)\n", 323 | "println(\"Probability the printer power button is on given out printer state and empty result = \" + answerIfPrinterStateOutAndResultNone)" 324 | ] 325 | }, 326 | { 327 | "cell_type": "code", 328 | "execution_count": 15, 329 | "metadata": { 330 | "collapsed": false 331 | }, 332 | "outputs": [ 333 | { 334 | "name": "stdout", 335 | "output_type": "stream", 336 | "text": [ 337 | "Prior probability the printer state is good = 0.39899999999999997\n", 338 | "Probability printer state is good given low toner indicator = 0.23398328690807796\n" 339 | ] 340 | }, 341 | { 342 | "data": { 343 | "text/plain": [ 344 | "\u001b[36mprinterStateGoodPrior\u001b[0m: \u001b[32mDouble\u001b[0m = \u001b[32m0.39899999999999997\u001b[0m\n", 345 | "\u001b[36mprinterStateGoodGivenTonerLowIndicatorOn\u001b[0m: \u001b[32mDouble\u001b[0m = \u001b[32m0.23398328690807796\u001b[0m" 346 | ] 347 | }, 348 | "metadata": {}, 349 | "output_type": "display_data" 350 | } 351 | ], 352 | "source": [ 353 | "// 5. 如果观察到墨粉不足指示灯,打印机状态良好的概率下降\n", 354 | "printResultSummary.unobserve()\n", 355 | "printerState.unobserve()\n", 356 | "val printerStateGoodPrior = VariableElimination.probability(printerState, 'good)\n", 357 | "println(\"Prior probability the printer state is good = \" + printerStateGoodPrior)\n", 358 | "\n", 359 | "tonerLowIndicatorOn.observe(true)\n", 360 | "val printerStateGoodGivenTonerLowIndicatorOn = VariableElimination.probability(printerState, 'good)\n", 361 | "println(\"Probability printer state is good given low toner indicator = \" + printerStateGoodGivenTonerLowIndicatorOn)" 362 | ] 363 | }, 364 | { 365 | "cell_type": "code", 366 | "execution_count": 16, 367 | "metadata": { 368 | "collapsed": false 369 | }, 370 | "outputs": [ 371 | { 372 | "name": "stdout", 373 | "output_type": "stream", 374 | "text": [ 375 | "Prior probability the software state is correct = 0.8\n", 376 | "Probability software state is correct given network up = 0.7999999999999999\n" 377 | ] 378 | }, 379 | { 380 | "data": { 381 | "text/plain": [ 382 | "\u001b[36msoftwareStateCorrectPrior\u001b[0m: \u001b[32mDouble\u001b[0m = \u001b[32m0.8\u001b[0m\n", 383 | "\u001b[36msoftwareStateCorrectGivenNetworkUp\u001b[0m: \u001b[32mDouble\u001b[0m = \u001b[32m0.7999999999999999\u001b[0m" 384 | ] 385 | }, 386 | "metadata": {}, 387 | "output_type": "display_data" 388 | } 389 | ], 390 | "source": [ 391 | "// 6. 一般来说网络正常运行和软件状态相对独立\n", 392 | "tonerLowIndicatorOn.unobserve()\n", 393 | "val softwareStateCorrectPrior = VariableElimination.probability(softwareState, 'correct)\n", 394 | "println(\"Prior probability the software state is correct = \" + softwareStateCorrectPrior)\n", 395 | "\n", 396 | "networkState.observe('up)\n", 397 | "val softwareStateCorrectGivenNetworkUp = VariableElimination.probability(softwareState, 'correct)\n", 398 | "println(\"Probability software state is correct given network up = \" + softwareStateCorrectGivenNetworkUp)" 399 | ] 400 | }, 401 | { 402 | "cell_type": "code", 403 | "execution_count": 17, 404 | "metadata": { 405 | "collapsed": false 406 | }, 407 | "outputs": [ 408 | { 409 | "name": "stdout", 410 | "output_type": "stream", 411 | "text": [ 412 | "Probability software state is correct given prints slowly = 0.6197991391678623\n", 413 | "Probability software state is correct given prints slowly and network up = 0.39024390243902435\n" 414 | ] 415 | }, 416 | { 417 | "data": { 418 | "text/plain": [ 419 | "\u001b[36msoftwareStateCorrectGivenPrintsSlowly\u001b[0m: \u001b[32mDouble\u001b[0m = \u001b[32m0.6197991391678623\u001b[0m\n", 420 | "\u001b[36msoftwareStateCorrectGivenPrintsSlowlyAndNetworkUp\u001b[0m: \u001b[32mDouble\u001b[0m = \u001b[32m0.39024390243902435\u001b[0m" 421 | ] 422 | }, 423 | "metadata": {}, 424 | "output_type": "display_data" 425 | } 426 | ], 427 | "source": [ 428 | "// 7. 如果打印机速度较慢,而得知网络正常连接,将显著降低软件状态正确的概率\n", 429 | "// Software State和Network State是独立的,但是在Prints Quickly给定的情况下,导致了诱导依赖性,使得两者不再条件独立\n", 430 | "networkState.unobserve()\n", 431 | "printsQuickly.observe(false)\n", 432 | "val softwareStateCorrectGivenPrintsSlowly = VariableElimination.probability(softwareState, 'correct)\n", 433 | "println(\"Probability software state is correct given prints slowly = \" + softwareStateCorrectGivenPrintsSlowly)\n", 434 | "\n", 435 | "networkState.observe('up)\n", 436 | "val softwareStateCorrectGivenPrintsSlowlyAndNetworkUp = VariableElimination.probability(softwareState, 'correct)\n", 437 | "println(\"Probability software state is correct given prints slowly and network up = \" + softwareStateCorrectGivenPrintsSlowlyAndNetworkUp)" 438 | ] 439 | }, 440 | { 441 | "cell_type": "code", 442 | "execution_count": null, 443 | "metadata": { 444 | "collapsed": true 445 | }, 446 | "outputs": [], 447 | "source": [] 448 | } 449 | ], 450 | "metadata": { 451 | "anaconda-cloud": {}, 452 | "kernelspec": { 453 | "display_name": "Scala 2.11", 454 | "language": "scala211", 455 | "name": "scala211" 456 | }, 457 | "language_info": { 458 | "codemirror_mode": "text/x-scala", 459 | "file_extension": ".scala", 460 | "mimetype": "text/x-scala", 461 | "name": "scala211", 462 | "pygments_lexer": "scala", 463 | "version": "2.11.8" 464 | } 465 | }, 466 | "nbformat": 4, 467 | "nbformat_minor": 0 468 | } 469 | -------------------------------------------------------------------------------- /p2.Figaro_dependent_model/print_result_summary.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonding1354/PRML_Notes/83612257ee4523034421f3e9810972eceb4f2ebb/p2.Figaro_dependent_model/print_result_summary.jpeg -------------------------------------------------------------------------------- /p2.Figaro_dependent_model/printer_state.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonding1354/PRML_Notes/83612257ee4523034421f3e9810972eceb4f2ebb/p2.Figaro_dependent_model/printer_state.jpeg --------------------------------------------------------------------------------