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.

2-autograd.ipynb 21 kB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. {
  2. "cells": [
  3. {
  4. "cell_type": "markdown",
  5. "metadata": {},
  6. "source": [
  7. "# 自动求导\n",
  8. "这次课程我们会了解 PyTorch 中的自动求导机制,自动求导是 PyTorch 中非常重要的特性,能够让我们避免手动去计算非常复杂的导数,这能够极大地减少了我们构建模型的时间,这也是其前身 Torch 这个框架所不具备的特性,下面我们通过例子看看 PyTorch 自动求导的独特魅力以及探究自动求导的更多用法。"
  9. ]
  10. },
  11. {
  12. "cell_type": "code",
  13. "execution_count": 1,
  14. "metadata": {},
  15. "outputs": [],
  16. "source": [
  17. "import torch\n",
  18. "from torch.autograd import Variable"
  19. ]
  20. },
  21. {
  22. "cell_type": "markdown",
  23. "metadata": {},
  24. "source": [
  25. "## 简单情况的自动求导\n",
  26. "下面我们显示一些简单情况的自动求导,\"简单\"体现在计算的结果都是标量,也就是一个数,我们对这个标量进行自动求导。"
  27. ]
  28. },
  29. {
  30. "cell_type": "code",
  31. "execution_count": 2,
  32. "metadata": {},
  33. "outputs": [
  34. {
  35. "name": "stdout",
  36. "output_type": "stream",
  37. "text": [
  38. "tensor([19.], grad_fn=<AddBackward0>)\n"
  39. ]
  40. }
  41. ],
  42. "source": [
  43. "x = Variable(torch.Tensor([2]), requires_grad=True)\n",
  44. "y = x + 2\n",
  45. "z = y ** 2 + 3\n",
  46. "print(z)"
  47. ]
  48. },
  49. {
  50. "cell_type": "markdown",
  51. "metadata": {},
  52. "source": [
  53. "通过上面的一些列操作,我们从 x 得到了最后的结果out,我们可以将其表示为数学公式\n",
  54. "\n",
  55. "$$\n",
  56. "z = (x + 2)^2 + 3\n",
  57. "$$\n",
  58. "\n",
  59. "那么我们从 z 对 x 求导的结果就是 \n",
  60. "\n",
  61. "$$\n",
  62. "\\frac{\\partial z}{\\partial x} = 2 (x + 2) = 2 (2 + 2) = 8\n",
  63. "$$\n",
  64. "如果你对求导不熟悉,可以查看以下[网址进行复习](https://baike.baidu.com/item/%E5%AF%BC%E6%95%B0#1)"
  65. ]
  66. },
  67. {
  68. "cell_type": "code",
  69. "execution_count": 3,
  70. "metadata": {},
  71. "outputs": [
  72. {
  73. "name": "stdout",
  74. "output_type": "stream",
  75. "text": [
  76. "tensor([8.])\n"
  77. ]
  78. }
  79. ],
  80. "source": [
  81. "# 使用自动求导\n",
  82. "z.backward()\n",
  83. "print(x.grad)"
  84. ]
  85. },
  86. {
  87. "cell_type": "markdown",
  88. "metadata": {},
  89. "source": [
  90. "对于上面这样一个简单的例子,我们验证了自动求导,同时可以发现发现使用自动求导非常方便。如果是一个更加复杂的例子,那么手动求导就会显得非常的麻烦,所以自动求导的机制能够帮助我们省去麻烦的数学计算,下面我们可以看一个更加复杂的例子。"
  91. ]
  92. },
  93. {
  94. "cell_type": "code",
  95. "execution_count": 8,
  96. "metadata": {},
  97. "outputs": [
  98. {
  99. "name": "stdout",
  100. "output_type": "stream",
  101. "text": [
  102. "tensor([[-1.5318, 1.5200, -2.1316, -1.3238, 1.0080, -1.0832, -0.2814, -1.0486,\n",
  103. " 1.0807, -2.2865, 0.6545, -0.3595, 0.4229, -0.9194, 0.1690, -0.3241,\n",
  104. " 1.8970, -0.8979, -0.7827, 0.3879],\n",
  105. " [ 0.1404, -0.8016, 0.1156, -0.8397, -1.8886, 1.1072, -1.0186, 0.2249,\n",
  106. " 0.5631, 0.4391, 0.7887, -2.3255, -0.4185, 0.6559, 0.7622, 1.6883,\n",
  107. " -1.4147, 0.2579, -0.6177, 0.2172],\n",
  108. " [-0.4866, -0.0322, -1.2484, 1.1913, -0.6569, 0.0810, 0.2491, -0.1258,\n",
  109. " 2.5903, -0.8370, -0.0554, 1.2174, 0.4059, -1.0759, 0.6649, 0.1642,\n",
  110. " -0.3512, -0.7695, 1.1469, -0.3409],\n",
  111. " [ 1.8789, -1.6553, -0.7401, -0.3198, -0.1010, -0.5512, -0.4792, -0.2891,\n",
  112. " -0.2655, -0.8132, 0.7210, 1.0885, -0.9557, -0.4472, -1.5340, 0.8093,\n",
  113. " 0.9349, 0.8352, -0.0774, -0.1728],\n",
  114. " [-0.3424, 0.1938, -2.4253, -0.0229, 0.3132, -0.7731, 0.8481, -1.3002,\n",
  115. " -0.1595, -0.0364, -1.5733, 0.8882, 0.1909, -0.1404, -1.5673, -1.1809,\n",
  116. " -0.7169, 0.7074, 0.3337, -1.0738],\n",
  117. " [-0.0501, 1.6210, 0.6854, 0.2216, 0.3034, -1.2762, -0.6216, 1.4884,\n",
  118. " 0.6078, 2.1512, -0.7141, 0.4110, -0.8187, 0.9474, -0.5978, -0.2679,\n",
  119. " 1.5315, -2.1550, 2.0969, -1.7669],\n",
  120. " [ 1.4505, -0.9497, 2.0269, -1.6402, -0.0047, -0.2716, -0.2727, 0.6795,\n",
  121. " -0.7367, -0.3248, -0.5312, 0.0887, -1.4303, -0.8390, 1.5324, 0.3761,\n",
  122. " -0.4658, -0.2044, 0.3050, -0.2756],\n",
  123. " [ 0.3265, -0.2513, 1.1441, 0.3805, -1.3629, -1.3120, -1.8571, 0.1180,\n",
  124. " 0.7466, -0.2654, -0.2154, 1.0603, -0.4113, -2.5965, 1.0736, 1.1610,\n",
  125. " 0.8165, 1.5916, 1.5556, 0.3078],\n",
  126. " [-0.4417, 0.1656, -2.1743, -0.1148, -1.2795, 1.0212, -0.7035, -0.8234,\n",
  127. " 0.3010, -1.0891, -1.0676, 0.8385, -0.2886, -1.1881, 0.5097, -0.5097,\n",
  128. " -1.7893, 0.0494, -0.0162, 1.5170],\n",
  129. " [-0.6435, -1.8376, 1.0022, -0.0397, 0.7187, -0.0661, -0.8528, 1.3248,\n",
  130. " -0.2566, -2.2886, 0.8728, -0.7152, 1.6180, 0.8416, 0.2788, 0.5515,\n",
  131. " -0.1266, -1.0025, 0.1767, -0.4987]], requires_grad=True)\n"
  132. ]
  133. }
  134. ],
  135. "source": [
  136. "x = Variable(torch.randn(10, 20), requires_grad=True)\n",
  137. "y = Variable(torch.randn(10, 5), requires_grad=True)\n",
  138. "w = Variable(torch.randn(20, 5), requires_grad=True)\n",
  139. "print(x)\n",
  140. "out = torch.mean(y - torch.matmul(x, w)) # torch.matmul 是做矩阵乘法\n",
  141. "out.backward()"
  142. ]
  143. },
  144. {
  145. "cell_type": "markdown",
  146. "metadata": {},
  147. "source": [
  148. "如果你对矩阵乘法不熟悉,可以查看下面的[网址进行复习](https://baike.baidu.com/item/%E7%9F%A9%E9%98%B5%E4%B9%98%E6%B3%95/5446029?fr=aladdin)"
  149. ]
  150. },
  151. {
  152. "cell_type": "code",
  153. "execution_count": 9,
  154. "metadata": {},
  155. "outputs": [
  156. {
  157. "name": "stdout",
  158. "output_type": "stream",
  159. "text": [
  160. "tensor([[-0.0198, -0.0066, -0.0288, 0.0080, 0.0079, -0.0569, -0.0489, 0.0505,\n",
  161. " 0.0132, -0.0072, -0.0024, 0.0400, 0.0691, -0.0273, 0.0124, 0.0104,\n",
  162. " 0.0098, -0.0598, 0.0365, 0.0177],\n",
  163. " [-0.0198, -0.0066, -0.0288, 0.0080, 0.0079, -0.0569, -0.0489, 0.0505,\n",
  164. " 0.0132, -0.0072, -0.0024, 0.0400, 0.0691, -0.0273, 0.0124, 0.0104,\n",
  165. " 0.0098, -0.0598, 0.0365, 0.0177],\n",
  166. " [-0.0198, -0.0066, -0.0288, 0.0080, 0.0079, -0.0569, -0.0489, 0.0505,\n",
  167. " 0.0132, -0.0072, -0.0024, 0.0400, 0.0691, -0.0273, 0.0124, 0.0104,\n",
  168. " 0.0098, -0.0598, 0.0365, 0.0177],\n",
  169. " [-0.0198, -0.0066, -0.0288, 0.0080, 0.0079, -0.0569, -0.0489, 0.0505,\n",
  170. " 0.0132, -0.0072, -0.0024, 0.0400, 0.0691, -0.0273, 0.0124, 0.0104,\n",
  171. " 0.0098, -0.0598, 0.0365, 0.0177],\n",
  172. " [-0.0198, -0.0066, -0.0288, 0.0080, 0.0079, -0.0569, -0.0489, 0.0505,\n",
  173. " 0.0132, -0.0072, -0.0024, 0.0400, 0.0691, -0.0273, 0.0124, 0.0104,\n",
  174. " 0.0098, -0.0598, 0.0365, 0.0177],\n",
  175. " [-0.0198, -0.0066, -0.0288, 0.0080, 0.0079, -0.0569, -0.0489, 0.0505,\n",
  176. " 0.0132, -0.0072, -0.0024, 0.0400, 0.0691, -0.0273, 0.0124, 0.0104,\n",
  177. " 0.0098, -0.0598, 0.0365, 0.0177],\n",
  178. " [-0.0198, -0.0066, -0.0288, 0.0080, 0.0079, -0.0569, -0.0489, 0.0505,\n",
  179. " 0.0132, -0.0072, -0.0024, 0.0400, 0.0691, -0.0273, 0.0124, 0.0104,\n",
  180. " 0.0098, -0.0598, 0.0365, 0.0177],\n",
  181. " [-0.0198, -0.0066, -0.0288, 0.0080, 0.0079, -0.0569, -0.0489, 0.0505,\n",
  182. " 0.0132, -0.0072, -0.0024, 0.0400, 0.0691, -0.0273, 0.0124, 0.0104,\n",
  183. " 0.0098, -0.0598, 0.0365, 0.0177],\n",
  184. " [-0.0198, -0.0066, -0.0288, 0.0080, 0.0079, -0.0569, -0.0489, 0.0505,\n",
  185. " 0.0132, -0.0072, -0.0024, 0.0400, 0.0691, -0.0273, 0.0124, 0.0104,\n",
  186. " 0.0098, -0.0598, 0.0365, 0.0177],\n",
  187. " [-0.0198, -0.0066, -0.0288, 0.0080, 0.0079, -0.0569, -0.0489, 0.0505,\n",
  188. " 0.0132, -0.0072, -0.0024, 0.0400, 0.0691, -0.0273, 0.0124, 0.0104,\n",
  189. " 0.0098, -0.0598, 0.0365, 0.0177]])\n"
  190. ]
  191. }
  192. ],
  193. "source": [
  194. "# 得到 x 的梯度\n",
  195. "print(x.grad)"
  196. ]
  197. },
  198. {
  199. "cell_type": "code",
  200. "execution_count": 10,
  201. "metadata": {},
  202. "outputs": [
  203. {
  204. "name": "stdout",
  205. "output_type": "stream",
  206. "text": [
  207. "tensor([[0.0200, 0.0200, 0.0200, 0.0200, 0.0200],\n",
  208. " [0.0200, 0.0200, 0.0200, 0.0200, 0.0200],\n",
  209. " [0.0200, 0.0200, 0.0200, 0.0200, 0.0200],\n",
  210. " [0.0200, 0.0200, 0.0200, 0.0200, 0.0200],\n",
  211. " [0.0200, 0.0200, 0.0200, 0.0200, 0.0200],\n",
  212. " [0.0200, 0.0200, 0.0200, 0.0200, 0.0200],\n",
  213. " [0.0200, 0.0200, 0.0200, 0.0200, 0.0200],\n",
  214. " [0.0200, 0.0200, 0.0200, 0.0200, 0.0200],\n",
  215. " [0.0200, 0.0200, 0.0200, 0.0200, 0.0200],\n",
  216. " [0.0200, 0.0200, 0.0200, 0.0200, 0.0200]])\n"
  217. ]
  218. }
  219. ],
  220. "source": [
  221. "# 得到 y 的的梯度\n",
  222. "print(y.grad)"
  223. ]
  224. },
  225. {
  226. "cell_type": "code",
  227. "execution_count": 11,
  228. "metadata": {},
  229. "outputs": [
  230. {
  231. "name": "stdout",
  232. "output_type": "stream",
  233. "text": [
  234. "tensor([[-0.0060, -0.0060, -0.0060, -0.0060, -0.0060],\n",
  235. " [ 0.0405, 0.0405, 0.0405, 0.0405, 0.0405],\n",
  236. " [ 0.0749, 0.0749, 0.0749, 0.0749, 0.0749],\n",
  237. " [ 0.0502, 0.0502, 0.0502, 0.0502, 0.0502],\n",
  238. " [ 0.0590, 0.0590, 0.0590, 0.0590, 0.0590],\n",
  239. " [ 0.0625, 0.0625, 0.0625, 0.0625, 0.0625],\n",
  240. " [ 0.0998, 0.0998, 0.0998, 0.0998, 0.0998],\n",
  241. " [-0.0050, -0.0050, -0.0050, -0.0050, -0.0050],\n",
  242. " [-0.0894, -0.0894, -0.0894, -0.0894, -0.0894],\n",
  243. " [ 0.1070, 0.1070, 0.1070, 0.1070, 0.1070],\n",
  244. " [ 0.0224, 0.0224, 0.0224, 0.0224, 0.0224],\n",
  245. " [-0.0438, -0.0438, -0.0438, -0.0438, -0.0438],\n",
  246. " [ 0.0337, 0.0337, 0.0337, 0.0337, 0.0337],\n",
  247. " [ 0.0952, 0.0952, 0.0952, 0.0952, 0.0952],\n",
  248. " [-0.0258, -0.0258, -0.0258, -0.0258, -0.0258],\n",
  249. " [-0.0494, -0.0494, -0.0494, -0.0494, -0.0494],\n",
  250. " [-0.0063, -0.0063, -0.0063, -0.0063, -0.0063],\n",
  251. " [ 0.0318, 0.0318, 0.0318, 0.0318, 0.0318],\n",
  252. " [-0.0824, -0.0824, -0.0824, -0.0824, -0.0824],\n",
  253. " [ 0.0340, 0.0340, 0.0340, 0.0340, 0.0340]])\n"
  254. ]
  255. }
  256. ],
  257. "source": [
  258. "# 得到 w 的梯度\n",
  259. "print(w.grad)"
  260. ]
  261. },
  262. {
  263. "cell_type": "markdown",
  264. "metadata": {},
  265. "source": [
  266. "上面数学公式就更加复杂,矩阵乘法之后对两个矩阵对应元素相乘,然后所有元素求平均,有兴趣的同学可以手动去计算一下梯度,使用 PyTorch 的自动求导,我们能够非常容易得到 x, y 和 w 的导数,因为深度学习中充满大量的矩阵运算,所以我们没有办法手动去求这些导数,有了自动求导能够非常方便地解决网络更新的问题。"
  267. ]
  268. },
  269. {
  270. "cell_type": "markdown",
  271. "metadata": {},
  272. "source": [
  273. "\n"
  274. ]
  275. },
  276. {
  277. "cell_type": "markdown",
  278. "metadata": {},
  279. "source": [
  280. "## 复杂情况的自动求导\n",
  281. "上面我们展示了简单情况下的自动求导,都是对标量进行自动求导,可能你会有一个疑问,如何对一个向量或者矩阵自动求导了呢?感兴趣的同学可以自己先去尝试一下,下面我们会介绍对多维数组的自动求导机制。"
  282. ]
  283. },
  284. {
  285. "cell_type": "code",
  286. "execution_count": 15,
  287. "metadata": {},
  288. "outputs": [
  289. {
  290. "name": "stdout",
  291. "output_type": "stream",
  292. "text": [
  293. "tensor([[2., 3.]], requires_grad=True)\n",
  294. "tensor([[0., 0.]])\n"
  295. ]
  296. }
  297. ],
  298. "source": [
  299. "m = Variable(torch.FloatTensor([[2, 3]]), requires_grad=True) # 构建一个 1 x 2 的矩阵\n",
  300. "n = Variable(torch.zeros(1, 2)) # 构建一个相同大小的 0 矩阵\n",
  301. "print(m)\n",
  302. "print(n)"
  303. ]
  304. },
  305. {
  306. "cell_type": "code",
  307. "execution_count": 16,
  308. "metadata": {},
  309. "outputs": [
  310. {
  311. "name": "stdout",
  312. "output_type": "stream",
  313. "text": [
  314. "tensor(2., grad_fn=<SelectBackward>)\n",
  315. "tensor([[ 4., 27.]], grad_fn=<CopySlices>)\n"
  316. ]
  317. }
  318. ],
  319. "source": [
  320. "# 通过 m 中的值计算新的 n 中的值\n",
  321. "print(m[0,0])\n",
  322. "n[0, 0] = m[0, 0] ** 2\n",
  323. "n[0, 1] = m[0, 1] ** 3\n",
  324. "print(n)"
  325. ]
  326. },
  327. {
  328. "cell_type": "markdown",
  329. "metadata": {},
  330. "source": [
  331. "将上面的式子写成数学公式,可以得到 \n",
  332. "$$\n",
  333. "n = (n_0,\\ n_1) = (m_0^2,\\ m_1^3) = (2^2,\\ 3^3) \n",
  334. "$$"
  335. ]
  336. },
  337. {
  338. "cell_type": "markdown",
  339. "metadata": {},
  340. "source": [
  341. "下面我们直接对 n 进行反向传播,也就是求 n 对 m 的导数。\n",
  342. "\n",
  343. "这时我们需要明确这个导数的定义,即如何定义\n",
  344. "\n",
  345. "$$\n",
  346. "\\frac{\\partial n}{\\partial m} = \\frac{\\partial (n_0,\\ n_1)}{\\partial (m_0,\\ m_1)}\n",
  347. "$$\n"
  348. ]
  349. },
  350. {
  351. "cell_type": "markdown",
  352. "metadata": {},
  353. "source": [
  354. "在 PyTorch 中,如果要调用自动求导,需要往`backward()`中传入一个参数,这个参数的形状和 n 一样大,比如是 $(w_0,\\ w_1)$,那么自动求导的结果就是:\n",
  355. "$$\n",
  356. "\\frac{\\partial n}{\\partial m_0} = w_0 \\frac{\\partial n_0}{\\partial m_0} + w_1 \\frac{\\partial n_1}{\\partial m_0}\n",
  357. "$$\n",
  358. "$$\n",
  359. "\\frac{\\partial n}{\\partial m_1} = w_0 \\frac{\\partial n_0}{\\partial m_1} + w_1 \\frac{\\partial n_1}{\\partial m_1}\n",
  360. "$$"
  361. ]
  362. },
  363. {
  364. "cell_type": "code",
  365. "execution_count": 17,
  366. "metadata": {},
  367. "outputs": [],
  368. "source": [
  369. "n.backward(torch.ones_like(n)) # 将 (w0, w1) 取成 (1, 1)"
  370. ]
  371. },
  372. {
  373. "cell_type": "code",
  374. "execution_count": 18,
  375. "metadata": {},
  376. "outputs": [
  377. {
  378. "name": "stdout",
  379. "output_type": "stream",
  380. "text": [
  381. "tensor([[ 4., 27.]])\n"
  382. ]
  383. }
  384. ],
  385. "source": [
  386. "print(m.grad)"
  387. ]
  388. },
  389. {
  390. "cell_type": "markdown",
  391. "metadata": {},
  392. "source": [
  393. "通过自动求导我们得到了梯度是 4 和 27,我们可以验算一下\n",
  394. "$$\n",
  395. "\\frac{\\partial n}{\\partial m_0} = w_0 \\frac{\\partial n_0}{\\partial m_0} + w_1 \\frac{\\partial n_1}{\\partial m_0} = 2 m_0 + 0 = 2 \\times 2 = 4\n",
  396. "$$\n",
  397. "$$\n",
  398. "\\frac{\\partial n}{\\partial m_1} = w_0 \\frac{\\partial n_0}{\\partial m_1} + w_1 \\frac{\\partial n_1}{\\partial m_1} = 0 + 3 m_1^2 = 3 \\times 3^2 = 27\n",
  399. "$$\n",
  400. "通过验算我们可以得到相同的结果"
  401. ]
  402. },
  403. {
  404. "cell_type": "markdown",
  405. "metadata": {},
  406. "source": [
  407. "\n"
  408. ]
  409. },
  410. {
  411. "cell_type": "markdown",
  412. "metadata": {},
  413. "source": [
  414. "## 多次自动求导\n",
  415. "通过调用 backward 我们可以进行一次自动求导,如果我们再调用一次 backward,会发现程序报错,没有办法再做一次。这是因为 PyTorch 默认做完一次自动求导之后,计算图就被丢弃了,所以两次自动求导需要手动设置一个东西,我们通过下面的小例子来说明。"
  416. ]
  417. },
  418. {
  419. "cell_type": "code",
  420. "execution_count": 4,
  421. "metadata": {},
  422. "outputs": [
  423. {
  424. "name": "stdout",
  425. "output_type": "stream",
  426. "text": [
  427. "tensor([18.], grad_fn=<AddBackward0>)\n"
  428. ]
  429. }
  430. ],
  431. "source": [
  432. "x = Variable(torch.FloatTensor([3]), requires_grad=True)\n",
  433. "y = x * 2 + x ** 2 + 3\n",
  434. "print(y)"
  435. ]
  436. },
  437. {
  438. "cell_type": "code",
  439. "execution_count": 5,
  440. "metadata": {},
  441. "outputs": [],
  442. "source": [
  443. "y.backward(retain_graph=True) # 设置 retain_graph 为 True 来保留计算图"
  444. ]
  445. },
  446. {
  447. "cell_type": "code",
  448. "execution_count": 6,
  449. "metadata": {},
  450. "outputs": [
  451. {
  452. "name": "stdout",
  453. "output_type": "stream",
  454. "text": [
  455. "tensor([8.])\n"
  456. ]
  457. }
  458. ],
  459. "source": [
  460. "print(x.grad)"
  461. ]
  462. },
  463. {
  464. "cell_type": "code",
  465. "execution_count": 7,
  466. "metadata": {},
  467. "outputs": [],
  468. "source": [
  469. "y.backward() # 再做一次自动求导,这次不保留计算图"
  470. ]
  471. },
  472. {
  473. "cell_type": "code",
  474. "execution_count": 8,
  475. "metadata": {},
  476. "outputs": [
  477. {
  478. "name": "stdout",
  479. "output_type": "stream",
  480. "text": [
  481. "tensor([16.])\n"
  482. ]
  483. }
  484. ],
  485. "source": [
  486. "print(x.grad)"
  487. ]
  488. },
  489. {
  490. "cell_type": "markdown",
  491. "metadata": {},
  492. "source": [
  493. "可以发现 x 的梯度变成了 16,因为这里做了两次自动求导,所以讲第一次的梯度 8 和第二次的梯度 8 加起来得到了 16 的结果。"
  494. ]
  495. },
  496. {
  497. "cell_type": "markdown",
  498. "metadata": {},
  499. "source": [
  500. "\n"
  501. ]
  502. },
  503. {
  504. "cell_type": "markdown",
  505. "metadata": {},
  506. "source": [
  507. "**小练习**\n",
  508. "\n",
  509. "定义\n",
  510. "\n",
  511. "$$\n",
  512. "x = \n",
  513. "\\left[\n",
  514. "\\begin{matrix}\n",
  515. "x_0 \\\\\n",
  516. "x_1\n",
  517. "\\end{matrix}\n",
  518. "\\right] = \n",
  519. "\\left[\n",
  520. "\\begin{matrix}\n",
  521. "2 \\\\\n",
  522. "3\n",
  523. "\\end{matrix}\n",
  524. "\\right]\n",
  525. "$$\n",
  526. "\n",
  527. "$$\n",
  528. "k = (k_0,\\ k_1) = (x_0^2 + 3 x_1,\\ 2 x_0 + x_1^2)\n",
  529. "$$\n",
  530. "\n",
  531. "我们希望求得\n",
  532. "\n",
  533. "$$\n",
  534. "j = \\left[\n",
  535. "\\begin{matrix}\n",
  536. "\\frac{\\partial k_0}{\\partial x_0} & \\frac{\\partial k_0}{\\partial x_1} \\\\\n",
  537. "\\frac{\\partial k_1}{\\partial x_0} & \\frac{\\partial k_1}{\\partial x_1}\n",
  538. "\\end{matrix}\n",
  539. "\\right]\n",
  540. "$$\n",
  541. "\n",
  542. "参考答案:\n",
  543. "\n",
  544. "$$\n",
  545. "\\left[\n",
  546. "\\begin{matrix}\n",
  547. "4 & 3 \\\\\n",
  548. "2 & 6 \\\\\n",
  549. "\\end{matrix}\n",
  550. "\\right]\n",
  551. "$$"
  552. ]
  553. },
  554. {
  555. "cell_type": "code",
  556. "execution_count": 21,
  557. "metadata": {},
  558. "outputs": [],
  559. "source": [
  560. "x = Variable(torch.FloatTensor([2, 3]), requires_grad=True)\n",
  561. "k = Variable(torch.zeros(2))\n",
  562. "\n",
  563. "k[0] = x[0] ** 2 + 3 * x[1]\n",
  564. "k[1] = x[1] ** 2 + 2 * x[0]"
  565. ]
  566. },
  567. {
  568. "cell_type": "code",
  569. "execution_count": 18,
  570. "metadata": {},
  571. "outputs": [],
  572. "source": [
  573. "#k.backward(torch.ones_like(k)) \n",
  574. "#print(x.grad)\n",
  575. "# 和上一个的区别在于该算法是求得导数和,并不是分布求解。"
  576. ]
  577. },
  578. {
  579. "cell_type": "code",
  580. "execution_count": 22,
  581. "metadata": {},
  582. "outputs": [
  583. {
  584. "name": "stdout",
  585. "output_type": "stream",
  586. "text": [
  587. "tensor([13., 13.], grad_fn=<CopySlices>)\n",
  588. "tensor([4., 3.])\n",
  589. "tensor([2., 6.])\n"
  590. ]
  591. }
  592. ],
  593. "source": [
  594. "j = torch.zeros(2, 2)\n",
  595. "k.backward(torch.FloatTensor([1, 0]), retain_graph=True)\n",
  596. "print(k)\n",
  597. "j[0] = x.grad.data\n",
  598. "print(x.grad.data)\n",
  599. "\n",
  600. "x.grad.data.zero_() # 归零之前求得的梯度\n",
  601. "\n",
  602. "k.backward(torch.FloatTensor([0, 1]))\n",
  603. "j[1] = x.grad.data\n",
  604. "print(x.grad.data)\n"
  605. ]
  606. },
  607. {
  608. "cell_type": "code",
  609. "execution_count": 12,
  610. "metadata": {},
  611. "outputs": [
  612. {
  613. "name": "stdout",
  614. "output_type": "stream",
  615. "text": [
  616. "tensor([13., 13.], grad_fn=<CopySlices>)\n"
  617. ]
  618. }
  619. ],
  620. "source": [
  621. "print(k)"
  622. ]
  623. },
  624. {
  625. "cell_type": "code",
  626. "execution_count": 13,
  627. "metadata": {},
  628. "outputs": [
  629. {
  630. "name": "stdout",
  631. "output_type": "stream",
  632. "text": [
  633. "tensor([[4., 3.],\n",
  634. " [2., 6.]])\n"
  635. ]
  636. }
  637. ],
  638. "source": [
  639. "print(j)"
  640. ]
  641. },
  642. {
  643. "cell_type": "markdown",
  644. "metadata": {},
  645. "source": [
  646. "下一次课我们会介绍两种神经网络的编程方式,动态图编程和静态图编程"
  647. ]
  648. }
  649. ],
  650. "metadata": {
  651. "kernelspec": {
  652. "display_name": "Python 3",
  653. "language": "python",
  654. "name": "python3"
  655. },
  656. "language_info": {
  657. "codemirror_mode": {
  658. "name": "ipython",
  659. "version": 3
  660. },
  661. "file_extension": ".py",
  662. "mimetype": "text/x-python",
  663. "name": "python",
  664. "nbconvert_exporter": "python",
  665. "pygments_lexer": "ipython3",
  666. "version": "3.6.9"
  667. }
  668. },
  669. "nbformat": 4,
  670. "nbformat_minor": 2
  671. }

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