{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 最小二乘\n", "\n", "## 1. 最小二乘的基本原理\n", "\n", "最小二乘法(Least Squares)是一种数学优化技术,它通过最小化误差的平方和找到一组数据的最佳函数匹配, 最小二乘法通常用于曲线拟合、求解模型。很多其他的优化问题也可通过最小化能量或最大化熵用最小二乘形式表达。\n", "\n", "![ls_theory](images/least_squares.png)\n", "\n", "最小二乘原理的一般形式为:\n", "$$\n", "L = \\sum (V_{obv} - V_{target}(\\theta))^2\n", "$$\n", "其中\n", "* $V_{obv}$是观测的多组样本值\n", "* $V_{target}$是假设拟合函数的输出值\n", "* $\\theta$为构造模型的参数\n", "* $L$是目标函数\n", "\n", "如果通过调整模型参数$\\theta$,使得$L$下降到最小则表明,拟合函数与观测最为接近,也就是找到了最优的模型。\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.1 示例\n", "\n", "假设我们有下面的一些观测数据,希望找到它们内在的规律。" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "%matplotlib inline\n", "\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "\n", "# 生成数据\n", "data_num = 50\n", "X = np.random.rand(data_num, 1)*10\n", "Y = X * 3 + 4 + 4*np.random.randn(data_num,1)\n", "\n", "# 画出数据的分布\n", "plt.scatter(X, Y)\n", "plt.xlabel(\"X\")\n", "plt.ylabel(\"Y\")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.2 数学原理\n", "有$N$个观测数据为:\n", "$$\n", "\\mathbf{X} = \\{x_1, x_2, ..., x_N \\} \\\\\n", "\\mathbf{Y} = \\{y_1, y_2, ..., y_N \\}\n", "$$\n", "其中$\\mathbf{X}$为自变量,$\\mathbf{Y}$为因变量。\n", "\n", "希望找到一个模型能够解释这些数据,假设使用最简单的线性模型来拟合数据:\n", "$$\n", "y = ax + b\n", "$$\n", "那么问题就变成求解参数$a$, $b$能够使得模型输出尽可能和观测数据有比较小的误差。\n", "\n", "如何构建函数来评估模型输出与观测数据之间的误差是一个关键问题,这里我们使用观测数据与模型输出的平方和来作为评估函数(也被称为损失函数Loss function):\n", "$$\n", "L = \\sum_{i=1}^{N} \\{y_i - (a x_i + b)\\}^2 \\\\\n", "L = \\sum_{i=1}^{N} (y_i - a x_i - b)^2 \n", "$$\n", "\n", "使误差函数最小,那么我们就可以求出模型的参数:\n", "$$\n", "\\frac{\\partial L}{\\partial a} = -2 \\sum_{i=1}^{N} (y_i - a x_i - b) x_i \\\\\n", "\\frac{\\partial L}{\\partial b} = -2 \\sum_{i=1}^{N} (y_i - a x_i - b)\n", "$$\n", "\n", "即当偏微分为0时,误差函数为最小,因此我们可以得到:\n", "$$\n", "-2 \\sum_{i=1}^{N} (y_i - a x_i - b) x_i = 0 \\\\\n", "-2 \\sum_{i=1}^{N} (y_i - a x_i - b) = 0 \\\\\n", "$$\n", "\n", "将上式调整一下顺序可以得到:\n", "$$\n", "a \\sum x_i^2 + b \\sum x_i = \\sum y_i x_i \\\\\n", "a \\sum x_i + b N = \\sum y_i\n", "$$\n", "\n", "上式中$\\sum x_i^2$, $\\sum x_i$, $\\sum y_i$, $\\sum y_i x_i$都是已知的数据,而参数$a$, $b$是我们想要求得未知参数。通过求解二元一次方程组,我们即可求出模型的最优参数。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.3 求解程序" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a = 2.854105, b = 3.832234\n" ] }, { "data": { "image/png": "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LFmyBGMMF110Eb///e+pUqUK69evZ9KkSbRt2/aEx3z99dfMmDGDb775hpycHFq1akXr1q0Lff6qVauybNkyXnrpJUaNGsW4ceNo1KgRn332GWXLlmXu3Lk8/PDDxzodFmbs2LGUL1+etWvXsnLlSlq1anXsZ08++SRnnnkmubm5dOnShZUrVzJgwABGjx7NggULqFq1apHnNW/ePKz/zZTyu1hWjESzAZavAnhJvQjC8fnnn3PddddRoUIFAHr16sVnn31Gjx49qFu37knBG2Dx4sVce+21JCYmkpiYyDXXXFPk8/fq1QuA1q1bH2s7u3fvXvr27cv69esREXJycopd46JFixgwYAAAzZs3PyHwvv3226SlpXH06FG2bdvGmjVrCg3MwZ6nVLyIRcVI+vJMXh73IQM+m8aIjv3IBEf7o/gqhRLrGw/5QT0S+W1py5Qpw9GjRwEYPHgwnTp1YvXq1fznP//h8OHDYT33xo0bGTVqFPPmzWPlypV069at0OcK9jyllIM2bqTsHbcza2x/eqxdRItt3wHOVrv4KoBH48bDpZdeSnp6OocOHeLgwYO8++67XHrppcU+pn379scC74EDB5g1a1ZIr7l3715q1rSfvhMnTizx/ONb1q5evfrYOLd9+/ZRoUIFzjjjDHbs2MGcOXOOPaZSpUrs37+/xPOUUg7bsgX+8hdo0IDLV8zj9Vbd6XDnOBaed+GxU5y66PRVCuWBrg1PyIFD5DceWrVqRb9+/WjTpg0At99+O8nJyWzatKnIx1x44YX06NGD5s2bU716dZo1a8YZZ5wR9Gv+85//pG/fvgwdOpRu3bqVeP5dd93FrbfeSuPGjWncuPGxfHuLFi1ITk6mUaNG1K5dm/bt2x97TP/+/bnyyis555xzWLBgQZHnKaUcsn07DB8Or7wCeXlwxx3ccMbvWWEqnnSqU9Uuvmsn65WJGAcOHKBixYocOnSIDh06kJaWdsLNRT/SdrJKhSErC55+GsaMgV9/hb59YfBgqFfvpMILsBedx/dQCUZR7WR9dQUO3plf179/f9asWcPhw4fp27ev74O3UipEv/wCzzwD//43HDwIN90Eqalw/vnHTol2tYvvArhX5OeklVJxZt8+O7939GjYuxeuvx4eewyK+O01mhedngjgxhjsbGTlllim0pTypYMH4cUXbbpk92649lp4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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "N = X.shape[0]\n", "\n", "S_X2 = np.sum(X*X)\n", "S_X = np.sum(X)\n", "S_XY = np.sum(X*Y)\n", "S_Y = np.sum(Y)\n", "\n", "A1 = np.array([[S_X2, S_X], \n", " [S_X, N]])\n", "B1 = np.array([S_XY, S_Y])\n", "\n", "# numpy.linalg模块包含线性代数的函数。\n", "# 使用这个模块,可以计算逆矩阵、求特征值、解线性方程组以及求解行列式等。\n", "coeff = np.linalg.inv(A1).dot(B1)\n", "\n", "print('a = %f, b = %f' % (coeff[0], coeff[1]))\n", "\n", "x_min = np.min(X)\n", "x_max = np.max(X)\n", "y_min = coeff[0] * x_min + coeff[1]\n", "y_max = coeff[0] * x_max + coeff[1]\n", "\n", "plt.scatter(X, Y, label='original data')\n", "plt.plot([x_min, x_max], [y_min, y_max], 'r', label='model')\n", "plt.legend()\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. 如何使用迭代的方法求出模型参数\n", "\n", "当数据比较多的时候,或者模型比较复杂,无法直接使用解析的方式求出模型参数。因此更为常用的方式是,通过迭代的方式逐步逼近模型的参数。\n", "\n", "### 2.1 梯度下降法\n", "在机器学习算法中,对于很多监督学习模型,需要对原始的模型构建损失函数,接下来便是通过优化算法对损失函数进行优化,以便寻找到最优的参数。在求解机器学习参数的优化算法中,使用较多的是基于梯度下降的优化算法(Gradient Descent, GD)。\n", "\n", "梯度下降法有很多优点,其中最主要的优点是,**在梯度下降法的求解过程中只需求解损失函数的一阶导数,计算的代价比较小,这使得梯度下降法能在很多大规模数据集上得到应用。**\n", "\n", "梯度下降法的含义是通过当前点的梯度方向寻找到新的迭代点。梯度下降法的基本思想可以类比为一个下山的过程。假设这样一个场景:\n", "* 一个人被困在山上,需要从山上下来,找到山的最低点,也就是山谷;\n", "* 但此时山上的浓雾很大,导致可视度很低。因此,下山的路径就无法全部确定,他必须利用自己周围的信息去找到下山的路径。\n", "* 以他当前的所处的位置为基准,寻找这个位置最陡峭的地方,然后朝着山的高度下降的地方走\n", "* 每走一段距离,都反复采用同一个方法,最后就能成功的抵达山谷。\n", "\n", "\n", "一般情况下,这座山最陡峭的地方是无法通过肉眼立马观察出来的,而是需要一个工具来测量;同时,这个人此时正好拥有测量出最陡峭方向的能力。所以,此人每走一段距离,都需要一段时间来测量所在位置最陡峭的方向,这是比较耗时的。那么为了在太阳下山之前到达山底,就要尽可能的减少测量方向的次数。这是一个两难的选择,如果测量的频繁,可以保证下山的方向是绝对正确的,但又非常耗时;如果测量的过少,又有偏离轨道的风险。所以需要找到一个合适的测量方向的频率,来确保下山的方向不错误,同时又不至于耗时太多!\n", "\n", "\n", "![gradient_descent](images/gradient_descent.png)\n", "\n", "如上图所示,得到了最优解。$x$,$y$表示的是$\\theta_0$和$\\theta_1$,$z$方向表示的是花费函数,很明显出发点不同,最后到达的收敛点可能不一样。当然如果是碗状的,那么收敛点就应该是一样的。\n", "\n", "对于最小二乘的损失函数\n", "$$\n", "L = \\sum_{i=1}^{N} (y_i - a x_i - b)^2\n", "$$\n", "\n", "更新的策略是:\n", "$$\n", "\\theta^1 = \\theta^0 - \\eta \\triangledown L(\\theta)\n", "$$\n", "其中$\\theta$代表了模型中的参数,例如$a$, $b$\n", "\n", "此公式的意义是:$L$是关于$\\theta$的一个函数,我们当前所处的位置为$\\theta_0$点,要从这个点走到L的最小值点,也就是山底。首先我们先确定前进的方向,也就是梯度的反向,然后走一段距离的步长,也就是$\\eta$,走完这个段步长,就到达了$\\theta_1$这个点!\n", "\n", "最终的更新方程是:\n", "\n", "$$\n", "a^1 = a^0 + 2 \\eta [ y - (ax+b)]*x \\\\\n", "b^1 = b^0 + 2 \\eta [ y - (ax+b)] \n", "$$\n", "\n", "下面就这个公式的几个常见的疑问:\n", "\n", "* **$\\eta$是什么含义?**\n", "$\\eta$在梯度下降算法中被称作为学习率或者步长,意味着我们可以通过$\\eta$来控制每一步走的距离,以保证不要步子跨的太大,错过了最低点。同时也要保证不要走的太慢,导致太阳下山了,还没有走到山下。所以$\\eta$的选择在梯度下降法中往往是很重要的。\n", "![gd_stepsize](images/gd_stepsize.png)\n", "\n", "* **为什么要梯度要乘以一个负号?**\n", "梯度前加一个负号,就意味着朝着梯度相反的方向前进!梯度的方向实际就是函数在此点上升最快的方向,而我们需要朝着下降最快的方向走,自然就是负的梯度的方向,所以此处需要加上负号。\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.2 示例代码" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "epoch 0: loss = 879.929586, a = 3.129702, b = 1.380542\n", "epoch 100: loss = 786.897748, a = 2.842720, b = 3.588741\n", "epoch 200: loss = 785.461171, a = 2.820253, b = 3.758918\n", "epoch 300: loss = 786.608664, a = 2.812600, b = 3.755006\n", "epoch 400: loss = 783.592455, a = 2.838910, b = 3.758545\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "import random\n", "\n", "n_epoch = 500 # epoch size\n", "a, b = 1, 1 # initial parameters\n", "epsilon = 0.001 # learning rate\n", "\n", "for i in range(n_epoch):\n", " data_idx = list(range(N))\n", " random.shuffle(data_idx)\n", " \n", " for j in data_idx:\n", " a = a + epsilon*2*(Y[j] - a*X[j] - b)*X[j]\n", " b = b + epsilon*2*(Y[j] - a*X[j] - b)\n", "\n", " L = 0\n", " for j in range(N):\n", " L = L + (Y[j]-a*X[j]-b)**2\n", " \n", " if i % 100 == 0:\n", " print(\"epoch %4d: loss = %f, a = %f, b = %f\" % (i, L, a, b))\n", " \n", "x_min = np.min(X)\n", "x_max = np.max(X)\n", "y_min = a * x_min + b\n", "y_max = a * x_max + b\n", "\n", "plt.scatter(X, Y, label='original data')\n", "plt.plot([x_min, x_max], [y_min, y_max], 'r', label='model')\n", "plt.legend()\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3. 如何可视化迭代过程" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "/* global mpl */\n", "window.mpl = {};\n", "\n", "mpl.get_websocket_type = function () {\n", " if (typeof WebSocket !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof MozWebSocket !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert(\n", " 'Your browser does not have WebSocket support. ' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.'\n", " );\n", " }\n", "};\n", "\n", "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = this.ws.binaryType !== undefined;\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById('mpl-warnings');\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent =\n", " 'This browser does not support binary websocket messages. ' +\n", " 'Performance may be slow.';\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = document.createElement('div');\n", " this.root.setAttribute('style', 'display: inline-block');\n", " this._root_extra_style(this.root);\n", "\n", " parent_element.appendChild(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message('supports_binary', { value: fig.supports_binary });\n", " fig.send_message('send_image_mode', {});\n", " if (fig.ratio !== 1) {\n", " fig.send_message('set_dpi_ratio', { dpi_ratio: fig.ratio });\n", " }\n", " fig.send_message('refresh', {});\n", " };\n", "\n", " this.imageObj.onload = function () {\n", " if (fig.image_mode === 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " };\n", "\n", " this.imageObj.onunload = function () {\n", " fig.ws.close();\n", " };\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "};\n", "\n", "mpl.figure.prototype._init_header = function () {\n", " var titlebar = document.createElement('div');\n", " titlebar.classList =\n", " 'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n", " var titletext = document.createElement('div');\n", " titletext.classList = 'ui-dialog-title';\n", " titletext.setAttribute(\n", " 'style',\n", " 'width: 100%; text-align: center; padding: 3px;'\n", " );\n", " titlebar.appendChild(titletext);\n", " this.root.appendChild(titlebar);\n", " this.header = titletext;\n", "};\n", "\n", "mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n", "\n", "mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n", "\n", "mpl.figure.prototype._init_canvas = function () {\n", " var fig = this;\n", "\n", " var canvas_div = (this.canvas_div = document.createElement('div'));\n", " canvas_div.setAttribute(\n", " 'style',\n", " 'border: 1px solid #ddd;' +\n", " 'box-sizing: content-box;' +\n", " 'clear: both;' +\n", " 'min-height: 1px;' +\n", " 'min-width: 1px;' +\n", " 'outline: 0;' +\n", " 'overflow: hidden;' +\n", " 'position: relative;' +\n", " 'resize: both;'\n", " );\n", "\n", " function on_keyboard_event_closure(name) {\n", " return function (event) {\n", " return fig.key_event(event, name);\n", " };\n", " }\n", "\n", " canvas_div.addEventListener(\n", " 'keydown',\n", " on_keyboard_event_closure('key_press')\n", " );\n", " canvas_div.addEventListener(\n", " 'keyup',\n", " on_keyboard_event_closure('key_release')\n", " );\n", "\n", " this._canvas_extra_style(canvas_div);\n", " this.root.appendChild(canvas_div);\n", "\n", " var canvas = (this.canvas = document.createElement('canvas'));\n", " canvas.classList.add('mpl-canvas');\n", " canvas.setAttribute('style', 'box-sizing: content-box;');\n", "\n", " this.context = canvas.getContext('2d');\n", "\n", " var backingStore =\n", " this.context.backingStorePixelRatio ||\n", " this.context.webkitBackingStorePixelRatio ||\n", " this.context.mozBackingStorePixelRatio ||\n", " this.context.msBackingStorePixelRatio ||\n", " this.context.oBackingStorePixelRatio ||\n", " this.context.backingStorePixelRatio ||\n", " 1;\n", "\n", " this.ratio = (window.devicePixelRatio || 1) / backingStore;\n", "\n", " var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n", " 'canvas'\n", " ));\n", " rubberband_canvas.setAttribute(\n", " 'style',\n", " 'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n", " );\n", "\n", " // Apply a ponyfill if ResizeObserver is not implemented by browser.\n", " if (this.ResizeObserver === undefined) {\n", " if (window.ResizeObserver !== undefined) {\n", " this.ResizeObserver = window.ResizeObserver;\n", " } else {\n", " var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n", " this.ResizeObserver = obs.ResizeObserver;\n", " }\n", " }\n", "\n", " this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n", " var nentries = entries.length;\n", " for (var i = 0; i < nentries; i++) {\n", " var entry = entries[i];\n", " var width, height;\n", " if (entry.contentBoxSize) {\n", " if (entry.contentBoxSize instanceof Array) {\n", " // Chrome 84 implements new version of spec.\n", " width = entry.contentBoxSize[0].inlineSize;\n", " height = entry.contentBoxSize[0].blockSize;\n", " } else {\n", " // Firefox implements old version of spec.\n", " width = entry.contentBoxSize.inlineSize;\n", " height = entry.contentBoxSize.blockSize;\n", " }\n", " } else {\n", " // Chrome <84 implements even older version of spec.\n", " width = entry.contentRect.width;\n", " height = entry.contentRect.height;\n", " }\n", "\n", " // Keep the size of the canvas and rubber band canvas in sync with\n", " // the canvas container.\n", " if (entry.devicePixelContentBoxSize) {\n", " // Chrome 84 implements new version of spec.\n", " canvas.setAttribute(\n", " 'width',\n", " entry.devicePixelContentBoxSize[0].inlineSize\n", " );\n", " canvas.setAttribute(\n", " 'height',\n", " entry.devicePixelContentBoxSize[0].blockSize\n", " );\n", " } else {\n", " canvas.setAttribute('width', width * fig.ratio);\n", " canvas.setAttribute('height', height * fig.ratio);\n", " }\n", " canvas.setAttribute(\n", " 'style',\n", " 'width: ' + width + 'px; height: ' + height + 'px;'\n", " );\n", "\n", " rubberband_canvas.setAttribute('width', width);\n", " rubberband_canvas.setAttribute('height', height);\n", "\n", " // And update the size in Python. We ignore the initial 0/0 size\n", " // that occurs as the element is placed into the DOM, which should\n", " // otherwise not happen due to the minimum size styling.\n", " if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n", " fig.request_resize(width, height);\n", " }\n", " }\n", " });\n", " this.resizeObserverInstance.observe(canvas_div);\n", "\n", " function on_mouse_event_closure(name) {\n", " return function (event) {\n", " return fig.mouse_event(event, name);\n", " };\n", " }\n", "\n", " rubberband_canvas.addEventListener(\n", " 'mousedown',\n", " on_mouse_event_closure('button_press')\n", " );\n", " rubberband_canvas.addEventListener(\n", " 'mouseup',\n", " on_mouse_event_closure('button_release')\n", " );\n", " rubberband_canvas.addEventListener(\n", " 'dblclick',\n", " on_mouse_event_closure('dblclick')\n", " );\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband_canvas.addEventListener(\n", " 'mousemove',\n", " on_mouse_event_closure('motion_notify')\n", " );\n", "\n", " rubberband_canvas.addEventListener(\n", " 'mouseenter',\n", " on_mouse_event_closure('figure_enter')\n", " );\n", " rubberband_canvas.addEventListener(\n", " 'mouseleave',\n", " on_mouse_event_closure('figure_leave')\n", " );\n", "\n", " canvas_div.addEventListener('wheel', function (event) {\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " on_mouse_event_closure('scroll')(event);\n", " });\n", "\n", " canvas_div.appendChild(canvas);\n", " canvas_div.appendChild(rubberband_canvas);\n", "\n", " this.rubberband_context = rubberband_canvas.getContext('2d');\n", " this.rubberband_context.strokeStyle = '#000000';\n", "\n", " this._resize_canvas = function (width, height, forward) {\n", " if (forward) {\n", " canvas_div.style.width = width + 'px';\n", " canvas_div.style.height = height + 'px';\n", " }\n", " };\n", "\n", " // Disable right mouse context menu.\n", " this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n", " event.preventDefault();\n", " return false;\n", " });\n", "\n", " function set_focus() {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "};\n", "\n", "mpl.figure.prototype._init_toolbar = function () {\n", " var fig = this;\n", "\n", " var toolbar = document.createElement('div');\n", " toolbar.classList = 'mpl-toolbar';\n", " this.root.appendChild(toolbar);\n", "\n", " function on_click_closure(name) {\n", " return function (_event) {\n", " return fig.toolbar_button_onclick(name);\n", " };\n", " }\n", "\n", " function on_mouseover_closure(tooltip) {\n", " return function (event) {\n", " if (!event.currentTarget.disabled) {\n", " return fig.toolbar_button_onmouseover(tooltip);\n", " }\n", " };\n", " }\n", "\n", " fig.buttons = {};\n", " var buttonGroup = document.createElement('div');\n", " buttonGroup.classList = 'mpl-button-group';\n", " for (var toolbar_ind in mpl.toolbar_items) {\n", " var name = mpl.toolbar_items[toolbar_ind][0];\n", " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", " var image = mpl.toolbar_items[toolbar_ind][2];\n", " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", "\n", " if (!name) {\n", " /* Instead of a spacer, we start a new button group. */\n", " if (buttonGroup.hasChildNodes()) {\n", " toolbar.appendChild(buttonGroup);\n", " }\n", " buttonGroup = document.createElement('div');\n", " buttonGroup.classList = 'mpl-button-group';\n", " continue;\n", " }\n", "\n", " var button = (fig.buttons[name] = document.createElement('button'));\n", " button.classList = 'mpl-widget';\n", " button.setAttribute('role', 'button');\n", " button.setAttribute('aria-disabled', 'false');\n", " button.addEventListener('click', on_click_closure(method_name));\n", " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", "\n", " var icon_img = document.createElement('img');\n", " icon_img.src = '_images/' + image + '.png';\n", " icon_img.srcset = '_images/' + image + '_large.png 2x';\n", " icon_img.alt = tooltip;\n", " button.appendChild(icon_img);\n", "\n", " buttonGroup.appendChild(button);\n", " }\n", "\n", " if (buttonGroup.hasChildNodes()) {\n", " toolbar.appendChild(buttonGroup);\n", " }\n", "\n", " var fmt_picker = document.createElement('select');\n", " fmt_picker.classList = 'mpl-widget';\n", " toolbar.appendChild(fmt_picker);\n", " this.format_dropdown = fmt_picker;\n", "\n", " for (var ind in mpl.extensions) {\n", " var fmt = mpl.extensions[ind];\n", " var option = document.createElement('option');\n", " option.selected = fmt === mpl.default_extension;\n", " option.innerHTML = fmt;\n", " fmt_picker.appendChild(option);\n", " }\n", "\n", " var status_bar = document.createElement('span');\n", " status_bar.classList = 'mpl-message';\n", " toolbar.appendChild(status_bar);\n", " this.message = status_bar;\n", "};\n", "\n", "mpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n", " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", " // which will in turn request a refresh of the image.\n", " this.send_message('resize', { width: x_pixels, height: y_pixels });\n", "};\n", "\n", "mpl.figure.prototype.send_message = function (type, properties) {\n", " properties['type'] = type;\n", " properties['figure_id'] = this.id;\n", " this.ws.send(JSON.stringify(properties));\n", "};\n", "\n", "mpl.figure.prototype.send_draw_message = function () {\n", " if (!this.waiting) {\n", " this.waiting = true;\n", " this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n", " }\n", "};\n", "\n", "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", " var format_dropdown = fig.format_dropdown;\n", " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", " fig.ondownload(fig, format);\n", "};\n", "\n", "mpl.figure.prototype.handle_resize = function (fig, msg) {\n", " var size = msg['size'];\n", " if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n", " fig._resize_canvas(size[0], size[1], msg['forward']);\n", " fig.send_message('refresh', {});\n", " }\n", "};\n", "\n", "mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n", " var x0 = msg['x0'] / fig.ratio;\n", " var y0 = (fig.canvas.height - msg['y0']) / fig.ratio;\n", " var x1 = msg['x1'] / fig.ratio;\n", " var y1 = (fig.canvas.height - msg['y1']) / fig.ratio;\n", " x0 = Math.floor(x0) + 0.5;\n", " y0 = Math.floor(y0) + 0.5;\n", " x1 = Math.floor(x1) + 0.5;\n", " y1 = Math.floor(y1) + 0.5;\n", " var min_x = Math.min(x0, x1);\n", " var min_y = Math.min(y0, y1);\n", " var width = Math.abs(x1 - x0);\n", " var height = Math.abs(y1 - y0);\n", "\n", " fig.rubberband_context.clearRect(\n", " 0,\n", " 0,\n", " fig.canvas.width / fig.ratio,\n", " fig.canvas.height / fig.ratio\n", " );\n", "\n", " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", "};\n", "\n", "mpl.figure.prototype.handle_figure_label = function (fig, msg) {\n", " // Updates the figure title.\n", " fig.header.textContent = msg['label'];\n", "};\n", "\n", "mpl.figure.prototype.handle_cursor = function (fig, msg) {\n", " var cursor = msg['cursor'];\n", " switch (cursor) {\n", " case 0:\n", " cursor = 'pointer';\n", " break;\n", " case 1:\n", " cursor = 'default';\n", " break;\n", " case 2:\n", " cursor = 'crosshair';\n", " break;\n", " case 3:\n", " cursor = 'move';\n", " break;\n", " }\n", " fig.rubberband_canvas.style.cursor = cursor;\n", "};\n", "\n", "mpl.figure.prototype.handle_message = function (fig, msg) {\n", " fig.message.textContent = msg['message'];\n", "};\n", "\n", "mpl.figure.prototype.handle_draw = function (fig, _msg) {\n", " // Request the server to send over a new figure.\n", " fig.send_draw_message();\n", "};\n", "\n", "mpl.figure.prototype.handle_image_mode = function (fig, msg) {\n", " fig.image_mode = msg['mode'];\n", "};\n", "\n", "mpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n", " for (var key in msg) {\n", " if (!(key in fig.buttons)) {\n", " continue;\n", " }\n", " fig.buttons[key].disabled = !msg[key];\n", " fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n", " }\n", "};\n", "\n", "mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n", " if (msg['mode'] === 'PAN') {\n", " fig.buttons['Pan'].classList.add('active');\n", " fig.buttons['Zoom'].classList.remove('active');\n", " } else if (msg['mode'] === 'ZOOM') {\n", " fig.buttons['Pan'].classList.remove('active');\n", " fig.buttons['Zoom'].classList.add('active');\n", " } else {\n", " fig.buttons['Pan'].classList.remove('active');\n", " fig.buttons['Zoom'].classList.remove('active');\n", " }\n", "};\n", "\n", "mpl.figure.prototype.updated_canvas_event = function () {\n", " // Called whenever the canvas gets updated.\n", " this.send_message('ack', {});\n", "};\n", "\n", "// A function to construct a web socket function for onmessage handling.\n", "// Called in the figure constructor.\n", "mpl.figure.prototype._make_on_message_function = function (fig) {\n", " return function socket_on_message(evt) {\n", " if (evt.data instanceof Blob) {\n", " var img = evt.data;\n", " if (img.type !== 'image/png') {\n", " /* FIXME: We get \"Resource interpreted as Image but\n", " * transferred with MIME type text/plain:\" errors on\n", " * Chrome. But how to set the MIME type? It doesn't seem\n", " * to be part of the websocket stream */\n", " img.type = 'image/png';\n", " }\n", "\n", " /* Free the memory for the previous frames */\n", " if (fig.imageObj.src) {\n", " (window.URL || window.webkitURL).revokeObjectURL(\n", " fig.imageObj.src\n", " );\n", " }\n", "\n", " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", " img\n", " );\n", " fig.updated_canvas_event();\n", " fig.waiting = false;\n", " return;\n", " } else if (\n", " typeof evt.data === 'string' &&\n", " evt.data.slice(0, 21) === 'data:image/png;base64'\n", " ) {\n", " fig.imageObj.src = evt.data;\n", " fig.updated_canvas_event();\n", " fig.waiting = false;\n", " return;\n", " }\n", "\n", " var msg = JSON.parse(evt.data);\n", " var msg_type = msg['type'];\n", "\n", " // Call the \"handle_{type}\" callback, which takes\n", " // the figure and JSON message as its only arguments.\n", " try {\n", " var callback = fig['handle_' + msg_type];\n", " } catch (e) {\n", " console.log(\n", " \"No handler for the '\" + msg_type + \"' message type: \",\n", " msg\n", " );\n", " return;\n", " }\n", "\n", " if (callback) {\n", " try {\n", " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", " callback(fig, msg);\n", " } catch (e) {\n", " console.log(\n", " \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n", " e,\n", " e.stack,\n", " msg\n", " );\n", " }\n", " }\n", " };\n", "};\n", "\n", "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", "mpl.findpos = function (e) {\n", " //this section is from http://www.quirksmode.org/js/events_properties.html\n", " var targ;\n", " if (!e) {\n", " e = window.event;\n", " }\n", " if (e.target) {\n", " targ = e.target;\n", " } else if (e.srcElement) {\n", " targ = e.srcElement;\n", " }\n", " if (targ.nodeType === 3) {\n", " // defeat Safari bug\n", " targ = targ.parentNode;\n", " }\n", "\n", " // pageX,Y are the mouse positions relative to the document\n", " var boundingRect = targ.getBoundingClientRect();\n", " var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n", " var y = e.pageY - (boundingRect.top + document.body.scrollTop);\n", "\n", " return { x: x, y: y };\n", "};\n", "\n", "/*\n", " * return a copy of an object with only non-object keys\n", " * we need this to avoid circular references\n", " * http://stackoverflow.com/a/24161582/3208463\n", " */\n", "function simpleKeys(original) {\n", " return Object.keys(original).reduce(function (obj, key) {\n", " if (typeof original[key] !== 'object') {\n", " obj[key] = original[key];\n", " }\n", " return obj;\n", " }, {});\n", "}\n", "\n", "mpl.figure.prototype.mouse_event = function (event, name) {\n", " var canvas_pos = mpl.findpos(event);\n", "\n", " if (name === 'button_press') {\n", " this.canvas.focus();\n", " this.canvas_div.focus();\n", " }\n", "\n", " var x = canvas_pos.x * this.ratio;\n", " var y = canvas_pos.y * this.ratio;\n", "\n", " this.send_message(name, {\n", " x: x,\n", " y: y,\n", " button: event.button,\n", " step: event.step,\n", " guiEvent: simpleKeys(event),\n", " });\n", "\n", " /* This prevents the web browser from automatically changing to\n", " * the text insertion cursor when the button is pressed. We want\n", " * to control all of the cursor setting manually through the\n", " * 'cursor' event from matplotlib */\n", " event.preventDefault();\n", " return false;\n", "};\n", "\n", "mpl.figure.prototype._key_event_extra = function (_event, _name) {\n", " // Handle any extra behaviour associated with a key event\n", "};\n", "\n", "mpl.figure.prototype.key_event = function (event, name) {\n", " // Prevent repeat events\n", " if (name === 'key_press') {\n", " if (event.key === this._key) {\n", " return;\n", " } else {\n", " this._key = event.key;\n", " }\n", " }\n", " if (name === 'key_release') {\n", " this._key = null;\n", " }\n", "\n", " var value = '';\n", " if (event.ctrlKey && event.key !== 'Control') {\n", " value += 'ctrl+';\n", " }\n", " else if (event.altKey && event.key !== 'Alt') {\n", " value += 'alt+';\n", " }\n", " else if (event.shiftKey && event.key !== 'Shift') {\n", " value += 'shift+';\n", " }\n", "\n", " value += 'k' + event.key;\n", "\n", " this._key_event_extra(event, name);\n", "\n", " this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n", " return false;\n", "};\n", "\n", "mpl.figure.prototype.toolbar_button_onclick = function (name) {\n", " if (name === 'download') {\n", " this.handle_save(this, null);\n", " } else {\n", " this.send_message('toolbar_button', { name: name });\n", " }\n", "};\n", "\n", "mpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n", " this.message.textContent = tooltip;\n", "};\n", "\n", "///////////////// REMAINING CONTENT GENERATED BY embed_js.py /////////////////\n", "// prettier-ignore\n", "var _JSXTOOLS_RESIZE_OBSERVER=function(A){var t,i=new WeakMap,n=new WeakMap,a=new WeakMap,r=new WeakMap,o=new Set;function s(e){if(!(this instanceof s))throw new TypeError(\"Constructor requires 'new' operator\");i.set(this,e)}function h(){throw new TypeError(\"Function is not a constructor\")}function c(e,t,i,n){e=0 in arguments?Number(arguments[0]):0,t=1 in arguments?Number(arguments[1]):0,i=2 in arguments?Number(arguments[2]):0,n=3 in arguments?Number(arguments[3]):0,this.right=(this.x=this.left=e)+(this.width=i),this.bottom=(this.y=this.top=t)+(this.height=n),Object.freeze(this)}function d(){t=requestAnimationFrame(d);var s=new WeakMap,p=new Set;o.forEach((function(t){r.get(t).forEach((function(i){var r=t instanceof window.SVGElement,o=a.get(t),d=r?0:parseFloat(o.paddingTop),f=r?0:parseFloat(o.paddingRight),l=r?0:parseFloat(o.paddingBottom),u=r?0:parseFloat(o.paddingLeft),g=r?0:parseFloat(o.borderTopWidth),m=r?0:parseFloat(o.borderRightWidth),w=r?0:parseFloat(o.borderBottomWidth),b=u+f,F=d+l,v=(r?0:parseFloat(o.borderLeftWidth))+m,W=g+w,y=r?0:t.offsetHeight-W-t.clientHeight,E=r?0:t.offsetWidth-v-t.clientWidth,R=b+v,z=F+W,M=r?t.width:parseFloat(o.width)-R-E,O=r?t.height:parseFloat(o.height)-z-y;if(n.has(t)){var k=n.get(t);if(k[0]===M&&k[1]===O)return}n.set(t,[M,O]);var S=Object.create(h.prototype);S.target=t,S.contentRect=new c(u,d,M,O),s.has(i)||(s.set(i,[]),p.add(i)),s.get(i).push(S)}))})),p.forEach((function(e){i.get(e).call(e,s.get(e),e)}))}return s.prototype.observe=function(i){if(i instanceof window.Element){r.has(i)||(r.set(i,new Set),o.add(i),a.set(i,window.getComputedStyle(i)));var n=r.get(i);n.has(this)||n.add(this),cancelAnimationFrame(t),t=requestAnimationFrame(d)}},s.prototype.unobserve=function(i){if(i instanceof window.Element&&r.has(i)){var n=r.get(i);n.has(this)&&(n.delete(this),n.size||(r.delete(i),o.delete(i))),n.size||r.delete(i),o.size||cancelAnimationFrame(t)}},A.DOMRectReadOnly=c,A.ResizeObserver=s,A.ResizeObserverEntry=h,A}; // eslint-disable-line\n", "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", "\n", "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n", "\n", "mpl.default_extension = \"png\";/* global mpl */\n", "\n", "var comm_websocket_adapter = function (comm) {\n", " // Create a \"websocket\"-like object which calls the given IPython comm\n", " // object with the appropriate methods. Currently this is a non binary\n", " // socket, so there is still some room for performance tuning.\n", " var ws = {};\n", "\n", " ws.binaryType = comm.kernel.ws.binaryType;\n", " ws.readyState = comm.kernel.ws.readyState;\n", " function updateReadyState(_event) {\n", " if (comm.kernel.ws) {\n", " ws.readyState = comm.kernel.ws.readyState;\n", " } else {\n", " ws.readyState = 3; // Closed state.\n", " }\n", " }\n", " comm.kernel.ws.addEventListener('open', updateReadyState);\n", " comm.kernel.ws.addEventListener('close', updateReadyState);\n", " comm.kernel.ws.addEventListener('error', updateReadyState);\n", "\n", " ws.close = function () {\n", " comm.close();\n", " };\n", " ws.send = function (m) {\n", " //console.log('sending', m);\n", " comm.send(m);\n", " };\n", " // Register the callback with on_msg.\n", " comm.on_msg(function (msg) {\n", " //console.log('receiving', msg['content']['data'], msg);\n", " var data = msg['content']['data'];\n", " if (data['blob'] !== undefined) {\n", " data = {\n", " data: new Blob(msg['buffers'], { type: data['blob'] }),\n", " };\n", " }\n", " // Pass the mpl event to the overridden (by mpl) onmessage function.\n", " ws.onmessage(data);\n", " });\n", " return ws;\n", "};\n", "\n", "mpl.mpl_figure_comm = function (comm, msg) {\n", " // This is the function which gets called when the mpl process\n", " // starts-up an IPython Comm through the \"matplotlib\" channel.\n", "\n", " var id = msg.content.data.id;\n", " // Get hold of the div created by the display call when the Comm\n", " // socket was opened in Python.\n", " var element = document.getElementById(id);\n", " var ws_proxy = comm_websocket_adapter(comm);\n", "\n", " function ondownload(figure, _format) {\n", " window.open(figure.canvas.toDataURL());\n", " }\n", "\n", " var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n", "\n", " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", " // web socket which is closed, not our websocket->open comm proxy.\n", " ws_proxy.onopen();\n", "\n", " fig.parent_element = element;\n", " fig.cell_info = mpl.find_output_cell(\"
\");\n", " if (!fig.cell_info) {\n", " console.error('Failed to find cell for figure', id, fig);\n", " return;\n", " }\n", " fig.cell_info[0].output_area.element.on(\n", " 'cleared',\n", " { fig: fig },\n", " fig._remove_fig_handler\n", " );\n", "};\n", "\n", "mpl.figure.prototype.handle_close = function (fig, msg) {\n", " var width = fig.canvas.width / fig.ratio;\n", " fig.cell_info[0].output_area.element.off(\n", " 'cleared',\n", " fig._remove_fig_handler\n", " );\n", " fig.resizeObserverInstance.unobserve(fig.canvas_div);\n", "\n", " // Update the output cell to use the data from the current canvas.\n", " fig.push_to_output();\n", " var dataURL = fig.canvas.toDataURL();\n", " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", " // the notebook keyboard shortcuts fail.\n", " IPython.keyboard_manager.enable();\n", " fig.parent_element.innerHTML =\n", " '';\n", " fig.close_ws(fig, msg);\n", "};\n", "\n", "mpl.figure.prototype.close_ws = function (fig, msg) {\n", " fig.send_message('closing', msg);\n", " // fig.ws.close()\n", "};\n", "\n", "mpl.figure.prototype.push_to_output = function (_remove_interactive) {\n", " // Turn the data on the canvas into data in the output cell.\n", " var width = this.canvas.width / this.ratio;\n", " var dataURL = this.canvas.toDataURL();\n", " this.cell_info[1]['text/html'] =\n", " '';\n", "};\n", "\n", "mpl.figure.prototype.updated_canvas_event = function () {\n", " // Tell IPython that the notebook contents must change.\n", " IPython.notebook.set_dirty(true);\n", " this.send_message('ack', {});\n", " var fig = this;\n", " // Wait a second, then push the new image to the DOM so\n", " // that it is saved nicely (might be nice to debounce this).\n", " setTimeout(function () {\n", " fig.push_to_output();\n", " }, 1000);\n", "};\n", "\n", "mpl.figure.prototype._init_toolbar = function () {\n", " var fig = this;\n", "\n", " var toolbar = document.createElement('div');\n", " toolbar.classList = 'btn-toolbar';\n", " this.root.appendChild(toolbar);\n", "\n", " function on_click_closure(name) {\n", " return function (_event) {\n", " return fig.toolbar_button_onclick(name);\n", " };\n", " }\n", "\n", " function on_mouseover_closure(tooltip) {\n", " return function (event) {\n", " if (!event.currentTarget.disabled) {\n", " return fig.toolbar_button_onmouseover(tooltip);\n", " }\n", " };\n", " }\n", "\n", " fig.buttons = {};\n", " var buttonGroup = document.createElement('div');\n", " buttonGroup.classList = 'btn-group';\n", " var button;\n", " for (var toolbar_ind in mpl.toolbar_items) {\n", " var name = mpl.toolbar_items[toolbar_ind][0];\n", " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", " var image = mpl.toolbar_items[toolbar_ind][2];\n", " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", "\n", " if (!name) {\n", " /* Instead of a spacer, we start a new button group. */\n", " if (buttonGroup.hasChildNodes()) {\n", " toolbar.appendChild(buttonGroup);\n", " }\n", " buttonGroup = document.createElement('div');\n", " buttonGroup.classList = 'btn-group';\n", " continue;\n", " }\n", "\n", " button = fig.buttons[name] = document.createElement('button');\n", " button.classList = 'btn btn-default';\n", " button.href = '#';\n", " button.title = name;\n", " button.innerHTML = '';\n", " button.addEventListener('click', on_click_closure(method_name));\n", " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", " buttonGroup.appendChild(button);\n", " }\n", "\n", " if (buttonGroup.hasChildNodes()) {\n", " toolbar.appendChild(buttonGroup);\n", " }\n", "\n", " // Add the status bar.\n", " var status_bar = document.createElement('span');\n", " status_bar.classList = 'mpl-message pull-right';\n", " toolbar.appendChild(status_bar);\n", " this.message = status_bar;\n", "\n", " // Add the close button to the window.\n", " var buttongrp = document.createElement('div');\n", " buttongrp.classList = 'btn-group inline pull-right';\n", " button = document.createElement('button');\n", " button.classList = 'btn btn-mini btn-primary';\n", " button.href = '#';\n", " button.title = 'Stop Interaction';\n", " button.innerHTML = '';\n", " button.addEventListener('click', function (_evt) {\n", " fig.handle_close(fig, {});\n", " });\n", " button.addEventListener(\n", " 'mouseover',\n", " on_mouseover_closure('Stop Interaction')\n", " );\n", " buttongrp.appendChild(button);\n", " var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n", " titlebar.insertBefore(buttongrp, titlebar.firstChild);\n", "};\n", "\n", "mpl.figure.prototype._remove_fig_handler = function (event) {\n", " var fig = event.data.fig;\n", " if (event.target !== this) {\n", " // Ignore bubbled events from children.\n", " return;\n", " }\n", " fig.close_ws(fig, {});\n", "};\n", "\n", "mpl.figure.prototype._root_extra_style = function (el) {\n", " el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n", "};\n", "\n", "mpl.figure.prototype._canvas_extra_style = function (el) {\n", " // this is important to make the div 'focusable\n", " el.setAttribute('tabindex', 0);\n", " // reach out to IPython and tell the keyboard manager to turn it's self\n", " // off when our div gets focus\n", "\n", " // location in version 3\n", " if (IPython.notebook.keyboard_manager) {\n", " IPython.notebook.keyboard_manager.register_events(el);\n", " } else {\n", " // location in version 2\n", " IPython.keyboard_manager.register_events(el);\n", " }\n", "};\n", "\n", "mpl.figure.prototype._key_event_extra = function (event, _name) {\n", " var manager = IPython.notebook.keyboard_manager;\n", " if (!manager) {\n", " manager = IPython.keyboard_manager;\n", " }\n", "\n", " // Check for shift+enter\n", " if (event.shiftKey && event.which === 13) {\n", " this.canvas_div.blur();\n", " // select the cell after this one\n", " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", " IPython.notebook.select(index + 1);\n", " }\n", "};\n", "\n", "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", " fig.ondownload(fig, null);\n", "};\n", "\n", "mpl.find_output_cell = function (html_output) {\n", " // Return the cell and output element which can be found *uniquely* in the notebook.\n", " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", " // IPython event is triggered only after the cells have been serialised, which for\n", " // our purposes (turning an active figure into a static one), is too late.\n", " var cells = IPython.notebook.get_cells();\n", " var ncells = cells.length;\n", " for (var i = 0; i < ncells; i++) {\n", " var cell = cells[i];\n", " if (cell.cell_type === 'code') {\n", " for (var j = 0; j < cell.output_area.outputs.length; j++) {\n", " var data = cell.output_area.outputs[j];\n", " if (data.data) {\n", " // IPython >= 3 moved mimebundle to data attribute of output\n", " data = data.data;\n", " }\n", " if (data['text/html'] === html_output) {\n", " return [cell, data, j];\n", " }\n", " }\n", " }\n", " }\n", "};\n", "\n", "// Register the function which deals with the matplotlib target/channel.\n", "// The kernel may be null if the page has been refreshed.\n", "if (IPython.notebook.kernel !== null) {\n", " IPython.notebook.kernel.comm_manager.register_target(\n", " 'matplotlib',\n", " mpl.mpl_figure_comm\n", " );\n", "}\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%matplotlib nbagg\n", "\n", "import matplotlib.pyplot as plt\n", "import matplotlib.animation as animation\n", "\n", "n_epoch = 300 # epoch size\n", "a, b = 1, 1 # initial parameters\n", "epsilon = 0.0001 # learning rate\n", "\n", "fig = plt.figure()\n", "imgs = []\n", "\n", "for i in range(n_epoch):\n", " data_idx = list(range(N))\n", " random.shuffle(data_idx)\n", " \n", " for j in data_idx[:10]:\n", " a = a + epsilon*2*(Y[j] - a*X[j] - b)*X[j]\n", " b = b + epsilon*2*(Y[j] - a*X[j] - b)\n", "\n", "\n", " if i<80 and i % 5 == 0:\n", " x_min = np.min(X)\n", " x_max = np.max(X)\n", " y_min = a * x_min + b\n", " y_max = a * x_max + b\n", "\n", " img = plt.scatter(X, Y, label='original data')\n", " img = plt.plot([x_min, x_max], [y_min, y_max], 'r', label='model')\n", " imgs.append(img)\n", " \n", "ani = animation.ArtistAnimation(fig, imgs)\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4. 如何使用批次更新的方法?\n", "\n", "如果有一些数据包含比较大的错误(异常数据),因此每次更新仅仅使用一个数据会导致不精确,同时每次仅仅使用一个数据来计算更新也导致计算效率比较低。\n", "\n", "\n", "* [梯度下降方法的几种形式](https://blog.csdn.net/u010402786/article/details/51188876)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5. 如何拟合多项式函数?\n", "\n", "需要设计一个弹道导弹防御系统,通过观测导弹的飞行路径,预测未来导弹的飞行轨迹,从而完成摧毁的任务。按照物理学,可以得知模型为:\n", "$$\n", "y = at^2 + bt + c\n", "$$\n", "我们需要求解三个模型参数$a, b, c$。\n", "\n", "损失函数的定义为:\n", "$$\n", "L = \\sum_{i=1}^N (y_i - at_i^2 - bt_i - c)^2\n", "$$\n" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "%matplotlib inline\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "\n", "pa = -20\n", "pb = 90\n", "pc = 800\n", "\n", "t = np.linspace(0, 10) \n", "y = pa*t**2 + pb*t + pc + np.random.randn(np.size(t))*15\n", "\n", "\n", "plt.plot(t, y)\n", "plt.xlabel(\"time\")\n", "plt.ylabel(\"height\")\n", "plt.savefig(\"fig-res-missle_taj.pdf\")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 5.1 如何得到更新项?\n", "\n", "$$\n", "L = \\sum_{i=1}^N (y_i - at_i^2 - bt_i - c)^2\n", "$$\n", "\n", "\\begin{eqnarray}\n", "\\frac{\\partial L}{\\partial a} & = & - 2\\sum_{i=1}^N (y_i - at_i^2 - bt_i -c) t_i^2 \\\\\n", "\\frac{\\partial L}{\\partial b} & = & - 2\\sum_{i=1}^N (y_i - at_i^2 - bt_i -c) t_i \\\\\n", "\\frac{\\partial L}{\\partial c} & = & - 2\\sum_{i=1}^N (y_i - at_i^2 - bt_i -c)\n", "\\end{eqnarray}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 5.2 程序" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "epoch 0: loss = 2.56475e+07, a = -3.94206, b = 6.99091, c = 4.31571\n", "epoch 500: loss = 1.02019e+06, a = -31.101, b = 240.081, c = 422.652\n", "epoch 1000: loss = 336249, a = -26.2534, b = 175.167, c = 583.595\n", "epoch 1500: loss = 114625, a = -23.492, b = 138.192, c = 675.243\n", "epoch 2000: loss = 42869.2, a = -21.9195, b = 117.136, c = 727.434\n", "epoch 2500: loss = 19664.8, a = -21.024, b = 105.145, c = 757.155\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "n_epoch = 3000 # epoch size\n", "a, b, c = 1.0, 1.0, 1.0 # initial parameters\n", "epsilon = 0.0001 # learning rate\n", "\n", "N = np.size(t)\n", "\n", "for i in range(n_epoch):\n", " for j in range(N):\n", " a = a + epsilon*2*(y[j] - a*t[j]**2 - b*t[j] - c)*t[j]**2\n", " b = b + epsilon*2*(y[j] - a*t[j]**2 - b*t[j] - c)*t[j]\n", " c = c + epsilon*2*(y[j] - a*t[j]**2 - b*t[j] - c)\n", "\n", " L = 0\n", " for j in range(N):\n", " L = L + (y[j] - a*t[j]**2 - b*t[j] - c)**2\n", " \n", " if i % 500 == 0:\n", " print(\"epoch %4d: loss = %10g, a = %10g, b = %10g, c = %10g\" % (i, L, a, b, c))\n", " \n", " \n", "y_est = a*t**2 + b*t + c \n", "\n", "\n", "plt.plot(t, y, 'r-', label='Real data')\n", "plt.plot(t, y_est, 'g-x', label='Estimated data')\n", "plt.legend()\n", "plt.savefig(\"fig-res-missle_est.pdf\")\n", "plt.show()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 6. 如何使用sklearn求解线性问题?\n" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "X: (100, 1)\n", "Y: (100, 1)\n", "a = 2.946639, b = 4.011924\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "%matplotlib inline\n", "\n", "import matplotlib.pyplot as plt\n", "from sklearn import linear_model\n", "import numpy as np\n", "\n", "# load data\n", "# generate data\n", "data_num = 100\n", "X = np.random.rand(data_num, 1)*10\n", "Y = X * 3 + 4 + 8*np.random.randn(data_num,1)\n", "\n", "print(\"X: \", X.shape)\n", "print(\"Y: \", Y.shape)\n", "\n", "# create regression model\n", "regr = linear_model.LinearRegression()\n", "regr.fit(X, Y)\n", "\n", "a, b = np.squeeze(regr.coef_), np.squeeze(regr.intercept_)\n", "\n", "print(\"a = %f, b = %f\" % (a, b))\n", "\n", "x_min = np.min(X)\n", "x_max = np.max(X)\n", "y_min = a * x_min + b\n", "y_max = a * x_max + b\n", "\n", "plt.scatter(X, Y)\n", "plt.plot([x_min, x_max], [y_min, y_max], 'r')\n", "plt.xlabel(\"X\")\n", "plt.ylabel(\"Y\")\n", "plt.savefig(\"fig-res-sklearn_linear_fitting.pdf\")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 7. 如何使用sklearn拟合多项式函数?" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([800., 90., -20.])" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Fitting polynomial functions\n", "\n", "from sklearn.preprocessing import PolynomialFeatures\n", "from sklearn.linear_model import LinearRegression\n", "from sklearn.pipeline import Pipeline\n", "\n", "t = np.array([2, 4, 6, 8])\n", "\n", "pa = -20\n", "pb = 90\n", "pc = 800\n", "\n", "y = pa*t**2 + pb*t + pc\n", "\n", "model = Pipeline([('poly', PolynomialFeatures(degree=2)),\n", " ('linear', LinearRegression(fit_intercept=False))])\n", "model = model.fit(t[:, np.newaxis], y)\n", "model.named_steps['linear'].coef_\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 参考资料\n", "* [梯度下降法](https://blog.csdn.net/u010402786/article/details/51188876)\n", "* [如何理解最小二乘法?](https://blog.csdn.net/ccnt_2012/article/details/81127117)\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "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.7.9" } }, "nbformat": 4, "nbformat_minor": 2 }