3218 lines
129 KiB
Plaintext
3218 lines
129 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "6d2db899",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"<!-- HTML file automatically generated from DocOnce source (https://github.com/doconce/doconce/)\n",
|
|
"doconce format html chapter13.do.txt -->"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "f4908a97",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"# Recurrent neural networks: Overarching view\n",
|
|
"\n",
|
|
"Till now our focus has been, including convolutional neural networks\n",
|
|
"as well, on feedforward neural networks. The output or the activations\n",
|
|
"flow only in one direction, from the input layer to the output layer.\n",
|
|
"\n",
|
|
"A recurrent neural network (RNN) looks very much like a feedforward\n",
|
|
"neural network, except that it also has connections pointing\n",
|
|
"backward. \n",
|
|
"\n",
|
|
"RNNs are used to analyze time series data such as stock prices, and\n",
|
|
"tell you when to buy or sell. In autonomous driving systems, they can\n",
|
|
"anticipate car trajectories and help avoid accidents. More generally,\n",
|
|
"they can work on sequences of arbitrary lengths, rather than on\n",
|
|
"fixed-sized inputs like all the nets we have discussed so far. For\n",
|
|
"example, they can take sentences, documents, or audio samples as\n",
|
|
"input, making them extremely useful for natural language processing\n",
|
|
"systems such as automatic translation and speech-to-text.\n",
|
|
"\n",
|
|
"More to text to be added"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "43cb4913",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## A simple example"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"id": "cf6b9dab",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stderr",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"/Users/mhjensen/miniforge3/envs/myenv/lib/python3.9/site-packages/jax/_src/lib/__init__.py:33: UserWarning: JAX on Mac ARM machines is experimental and minimally tested. Please see https://github.com/google/jax/issues/5501 in the event of problems.\n",
|
|
" warnings.warn(\"JAX on Mac ARM machines is experimental and minimally tested. \"\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAXwAAAD4CAYAAADvsV2wAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAABKj0lEQVR4nO2deZzUVNb3f6d6A5odmkW2BgQEVARZRRYXVMRl1BlHfV1HZXD0edRxxodx18dxcBydcXvcHXXc9w0QFQVBVGQH2UGQnWZrlqa3qvP+UUlVKpVUJambVCp1v58PdFWSyr1Jbs4999xzzyFmhkQikUiCTyjbFZBIJBKJN0iBL5FIJHmCFPgSiUSSJ0iBL5FIJHmCFPgSiUSSJxRmuwKpaN26NZeXl2e7GhKJRJIzzJ8/fxczlxnt87XALy8vx7x587JdDYlEIskZiGij2T5p0pFIJJI8QQp8iUQiyROkwJdIJJI8IWOBT0QNiGguES0mop+I6F6DY4iIHiOitUS0hIgGZFquRCKRSOwhYtK2BsDJzHyQiIoAzCaiqcz8veaYsQB6KP+GAHhK+SuRSCQSj8hYw+coB5WvRco/fUS2cwG8ohz7PYDmRNQ+07IlEolEYh0hNnwiKiCiRQB2AviCmX/QHdIBwCbN983KNqNzjSeieUQ0r6KiQkT1JBKJRAJBAp+Zw8x8HICOAAYT0dG6Q8joZybnepaZBzLzwLIyw7UDEkmM79btxrqKg+kPlEgkYhdeMfM+IpoB4AwAyzS7NgPopPneEcBWkWVL8osLn/kOm/ZUYVtlNQBgw6RxWa6RROJ/RHjplBFRc+VzQwCnAlipO+xjAJcr3jpDAVQy87ZMy3aTXQdrsHL7/mxXQ2LC3J/3xIS9xB3GPTYLJz88I9vVkAhEhIbfHsDLRFSAaAfyNjN/SkQTAICZnwYwBcCZANYCqAJwlYByXWXMIzOxt6rOUHM8VFOPgzX1aNu0QRZqJpF4w09bpcITNDIW+My8BEB/g+1Paz4zgOszLctL9lbVme674Kk5WLn9ADZMGofpK3agdeMS9OvU3LvKSSQSiQN8HTzNr6zcfiD2+eqXo8HdpA3ZHcIRBgEIhYzm/SUSiR1kaAWJr+l952c45ZGZCdt2H6zJUm3yh817q2z/Zu7Pe1AfjuDlORvwy277v5e4jxT4El9TG47g512HErYdf/+XWapN/nDig1/HPk9esg0rtqW258/fuAcXPvMdbv9gGe7++Cfc8MYCt6socYAU+BKJJCXXv74AYx+dheq6MGrqwwCATXuqYp8BxDympq/cCQAoKpCixY/IpyKRSCxx1J2fYcgD01FdF8aIv3+NXnd8hvcXbAYQnWsBou7MANCumfRg8yNS4GeA2sglkqDAzHh3/mbT/fuq6lBTF4l9/+PbiwEAEU58FwrlJLsvkQI/A7RDWpUd+6txoNrcpVMi8TNfrdyJP72z2PbvwkofUCAFva+RAl9h/sa9eGrGOlu/OVybLPCHPDAdZz42S1S1JBJP2XOoNv1BBjI9HIlKfFXeS7HvT6QfvsIFT80BAFw3urvl31QZCHwA2LTnsJA6SSReU+/QTPnLnqgbZogIAINIinw/IjV8AFv3ORPQh+uMBT4g7fuS3KQuHEl/kI49h2rx5NfR0bE06fgbKfABnDDpK0e/q04h8LvfNgVrdhzA2z9uwrItlU6rlnds2lOFTXvkop1sURdOr6iwboL2UE197HOB1Ox9jTTpZEBtfaI2FNFp9f/v+R+w80DUTU2GXrDGiL9HF/zI+5Ud6i1o+Dp5j8KCuJCXITD8jdTwM6BGJ/BrdS9LqhGABPhs2XaUT5yM9TKBiW+wYsPXu2BqtXop7/2NFPhpYGbUhyN4YfbPSRq9/ru+A9B/lyQyeWk0JcJSA5OX3mwg8QYrNnz9k9F+V6PMSrlvn0M19ZizdperZUiBb4DWNBNh4I0fN+F/P12O52atTzhO74ef/F0K/FSkEuqpJsTNiEQ4Nqo6WFOPRZv2Oa1a3lJvwYav1/D13wFIie+AW95ejEue/wHbKt3z8pMC34DbP1wa+xxhRo0iRB6atgqXvzg3tk8V6Kpngl7jl1jDyIXPiZfT/7y3BEfd+RkAYMJ/5uNXT35ruFZCEue5b9ajfOJkVNVGJ17rIunb8DMzExWfuno5GhPB6h3RsOtm7t4iEJHisBMRfU1EK4joJyK60eCY0URUSUSLlH93ZVqum7wxd1PsMzNQUlQQ+/7N6orYZ73Alxq9PVKJiXCEbZt13tGEBFisaPdWBFg+8+K3PwOIm2KsCO8XZv+c8P3xr9aIr5jEFUR46dQDuIWZFxBREwDziegLZl6uO24WM58loDxPiTCjpNC4X4wJfCL8Y9oqfLd+t5dVCwxGo//j7vsC445t7+h8kQhDHTSwlPdJVNeFUVIYAhHFzDHqZGu9gw5yq4smCIlYMtbwmXkbMy9QPh8AsAJAh0zP6xeYYSrwazUa/hNfr8X8jXu9rFrgmbzEWZ77MHPMPXBvlYVQAXnE7oM1OOrOz/DsN1GzjDqICik9pBU/fD1W7P4SfyDUhk9E5Yjmt/3BYPcwIlpMRFOJqG+Kc4wnonlENK+iosLsMM9gMEoKCwz3qZO00hXNX4QjHBNgo/8xA7PXuOv5kEuo60I+WLgFQNQpAUBsRGTFD1+PXFWeOwgT+ETUGMB7AG5iZn16nAUAujBzPwCPA/jQ7DzM/CwzD2TmgWVlZaKq55gIAyVFJiYdJUxsoUz24CuiAj/+XY684qhhi1V/e3WehJC43Q5GvyHppuNLhEgqIipCVNi/xszv6/cz835mPqh8ngKgiIhaiyjbbZjj2qIedaGVjB9infkb92D4pK9wsKY+adZ2x/7qjM4dt0MnBu/ilNPD+YXaVlWtXO9SqV88aAUjDV//yoQjjNd/+MXRCEIiDhFeOgTgBQArmPkRk2PaKceBiAYr5WZ1hvNQTT1ueH0Bdh5ILWQibOJnjLiGbyV+yE1vLsS9n/xkv6IB48HPVmHLvsNYtqUS366LmlrU2zfkgekZnVvtmCMRTngmcg1XnIKYhh9tu+qtUTV9JwLZyqjg9R824rYPluKlORtsnz9fUO9i5WH38mmI8NIZDuAyAEuJaJGy7TYAnQGAmZ8G8GsA1xFRPYDDAC7iLC+l/GjRVny6ZBuaNEh9C5jZ1H+wNhy14VvR8D9ctBUAcPfZptMXeYGqDRaECPtiqzLFjJBCIQIijHqdSUfK+zhqpxhWJlrV56HeI2eTtuk7iT2Hos96v4vCLJc5UF0XW+V8/v/NcS2WVMYCn5lnI826OmZ+AsATmZYlkobF0cFNuoU5lYfrsN8kg5Wq4YekCd8yWoEvGvWUEdbFY5cqfgz1toRZteEj4a+T8MhWJm3V8vI5Tv7Puw7hro+W4ZnLjkej4kTRe8w9n3tSh7wVVQ0Uzxv9En79wGPUQzNw45uLDM+hLvQpdCjxp6/YgXV5FjgsJvBtvvinPDwDO/dXmy7GWrX9AKqVDrg+wrITNkG9fWHdpG0kZtIRM2mbXK57HX2u8LcpKzBrzS5c9+qCtMe6ZQDJ29eiQbEq8BM1Gif32Ukjrjxch6tfnodTHp5pv8AcxqmGv67iEN5fuMX0+Vz32vzY50gkcaJd6vfJ1McmbaPfObbdgQ3fYFRAuv0790fdQfNY3sfCSM9cnd7d3C1P1/wV+IqGX60z6Ti5z06SPlz87PcOSsp9MjHpRNjc36ZUM0Su1wt8KfGTUG34EU7U9B3Z8NN46dzzyU94a140XMkXK3amdZQIKgWaYWdNfRgHTEzFgLmjSKbkjcB/fPoalE+cHLNRqgInnUnHCk6E1/Jt+qUK+YFqyy3U3DOr/SWz+fMpLYkvjgtHIgnnlG6ZcdTbF/fD128XY8N/e97mWOTSaT/tiG1fvGkfLnt+btLx+YC2zV/4zPcp7fZfr9zpSh3yRuA/oywlVxuh2oMmCXwH55b2YmvMWbcLa3dG5yy0Atlqd8kpNPzGJXENPxxBgoYfYeBvU1fE/PwXbdqHW99dnJcx99U7GPfOSRT8Tmz4ZhO9amJz/Qh48978TGGpVQwXpwndPf4/81Pud0reiCr1Vsf9jqN/9drJFS/mp/bhBZc8F4+44UTWRtj8d1qBXx+JJK603bAXz8xcjz++vQhA9Bm/PW+zq/7OfkWvycdt+NEPohZeabfrR8BmCxmDTqEPJjDyRuCrEp91DVzPnHX214PloaKYMU5uWXRJhPEvG2ps+JEkDV8RZkqwO3VXPoaAUS9Zvfa4DT/6XaSXjirwtTlvgfzNe+sHD6W8EfgxDV/XwEU8Ainw7eNMw2fT32mVxvpIRBdaIc7ugzVJbSEf2LSnClOXbku6ZtYJfpErbdVzJmv4tosIBGYavpftUMRKW1+z4Je9OP//5sS+6yepRJA/YsM5EZ1QcDKRysyxOQA9r//wS7wsZkOh8uOGvTj+/i81dcgfzn5iNvZV1WH6LaMM98dW2joY9piZdNTNehu+HzTdbFBgMtnnpd4ReA3/nXmbE77HhrACX/d80hSdctfHyxK+a2+ZVZNuhIGzHp+d9rj6cKJbptnp3XJ98yNqGAszk03cpCMuuJmZDV+/2vaX3VVJCkEQKSowboletsPAC3z9TVbdAmPtS4CyIeJ5PTRtJT5atCXzE/kUbdpIQN/IrT2EL1fsSH8Qos9Ybzc2JPgyJgmz5PDx4Gnibor6jJNs+Jqvq7YfwMiHvo550QUZs7kLL/u6PBD4iZcYN+kI1PAFSI4nv15nGsIhCOg7XiepZlduP2DpuH9+sRoLf9kX+272dC553ihPTzBR7/8zM9cZ7o+bdNzQ8BPfQe3oS3XdnL9xj7By/cjanQfx+U/bDfd5uU4k8DZ8/XAyHGG8+v1Gy2YEK+SRZcAxRQWhWKwbID7ScoMfN+y1dJzZfEAQKS4IoS4cxtRlJkJHeRxOVtqaoZpp9IMtIw+qoAdV+/XTc2JmNT0VShYyLwi8hl9VW5/wfW9VLe74cBlu/yBqUxbipSPgHEFHnxdYb7e88c2FwsoaXN4y4XuqZ1wXjuCG1xcEXvgXm+RlVtEvyBLByu0HwMxJwQUTA5lGywv6PG6qqLxjH53lWT0Cr+Hre8+rX5onvAyr5qHWjYuFl50rFCeZ1hLv2UdKvgAh2BAeizftw6dLtmHrvsN4/w/DxdXBZ6QT+AItOTHu+3Q5GpcUJo2ytd/V/iXoi7E6tmiIdRWHDPcdqK433O4Ggdfwt+5LDNS0XZdGz+wh2MGqTmSWDD0f0AscrTPI4TqxDV4vOlI9n4DLmRhWNHw3vM1+3n3IYNI2/v1dJcR40AV+68Yl2a4CADEpDjsR0ddEtIKIfiKiGw2OISJ6jIjWEtESIhqQablW0Qt4N7D6nuSTG6Ae/eS59l7c/NZioWXZkR2qaQ+I2vSvfWUeaupTJ8XJJdTwEfoRlh5mZwnM09GsYZGBW2b881dKkLCAy3u0LDUe3S/bUulpPURo+PUAbmHm3gCGArieiProjhkLoIfybzyApwSUawl1Ob2bWNWMRNpHcw29humm37WdU2s9f27/YCm+WL4D8zdam/T1O18u34F+936OuT8be8Bo2y2zs2xX6Zg0dSV+2Z0YLM1Imw+6ht+sYZHhdivrSkSSscBn5m3MvED5fADACgAddIedC+AVjvI9gOZE1D7Tsq3ghZC1WkIey/tkge/ivXDamcSXZuS+8Fm2pRKz1kQTbSzetM+wjb71Y3xtxPb91aZeJJmyflei2dRogjbok7Z+QeikLRGVA+gPQO/g3AGAduXNZmXbNoNzjEd0FIDOnTtnXCc3tBY9Vi014UgEs9ZU4MQjW7tbIR+ijyNy6Qvu+cDrTRN2bdO5rmw+NWMdHvxsZcI2o1swTeMXfu0r8zyzM+ejhu8Xc66wSVsiagzgPQA3MbM+u4fR0zS8A8z8LDMPZOaBZWVlGdfLCw3fahl7q+pw2Qtz8cmSxH4ucWjtj4YhGi9faP3zsOxaHpBbrxf2gHG70neMuw564w9uKPADruL7ZXQvROATURGiwv41Zn7f4JDNADppvncEINAPzxhmdmUiSs+WfYdtHb+9MvF4rYD6dEnSoCcQWAp1IAi9wLfaiaq+6EEUPUZ3YNaaXULLGNqtZfqDAFQcrMFnugVgTtKE5hJ29bjfDuyU/iAHiPDSIQAvAFjBzI+YHPYxgMsVb52hACqZ2XXJ5tdJUr2Go63mhl2Zu4n6EbNIgW6QLPCt/S4WMjuAwseLgeM95/S1dFzFgRpMeHV+Qkcc9Kxxfhm5i7jNwwFcBuBkIlqk/DuTiCYQ0QTlmCkA1gNYC+A5AH8QUK4pm/ZU4aY3F6LKJFBUttG7qfnFvucmHir4SWEbltp0fQugvPekjdk12yVGTA3gTdfgl3c840lbZp6NNKNgjnZv12dallVuemsR5m/ci3OP0zsL+YO8FPge2midjuyC+hSIvNHw7T5ibbt/b/5m3HdOXxSmWS+Qq/ilbQXy7m5VbOq/f9WdRMCZotdmtPLJLw1DNF4K/PoM4wQEW9d0D7taurat19RH8MLsn8VWyEfY1UHcGvAEUuDvVOLneLHoygn6CSqp4YvFibxf8Mu+mJ01160LXVo1StrmhQ3Z7m3TV8krLyEvqKqtx8bd8fk4v7zjgRT4fp2sVdGPWjfuqjI+MMd5Z94mzFkX9QTxctLWrteUSrzZ5LbE13eu909egT1Vta6Xa9eGrxeCPpGJQrjyxR8x6qEZ8Q0+ubbAR8v0I/oX4+wn4surg9To//zuEgDAhknjPJ20dcqiTfuyXQUxGLQhbS4Ct7Ar8PWLIn2up1kmHGHM3ZAYzkJq+HmMFfPGk1+vxdF3T8PXq3Z6UCP38Udzt0aum3Syda/t3je9yVWf+enlORtQPnFyUk4Lv/PAlBWxzzNW7cRRd061HQJZ2vADRKrOXm30D01bhYM19bjq3z96VCt3CYr25mf++cVqdPvLZN9ok+mo1gt8XbWfmxXNc7vrgPvmKJFoF5X984vVqK6LYM1Oa+k53UYK/CyQKr6PvtGbZbr3E+UTJ+OWt1OHOM4VIQTkrgX/0elrEOHsmQXtTswfqknUel+asyHhuxrSudaDeFhuoSo6fmn+UuBngTob6q4+PZxfeW/B5tQH+KTBWyHXFwFlq3O1K/DTmTnUCKteBEB0C3XE7pfmnxvSJGDU2FgBnAsavhWkhu8OzIzLXvgBXy7fEdtWLzARuR3s9pN6DV+PGn8plwX+si3ROJJ+aVPSSycL/GCSkAJI1gTSpabLFbIh8Js3KnIU4z2XFPwV2w5g1ppdWL0jbiPOVsYuu146B9MIfDVLWl2WOrDs4k4jDIY0yTEOVFsXQvrUgLlKNiZtH72ov6Pf5UoClF0Ha3DmY7MAAO2aNYxtz9aCQ7sRL40EfvnEydivvB9xgZ9bGr5fAqUZEQxpkmPYWQkaFIGfjZfA6eLeXNHwtQlMtGZCtyY5+3dunnK/XQ2/ykTDVxciFueowPczwZAmOYY+mmMCun1BseFnQ+kJfBYlzbBJm5vXLRPIJYNTZ6Ajm9LELFeFav4rCoANX8UvOr8U+FnATlKWoGj4btjw2zZNnZIv2OLe+xAi6byX7Jp0zNqEul2NnFlb7xdx6Ry7zV8uvAoQdpJsB0HgX/vKPHy7brfw8952Zm+c1988BLZT90ofm2AT8Ntcpt0RlZnirr4eqkkn0+inXmPU7vxi1899aZIjdCsrjX1OpZnp93iZGtAtvli+w5WJxIJQ6unVgKdJtaU4ZMp1o7unPcZu/2qm4TMzLn72e0xeGk2KV1sfQSTC2Hmg2l4BPiKlGddDROW0fZGIdhLRMpP9o4moUpMR6y4R5VrFy9C8pnXQvA12zBuFPqi7XyFQSvOYYw0fjI27D9nypsoGXgqRrq1K05rI7L5nZlpvOML4bv1uzXHRVcSD/zod2yqdRULNNmGfDMdEafgvATgjzTGzmPk45d99gsq1hJsTn80aFlk6Tvsy2LG95oqLYDYIUep76bSvZAZGPTQDFzw1x2HNvMFTG76FeynapKPCQCyI4I79/ouZXx+OJMS+N8Ju59yrbZNMqmSKEIHPzN8AMF9NlGXctINb7UwSBH6Kh5+0y4fyftfBmoSFPtmCiFJ6cDid+FIfweodBxGOsG+jNXpp0iEk3s/zDeZOMklxqEWv+TOzH1+DGA9NW4VRD81ImYfBbud8+bAumVbLEC9t+MOIaDERTSUi0/T2RDSeiOYR0byKigohBRe7OvFpX+DbeVH92NDHPDITp/3zm2xXA5RGw3c+aRs/5x0fLkWfu6b5ZtJNi6cKPlGCMmKkRNm93+ZeOonftV/9+BxU89OuA+ajDztm3Falxa7Fc/JK4C8A0IWZ+wF4HMCHZgcy87PMPJCZB5aVlQkp3E0N3+pz0Q53U2r4umlbP7qS73UQrsANmFMHohNx696YuwkAUHm4DhUpXmiv2Lj7EHrePhXrKw56asPX30sRzgRmnXXSdTFiL4L/xH28o0v1PNK5Yl87omvS+dzAE4HPzPuZ+aDyeQqAIiJq7UXZAFBU6N4NtHrmBJNOigkcfZvJVRu+N5oYI5zCZc/pwiujmg95YDoG/fVLR+cTyUeLtqI2HMEHC7d4atIBEpUPEc4EZgJS/0wjPjLp/N+MtTjtnzMTtql9n9rmjdp+utdB+yjdNEh4IvCJqB0p3RYRDVbKFe+YbYIfNHztYXY0Mz9q+Cp7D9Vi/kbjqRuvZFGqVaWObfgGp6zJUnyaVNhZwJcp+ntp9k49eckAy+esMJmA1T/TRJOO5dO7wt8/W4XVOw4mbFMVi0weh/a67C5gs4OQaJlE9AaA0QBaE9FmAHcDKAIAZn4awK8BXEdE9QAOA7iIPTTGuWvDt4+dleJ+FviXvzgXS7dUGu7zIjomczovHWc379Z3UydzySba2+qlPZsosexCk3dq3LHtcf3r1s75/sIthtv1z5Q5/h7MWlOBfh2bmZafDWICPwOJr31fQi66YgsR+Mx8cZr9TwB4QkRZThCh4b//hxNw/v8lu+k5MbnYEYZ+NumYCXvAG4Ef4dRartPOcl1Fahc7P0Dw1i2TQADFy3PT1Vn/TBlxk86/voxm9frjmJ6ulW8XtZ1lMqei7bzdXDfkn27SRZxOMHVq2RCtSosBAI1LjPtGq0JF2xTsrLT1s4ZvxKY9VaisqvNs6J3Khu/nzlIEnk7a6m7l8CPdm4LTP9Oohh+vwPqKg/qfZBVVwz9YXe84F4H2Sbpp0skLgS/iBpp1uk7O7HTo9/a8TfjP9xsd/VYkqUxkI/7+NU7/1zfemHTA6Nu+men+UMg9f+ZsofXi8tqerXagY49uh6HdWrlWjj5jl/4ys23H16Nq5OP/Mx/nPelssZ72mtw06eSFwHdqy9V2FHZdpSaOPcp0n71J23i5t767BHd+aBi9wlPSDee376/2ZNI2wsCdZ/fBNSd2NdxPIFwwoKPwcqvrwqjMtmsqkbcmHU07FJ2F7c3xQxMWciXb8BO/Zytd5p5DtYbbtQJ6+bb9js6tvSap4WeKw/vXoKggpl2YdRoP/aaf7fOmelE/XLgF78zbFPtuVnVmxpNfr8XmvVW2y/cCbyZtGY1LCnHbmb0N94fInZj4Zz0+G/3u+1z4eVPxzMx1+K83FuJfX66JbfPSS0crdEU/2n4dm6NLq3hwQf3aCubE9yBbAn/6ih2G20Uo5NpLdtOMmxcC3+kDKdFoMmanMLNl6o+32mC3VVbjz+8uif/OpOBf9lThoWmrMP6V+abnEsnM1RV4/YdfLB/PHnoxmg2Bidx5edbu9N6G/LepK/HJ4q0J27z0w48wuyaIiBLf0fqw3oafWHa28qGYvbYilAqvJm3zIom508m7ksKC+DkEPgM7Q3GzxqT6KlfXeZOw+ooX5wIALhlinvXouW/Wxz4bdWotGhWlXaVbGEodAdMORJRzk95GGLlfErzVdMMRIKS8DqJLJUrstI1s+Np3OFsavn4VvIoI+Zzghy9t+JkRcniVJUUhjO4VDe/QsKggzdHWsSPPvlq500STU7Z5INCuezU+ijjr8Vmmx/11yorYZ6OXsqXi8ZQKO69yuhc/RBSINIdGl0nkrZdOKm+oTNErZPqcvPrLjCSYl9izuQyrGn6q+b7OLRsZn1vT8t1ss/kh8B3ewJLCECadfyxm3XoSSk3cMr1g4aZ9SdvYO3mPqcviybKXbdlvSSgbvYNNGqQPJS1yMZE+wqNovIqiadSx/evLNXh/gfHCJQAYd0x7oXVw04yin2sx9NLRPEdt27ry3z+i+21TcN8ny92roLYeBujlS6o2/MQl/Q23Rxh46NfHApAaftYoKSxAcWEInVo2QgObGn4nk57cGQaxOZS/bgZaygSjRm9lsY4dcZ+ub3Bbw+9z1zTs3O9+FiYnCmxpibgRKZCo4Yte4as3velDXhuFS1aZuToaUffFb38WWicjzFY5W7UgtGvawNS8HGHGaX3aAQAmjEqfXcwpeSHwM9HwVQpCZCkpQXFhCO9MGIaxR7dzVKYRxjkylX3CShGLkZCyornoZUmqTiKdICRy//54MYHrxGZ9fJcWQutQH2HXlAtCoh28zmjhlea7H2z42ipYvS+f/3Gk6YiTGWjWqAgbJo3DmD5tM6lmSvJC4Dttp4O7tkz4PqRbS5Mj40QijEHlLYW+HPoz1dZHYo3Ppwq+4UvpJMRFJvcx6qXj7g3yIlS0EwHX9wjzBWlOcNNOHu2Y48+prt4gtILWpJMlLx3tLVi/Kx5+w6pC2TSFSdOruEh5IfD3H7b/UrZuXILfDuqUsO3Os/qgSYOoLf+E7q3w0fXDk35n5mHSqnH6CUsz9A2q5x1TsXF31P+eQKg8XOe7XJ9GQsqJbbJNkxLTfeleEi+8dPZWGS/GEckfXltg+zci4tVr0bZr8V46ic+p3kDD15ItDV9bkTP+FU8AZOdWm7VHrzxs80LgmwnhVPKnvFWjJO2wqCCEDs0bAgD+dHov9OvU3HIdRvVsg/t/dbTl47UYNZJnZq6L7Tvl4ZkY9revHJ3bLYzeSScx1N/6/bCkbYPLoyOt7m0aJ+0bd2x8srJFoyLXvXQOVLs/cTtjlf3Mb4VOXdNMCEfciUmvNgntc0qy4cMvbplxtDLFThvTH3tMh+hIzKtryguBb3YvUy0RN7v9qstYic3l5UTAGQ7t+kYNSm1vRIRdB8VnYlq5fT92m5zXSts0asB2hdDFgzvFOlggHsDuqUsHYM7EkzGgc7KdWr1XAzo3R6PiQiE+0rmIiAQlWhJMOgJlk6pUJU7aJq+0Na2Lh5gtdLNjNtQfeu3IbgC8y+SVFwLfDCftplZJhGHXa4cgdgIx5qUj8JxazvjXrIzy1hpO2to0MzRtmGjzHKLMqRSECEdoOgItqpy7TAmaJjpiptdZppySiUnnyUsG4NnLjk/YFp20TTzuIsXk+eKVA2MuhXZRhXcqDV+vPLj1CB6fvgZrdhww3W/ulpn4fWulueeWvj2qimODQrFeVWbkxUpbM2pTZDHq2TbZXADEMx/ZFfiA8wlEw5+x+5O2uw/VYtYaZ4nkDSdtM9Q6H7u4P1Zs24/mjcznQ9TAU6rMEH1/3l2wOeG7XyfNnZh02jQpwc4DNejQomHSCMGoo3vgvGNw77l9E1akOyXBhm+QxUy7340JzsO1YTz8xWo8P/tnLL77tITtf5u6An8+vZeQ0Ar6Q0/t3RY3ndoDVw3v6qTathGV8epFAGcB2MnMSYZqJb3howDOBFAF4Epmtj8T5bh+9n9z99l9DbernYQTk45TeWekpaYL6iaKy16Ya1B2+hfucG1yyIeCDO3KpSWFGFhu7CnVsUVD1IUjsSX6EZc6xN0HEydpfSrvHWn42rbUsDhRiCdO2ipaeYhQEhKjmWqVoeSVtjovHRc0fPWa9Ergf77fgFe+24jSkkK0bmzsQGAnnLH+yIIQ4aZTvUvmIsqk8xKAM1LsHwugh/JvPICnBJXrGmYavJFJ54ubR2LS+cckHfvq1UPQp31TAFGh7dS8YCQnjQTat2t3OTq/XYw0MD1nPT47aZtdu/Jvjo+GNn760gG4dKh5DB8AmP0/J+OH206NdaqqFii6Q3zws5VCz5eKzXurHCfUcGLD13pRNdIJ/HAkgnZNGwAAjmyTfj2KXRL88A1CK2Rr0latSoTZdGRhx9s42yNCIQKfmb8BYJzNOsq5AF7hKN8DaE5EYtd+CyTVy6KGWNBq+D3aNsHZ/Y4AANx4So/Y9hN7tEafI5rGfyxSwzdYePX/nv/BWQE2cRrczG5iB1WwnHF0e9z/q+QO1YiuraOmuDZNosLJ7RfMyvmf/HotNu5OTpu4Ytt+zF5j3ElX14Vx4oNf41ZN5FQ7OMn5qlUsyhqXoO8RTTGiRzQabH2EMbC8Jd7+/bCENi6KBD98Ay8dLaInbW//YClemrPBcJ+V0WyrUnPX4WSyK/G9suF3ALBJ832zsm2b/kAiGo/oKACdO6fW6twi1XD4nQnDMHvtrqRFRKUlhVjz17FJ22NKAYkVPvHzJp/0ihfnYtmWSsy/c4y4AnOE8SO74egOTTGiRzToXbaDp1UcqMFD01bhrR834ZtbT0rYN/bRaCC6DZPGJf1OjYL69cqdjsp1pOFr7lVhQQiT/3sEFvyyF7PW7MIwJcOVfjGiKEIJI9XdCfu0SczV7wBMO0u7vGYh7DeBTG34dppYtr3GvPLSMZx2NDqQmZ9l5oHMPLCsrMzlahmTagKla+tSXDa0i+G+VCtJM/HSMdIy1Mw6Rg1o5uoK7NZk5/ls2XaUT5yMgzXeBPtywiu/GwwAaNogMx2kIEQxYQ9kW5+Km5aqDOY0rOB0ot+JwDfqHAd0boFl956O0/padyl+7ZohePHKgbbKTnWZehOOGiX00he8GdGa1UPFjoUp27GvvBL4mwFol612BLDV5Fjh2LnFE0Z1x62n9xJWtlZYO33YqRqUlTM+Oj2aJUk1K1QerkOlg9XHmZLq8kf2LMOTlwzA5P8eIbhMd18wOy/7si2VpsHWDteG8dSMdTFzRaZmaiermtXf6G3VjW1Gih1+ZGucfJS9eDCpnpP+Vnhpw9cWpbck1YUjeGrGOlQ7nGfJBl4J/I8BXE5RhgKoZOYkc44fKAiJFRKnKA3/6A7NHGubqRq4vq5fLk9OwxafyIz+7Xfv5+h3r7cp+qww7tj2gqOMum/DtyN6znp8Nk59ZCYAYO3OuL/37oM1+OeXq/HgZyvx4cJoyOMV26MjOKf1d9KG3QzLm46UJXNi4DYR8r6yqg63fbDUcgIhouSR9ls/bsKDn63EMzPXm/wqjnprnU7Ci0KIwCeiNwB8B6AXEW0moquJaAIRTVAOmQJgPYC1AJ4D8AcR5bqB6IU6445tjxX3nYHe7Zs6fnntaPjXvDIv9llNFacO1bO1QtEuY/q0xQ0nHSnkXG6LMLPOeOeBavS8YyqWbK5M2L5fCcVw6iPxRW3H3/9lLETDnkO1iEQYlzwXNVe4Wf92TRtg5f/Gneu6tIp2ttnI/ZBqrsUNDf+RL1bh9R9+wTvzE9dVHK4Lx0Y48zfuxUPTVsXroSv2kA0Tqbqq36lpTxRCniwzX5xmPwO4XkRZbuOGRqj6NIvuTIDUL8qh2jCaNQwl+aYbMX/jHvTv1MK2J40bPHe5PftvKrJl0pmzdjdq6yN4fnZ67U/LX6eswGEP0la+cMVADO7aMsG9+O+/7ofzB+xGTwthwEWTaolGVW0Y36yOLwAUobioCygLDNrHc7PWY/zI7pjwaup80XZqoS5O6yJ4BGuX/AitkG3nVwU3NPxUfYiqgagyfOJ7S1E+cXLScUs278MFT32HR75Y7ayCOcLdZ/cRfk4z32y149THhbHCp0vi01tudFiNigswtFurpAxkTRsU4nQbk7NW+e4vJ6c9JpUy9MLsxOQmZu+DnXkp1bXYaHJbm+EtsVx9iAfrz1bV8Fs1LjH0yvKK/BD4FhivBDFys2twLPDBph42qU5ZpzPprDKJE6K22ynLsjOt4kV/3LxREa4YVi78vGbvvKo51jvIDahdkexGGIHl951haLZxazTUvlnDhFFbv47JsfpFFH2txpyZDvW5GLlgm42a9Y/CzqMpdrAuwg38UYss8fSlAwBEe9/mjaLajpMkHVZxatJhBk76xwzjc6Y4pdog01lp1Mm6igPio25eOyLu4mpWDaNhtRu4UYyZdUFtRnEN37p00Gb5yo1Zl/Roszj97sRkt2c7nY1ZJzj35/jaz7U7D6J84uSEbVrqVA3f4H03el8Iyc/CTmdcUuQPUeuPWmSJkT2j/tqRCON3w7tiwqjusXClbuBcwzcXxlYmu+y8TFW19Rj32CwbtUvNKb2T3fP0qSK9WhzlhgZrthJTvSb9qlEraO+HF9E5rxpe7sp5/3b+MXh3QnI+AyM5aWfqaGtltaFpUstsJejf5CXG3t/hsLlJx6ydZKLh335mb+sHu0heR8tUIwrWRxgNigowcexRrpbnjlum+e/i8WQsFsRRz4Sftu63UbvUGAnz0/u2TTAvtWlqZ2m6Pdz30jHeXhBKFPh25LYbZpzWjUtM8ybcfXZf02CBmXDx4MSV8ree0QsLNu417CStxGeyg3o6M+GtZtUyEviGGj45D9P8zoRhGGQS9M9r8lzgezuZ687CK/NzRmImHeNjKg7UoKxJiRC/ZjNCFNUg//3thpi5TOsJ9NCvj8UJR7Z2rfymDYswuGtLYW6eeqxO2tqx5buRTtAPfgt/GB19Bh8s3Jy0b12F2GTw6sjIbG2B+lxS2fD1e/TP2kqcnej5kre9ce1QdGxhnNPBTfLapBMKEZqUFOIeF7w3jHD6zj3+1Rrzc6ZesQLAXOAP+uuXiEQ4cTWwYJ2YiHDnuD6Ye9spKC2JuqZpbfa/GZiY1Uo0BSHC278fFjPffX7zSKHnTzdpq2r4dlwJtdputtK3uonRNRmZ/pxwysMzsK3ycCz8gpnAN0q8omI6aav7bv2RJp9vWPdWwhcZWiGvBT4ALL33dFzpUfIBq1qWvo2mymmackl6bFhrXlbFwZrYcWyjjnpG9zKOexSiaMfapmmDWKjZggLC70d2w33nijcjpEPvY96trDSj8003CG7GzHji67UA4tp62Ibk1ibxdsO840eOs5EfOhXrKg7hvfmbYwJ9x/5qw9GD2hEb3V2jd8AoeJrVZ+ODpS0xAi/w7xjnj8kSIFE4T71xBOZMNPZPtpVBJ8U+tTmmOt8ve6oSGr3TtmlWhnZ7OBJf7PKXM3vjchfcJO0w/ZZRGZ9jxbb9+GrljoSXf+X2AzHvkDplgU8kjUVHe/u0owFRc7Y+kjmuj1pCIYqZdD5atBWnPDwz6Zh4zKLkyoSIsL+6Djs1jhJ1kUisE49tszjvkO2AaVoCLfAblxTimhHdfNXYVXq3b4rSYuMplExSpmlR23KqGClVteHERu/wZpkVkSjw09fHS7qXGaextMvvXpqHyUvjaxi0ArtOkfRard0orK/2EWgFiZeBwrzC7SsqIEo7olLdMo064hAB93z8U8K2BRv3Jh0nNXyJPUwagh2FINWhEQteOsxxC/7BmvpYDBe7mGkxianpUs8p5DK7NNqgVkirwlurqe+pSkyTqCfswqStn3DbTFUQorQjo0rlGRh1qCEi7D+cuNBxb1XyKl6rV+FGSBWnBFrgm93mMX3a4v5fJaXe9RwzuWdHA07ph5/GNQ0QJ1DMFk9p63fp0M5o3qgIY48Rv3w/29zzyfJYHl+tDDGarE33eBO00yBKfJcp0Jh09FRW1eHTJVtj61qMDguFKCln9T6DTtrqGokMUzkLJS/dMn87sBNO7SPGKyATrNi905Hq0C37DmPH/urUAobF2FTNGrV2+5FtmmDRXadlXphP+W79LmzZV43e7VIHH7Oj8Vl1/cslXDfphMjUFPZfby5MCMRmrOEjSeCrUU61WJ1fUQOn+YG8EPh6oViQIoWhl5jVwp7Fw/xgNbbI2KPNNeqoQMn8FTQbRQTRfGPGu/M3Y8rS7QlhBIywc0symbQtCJE/Q2K7PWmbwoa/dd/hhO9G+ZlDRJZCIVjtjPWdRzbxT01c5FTFx1ddaOX1gisz0mn4Fw3qZLhfixXhkc7sI0TDN72WzM+dK6gx7SsN7L1aVmyzvpI5E3v3jD+Njn3Oo34XhSlMOnrCBrO2UZNOeq3c6qORAt8rlEb+h9HdseDOMWjXrAEA74J1pSOdDd+KO5cVgZo6X6gYhcusHn5ySTNCZO3Ua02n+T3+1dqU+7Vk8myysbDHCmp+CLeIjmysHWsU0iFEyTZ8I6x6UBX7SOALMekQ0RkAHgVQAOB5Zp6k2z8awEcAflY2vc/M94ko22L90LK0ONbrG0XI85KjUth4Z/55NC54ag4Ai8LcgshKreGzEA3fyqStX5h200hXXEP1qSTtoL1N2pqJcmghEE7t3SY22s0m445pjx37q/Hr4zu6Ep02lQ1fj5HJa9qy7ajV9RhGIy3rGn6AbPhEVADgSQBjEE1W/iMRfczMy3WHzmLmszItz1bddN+rlExCdpMyi+SLm0eirTLSMBKGXVqVxjRFK8IyU3nKEOMmZ27Dz/jUwumVZlLVKZlc6qrtxrkKRPL8FYNcL8MKoRDhmhHuRaUNkXWBX2cg8PXCHjC29eeihi+iJoMBrGXm9cxcC+BNAOcKOG/G6IWQmk8ymwK/R9smaKpkGjIT1qqQtKKFZizwBWmQZoqaHzV8t4ibdOwzX7Owx4fTrJ7w2U0jhJznprcWYfch47UO+tYYtmj70b8nvds3tTyh7peFhoAYgd8BwCbN983KNj3DiGgxEU0lItMgKkQ0nojmEdG8igrzGDJOqFWWuTdu4A/nJDNhqJpHrMjKzG3kYhz/zExLeSTvNSadzO6okyxZQeCodk2FneunLZWWjjPS3K3QrXUpcrFrFiHwjV5p/Z1YAKALM/cD8DiAD81OxszPMvNAZh5YVmYckCsdc287JeV+NWpjtjF3y7Rh0rFQTqpmKcxLR2r4EDUFLDI2fJdW/py4dZtmDYsMt+ubo1O3VQanjY/kR0QI/M0AtP6DHQEkpJlh5v3MfFD5PAVAERG5FwQ9zXvnl0kUU5OO8lSseeCkPyiVxhn1ws9cwIhYRJbrxDT8DM9TJ1CSvHHtUGHn8jt/0SQwsvoMnGr4zLkZ50iEwP8RQA8i6kpExQAuAvCx9gAiakeKZCKiwUq5uwWUbYhqXtDLmlevHhJLVu4HiAjvXXdC0vaQYA0/1ZxFhMX4ZeaqH/6JSvIVNV5+Jqj3IFM5YDUKoxXUZOUjerinX/kFbWJ2q6Mkxxq+IHdmr8nYmM3M9UR0A4BpiLplvsjMPxHRBGX/0wB+DeA6IqoHcBjARexiBCUzOXlij9Y40WcNv6xxcnq/WMYdQX74qbwEPl60Faf1zTy2jdnElN/98O84qw9+d2JXPGHDN94MUZcqcnVss4ZF+ObPJ8XWoAQZbRvU38Ot+w5jXcXBpLkmxxo+OCc1fCGzl4qZZopu29Oaz08AeEJEWVbwt4hJpGOLhrjyhHK8NGdDbJsqOESZdFI16s+X78Dny3ekL8ghftfwiwpC6NKqVIjpSZtIxk90ziE7PpHzEZJW4NfrzGJn/Osb7K+uRy9dAhyjlbZWEDX35TX+cRAViN+1Si2hEOGecxKdllThY8kt00IZVpeZZ0Ku2/BDAnqm2FxILkoCn5DJU9CGTNE3eTX4mb45ztuQHOfeCqLWr3hNIAW+Sm6ImmTUdmul43p/4Za0xzgdttrBzA8/R+S9kJFIDr7/viMTZS2Vhq+if0Y/KJnJ7BKdtHX006wSaIGfq8QnbcWcz4uIiWaavJ+SP6RCxEgkFwWA35h4xlHpDzKhUOMbHDaZtLWTWzgdufi4Aynwc3GopcWOl44VvNDwRZhEssnwI1vFPrdr6nSCkzX/S5xwbQZedNpRplmbF7eoLTcnbYMp8JW/uWTL12LHD98K3tjwXS/CVc44uj2m3hhd2u+02bA04WeVAq2GbybwBb0LzMCmPVWm+/26/sEfMQZcIpdk0BvXDsX366NLE+y4ZVohmyadQp8km7FCU5PVmXqKC0KGAbZUjS+IWapygcIEG76Zhi/m2fy0dT+276823e9XK0OgBX4uMax7KwzrHjUr2AmtYAUvTDpmnVNpFgPVOSXdXW9YXIDaw0YCP/p32RbrCU4k4tBO2pqNas0mc+2SStgD/jXr5d7baAGfdq6WiUfLFHM+p77GdjAy6UQDTOUOVrWyE3u0xuQl25J/L7pCEltY0fBFrmJORTjCmDj2KBzbsZkn5VklkDZ8lRw14efkpK1fsoiJIJUp7atbRuG/Tj7ScJ9fh/G5zIUDO1o+NtVKW5W6DCZt7zvXNMhvEhFmTBjVHSd099fK/kAKfDUa5ukCQgZkA9WTQFQ2oFlrdgk5Typy3UvHKt3KGpt2blLei6d9s4aWj7Xih5+J8mNHAfNrWwikSadRcSHm3XEqmluchPMbOw/UAACOaG69sWcbo3fhosHpk7D7Casvqdl7LydrxVNoQ5HQjszM5HomGr7VDHTMwJFtGjsux00CqeEDQOvGJVnPXesU1c7YwccCv5/ONmn0Mowf2d2r6ggl3XttZvLJxfjofqfAwMvrrrP6GB5rRQHPRPO2Ik7O698B6x4407cJ5AOp4ec6/7l6MGav2YVGxf6I22+I7u3SK2J+SJbtFmZyJRcX4vgdIw1/UHlLw2PdNipaMumwv1Ia6slNFTjg9G7fFNeO7JYzgceA5JehQ/PcC8drJq83TBqX8N3suUhxL54Cg1Rq5rmgzd8XETI4l95HM6TA9zG51L70L0OqGPx+J71Jx3i79NIRj5GGb7a2I9VzE/FkLGnuPn9nc/etzDOKfT4foX8XclHgayddU9XfVMOX8l44RkK2tLgAVwzrkrQ9RIR//Kaf4XnE5G32uTS3gJC3kojOIKJVRLSWiCYa7CciekzZv4SIBogoN+ho5YrftX39yyDKpdRL2jZtgIZFBZh4Rm98+z8nJ+1P5zEi5b14DO85AW1MAtx1bOGeo4Mlee/zRpDxpC0RFQB4EsAYRBOa/0hEHzPzcs1hYwH0UP4NAfCU8leSAq03SGGIUJPFugw/shW+XWuehljvuZKLAr9BUQFW/O8ZhvseOO8YDCpvAcBc08vmpO1FgzrhcF0YHy3amrU6uIF56kzjbW7qRUFYXCjirRwMYC0zr2fmWgBvAjhXd8y5AF7hKN8DaE5E7QWUnTc0aVCE+391dNbK79W2acJ3fdOvrU/0SSzJQZOOnrfGD8UrvxsMALhkSGf0UNLjmXvpiCv7hO6t0h+kYdIFx+LRi/oDAC4YYH11qh+Z8afRKFLcMY0UBwIZmtWY3Y2QK006UToA2KT5vlnZZvcYiQ7tJCCDcenQZLulF3RtXYqSosSmon+v2jSJJmNXc4aWNUlOzp5rDOnWCiN7liVtN/XWEKjh927fNP1BBmyYNA4PX2hsx84VyluXYpRy3400fCJzbdtNmWxFw/e5RUeIH77RXdBft5VjogcSjQcwHgA6d+6cWc1yHL9MAn51yyg8+NmqlMc0b1SEDZPGoS4cwadLtuKcfkd4VDvvMXvvRWr4AVAmM0Jt+4YCH+batptWFwMP0ZxDxCVsBqBdQ98RgN6QaOUYAAAzP8vMA5l5YFlZsnaVT2gFfjaFPxGltU+rqQyLCkI4r3/HnE0+YwWzS1u6pVJYGV5FdfQr6tUba/hk2CFGm6iLJp0AtGkRAv9HAD2IqCsRFQO4CMDHumM+BnC54q0zFEAlMyfHl5Uk4KeVm14kUckVvMjTm+8+/er1G3npEIw7Aga7quH7eQWtVTI26TBzPRHdAGAagAIALzLzT0Q0Qdn/NIApAM4EsBZAFYCrMi03H4gk2PCzSzqBHwDlxzJevPfZft7ZRr1+I62ayHg7s7teOuk0/PbNGuD3o5zn5PUCIbF0mHkKokJdu+1pzWcGcL2IsvIJrYz12iVsUHkL/Lhhr6Yu6Uw6+YMX5qo8V/Bx/oCOmLGqAr3aNUnaR6AU7pruPZt0p/7uL6e4VrYoAjANEVy0ni4Nirx9VH8975iE73qBn9T280jie6Hh+8mclw3O6XcENkwaZxoi3NCGD3ebYRDMmlLg+5hmDYvw4fXDAQAlhd5GztS/OOnCiHth1/YLntjwdd+bGeR2eOay412vhy8xMekA7poWvcgc5zZS4PscdfJK7wfvNvqhsVlSaJV2zXIvOqZTyINHoVfwP7nhRPcLzRHMbfjsamccNvGcmvnn0fj85pGulSsSGQ/f59QoK1i9Xrmqf5/CJiaGLq0aYePuKnTxacIHN/BmLKMzoZm6IeYf5l46bmv4xsPcLq1K3StUMFLg+5zqujCAaJwXL9G/N0k2fOXNevCCY9H3iKaBWHZuFS/8sfWyJZ+8oNJBRIbtLRpawb1yg7A2Qpp0fE4qDd/Nidx0Jp27z+6Dfh2b4bhOzdGkQW7mDnaKF8JXnx/XuJPJfQFkhYd1IY8Jxl5rHZo3FGrSefzi/pg49qjYd73S07K0GCf1yq3FoVLg+5z+nZsDAK4ZkezfO/+OMa6VmzRpq5Mtx3Zsjo9uONHzkYcf8ELD15trgrDK0ynnHJcYpoMoOb/sHeN6o12zBkI747P7HYEJo+J5mccenRjvccGdY/DvqwaLK9ADpEnH57Rp0iApxZ6KWeYfEehfnHSTthKx6O+2eSiBeOC6oKLv7AiUNAJV3wU3+8VcTOqjRwp8iSH6oXG++4Vr8ULZNpsz0cIAZt16EpoG3KRm1NmZumXmkXuwE6TAz1FG9Gjt6vmTvHSkhu8tuttt5qXTKQ+8o/SdnZFJR7tPYk7uj1HylH9fOcjT8k4+qo2n5fmZIiVO7iiDWPmi0Gv4+WzDN8Jcw5ekQmr4OYrbkfv079NvB3XCmce2x7H3fO5qublAKETYMGkc5m/ci5mrK1wpw5INP0+8dPRENXzvVto+eMEx6HtEM/EnzgJS4OcobgfwSpooIwq8rdgubj4C/ZRJkPMLOOFoUwFs7T41LCrAYWWNSzp+Oyg4iZikSUdiiJQv6XHzFqXS8Lu1zp2VnaKYfsuo2GdmoEVpseFxVge+DYvzz50YkAI/53jpqkEYd6z7+d+lt0N63NS6U9nw1Xy3+eQ41b2sMWb/z0n4+wXHxtZ+DD8yOdG71WfSMA/XjwBS4Occo3u1wZOXDHC9HLP35r9PPhIP6EIn5yuuTqOk8NI5rW9bAEDv9smx4oNMxxaNcOGgeKbU5y8flOStZvWR5KuGL234EkPMXpw/ntbL03r4GTdHQU114ZC1Gv65x3XA6X3b5eUqZy0NiwvQQRcv3+qgK1MN//Vrh2T0+2yRkcAnopYA3gJQDmADgAuZea/BcRsAHAAQBlDPzAMzKVcS54phXfDydxvFn1hadNKiml1KiwtwqNbaBKCWE7q3wpx1uxO2PXvZ8di09zB+O6gT3pj7S2w7EbD0ntNiJot8F/ZmWO2E7zmnLy54ao7p/tevMRbon900Ai0bFaNN09wMB56pSWcigOnM3APAdOW7GScx83FS2ItFvvjZY09VLQCgp0EaPisYrV4+rW87XH1iVzTWhc0IEaFJg6Kk7ZJErGj4XVuX4vguLWLffzuwU9IxJxxpvLDxqHZNc1bYA5kL/HMBvKx8fhnArzI8n8Qmrvnj59GEoFOGd2+NK08ox9/OdzanoQ2B/OfTe2HubYk5Ue86q0/ss1x4JQ79nTTz+AkimQr8tsy8DQCUv2bLMRnA50Q0n4jGpzohEY0nonlENK+iwp1FLUGiUFljfl7/DnjpquTVt04Da0l5n57iwhDuOacvWjoUGFoNv0mDwiTN8Xcndo19luLeGpb6Rd0x+dSXphX4RPQlES0z+HeujXKGM/MAAGMBXE9EpvnAmPlZZh7IzAPLynIr1nQ2GNM76rFx5QnlGN0rub91avKRwdKs43TydoDGrJDOnTCfhJIdhiumlz6Kq6oVt8x8vpVpDYLMfKrZPiLaQUTtmXkbEbUHsNPkHFuVvzuJ6AMAgwF847DOEg3HdGxmGj4Z8D41Yj6ilTF2VnCOH9kNSzbvw/fr95gKoZ5tG2P1joNypa0JZ/c7AiN7lsWSvFuxcCYFY3OjYj4lU2nwMYArlM9XAPhIfwARlRJRE/UzgNMALMuwXIlF2tqYYGqmcQWUCr51tPb1I9s0TtkB63/XVVk1a2ajf3P8MLz9+2GZVzLAaNutldGWvlPIp740U4E/CcAYIloDYIzyHUR0BBFNUY5pC2A2ES0GMBfAZGb+LMNyJRa5/1dHWz72hSviDlSFeZSjNlO0d8pObl9CPOy02c9alhZjcNeWziuXZ1gR3vpOIZ9WlWfk48XMuwGcYrB9K4Azlc/rAfTTHyPxBv0CnlRohVUuu555jVbI2OkniYCw4qnjdvTTfMHSnK3U8CVBxY4cURNDt28mhb0dtBqiHfdJAqFe8c0sLMgjqeMmmts49/YkXTTlT9xOKuQHpMAPOHaGq1LLdIjmthXYURcJqFdMOoUh+SqKQG3vRECTEuPRrTppu+DOMZgz8eSYiq9djBVUZCsLOKR7wqN6lqGdiblG1U7lhK09Ekw6yv2eeuMITL1xRNrfhcOqwJedrQjUZxEiMjXV1Ct2tJalxThCE4snH9q9FPgBR29iSCVXpIbvjMbFhRq3wOg97N2+KY5s0zh2zN1n90n6HSGu4ct7LwbS/DW7p2t2HjT8TR7Ieynwg46+yaeyMevfj9evHYJnLjtefKUCRihEeOKS/tHPmvurvZ1XDe8KPUSEsLThC0U114SILM+n5NOkrYzEFHCMUhWaoe5Tc6We0D34k1iiOKpddKXnFSeUx7bp7/2IHq0xa82u2PdEDV/qXiIIaVR824MmZnxyw4loWBzcZyEFfsBQV2aq6OV7qpcgnzQd0ZQ1KUlacKW/ny9fNRgLN+3FBU99F9sfjkgbvkhik7awnv1K/Q0junI9yAS3K8tTPrx+eELURSOfYzaxVkqRIxa9wAmFCH01ybcJhPqwtOELRbmN6q3fMGlc2vAi6rFy0laSczQqjkZd7Na6FEe1a5Lklqk3M/z7qkExrV966biPNpgdEWJ++EXShi8E0rVl/WfD3yh/zRShICFNOgHlqz+NBgBEIoyebRujc8tSfLliR1LjP0kTYVOadLwnLG34rpAQ7iJNu75wUCd8vHgrLhnSxdU6+QHZygJOKET4/OZROOe4IwBEhXpSLBFS7Z5S4nuBar6hhIVX8t6LQB2dGmn4w7q1MvxN26YN8MUfRyXlxw0iUuDnCcxqkK5kwRJzbFBtmR7VKV85sizqn8+s1fClwBeC0ni1zfzyE6Kae2lJ1JymutDmI9KkkyeoCU20L8LNp/ZMOKZ14xIM7toSN57Sw8uq5R2vXTsEC3/ZhwZFBVLDF0y8ncfv559O64WbT+2JGasq8OWKnejXsXmWapd9pMDPE7RDXXVy6sJBHQHEO4GCEMnY64K5ZUxPDNcF5WrduARj+kQzlanL/KWGL4YmDQpR1qQEd4zrHdtGRCgsIJzap63lXAVBRQr8PCFiMNTV2+zzwUvBa/4rzWjpmcsG4t/f/ozyVqUe1SjYFBaE8OPtpkn68h5pw88TurZuBADo36l50r7uik1ZTtp6T692TTDpgmNtJU6RSJySkcAnot8Q0U9EFCGigSmOO4OIVhHRWiKamEmZEmcc36UlvrplFC4dmux69to1Q/DSVYNQLPPfSiSBJtM3fBmA85EiITkRFQB4EsBYAH0AXExEyaEDJa7TrawxiAgNlcU/qnmnVeMSjNb440skkmCSaYrDFUDamBWDAaxVUh2CiN4EcC6A5ZmULXHOK78bgk+WbEWbJiXZropEIvEQL8bwHQBs0nzfrGwzhIjGE9E8IppXUVHheuXykc6tGuH6k460HFxKIpEEg7QaPhF9CaCdwa7bmfkjC2UYSRVTdxBmfhbAswAwcOBA6TYikUgkgkgr8Jk5Ux+nzQA6ab53BLA1w3NKJBKJxCZemHR+BNCDiLoSUTGAiwB87EG5EolEItGQqVvmeUS0GcAwAJOJaJqy/QgimgIAzFwP4AYA0wCsAPA2M/+UWbUlEolEYpdMvXQ+APCBwfatAM7UfJ8CYEomZUkkEokkM+RKG4lEIskTpMCXSCSSPEEKfIlEIskTiH2cwJSIKgBsdPjz1gB2CaxOLiCvOT+Q1xx8MrneLsxcZrTD1wI/E4hoHjObBnQLIvKa8wN5zcHHreuVJh2JRCLJE6TAl0gkkjwhyAL/2WxXIAvIa84P5DUHH1euN7A2fIlEIpEkEmQNXyKRSCQapMCXSCSSPCFwAj+o+XOJqBMRfU1EK5Q8wjcq21sS0RdEtEb520Lzm78o92EVEZ2evdpnBhEVENFCIvpU+R7oayai5kT0LhGtVJ73sDy45puVdr2MiN4gogZBu2YiepGIdhLRMs0229dIRMcT0VJl32NkJ5MRMwfmH4ACAOsAdANQDGAxgD7Zrpega2sPYIDyuQmA1YjmCP47gInK9okAHlQ+91GuvwRAV+W+FGT7Ohxe+x8BvA7gU+V7oK8ZwMsArlE+FwNoHuRrRjQD3s8AGirf3wZwZdCuGcBIAAMALNNss32NAOYiGqGYAEwFMNZqHYKm4cfy5zJzLQA1f27Ow8zbmHmB8vkAoqGmOyB6fS8rh70M4FfK53MBvMnMNcz8M4C1iN6fnIKIOgIYB+B5zebAXjMRNUVUMLwAAMxcy8z7EOBrVigE0JCICgE0QjRJUqCumZm/AbBHt9nWNRJRewBNmfk7jkr/VzS/SUvQBL6t/Lm5ChGVA+gP4AcAbZl5GxDtFAC0UQ4Lyr34F4BbAUQ024J8zd0AVAD4t2LGep6IShHga2bmLQD+AeAXANsAVDLz5wjwNWuwe40dlM/67ZYImsC3lT83FyGixgDeA3ATM+9PdajBtpy6F0R0FoCdzDzf6k8MtuXUNSOq6Q4A8BQz9wdwCNGhvhk5f82K3fpcRE0XRwAoJaJLU/3EYFtOXbMFzK4xo2sPmsAPdP5cIipCVNi/xszvK5t3KMM8KH93KtuDcC+GAziHiDYgap47mYheRbCveTOAzcz8g/L9XUQ7gCBf86kAfmbmCmauA/A+gBMQ7GtWsXuNm5XP+u2WCJrAD2z+XGUm/gUAK5j5Ec2ujwFcoXy+AsBHmu0XEVEJEXUF0APRyZ6cgZn/wswdmbkc0Wf5FTNfimBf83YAm4iol7LpFADLEeBrRtSUM5SIGint/BRE56iCfM0qtq5RMfscIKKhyr26XPOb9GR75tqFmfAzEfVgWQfg9mzXR+B1nYjo0G0JgEXKvzMBtAIwHcAa5W9LzW9uV+7DKtiYyffjPwCjEffSCfQ1AzgOwDzlWX8IoEUeXPO9AFYCWAbgP4h6pwTqmgG8gegcRR2imvrVTq4RwEDlPq0D8ASUiAlW/snQChKJRJInBM2kI5FIJBITpMCXSCSSPEEKfIlEIskTpMCXSCSSPEEKfIlEIskTpMCXSCSSPEEKfIlEIskT/j8xpQaViviG0AAAAABJRU5ErkJggg==\n",
|
|
"text/plain": [
|
|
"<Figure size 432x288 with 1 Axes>"
|
|
]
|
|
},
|
|
"metadata": {
|
|
"filenames": {
|
|
"image/png": "/Users/mhjensen/Teaching/MachineLearning/doc/LectureNotes/_build/jupyter_execute/chapter13_3_1.png"
|
|
},
|
|
"needs_background": "light"
|
|
},
|
|
"output_type": "display_data"
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Model: \"sequential\"\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"_________________________________________________________________\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
" Layer (type) Output Shape Param # \n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"=================================================================\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
" simple_rnn (SimpleRNN) (None, 32) 1184 \n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
" \n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
" dense (Dense) (None, 8) 264 \n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
" \n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
" dense_1 (Dense) (None, 1) 9 \n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
" \n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"=================================================================\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Total params: 1,457\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Trainable params: 1,457\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Non-trainable params: 0\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"_________________________________________________________________\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 1/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 2s - loss: 1.1810 - 2s/epoch - 33ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 2/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4703 - 307ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 3/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4379 - 303ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 4/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4275 - 305ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 5/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4224 - 307ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 6/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4224 - 308ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 7/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4212 - 308ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 8/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4198 - 308ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 9/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4198 - 304ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 10/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4177 - 304ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 11/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4186 - 305ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 12/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4176 - 305ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 13/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4167 - 303ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 14/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4143 - 306ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 15/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4128 - 306ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 16/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4144 - 324ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 17/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4146 - 307ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 18/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4131 - 303ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 19/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4117 - 305ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 20/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4115 - 319ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 21/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4100 - 305ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 22/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4088 - 307ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 23/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4089 - 303ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 24/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4082 - 306ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 25/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4084 - 304ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 26/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4068 - 306ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 27/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4075 - 306ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 28/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4055 - 307ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 29/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4069 - 305ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 30/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4048 - 307ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 31/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4038 - 305ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 32/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4059 - 307ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 33/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4039 - 306ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 34/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4045 - 320ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 35/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4030 - 306ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 36/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4012 - 304ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 37/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3994 - 304ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 38/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4027 - 306ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 39/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4011 - 305ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 40/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4017 - 305ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 41/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3996 - 303ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 42/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3996 - 305ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 43/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.4005 - 306ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 44/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3994 - 303ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 45/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3979 - 307ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 46/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3983 - 305ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 47/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3979 - 304ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 48/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3955 - 305ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 49/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3970 - 305ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 50/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3962 - 304ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 51/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3943 - 306ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 52/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3975 - 304ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 53/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3944 - 305ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 54/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3950 - 304ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 55/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3960 - 305ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 56/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3922 - 305ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 57/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3922 - 305ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 58/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3928 - 306ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 59/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3915 - 317ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 60/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3916 - 304ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 61/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3889 - 308ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 62/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3917 - 305ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 63/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3891 - 307ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 64/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3906 - 308ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 65/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3914 - 306ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 66/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3889 - 307ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 67/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3872 - 302ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 68/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3881 - 306ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 69/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3869 - 305ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 70/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3888 - 305ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 71/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3864 - 305ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 72/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3871 - 302ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 73/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3862 - 306ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 74/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3861 - 303ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 75/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3858 - 306ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 76/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3864 - 326ms/epoch - 7ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 77/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3851 - 331ms/epoch - 7ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 78/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3862 - 312ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 79/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3837 - 324ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 80/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3815 - 341ms/epoch - 7ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 81/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3838 - 306ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 82/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3834 - 307ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 83/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3830 - 311ms/epoch - 6ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 84/100\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"50/50 - 0s - loss: 0.3839 - 368ms/epoch - 7ms/step\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 85/100\n"
|
|
]
|
|
},
|
|
{
|
|
"ename": "KeyboardInterrupt",
|
|
"evalue": "",
|
|
"output_type": "error",
|
|
"traceback": [
|
|
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
|
"\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
|
|
"\u001b[0;32m<ipython-input-1-fdfcc778e1f8>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 56\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msummary\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 57\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 58\u001b[0;31m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtrainX\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mtrainY\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mepochs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m100\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbatch_size\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m16\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mverbose\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 59\u001b[0m \u001b[0mtrainPredict\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpredict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtrainX\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 60\u001b[0m \u001b[0mtestPredict\u001b[0m\u001b[0;34m=\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpredict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtestX\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;32m~/miniforge3/envs/myenv/lib/python3.9/site-packages/keras/utils/traceback_utils.py\u001b[0m in \u001b[0;36merror_handler\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 62\u001b[0m \u001b[0mfiltered_tb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 63\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 64\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mfn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 65\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mException\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;31m# pylint: disable=broad-except\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 66\u001b[0m \u001b[0mfiltered_tb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_process_traceback_frames\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0me\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__traceback__\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;32m~/miniforge3/envs/myenv/lib/python3.9/site-packages/keras/engine/training.py\u001b[0m in \u001b[0;36mfit\u001b[0;34m(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_batch_size, validation_freq, max_queue_size, workers, use_multiprocessing)\u001b[0m\n\u001b[1;32m 1382\u001b[0m _r=1):\n\u001b[1;32m 1383\u001b[0m \u001b[0mcallbacks\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mon_train_batch_begin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstep\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1384\u001b[0;31m \u001b[0mtmp_logs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtrain_function\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0miterator\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1385\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mdata_handler\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshould_sync\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1386\u001b[0m \u001b[0mcontext\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0masync_wait\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;32m~/miniforge3/envs/myenv/lib/python3.9/site-packages/tensorflow/python/util/traceback_utils.py\u001b[0m in \u001b[0;36merror_handler\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 148\u001b[0m \u001b[0mfiltered_tb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 149\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 150\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mfn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 151\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mException\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 152\u001b[0m \u001b[0mfiltered_tb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_process_traceback_frames\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0me\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__traceback__\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;32m~/miniforge3/envs/myenv/lib/python3.9/site-packages/tensorflow/python/eager/def_function.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, *args, **kwds)\u001b[0m\n\u001b[1;32m 913\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 914\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mOptionalXlaContext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_jit_compile\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 915\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_call\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwds\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 916\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 917\u001b[0m \u001b[0mnew_tracing_count\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexperimental_get_tracing_count\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;32m~/miniforge3/envs/myenv/lib/python3.9/site-packages/tensorflow/python/eager/def_function.py\u001b[0m in \u001b[0;36m_call\u001b[0;34m(self, *args, **kwds)\u001b[0m\n\u001b[1;32m 945\u001b[0m \u001b[0;31m# In this case we have created variables on the first call, so we run the\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 946\u001b[0m \u001b[0;31m# defunned version which is guaranteed to never create variables.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 947\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_stateless_fn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwds\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# pylint: disable=not-callable\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 948\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_stateful_fn\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 949\u001b[0m \u001b[0;31m# Release the lock early so that multiple threads can perform the call\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;32m~/miniforge3/envs/myenv/lib/python3.9/site-packages/tensorflow/python/eager/function.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 2954\u001b[0m (graph_function,\n\u001b[1;32m 2955\u001b[0m filtered_flat_args) = self._maybe_define_function(args, kwargs)\n\u001b[0;32m-> 2956\u001b[0;31m return graph_function._call_flat(\n\u001b[0m\u001b[1;32m 2957\u001b[0m filtered_flat_args, captured_inputs=graph_function.captured_inputs) # pylint: disable=protected-access\n\u001b[1;32m 2958\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;32m~/miniforge3/envs/myenv/lib/python3.9/site-packages/tensorflow/python/eager/function.py\u001b[0m in \u001b[0;36m_call_flat\u001b[0;34m(self, args, captured_inputs, cancellation_manager)\u001b[0m\n\u001b[1;32m 1851\u001b[0m and executing_eagerly):\n\u001b[1;32m 1852\u001b[0m \u001b[0;31m# No tape is watching; skip to running the function.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1853\u001b[0;31m return self._build_call_outputs(self._inference_function.call(\n\u001b[0m\u001b[1;32m 1854\u001b[0m ctx, args, cancellation_manager=cancellation_manager))\n\u001b[1;32m 1855\u001b[0m forward_backward = self._select_forward_and_backward_functions(\n",
|
|
"\u001b[0;32m~/miniforge3/envs/myenv/lib/python3.9/site-packages/tensorflow/python/eager/function.py\u001b[0m in \u001b[0;36mcall\u001b[0;34m(self, ctx, args, cancellation_manager)\u001b[0m\n\u001b[1;32m 497\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0m_InterpolateFunctionError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 498\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mcancellation_manager\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 499\u001b[0;31m outputs = execute.execute(\n\u001b[0m\u001b[1;32m 500\u001b[0m \u001b[0mstr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 501\u001b[0m \u001b[0mnum_outputs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_num_outputs\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;32m~/miniforge3/envs/myenv/lib/python3.9/site-packages/tensorflow/python/eager/execute.py\u001b[0m in \u001b[0;36mquick_execute\u001b[0;34m(op_name, num_outputs, inputs, attrs, ctx, name)\u001b[0m\n\u001b[1;32m 52\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 53\u001b[0m \u001b[0mctx\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mensure_initialized\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 54\u001b[0;31m tensors = pywrap_tfe.TFE_Py_Execute(ctx._handle, device_name, op_name,\n\u001b[0m\u001b[1;32m 55\u001b[0m inputs, attrs, num_outputs)\n\u001b[1;32m 56\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mcore\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_NotOkStatusException\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;31mKeyboardInterrupt\u001b[0m: "
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%matplotlib inline\n",
|
|
"\n",
|
|
"# Start importing packages\n",
|
|
"import pandas as pd\n",
|
|
"import numpy as np\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"import tensorflow as tf\n",
|
|
"from tensorflow.keras import datasets, layers, models\n",
|
|
"from tensorflow.keras.layers import Input\n",
|
|
"from tensorflow.keras.models import Model, Sequential \n",
|
|
"from tensorflow.keras.layers import Dense, SimpleRNN, LSTM, GRU\n",
|
|
"from tensorflow.keras import optimizers \n",
|
|
"from tensorflow.keras import regularizers \n",
|
|
"from tensorflow.keras.utils import to_categorical \n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"# convert into dataset matrix\n",
|
|
"def convertToMatrix(data, step):\n",
|
|
" X, Y =[], []\n",
|
|
" for i in range(len(data)-step):\n",
|
|
" d=i+step \n",
|
|
" X.append(data[i:d,])\n",
|
|
" Y.append(data[d,])\n",
|
|
" return np.array(X), np.array(Y)\n",
|
|
"\n",
|
|
"step = 4\n",
|
|
"N = 1000 \n",
|
|
"Tp = 800 \n",
|
|
"\n",
|
|
"t=np.arange(0,N)\n",
|
|
"x=np.sin(0.02*t)+2*np.random.rand(N)\n",
|
|
"df = pd.DataFrame(x)\n",
|
|
"df.head()\n",
|
|
"\n",
|
|
"plt.plot(df)\n",
|
|
"plt.show()\n",
|
|
"\n",
|
|
"values=df.values\n",
|
|
"train,test = values[0:Tp,:], values[Tp:N,:]\n",
|
|
"\n",
|
|
"# add step elements into train and test\n",
|
|
"test = np.append(test,np.repeat(test[-1,],step))\n",
|
|
"train = np.append(train,np.repeat(train[-1,],step))\n",
|
|
" \n",
|
|
"trainX,trainY =convertToMatrix(train,step)\n",
|
|
"testX,testY =convertToMatrix(test,step)\n",
|
|
"trainX = np.reshape(trainX, (trainX.shape[0], 1, trainX.shape[1]))\n",
|
|
"testX = np.reshape(testX, (testX.shape[0], 1, testX.shape[1]))\n",
|
|
"\n",
|
|
"model = Sequential()\n",
|
|
"model.add(SimpleRNN(units=32, input_shape=(1,step), activation=\"relu\"))\n",
|
|
"model.add(Dense(8, activation=\"relu\")) \n",
|
|
"model.add(Dense(1))\n",
|
|
"model.compile(loss='mean_squared_error', optimizer='rmsprop')\n",
|
|
"model.summary()\n",
|
|
"\n",
|
|
"model.fit(trainX,trainY, epochs=100, batch_size=16, verbose=2)\n",
|
|
"trainPredict = model.predict(trainX)\n",
|
|
"testPredict= model.predict(testX)\n",
|
|
"predicted=np.concatenate((trainPredict,testPredict),axis=0)\n",
|
|
"\n",
|
|
"trainScore = model.evaluate(trainX, trainY, verbose=0)\n",
|
|
"print(trainScore)\n",
|
|
"\n",
|
|
"index = df.index.values\n",
|
|
"plt.plot(index,df)\n",
|
|
"plt.plot(index,predicted)\n",
|
|
"plt.axvline(df.index[Tp], c=\"r\")\n",
|
|
"plt.show()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "897a47c7",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## An extrapolation example\n",
|
|
"\n",
|
|
"The following code provides an example of how recurrent neural\n",
|
|
"networks can be used to extrapolate to unknown values of physics data\n",
|
|
"sets. Specifically, the data sets used in this program come from\n",
|
|
"a quantum mechanical many-body calculation of energies as functions of the number of particles."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"id": "6776ae2a",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"\n",
|
|
"# For matrices and calculations\n",
|
|
"import numpy as np\n",
|
|
"# For machine learning (backend for keras)\n",
|
|
"import tensorflow as tf\n",
|
|
"# User-friendly machine learning library\n",
|
|
"# Front end for TensorFlow\n",
|
|
"import tensorflow.keras\n",
|
|
"# Different methods from Keras needed to create an RNN\n",
|
|
"# This is not necessary but it shortened function calls \n",
|
|
"# that need to be used in the code.\n",
|
|
"from tensorflow.keras import datasets, layers, models\n",
|
|
"from tensorflow.keras.layers import Input\n",
|
|
"from tensorflow.keras import regularizers\n",
|
|
"from tensorflow.keras.models import Model, Sequential\n",
|
|
"from tensorflow.keras.layers import Dense, SimpleRNN, LSTM, GRU\n",
|
|
"# For timing the code\n",
|
|
"from timeit import default_timer as timer\n",
|
|
"# For plotting\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"\n",
|
|
"\n",
|
|
"# The data set\n",
|
|
"datatype='VaryDimension'\n",
|
|
"X_tot = np.arange(2, 42, 2)\n",
|
|
"y_tot = np.array([-0.03077640549, -0.08336233266, -0.1446729567, -0.2116753732, -0.2830637392, -0.3581341341, -0.436462435, -0.5177783846,\n",
|
|
"\t-0.6019067271, -0.6887363571, -0.7782028952, -0.8702784034, -0.9649652536, -1.062292565, -1.16231451, \n",
|
|
"\t-1.265109911, -1.370782966, -1.479465113, -1.591317992, -1.70653767])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "35227d36",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"The way the recurrent neural networks are trained in this program\n",
|
|
"differs from how machine learning algorithms are usually trained.\n",
|
|
"Typically a machine learning algorithm is trained by learning the\n",
|
|
"relationship between the x data and the y data. In this program, the\n",
|
|
"recurrent neural network will be trained to recognize the relationship\n",
|
|
"in a sequence of y values. This is type of data formatting is\n",
|
|
"typically used time series forcasting, but it can also be used in any\n",
|
|
"extrapolation (time series forecasting is just a specific type of\n",
|
|
"extrapolation along the time axis). This method of data formatting\n",
|
|
"does not use the x data and assumes that the y data are evenly spaced.\n",
|
|
"\n",
|
|
"For a standard machine learning algorithm, the training data has the\n",
|
|
"form of (x,y) so the machine learning algorithm learns to assiciate a\n",
|
|
"y value with a given x value. This is useful when the test data has x\n",
|
|
"values within the same range as the training data. However, for this\n",
|
|
"application, the x values of the test data are outside of the x values\n",
|
|
"of the training data and the traditional method of training a machine\n",
|
|
"learning algorithm does not work as well. For this reason, the\n",
|
|
"recurrent neural network is trained on sequences of y values of the\n",
|
|
"form ((y1, y2), y3), so that the network is concerned with learning\n",
|
|
"the pattern of the y data and not the relation between the x and y\n",
|
|
"data. As long as the pattern of y data outside of the training region\n",
|
|
"stays relatively stable compared to what was inside the training\n",
|
|
"region, this method of training can produce accurate extrapolations to\n",
|
|
"y values far removed from the training data set."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"id": "7dc577d1",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# FORMAT_DATA\n",
|
|
"def format_data(data, length_of_sequence = 2): \n",
|
|
" \"\"\"\n",
|
|
" Inputs:\n",
|
|
" data(a numpy array): the data that will be the inputs to the recurrent neural\n",
|
|
" network\n",
|
|
" length_of_sequence (an int): the number of elements in one iteration of the\n",
|
|
" sequence patter. For a function approximator use length_of_sequence = 2.\n",
|
|
" Returns:\n",
|
|
" rnn_input (a 3D numpy array): the input data for the recurrent neural network. Its\n",
|
|
" dimensions are length of data - length of sequence, length of sequence, \n",
|
|
" dimnsion of data\n",
|
|
" rnn_output (a numpy array): the training data for the neural network\n",
|
|
" Formats data to be used in a recurrent neural network.\n",
|
|
" \"\"\"\n",
|
|
"\n",
|
|
" X, Y = [], []\n",
|
|
" for i in range(len(data)-length_of_sequence):\n",
|
|
" # Get the next length_of_sequence elements\n",
|
|
" a = data[i:i+length_of_sequence]\n",
|
|
" # Get the element that immediately follows that\n",
|
|
" b = data[i+length_of_sequence]\n",
|
|
" # Reshape so that each data point is contained in its own array\n",
|
|
" a = np.reshape (a, (len(a), 1))\n",
|
|
" X.append(a)\n",
|
|
" Y.append(b)\n",
|
|
" rnn_input = np.array(X)\n",
|
|
" rnn_output = np.array(Y)\n",
|
|
"\n",
|
|
" return rnn_input, rnn_output\n",
|
|
"\n",
|
|
"\n",
|
|
"# ## Defining the Recurrent Neural Network Using Keras\n",
|
|
"# \n",
|
|
"# The following method defines a simple recurrent neural network in keras consisting of one input layer, one hidden layer, and one output layer.\n",
|
|
"\n",
|
|
"def rnn(length_of_sequences, batch_size = None, stateful = False):\n",
|
|
" \"\"\"\n",
|
|
" Inputs:\n",
|
|
" length_of_sequences (an int): the number of y values in \"x data\". This is determined\n",
|
|
" when the data is formatted\n",
|
|
" batch_size (an int): Default value is None. See Keras documentation of SimpleRNN.\n",
|
|
" stateful (a boolean): Default value is False. See Keras documentation of SimpleRNN.\n",
|
|
" Returns:\n",
|
|
" model (a Keras model): The recurrent neural network that is built and compiled by this\n",
|
|
" method\n",
|
|
" Builds and compiles a recurrent neural network with one hidden layer and returns the model.\n",
|
|
" \"\"\"\n",
|
|
" # Number of neurons in the input and output layers\n",
|
|
" in_out_neurons = 1\n",
|
|
" # Number of neurons in the hidden layer\n",
|
|
" hidden_neurons = 200\n",
|
|
" # Define the input layer\n",
|
|
" inp = Input(batch_shape=(batch_size, \n",
|
|
" length_of_sequences, \n",
|
|
" in_out_neurons)) \n",
|
|
" # Define the hidden layer as a simple RNN layer with a set number of neurons and add it to \n",
|
|
" # the network immediately after the input layer\n",
|
|
" rnn = SimpleRNN(hidden_neurons, \n",
|
|
" return_sequences=False,\n",
|
|
" stateful = stateful,\n",
|
|
" name=\"RNN\")(inp)\n",
|
|
" # Define the output layer as a dense neural network layer (standard neural network layer)\n",
|
|
" #and add it to the network immediately after the hidden layer.\n",
|
|
" dens = Dense(in_out_neurons,name=\"dense\")(rnn)\n",
|
|
" # Create the machine learning model starting with the input layer and ending with the \n",
|
|
" # output layer\n",
|
|
" model = Model(inputs=[inp],outputs=[dens])\n",
|
|
" # Compile the machine learning model using the mean squared error function as the loss \n",
|
|
" # function and an Adams optimizer.\n",
|
|
" model.compile(loss=\"mean_squared_error\", optimizer=\"adam\") \n",
|
|
" return model"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "1978b6a1",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## Predicting New Points With A Trained Recurrent Neural Network"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"id": "d4ad417a",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def test_rnn (x1, y_test, plot_min, plot_max):\n",
|
|
" \"\"\"\n",
|
|
" Inputs:\n",
|
|
" x1 (a list or numpy array): The complete x component of the data set\n",
|
|
" y_test (a list or numpy array): The complete y component of the data set\n",
|
|
" plot_min (an int or float): the smallest x value used in the training data\n",
|
|
" plot_max (an int or float): the largest x valye used in the training data\n",
|
|
" Returns:\n",
|
|
" None.\n",
|
|
" Uses a trained recurrent neural network model to predict future points in the \n",
|
|
" series. Computes the MSE of the predicted data set from the true data set, saves\n",
|
|
" the predicted data set to a csv file, and plots the predicted and true data sets w\n",
|
|
" while also displaying the data range used for training.\n",
|
|
" \"\"\"\n",
|
|
" # Add the training data as the first dim points in the predicted data array as these\n",
|
|
" # are known values.\n",
|
|
" y_pred = y_test[:dim].tolist()\n",
|
|
" # Generate the first input to the trained recurrent neural network using the last two \n",
|
|
" # points of the training data. Based on how the network was trained this means that it\n",
|
|
" # will predict the first point in the data set after the training data. All of the \n",
|
|
" # brackets are necessary for Tensorflow.\n",
|
|
" next_input = np.array([[[y_test[dim-2]], [y_test[dim-1]]]])\n",
|
|
" # Save the very last point in the training data set. This will be used later.\n",
|
|
" last = [y_test[dim-1]]\n",
|
|
"\n",
|
|
" # Iterate until the complete data set is created.\n",
|
|
" for i in range (dim, len(y_test)):\n",
|
|
" # Predict the next point in the data set using the previous two points.\n",
|
|
" next = model.predict(next_input)\n",
|
|
" # Append just the number of the predicted data set\n",
|
|
" y_pred.append(next[0][0])\n",
|
|
" # Create the input that will be used to predict the next data point in the data set.\n",
|
|
" next_input = np.array([[last, next[0]]], dtype=np.float64)\n",
|
|
" last = next\n",
|
|
"\n",
|
|
" # Print the mean squared error between the known data set and the predicted data set.\n",
|
|
" print('MSE: ', np.square(np.subtract(y_test, y_pred)).mean())\n",
|
|
" # Save the predicted data set as a csv file for later use\n",
|
|
" name = datatype + 'Predicted'+str(dim)+'.csv'\n",
|
|
" np.savetxt(name, y_pred, delimiter=',')\n",
|
|
" # Plot the known data set and the predicted data set. The red box represents the region that was used\n",
|
|
" # for the training data.\n",
|
|
" fig, ax = plt.subplots()\n",
|
|
" ax.plot(x1, y_test, label=\"true\", linewidth=3)\n",
|
|
" ax.plot(x1, y_pred, 'g-.',label=\"predicted\", linewidth=4)\n",
|
|
" ax.legend()\n",
|
|
" # Created a red region to represent the points used in the training data.\n",
|
|
" ax.axvspan(plot_min, plot_max, alpha=0.25, color='red')\n",
|
|
" plt.show()\n",
|
|
"\n",
|
|
"# Check to make sure the data set is complete\n",
|
|
"assert len(X_tot) == len(y_tot)\n",
|
|
"\n",
|
|
"# This is the number of points that will be used in as the training data\n",
|
|
"dim=12\n",
|
|
"\n",
|
|
"# Separate the training data from the whole data set\n",
|
|
"X_train = X_tot[:dim]\n",
|
|
"y_train = y_tot[:dim]\n",
|
|
"\n",
|
|
"\n",
|
|
"# Generate the training data for the RNN, using a sequence of 2\n",
|
|
"rnn_input, rnn_training = format_data(y_train, 2)\n",
|
|
"\n",
|
|
"\n",
|
|
"# Create a recurrent neural network in Keras and produce a summary of the \n",
|
|
"# machine learning model\n",
|
|
"model = rnn(length_of_sequences = rnn_input.shape[1])\n",
|
|
"model.summary()\n",
|
|
"\n",
|
|
"# Start the timer. Want to time training+testing\n",
|
|
"start = timer()\n",
|
|
"# Fit the model using the training data genenerated above using 150 training iterations and a 5%\n",
|
|
"# validation split. Setting verbose to True prints information about each training iteration.\n",
|
|
"hist = model.fit(rnn_input, rnn_training, batch_size=None, epochs=150, \n",
|
|
" verbose=True,validation_split=0.05)\n",
|
|
"\n",
|
|
"for label in [\"loss\",\"val_loss\"]:\n",
|
|
" plt.plot(hist.history[label],label=label)\n",
|
|
"\n",
|
|
"plt.ylabel(\"loss\")\n",
|
|
"plt.xlabel(\"epoch\")\n",
|
|
"plt.title(\"The final validation loss: {}\".format(hist.history[\"val_loss\"][-1]))\n",
|
|
"plt.legend()\n",
|
|
"plt.show()\n",
|
|
"\n",
|
|
"# Use the trained neural network to predict more points of the data set\n",
|
|
"test_rnn(X_tot, y_tot, X_tot[0], X_tot[dim-1])\n",
|
|
"# Stop the timer and calculate the total time needed.\n",
|
|
"end = timer()\n",
|
|
"print('Time: ', end-start)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "e2cad4fc",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Changing the size of the recurrent neural network and its parameters\n",
|
|
"can drastically change the results you get from the model. The below\n",
|
|
"code takes the simple recurrent neural network from above and adds a\n",
|
|
"second hidden layer, changes the number of neurons in the hidden\n",
|
|
"layer, and explicitly declares the activation function of the hidden\n",
|
|
"layers to be a sigmoid function. The loss function and optimizer can\n",
|
|
"also be changed but are kept the same as the above network. These\n",
|
|
"parameters can be tuned to provide the optimal result from the\n",
|
|
"network. For some ideas on how to improve the performance of a\n",
|
|
"[recurrent neural network](https://danijar.com/tips-for-training-recurrent-neural-networks)."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"id": "c39f1516",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def rnn_2layers(length_of_sequences, batch_size = None, stateful = False):\n",
|
|
" \"\"\"\n",
|
|
" Inputs:\n",
|
|
" length_of_sequences (an int): the number of y values in \"x data\". This is determined\n",
|
|
" when the data is formatted\n",
|
|
" batch_size (an int): Default value is None. See Keras documentation of SimpleRNN.\n",
|
|
" stateful (a boolean): Default value is False. See Keras documentation of SimpleRNN.\n",
|
|
" Returns:\n",
|
|
" model (a Keras model): The recurrent neural network that is built and compiled by this\n",
|
|
" method\n",
|
|
" Builds and compiles a recurrent neural network with two hidden layers and returns the model.\n",
|
|
" \"\"\"\n",
|
|
" # Number of neurons in the input and output layers\n",
|
|
" in_out_neurons = 1\n",
|
|
" # Number of neurons in the hidden layer, increased from the first network\n",
|
|
" hidden_neurons = 500\n",
|
|
" # Define the input layer\n",
|
|
" inp = Input(batch_shape=(batch_size, \n",
|
|
" length_of_sequences, \n",
|
|
" in_out_neurons)) \n",
|
|
" # Create two hidden layers instead of one hidden layer. Explicitly set the activation\n",
|
|
" # function to be the sigmoid function (the default value is hyperbolic tangent)\n",
|
|
" rnn1 = SimpleRNN(hidden_neurons, \n",
|
|
" return_sequences=True, # This needs to be True if another hidden layer is to follow\n",
|
|
" stateful = stateful, activation = 'sigmoid',\n",
|
|
" name=\"RNN1\")(inp)\n",
|
|
" rnn2 = SimpleRNN(hidden_neurons, \n",
|
|
" return_sequences=False, activation = 'sigmoid',\n",
|
|
" stateful = stateful,\n",
|
|
" name=\"RNN2\")(rnn1)\n",
|
|
" # Define the output layer as a dense neural network layer (standard neural network layer)\n",
|
|
" #and add it to the network immediately after the hidden layer.\n",
|
|
" dens = Dense(in_out_neurons,name=\"dense\")(rnn2)\n",
|
|
" # Create the machine learning model starting with the input layer and ending with the \n",
|
|
" # output layer\n",
|
|
" model = Model(inputs=[inp],outputs=[dens])\n",
|
|
" # Compile the machine learning model using the mean squared error function as the loss \n",
|
|
" # function and an Adams optimizer.\n",
|
|
" model.compile(loss=\"mean_squared_error\", optimizer=\"adam\") \n",
|
|
" return model\n",
|
|
"\n",
|
|
"# Check to make sure the data set is complete\n",
|
|
"assert len(X_tot) == len(y_tot)\n",
|
|
"\n",
|
|
"# This is the number of points that will be used in as the training data\n",
|
|
"dim=12\n",
|
|
"\n",
|
|
"# Separate the training data from the whole data set\n",
|
|
"X_train = X_tot[:dim]\n",
|
|
"y_train = y_tot[:dim]\n",
|
|
"\n",
|
|
"\n",
|
|
"# Generate the training data for the RNN, using a sequence of 2\n",
|
|
"rnn_input, rnn_training = format_data(y_train, 2)\n",
|
|
"\n",
|
|
"\n",
|
|
"# Create a recurrent neural network in Keras and produce a summary of the \n",
|
|
"# machine learning model\n",
|
|
"model = rnn_2layers(length_of_sequences = 2)\n",
|
|
"model.summary()\n",
|
|
"\n",
|
|
"# Start the timer. Want to time training+testing\n",
|
|
"start = timer()\n",
|
|
"# Fit the model using the training data genenerated above using 150 training iterations and a 5%\n",
|
|
"# validation split. Setting verbose to True prints information about each training iteration.\n",
|
|
"hist = model.fit(rnn_input, rnn_training, batch_size=None, epochs=150, \n",
|
|
" verbose=True,validation_split=0.05)\n",
|
|
"\n",
|
|
"\n",
|
|
"# This section plots the training loss and the validation loss as a function of training iteration.\n",
|
|
"# This is not required for analyzing the couple cluster data but can help determine if the network is\n",
|
|
"# being overtrained.\n",
|
|
"for label in [\"loss\",\"val_loss\"]:\n",
|
|
" plt.plot(hist.history[label],label=label)\n",
|
|
"\n",
|
|
"plt.ylabel(\"loss\")\n",
|
|
"plt.xlabel(\"epoch\")\n",
|
|
"plt.title(\"The final validation loss: {}\".format(hist.history[\"val_loss\"][-1]))\n",
|
|
"plt.legend()\n",
|
|
"plt.show()\n",
|
|
"\n",
|
|
"# Use the trained neural network to predict more points of the data set\n",
|
|
"test_rnn(X_tot, y_tot, X_tot[0], X_tot[dim-1])\n",
|
|
"# Stop the timer and calculate the total time needed.\n",
|
|
"end = timer()\n",
|
|
"print('Time: ', end-start)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "842c7602",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## Other Types of Recurrent Neural Networks\n",
|
|
"\n",
|
|
"Besides a simple recurrent neural network layer, there are two other\n",
|
|
"commonly used types of recurrent neural network layers: Long Short\n",
|
|
"Term Memory (LSTM) and Gated Recurrent Unit (GRU). For a short\n",
|
|
"introduction to these layers see <https://medium.com/mindboard/lstm-vs-gru-experimental-comparison-955820c21e8b>\n",
|
|
"and <https://medium.com/mindboard/lstm-vs-gru-experimental-comparison-955820c21e8b>.\n",
|
|
"\n",
|
|
"The first network created below is similar to the previous network,\n",
|
|
"but it replaces the SimpleRNN layers with LSTM layers. The second\n",
|
|
"network below has two hidden layers made up of GRUs, which are\n",
|
|
"preceeded by two dense (feeddorward) neural network layers. These\n",
|
|
"dense layers \"preprocess\" the data before it reaches the recurrent\n",
|
|
"layers. This architecture has been shown to improve the performance\n",
|
|
"of recurrent neural networks (see the link above and also\n",
|
|
"<https://arxiv.org/pdf/1807.02857.pdf>."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"id": "6f0e9b62",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def lstm_2layers(length_of_sequences, batch_size = None, stateful = False):\n",
|
|
" \"\"\"\n",
|
|
" Inputs:\n",
|
|
" length_of_sequences (an int): the number of y values in \"x data\". This is determined\n",
|
|
" when the data is formatted\n",
|
|
" batch_size (an int): Default value is None. See Keras documentation of SimpleRNN.\n",
|
|
" stateful (a boolean): Default value is False. See Keras documentation of SimpleRNN.\n",
|
|
" Returns:\n",
|
|
" model (a Keras model): The recurrent neural network that is built and compiled by this\n",
|
|
" method\n",
|
|
" Builds and compiles a recurrent neural network with two LSTM hidden layers and returns the model.\n",
|
|
" \"\"\"\n",
|
|
" # Number of neurons on the input/output layer and the number of neurons in the hidden layer\n",
|
|
" in_out_neurons = 1\n",
|
|
" hidden_neurons = 250\n",
|
|
" # Input Layer\n",
|
|
" inp = Input(batch_shape=(batch_size, \n",
|
|
" length_of_sequences, \n",
|
|
" in_out_neurons)) \n",
|
|
" # Hidden layers (in this case they are LSTM layers instead if SimpleRNN layers)\n",
|
|
" rnn= LSTM(hidden_neurons, \n",
|
|
" return_sequences=True,\n",
|
|
" stateful = stateful,\n",
|
|
" name=\"RNN\", use_bias=True, activation='tanh')(inp)\n",
|
|
" rnn1 = LSTM(hidden_neurons, \n",
|
|
" return_sequences=False,\n",
|
|
" stateful = stateful,\n",
|
|
" name=\"RNN1\", use_bias=True, activation='tanh')(rnn)\n",
|
|
" # Output layer\n",
|
|
" dens = Dense(in_out_neurons,name=\"dense\")(rnn1)\n",
|
|
" # Define the midel\n",
|
|
" model = Model(inputs=[inp],outputs=[dens])\n",
|
|
" # Compile the model\n",
|
|
" model.compile(loss='mean_squared_error', optimizer='adam') \n",
|
|
" # Return the model\n",
|
|
" return model\n",
|
|
"\n",
|
|
"def dnn2_gru2(length_of_sequences, batch_size = None, stateful = False):\n",
|
|
" \"\"\"\n",
|
|
" Inputs:\n",
|
|
" length_of_sequences (an int): the number of y values in \"x data\". This is determined\n",
|
|
" when the data is formatted\n",
|
|
" batch_size (an int): Default value is None. See Keras documentation of SimpleRNN.\n",
|
|
" stateful (a boolean): Default value is False. See Keras documentation of SimpleRNN.\n",
|
|
" Returns:\n",
|
|
" model (a Keras model): The recurrent neural network that is built and compiled by this\n",
|
|
" method\n",
|
|
" Builds and compiles a recurrent neural network with four hidden layers (two dense followed by\n",
|
|
" two GRU layers) and returns the model.\n",
|
|
" \"\"\" \n",
|
|
" # Number of neurons on the input/output layers and hidden layers\n",
|
|
" in_out_neurons = 1\n",
|
|
" hidden_neurons = 250\n",
|
|
" # Input layer\n",
|
|
" inp = Input(batch_shape=(batch_size, \n",
|
|
" length_of_sequences, \n",
|
|
" in_out_neurons)) \n",
|
|
" # Hidden Dense (feedforward) layers\n",
|
|
" dnn = Dense(hidden_neurons/2, activation='relu', name='dnn')(inp)\n",
|
|
" dnn1 = Dense(hidden_neurons/2, activation='relu', name='dnn1')(dnn)\n",
|
|
" # Hidden GRU layers\n",
|
|
" rnn1 = GRU(hidden_neurons, \n",
|
|
" return_sequences=True,\n",
|
|
" stateful = stateful,\n",
|
|
" name=\"RNN1\", use_bias=True)(dnn1)\n",
|
|
" rnn = GRU(hidden_neurons, \n",
|
|
" return_sequences=False,\n",
|
|
" stateful = stateful,\n",
|
|
" name=\"RNN\", use_bias=True)(rnn1)\n",
|
|
" # Output layer\n",
|
|
" dens = Dense(in_out_neurons,name=\"dense\")(rnn)\n",
|
|
" # Define the model\n",
|
|
" model = Model(inputs=[inp],outputs=[dens])\n",
|
|
" # Compile the mdoel\n",
|
|
" model.compile(loss='mean_squared_error', optimizer='adam') \n",
|
|
" # Return the model\n",
|
|
" return model\n",
|
|
"\n",
|
|
"# Check to make sure the data set is complete\n",
|
|
"assert len(X_tot) == len(y_tot)\n",
|
|
"\n",
|
|
"# This is the number of points that will be used in as the training data\n",
|
|
"dim=12\n",
|
|
"\n",
|
|
"# Separate the training data from the whole data set\n",
|
|
"X_train = X_tot[:dim]\n",
|
|
"y_train = y_tot[:dim]\n",
|
|
"\n",
|
|
"\n",
|
|
"# Generate the training data for the RNN, using a sequence of 2\n",
|
|
"rnn_input, rnn_training = format_data(y_train, 2)\n",
|
|
"\n",
|
|
"\n",
|
|
"# Create a recurrent neural network in Keras and produce a summary of the \n",
|
|
"# machine learning model\n",
|
|
"# Change the method name to reflect which network you want to use\n",
|
|
"model = dnn2_gru2(length_of_sequences = 2)\n",
|
|
"model.summary()\n",
|
|
"\n",
|
|
"# Start the timer. Want to time training+testing\n",
|
|
"start = timer()\n",
|
|
"# Fit the model using the training data genenerated above using 150 training iterations and a 5%\n",
|
|
"# validation split. Setting verbose to True prints information about each training iteration.\n",
|
|
"hist = model.fit(rnn_input, rnn_training, batch_size=None, epochs=150, \n",
|
|
" verbose=True,validation_split=0.05)\n",
|
|
"\n",
|
|
"\n",
|
|
"# This section plots the training loss and the validation loss as a function of training iteration.\n",
|
|
"# This is not required for analyzing the couple cluster data but can help determine if the network is\n",
|
|
"# being overtrained.\n",
|
|
"for label in [\"loss\",\"val_loss\"]:\n",
|
|
" plt.plot(hist.history[label],label=label)\n",
|
|
"\n",
|
|
"plt.ylabel(\"loss\")\n",
|
|
"plt.xlabel(\"epoch\")\n",
|
|
"plt.title(\"The final validation loss: {}\".format(hist.history[\"val_loss\"][-1]))\n",
|
|
"plt.legend()\n",
|
|
"plt.show()\n",
|
|
"\n",
|
|
"# Use the trained neural network to predict more points of the data set\n",
|
|
"test_rnn(X_tot, y_tot, X_tot[0], X_tot[dim-1])\n",
|
|
"# Stop the timer and calculate the total time needed.\n",
|
|
"end = timer()\n",
|
|
"print('Time: ', end-start)\n",
|
|
"\n",
|
|
"\n",
|
|
"# ### Training Recurrent Neural Networks in the Standard Way (i.e. learning the relationship between the X and Y data)\n",
|
|
"# \n",
|
|
"# Finally, comparing the performace of a recurrent neural network using the standard data formatting to the performance of the network with time sequence data formatting shows the benefit of this type of data formatting with extrapolation.\n",
|
|
"\n",
|
|
"# Check to make sure the data set is complete\n",
|
|
"assert len(X_tot) == len(y_tot)\n",
|
|
"\n",
|
|
"# This is the number of points that will be used in as the training data\n",
|
|
"dim=12\n",
|
|
"\n",
|
|
"# Separate the training data from the whole data set\n",
|
|
"X_train = X_tot[:dim]\n",
|
|
"y_train = y_tot[:dim]\n",
|
|
"\n",
|
|
"# Reshape the data for Keras specifications\n",
|
|
"X_train = X_train.reshape((dim, 1))\n",
|
|
"y_train = y_train.reshape((dim, 1))\n",
|
|
"\n",
|
|
"\n",
|
|
"# Create a recurrent neural network in Keras and produce a summary of the \n",
|
|
"# machine learning model\n",
|
|
"# Set the sequence length to 1 for regular data formatting \n",
|
|
"model = rnn(length_of_sequences = 1)\n",
|
|
"model.summary()\n",
|
|
"\n",
|
|
"# Start the timer. Want to time training+testing\n",
|
|
"start = timer()\n",
|
|
"# Fit the model using the training data genenerated above using 150 training iterations and a 5%\n",
|
|
"# validation split. Setting verbose to True prints information about each training iteration.\n",
|
|
"hist = model.fit(X_train, y_train, batch_size=None, epochs=150, \n",
|
|
" verbose=True,validation_split=0.05)\n",
|
|
"\n",
|
|
"\n",
|
|
"# This section plots the training loss and the validation loss as a function of training iteration.\n",
|
|
"# This is not required for analyzing the couple cluster data but can help determine if the network is\n",
|
|
"# being overtrained.\n",
|
|
"for label in [\"loss\",\"val_loss\"]:\n",
|
|
" plt.plot(hist.history[label],label=label)\n",
|
|
"\n",
|
|
"plt.ylabel(\"loss\")\n",
|
|
"plt.xlabel(\"epoch\")\n",
|
|
"plt.title(\"The final validation loss: {}\".format(hist.history[\"val_loss\"][-1]))\n",
|
|
"plt.legend()\n",
|
|
"plt.show()\n",
|
|
"\n",
|
|
"# Use the trained neural network to predict the remaining data points\n",
|
|
"X_pred = X_tot[dim:]\n",
|
|
"X_pred = X_pred.reshape((len(X_pred), 1))\n",
|
|
"y_model = model.predict(X_pred)\n",
|
|
"y_pred = np.concatenate((y_tot[:dim], y_model.flatten()))\n",
|
|
"\n",
|
|
"# Plot the known data set and the predicted data set. The red box represents the region that was used\n",
|
|
"# for the training data.\n",
|
|
"fig, ax = plt.subplots()\n",
|
|
"ax.plot(X_tot, y_tot, label=\"true\", linewidth=3)\n",
|
|
"ax.plot(X_tot, y_pred, 'g-.',label=\"predicted\", linewidth=4)\n",
|
|
"ax.legend()\n",
|
|
"# Created a red region to represent the points used in the training data.\n",
|
|
"ax.axvspan(X_tot[0], X_tot[dim], alpha=0.25, color='red')\n",
|
|
"plt.show()\n",
|
|
"\n",
|
|
"# Stop the timer and calculate the total time needed.\n",
|
|
"end = timer()\n",
|
|
"print('Time: ', end-start)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "0752ba7f",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"# Generative Models\n",
|
|
"\n",
|
|
"**Generative models** describe a class of statistical models that are a contrast\n",
|
|
"to **discriminative models**. Informally we say that generative models can\n",
|
|
"generate new data instances while discriminative models discriminate between\n",
|
|
"different kinds of data instances. A generative model could generate new photos\n",
|
|
"of animals that look like 'real' animals while a discriminative model could tell\n",
|
|
"a dog from a cat. More formally, given a data set $x$ and a set of labels /\n",
|
|
"targets $y$. Generative models capture the joint probability $p(x, y)$, or\n",
|
|
"just $p(x)$ if there are no labels, while discriminative models capture the\n",
|
|
"conditional probability $p(y | x)$. Discriminative models generally try to draw\n",
|
|
"boundaries in the data space (often high dimensional), while generative models\n",
|
|
"try to model how data is placed throughout the space.\n",
|
|
"\n",
|
|
"**Note**: this material is thanks to Linus Ekstrøm."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "784138f8",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## Generative Adversarial Networks\n",
|
|
"\n",
|
|
"**Generative Adversarial Networks** are a type of unsupervised machine learning\n",
|
|
"algorithm proposed by [Goodfellow et. al](https://arxiv.org/pdf/1406.2661.pdf)\n",
|
|
"in 2014 (short and good article).\n",
|
|
"\n",
|
|
"The simplest formulation of\n",
|
|
"the model is based on a game theoretic approach, *zero sum game*, where we pit\n",
|
|
"two neural networks against one another. We define two rival networks, one\n",
|
|
"generator $g$, and one discriminator $d$. The generator directly produces\n",
|
|
"samples"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "a42f89ee",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"<!-- Equation labels as ordinary links -->\n",
|
|
"<div id=\"_auto1\"></div>\n",
|
|
"\n",
|
|
"$$\n",
|
|
"\\begin{equation}\n",
|
|
" x = g(z; \\theta^{(g)})\n",
|
|
"\\label{_auto1} \\tag{1}\n",
|
|
"\\end{equation}\n",
|
|
"$$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "abe7212f",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"The discriminator attempts to distinguish between samples drawn from the\n",
|
|
"training data and samples drawn from the generator. In other words, it tries to\n",
|
|
"tell the difference between the fake data produced by $g$ and the actual data\n",
|
|
"samples we want to do prediction on. The discriminator outputs a probability\n",
|
|
"value given by"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "0821eaee",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"<!-- Equation labels as ordinary links -->\n",
|
|
"<div id=\"_auto2\"></div>\n",
|
|
"\n",
|
|
"$$\n",
|
|
"\\begin{equation}\n",
|
|
" d(x; \\theta^{(d)})\n",
|
|
"\\label{_auto2} \\tag{2}\n",
|
|
"\\end{equation}\n",
|
|
"$$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "55e0ccf6",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"indicating the probability that $x$ is a real training example rather than a\n",
|
|
"fake sample the generator has generated. The simplest way to formulate the\n",
|
|
"learning process in a generative adversarial network is a zero-sum game, in\n",
|
|
"which a function"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "f37ece14",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"<!-- Equation labels as ordinary links -->\n",
|
|
"<div id=\"_auto3\"></div>\n",
|
|
"\n",
|
|
"$$\n",
|
|
"\\begin{equation}\n",
|
|
" v(\\theta^{(g)}, \\theta^{(d)})\n",
|
|
"\\label{_auto3} \\tag{3}\n",
|
|
"\\end{equation}\n",
|
|
"$$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "d6d6d5fa",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"determines the reward for the discriminator, while the generator gets the\n",
|
|
"conjugate reward"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "3c74b45c",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"<!-- Equation labels as ordinary links -->\n",
|
|
"<div id=\"_auto4\"></div>\n",
|
|
"\n",
|
|
"$$\n",
|
|
"\\begin{equation}\n",
|
|
" -v(\\theta^{(g)}, \\theta^{(d)})\n",
|
|
"\\label{_auto4} \\tag{4}\n",
|
|
"\\end{equation}\n",
|
|
"$$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "605ac8c9",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"During learning both of the networks maximize their own reward function, so that\n",
|
|
"the generator gets better and better at tricking the discriminator, while the\n",
|
|
"discriminator gets better and better at telling the difference between the fake\n",
|
|
"and real data. The generator and discriminator alternate on which one trains at\n",
|
|
"one time (i.e. for one epoch). In other words, we keep the generator constant\n",
|
|
"and train the discriminator, then we keep the discriminator constant to train\n",
|
|
"the generator and repeat. It is this back and forth dynamic which lets GANs\n",
|
|
"tackle otherwise intractable generative problems. As the generator improves with\n",
|
|
" training, the discriminator's performance gets worse because it cannot easily\n",
|
|
" tell the difference between real and fake. If the generator ends up succeeding\n",
|
|
" perfectly, the the discriminator will do no better than random guessing i.e.\n",
|
|
" 50\\%. This progression in the training poses a problem for the convergence\n",
|
|
" criteria for GANs. The discriminator feedback gets less meaningful over time,\n",
|
|
" if we continue training after this point then the generator is effectively\n",
|
|
" training on junk data which can undo the learning up to that point. Therefore,\n",
|
|
" we stop training when the discriminator starts outputting $1/2$ everywhere.\n",
|
|
"\n",
|
|
"At convergence we have"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "cfec7462",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"<!-- Equation labels as ordinary links -->\n",
|
|
"<div id=\"_auto5\"></div>\n",
|
|
"\n",
|
|
"$$\n",
|
|
"\\begin{equation}\n",
|
|
" g^* = \\underset{g}{\\mathrm{argmin}}\\hspace{2pt}\n",
|
|
" \\underset{d}{\\mathrm{max}}v(\\theta^{(g)}, \\theta^{(d)})\n",
|
|
"\\label{_auto5} \\tag{5}\n",
|
|
"\\end{equation}\n",
|
|
"$$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "37c65d4c",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"The default choice for $v$ is"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "c868a092",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"<!-- Equation labels as ordinary links -->\n",
|
|
"<div id=\"_auto6\"></div>\n",
|
|
"\n",
|
|
"$$\n",
|
|
"\\begin{equation}\n",
|
|
" v(\\theta^{(g)}, \\theta^{(d)}) = \\mathbb{E}_{x\\sim p_\\mathrm{data}}\\log d(x)\n",
|
|
" + \\mathbb{E}_{x\\sim p_\\mathrm{model}}\n",
|
|
" \\log (1 - d(x))\n",
|
|
"\\label{_auto6} \\tag{6}\n",
|
|
"\\end{equation}\n",
|
|
"$$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "ad465af3",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"The main motivation for the design of GANs is that the learning process requires\n",
|
|
"neither approximate inference (variational autoencoders for example) nor\n",
|
|
"approximation of a partition function. In the case where"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "27858a4e",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"<!-- Equation labels as ordinary links -->\n",
|
|
"<div id=\"_auto7\"></div>\n",
|
|
"\n",
|
|
"$$\n",
|
|
"\\begin{equation}\n",
|
|
" \\underset{d}{\\mathrm{max}}v(\\theta^{(g)}, \\theta^{(d)})\n",
|
|
"\\label{_auto7} \\tag{7}\n",
|
|
"\\end{equation}\n",
|
|
"$$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "86006023",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"is convex in $\\theta^{(g)} then the procedure is guaranteed to converge and is\n",
|
|
"asymptotically consistent\n",
|
|
"( [Seth Lloyd on QuGANs](https://arxiv.org/pdf/1804.09139.pdf) ).\n",
|
|
"\n",
|
|
"This is in\n",
|
|
"general not the case and it is possible to get situations where the training\n",
|
|
"process never converges because the generator and discriminator chase one\n",
|
|
"another around in the parameter space indefinitely. A much deeper discussion on\n",
|
|
"the currently open research problem of GAN convergence is available\n",
|
|
"[here](https://www.deeplearningbook.org/contents/generative_models.html). To\n",
|
|
"anyone interested in learning more about GANs it is a highly recommended read.\n",
|
|
"Direct quote: \"In this best-performing formulation, the generator aims to\n",
|
|
"increase the log probability that the discriminator makes a mistake, rather than\n",
|
|
"aiming to decrease the log probability that the discriminator makes the correct\n",
|
|
"prediction.\" [Another interesting read](https://arxiv.org/abs/1701.00160)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "2fee38bd",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## Writing Our First Generative Adversarial Network\n",
|
|
"Let us now move on to actually implementing a GAN in tensorflow. We will study\n",
|
|
"the performance of our GAN on the MNIST dataset. This code is based on and\n",
|
|
"adapted from the\n",
|
|
"[google tutorial](https://www.tensorflow.org/tutorials/generative/dcgan)\n",
|
|
"\n",
|
|
"First we import our libraries"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"id": "004a0b53",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"import os\n",
|
|
"import time\n",
|
|
"import numpy as np\n",
|
|
"import tensorflow as tf\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"from tensorflow.keras import layers\n",
|
|
"from tensorflow.keras.utils import plot_model"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "353af161",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Next we define our hyperparameters and import our data the usual way"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"id": "8cbaf16a",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"BUFFER_SIZE = 60000\n",
|
|
"BATCH_SIZE = 256\n",
|
|
"EPOCHS = 30\n",
|
|
"\n",
|
|
"data = tf.keras.datasets.mnist.load_data()\n",
|
|
"(train_images, train_labels), (test_images, test_labels) = data\n",
|
|
"train_images = np.reshape(train_images, (train_images.shape[0],\n",
|
|
" 28,\n",
|
|
" 28,\n",
|
|
" 1)).astype('float32')\n",
|
|
"\n",
|
|
"# we normalize between -1 and 1\n",
|
|
"train_images = (train_images - 127.5) / 127.5\n",
|
|
"training_dataset = tf.data.Dataset.from_tensor_slices(\n",
|
|
" train_images).shuffle(BUFFER_SIZE).batch(BATCH_SIZE)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "822b8cc7",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"### MNIST and GANs\n",
|
|
"\n",
|
|
"Let's have a quick look"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 9,
|
|
"id": "52b5965c",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"plt.imshow(train_images[0], cmap='Greys')\n",
|
|
"plt.show()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "21c5199c",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Now we define our two models. This is where the 'magic' happens. There are a\n",
|
|
"huge amount of possible formulations for both models. A lot of engineering and\n",
|
|
"trial and error can be done here to try to produce better performing models. For\n",
|
|
"more advanced GANs this is by far the step where you can 'make or break' a\n",
|
|
"model.\n",
|
|
"\n",
|
|
"We start with the generator. As stated in the introductory text the generator\n",
|
|
"$g$ upsamples from a random sample to the shape of what we want to predict. In\n",
|
|
"our case we are trying to predict MNIST images ($28\\times 28$ pixels)."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 10,
|
|
"id": "356759c7",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def generator_model():\n",
|
|
" \"\"\"\n",
|
|
" The generator uses upsampling layers tf.keras.layers.Conv2DTranspose() to\n",
|
|
" produce an image from a random seed. We start with a Dense layer taking this\n",
|
|
" random sample as an input and subsequently upsample through multiple\n",
|
|
" convolutional layers.\n",
|
|
" \"\"\"\n",
|
|
"\n",
|
|
" # we define our model\n",
|
|
" model = tf.keras.Sequential()\n",
|
|
"\n",
|
|
"\n",
|
|
" # adding our input layer. Dense means that every neuron is connected and\n",
|
|
" # the input shape is the shape of our random noise. The units need to match\n",
|
|
" # in some sense the upsampling strides to reach our desired output shape.\n",
|
|
" # we are using 100 random numbers as our seed\n",
|
|
" model.add(layers.Dense(units=7*7*BATCH_SIZE,\n",
|
|
" use_bias=False,\n",
|
|
" input_shape=(100, )))\n",
|
|
" # we normalize the output form the Dense layer\n",
|
|
" model.add(layers.BatchNormalization())\n",
|
|
" # and add an activation function to our 'layer'. LeakyReLU avoids vanishing\n",
|
|
" # gradient problem\n",
|
|
" model.add(layers.LeakyReLU())\n",
|
|
" model.add(layers.Reshape((7, 7, BATCH_SIZE)))\n",
|
|
" assert model.output_shape == (None, 7, 7, BATCH_SIZE)\n",
|
|
" # even though we just added four keras layers we think of everything above\n",
|
|
" # as 'one' layer\n",
|
|
"\n",
|
|
" # next we add our upscaling convolutional layers\n",
|
|
" model.add(layers.Conv2DTranspose(filters=128,\n",
|
|
" kernel_size=(5, 5),\n",
|
|
" strides=(1, 1),\n",
|
|
" padding='same',\n",
|
|
" use_bias=False))\n",
|
|
" model.add(layers.BatchNormalization())\n",
|
|
" model.add(layers.LeakyReLU())\n",
|
|
" assert model.output_shape == (None, 7, 7, 128)\n",
|
|
"\n",
|
|
" model.add(layers.Conv2DTranspose(filters=64,\n",
|
|
" kernel_size=(5, 5),\n",
|
|
" strides=(2, 2),\n",
|
|
" padding='same',\n",
|
|
" use_bias=False))\n",
|
|
" model.add(layers.BatchNormalization())\n",
|
|
" model.add(layers.LeakyReLU())\n",
|
|
" assert model.output_shape == (None, 14, 14, 64)\n",
|
|
"\n",
|
|
" model.add(layers.Conv2DTranspose(filters=1,\n",
|
|
" kernel_size=(5, 5),\n",
|
|
" strides=(2, 2),\n",
|
|
" padding='same',\n",
|
|
" use_bias=False,\n",
|
|
" activation='tanh'))\n",
|
|
" assert model.output_shape == (None, 28, 28, 1)\n",
|
|
"\n",
|
|
" return model"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "854bcd6b",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"And there we have our 'simple' generator model. Now we move on to defining our\n",
|
|
"discriminator model $d$, which is a convolutional neural network based image\n",
|
|
"classifier."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 11,
|
|
"id": "41473304",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def discriminator_model():\n",
|
|
" \"\"\"\n",
|
|
" The discriminator is a convolutional neural network based image classifier\n",
|
|
" \"\"\"\n",
|
|
"\n",
|
|
" # we define our model\n",
|
|
" model = tf.keras.Sequential()\n",
|
|
" model.add(layers.Conv2D(filters=64,\n",
|
|
" kernel_size=(5, 5),\n",
|
|
" strides=(2, 2),\n",
|
|
" padding='same',\n",
|
|
" input_shape=[28, 28, 1]))\n",
|
|
" model.add(layers.LeakyReLU())\n",
|
|
" # adding a dropout layer as you do in conv-nets\n",
|
|
" model.add(layers.Dropout(0.3))\n",
|
|
"\n",
|
|
"\n",
|
|
" model.add(layers.Conv2D(filters=128,\n",
|
|
" kernel_size=(5, 5),\n",
|
|
" strides=(2, 2),\n",
|
|
" padding='same'))\n",
|
|
" model.add(layers.LeakyReLU())\n",
|
|
" # adding a dropout layer as you do in conv-nets\n",
|
|
" model.add(layers.Dropout(0.3))\n",
|
|
"\n",
|
|
" model.add(layers.Flatten())\n",
|
|
" model.add(layers.Dense(1))\n",
|
|
"\n",
|
|
" return model"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "353af567",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Let us take a look at our models."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 12,
|
|
"id": "f899d4e3",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"generator = generator_model()\n",
|
|
"plot_model(generator, show_shapes=True, rankdir='LR')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 13,
|
|
"id": "87ef384b",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"discriminator = discriminator_model()\n",
|
|
"plot_model(discriminator, show_shapes=True, rankdir='LR')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "b2bef82d",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Next we need a few helper objects we will use in training"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 14,
|
|
"id": "e397847a",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"cross_entropy = tf.keras.losses.BinaryCrossentropy(from_logits=True)\n",
|
|
"generator_optimizer = tf.keras.optimizers.Adam(1e-4)\n",
|
|
"discriminator_optimizer = tf.keras.optimizers.Adam(1e-4)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "db3396cc",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"The first object, *cross_entropy* is our loss function and the two others are\n",
|
|
"our optimizers. Notice we use the same learning rate for both $g$ and $d$. This\n",
|
|
"is because they need to improve their accuracy at approximately equal speeds to\n",
|
|
"get convergence (not necessarily exactly equal). Now we define our loss\n",
|
|
"functions"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 15,
|
|
"id": "931eaced",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def generator_loss(fake_output):\n",
|
|
" loss = cross_entropy(tf.ones_like(fake_output), fake_output)\n",
|
|
"\n",
|
|
" return loss"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 16,
|
|
"id": "0c4a44bb",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def discriminator_loss(real_output, fake_output):\n",
|
|
" real_loss = cross_entropy(tf.ones_like(real_output), real_output)\n",
|
|
" fake_loss = cross_entropy(tf.zeros_liks(fake_output), fake_output)\n",
|
|
" total_loss = real_loss + fake_loss\n",
|
|
"\n",
|
|
" return total_loss"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "fcf8f066",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Next we define a kind of seed to help us compare the learning process over\n",
|
|
"multiple training epochs."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 17,
|
|
"id": "eea2bbee",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"noise_dimension = 100\n",
|
|
"n_examples_to_generate = 16\n",
|
|
"seed_images = tf.random.normal([n_examples_to_generate, noise_dimension])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "94a6e341",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Now we have everything we need to define our training step, which we will apply\n",
|
|
"for every step in our training loop. Notice the @tf.function flag signifying\n",
|
|
"that the function is tensorflow 'compiled'. Removing this flag doubles the\n",
|
|
"computation time."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 18,
|
|
"id": "8d48470b",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"@tf.function\n",
|
|
"def train_step(images):\n",
|
|
" noise = tf.random.normal([BATCH_SIZE, noise_dimension])\n",
|
|
"\n",
|
|
" with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:\n",
|
|
" generated_images = generator(noise, training=True)\n",
|
|
"\n",
|
|
" real_output = discriminator(images, training=True)\n",
|
|
" fake_output = discriminator(generated_images, training=True)\n",
|
|
"\n",
|
|
" gen_loss = generator_loss(fake_output)\n",
|
|
" disc_loss = discriminator_loss(real_output, fake_output)\n",
|
|
"\n",
|
|
" gradients_of_generator = gen_tape.gradient(gen_loss,\n",
|
|
" generator.trainable_variables)\n",
|
|
" gradients_of_discriminator = disc_tape.gradient(disc_loss,\n",
|
|
" discriminator.trainable_variables)\n",
|
|
" generator_optimizer.apply_gradients(zip(gradients_of_generator,\n",
|
|
" generator.trainable_variables))\n",
|
|
" discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator,\n",
|
|
" discriminator.trainable_variables))\n",
|
|
"\n",
|
|
" return gen_loss, disc_loss"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "62015b88",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Next we define a helper function to produce an output over our training epochs\n",
|
|
"to see the predictive progression of our generator model. **Note**: I am including\n",
|
|
"this code here, but comment it out in the training loop."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 19,
|
|
"id": "b189ed96",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def generate_and_save_images(model, epoch, test_input):\n",
|
|
" # we're making inferences here\n",
|
|
" predictions = model(test_input, training=False)\n",
|
|
"\n",
|
|
" fig = plt.figure(figsize=(4, 4))\n",
|
|
"\n",
|
|
" for i in range(predictions.shape[0]):\n",
|
|
" plt.subplot(4, 4, i+1)\n",
|
|
" plt.imshow(predictions[i, :, :, 0] * 127.5 + 127.5, cmap='gray')\n",
|
|
" plt.axis('off')\n",
|
|
"\n",
|
|
" plt.savefig(f'./images_from_seed_images/image_at_epoch_{str(epoch).zfill(3)}.png')\n",
|
|
" plt.close()\n",
|
|
" #plt.show()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "ba2c82d5",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Setting up checkpoints to periodically save our model during training so that\n",
|
|
"everything is not lost even if the program were to somehow terminate while\n",
|
|
"training."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 20,
|
|
"id": "a0e2fc8a",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Setting up checkpoints to save model during training\n",
|
|
"checkpoint_dir = './training_checkpoints'\n",
|
|
"checkpoint_prefix = os.path.join(checkpoint_dir, 'ckpt')\n",
|
|
"checkpoint = tf.train.Checkpoint(generator_optimizer=generator_optimizer,\n",
|
|
" discriminator_optimizer=discriminator_optimizer,\n",
|
|
" generator=generator,\n",
|
|
" discriminator=discriminator)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "4d93a0f7",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Now we define our training loop"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 21,
|
|
"id": "a1275556",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def train(dataset, epochs):\n",
|
|
" generator_loss_list = []\n",
|
|
" discriminator_loss_list = []\n",
|
|
"\n",
|
|
" for epoch in range(epochs):\n",
|
|
" start = time.time()\n",
|
|
"\n",
|
|
" for image_batch in dataset:\n",
|
|
" gen_loss, disc_loss = train_step(image_batch)\n",
|
|
" generator_loss_list.append(gen_loss.numpy())\n",
|
|
" discriminator_loss_list.append(disc_loss.numpy())\n",
|
|
"\n",
|
|
" #generate_and_save_images(generator, epoch + 1, seed_images)\n",
|
|
"\n",
|
|
" if (epoch + 1) % 15 == 0:\n",
|
|
" checkpoint.save(file_prefix=checkpoint_prefix)\n",
|
|
"\n",
|
|
" print(f'Time for epoch {epoch} is {time.time() - start}')\n",
|
|
"\n",
|
|
" #generate_and_save_images(generator, epochs, seed_images)\n",
|
|
"\n",
|
|
" loss_file = './data/lossfile.txt'\n",
|
|
" with open(loss_file, 'w') as outfile:\n",
|
|
" outfile.write(str(generator_loss_list))\n",
|
|
" outfile.write('\\n')\n",
|
|
" outfile.write('\\n')\n",
|
|
" outfile.write(str(discriminator_loss_list))\n",
|
|
" outfile.write('\\n')\n",
|
|
" outfile.write('\\n')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "6ff3a75a",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"To train simply call this function. **Warning**: this might take a long time so\n",
|
|
"there is a folder of a pretrained network already included in the repository."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 22,
|
|
"id": "371ed41a",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"train(train_dataset, EPOCHS)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "654399f1",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Now to avoid having to train and everything, which will take a while depending\n",
|
|
"on your computer setup we now load in the model which produced the above gif."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 23,
|
|
"id": "dec4b560",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"checkpoint.restore(tf.train.latest_checkpoint(checkpoint_dir))\n",
|
|
"restored_generator = checkpoint.generator\n",
|
|
"restored_discriminator = checkpoint.discriminator\n",
|
|
"\n",
|
|
"print(restored_generator)\n",
|
|
"print(restored_discriminator)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "296bfa5c",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"We have successfully loaded in our latest model. Let us now play around a bit\n",
|
|
"and see what kind of things we can learn about this model. Our generator takes\n",
|
|
"an array of 100 numbers. One idea can be to try to systematically change our\n",
|
|
"input. Let us try and see what we get"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 24,
|
|
"id": "eecfbb1f",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def generate_latent_points(number=100, scale_means=1, scale_stds=1):\n",
|
|
" latent_dim = 100\n",
|
|
" means = scale_means * tf.linspace(-1, 1, num=latent_dim)\n",
|
|
" stds = scale_stds * tf.linspace(-1, 1, num=latent_dim)\n",
|
|
" latent_space_value_range = tf.random.normal([number, latent_dim],\n",
|
|
" means,\n",
|
|
" stds,\n",
|
|
" dtype=tf.float64)\n",
|
|
"\n",
|
|
" return latent_space_value_range\n",
|
|
"\n",
|
|
"def generate_images(latent_points):\n",
|
|
" # notice we set training to false because we are making inferences\n",
|
|
" generated_images = restored_generator.predict(latent_points)\n",
|
|
"\n",
|
|
" return generated_images"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 25,
|
|
"id": "333a593d",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def plot_result(generated_images, number=100):\n",
|
|
" # obviously this assumes sqrt number is an int\n",
|
|
" fig, axs = plt.subplots(int(np.sqrt(number)), int(np.sqrt(number)),\n",
|
|
" figsize=(10, 10))\n",
|
|
"\n",
|
|
" for i in range(int(np.sqrt(number))):\n",
|
|
" for j in range(int(np.sqrt(number))):\n",
|
|
" axs[i, j].imshow(generated_images[i*j], cmap='Greys')\n",
|
|
" axs[i, j].axis('off')\n",
|
|
"\n",
|
|
" plt.show()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 26,
|
|
"id": "2f5f0154",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"generated_images = generate_images(generate_latent_points())\n",
|
|
"plot_result(generated_images)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "ff581bf2",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"We see that the generator generates images that look like MNIST\n",
|
|
"numbers: $1, 4, 7, 9$. Let's try to tweak it a bit more to see if we are able\n",
|
|
"to generate a similar plot where we generate every MNIST number. Let us now try\n",
|
|
"to 'move' a bit around in the latent space. **Note**: decrease the plot number if\n",
|
|
"these following cells take too long to run on your computer."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 27,
|
|
"id": "d3617ad8",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"plot_number = 225\n",
|
|
"\n",
|
|
"generated_images = generate_images(generate_latent_points(number=plot_number,\n",
|
|
" scale_means=5,\n",
|
|
" scale_stds=1))\n",
|
|
"plot_result(generated_images, number=plot_number)\n",
|
|
"\n",
|
|
"generated_images = generate_images(generate_latent_points(number=plot_number,\n",
|
|
" scale_means=-5,\n",
|
|
" scale_stds=1))\n",
|
|
"plot_result(generated_images, number=plot_number)\n",
|
|
"\n",
|
|
"generated_images = generate_images(generate_latent_points(number=plot_number,\n",
|
|
" scale_means=1,\n",
|
|
" scale_stds=5))\n",
|
|
"plot_result(generated_images, number=plot_number)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "1a074f93",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Again, we have found something interesting. *Moving* around using our means\n",
|
|
"takes us from digit to digit, while *moving* around using our standard\n",
|
|
"deviations seem to increase the number of different digits! In the last image\n",
|
|
"above, we can barely make out every MNIST digit. Let us make on last plot using\n",
|
|
"this information by upping the standard deviation of our Gaussian noises."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 28,
|
|
"id": "4ef8937d",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"plot_number = 400\n",
|
|
"generated_images = generate_images(generate_latent_points(number=plot_number,\n",
|
|
" scale_means=1,\n",
|
|
" scale_stds=10))\n",
|
|
"plot_result(generated_images, number=plot_number)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "385a2d0a",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"A pretty cool result! We see that our generator indeed has learned a\n",
|
|
"distribution which qualitatively looks a whole lot like the MNIST dataset.\n",
|
|
"\n",
|
|
"Another interesting way to explore the latent space of our generator model is by\n",
|
|
"interpolating between the MNIST digits. This section is largely based on\n",
|
|
"[this excellent blogpost](https://machinelearningmastery.com/how-to-interpolate-and-perform-vector-arithmetic-with-faces-using-a-generative-adversarial-network/)\n",
|
|
"by Jason Brownlee.\n",
|
|
"\n",
|
|
"So let us start by defining a function to interpolate between two points in the\n",
|
|
"latent space."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 29,
|
|
"id": "57de87b8",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def interpolation(point_1, point_2, n_steps=10):\n",
|
|
" ratios = np.linspace(0, 1, num=n_steps)\n",
|
|
" vectors = []\n",
|
|
" for i, ratio in enumerate(ratios):\n",
|
|
" vectors.append(((1.0 - ratio) * point_1 + ratio * point_2))\n",
|
|
"\n",
|
|
" return tf.stack(vectors)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "cfb76bb6",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Now we have all we need to do our interpolation analysis."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 30,
|
|
"id": "e25decef",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"plot_number = 100\n",
|
|
"latent_points = generate_latent_points(number=plot_number)\n",
|
|
"results = None\n",
|
|
"for i in range(0, 2*np.sqrt(plot_number), 2):\n",
|
|
" interpolated = interpolation(latent_points[i], latent_points[i+1])\n",
|
|
" generated_images = generate_images(interpolated)\n",
|
|
"\n",
|
|
" if results is None:\n",
|
|
" results = generated_images\n",
|
|
" else:\n",
|
|
" results = tf.stack((results, generated_images))\n",
|
|
"\n",
|
|
"plot_results(results, plot_number)"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.9.10"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
} |