|
23 | 23 | },
|
24 | 24 | {
|
25 | 25 | "cell_type": "code",
|
26 |
| - "execution_count": 118, |
| 26 | + "execution_count": 87, |
27 | 27 | "outputs": [],
|
28 | 28 | "source": [
|
29 | 29 | "import numpy as np\n",
|
|
52 | 52 | },
|
53 | 53 | {
|
54 | 54 | "cell_type": "code",
|
55 |
| - "execution_count": 119, |
| 55 | + "execution_count": 88, |
56 | 56 | "outputs": [],
|
57 | 57 | "source": [
|
58 | 58 | "def get_pb1():\n",
|
|
73 | 73 | }
|
74 | 74 | }
|
75 | 75 | },
|
| 76 | + { |
| 77 | + "cell_type": "markdown", |
| 78 | + "source": [ |
| 79 | + "#### Emission" |
| 80 | + ], |
| 81 | + "metadata": { |
| 82 | + "collapsed": false |
| 83 | + } |
| 84 | + }, |
| 85 | + { |
| 86 | + "cell_type": "code", |
| 87 | + "execution_count": 89, |
| 88 | + "outputs": [], |
| 89 | + "source": [ |
| 90 | + "def fair_die_emission():\n", |
| 91 | + " return 1/6\n", |
| 92 | + "\n", |
| 93 | + "def loaded_die_emission(value):\n", |
| 94 | + " if value == 6:\n", |
| 95 | + " return .5\n", |
| 96 | + " else:\n", |
| 97 | + " return .1\n", |
| 98 | + "\n", |
| 99 | + "def emission(value):\n", |
| 100 | + " return np.asarray((fair_die_emission(), loaded_die_emission(value)))" |
| 101 | + ], |
| 102 | + "metadata": { |
| 103 | + "collapsed": false, |
| 104 | + "pycharm": { |
| 105 | + "name": "#%%\n" |
| 106 | + } |
| 107 | + } |
| 108 | + }, |
76 | 109 | {
|
77 | 110 | "cell_type": "markdown",
|
78 | 111 | "source": [
|
|
86 | 119 | },
|
87 | 120 | {
|
88 | 121 | "cell_type": "code",
|
89 |
| - "execution_count": 120, |
| 122 | + "execution_count": 90, |
90 | 123 | "outputs": [
|
91 | 124 | {
|
92 | 125 | "name": "stdout",
|
|
108 | 141 | }
|
109 | 142 | ],
|
110 | 143 | "source": [
|
111 |
| - "def fair_die_emission():\n", |
112 |
| - " return 1/6\n", |
113 |
| - "\n", |
114 |
| - "def loaded_die_emission(value):\n", |
115 |
| - " if value == 6:\n", |
116 |
| - " return .5\n", |
117 |
| - " else:\n", |
118 |
| - " return .1\n", |
119 |
| - "\n", |
120 |
| - "def emission(value):\n", |
121 |
| - " return np.asarray((fair_die_emission(), loaded_die_emission(value)))\n", |
122 |
| - "\n", |
123 | 144 | "def viterbi(sequence):\n",
|
124 | 145 | " a = np.asarray([[.95,.05],[.05,.95]]) # transition probability\n",
|
125 | 146 | " b = emission(sequence[0]) # Emission probability\n",
|
|
163 | 184 | }
|
164 | 185 | },
|
165 | 186 | {
|
166 |
| - "cell_type": "markdown", |
| 187 | + "cell_type": "code", |
| 188 | + "execution_count": 91, |
| 189 | + "outputs": [ |
| 190 | + { |
| 191 | + "name": "stdout", |
| 192 | + "output_type": "stream", |
| 193 | + "text": [ |
| 194 | + "0.39891275119173036\n" |
| 195 | + ] |
| 196 | + } |
| 197 | + ], |
167 | 198 | "source": [
|
168 |
| - "2. Download the dataset hmm_pb2.csv from Canvas. It represents a sequence of\n", |
169 |
| - "10000 dice rolls x from the Dishonest casino model but with other values for the a and\n", |
170 |
| - "b parameters than those from class. Having so many observations, you are going to\n", |
171 |
| - "learn the model parameters.\n" |
| 199 | + "def forward(sequence):\n", |
| 200 | + " tran = np.asarray([[.95,.05],[.05,.95]]) # transition probability\n", |
| 201 | + " b = emission(sequence[0]) # Emission probability\n", |
| 202 | + " p = np.asarray((.5,.5)) # Start probability\n", |
| 203 | + " a = np.ndarray((sequence.size, 2))\n", |
| 204 | + " a[0] = b*p\n", |
| 205 | + " for i in range(1,sequence.size):\n", |
| 206 | + " a[i] = emission(sequence[i]) * np.sum(a[i-1]*tran, axis=1)\n", |
| 207 | + " return a\n", |
| 208 | + "\n", |
| 209 | + "a = forward(get_pb1())\n", |
| 210 | + "print(a[124,0]/a[124,1])" |
172 | 211 | ],
|
173 | 212 | "metadata": {
|
174 |
| - "collapsed": false |
| 213 | + "collapsed": false, |
| 214 | + "pycharm": { |
| 215 | + "name": "#%%\n" |
| 216 | + } |
| 217 | + } |
| 218 | + }, |
| 219 | + { |
| 220 | + "cell_type": "code", |
| 221 | + "execution_count": 137, |
| 222 | + "outputs": [ |
| 223 | + { |
| 224 | + "name": "stdout", |
| 225 | + "output_type": "stream", |
| 226 | + "text": [ |
| 227 | + "3.856448201261194\n" |
| 228 | + ] |
| 229 | + } |
| 230 | + ], |
| 231 | + "source": [ |
| 232 | + "def backward(sequence):\n", |
| 233 | + " tran = np.asarray([[.95,.05],[.05,.95]]) # transition probability\n", |
| 234 | + " B = np.ndarray((sequence.size, 2))\n", |
| 235 | + " B[-1] = np.ones(2)\n", |
| 236 | + " for i in range(sequence.size-2, -1, -1):\n", |
| 237 | + " B[i] = np.sum(tran*B[i+1]*emission(sequence[i+1]), axis=1)\n", |
| 238 | + " B[i] *=6 # multiply by constant to avoid overflow\n", |
| 239 | + " return B\n", |
| 240 | + "\n", |
| 241 | + "B = backward(get_pb1())\n", |
| 242 | + "print(B[124,0]/B[124,1])" |
| 243 | + ], |
| 244 | + "metadata": { |
| 245 | + "collapsed": false, |
| 246 | + "pycharm": { |
| 247 | + "name": "#%%\n" |
| 248 | + } |
175 | 249 | }
|
176 | 250 | },
|
177 | 251 | {
|
178 | 252 | "cell_type": "markdown",
|
179 | 253 | "source": [
|
| 254 | + "2. Download the dataset hmm_pb2.csv from Canvas. It represents a sequence of\n", |
| 255 | + "10000 dice rolls x from the Dishonest casino model but with other values for the a and\n", |
| 256 | + "b parameters than those from class. Having so many observations, you are going to\n", |
| 257 | + "learn the model parameters.\n", |
| 258 | + "\n", |
180 | 259 | "Implement and run the Baum-Welch algorithm using the forward and backward\n",
|
181 | 260 | "algorithms that you already implemented for Pb 1. You can initialize the $\\pi,a,b$ with\n",
|
182 | 261 | "your guess, or with some random probabilities (make sure that $\\pi$ sums to 1 and that\n",
|
183 | 262 | "$a_{ij}, b^i_k$\n",
|
184 | 263 | "sum to 1 for each $i$). The algorithm converges quite slowly, so you might need\n",
|
185 | 264 | "to run it for up 1000 iterations or more for the parameters to converge.\n",
|
186 |
| - "Report the values of $\\pi,a,b$ that you have obtained. (4 points)\n", |
187 |
| - "\n" |
| 265 | + "Report the values of $\\pi,a,b$ that you have obtained. (4 points)\n" |
188 | 266 | ],
|
189 | 267 | "metadata": {
|
190 |
| - "collapsed": false |
| 268 | + "collapsed": false, |
| 269 | + "pycharm": { |
| 270 | + "name": "#%% md\n" |
| 271 | + } |
| 272 | + } |
| 273 | + }, |
| 274 | + { |
| 275 | + "cell_type": "code", |
| 276 | + "execution_count": 151, |
| 277 | + "outputs": [ |
| 278 | + { |
| 279 | + "name": "stderr", |
| 280 | + "output_type": "stream", |
| 281 | + "text": [ |
| 282 | + "c:\\users\\okosa\\pycharmprojects\\regressionasignment\\venv\\lib\\site-packages\\ipykernel_launcher.py:8: RuntimeWarning: invalid value encountered in true_divide\n", |
| 283 | + " \n" |
| 284 | + ] |
| 285 | + }, |
| 286 | + { |
| 287 | + "name": "stdout", |
| 288 | + "output_type": "stream", |
| 289 | + "text": [ |
| 290 | + "pi [0.71477891 0.28522109]\n", |
| 291 | + "a [[2.72155818e-179 4.85324561e-181]\n", |
| 292 | + " [3.87594275e-180 2.70099412e-179]]\n", |
| 293 | + "b [[nan nan]\n", |
| 294 | + " [nan nan]\n", |
| 295 | + " [nan nan]\n", |
| 296 | + " [nan nan]\n", |
| 297 | + " [nan nan]\n", |
| 298 | + " [nan nan]]\n", |
| 299 | + "b sum [nan nan]\n" |
| 300 | + ] |
| 301 | + } |
| 302 | + ], |
| 303 | + "source": [ |
| 304 | + "def baum_welch(sequence):\n", |
| 305 | + " for _ in range(20):\n", |
| 306 | + " # Expection step\n", |
| 307 | + " a = np.asarray([[.95,.05],[.05,.95]]) # transition probability\n", |
| 308 | + " A = forward(sequence)\n", |
| 309 | + " B = backward(sequence)\n", |
| 310 | + " emissions = np.asarray([emission(i) for i in range(1,7)])\n", |
| 311 | + " gamma = A*B / np.sum(A*B, axis=1)[np.newaxis].T\n", |
| 312 | + " eta = np.ndarray((sequence.size,2,2))\n", |
| 313 | + " for t in range(sequence.size):\n", |
| 314 | + " for i in range(2):\n", |
| 315 | + " for j in range(2):\n", |
| 316 | + " temp = A[t,i]*a[i,j]*B[t,j]*(emissions[int(sequence[t]-1)][j])\n", |
| 317 | + " eta[t,i,j] = temp\n", |
| 318 | + "\n", |
| 319 | + " # maximization step\n", |
| 320 | + " pi = gamma[0]\n", |
| 321 | + " for i in range(2):\n", |
| 322 | + " for j in range(2):\n", |
| 323 | + " a[i,j] = np.sum(eta[:,i,j])\n", |
| 324 | + " for i in range(2):\n", |
| 325 | + " for k in range(1,7):\n", |
| 326 | + " emissions[k-1,i] = np.sum(gamma[sequence==k, i])/np.sum(gamma)\n", |
| 327 | + " print(\"pi\", pi)\n", |
| 328 | + " print(\"a\", a)\n", |
| 329 | + " print(\"b\",emissions)\n", |
| 330 | + " print(\"b sum\",np.sum(emissions, axis=0))\n", |
| 331 | + "\n", |
| 332 | + "\n", |
| 333 | + "\n", |
| 334 | + "baum_welch(get_pb2())\n" |
| 335 | + ], |
| 336 | + "metadata": { |
| 337 | + "collapsed": false, |
| 338 | + "pycharm": { |
| 339 | + "name": "#%%\n" |
| 340 | + } |
191 | 341 | }
|
192 | 342 | }
|
193 | 343 | ],
|
|
0 commit comments