You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

1-Least_squares.ipynb 192 kB

4 years ago
4 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642
  1. {
  2. "cells": [
  3. {
  4. "cell_type": "markdown",
  5. "metadata": {},
  6. "source": [
  7. "# 最小二乘\n",
  8. "\n",
  9. "## 1. 最小二乘的基本原理\n",
  10. "\n",
  11. "最小二乘法(Least Squares)是一种数学优化技术,它通过最小化误差的平方和找到一组数据的最佳函数匹配, 最小二乘法通常用于曲线拟合、求解模型。很多其他的优化问题也可通过最小化能量或最大化熵用最小二乘形式表达。\n",
  12. "\n",
  13. "![ls_theory](images/least_squares.png)\n",
  14. "\n",
  15. "最小二乘原理的一般形式为:\n",
  16. "$$\n",
  17. "L = \\sum (V_{obv} - V_{target}(\\theta))^2\n",
  18. "$$\n",
  19. "其中\n",
  20. "* $V_{obv}$是观测的多组样本值\n",
  21. "* $V_{target}$是假设拟合函数的输出值\n",
  22. "* $\\theta$为构造模型的参数\n",
  23. "* $L$是目标函数\n",
  24. "\n",
  25. "如果通过调整模型参数$\\theta$,使得$L$下降到最小则表明,拟合函数与观测最为接近,也就是找到了最优的模型。\n"
  26. ]
  27. },
  28. {
  29. "cell_type": "markdown",
  30. "metadata": {},
  31. "source": [
  32. "### 1.1 示例\n",
  33. "\n",
  34. "假设我们有下面的一些观测数据,我们希望找到他们内在的规律。"
  35. ]
  36. },
  37. {
  38. "cell_type": "code",
  39. "execution_count": 1,
  40. "metadata": {},
  41. "outputs": [
  42. {
  43. "data": {
  44. "image/png": "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\n",
  45. "text/plain": [
  46. "<Figure size 432x288 with 1 Axes>"
  47. ]
  48. },
  49. "metadata": {
  50. "needs_background": "light"
  51. },
  52. "output_type": "display_data"
  53. }
  54. ],
  55. "source": [
  56. "%matplotlib inline\n",
  57. "\n",
  58. "import matplotlib.pyplot as plt\n",
  59. "import numpy as np\n",
  60. "\n",
  61. "# 生成数据\n",
  62. "data_num = 50\n",
  63. "X = np.random.rand(data_num, 1)*10\n",
  64. "Y = X * 3 + 4 + 4*np.random.randn(data_num,1)\n",
  65. "\n",
  66. "# 画出数据的分布\n",
  67. "plt.scatter(X, Y)\n",
  68. "plt.xlabel(\"X\")\n",
  69. "plt.ylabel(\"Y\")\n",
  70. "plt.show()"
  71. ]
  72. },
  73. {
  74. "cell_type": "markdown",
  75. "metadata": {},
  76. "source": [
  77. "### 1.2 数学原理\n",
  78. "有$N$个观测数据为:\n",
  79. "$$\n",
  80. "\\mathbf{X} = \\{x_1, x_2, ..., x_N \\} \\\\\n",
  81. "\\mathbf{Y} = \\{y_1, y_2, ..., y_N \\}\n",
  82. "$$\n",
  83. "其中$\\mathbf{X}$为自变量,$\\mathbf{Y}$为因变量。\n",
  84. "\n",
  85. "我们希望找到一个模型能够解释这些数据,假设使用最简单的线性模型来拟合数据:\n",
  86. "$$\n",
  87. "y = ax + b\n",
  88. "$$\n",
  89. "那么问题就变成求解参数$a$, $b$能够使得模型输出尽可能和观测数据有比较小的误差。\n",
  90. "\n",
  91. "如何构建函数来评估模型输出与观测数据之间的误差是一个关键问题,这里我们使用观测数据与模型输出的平方和来作为评估函数(也被称为损失函数Loss function):\n",
  92. "$$\n",
  93. "L = \\sum_{i=1}^{N} \\{y_i - (a x_i + b)\\}^2 \\\\\n",
  94. "L = \\sum_{i=1}^{N} (y_i - a x_i - b)^2 \n",
  95. "$$\n",
  96. "\n",
  97. "使误差函数最小,那么我们就可以求出模型的参数:\n",
  98. "$$\n",
  99. "\\frac{\\partial L}{\\partial a} = -2 \\sum_{i=1}^{N} (y_i - a x_i - b) x_i \\\\\n",
  100. "\\frac{\\partial L}{\\partial b} = -2 \\sum_{i=1}^{N} (y_i - a x_i - b)\n",
  101. "$$\n",
  102. "\n",
  103. "即当偏微分为0时,误差函数为最小,因此我们可以得到:\n",
  104. "$$\n",
  105. "-2 \\sum_{i=1}^{N} (y_i - a x_i - b) x_i = 0 \\\\\n",
  106. "-2 \\sum_{i=1}^{N} (y_i - a x_i - b) = 0 \\\\\n",
  107. "$$\n",
  108. "\n",
  109. "将上式调整一下顺序可以得到:\n",
  110. "$$\n",
  111. "a \\sum x_i^2 + b \\sum x_i = \\sum y_i x_i \\\\\n",
  112. "a \\sum x_i + b N = \\sum y_i\n",
  113. "$$\n",
  114. "\n",
  115. "上式中$\\sum x_i^2$, $\\sum x_i$, $\\sum y_i$, $\\sum y_i x_i$都是已知的数据,而参数$a$, $b$是我们想要求得未知参数。通过求解二元一次方程组,我们即可求出模型的最优参数。"
  116. ]
  117. },
  118. {
  119. "cell_type": "markdown",
  120. "metadata": {},
  121. "source": [
  122. "### 1.3 求解程序"
  123. ]
  124. },
  125. {
  126. "cell_type": "code",
  127. "execution_count": 2,
  128. "metadata": {},
  129. "outputs": [
  130. {
  131. "name": "stdout",
  132. "output_type": "stream",
  133. "text": [
  134. "a = 2.985262, b = 3.577796\n"
  135. ]
  136. },
  137. {
  138. "data": {
  139. "image/png": "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\n",
  140. "text/plain": [
  141. "<Figure size 432x288 with 1 Axes>"
  142. ]
  143. },
  144. "metadata": {
  145. "needs_background": "light"
  146. },
  147. "output_type": "display_data"
  148. }
  149. ],
  150. "source": [
  151. "N = X.shape[0]\n",
  152. "\n",
  153. "S_X2 = np.sum(X*X)\n",
  154. "S_X = np.sum(X)\n",
  155. "S_XY = np.sum(X*Y)\n",
  156. "S_Y = np.sum(Y)\n",
  157. "\n",
  158. "A1 = np.array([[S_X2, S_X], \n",
  159. " [S_X, N]])\n",
  160. "B1 = np.array([S_XY, S_Y])\n",
  161. "\n",
  162. "# numpy.linalg模块包含线性代数的函数。\n",
  163. "# 使用这个模块,可以计算逆矩阵、求特征值、解线性方程组以及求解行列式等。\n",
  164. "coeff = np.linalg.inv(A1).dot(B1)\n",
  165. "\n",
  166. "print('a = %f, b = %f' % (coeff[0], coeff[1]))\n",
  167. "\n",
  168. "x_min = np.min(X)\n",
  169. "x_max = np.max(X)\n",
  170. "y_min = coeff[0] * x_min + coeff[1]\n",
  171. "y_max = coeff[0] * x_max + coeff[1]\n",
  172. "\n",
  173. "plt.scatter(X, Y, label='original data')\n",
  174. "plt.plot([x_min, x_max], [y_min, y_max], 'r', label='model')\n",
  175. "plt.legend()\n",
  176. "plt.show()"
  177. ]
  178. },
  179. {
  180. "cell_type": "markdown",
  181. "metadata": {},
  182. "source": [
  183. "## 2. 如何使用迭代的方法求出模型参数\n",
  184. "\n",
  185. "当数据比较多的时候,或者模型比较复杂,无法直接使用解析的方式求出模型参数。因此更为常用的方式是,通过迭代的方式逐步逼近模型的参数。\n",
  186. "\n",
  187. "### 2.1 梯度下降法\n",
  188. "在机器学习算法中,对于很多监督学习模型,需要对原始的模型构建损失函数,接下来便是通过优化算法对损失函数进行优化,以便寻找到最优的参数。在求解机器学习参数的优化算法中,使用较多的是基于梯度下降的优化算法(Gradient Descent, GD)。\n",
  189. "\n",
  190. "梯度下降法有很多优点,其中最主要的优点是,**在梯度下降法的求解过程中只需求解损失函数的一阶导数,计算的代价比较小,这使得梯度下降法能在很多大规模数据集上得到应用。**\n",
  191. "\n",
  192. "梯度下降法的含义是通过当前点的梯度方向寻找到新的迭代点。梯度下降法的基本思想可以类比为一个下山的过程。假设这样一个场景:\n",
  193. "* 一个人被困在山上,需要从山上下来(i.e. 找到山的最低点,也就是山谷)。\n",
  194. "* 但此时山上的浓雾很大,导致可视度很低。因此,下山的路径就无法全部确定,他必须利用自己周围的信息去找到下山的路径。\n",
  195. "* 这个时候,他就可以利用梯度下降算法来帮助自己下山。\n",
  196. " - 具体来说就是,以他当前的所处的位置为基准,寻找这个位置最陡峭的地方,然后朝着山的高度下降的地方走\n",
  197. " - 然后每走一段距离,都反复采用同一个方法,最后就能成功的抵达山谷。\n",
  198. "\n",
  199. "\n",
  200. "一般情况下,这座山最陡峭的地方是无法通过肉眼立马观察出来的,而是需要一个工具来测量;同时,这个人此时正好拥有测量出最陡峭方向的能力。所以,此人每走一段距离,都需要一段时间来测量所在位置最陡峭的方向,这是比较耗时的。那么为了在太阳下山之前到达山底,就要尽可能的减少测量方向的次数。这是一个两难的选择,如果测量的频繁,可以保证下山的方向是绝对正确的,但又非常耗时;如果测量的过少,又有偏离轨道的风险。所以需要找到一个合适的测量方向的频率,来确保下山的方向不错误,同时又不至于耗时太多!\n",
  201. "\n",
  202. "\n",
  203. "![gradient_descent](images/gradient_descent.png)\n",
  204. "\n",
  205. "如上图所示,得到了最优解。$x$,$y$表示的是$\\theta_0$和$\\theta_1$,$z$方向表示的是花费函数,很明显出发点不同,最后到达的收敛点可能不一样。当然如果是碗状的,那么收敛点就应该是一样的。\n",
  206. "\n",
  207. "对于最小二乘的损失函数\n",
  208. "$$\n",
  209. "L = \\sum_{i=1}^{N} (y_i - a x_i - b)^2\n",
  210. "$$\n",
  211. "\n",
  212. "我们更新的策略是:\n",
  213. "$$\n",
  214. "\\theta^1 = \\theta^0 - \\eta \\triangledown L(\\theta)\n",
  215. "$$\n",
  216. "其中$\\theta$代表了模型中的参数,例如$a$, $b$\n",
  217. "\n",
  218. "此公式的意义是:$L$是关于$\\theta$的一个函数,我们当前所处的位置为$\\theta_0$点,要从这个点走到L的最小值点,也就是山底。首先我们先确定前进的方向,也就是梯度的反向,然后走一段距离的步长,也就是$\\eta$,走完这个段步长,就到达了$\\theta_1$这个点!\n",
  219. "\n",
  220. "更新的策略是:\n",
  221. "\n",
  222. "$$\n",
  223. "a^1 = a^0 + 2 \\eta [ y - (ax+b)]*x \\\\\n",
  224. "b^1 = b^0 + 2 \\eta [ y - (ax+b)] \n",
  225. "$$\n",
  226. "\n",
  227. "下面就这个公式的几个常见的疑问:\n",
  228. "\n",
  229. "* **$\\eta$是什么含义?**\n",
  230. "$\\eta$在梯度下降算法中被称作为学习率或者步长,意味着我们可以通过$\\eta$来控制每一步走的距离,以保证不要步子跨的太大,错过了最低点。同时也要保证不要走的太慢,导致太阳下山了,还没有走到山下。所以$\\eta$的选择在梯度下降法中往往是很重要的。\n",
  231. "![gd_stepsize](images/gd_stepsize.png)\n",
  232. "\n",
  233. "* **为什么要梯度要乘以一个负号?**\n",
  234. "梯度前加一个负号,就意味着朝着梯度相反的方向前进!梯度的方向实际就是函数在此点上升最快的方向,而我们需要朝着下降最快的方向走,自然就是负的梯度的方向,所以此处需要加上负号。\n",
  235. "\n"
  236. ]
  237. },
  238. {
  239. "cell_type": "markdown",
  240. "metadata": {},
  241. "source": [
  242. "### 2.2 示例代码"
  243. ]
  244. },
  245. {
  246. "cell_type": "code",
  247. "execution_count": 3,
  248. "metadata": {},
  249. "outputs": [
  250. {
  251. "name": "stdout",
  252. "output_type": "stream",
  253. "text": [
  254. "epoch 0: loss = 961.232595, a = 3.042831, b = 1.277951\n",
  255. "epoch 100: loss = 780.212993, a = 3.110374, b = 3.224871\n",
  256. "epoch 200: loss = 797.359161, a = 2.879130, b = 3.475558\n",
  257. "epoch 300: loss = 845.492885, a = 2.799842, b = 3.518333\n",
  258. "epoch 400: loss = 835.064012, a = 2.813343, b = 3.517065\n"
  259. ]
  260. },
  261. {
  262. "data": {
  263. "image/png": "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\n",
  264. "text/plain": [
  265. "<Figure size 432x288 with 1 Axes>"
  266. ]
  267. },
  268. "metadata": {
  269. "needs_background": "light"
  270. },
  271. "output_type": "display_data"
  272. }
  273. ],
  274. "source": [
  275. "import random\n",
  276. "\n",
  277. "n_epoch = 500 # epoch size\n",
  278. "a, b = 1, 1 # initial parameters\n",
  279. "epsilon = 0.001 # learning rate\n",
  280. "\n",
  281. "for i in range(n_epoch):\n",
  282. " data_idx = list(range(N))\n",
  283. " random.shuffle(data_idx)\n",
  284. " \n",
  285. " for j in data_idx:\n",
  286. " a = a + epsilon*2*(Y[j] - a*X[j] - b)*X[j]\n",
  287. " b = b + epsilon*2*(Y[j] - a*X[j] - b)\n",
  288. "\n",
  289. " L = 0\n",
  290. " for j in range(N):\n",
  291. " L = L + (Y[j]-a*X[j]-b)**2\n",
  292. " \n",
  293. " if i % 100 == 0:\n",
  294. " print(\"epoch %4d: loss = %f, a = %f, b = %f\" % (i, L, a, b))\n",
  295. " \n",
  296. "x_min = np.min(X)\n",
  297. "x_max = np.max(X)\n",
  298. "y_min = a * x_min + b\n",
  299. "y_max = a * x_max + b\n",
  300. "\n",
  301. "plt.scatter(X, Y, label='original data')\n",
  302. "plt.plot([x_min, x_max], [y_min, y_max], 'r', label='model')\n",
  303. "plt.legend()\n",
  304. "plt.show()"
  305. ]
  306. },
  307. {
  308. "cell_type": "markdown",
  309. "metadata": {},
  310. "source": [
  311. "## 3. 如何可视化迭代过程"
  312. ]
  313. },
  314. {
  315. "cell_type": "code",
  316. "execution_count": 4,
  317. "metadata": {},
  318. "outputs": [
  319. {
  320. "data": {
  321. "application/javascript": [
  322. "/* Put everything inside the global mpl namespace */\n",
  323. "/* global mpl */\n",
  324. "window.mpl = {};\n",
  325. "\n",
  326. "mpl.get_websocket_type = function () {\n",
  327. " if (typeof WebSocket !== 'undefined') {\n",
  328. " return WebSocket;\n",
  329. " } else if (typeof MozWebSocket !== 'undefined') {\n",
  330. " return MozWebSocket;\n",
  331. " } else {\n",
  332. " alert(\n",
  333. " 'Your browser does not have WebSocket support. ' +\n",
  334. " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
  335. " 'Firefox 4 and 5 are also supported but you ' +\n",
  336. " 'have to enable WebSockets in about:config.'\n",
  337. " );\n",
  338. " }\n",
  339. "};\n",
  340. "\n",
  341. "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n",
  342. " this.id = figure_id;\n",
  343. "\n",
  344. " this.ws = websocket;\n",
  345. "\n",
  346. " this.supports_binary = this.ws.binaryType !== undefined;\n",
  347. "\n",
  348. " if (!this.supports_binary) {\n",
  349. " var warnings = document.getElementById('mpl-warnings');\n",
  350. " if (warnings) {\n",
  351. " warnings.style.display = 'block';\n",
  352. " warnings.textContent =\n",
  353. " 'This browser does not support binary websocket messages. ' +\n",
  354. " 'Performance may be slow.';\n",
  355. " }\n",
  356. " }\n",
  357. "\n",
  358. " this.imageObj = new Image();\n",
  359. "\n",
  360. " this.context = undefined;\n",
  361. " this.message = undefined;\n",
  362. " this.canvas = undefined;\n",
  363. " this.rubberband_canvas = undefined;\n",
  364. " this.rubberband_context = undefined;\n",
  365. " this.format_dropdown = undefined;\n",
  366. "\n",
  367. " this.image_mode = 'full';\n",
  368. "\n",
  369. " this.root = document.createElement('div');\n",
  370. " this.root.setAttribute('style', 'display: inline-block');\n",
  371. " this._root_extra_style(this.root);\n",
  372. "\n",
  373. " parent_element.appendChild(this.root);\n",
  374. "\n",
  375. " this._init_header(this);\n",
  376. " this._init_canvas(this);\n",
  377. " this._init_toolbar(this);\n",
  378. "\n",
  379. " var fig = this;\n",
  380. "\n",
  381. " this.waiting = false;\n",
  382. "\n",
  383. " this.ws.onopen = function () {\n",
  384. " fig.send_message('supports_binary', { value: fig.supports_binary });\n",
  385. " fig.send_message('send_image_mode', {});\n",
  386. " if (fig.ratio !== 1) {\n",
  387. " fig.send_message('set_dpi_ratio', { dpi_ratio: fig.ratio });\n",
  388. " }\n",
  389. " fig.send_message('refresh', {});\n",
  390. " };\n",
  391. "\n",
  392. " this.imageObj.onload = function () {\n",
  393. " if (fig.image_mode === 'full') {\n",
  394. " // Full images could contain transparency (where diff images\n",
  395. " // almost always do), so we need to clear the canvas so that\n",
  396. " // there is no ghosting.\n",
  397. " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
  398. " }\n",
  399. " fig.context.drawImage(fig.imageObj, 0, 0);\n",
  400. " };\n",
  401. "\n",
  402. " this.imageObj.onunload = function () {\n",
  403. " fig.ws.close();\n",
  404. " };\n",
  405. "\n",
  406. " this.ws.onmessage = this._make_on_message_function(this);\n",
  407. "\n",
  408. " this.ondownload = ondownload;\n",
  409. "};\n",
  410. "\n",
  411. "mpl.figure.prototype._init_header = function () {\n",
  412. " var titlebar = document.createElement('div');\n",
  413. " titlebar.classList =\n",
  414. " 'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n",
  415. " var titletext = document.createElement('div');\n",
  416. " titletext.classList = 'ui-dialog-title';\n",
  417. " titletext.setAttribute(\n",
  418. " 'style',\n",
  419. " 'width: 100%; text-align: center; padding: 3px;'\n",
  420. " );\n",
  421. " titlebar.appendChild(titletext);\n",
  422. " this.root.appendChild(titlebar);\n",
  423. " this.header = titletext;\n",
  424. "};\n",
  425. "\n",
  426. "mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n",
  427. "\n",
  428. "mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n",
  429. "\n",
  430. "mpl.figure.prototype._init_canvas = function () {\n",
  431. " var fig = this;\n",
  432. "\n",
  433. " var canvas_div = (this.canvas_div = document.createElement('div'));\n",
  434. " canvas_div.setAttribute(\n",
  435. " 'style',\n",
  436. " 'border: 1px solid #ddd;' +\n",
  437. " 'box-sizing: content-box;' +\n",
  438. " 'clear: both;' +\n",
  439. " 'min-height: 1px;' +\n",
  440. " 'min-width: 1px;' +\n",
  441. " 'outline: 0;' +\n",
  442. " 'overflow: hidden;' +\n",
  443. " 'position: relative;' +\n",
  444. " 'resize: both;'\n",
  445. " );\n",
  446. "\n",
  447. " function on_keyboard_event_closure(name) {\n",
  448. " return function (event) {\n",
  449. " return fig.key_event(event, name);\n",
  450. " };\n",
  451. " }\n",
  452. "\n",
  453. " canvas_div.addEventListener(\n",
  454. " 'keydown',\n",
  455. " on_keyboard_event_closure('key_press')\n",
  456. " );\n",
  457. " canvas_div.addEventListener(\n",
  458. " 'keyup',\n",
  459. " on_keyboard_event_closure('key_release')\n",
  460. " );\n",
  461. "\n",
  462. " this._canvas_extra_style(canvas_div);\n",
  463. " this.root.appendChild(canvas_div);\n",
  464. "\n",
  465. " var canvas = (this.canvas = document.createElement('canvas'));\n",
  466. " canvas.classList.add('mpl-canvas');\n",
  467. " canvas.setAttribute('style', 'box-sizing: content-box;');\n",
  468. "\n",
  469. " this.context = canvas.getContext('2d');\n",
  470. "\n",
  471. " var backingStore =\n",
  472. " this.context.backingStorePixelRatio ||\n",
  473. " this.context.webkitBackingStorePixelRatio ||\n",
  474. " this.context.mozBackingStorePixelRatio ||\n",
  475. " this.context.msBackingStorePixelRatio ||\n",
  476. " this.context.oBackingStorePixelRatio ||\n",
  477. " this.context.backingStorePixelRatio ||\n",
  478. " 1;\n",
  479. "\n",
  480. " this.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
  481. "\n",
  482. " var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n",
  483. " 'canvas'\n",
  484. " ));\n",
  485. " rubberband_canvas.setAttribute(\n",
  486. " 'style',\n",
  487. " 'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n",
  488. " );\n",
  489. "\n",
  490. " // Apply a ponyfill if ResizeObserver is not implemented by browser.\n",
  491. " if (this.ResizeObserver === undefined) {\n",
  492. " if (window.ResizeObserver !== undefined) {\n",
  493. " this.ResizeObserver = window.ResizeObserver;\n",
  494. " } else {\n",
  495. " var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n",
  496. " this.ResizeObserver = obs.ResizeObserver;\n",
  497. " }\n",
  498. " }\n",
  499. "\n",
  500. " this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n",
  501. " var nentries = entries.length;\n",
  502. " for (var i = 0; i < nentries; i++) {\n",
  503. " var entry = entries[i];\n",
  504. " var width, height;\n",
  505. " if (entry.contentBoxSize) {\n",
  506. " if (entry.contentBoxSize instanceof Array) {\n",
  507. " // Chrome 84 implements new version of spec.\n",
  508. " width = entry.contentBoxSize[0].inlineSize;\n",
  509. " height = entry.contentBoxSize[0].blockSize;\n",
  510. " } else {\n",
  511. " // Firefox implements old version of spec.\n",
  512. " width = entry.contentBoxSize.inlineSize;\n",
  513. " height = entry.contentBoxSize.blockSize;\n",
  514. " }\n",
  515. " } else {\n",
  516. " // Chrome <84 implements even older version of spec.\n",
  517. " width = entry.contentRect.width;\n",
  518. " height = entry.contentRect.height;\n",
  519. " }\n",
  520. "\n",
  521. " // Keep the size of the canvas and rubber band canvas in sync with\n",
  522. " // the canvas container.\n",
  523. " if (entry.devicePixelContentBoxSize) {\n",
  524. " // Chrome 84 implements new version of spec.\n",
  525. " canvas.setAttribute(\n",
  526. " 'width',\n",
  527. " entry.devicePixelContentBoxSize[0].inlineSize\n",
  528. " );\n",
  529. " canvas.setAttribute(\n",
  530. " 'height',\n",
  531. " entry.devicePixelContentBoxSize[0].blockSize\n",
  532. " );\n",
  533. " } else {\n",
  534. " canvas.setAttribute('width', width * fig.ratio);\n",
  535. " canvas.setAttribute('height', height * fig.ratio);\n",
  536. " }\n",
  537. " canvas.setAttribute(\n",
  538. " 'style',\n",
  539. " 'width: ' + width + 'px; height: ' + height + 'px;'\n",
  540. " );\n",
  541. "\n",
  542. " rubberband_canvas.setAttribute('width', width);\n",
  543. " rubberband_canvas.setAttribute('height', height);\n",
  544. "\n",
  545. " // And update the size in Python. We ignore the initial 0/0 size\n",
  546. " // that occurs as the element is placed into the DOM, which should\n",
  547. " // otherwise not happen due to the minimum size styling.\n",
  548. " if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n",
  549. " fig.request_resize(width, height);\n",
  550. " }\n",
  551. " }\n",
  552. " });\n",
  553. " this.resizeObserverInstance.observe(canvas_div);\n",
  554. "\n",
  555. " function on_mouse_event_closure(name) {\n",
  556. " return function (event) {\n",
  557. " return fig.mouse_event(event, name);\n",
  558. " };\n",
  559. " }\n",
  560. "\n",
  561. " rubberband_canvas.addEventListener(\n",
  562. " 'mousedown',\n",
  563. " on_mouse_event_closure('button_press')\n",
  564. " );\n",
  565. " rubberband_canvas.addEventListener(\n",
  566. " 'mouseup',\n",
  567. " on_mouse_event_closure('button_release')\n",
  568. " );\n",
  569. " rubberband_canvas.addEventListener(\n",
  570. " 'dblclick',\n",
  571. " on_mouse_event_closure('dblclick')\n",
  572. " );\n",
  573. " // Throttle sequential mouse events to 1 every 20ms.\n",
  574. " rubberband_canvas.addEventListener(\n",
  575. " 'mousemove',\n",
  576. " on_mouse_event_closure('motion_notify')\n",
  577. " );\n",
  578. "\n",
  579. " rubberband_canvas.addEventListener(\n",
  580. " 'mouseenter',\n",
  581. " on_mouse_event_closure('figure_enter')\n",
  582. " );\n",
  583. " rubberband_canvas.addEventListener(\n",
  584. " 'mouseleave',\n",
  585. " on_mouse_event_closure('figure_leave')\n",
  586. " );\n",
  587. "\n",
  588. " canvas_div.addEventListener('wheel', function (event) {\n",
  589. " if (event.deltaY < 0) {\n",
  590. " event.step = 1;\n",
  591. " } else {\n",
  592. " event.step = -1;\n",
  593. " }\n",
  594. " on_mouse_event_closure('scroll')(event);\n",
  595. " });\n",
  596. "\n",
  597. " canvas_div.appendChild(canvas);\n",
  598. " canvas_div.appendChild(rubberband_canvas);\n",
  599. "\n",
  600. " this.rubberband_context = rubberband_canvas.getContext('2d');\n",
  601. " this.rubberband_context.strokeStyle = '#000000';\n",
  602. "\n",
  603. " this._resize_canvas = function (width, height, forward) {\n",
  604. " if (forward) {\n",
  605. " canvas_div.style.width = width + 'px';\n",
  606. " canvas_div.style.height = height + 'px';\n",
  607. " }\n",
  608. " };\n",
  609. "\n",
  610. " // Disable right mouse context menu.\n",
  611. " this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n",
  612. " event.preventDefault();\n",
  613. " return false;\n",
  614. " });\n",
  615. "\n",
  616. " function set_focus() {\n",
  617. " canvas.focus();\n",
  618. " canvas_div.focus();\n",
  619. " }\n",
  620. "\n",
  621. " window.setTimeout(set_focus, 100);\n",
  622. "};\n",
  623. "\n",
  624. "mpl.figure.prototype._init_toolbar = function () {\n",
  625. " var fig = this;\n",
  626. "\n",
  627. " var toolbar = document.createElement('div');\n",
  628. " toolbar.classList = 'mpl-toolbar';\n",
  629. " this.root.appendChild(toolbar);\n",
  630. "\n",
  631. " function on_click_closure(name) {\n",
  632. " return function (_event) {\n",
  633. " return fig.toolbar_button_onclick(name);\n",
  634. " };\n",
  635. " }\n",
  636. "\n",
  637. " function on_mouseover_closure(tooltip) {\n",
  638. " return function (event) {\n",
  639. " if (!event.currentTarget.disabled) {\n",
  640. " return fig.toolbar_button_onmouseover(tooltip);\n",
  641. " }\n",
  642. " };\n",
  643. " }\n",
  644. "\n",
  645. " fig.buttons = {};\n",
  646. " var buttonGroup = document.createElement('div');\n",
  647. " buttonGroup.classList = 'mpl-button-group';\n",
  648. " for (var toolbar_ind in mpl.toolbar_items) {\n",
  649. " var name = mpl.toolbar_items[toolbar_ind][0];\n",
  650. " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
  651. " var image = mpl.toolbar_items[toolbar_ind][2];\n",
  652. " var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
  653. "\n",
  654. " if (!name) {\n",
  655. " /* Instead of a spacer, we start a new button group. */\n",
  656. " if (buttonGroup.hasChildNodes()) {\n",
  657. " toolbar.appendChild(buttonGroup);\n",
  658. " }\n",
  659. " buttonGroup = document.createElement('div');\n",
  660. " buttonGroup.classList = 'mpl-button-group';\n",
  661. " continue;\n",
  662. " }\n",
  663. "\n",
  664. " var button = (fig.buttons[name] = document.createElement('button'));\n",
  665. " button.classList = 'mpl-widget';\n",
  666. " button.setAttribute('role', 'button');\n",
  667. " button.setAttribute('aria-disabled', 'false');\n",
  668. " button.addEventListener('click', on_click_closure(method_name));\n",
  669. " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n",
  670. "\n",
  671. " var icon_img = document.createElement('img');\n",
  672. " icon_img.src = '_images/' + image + '.png';\n",
  673. " icon_img.srcset = '_images/' + image + '_large.png 2x';\n",
  674. " icon_img.alt = tooltip;\n",
  675. " button.appendChild(icon_img);\n",
  676. "\n",
  677. " buttonGroup.appendChild(button);\n",
  678. " }\n",
  679. "\n",
  680. " if (buttonGroup.hasChildNodes()) {\n",
  681. " toolbar.appendChild(buttonGroup);\n",
  682. " }\n",
  683. "\n",
  684. " var fmt_picker = document.createElement('select');\n",
  685. " fmt_picker.classList = 'mpl-widget';\n",
  686. " toolbar.appendChild(fmt_picker);\n",
  687. " this.format_dropdown = fmt_picker;\n",
  688. "\n",
  689. " for (var ind in mpl.extensions) {\n",
  690. " var fmt = mpl.extensions[ind];\n",
  691. " var option = document.createElement('option');\n",
  692. " option.selected = fmt === mpl.default_extension;\n",
  693. " option.innerHTML = fmt;\n",
  694. " fmt_picker.appendChild(option);\n",
  695. " }\n",
  696. "\n",
  697. " var status_bar = document.createElement('span');\n",
  698. " status_bar.classList = 'mpl-message';\n",
  699. " toolbar.appendChild(status_bar);\n",
  700. " this.message = status_bar;\n",
  701. "};\n",
  702. "\n",
  703. "mpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n",
  704. " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
  705. " // which will in turn request a refresh of the image.\n",
  706. " this.send_message('resize', { width: x_pixels, height: y_pixels });\n",
  707. "};\n",
  708. "\n",
  709. "mpl.figure.prototype.send_message = function (type, properties) {\n",
  710. " properties['type'] = type;\n",
  711. " properties['figure_id'] = this.id;\n",
  712. " this.ws.send(JSON.stringify(properties));\n",
  713. "};\n",
  714. "\n",
  715. "mpl.figure.prototype.send_draw_message = function () {\n",
  716. " if (!this.waiting) {\n",
  717. " this.waiting = true;\n",
  718. " this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n",
  719. " }\n",
  720. "};\n",
  721. "\n",
  722. "mpl.figure.prototype.handle_save = function (fig, _msg) {\n",
  723. " var format_dropdown = fig.format_dropdown;\n",
  724. " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
  725. " fig.ondownload(fig, format);\n",
  726. "};\n",
  727. "\n",
  728. "mpl.figure.prototype.handle_resize = function (fig, msg) {\n",
  729. " var size = msg['size'];\n",
  730. " if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n",
  731. " fig._resize_canvas(size[0], size[1], msg['forward']);\n",
  732. " fig.send_message('refresh', {});\n",
  733. " }\n",
  734. "};\n",
  735. "\n",
  736. "mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n",
  737. " var x0 = msg['x0'] / fig.ratio;\n",
  738. " var y0 = (fig.canvas.height - msg['y0']) / fig.ratio;\n",
  739. " var x1 = msg['x1'] / fig.ratio;\n",
  740. " var y1 = (fig.canvas.height - msg['y1']) / fig.ratio;\n",
  741. " x0 = Math.floor(x0) + 0.5;\n",
  742. " y0 = Math.floor(y0) + 0.5;\n",
  743. " x1 = Math.floor(x1) + 0.5;\n",
  744. " y1 = Math.floor(y1) + 0.5;\n",
  745. " var min_x = Math.min(x0, x1);\n",
  746. " var min_y = Math.min(y0, y1);\n",
  747. " var width = Math.abs(x1 - x0);\n",
  748. " var height = Math.abs(y1 - y0);\n",
  749. "\n",
  750. " fig.rubberband_context.clearRect(\n",
  751. " 0,\n",
  752. " 0,\n",
  753. " fig.canvas.width / fig.ratio,\n",
  754. " fig.canvas.height / fig.ratio\n",
  755. " );\n",
  756. "\n",
  757. " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
  758. "};\n",
  759. "\n",
  760. "mpl.figure.prototype.handle_figure_label = function (fig, msg) {\n",
  761. " // Updates the figure title.\n",
  762. " fig.header.textContent = msg['label'];\n",
  763. "};\n",
  764. "\n",
  765. "mpl.figure.prototype.handle_cursor = function (fig, msg) {\n",
  766. " var cursor = msg['cursor'];\n",
  767. " switch (cursor) {\n",
  768. " case 0:\n",
  769. " cursor = 'pointer';\n",
  770. " break;\n",
  771. " case 1:\n",
  772. " cursor = 'default';\n",
  773. " break;\n",
  774. " case 2:\n",
  775. " cursor = 'crosshair';\n",
  776. " break;\n",
  777. " case 3:\n",
  778. " cursor = 'move';\n",
  779. " break;\n",
  780. " }\n",
  781. " fig.rubberband_canvas.style.cursor = cursor;\n",
  782. "};\n",
  783. "\n",
  784. "mpl.figure.prototype.handle_message = function (fig, msg) {\n",
  785. " fig.message.textContent = msg['message'];\n",
  786. "};\n",
  787. "\n",
  788. "mpl.figure.prototype.handle_draw = function (fig, _msg) {\n",
  789. " // Request the server to send over a new figure.\n",
  790. " fig.send_draw_message();\n",
  791. "};\n",
  792. "\n",
  793. "mpl.figure.prototype.handle_image_mode = function (fig, msg) {\n",
  794. " fig.image_mode = msg['mode'];\n",
  795. "};\n",
  796. "\n",
  797. "mpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n",
  798. " for (var key in msg) {\n",
  799. " if (!(key in fig.buttons)) {\n",
  800. " continue;\n",
  801. " }\n",
  802. " fig.buttons[key].disabled = !msg[key];\n",
  803. " fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n",
  804. " }\n",
  805. "};\n",
  806. "\n",
  807. "mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n",
  808. " if (msg['mode'] === 'PAN') {\n",
  809. " fig.buttons['Pan'].classList.add('active');\n",
  810. " fig.buttons['Zoom'].classList.remove('active');\n",
  811. " } else if (msg['mode'] === 'ZOOM') {\n",
  812. " fig.buttons['Pan'].classList.remove('active');\n",
  813. " fig.buttons['Zoom'].classList.add('active');\n",
  814. " } else {\n",
  815. " fig.buttons['Pan'].classList.remove('active');\n",
  816. " fig.buttons['Zoom'].classList.remove('active');\n",
  817. " }\n",
  818. "};\n",
  819. "\n",
  820. "mpl.figure.prototype.updated_canvas_event = function () {\n",
  821. " // Called whenever the canvas gets updated.\n",
  822. " this.send_message('ack', {});\n",
  823. "};\n",
  824. "\n",
  825. "// A function to construct a web socket function for onmessage handling.\n",
  826. "// Called in the figure constructor.\n",
  827. "mpl.figure.prototype._make_on_message_function = function (fig) {\n",
  828. " return function socket_on_message(evt) {\n",
  829. " if (evt.data instanceof Blob) {\n",
  830. " var img = evt.data;\n",
  831. " if (img.type !== 'image/png') {\n",
  832. " /* FIXME: We get \"Resource interpreted as Image but\n",
  833. " * transferred with MIME type text/plain:\" errors on\n",
  834. " * Chrome. But how to set the MIME type? It doesn't seem\n",
  835. " * to be part of the websocket stream */\n",
  836. " img.type = 'image/png';\n",
  837. " }\n",
  838. "\n",
  839. " /* Free the memory for the previous frames */\n",
  840. " if (fig.imageObj.src) {\n",
  841. " (window.URL || window.webkitURL).revokeObjectURL(\n",
  842. " fig.imageObj.src\n",
  843. " );\n",
  844. " }\n",
  845. "\n",
  846. " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
  847. " img\n",
  848. " );\n",
  849. " fig.updated_canvas_event();\n",
  850. " fig.waiting = false;\n",
  851. " return;\n",
  852. " } else if (\n",
  853. " typeof evt.data === 'string' &&\n",
  854. " evt.data.slice(0, 21) === 'data:image/png;base64'\n",
  855. " ) {\n",
  856. " fig.imageObj.src = evt.data;\n",
  857. " fig.updated_canvas_event();\n",
  858. " fig.waiting = false;\n",
  859. " return;\n",
  860. " }\n",
  861. "\n",
  862. " var msg = JSON.parse(evt.data);\n",
  863. " var msg_type = msg['type'];\n",
  864. "\n",
  865. " // Call the \"handle_{type}\" callback, which takes\n",
  866. " // the figure and JSON message as its only arguments.\n",
  867. " try {\n",
  868. " var callback = fig['handle_' + msg_type];\n",
  869. " } catch (e) {\n",
  870. " console.log(\n",
  871. " \"No handler for the '\" + msg_type + \"' message type: \",\n",
  872. " msg\n",
  873. " );\n",
  874. " return;\n",
  875. " }\n",
  876. "\n",
  877. " if (callback) {\n",
  878. " try {\n",
  879. " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
  880. " callback(fig, msg);\n",
  881. " } catch (e) {\n",
  882. " console.log(\n",
  883. " \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n",
  884. " e,\n",
  885. " e.stack,\n",
  886. " msg\n",
  887. " );\n",
  888. " }\n",
  889. " }\n",
  890. " };\n",
  891. "};\n",
  892. "\n",
  893. "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
  894. "mpl.findpos = function (e) {\n",
  895. " //this section is from http://www.quirksmode.org/js/events_properties.html\n",
  896. " var targ;\n",
  897. " if (!e) {\n",
  898. " e = window.event;\n",
  899. " }\n",
  900. " if (e.target) {\n",
  901. " targ = e.target;\n",
  902. " } else if (e.srcElement) {\n",
  903. " targ = e.srcElement;\n",
  904. " }\n",
  905. " if (targ.nodeType === 3) {\n",
  906. " // defeat Safari bug\n",
  907. " targ = targ.parentNode;\n",
  908. " }\n",
  909. "\n",
  910. " // pageX,Y are the mouse positions relative to the document\n",
  911. " var boundingRect = targ.getBoundingClientRect();\n",
  912. " var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n",
  913. " var y = e.pageY - (boundingRect.top + document.body.scrollTop);\n",
  914. "\n",
  915. " return { x: x, y: y };\n",
  916. "};\n",
  917. "\n",
  918. "/*\n",
  919. " * return a copy of an object with only non-object keys\n",
  920. " * we need this to avoid circular references\n",
  921. " * http://stackoverflow.com/a/24161582/3208463\n",
  922. " */\n",
  923. "function simpleKeys(original) {\n",
  924. " return Object.keys(original).reduce(function (obj, key) {\n",
  925. " if (typeof original[key] !== 'object') {\n",
  926. " obj[key] = original[key];\n",
  927. " }\n",
  928. " return obj;\n",
  929. " }, {});\n",
  930. "}\n",
  931. "\n",
  932. "mpl.figure.prototype.mouse_event = function (event, name) {\n",
  933. " var canvas_pos = mpl.findpos(event);\n",
  934. "\n",
  935. " if (name === 'button_press') {\n",
  936. " this.canvas.focus();\n",
  937. " this.canvas_div.focus();\n",
  938. " }\n",
  939. "\n",
  940. " var x = canvas_pos.x * this.ratio;\n",
  941. " var y = canvas_pos.y * this.ratio;\n",
  942. "\n",
  943. " this.send_message(name, {\n",
  944. " x: x,\n",
  945. " y: y,\n",
  946. " button: event.button,\n",
  947. " step: event.step,\n",
  948. " guiEvent: simpleKeys(event),\n",
  949. " });\n",
  950. "\n",
  951. " /* This prevents the web browser from automatically changing to\n",
  952. " * the text insertion cursor when the button is pressed. We want\n",
  953. " * to control all of the cursor setting manually through the\n",
  954. " * 'cursor' event from matplotlib */\n",
  955. " event.preventDefault();\n",
  956. " return false;\n",
  957. "};\n",
  958. "\n",
  959. "mpl.figure.prototype._key_event_extra = function (_event, _name) {\n",
  960. " // Handle any extra behaviour associated with a key event\n",
  961. "};\n",
  962. "\n",
  963. "mpl.figure.prototype.key_event = function (event, name) {\n",
  964. " // Prevent repeat events\n",
  965. " if (name === 'key_press') {\n",
  966. " if (event.key === this._key) {\n",
  967. " return;\n",
  968. " } else {\n",
  969. " this._key = event.key;\n",
  970. " }\n",
  971. " }\n",
  972. " if (name === 'key_release') {\n",
  973. " this._key = null;\n",
  974. " }\n",
  975. "\n",
  976. " var value = '';\n",
  977. " if (event.ctrlKey && event.key !== 'Control') {\n",
  978. " value += 'ctrl+';\n",
  979. " }\n",
  980. " else if (event.altKey && event.key !== 'Alt') {\n",
  981. " value += 'alt+';\n",
  982. " }\n",
  983. " else if (event.shiftKey && event.key !== 'Shift') {\n",
  984. " value += 'shift+';\n",
  985. " }\n",
  986. "\n",
  987. " value += 'k' + event.key;\n",
  988. "\n",
  989. " this._key_event_extra(event, name);\n",
  990. "\n",
  991. " this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n",
  992. " return false;\n",
  993. "};\n",
  994. "\n",
  995. "mpl.figure.prototype.toolbar_button_onclick = function (name) {\n",
  996. " if (name === 'download') {\n",
  997. " this.handle_save(this, null);\n",
  998. " } else {\n",
  999. " this.send_message('toolbar_button', { name: name });\n",
  1000. " }\n",
  1001. "};\n",
  1002. "\n",
  1003. "mpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n",
  1004. " this.message.textContent = tooltip;\n",
  1005. "};\n",
  1006. "\n",
  1007. "///////////////// REMAINING CONTENT GENERATED BY embed_js.py /////////////////\n",
  1008. "// prettier-ignore\n",
  1009. "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",
  1010. "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",
  1011. "\n",
  1012. "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
  1013. "\n",
  1014. "mpl.default_extension = \"png\";/* global mpl */\n",
  1015. "\n",
  1016. "var comm_websocket_adapter = function (comm) {\n",
  1017. " // Create a \"websocket\"-like object which calls the given IPython comm\n",
  1018. " // object with the appropriate methods. Currently this is a non binary\n",
  1019. " // socket, so there is still some room for performance tuning.\n",
  1020. " var ws = {};\n",
  1021. "\n",
  1022. " ws.binaryType = comm.kernel.ws.binaryType;\n",
  1023. " ws.readyState = comm.kernel.ws.readyState;\n",
  1024. " function updateReadyState(_event) {\n",
  1025. " if (comm.kernel.ws) {\n",
  1026. " ws.readyState = comm.kernel.ws.readyState;\n",
  1027. " } else {\n",
  1028. " ws.readyState = 3; // Closed state.\n",
  1029. " }\n",
  1030. " }\n",
  1031. " comm.kernel.ws.addEventListener('open', updateReadyState);\n",
  1032. " comm.kernel.ws.addEventListener('close', updateReadyState);\n",
  1033. " comm.kernel.ws.addEventListener('error', updateReadyState);\n",
  1034. "\n",
  1035. " ws.close = function () {\n",
  1036. " comm.close();\n",
  1037. " };\n",
  1038. " ws.send = function (m) {\n",
  1039. " //console.log('sending', m);\n",
  1040. " comm.send(m);\n",
  1041. " };\n",
  1042. " // Register the callback with on_msg.\n",
  1043. " comm.on_msg(function (msg) {\n",
  1044. " //console.log('receiving', msg['content']['data'], msg);\n",
  1045. " var data = msg['content']['data'];\n",
  1046. " if (data['blob'] !== undefined) {\n",
  1047. " data = {\n",
  1048. " data: new Blob(msg['buffers'], { type: data['blob'] }),\n",
  1049. " };\n",
  1050. " }\n",
  1051. " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
  1052. " ws.onmessage(data);\n",
  1053. " });\n",
  1054. " return ws;\n",
  1055. "};\n",
  1056. "\n",
  1057. "mpl.mpl_figure_comm = function (comm, msg) {\n",
  1058. " // This is the function which gets called when the mpl process\n",
  1059. " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
  1060. "\n",
  1061. " var id = msg.content.data.id;\n",
  1062. " // Get hold of the div created by the display call when the Comm\n",
  1063. " // socket was opened in Python.\n",
  1064. " var element = document.getElementById(id);\n",
  1065. " var ws_proxy = comm_websocket_adapter(comm);\n",
  1066. "\n",
  1067. " function ondownload(figure, _format) {\n",
  1068. " window.open(figure.canvas.toDataURL());\n",
  1069. " }\n",
  1070. "\n",
  1071. " var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n",
  1072. "\n",
  1073. " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
  1074. " // web socket which is closed, not our websocket->open comm proxy.\n",
  1075. " ws_proxy.onopen();\n",
  1076. "\n",
  1077. " fig.parent_element = element;\n",
  1078. " fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
  1079. " if (!fig.cell_info) {\n",
  1080. " console.error('Failed to find cell for figure', id, fig);\n",
  1081. " return;\n",
  1082. " }\n",
  1083. " fig.cell_info[0].output_area.element.on(\n",
  1084. " 'cleared',\n",
  1085. " { fig: fig },\n",
  1086. " fig._remove_fig_handler\n",
  1087. " );\n",
  1088. "};\n",
  1089. "\n",
  1090. "mpl.figure.prototype.handle_close = function (fig, msg) {\n",
  1091. " var width = fig.canvas.width / fig.ratio;\n",
  1092. " fig.cell_info[0].output_area.element.off(\n",
  1093. " 'cleared',\n",
  1094. " fig._remove_fig_handler\n",
  1095. " );\n",
  1096. " fig.resizeObserverInstance.unobserve(fig.canvas_div);\n",
  1097. "\n",
  1098. " // Update the output cell to use the data from the current canvas.\n",
  1099. " fig.push_to_output();\n",
  1100. " var dataURL = fig.canvas.toDataURL();\n",
  1101. " // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
  1102. " // the notebook keyboard shortcuts fail.\n",
  1103. " IPython.keyboard_manager.enable();\n",
  1104. " fig.parent_element.innerHTML =\n",
  1105. " '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
  1106. " fig.close_ws(fig, msg);\n",
  1107. "};\n",
  1108. "\n",
  1109. "mpl.figure.prototype.close_ws = function (fig, msg) {\n",
  1110. " fig.send_message('closing', msg);\n",
  1111. " // fig.ws.close()\n",
  1112. "};\n",
  1113. "\n",
  1114. "mpl.figure.prototype.push_to_output = function (_remove_interactive) {\n",
  1115. " // Turn the data on the canvas into data in the output cell.\n",
  1116. " var width = this.canvas.width / this.ratio;\n",
  1117. " var dataURL = this.canvas.toDataURL();\n",
  1118. " this.cell_info[1]['text/html'] =\n",
  1119. " '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
  1120. "};\n",
  1121. "\n",
  1122. "mpl.figure.prototype.updated_canvas_event = function () {\n",
  1123. " // Tell IPython that the notebook contents must change.\n",
  1124. " IPython.notebook.set_dirty(true);\n",
  1125. " this.send_message('ack', {});\n",
  1126. " var fig = this;\n",
  1127. " // Wait a second, then push the new image to the DOM so\n",
  1128. " // that it is saved nicely (might be nice to debounce this).\n",
  1129. " setTimeout(function () {\n",
  1130. " fig.push_to_output();\n",
  1131. " }, 1000);\n",
  1132. "};\n",
  1133. "\n",
  1134. "mpl.figure.prototype._init_toolbar = function () {\n",
  1135. " var fig = this;\n",
  1136. "\n",
  1137. " var toolbar = document.createElement('div');\n",
  1138. " toolbar.classList = 'btn-toolbar';\n",
  1139. " this.root.appendChild(toolbar);\n",
  1140. "\n",
  1141. " function on_click_closure(name) {\n",
  1142. " return function (_event) {\n",
  1143. " return fig.toolbar_button_onclick(name);\n",
  1144. " };\n",
  1145. " }\n",
  1146. "\n",
  1147. " function on_mouseover_closure(tooltip) {\n",
  1148. " return function (event) {\n",
  1149. " if (!event.currentTarget.disabled) {\n",
  1150. " return fig.toolbar_button_onmouseover(tooltip);\n",
  1151. " }\n",
  1152. " };\n",
  1153. " }\n",
  1154. "\n",
  1155. " fig.buttons = {};\n",
  1156. " var buttonGroup = document.createElement('div');\n",
  1157. " buttonGroup.classList = 'btn-group';\n",
  1158. " var button;\n",
  1159. " for (var toolbar_ind in mpl.toolbar_items) {\n",
  1160. " var name = mpl.toolbar_items[toolbar_ind][0];\n",
  1161. " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
  1162. " var image = mpl.toolbar_items[toolbar_ind][2];\n",
  1163. " var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
  1164. "\n",
  1165. " if (!name) {\n",
  1166. " /* Instead of a spacer, we start a new button group. */\n",
  1167. " if (buttonGroup.hasChildNodes()) {\n",
  1168. " toolbar.appendChild(buttonGroup);\n",
  1169. " }\n",
  1170. " buttonGroup = document.createElement('div');\n",
  1171. " buttonGroup.classList = 'btn-group';\n",
  1172. " continue;\n",
  1173. " }\n",
  1174. "\n",
  1175. " button = fig.buttons[name] = document.createElement('button');\n",
  1176. " button.classList = 'btn btn-default';\n",
  1177. " button.href = '#';\n",
  1178. " button.title = name;\n",
  1179. " button.innerHTML = '<i class=\"fa ' + image + ' fa-lg\"></i>';\n",
  1180. " button.addEventListener('click', on_click_closure(method_name));\n",
  1181. " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n",
  1182. " buttonGroup.appendChild(button);\n",
  1183. " }\n",
  1184. "\n",
  1185. " if (buttonGroup.hasChildNodes()) {\n",
  1186. " toolbar.appendChild(buttonGroup);\n",
  1187. " }\n",
  1188. "\n",
  1189. " // Add the status bar.\n",
  1190. " var status_bar = document.createElement('span');\n",
  1191. " status_bar.classList = 'mpl-message pull-right';\n",
  1192. " toolbar.appendChild(status_bar);\n",
  1193. " this.message = status_bar;\n",
  1194. "\n",
  1195. " // Add the close button to the window.\n",
  1196. " var buttongrp = document.createElement('div');\n",
  1197. " buttongrp.classList = 'btn-group inline pull-right';\n",
  1198. " button = document.createElement('button');\n",
  1199. " button.classList = 'btn btn-mini btn-primary';\n",
  1200. " button.href = '#';\n",
  1201. " button.title = 'Stop Interaction';\n",
  1202. " button.innerHTML = '<i class=\"fa fa-power-off icon-remove icon-large\"></i>';\n",
  1203. " button.addEventListener('click', function (_evt) {\n",
  1204. " fig.handle_close(fig, {});\n",
  1205. " });\n",
  1206. " button.addEventListener(\n",
  1207. " 'mouseover',\n",
  1208. " on_mouseover_closure('Stop Interaction')\n",
  1209. " );\n",
  1210. " buttongrp.appendChild(button);\n",
  1211. " var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n",
  1212. " titlebar.insertBefore(buttongrp, titlebar.firstChild);\n",
  1213. "};\n",
  1214. "\n",
  1215. "mpl.figure.prototype._remove_fig_handler = function (event) {\n",
  1216. " var fig = event.data.fig;\n",
  1217. " if (event.target !== this) {\n",
  1218. " // Ignore bubbled events from children.\n",
  1219. " return;\n",
  1220. " }\n",
  1221. " fig.close_ws(fig, {});\n",
  1222. "};\n",
  1223. "\n",
  1224. "mpl.figure.prototype._root_extra_style = function (el) {\n",
  1225. " el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n",
  1226. "};\n",
  1227. "\n",
  1228. "mpl.figure.prototype._canvas_extra_style = function (el) {\n",
  1229. " // this is important to make the div 'focusable\n",
  1230. " el.setAttribute('tabindex', 0);\n",
  1231. " // reach out to IPython and tell the keyboard manager to turn it's self\n",
  1232. " // off when our div gets focus\n",
  1233. "\n",
  1234. " // location in version 3\n",
  1235. " if (IPython.notebook.keyboard_manager) {\n",
  1236. " IPython.notebook.keyboard_manager.register_events(el);\n",
  1237. " } else {\n",
  1238. " // location in version 2\n",
  1239. " IPython.keyboard_manager.register_events(el);\n",
  1240. " }\n",
  1241. "};\n",
  1242. "\n",
  1243. "mpl.figure.prototype._key_event_extra = function (event, _name) {\n",
  1244. " var manager = IPython.notebook.keyboard_manager;\n",
  1245. " if (!manager) {\n",
  1246. " manager = IPython.keyboard_manager;\n",
  1247. " }\n",
  1248. "\n",
  1249. " // Check for shift+enter\n",
  1250. " if (event.shiftKey && event.which === 13) {\n",
  1251. " this.canvas_div.blur();\n",
  1252. " // select the cell after this one\n",
  1253. " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
  1254. " IPython.notebook.select(index + 1);\n",
  1255. " }\n",
  1256. "};\n",
  1257. "\n",
  1258. "mpl.figure.prototype.handle_save = function (fig, _msg) {\n",
  1259. " fig.ondownload(fig, null);\n",
  1260. "};\n",
  1261. "\n",
  1262. "mpl.find_output_cell = function (html_output) {\n",
  1263. " // Return the cell and output element which can be found *uniquely* in the notebook.\n",
  1264. " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
  1265. " // IPython event is triggered only after the cells have been serialised, which for\n",
  1266. " // our purposes (turning an active figure into a static one), is too late.\n",
  1267. " var cells = IPython.notebook.get_cells();\n",
  1268. " var ncells = cells.length;\n",
  1269. " for (var i = 0; i < ncells; i++) {\n",
  1270. " var cell = cells[i];\n",
  1271. " if (cell.cell_type === 'code') {\n",
  1272. " for (var j = 0; j < cell.output_area.outputs.length; j++) {\n",
  1273. " var data = cell.output_area.outputs[j];\n",
  1274. " if (data.data) {\n",
  1275. " // IPython >= 3 moved mimebundle to data attribute of output\n",
  1276. " data = data.data;\n",
  1277. " }\n",
  1278. " if (data['text/html'] === html_output) {\n",
  1279. " return [cell, data, j];\n",
  1280. " }\n",
  1281. " }\n",
  1282. " }\n",
  1283. " }\n",
  1284. "};\n",
  1285. "\n",
  1286. "// Register the function which deals with the matplotlib target/channel.\n",
  1287. "// The kernel may be null if the page has been refreshed.\n",
  1288. "if (IPython.notebook.kernel !== null) {\n",
  1289. " IPython.notebook.kernel.comm_manager.register_target(\n",
  1290. " 'matplotlib',\n",
  1291. " mpl.mpl_figure_comm\n",
  1292. " );\n",
  1293. "}\n"
  1294. ],
  1295. "text/plain": [
  1296. "<IPython.core.display.Javascript object>"
  1297. ]
  1298. },
  1299. "metadata": {},
  1300. "output_type": "display_data"
  1301. },
  1302. {
  1303. "data": {
  1304. "text/html": [
  1305. "<img src=\"data:image/png;base64,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ECBAgMCABAToATXbVAkQIECAAAECBAgQIECgv4AA3d/OkQQIECBAgAABAgQIECAwIAEBekDNNlUCBAgQIECAAAECBAgQ6C8gQPe3cyQBAgQIECBAgAABAgQIDEhAgB5Qs02VAAECBAgQIECAAAECBPoLCND97RxJgAABAgQIECBAgAABAgMSEKAH1GxTJUCAAAECBAgQIECAAIH+AgJ0fztHEiBAgAABAgQIECBAgMCABAToATXbVAkQIECAAAECBAgQIECgv4AA3d/OkQQIECBAgAABAgQIECAwIAEBekDNNlUCBAgQIECAAAECBAgQ6C8gQPe3cyQBAgQIECBAgAABAgQIDEhAgB5Qs02VAAECBAgQIECAAAECBPoLCND97RxJgAABAgQIECBAgAABAgMSEKAH1GxTJUCAAAECBAgQIECAAIH+AgJ0fztHEiBAgAABAgQIECBAgMCABAToATXbVAkQIECAAAECBAgQIECgv4AA3d/OkQQIECBAgAABAgQIECAwIAEBekDNNlUCBAgQIECAAAECBAgQ6C8gQPe3cyQBAgQIECBAgAABAgQIDEhAgB5Qs02VAAECBAgQIECAAAECBPoLCND97RxJgAABAgQIECBAgAABAgMSEKAH1GxTJUCAAAECBAgQIECAAIH+AgJ0fztHEiBAgAABAgQIECBAgMCABAToATXbVAkQIECAAAECBAgQIECgv4AA3d/OkQQIECBAgAABAgQIECAwIAEBekDNNlUCBAgQIECAAAECBAgQ6C8gQPe3cyQBAgQIECBAgAABAgQIDEhAgB5Qs02VAAECBAgQIECAAAECBPoLCND97RxJgAABAgQIECBAgAABAgMSEKAH1GxTJUCAAAECBAgQIECAAIH+AgJ0fztHEiBAgAABAgQIECBAgMCABAToATXbVAkQIECAAAECBAgQIECgv4AA3d/OkQQIECBAgAABAgQIECAwIAEBekDNNlUCBAgQIECAAAECBAgQ6C8gQPe3cyQBAgQIECBAgAABAgQIDEhAgB5Qs02VAAECBAgQIECAAAECBPoLCND97RxJgAABAgQIECBAgAABAgMSEKAH1GxTJUCAAAECBAgQIECAAIH+AgJ0fztHEiBAgAABAgQIECBAgMCABAToATXbVAkQIECAAAECBAgQIECgv4AA3d/OkQQIECBAgAABAgQIECAwIAEBekDNNlUCBAgQIECAAAECBAgQ6C8gQPe3cyQBAgQIECBAgAABAgQIDEhAgB5Qs02VAAECBAgQIECAAAECBPoLCND97RxJgAABAgQIECBAgAABAgMSEKAH1GxTJUCAAAECBAgQIECAAIH+AgJ0fztHEiBAgAABAgQIECBAgMCABAToATXbVAkQIECAAAECBAgQIECgv4AA3d/OkQQIECBAgAABAgQIECAwIIH/D/U0kjBl61BxAAAAAElFTkSuQmCC\" width=\"648.9766233766234\">"
  1306. ],
  1307. "text/plain": [
  1308. "<IPython.core.display.HTML object>"
  1309. ]
  1310. },
  1311. "metadata": {},
  1312. "output_type": "display_data"
  1313. }
  1314. ],
  1315. "source": [
  1316. "%matplotlib nbagg\n",
  1317. "\n",
  1318. "import matplotlib.pyplot as plt\n",
  1319. "import matplotlib.animation as animation\n",
  1320. "\n",
  1321. "n_epoch = 300 # epoch size\n",
  1322. "a, b = 1, 1 # initial parameters\n",
  1323. "epsilon = 0.0001 # learning rate\n",
  1324. "\n",
  1325. "fig = plt.figure()\n",
  1326. "imgs = []\n",
  1327. "\n",
  1328. "for i in range(n_epoch):\n",
  1329. " data_idx = list(range(N))\n",
  1330. " random.shuffle(data_idx)\n",
  1331. " \n",
  1332. " for j in data_idx[:10]:\n",
  1333. " a = a + epsilon*2*(Y[j] - a*X[j] - b)*X[j]\n",
  1334. " b = b + epsilon*2*(Y[j] - a*X[j] - b)\n",
  1335. "\n",
  1336. "\n",
  1337. " if i<80 and i % 5 == 0:\n",
  1338. " x_min = np.min(X)\n",
  1339. " x_max = np.max(X)\n",
  1340. " y_min = a * x_min + b\n",
  1341. " y_max = a * x_max + b\n",
  1342. "\n",
  1343. " img = plt.scatter(X, Y, label='original data')\n",
  1344. " img = plt.plot([x_min, x_max], [y_min, y_max], 'r', label='model')\n",
  1345. " imgs.append(img)\n",
  1346. " \n",
  1347. "ani = animation.ArtistAnimation(fig, imgs)\n",
  1348. "plt.show()"
  1349. ]
  1350. },
  1351. {
  1352. "cell_type": "markdown",
  1353. "metadata": {},
  1354. "source": [
  1355. "## 4. 如何使用批次更新的方法?\n",
  1356. "\n",
  1357. "如果有一些数据包含比较大的错误(异常数据),因此每次更新仅仅使用一个数据会导致不精确,同时每次仅仅使用一个数据来计算更新也导致计算效率比较低。\n",
  1358. "\n",
  1359. "\n",
  1360. "* [梯度下降方法的几种形式](https://blog.csdn.net/u010402786/article/details/51188876)"
  1361. ]
  1362. },
  1363. {
  1364. "cell_type": "markdown",
  1365. "metadata": {},
  1366. "source": [
  1367. "## 5. 如何拟合多项式函数?\n",
  1368. "\n",
  1369. "需要设计一个弹道导弹防御系统,通过观测导弹的飞行路径,预测未来导弹的飞行轨迹,从而完成摧毁的任务。按照物理学,可以得知模型为:\n",
  1370. "$$\n",
  1371. "y = at^2 + bt + c\n",
  1372. "$$\n",
  1373. "我们需要求解三个模型参数$a, b, c$。\n",
  1374. "\n",
  1375. "损失函数的定义为:\n",
  1376. "$$\n",
  1377. "L = \\sum_{i=1}^N (y_i - at_i^2 - bt_i - c)^2\n",
  1378. "$$\n"
  1379. ]
  1380. },
  1381. {
  1382. "cell_type": "code",
  1383. "execution_count": 5,
  1384. "metadata": {},
  1385. "outputs": [
  1386. {
  1387. "data": {
  1388. "image/png": "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\n",
  1389. "text/plain": [
  1390. "<Figure size 432x288 with 1 Axes>"
  1391. ]
  1392. },
  1393. "metadata": {
  1394. "needs_background": "light"
  1395. },
  1396. "output_type": "display_data"
  1397. }
  1398. ],
  1399. "source": [
  1400. "%matplotlib inline\n",
  1401. "import matplotlib.pyplot as plt\n",
  1402. "import numpy as np\n",
  1403. "\n",
  1404. "pa = -20\n",
  1405. "pb = 90\n",
  1406. "pc = 800\n",
  1407. "\n",
  1408. "t = np.linspace(0, 10) \n",
  1409. "y = pa*t**2 + pb*t + pc + np.random.randn(np.size(t))*15\n",
  1410. "\n",
  1411. "\n",
  1412. "plt.plot(t, y)\n",
  1413. "plt.show()"
  1414. ]
  1415. },
  1416. {
  1417. "cell_type": "markdown",
  1418. "metadata": {},
  1419. "source": [
  1420. "### 5.1 如何得到更新项?\n",
  1421. "\n",
  1422. "$$\n",
  1423. "L = \\sum_{i=1}^N (y_i - at_i^2 - bt_i - c)^2\n",
  1424. "$$\n",
  1425. "\n",
  1426. "\\begin{eqnarray}\n",
  1427. "\\frac{\\partial L}{\\partial a} & = & - 2\\sum_{i=1}^N (y_i - at_i^2 - bt_i -c) t_i^2 \\\\\n",
  1428. "\\frac{\\partial L}{\\partial b} & = & - 2\\sum_{i=1}^N (y_i - at_i^2 - bt_i -c) t_i \\\\\n",
  1429. "\\frac{\\partial L}{\\partial c} & = & - 2\\sum_{i=1}^N (y_i - at_i^2 - bt_i -c)\n",
  1430. "\\end{eqnarray}"
  1431. ]
  1432. },
  1433. {
  1434. "cell_type": "markdown",
  1435. "metadata": {},
  1436. "source": [
  1437. "### 5.2 程序"
  1438. ]
  1439. },
  1440. {
  1441. "cell_type": "code",
  1442. "execution_count": 6,
  1443. "metadata": {},
  1444. "outputs": [
  1445. {
  1446. "name": "stdout",
  1447. "output_type": "stream",
  1448. "text": [
  1449. "epoch 0: loss = 2.59199e+07, a = -4.03101, b = 7.0103, c = 4.32798\n",
  1450. "epoch 500: loss = 1.03254e+06, a = -31.3488, b = 241.561, c = 424.128\n",
  1451. "epoch 1000: loss = 344061, a = -26.488, b = 176.47, c = 585.509\n",
  1452. "epoch 1500: loss = 120771, a = -23.7191, b = 139.394, c = 677.407\n",
  1453. "epoch 2000: loss = 48363.3, a = -22.1423, b = 118.28, c = 729.741\n",
  1454. "epoch 2500: loss = 24884.4, a = -21.2443, b = 106.257, c = 759.543\n"
  1455. ]
  1456. },
  1457. {
  1458. "data": {
  1459. "image/png": "iVBORw0KGgoAAAANSUhEUgAAAX8AAAD4CAYAAAAEhuazAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/MnkTPAAAACXBIWXMAAAsTAAALEwEAmpwYAAA2Y0lEQVR4nO3de3zN9R/A8ddnd0PZRYTYMLnfV2mFuW6ZS2FEoctP96SLqF900YUSipRUiHA2hJBkx6USm6gwuYu5zX3D7Pb+/bFjv9Fc1s52tp338/E4j30vn/P9vr+7vM93n9vXiAhKKaWci4ujA1BKKVX4NPkrpZQT0uSvlFJOSJO/Uko5IU3+SinlhNwcHcD18Pf3l4CAAEeHoZRSxcqGDRuOiUj53PYVi+QfEBBAXFyco8NQSqlixRiz70r7tNpHKaWckCZ/pZRyQpr8lVLKCRWLOn+lVMFLS0vjwIEDpKSkODoUlUdeXl5UqVIFd3f3636PJn+lFAAHDhygbNmyBAQEYIxxdDjqOokIx48f58CBAwQGBl73+7TaRykFQEpKCn5+fpr4ixljDH5+fnn+j02Tv1Iqmyb+4unf/Nw0+RdXIrBxI4wbB/Hxjo5GKVXMaPIvTi4m/FdegaAgaNoUBg+GunWhWzf49VdG/zwa6x7rJW+z7rFyz8x7ct/+dRjW+R/Cyy9D374wbhzWpZ9kbc+l/OifRsG+fTB/PnzwAezdW8AXrZyJq6srjRs3pn79+nTu3JlTp079q+NMnTqVp59++prlAgICOHbs2FXLvPPOO/8qhiJPRIr8q1mzZuKUzp0T+fNPkXnzRIYNE6lZUwREXF1l1IAgifn4eZFt20SGDxfx8ZGYAGTgfyqK/8gbJGbXChERidkdI/6j/WXML2PEf7S/xOyOEdmzR2LGPyf+r3rImFbu4v8SElPTVaRSJYkJQPxfQsbc5Sr+r7hJzNBeIl9+KTFDe4n/q+4S07CsjApBYgLIiqVsWZGvv5aY3TESPiM86/g5xOyOkVE/jXLEd0/l0datWx0dgpQuXTp7uV+/fjJy5Mh/dZyvvvpKnnrqqWuWq1atmiQmJl53TEVZbj8/IE6ukFe1t09RsnEjfP457NgB27cz+pa/CU6A0L2Aqyu0aYN1UBdia5UhOKg1kdGRWDwiCH3jDRZ3b8CD8/vx2q/nGLjrDJ1T2tM41ZcNXidoefIG1kx9gyqe5+kwtQ0+5+FEKah4wYWJd5fB1as07R44QxmPZM6muVDNrTyW1oZKZ0/TscwcamyYw95ycN9hHza2rcXJm2+kW+rPvNfoRbqN+56twx+kd19PhoW+lhVTDwuhgaFY91iJjI7kvtr3Yd1jJTQwNPtSrXusxB6MZUjIEEd9t1UR16JFC/744w8Adu3axVNPPUViYiLe3t58/vnn1K5dm0WLFjFy5EhSU1Px8/Nj5syZVKhQ4YrHPH78OPfffz8JCQm0aNECyfEkw27durF//35SUlIYNGgQAwcOZOjQoZw/f57GjRtTr149Zs6cmWu54sjkvPiiqnnz5lKS5/YZ/fNogjMqENptMKSlQd26WBuWZXaVU8xz3Y4l+H1a3tELy99LeWLxEwxoPACDYe2BtcQdjMPFuJCWmZbrsb0yDBXSPLlRPLgBLw57XGCn62nq3FCDRrcE4+riiquLK78f/p3fj/xOvfL1qOlbk5T0FM6nn2fn8R0cTD5EaffSXMi4QHpmeq7nqXIa6iR74dGwCdYzvxNeM5yYPTHM6TEHt5RUIr/ti+VcJ0LLB2PtVI/Ib/tkf0iooiE+Pp46depkrTz3HGzaZN8TNG6c1UZ1FWXKlCE5OZmMjAx69+7NI488QlhYGG3btuXTTz8lKCiIdevWMWzYMGJiYjh58iTlypXDGMOUKVOIj49nzJgxTJ06lbi4OCZMmHDJ8Z999ln8/f0ZPnw4ixcvJiIigsTERPz9/Tlx4gS+vr6cP3+e4OBgVq1ahZ+fX3ZMF12pnKNd8vOzMcZsEJHmuZXXO/9CNPrn0QRXCv7HHfCug5t5/7dhWKqVJXTu7yzJ2EbfuX15sNGDBJ+4iQ7rn0bWPUWGZAAwft14vN29CfINIsgviG3HttE2sC0DGg+gUtlK7D+9nxd+eIEnmj/Bpxs+5avL7sRfa/4ak+ImMbDZwP9v3xHJay2ztn8c/vGl5W3bF/ZeSNNKTTl27hjHzh1j7K9jsWyxcEflO7ilYmn2bv6JffvWcq4MzI2fC0Cn6R2pdUyofxYiKn9DxM/f8GOiK9GhnxJ7MBZA/yNQ2S7eZSckJFCnTh3at29PcnIyv/zyCz179swud+HCBSBrbEKvXr04dOgQqamp1+znvnr1aubNmwdAp06d8PHxyd730UcfMX/+fAD279/Pjh07ck3q11uuyLtSfVBRepWUOv+L9e8X68VjdseI/yh/+bJHTRkc7iKeb7qL73u+wutkv/xG+UnguEDhdaTTzE5i3WOVA6cPSGZmZvbxXot5Lfu4uZ7j8jr/fGy/fD3nuSUpSWKeCBf/l5D/RCBlhyH3P+YvnYcHSfV3b77kum4ZjLR8vZqUfttbxv4yVpIvJGcfc+DCgVdvO8jMzGoLSU0t8J+ZMylKdf5nz56Vu+66S8aPHy+nT5+WihUr5lq+VatWsmDBAhERsVqt0qpVKxG5cp1/o0aNZNeuXdnrPj4+kpiYKFarVUJCQuTs2bPZx7VarZfEdPEcVyrnaHmt89fePgXgSj1uYg/GMqv7LO6z3Ee76e0ImxnGheRTPFx/J2Nvz8TN1YMTKSdoVa0VC3svZP/g/Vh6WEhKTeK1lq+xLmEdIkLlGyqzcu/K7Pr1N0PfxNLDQmR0JLM3z76kOiU0MBRLDws/7v7RLttjD8Zm/0dw+bk//HMykYGxWO4az+TBK1jQbwnLa8DgAZ8xpddM/Er5MaDxAEq7eVPTvQIHTuzjbNo5Bv8wmLLvlqXDjA6E1Qijln8tIqMis7+HF88XXL4RTJ8OzZpBgwYwYEBWDyhV4nh7e/PRRx8xZswYvL29CQwMJCoqCsi6Yf39998BOH36NJUrVwZg2rRp1zxuy5Yt+eabbwBYunQpJ0+ezD6Oj48P3t7ebNu2jV9//TX7Pe7u7qSlpV2zXLFzpU+FovQqbnf+2XfJ300QSUiQqM1RUuadMtJ6amvxHfX/O3vfEV7ycBfkq7e6y9e/f33dd/EX74Id1bPmSue+Um+fgQsH5n4dX78lRwNukt49sr4flUf6iusbrsLriPub7uL+pru0/qq1lHvnRlnxen+RChWyehq1qibSu3dWb6OJE7VHkZ0UpTv/iyIiImT69Omye/du6dixozRs2FDq1Kkjb7zxhoiIfPvttxIYGChNmzaVF1988Zp3/seOHZP27dtL3bp15dFHH5WqVatKYmKipKSkSFhYmNSuXVu6du16yR39kCFDpHbt2tKnT5+rlnO0vN75a4NvPuRah//7t6xf/Dll16znxWbHKHsBjpbJ2lexVHkaVmrC2v1redTrTr4+tAxLcji8+CKRc3vl2kumd/3exb5O/EptHbEHYwkueyuR0b144qcLTGoOX30LxsUQ0+hGZgad44h7KpDVoNw5pSpVm7djzLGFWHrMJvSZD7FuX0bkQ2Wx3D9PG4/zKbcGQ1V85LXBV5N/PmRXf3SfQ8vEUkyYMYhhN8ZS5gIklgGDQRDaHi3DmLnJHC8Fve53wyLdCR0zD2tEfSLv2M99dUpGks+rnNVHoRVux/rzDCLXvYgltRv8/TeRlX6i31Z3JjfKoPFNDdh4+i/Opp3Fy9WLTDLpVK09q7cuJWqFL7EjnyA4KNTpvof2pMm/eNPePvaUkcHoOc8SvD2Z0GXb4Y8/wNMTaw1XYisJL+2txPBbS3NPUjtcM4Sz/uAuLrSo2pK61e/g898+58ngJ5kUN4kT0ZOIW/UNlp92E/r9HKhdm9AvVmA5tYnYg7H/uGsNDQwt8XeysQdjL21XaD8QS80gZm+ezbyyW7D0WE5oYCgRtg+JuZFzyZRMFm1fxIw/ZjB/92LcvFz5LPAE9WZ/Q2TtSVh6Xvrfk6WHxcFXqVTR5Lx3/mlpcOIEpKTAhQuXvrZtg2XLYPlyrOVOEdkTLJtrE1qrI1aXffQos4QuyZVZ43WUXZ5nccuEdBe4r2YXpvaYQdzBuFwHO2UnugMHoGxZuPFG+15TCXG1aqIhIUOyv5+dgjoxZ8scPDLgjKRQWtxJd3Mhsl4kS3cu1XEEeaR3/sWbVvtcjzVr4P77ISHhymUqVYKOHSEsDGttT3p+/wgtqrRg2a5lpGWmYTCEBoYSfHMwUzZOyb7Dv9gj5mrJS/17l3+QXlx/KSGArfvimNXEjVRJx8fLhyEhQ0hOTaZtYFv9WVwHTf7Fm1b7XE1mJoweDf/9LwQGwoQJUKoUeHoyOul7gm+oTah/MFSunDXKdu9Kvtv+HRcOXCDpQhLf7fgO31K+vNDiBR5o+AC7TuwiMjqSqJ5RWdU0AaGX3uHn4AzVOIXhH1VFF7ug7vuF/m+fZPG53dwV1J7FB1cybMUwXHDh/V/eZ0SrEQwJGcKafWu0OkgpnCn5Hz8O/frBkiUQGZk1h84NN2TvDt5TKSsptLAQUjWIkStH8N5P75GWmYa7izsuxoWHGj/Eou2LaFGlBVVvrHrFPvW51eEr+8jtbv3i9zqy7YdYZnoTunMN1kc70v3m1XSoFc6yXct4NeZVRv00igzJYOZ9M3V0sVJX6gOalxcwGNgCbAZmAV5AILAO2AnMATxsZT1t6ztt+wOudfx89/P/+WeRKlVEPDxEJk7MGiGai/nx88X7bW8p/XZp4XWk4vsVZeDCgeI3yu+KI11V0ZA99uCvv0QefVTE01NiApBRD98qqd8vkR5zemSPr/B+21s6f9NZfN7z0Z9rDkWhn7+Li4s0atQo+/Xuu+9esez8+fNly5Yt2euvvfaaLF++PN8xnDx5UiZOnJjn940YMULef//9a5a71iyh//b8ee3nb4/EXxnYA5SyrVuAAbavvW3bPgWesC0/CXxqW+4NzLnWOf518s/MFPngAxE3N5HAQJG4uFwHKM34fYa0mNJCSo0slZ0gekf3lvSMdIcOplL5cPSoyJtvilSokDVN9TBXee2/d4rPcE8Jf6mSeA53yRpMNtxIn4F+4v/W/6fBdlZ5Sf4F9XeRl+mT+/fvL1FRUfk6X2727Nkj9erVy/P77JX8/+35HZX89wO+ZFUjfQd0BI4BbrYyLYBltuVlQAvbsputnLnaOf518t+2Letu/957RU6eFJFL7/BiE2Kl9dTWwuuI6xuuEv51uPi853PpfDWqWIv563vxf7OsxLSrIeLiIjH1S4v/UBeZ17GavPVgNSn9WtaI4oovINE96klGXKzTfuDnJflfbfR5flwpMb788stSp04dadCggbzwwgvy888/i4+PjwQEBEijRo1k586dl3wYVKtWTYYOHSqNGjWSZs2ayYYNG6RDhw5SvXp1mTRpkoiIJCUlSZs2baRJkyZSv359+fbbb0VEpFevXuLl5SWNGjWSF198UURERo8eLc2bN5cGDRrI8OHDs+MaOXKkBAUFSUhIiPTu3TvX5L9792654447pH79+vLqq69mX+P1nv9K5S5X6Mk/6/gMApKBRGAm4A/szLH/FmCzbXkzUCXHvl2Afy7HHAjEAXFVq1bN9WKvy6ZN/6jmGbd2nLi/6S68jpjXjfSO6i2WzZYC+WVWjnVJIrf9HuScHsN/tL90ntFJXF83wutInaeQoc/VF//3fJ3udyFn8hi0dJC0+qrVVV8NJzUU9zfdperYquL+prs0nNTwquUHLR10zRgur/aZPXu2HDt2TGrVqiWZtp/fSduN3OV3/pcn/08++URERJ577jlp0KCBnDlzRo4ePSo33XSTiIikpaXJ6dOnRUQkMTFRatSoIZmZmf+48162bJn85z//kczMTMnIyJBOnTrJqlWrJC4uTurXry9nz56V06dP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\n",
  1460. "text/plain": [
  1461. "<Figure size 432x288 with 1 Axes>"
  1462. ]
  1463. },
  1464. "metadata": {
  1465. "needs_background": "light"
  1466. },
  1467. "output_type": "display_data"
  1468. }
  1469. ],
  1470. "source": [
  1471. "n_epoch = 3000 # epoch size\n",
  1472. "a, b, c = 1.0, 1.0, 1.0 # initial parameters\n",
  1473. "epsilon = 0.0001 # learning rate\n",
  1474. "\n",
  1475. "N = np.size(t)\n",
  1476. "\n",
  1477. "for i in range(n_epoch):\n",
  1478. " for j in range(N):\n",
  1479. " a = a + epsilon*2*(y[j] - a*t[j]**2 - b*t[j] - c)*t[j]**2\n",
  1480. " b = b + epsilon*2*(y[j] - a*t[j]**2 - b*t[j] - c)*t[j]\n",
  1481. " c = c + epsilon*2*(y[j] - a*t[j]**2 - b*t[j] - c)\n",
  1482. "\n",
  1483. " L = 0\n",
  1484. " for j in range(N):\n",
  1485. " L = L + (y[j] - a*t[j]**2 - b*t[j] - c)**2\n",
  1486. " \n",
  1487. " if i % 500 == 0:\n",
  1488. " print(\"epoch %4d: loss = %10g, a = %10g, b = %10g, c = %10g\" % (i, L, a, b, c))\n",
  1489. " \n",
  1490. " \n",
  1491. "y_est = a*t**2 + b*t + c \n",
  1492. "\n",
  1493. "\n",
  1494. "plt.plot(t, y, 'r-', label='Real data')\n",
  1495. "plt.plot(t, y_est, 'g-x', label='Estimated data')\n",
  1496. "plt.legend()\n",
  1497. "plt.show()\n"
  1498. ]
  1499. },
  1500. {
  1501. "cell_type": "markdown",
  1502. "metadata": {},
  1503. "source": [
  1504. "## 6. 如何使用sklearn求解线性问题?\n"
  1505. ]
  1506. },
  1507. {
  1508. "cell_type": "code",
  1509. "execution_count": 7,
  1510. "metadata": {},
  1511. "outputs": [
  1512. {
  1513. "name": "stdout",
  1514. "output_type": "stream",
  1515. "text": [
  1516. "X: (100, 1)\n",
  1517. "Y: (100, 1)\n",
  1518. "a = 2.825254, b = 5.366227\n"
  1519. ]
  1520. },
  1521. {
  1522. "data": {
  1523. "image/png": "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\n",
  1524. "text/plain": [
  1525. "<Figure size 432x288 with 1 Axes>"
  1526. ]
  1527. },
  1528. "metadata": {
  1529. "needs_background": "light"
  1530. },
  1531. "output_type": "display_data"
  1532. }
  1533. ],
  1534. "source": [
  1535. "%matplotlib inline\n",
  1536. "\n",
  1537. "from sklearn import linear_model\n",
  1538. "import numpy as np\n",
  1539. "\n",
  1540. "# load data\n",
  1541. "# generate data\n",
  1542. "data_num = 100\n",
  1543. "X = np.random.rand(data_num, 1)*10\n",
  1544. "Y = X * 3 + 4 + 8*np.random.randn(data_num,1)\n",
  1545. "\n",
  1546. "print(\"X: \", X.shape)\n",
  1547. "print(\"Y: \", Y.shape)\n",
  1548. "\n",
  1549. "# create regression model\n",
  1550. "regr = linear_model.LinearRegression()\n",
  1551. "regr.fit(X, Y)\n",
  1552. "\n",
  1553. "a, b = np.squeeze(regr.coef_), np.squeeze(regr.intercept_)\n",
  1554. "\n",
  1555. "print(\"a = %f, b = %f\" % (a, b))\n",
  1556. "\n",
  1557. "x_min = np.min(X)\n",
  1558. "x_max = np.max(X)\n",
  1559. "y_min = a * x_min + b\n",
  1560. "y_max = a * x_max + b\n",
  1561. "\n",
  1562. "plt.scatter(X, Y)\n",
  1563. "plt.plot([x_min, x_max], [y_min, y_max], 'r')\n",
  1564. "plt.show()"
  1565. ]
  1566. },
  1567. {
  1568. "cell_type": "markdown",
  1569. "metadata": {},
  1570. "source": [
  1571. "## 7. 如何使用sklearn拟合多项式函数?"
  1572. ]
  1573. },
  1574. {
  1575. "cell_type": "code",
  1576. "execution_count": 8,
  1577. "metadata": {},
  1578. "outputs": [
  1579. {
  1580. "data": {
  1581. "text/plain": [
  1582. "array([800., 90., -20.])"
  1583. ]
  1584. },
  1585. "execution_count": 8,
  1586. "metadata": {},
  1587. "output_type": "execute_result"
  1588. }
  1589. ],
  1590. "source": [
  1591. "# Fitting polynomial functions\n",
  1592. "\n",
  1593. "from sklearn.preprocessing import PolynomialFeatures\n",
  1594. "from sklearn.linear_model import LinearRegression\n",
  1595. "from sklearn.pipeline import Pipeline\n",
  1596. "\n",
  1597. "t = np.array([2, 4, 6, 8])\n",
  1598. "\n",
  1599. "pa = -20\n",
  1600. "pb = 90\n",
  1601. "pc = 800\n",
  1602. "\n",
  1603. "y = pa*t**2 + pb*t + pc\n",
  1604. "\n",
  1605. "model = Pipeline([('poly', PolynomialFeatures(degree=2)),\n",
  1606. " ('linear', LinearRegression(fit_intercept=False))])\n",
  1607. "model = model.fit(t[:, np.newaxis], y)\n",
  1608. "model.named_steps['linear'].coef_\n"
  1609. ]
  1610. },
  1611. {
  1612. "cell_type": "markdown",
  1613. "metadata": {},
  1614. "source": [
  1615. "## 参考资料\n",
  1616. "* [梯度下降法](https://blog.csdn.net/u010402786/article/details/51188876)\n",
  1617. "* [如何理解最小二乘法?](https://blog.csdn.net/ccnt_2012/article/details/81127117)\n"
  1618. ]
  1619. }
  1620. ],
  1621. "metadata": {
  1622. "kernelspec": {
  1623. "display_name": "Python 3",
  1624. "language": "python",
  1625. "name": "python3"
  1626. },
  1627. "language_info": {
  1628. "codemirror_mode": {
  1629. "name": "ipython",
  1630. "version": 3
  1631. },
  1632. "file_extension": ".py",
  1633. "mimetype": "text/x-python",
  1634. "name": "python",
  1635. "nbconvert_exporter": "python",
  1636. "pygments_lexer": "ipython3",
  1637. "version": "3.7.9"
  1638. }
  1639. },
  1640. "nbformat": 4,
  1641. "nbformat_minor": 2
  1642. }

机器学习越来越多应用到飞行器、机器人等领域,其目的是利用计算机实现类似人类的智能,从而实现装备的智能化与无人化。本课程旨在引导学生掌握机器学习的基本知识、典型方法与技术,通过具体的应用案例激发学生对该学科的兴趣,鼓励学生能够从人工智能的角度来分析、解决飞行器、机器人所面临的问题和挑战。本课程主要内容包括Python编程基础,机器学习模型,无监督学习、监督学习、深度学习基础知识与实现,并学习如何利用机器学习解决实际问题,从而全面提升自我的《综合能力》。