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 190 kB

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

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