From 43c5a01e20b581c8f0be3dbe375bef0202c7aaea Mon Sep 17 00:00:00 2001 From: yinkanglong_lab Date: Mon, 22 Mar 2021 23:35:27 +0800 Subject: [PATCH] =?UTF-8?q?pytorch=E8=B5=B7=E9=A3=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Sklearn/sklearn-cookbook-zh/2.ipynb | 139 ++ Sklearn/sklearn-cookbook-zh/5.ipynb | 82 + pytorch/README.md | 1 - pytorch/{ => 个人教程}/01.md | 0 pytorch/{ => 个人教程}/02.md | 0 pytorch/{ => 个人教程}/03.md | 0 pytorch/{ => 个人教程}/04.md | 0 pytorch/{ => 个人教程}/05.md | 0 pytorch/{ => 个人教程}/06.md | 0 pytorch/{ => 个人教程}/07.md | 0 pytorch/{ => 个人教程}/08.md | 0 pytorch/{ => 个人教程}/09.md | 0 pytorch/{ => 个人教程}/10.md | 0 pytorch/{ => 个人教程}/11.md | 0 pytorch/{ => 个人教程}/12.md | 0 pytorch/{ => 个人教程}/13.md | 0 pytorch/{ => 个人教程}/14.md | 0 pytorch/{ => 个人教程}/15.md | 0 pytorch/{ => 个人教程}/16.md | 0 pytorch/{ => 个人教程}/17.md | 0 pytorch/{ => 个人教程}/18.md | 0 pytorch/{ => 个人教程}/19.md | 0 pytorch/{ => 个人教程}/20.md | 0 pytorch/{ => 个人教程}/21.md | 0 pytorch/{ => 个人教程}/22.md | 0 pytorch/{ => 个人教程}/23.md | 0 pytorch/{ => 个人教程}/24.md | 0 pytorch/{ => 个人教程}/25.md | 0 pytorch/{ => 个人教程}/26.md | 0 pytorch/{ => 个人教程}/SUMMARY.md | 0 .../img/03f4667f9aae4918338a56b74865a389.png | Bin .../img/04a6040ad4f06a69a92f440ea17dde44.png | Bin .../img/13e0473ef73a9de2569a81c62e30d054.png | Bin .../img/1b292936f4a0c3be1d04e43a994fd48c.png | Bin .../img/1f0b990d5a8d78692d3730d855fe44ea.png | Bin .../img/20e2ebdf112e4aa3202e951e072c2dc2.png | Bin .../img/22309cd02ee52b3a65e1f0022e8b964e.png | Bin .../img/25959870b2b1e7d6fd61229cb20bed29.png | Bin .../img/25ed82d9ef8a8b1c9c60445c7c08c732.png | Bin .../img/2fc34594dcb247d4a3414467eed4a109.png | Bin .../img/388ca39bf710c8f053f533ad10872cd7.png | Bin .../img/4d69c0a49be83a66f774caf12e64c3a7.png | Bin .../img/5a415b795ebbb116db6d4a2394d93b27.png | Bin .../img/6730e1145d2a40e8ced1fda4d453d9c6.png | Bin .../img/68f39521fc6853acdf26440e7d5a2861.png | Bin .../img/7345448d48d8d6c6c1b03fda91334e3e.png | Bin .../img/761c210ceb0fdd69c7e0f8bd85e39698.png | Bin .../img/7a8716c377832b032ee24276b7ddcc31.png | Bin .../img/7eca2f8318f254b17ca0bc215ec4f5a0.png | Bin .../img/90e1ab65f286c889d94c9f6c57d596c9.png | Bin .../img/94268b7d9687d039d872da203453c97b.png | Bin .../img/99c72d57612c137b62599837526f0e0e.png | Bin .../img/9e1df524980c8f42ab4353070c2a1b74.png | Bin .../img/a545e4a49909bd7a80e042fd6d8267cb.png | Bin .../img/a577eb2dc81a64cfc4f6d04ff9a25873.png | Bin .../img/b708f231f544bd7bcefa1d55c82653dd.png | Bin .../img/bbd3ae66e0235fac8745c37306e74a52.png | Bin .../img/bce7313d5ac6f2600b62a4962a6daf3a.png | Bin .../img/c2914d88b6f17b84982e162cf6930a88.png | Bin .../img/c429fb827df769a542339e200e2ea20c.png | Bin .../img/c42f3cec435a83431d5a1737e99b8b8c.png | Bin .../img/c8011979fa20046cbfa36e46cf508689.png | Bin .../img/cb2138c3f800c7ca4b5ae38076d09429.png | Bin .../img/f1108a1b6941305fa7a39e488c023fe9.png | Bin .../img/f38868821469cadc36810cfd827511d1.png | Bin .../img/f790e22ee4be05f818e52467c2f13b37.png | Bin .../img/febe7e5dc5d5b9a5004d15c50d3228c1.png | Bin .../img/fedaa24e2fcad876c77a2038c2d8d14d.png | Bin .../img/ffeedc89cc695e61aa6e941c1c696a39.png | Bin pytorch/官方教程/01.md | 1 + pytorch/官方教程/02.md | 39 + pytorch/官方教程/03.md | 292 +++ pytorch/官方教程/04.md | 236 +++ pytorch/官方教程/05.md | 292 +++ pytorch/官方教程/06.md | 421 ++++ pytorch/官方教程/07.md | 631 ++++++ pytorch/官方教程/08.md | 59 + pytorch/官方教程/09.md | 64 + pytorch/官方教程/10.md | 77 + pytorch/官方教程/11.md | 103 + pytorch/官方教程/12.md | 87 + pytorch/官方教程/13.md | 71 + pytorch/官方教程/14.md | 75 + pytorch/官方教程/15.md | 82 + pytorch/官方教程/16.md | 971 ++++++++++ pytorch/官方教程/17.md | 348 ++++ pytorch/官方教程/18.md | 1 + pytorch/官方教程/19.md | 453 +++++ pytorch/官方教程/20.md | 590 ++++++ pytorch/官方教程/21.md | 301 +++ pytorch/官方教程/22.md | 735 +++++++ pytorch/官方教程/23.md | 1 + pytorch/官方教程/24.md | 499 +++++ pytorch/官方教程/25.md | 456 +++++ pytorch/官方教程/26.md | 1 + pytorch/官方教程/27.md | 329 ++++ pytorch/官方教程/28.md | 555 ++++++ pytorch/官方教程/29.md | 426 ++++ pytorch/官方教程/30.md | 794 ++++++++ pytorch/官方教程/31.md | 348 ++++ pytorch/官方教程/32.md | 501 +++++ pytorch/官方教程/33.md | 1 + pytorch/官方教程/34.md | 396 ++++ pytorch/官方教程/35.md | 671 +++++++ pytorch/官方教程/36.md | 1 + pytorch/官方教程/37.md | 319 +++ pytorch/官方教程/38.md | 480 +++++ pytorch/官方教程/39.md | 298 +++ pytorch/官方教程/40.md | 219 +++ pytorch/官方教程/41.md | 1 + pytorch/官方教程/42.md | 607 ++++++ pytorch/官方教程/43.md | 416 ++++ pytorch/官方教程/44.md | 965 ++++++++++ pytorch/官方教程/45.md | 996 ++++++++++ pytorch/官方教程/46.md | 782 ++++++++ pytorch/官方教程/47.md | 529 +++++ pytorch/官方教程/48.md | 233 +++ pytorch/官方教程/49.md | 414 ++++ pytorch/官方教程/50.md | 244 +++ pytorch/官方教程/51.md | 1 + pytorch/官方教程/52.md | 285 +++ pytorch/官方教程/53.md | 1711 +++++++++++++++++ pytorch/官方教程/54.md | 781 ++++++++ pytorch/官方教程/55.md | 398 ++++ pytorch/官方教程/56.md | 444 +++++ pytorch/官方教程/57.md | 813 ++++++++ pytorch/官方教程/58.md | 431 +++++ pytorch/官方教程/59.md | 1 + pytorch/官方教程/60.md | 73 + pytorch/官方教程/61.md | 263 +++ pytorch/官方教程/62.md | 224 +++ pytorch/官方教程/63.md | 385 ++++ pytorch/官方教程/64.md | 467 +++++ pytorch/官方教程/65.md | 412 ++++ pytorch/官方教程/66.md | 292 +++ pytorch/官方教程/67.md | 393 ++++ pytorch/官方教程/68.md | 234 +++ pytorch/官方教程/README.md | 35 + pytorch/官方教程/SUMMARY.md | 71 + pytorch/官方教程/book.json | 176 ++ .../img/029a9d26725997aae97e9e3f6f10067f.png | Bin 0 -> 15068 bytes .../img/049e79b05a41598709a2aeef166e4a2a.png | Bin 0 -> 47233 bytes .../img/04ee335faf821b337dba0c4d7ccb0b67.png | Bin 0 -> 3397 bytes .../img/04fb3a8ed8e63cf7cffb5f29224decca.png | Bin 0 -> 80358 bytes .../img/063cdb1f0b70bc4c83494b9819c6a3f5.png | Bin 0 -> 7098 bytes .../img/08bcfed65e8ab03ac7f380e20d421434.png | Bin 0 -> 3979 bytes .../img/097cd68a7de6371c697afbe4230ef328.png | Bin 0 -> 7024 bytes .../img/0a7a97c39d6dfc0e08d2701eb7a49231.png | Bin 0 -> 1483 bytes .../img/0c7a402331744a44f5e17575b1607904.png | Bin 0 -> 1611 bytes .../img/0ef9693f0008d5a75aa5ac2b542b83ac.png | Bin 0 -> 13695 bytes .../img/1226e2e8b7633b50c2c45ce699d8f71f.png | Bin 0 -> 4923 bytes .../img/1270bde38f2cfccd4900a5df8ac70a7d.png | Bin 0 -> 2943 bytes .../img/1af46e992c93618e7ba22e311f063d1b.png | Bin 0 -> 5611 bytes .../img/1c451df4406aea85e640d1ae7df6df31.png | Bin 0 -> 6181 bytes .../img/20ef8681366b44461cf49d1ab98ab8f2.png | Bin 0 -> 4284 bytes .../img/28a4f1426695fb55f1f6bc86278f6547.png | Bin 0 -> 5235 bytes .../img/2a31b55ef7bfff0c24c35bc635656078.png | Bin 0 -> 76825 bytes .../img/30f766e7717c0e45a583a4f58ebc322a.png | Bin 0 -> 4650 bytes .../img/3250cbba812d68265cf7815d987bcd1b.png | Bin 0 -> 9416 bytes .../img/32ec68a6e0d29efae32b0f50db877598.png | Bin 0 -> 4996 bytes .../img/3313f4800c7d01049e2a2ef2079e5905.png | Bin 0 -> 2296 bytes .../img/335fb81e535f98bfda7cbdb3e50d8832.png | Bin 0 -> 3397 bytes .../img/342d5d0add3b5754dae73ff222bbc543.png | Bin 0 -> 62523 bytes .../img/34b376e0c7299810f7349ab99c2c5497.png | Bin 0 -> 1995 bytes .../img/35d54d0c48ca1c52d56850a202a2c160.png | Bin 0 -> 10685 bytes .../img/3aa3584628cb0526c8b0e9d02b15d876.png | Bin 0 -> 6315 bytes .../img/3fae03d85aed3a2237fd4b2f7fb7b480.png | Bin 0 -> 1192 bytes .../img/4262b5e808a503bf338ce30fb37e6db9.png | Bin 0 -> 6154 bytes .../img/45cf97ab2bd8f85e41c99cd60c565619.png | Bin 0 -> 7257 bytes .../img/462373919a0dfe17cd816fa0d8af140c.png | Bin 0 -> 1440 bytes .../img/48d2e67f025b05eeb9259e249566add3.png | Bin 0 -> 3710 bytes .../img/4a48977cd9545f897942a4a4ef1175ac.png | Bin 0 -> 14081 bytes .../img/4b79dddf1ff54b9384754144d8246d9b.png | Bin 0 -> 35130 bytes .../img/4d4a02b1af752dcb28b536a50d0f9ee4.png | Bin 0 -> 136 bytes .../img/5015200eb4481feb8a71a658b384ec39.png | Bin 0 -> 136 bytes .../img/525847c9d4b48933cb231204a2d13e0e.png | Bin 0 -> 5867 bytes .../img/5412faceb18bc6fa2823be3ae1bdfd8d.png | Bin 0 -> 1552 bytes .../img/54625e60404f9c98f34cf32ca56bb118.png | Bin 0 -> 16425 bytes .../img/592fae78143370fffc1d0c7957706384.png | Bin 0 -> 2307 bytes .../img/5ad82e2b23a82287af2caa2fe4b316b3.png | Bin 0 -> 4664 bytes .../img/5c33a15f9b0da3f9377dc63f70bb58a7.png | Bin 0 -> 2636 bytes .../img/611c2725bdfb89e258da9a99fca53433.png | Bin 0 -> 38085 bytes .../img/62754b628ac962d094ed602f9067fcf2.png | Bin 0 -> 4781 bytes .../img/6b495cb0cd4336a2469d9f07696faa3e.png | Bin 0 -> 23000 bytes .../img/6e09db671ada03c61bdd1f32b6a7624b.png | Bin 0 -> 4872 bytes .../img/7633144b009ac008488a6bd051f404c9.png | Bin 0 -> 4364 bytes .../img/77e0660b596f377125122a2409288181.png | Bin 0 -> 1431 bytes .../img/7a28f697e6bab9f3d9b1e8da4a5a5249.png | Bin 0 -> 20640 bytes .../img/7c783def0bbe536f41ed172041b7e89e.png | Bin 0 -> 6422 bytes .../img/7e8670a3b7cdc7848394514ef1da090a.png | Bin 0 -> 6114 bytes .../img/7f2d776cf49fcf3fd44fd84a238a3cc6.png | Bin 0 -> 3102 bytes .../img/7fa129004e942671707f8f2d4fb80a20.png | Bin 0 -> 1521 bytes .../img/8130c72979511b4b2daddcb2d909388a.png | Bin 0 -> 1679 bytes .../img/85974d98be6202902f21ce274418953f.png | Bin 0 -> 17987 bytes .../img/85fee85630aaace1c60fe5ba0df8c795.png | Bin 0 -> 51016 bytes .../img/87aa5017f5f0ba9a29d66e74ac6b3d1a.png | Bin 0 -> 3397 bytes .../img/8879aed8539537d699fb0d155b55b403.png | Bin 0 -> 10092 bytes .../img/89adff7333b116436cf785388029ba1a.png | Bin 0 -> 5970 bytes .../img/8b09d6361316e495383ceedf9b8407ea.png | Bin 0 -> 55030 bytes .../img/8ec7228e178647ed9c25273de4b9a270.png | Bin 0 -> 5509 bytes .../img/8f596b99dbb3c262b61db267d5db2d63.png | Bin 0 -> 70390 bytes .../img/901c72128f102e0be23409cd1d103a9b.png | Bin 0 -> 4957 bytes .../img/90c999fe7ccda5e8a8fb0f86000d887f.png | Bin 0 -> 7020 bytes .../img/931dea1655c975ec616a9e22c80c242f.png | Bin 0 -> 3724 bytes .../img/97b434ffec8449a196f698b23197df05.png | Bin 0 -> 5226 bytes .../img/9ae42af4b6629f7493bc1bc150af6355.png | Bin 0 -> 4781 bytes .../img/9b7e299515676cf41cd2c0fd6ab1295d.png | Bin 0 -> 1582 bytes .../img/9d53a7aba4b9016ea39aa794905ee059.png | Bin 0 -> 4175 bytes .../img/a2eafa804c5b1d5c8564675a255507b2.png | Bin 0 -> 5903 bytes .../img/a5c5d931ed12e34bf68476f4f157b780.png | Bin 0 -> 3397 bytes .../img/aaf8c905effc5044cb9691420e5261fa.png | Bin 0 -> 11945 bytes .../img/ac8752539498c11001a65c1ff470d696.png | Bin 0 -> 80330 bytes .../img/ad48ffbd1cfc0475d744b8b89a0d962a.png | Bin 0 -> 5388 bytes .../img/ae800707f2489607d51d67499071db16.png | Bin 0 -> 30944 bytes .../img/afd408b97567c661cc8cb8a80c7c777c.png | Bin 0 -> 78141 bytes .../img/afda8238ecd1f547d61be4d155844f68.png | Bin 0 -> 20723 bytes .../img/b01274082109b1019682274a0d4ca4d8.png | Bin 0 -> 3908 bytes .../img/b1ba956974f3e844b0b0cea490cc1148.png | Bin 0 -> 4232 bytes .../img/b3f0b96ed8ba751fee4a5fc7ca878eb1.png | Bin 0 -> 3397 bytes .../img/b43b70d8a6eef9ea4f75867b5e83b483.png | Bin 0 -> 29291 bytes .../img/be538c850b645a41a7a77ff388954e14.png | Bin 0 -> 18441 bytes .../img/be60e8e1f4baa0de87cf9d37c5325525.png | Bin 0 -> 4216 bytes .../img/beccc5ac5df1571304e11d6b12772a99.png | Bin 0 -> 5625 bytes .../img/bf0b252ce2d39ba6da26c16bee984d39.png | Bin 0 -> 3397 bytes .../img/c0f8a413c1f6dd23bb137d8adff1adda.png | Bin 0 -> 122782 bytes .../img/c814c5c2350e00cf5fc0d883acf0843c.png | Bin 0 -> 2492 bytes .../img/c9d3ddd13da5858e2cb03b53753ece3c.png | Bin 0 -> 3677 bytes .../img/cc57a36a43d450df4bfc1d1d1b1ce274.png | Bin 0 -> 4468 bytes .../img/d0d82c063f83a0ba4bb8df4dcec57138.png | Bin 0 -> 2002 bytes .../img/d148a5bd51a3278e9698bba522cbc34a.png | Bin 0 -> 11320 bytes .../img/d15de2be2b754f9a4f46418764232b5e.png | Bin 0 -> 40274 bytes .../img/d5ab1f07cb4a9d9200c2a2d3b238340d.png | Bin 0 -> 157215 bytes .../img/d74012096c3134b776b5e9f70e8178f3.png | Bin 0 -> 90361 bytes .../img/e21cb5ec883a2e5dceeff4064add3acd.png | Bin 0 -> 8365 bytes .../img/e46d7dbb0cc58ac0895589bf255444be.png | Bin 0 -> 2895 bytes .../img/ea0bddb69dfbd67215b823007544ab8f.png | Bin 0 -> 3397 bytes .../img/ebec7787362bc53fe2289e5740da5756.png | Bin 0 -> 18697 bytes .../img/efb29904552d032a076d8512d4e60b95.png | Bin 0 -> 73798 bytes .../img/f29264b289639882a61fb5c3447b1ecc.png | Bin 0 -> 2332 bytes .../img/f4990a0920dff7e4647a23cfc1639a8a.png | Bin 0 -> 42628 bytes .../img/f5504c7ed93640f2bed4d2a606c015ba.png | Bin 0 -> 4081 bytes .../img/fed25c69a6015a90b6e9406e4ac6e01c.png | Bin 0 -> 19024 bytes .../img/ffad28c33f8a48d06521421f1aa441ed.png | Bin 0 -> 3397 bytes pytorch/官方教程/img/tex21-1.gif | Bin 0 -> 2306 bytes pytorch/官方教程/img/tex22-1.gif | Bin 0 -> 2339 bytes pytorch/官方教程/img/tex22-2.gif | Bin 0 -> 1706 bytes pytorch/官方教程/img/tex27-1.gif | Bin 0 -> 18636 bytes pytorch/官方教程/img/tex34-1.gif | Bin 0 -> 875 bytes pytorch/官方教程/img/tex34-2.gif | Bin 0 -> 925 bytes pytorch/官方教程/img/tex34-3.gif | Bin 0 -> 1076 bytes pytorch/官方教程/img/tex34-4.gif | Bin 0 -> 1029 bytes pytorch/官方教程/img/tex34-5.gif | Bin 0 -> 8852 bytes pytorch/官方教程/img/tex35-1.gif | Bin 0 -> 690 bytes pytorch/官方教程/img/tex35-2.gif | Bin 0 -> 1611 bytes pytorch/官方教程/img/tex35-3.gif | Bin 0 -> 1044 bytes pytorch/官方教程/img/tex35-4.gif | Bin 0 -> 525 bytes pytorch/官方教程/img/tex4-1.gif | Bin 0 -> 441 bytes pytorch/官方教程/img/tex4-2.gif | Bin 0 -> 535 bytes pytorch/官方教程/img/tex4-3.gif | Bin 0 -> 517 bytes pytorch/官方教程/img/tex4-4.gif | Bin 0 -> 439 bytes pytorch/官方教程/img/tex4-5.gif | Bin 0 -> 13131 bytes pytorch/官方教程/img/tex4-6.gif | Bin 0 -> 880 bytes pytorch/官方教程/img/tex4-7.gif | Bin 0 -> 16590 bytes pytorch/官方教程/img/tex56-1.gif | Bin 0 -> 1342 bytes pytorch/实战/1.ipynb | 213 ++ 工作日志/2021年3月19日-四月份计划.md | 58 +- 工作日志/2021年3月22日-今日计划.md | 36 +- .../机器学习开发日志/3 两种生成随机布尔屏蔽.ipynb | 41 +- .../机器学习开发日志/4 sklearn中的sgd说明.ipynb | 120 ++ 269 files changed, 25968 insertions(+), 23 deletions(-) create mode 100644 Sklearn/sklearn-cookbook-zh/2.ipynb create mode 100644 Sklearn/sklearn-cookbook-zh/5.ipynb delete mode 100644 pytorch/README.md rename pytorch/{ => 个人教程}/01.md (100%) rename pytorch/{ => 个人教程}/02.md (100%) rename pytorch/{ => 个人教程}/03.md (100%) rename pytorch/{ => 个人教程}/04.md (100%) rename pytorch/{ => 个人教程}/05.md (100%) rename pytorch/{ => 个人教程}/06.md (100%) rename pytorch/{ => 个人教程}/07.md (100%) rename pytorch/{ => 个人教程}/08.md (100%) rename pytorch/{ => 个人教程}/09.md (100%) rename pytorch/{ => 个人教程}/10.md (100%) rename pytorch/{ => 个人教程}/11.md (100%) rename pytorch/{ => 个人教程}/12.md (100%) rename pytorch/{ => 个人教程}/13.md (100%) rename pytorch/{ => 个人教程}/14.md (100%) rename pytorch/{ => 个人教程}/15.md (100%) rename pytorch/{ => 个人教程}/16.md (100%) rename pytorch/{ => 个人教程}/17.md (100%) rename pytorch/{ => 个人教程}/18.md (100%) rename pytorch/{ => 个人教程}/19.md (100%) rename pytorch/{ => 个人教程}/20.md (100%) rename pytorch/{ => 个人教程}/21.md (100%) rename pytorch/{ => 个人教程}/22.md (100%) rename pytorch/{ => 个人教程}/23.md (100%) rename pytorch/{ => 个人教程}/24.md (100%) rename pytorch/{ => 个人教程}/25.md (100%) rename pytorch/{ => 个人教程}/26.md (100%) rename pytorch/{ => 个人教程}/SUMMARY.md (100%) rename pytorch/{ => 个人教程}/img/03f4667f9aae4918338a56b74865a389.png (100%) rename pytorch/{ => 个人教程}/img/04a6040ad4f06a69a92f440ea17dde44.png (100%) rename pytorch/{ => 个人教程}/img/13e0473ef73a9de2569a81c62e30d054.png (100%) rename pytorch/{ => 个人教程}/img/1b292936f4a0c3be1d04e43a994fd48c.png (100%) rename pytorch/{ => 个人教程}/img/1f0b990d5a8d78692d3730d855fe44ea.png (100%) rename pytorch/{ => 个人教程}/img/20e2ebdf112e4aa3202e951e072c2dc2.png (100%) rename pytorch/{ => 个人教程}/img/22309cd02ee52b3a65e1f0022e8b964e.png (100%) rename pytorch/{ => 个人教程}/img/25959870b2b1e7d6fd61229cb20bed29.png (100%) rename pytorch/{ => 个人教程}/img/25ed82d9ef8a8b1c9c60445c7c08c732.png (100%) rename pytorch/{ => 个人教程}/img/2fc34594dcb247d4a3414467eed4a109.png (100%) rename pytorch/{ => 个人教程}/img/388ca39bf710c8f053f533ad10872cd7.png (100%) rename pytorch/{ => 个人教程}/img/4d69c0a49be83a66f774caf12e64c3a7.png (100%) rename pytorch/{ => 个人教程}/img/5a415b795ebbb116db6d4a2394d93b27.png (100%) rename pytorch/{ => 个人教程}/img/6730e1145d2a40e8ced1fda4d453d9c6.png (100%) rename pytorch/{ => 个人教程}/img/68f39521fc6853acdf26440e7d5a2861.png (100%) rename pytorch/{ => 个人教程}/img/7345448d48d8d6c6c1b03fda91334e3e.png (100%) rename pytorch/{ => 个人教程}/img/761c210ceb0fdd69c7e0f8bd85e39698.png (100%) rename pytorch/{ => 个人教程}/img/7a8716c377832b032ee24276b7ddcc31.png (100%) rename pytorch/{ => 个人教程}/img/7eca2f8318f254b17ca0bc215ec4f5a0.png (100%) rename pytorch/{ => 个人教程}/img/90e1ab65f286c889d94c9f6c57d596c9.png (100%) rename pytorch/{ => 个人教程}/img/94268b7d9687d039d872da203453c97b.png (100%) rename pytorch/{ => 个人教程}/img/99c72d57612c137b62599837526f0e0e.png (100%) rename pytorch/{ => 个人教程}/img/9e1df524980c8f42ab4353070c2a1b74.png (100%) rename pytorch/{ => 个人教程}/img/a545e4a49909bd7a80e042fd6d8267cb.png (100%) rename pytorch/{ => 个人教程}/img/a577eb2dc81a64cfc4f6d04ff9a25873.png (100%) rename pytorch/{ => 个人教程}/img/b708f231f544bd7bcefa1d55c82653dd.png (100%) rename pytorch/{ => 个人教程}/img/bbd3ae66e0235fac8745c37306e74a52.png (100%) rename pytorch/{ => 个人教程}/img/bce7313d5ac6f2600b62a4962a6daf3a.png (100%) rename pytorch/{ => 个人教程}/img/c2914d88b6f17b84982e162cf6930a88.png (100%) rename pytorch/{ => 个人教程}/img/c429fb827df769a542339e200e2ea20c.png (100%) rename pytorch/{ => 个人教程}/img/c42f3cec435a83431d5a1737e99b8b8c.png (100%) rename pytorch/{ => 个人教程}/img/c8011979fa20046cbfa36e46cf508689.png (100%) rename pytorch/{ => 个人教程}/img/cb2138c3f800c7ca4b5ae38076d09429.png (100%) rename pytorch/{ => 个人教程}/img/f1108a1b6941305fa7a39e488c023fe9.png (100%) rename pytorch/{ => 个人教程}/img/f38868821469cadc36810cfd827511d1.png (100%) rename pytorch/{ => 个人教程}/img/f790e22ee4be05f818e52467c2f13b37.png (100%) rename pytorch/{ => 个人教程}/img/febe7e5dc5d5b9a5004d15c50d3228c1.png (100%) rename pytorch/{ => 个人教程}/img/fedaa24e2fcad876c77a2038c2d8d14d.png (100%) rename pytorch/{ => 个人教程}/img/ffeedc89cc695e61aa6e941c1c696a39.png (100%) create mode 100644 pytorch/官方教程/01.md create mode 100644 pytorch/官方教程/02.md create mode 100644 pytorch/官方教程/03.md create mode 100644 pytorch/官方教程/04.md create mode 100644 pytorch/官方教程/05.md create mode 100644 pytorch/官方教程/06.md create mode 100644 pytorch/官方教程/07.md create mode 100644 pytorch/官方教程/08.md create mode 100644 pytorch/官方教程/09.md create mode 100644 pytorch/官方教程/10.md create mode 100644 pytorch/官方教程/11.md create mode 100644 pytorch/官方教程/12.md create mode 100644 pytorch/官方教程/13.md create mode 100644 pytorch/官方教程/14.md create mode 100644 pytorch/官方教程/15.md create mode 100644 pytorch/官方教程/16.md create mode 100644 pytorch/官方教程/17.md create mode 100644 pytorch/官方教程/18.md create mode 100644 pytorch/官方教程/19.md create mode 100644 pytorch/官方教程/20.md create mode 100644 pytorch/官方教程/21.md create mode 100644 pytorch/官方教程/22.md create mode 100644 pytorch/官方教程/23.md create mode 100644 pytorch/官方教程/24.md create mode 100644 pytorch/官方教程/25.md create mode 100644 pytorch/官方教程/26.md create mode 100644 pytorch/官方教程/27.md create mode 100644 pytorch/官方教程/28.md create mode 100644 pytorch/官方教程/29.md create mode 100644 pytorch/官方教程/30.md create mode 100644 pytorch/官方教程/31.md create mode 100644 pytorch/官方教程/32.md create mode 100644 pytorch/官方教程/33.md create mode 100644 pytorch/官方教程/34.md create mode 100644 pytorch/官方教程/35.md create mode 100644 pytorch/官方教程/36.md create mode 100644 pytorch/官方教程/37.md create mode 100644 pytorch/官方教程/38.md create mode 100644 pytorch/官方教程/39.md create mode 100644 pytorch/官方教程/40.md create mode 100644 pytorch/官方教程/41.md create mode 100644 pytorch/官方教程/42.md create mode 100644 pytorch/官方教程/43.md create mode 100644 pytorch/官方教程/44.md create mode 100644 pytorch/官方教程/45.md create mode 100644 pytorch/官方教程/46.md create mode 100644 pytorch/官方教程/47.md create mode 100644 pytorch/官方教程/48.md create mode 100644 pytorch/官方教程/49.md create mode 100644 pytorch/官方教程/50.md create mode 100644 pytorch/官方教程/51.md create mode 100644 pytorch/官方教程/52.md create mode 100644 pytorch/官方教程/53.md create mode 100644 pytorch/官方教程/54.md create mode 100644 pytorch/官方教程/55.md create mode 100644 pytorch/官方教程/56.md create mode 100644 pytorch/官方教程/57.md create mode 100644 pytorch/官方教程/58.md create mode 100644 pytorch/官方教程/59.md create mode 100644 pytorch/官方教程/60.md create mode 100644 pytorch/官方教程/61.md create mode 100644 pytorch/官方教程/62.md create mode 100644 pytorch/官方教程/63.md create mode 100644 pytorch/官方教程/64.md create mode 100644 pytorch/官方教程/65.md create mode 100644 pytorch/官方教程/66.md create mode 100644 pytorch/官方教程/67.md create mode 100644 pytorch/官方教程/68.md create mode 100644 pytorch/官方教程/README.md create mode 100644 pytorch/官方教程/SUMMARY.md create mode 100644 pytorch/官方教程/book.json create mode 100644 pytorch/官方教程/img/029a9d26725997aae97e9e3f6f10067f.png create mode 100644 pytorch/官方教程/img/049e79b05a41598709a2aeef166e4a2a.png create mode 100644 pytorch/官方教程/img/04ee335faf821b337dba0c4d7ccb0b67.png create mode 100644 pytorch/官方教程/img/04fb3a8ed8e63cf7cffb5f29224decca.png create mode 100644 pytorch/官方教程/img/063cdb1f0b70bc4c83494b9819c6a3f5.png create mode 100644 pytorch/官方教程/img/08bcfed65e8ab03ac7f380e20d421434.png create mode 100644 pytorch/官方教程/img/097cd68a7de6371c697afbe4230ef328.png create mode 100644 pytorch/官方教程/img/0a7a97c39d6dfc0e08d2701eb7a49231.png create mode 100644 pytorch/官方教程/img/0c7a402331744a44f5e17575b1607904.png create mode 100644 pytorch/官方教程/img/0ef9693f0008d5a75aa5ac2b542b83ac.png create mode 100644 pytorch/官方教程/img/1226e2e8b7633b50c2c45ce699d8f71f.png create mode 100644 pytorch/官方教程/img/1270bde38f2cfccd4900a5df8ac70a7d.png create mode 100644 pytorch/官方教程/img/1af46e992c93618e7ba22e311f063d1b.png create mode 100644 pytorch/官方教程/img/1c451df4406aea85e640d1ae7df6df31.png create mode 100644 pytorch/官方教程/img/20ef8681366b44461cf49d1ab98ab8f2.png create mode 100644 pytorch/官方教程/img/28a4f1426695fb55f1f6bc86278f6547.png create mode 100644 pytorch/官方教程/img/2a31b55ef7bfff0c24c35bc635656078.png create mode 100644 pytorch/官方教程/img/30f766e7717c0e45a583a4f58ebc322a.png create mode 100644 pytorch/官方教程/img/3250cbba812d68265cf7815d987bcd1b.png create mode 100644 pytorch/官方教程/img/32ec68a6e0d29efae32b0f50db877598.png create mode 100644 pytorch/官方教程/img/3313f4800c7d01049e2a2ef2079e5905.png create mode 100644 pytorch/官方教程/img/335fb81e535f98bfda7cbdb3e50d8832.png create mode 100644 pytorch/官方教程/img/342d5d0add3b5754dae73ff222bbc543.png create mode 100644 pytorch/官方教程/img/34b376e0c7299810f7349ab99c2c5497.png create mode 100644 pytorch/官方教程/img/35d54d0c48ca1c52d56850a202a2c160.png create mode 100644 pytorch/官方教程/img/3aa3584628cb0526c8b0e9d02b15d876.png create mode 100644 pytorch/官方教程/img/3fae03d85aed3a2237fd4b2f7fb7b480.png create mode 100644 pytorch/官方教程/img/4262b5e808a503bf338ce30fb37e6db9.png create mode 100644 pytorch/官方教程/img/45cf97ab2bd8f85e41c99cd60c565619.png create mode 100644 pytorch/官方教程/img/462373919a0dfe17cd816fa0d8af140c.png create mode 100644 pytorch/官方教程/img/48d2e67f025b05eeb9259e249566add3.png create mode 100644 pytorch/官方教程/img/4a48977cd9545f897942a4a4ef1175ac.png create mode 100644 pytorch/官方教程/img/4b79dddf1ff54b9384754144d8246d9b.png create mode 100644 pytorch/官方教程/img/4d4a02b1af752dcb28b536a50d0f9ee4.png create mode 100644 pytorch/官方教程/img/5015200eb4481feb8a71a658b384ec39.png create mode 100644 pytorch/官方教程/img/525847c9d4b48933cb231204a2d13e0e.png create mode 100644 pytorch/官方教程/img/5412faceb18bc6fa2823be3ae1bdfd8d.png create mode 100644 pytorch/官方教程/img/54625e60404f9c98f34cf32ca56bb118.png create mode 100644 pytorch/官方教程/img/592fae78143370fffc1d0c7957706384.png create mode 100644 pytorch/官方教程/img/5ad82e2b23a82287af2caa2fe4b316b3.png create mode 100644 pytorch/官方教程/img/5c33a15f9b0da3f9377dc63f70bb58a7.png create mode 100644 pytorch/官方教程/img/611c2725bdfb89e258da9a99fca53433.png create mode 100644 pytorch/官方教程/img/62754b628ac962d094ed602f9067fcf2.png create mode 100644 pytorch/官方教程/img/6b495cb0cd4336a2469d9f07696faa3e.png create mode 100644 pytorch/官方教程/img/6e09db671ada03c61bdd1f32b6a7624b.png create mode 100644 pytorch/官方教程/img/7633144b009ac008488a6bd051f404c9.png create mode 100644 pytorch/官方教程/img/77e0660b596f377125122a2409288181.png create mode 100644 pytorch/官方教程/img/7a28f697e6bab9f3d9b1e8da4a5a5249.png create mode 100644 pytorch/官方教程/img/7c783def0bbe536f41ed172041b7e89e.png create mode 100644 pytorch/官方教程/img/7e8670a3b7cdc7848394514ef1da090a.png create mode 100644 pytorch/官方教程/img/7f2d776cf49fcf3fd44fd84a238a3cc6.png create mode 100644 pytorch/官方教程/img/7fa129004e942671707f8f2d4fb80a20.png create mode 100644 pytorch/官方教程/img/8130c72979511b4b2daddcb2d909388a.png create mode 100644 pytorch/官方教程/img/85974d98be6202902f21ce274418953f.png create mode 100644 pytorch/官方教程/img/85fee85630aaace1c60fe5ba0df8c795.png create mode 100644 pytorch/官方教程/img/87aa5017f5f0ba9a29d66e74ac6b3d1a.png create mode 100644 pytorch/官方教程/img/8879aed8539537d699fb0d155b55b403.png create mode 100644 pytorch/官方教程/img/89adff7333b116436cf785388029ba1a.png create mode 100644 pytorch/官方教程/img/8b09d6361316e495383ceedf9b8407ea.png create mode 100644 pytorch/官方教程/img/8ec7228e178647ed9c25273de4b9a270.png create mode 100644 pytorch/官方教程/img/8f596b99dbb3c262b61db267d5db2d63.png create mode 100644 pytorch/官方教程/img/901c72128f102e0be23409cd1d103a9b.png create mode 100644 pytorch/官方教程/img/90c999fe7ccda5e8a8fb0f86000d887f.png create mode 100644 pytorch/官方教程/img/931dea1655c975ec616a9e22c80c242f.png create mode 100644 pytorch/官方教程/img/97b434ffec8449a196f698b23197df05.png create mode 100644 pytorch/官方教程/img/9ae42af4b6629f7493bc1bc150af6355.png create mode 100644 pytorch/官方教程/img/9b7e299515676cf41cd2c0fd6ab1295d.png create mode 100644 pytorch/官方教程/img/9d53a7aba4b9016ea39aa794905ee059.png create mode 100644 pytorch/官方教程/img/a2eafa804c5b1d5c8564675a255507b2.png create mode 100644 pytorch/官方教程/img/a5c5d931ed12e34bf68476f4f157b780.png create mode 100644 pytorch/官方教程/img/aaf8c905effc5044cb9691420e5261fa.png create mode 100644 pytorch/官方教程/img/ac8752539498c11001a65c1ff470d696.png create mode 100644 pytorch/官方教程/img/ad48ffbd1cfc0475d744b8b89a0d962a.png create mode 100644 pytorch/官方教程/img/ae800707f2489607d51d67499071db16.png create mode 100644 pytorch/官方教程/img/afd408b97567c661cc8cb8a80c7c777c.png create mode 100644 pytorch/官方教程/img/afda8238ecd1f547d61be4d155844f68.png create mode 100644 pytorch/官方教程/img/b01274082109b1019682274a0d4ca4d8.png create mode 100644 pytorch/官方教程/img/b1ba956974f3e844b0b0cea490cc1148.png create mode 100644 pytorch/官方教程/img/b3f0b96ed8ba751fee4a5fc7ca878eb1.png create mode 100644 pytorch/官方教程/img/b43b70d8a6eef9ea4f75867b5e83b483.png create mode 100644 pytorch/官方教程/img/be538c850b645a41a7a77ff388954e14.png create mode 100644 pytorch/官方教程/img/be60e8e1f4baa0de87cf9d37c5325525.png create mode 100644 pytorch/官方教程/img/beccc5ac5df1571304e11d6b12772a99.png create mode 100644 pytorch/官方教程/img/bf0b252ce2d39ba6da26c16bee984d39.png create mode 100644 pytorch/官方教程/img/c0f8a413c1f6dd23bb137d8adff1adda.png create mode 100644 pytorch/官方教程/img/c814c5c2350e00cf5fc0d883acf0843c.png create mode 100644 pytorch/官方教程/img/c9d3ddd13da5858e2cb03b53753ece3c.png create mode 100644 pytorch/官方教程/img/cc57a36a43d450df4bfc1d1d1b1ce274.png create mode 100644 pytorch/官方教程/img/d0d82c063f83a0ba4bb8df4dcec57138.png create mode 100644 pytorch/官方教程/img/d148a5bd51a3278e9698bba522cbc34a.png create mode 100644 pytorch/官方教程/img/d15de2be2b754f9a4f46418764232b5e.png create mode 100644 pytorch/官方教程/img/d5ab1f07cb4a9d9200c2a2d3b238340d.png create mode 100644 pytorch/官方教程/img/d74012096c3134b776b5e9f70e8178f3.png create mode 100644 pytorch/官方教程/img/e21cb5ec883a2e5dceeff4064add3acd.png create mode 100644 pytorch/官方教程/img/e46d7dbb0cc58ac0895589bf255444be.png create mode 100644 pytorch/官方教程/img/ea0bddb69dfbd67215b823007544ab8f.png create mode 100644 pytorch/官方教程/img/ebec7787362bc53fe2289e5740da5756.png create mode 100644 pytorch/官方教程/img/efb29904552d032a076d8512d4e60b95.png create mode 100644 pytorch/官方教程/img/f29264b289639882a61fb5c3447b1ecc.png create mode 100644 pytorch/官方教程/img/f4990a0920dff7e4647a23cfc1639a8a.png create mode 100644 pytorch/官方教程/img/f5504c7ed93640f2bed4d2a606c015ba.png create mode 100644 pytorch/官方教程/img/fed25c69a6015a90b6e9406e4ac6e01c.png create mode 100644 pytorch/官方教程/img/ffad28c33f8a48d06521421f1aa441ed.png create mode 100644 pytorch/官方教程/img/tex21-1.gif create mode 100644 pytorch/官方教程/img/tex22-1.gif create mode 100644 pytorch/官方教程/img/tex22-2.gif create mode 100644 pytorch/官方教程/img/tex27-1.gif create mode 100644 pytorch/官方教程/img/tex34-1.gif create mode 100644 pytorch/官方教程/img/tex34-2.gif create mode 100644 pytorch/官方教程/img/tex34-3.gif create mode 100644 pytorch/官方教程/img/tex34-4.gif create mode 100644 pytorch/官方教程/img/tex34-5.gif create mode 100644 pytorch/官方教程/img/tex35-1.gif create mode 100644 pytorch/官方教程/img/tex35-2.gif create mode 100644 pytorch/官方教程/img/tex35-3.gif create mode 100644 pytorch/官方教程/img/tex35-4.gif create mode 100644 pytorch/官方教程/img/tex4-1.gif create mode 100644 pytorch/官方教程/img/tex4-2.gif create mode 100644 pytorch/官方教程/img/tex4-3.gif create mode 100644 pytorch/官方教程/img/tex4-4.gif create mode 100644 pytorch/官方教程/img/tex4-5.gif create mode 100644 pytorch/官方教程/img/tex4-6.gif create mode 100644 pytorch/官方教程/img/tex4-7.gif create mode 100644 pytorch/官方教程/img/tex56-1.gif create mode 100644 pytorch/实战/1.ipynb create mode 100644 机器学习/殷康龙/机器学习开发日志/4 sklearn中的sgd说明.ipynb diff --git a/Sklearn/sklearn-cookbook-zh/2.ipynb b/Sklearn/sklearn-cookbook-zh/2.ipynb new file mode 100644 index 00000000..83a4203f --- /dev/null +++ b/Sklearn/sklearn-cookbook-zh/2.ipynb @@ -0,0 +1,139 @@ +{ + "metadata": { + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.0-final" + }, + "orig_nbformat": 2, + "kernelspec": { + "name": "python3", + "display_name": "Python 3.8.0 64-bit", + "metadata": { + "interpreter": { + "hash": "38740d3277777e2cd7c6c2cc9d8addf5118fdf3f82b1b39231fd12aeac8aee8b" + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 2, + "cells": [ + { + "source": [ + "## 2.7 用线性方法处理分类问题——逻辑回归" + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "[]" + ] + }, + "metadata": {}, + "execution_count": 3 + }, + { + "output_type": "display_data", + "data": { + "text/plain": "
", + "image/svg+xml": "\r\n\r\n\r\n\r\n \r\n \r\n \r\n \r\n 2021-03-22T16:26:26.162497\r\n image/svg+xml\r\n \r\n \r\n Matplotlib v3.3.2, https://matplotlib.org/\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + } + } + ], + "source": [ + "import numpy as np \n", + "import matplotlib.pyplot as plt \n", + "\n", + "fig,ax = plt.subplots(figsize=(10,5))\n", + "\n", + "rng = np.linspace(-5,5)\n", + "log_f = np.apply_along_axis(lambda x:1/(1+np.exp(-x)),0,rng)\n", + "\n", + "ax.set_title(\"logistic function\")\n", + "ax.plot(rng,log_f)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "0.8977272727272727\n(88,)\n0.47058823529411764\n" + ] + } + ], + "source": [ + "from sklearn.datasets import make_classification\n", + "X,y = make_classification(n_samples = 1000,n_features=4,weights=[0.9])\n", + "\n", + "from sklearn.linear_model import LogisticRegression\n", + "lr = LogisticRegression()\n", + "\n", + "training = np.random.choice([True,False],p=[0.9,0.1],size=y.shape)\n", + "testing = ~training\n", + "\n", + "lr.fit(X[training],y[training])\n", + "pred = lr.predict(X[testing])\n", + "# 正确率\n", + "print((pred == y[testing]).mean())\n", + "\n", + "# 偏斜的小类的正确率。\n", + "y1 = y[testing]==1\n", + "print(y1.shape)\n", + "# 小类的正确率很低\n", + "print((y1[y1]==pred[y1==1]).sum().astype(float)/y1[y1==1].shape[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "(88,)\n0.8235294117647058\n" + ] + } + ], + "source": [ + "# 使用重采样的方法,来增加小类的数量\n", + "# class_weight表示各个标签数据集参与的比例。1标签参与0.9 \n", + "lr = LogisticRegression(class_weight={0:.1,1:.9})\n", + "lr.fit(X[training],y[training])\n", + "pred = lr.predict(X[testing])\n", + "\n", + "\n", + "y1 = y[testing]==1\n", + "print(y1.shape)\n", + "# 小类的正确率很低。重采样后。小类的正确率升高。\n", + "print((y1[y1]==pred[y1==1]).sum().astype(float)/y1[y1==1].shape[0])" + ] + } + ] +} \ No newline at end of file diff --git a/Sklearn/sklearn-cookbook-zh/5.ipynb b/Sklearn/sklearn-cookbook-zh/5.ipynb new file mode 100644 index 00000000..fb6b892a --- /dev/null +++ b/Sklearn/sklearn-cookbook-zh/5.ipynb @@ -0,0 +1,82 @@ +{ + "metadata": { + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.0-final" + }, + "orig_nbformat": 2, + "kernelspec": { + "name": "python3", + "display_name": "Python 3.8.0 64-bit", + "metadata": { + "interpreter": { + "hash": "38740d3277777e2cd7c6c2cc9d8addf5118fdf3f82b1b39231fd12aeac8aee8b" + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 2, + "cells": [ + { + "source": [ + "## 5.1 K-fold交叉验证" + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "# 创建数据集\n", + "N =1000\n", + "holdout = 200\n", + "from sklearn.datasets import make_regression\n", + "X,y = make_regression(1000,shuffle=True)\n", + "\n", + "# 分割数据集的第二种方法。\n", + "X_h,y_h = X[:holdout],y[:holdout]\n", + "X_t,y_t = X[holdout:],y[holdout:]\n", + "\n", + "# 方法的接口变了\n", + "from sklearn.model_selection import KFold\n", + "\n", + "kfold = KFold(n_splits=4)\n", + "\n", + "\n" + ] + }, + { + "source": [ + "## 5.8 回归模型评估" + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "source": [ + "## 5.9 特征选取" + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "source": [ + "## 5.11 使用joblib保存模型" + ], + "cell_type": "markdown", + "metadata": {} + } + ] +} \ No newline at end of file diff --git a/pytorch/README.md b/pytorch/README.md deleted file mode 100644 index b5ce3919..00000000 --- a/pytorch/README.md +++ /dev/null @@ -1 +0,0 @@ -# 莫烦 PyTorch 系列教程 diff --git a/pytorch/01.md b/pytorch/个人教程/01.md similarity index 100% rename from pytorch/01.md rename to pytorch/个人教程/01.md diff --git a/pytorch/02.md b/pytorch/个人教程/02.md similarity index 100% rename from pytorch/02.md rename to pytorch/个人教程/02.md diff --git a/pytorch/03.md b/pytorch/个人教程/03.md similarity index 100% rename from pytorch/03.md rename to pytorch/个人教程/03.md diff --git a/pytorch/04.md b/pytorch/个人教程/04.md similarity index 100% rename from pytorch/04.md rename to pytorch/个人教程/04.md diff --git a/pytorch/05.md b/pytorch/个人教程/05.md similarity index 100% rename from pytorch/05.md rename to pytorch/个人教程/05.md diff --git a/pytorch/06.md b/pytorch/个人教程/06.md similarity index 100% rename from pytorch/06.md rename to pytorch/个人教程/06.md diff --git a/pytorch/07.md b/pytorch/个人教程/07.md similarity index 100% rename from pytorch/07.md rename to pytorch/个人教程/07.md diff --git a/pytorch/08.md b/pytorch/个人教程/08.md similarity index 100% rename from pytorch/08.md rename to pytorch/个人教程/08.md diff --git a/pytorch/09.md b/pytorch/个人教程/09.md similarity index 100% rename from pytorch/09.md rename to pytorch/个人教程/09.md diff --git a/pytorch/10.md b/pytorch/个人教程/10.md similarity index 100% rename from pytorch/10.md rename to pytorch/个人教程/10.md diff --git a/pytorch/11.md b/pytorch/个人教程/11.md similarity index 100% rename from pytorch/11.md rename to pytorch/个人教程/11.md diff --git a/pytorch/12.md b/pytorch/个人教程/12.md similarity index 100% rename from pytorch/12.md rename to pytorch/个人教程/12.md diff --git a/pytorch/13.md b/pytorch/个人教程/13.md similarity index 100% rename from pytorch/13.md rename to pytorch/个人教程/13.md diff --git a/pytorch/14.md b/pytorch/个人教程/14.md similarity index 100% rename from pytorch/14.md rename to pytorch/个人教程/14.md diff --git a/pytorch/15.md b/pytorch/个人教程/15.md similarity index 100% rename from pytorch/15.md rename to pytorch/个人教程/15.md diff --git a/pytorch/16.md b/pytorch/个人教程/16.md similarity index 100% rename from pytorch/16.md rename to pytorch/个人教程/16.md diff --git a/pytorch/17.md b/pytorch/个人教程/17.md similarity index 100% rename from pytorch/17.md rename to pytorch/个人教程/17.md diff --git a/pytorch/18.md b/pytorch/个人教程/18.md similarity index 100% rename from pytorch/18.md rename to pytorch/个人教程/18.md diff --git a/pytorch/19.md b/pytorch/个人教程/19.md similarity index 100% rename from pytorch/19.md rename to pytorch/个人教程/19.md diff --git a/pytorch/20.md b/pytorch/个人教程/20.md similarity index 100% rename from pytorch/20.md rename to pytorch/个人教程/20.md diff --git a/pytorch/21.md b/pytorch/个人教程/21.md similarity index 100% rename from pytorch/21.md rename to pytorch/个人教程/21.md diff --git a/pytorch/22.md b/pytorch/个人教程/22.md similarity index 100% rename from pytorch/22.md rename to pytorch/个人教程/22.md diff --git a/pytorch/23.md b/pytorch/个人教程/23.md similarity index 100% rename from pytorch/23.md rename to pytorch/个人教程/23.md diff --git a/pytorch/24.md b/pytorch/个人教程/24.md similarity index 100% rename from pytorch/24.md rename to pytorch/个人教程/24.md diff --git a/pytorch/25.md b/pytorch/个人教程/25.md similarity index 100% rename from pytorch/25.md rename to pytorch/个人教程/25.md diff --git a/pytorch/26.md b/pytorch/个人教程/26.md similarity index 100% rename from pytorch/26.md rename to pytorch/个人教程/26.md diff --git a/pytorch/SUMMARY.md b/pytorch/个人教程/SUMMARY.md similarity index 100% rename from pytorch/SUMMARY.md rename to pytorch/个人教程/SUMMARY.md diff --git a/pytorch/img/03f4667f9aae4918338a56b74865a389.png b/pytorch/个人教程/img/03f4667f9aae4918338a56b74865a389.png similarity index 100% rename from pytorch/img/03f4667f9aae4918338a56b74865a389.png rename to pytorch/个人教程/img/03f4667f9aae4918338a56b74865a389.png diff --git a/pytorch/img/04a6040ad4f06a69a92f440ea17dde44.png b/pytorch/个人教程/img/04a6040ad4f06a69a92f440ea17dde44.png similarity index 100% rename from pytorch/img/04a6040ad4f06a69a92f440ea17dde44.png rename to pytorch/个人教程/img/04a6040ad4f06a69a92f440ea17dde44.png diff --git a/pytorch/img/13e0473ef73a9de2569a81c62e30d054.png b/pytorch/个人教程/img/13e0473ef73a9de2569a81c62e30d054.png similarity index 100% rename from pytorch/img/13e0473ef73a9de2569a81c62e30d054.png rename to pytorch/个人教程/img/13e0473ef73a9de2569a81c62e30d054.png diff --git a/pytorch/img/1b292936f4a0c3be1d04e43a994fd48c.png b/pytorch/个人教程/img/1b292936f4a0c3be1d04e43a994fd48c.png similarity index 100% rename from pytorch/img/1b292936f4a0c3be1d04e43a994fd48c.png rename to pytorch/个人教程/img/1b292936f4a0c3be1d04e43a994fd48c.png diff --git a/pytorch/img/1f0b990d5a8d78692d3730d855fe44ea.png b/pytorch/个人教程/img/1f0b990d5a8d78692d3730d855fe44ea.png similarity index 100% rename from pytorch/img/1f0b990d5a8d78692d3730d855fe44ea.png rename to pytorch/个人教程/img/1f0b990d5a8d78692d3730d855fe44ea.png diff --git a/pytorch/img/20e2ebdf112e4aa3202e951e072c2dc2.png b/pytorch/个人教程/img/20e2ebdf112e4aa3202e951e072c2dc2.png similarity index 100% rename from pytorch/img/20e2ebdf112e4aa3202e951e072c2dc2.png rename to pytorch/个人教程/img/20e2ebdf112e4aa3202e951e072c2dc2.png diff --git a/pytorch/img/22309cd02ee52b3a65e1f0022e8b964e.png b/pytorch/个人教程/img/22309cd02ee52b3a65e1f0022e8b964e.png similarity index 100% rename from pytorch/img/22309cd02ee52b3a65e1f0022e8b964e.png rename to pytorch/个人教程/img/22309cd02ee52b3a65e1f0022e8b964e.png diff --git a/pytorch/img/25959870b2b1e7d6fd61229cb20bed29.png b/pytorch/个人教程/img/25959870b2b1e7d6fd61229cb20bed29.png similarity index 100% rename from pytorch/img/25959870b2b1e7d6fd61229cb20bed29.png rename to pytorch/个人教程/img/25959870b2b1e7d6fd61229cb20bed29.png diff --git a/pytorch/img/25ed82d9ef8a8b1c9c60445c7c08c732.png b/pytorch/个人教程/img/25ed82d9ef8a8b1c9c60445c7c08c732.png similarity index 100% rename from pytorch/img/25ed82d9ef8a8b1c9c60445c7c08c732.png rename to pytorch/个人教程/img/25ed82d9ef8a8b1c9c60445c7c08c732.png diff --git a/pytorch/img/2fc34594dcb247d4a3414467eed4a109.png b/pytorch/个人教程/img/2fc34594dcb247d4a3414467eed4a109.png similarity index 100% rename from pytorch/img/2fc34594dcb247d4a3414467eed4a109.png rename to pytorch/个人教程/img/2fc34594dcb247d4a3414467eed4a109.png diff --git a/pytorch/img/388ca39bf710c8f053f533ad10872cd7.png b/pytorch/个人教程/img/388ca39bf710c8f053f533ad10872cd7.png similarity index 100% rename from pytorch/img/388ca39bf710c8f053f533ad10872cd7.png rename to pytorch/个人教程/img/388ca39bf710c8f053f533ad10872cd7.png diff --git a/pytorch/img/4d69c0a49be83a66f774caf12e64c3a7.png b/pytorch/个人教程/img/4d69c0a49be83a66f774caf12e64c3a7.png similarity index 100% rename from pytorch/img/4d69c0a49be83a66f774caf12e64c3a7.png rename to pytorch/个人教程/img/4d69c0a49be83a66f774caf12e64c3a7.png diff --git a/pytorch/img/5a415b795ebbb116db6d4a2394d93b27.png b/pytorch/个人教程/img/5a415b795ebbb116db6d4a2394d93b27.png similarity index 100% rename from pytorch/img/5a415b795ebbb116db6d4a2394d93b27.png rename to pytorch/个人教程/img/5a415b795ebbb116db6d4a2394d93b27.png diff --git a/pytorch/img/6730e1145d2a40e8ced1fda4d453d9c6.png b/pytorch/个人教程/img/6730e1145d2a40e8ced1fda4d453d9c6.png similarity index 100% rename from pytorch/img/6730e1145d2a40e8ced1fda4d453d9c6.png rename to pytorch/个人教程/img/6730e1145d2a40e8ced1fda4d453d9c6.png diff --git a/pytorch/img/68f39521fc6853acdf26440e7d5a2861.png b/pytorch/个人教程/img/68f39521fc6853acdf26440e7d5a2861.png similarity index 100% rename from pytorch/img/68f39521fc6853acdf26440e7d5a2861.png rename to pytorch/个人教程/img/68f39521fc6853acdf26440e7d5a2861.png diff --git a/pytorch/img/7345448d48d8d6c6c1b03fda91334e3e.png b/pytorch/个人教程/img/7345448d48d8d6c6c1b03fda91334e3e.png similarity index 100% rename from pytorch/img/7345448d48d8d6c6c1b03fda91334e3e.png rename to pytorch/个人教程/img/7345448d48d8d6c6c1b03fda91334e3e.png diff --git a/pytorch/img/761c210ceb0fdd69c7e0f8bd85e39698.png b/pytorch/个人教程/img/761c210ceb0fdd69c7e0f8bd85e39698.png similarity index 100% rename from pytorch/img/761c210ceb0fdd69c7e0f8bd85e39698.png rename to pytorch/个人教程/img/761c210ceb0fdd69c7e0f8bd85e39698.png diff --git a/pytorch/img/7a8716c377832b032ee24276b7ddcc31.png b/pytorch/个人教程/img/7a8716c377832b032ee24276b7ddcc31.png similarity index 100% rename from pytorch/img/7a8716c377832b032ee24276b7ddcc31.png rename to pytorch/个人教程/img/7a8716c377832b032ee24276b7ddcc31.png diff --git a/pytorch/img/7eca2f8318f254b17ca0bc215ec4f5a0.png b/pytorch/个人教程/img/7eca2f8318f254b17ca0bc215ec4f5a0.png similarity index 100% rename from pytorch/img/7eca2f8318f254b17ca0bc215ec4f5a0.png rename to pytorch/个人教程/img/7eca2f8318f254b17ca0bc215ec4f5a0.png diff --git a/pytorch/img/90e1ab65f286c889d94c9f6c57d596c9.png b/pytorch/个人教程/img/90e1ab65f286c889d94c9f6c57d596c9.png similarity index 100% rename from pytorch/img/90e1ab65f286c889d94c9f6c57d596c9.png rename to pytorch/个人教程/img/90e1ab65f286c889d94c9f6c57d596c9.png diff --git a/pytorch/img/94268b7d9687d039d872da203453c97b.png b/pytorch/个人教程/img/94268b7d9687d039d872da203453c97b.png similarity index 100% rename from pytorch/img/94268b7d9687d039d872da203453c97b.png rename to pytorch/个人教程/img/94268b7d9687d039d872da203453c97b.png diff --git a/pytorch/img/99c72d57612c137b62599837526f0e0e.png b/pytorch/个人教程/img/99c72d57612c137b62599837526f0e0e.png similarity index 100% rename from pytorch/img/99c72d57612c137b62599837526f0e0e.png rename to pytorch/个人教程/img/99c72d57612c137b62599837526f0e0e.png diff --git a/pytorch/img/9e1df524980c8f42ab4353070c2a1b74.png b/pytorch/个人教程/img/9e1df524980c8f42ab4353070c2a1b74.png similarity index 100% rename from pytorch/img/9e1df524980c8f42ab4353070c2a1b74.png rename to pytorch/个人教程/img/9e1df524980c8f42ab4353070c2a1b74.png diff --git a/pytorch/img/a545e4a49909bd7a80e042fd6d8267cb.png b/pytorch/个人教程/img/a545e4a49909bd7a80e042fd6d8267cb.png similarity index 100% rename from pytorch/img/a545e4a49909bd7a80e042fd6d8267cb.png rename to pytorch/个人教程/img/a545e4a49909bd7a80e042fd6d8267cb.png diff --git a/pytorch/img/a577eb2dc81a64cfc4f6d04ff9a25873.png b/pytorch/个人教程/img/a577eb2dc81a64cfc4f6d04ff9a25873.png similarity index 100% rename from pytorch/img/a577eb2dc81a64cfc4f6d04ff9a25873.png rename to pytorch/个人教程/img/a577eb2dc81a64cfc4f6d04ff9a25873.png diff --git a/pytorch/img/b708f231f544bd7bcefa1d55c82653dd.png b/pytorch/个人教程/img/b708f231f544bd7bcefa1d55c82653dd.png similarity index 100% rename from pytorch/img/b708f231f544bd7bcefa1d55c82653dd.png rename to pytorch/个人教程/img/b708f231f544bd7bcefa1d55c82653dd.png diff --git a/pytorch/img/bbd3ae66e0235fac8745c37306e74a52.png b/pytorch/个人教程/img/bbd3ae66e0235fac8745c37306e74a52.png similarity index 100% rename from pytorch/img/bbd3ae66e0235fac8745c37306e74a52.png rename to pytorch/个人教程/img/bbd3ae66e0235fac8745c37306e74a52.png diff --git a/pytorch/img/bce7313d5ac6f2600b62a4962a6daf3a.png b/pytorch/个人教程/img/bce7313d5ac6f2600b62a4962a6daf3a.png similarity index 100% rename from pytorch/img/bce7313d5ac6f2600b62a4962a6daf3a.png rename to pytorch/个人教程/img/bce7313d5ac6f2600b62a4962a6daf3a.png diff --git a/pytorch/img/c2914d88b6f17b84982e162cf6930a88.png b/pytorch/个人教程/img/c2914d88b6f17b84982e162cf6930a88.png similarity index 100% rename from pytorch/img/c2914d88b6f17b84982e162cf6930a88.png rename to pytorch/个人教程/img/c2914d88b6f17b84982e162cf6930a88.png diff --git a/pytorch/img/c429fb827df769a542339e200e2ea20c.png b/pytorch/个人教程/img/c429fb827df769a542339e200e2ea20c.png similarity index 100% rename from pytorch/img/c429fb827df769a542339e200e2ea20c.png rename to pytorch/个人教程/img/c429fb827df769a542339e200e2ea20c.png diff --git a/pytorch/img/c42f3cec435a83431d5a1737e99b8b8c.png b/pytorch/个人教程/img/c42f3cec435a83431d5a1737e99b8b8c.png similarity index 100% rename from pytorch/img/c42f3cec435a83431d5a1737e99b8b8c.png rename to pytorch/个人教程/img/c42f3cec435a83431d5a1737e99b8b8c.png diff --git a/pytorch/img/c8011979fa20046cbfa36e46cf508689.png b/pytorch/个人教程/img/c8011979fa20046cbfa36e46cf508689.png similarity index 100% rename from pytorch/img/c8011979fa20046cbfa36e46cf508689.png rename to pytorch/个人教程/img/c8011979fa20046cbfa36e46cf508689.png diff --git a/pytorch/img/cb2138c3f800c7ca4b5ae38076d09429.png b/pytorch/个人教程/img/cb2138c3f800c7ca4b5ae38076d09429.png similarity index 100% rename from pytorch/img/cb2138c3f800c7ca4b5ae38076d09429.png rename to pytorch/个人教程/img/cb2138c3f800c7ca4b5ae38076d09429.png diff --git a/pytorch/img/f1108a1b6941305fa7a39e488c023fe9.png b/pytorch/个人教程/img/f1108a1b6941305fa7a39e488c023fe9.png similarity index 100% rename from pytorch/img/f1108a1b6941305fa7a39e488c023fe9.png rename to pytorch/个人教程/img/f1108a1b6941305fa7a39e488c023fe9.png diff --git a/pytorch/img/f38868821469cadc36810cfd827511d1.png b/pytorch/个人教程/img/f38868821469cadc36810cfd827511d1.png similarity index 100% rename from pytorch/img/f38868821469cadc36810cfd827511d1.png rename to pytorch/个人教程/img/f38868821469cadc36810cfd827511d1.png diff --git a/pytorch/img/f790e22ee4be05f818e52467c2f13b37.png b/pytorch/个人教程/img/f790e22ee4be05f818e52467c2f13b37.png similarity index 100% rename from pytorch/img/f790e22ee4be05f818e52467c2f13b37.png rename to pytorch/个人教程/img/f790e22ee4be05f818e52467c2f13b37.png diff --git a/pytorch/img/febe7e5dc5d5b9a5004d15c50d3228c1.png b/pytorch/个人教程/img/febe7e5dc5d5b9a5004d15c50d3228c1.png similarity index 100% rename from pytorch/img/febe7e5dc5d5b9a5004d15c50d3228c1.png rename to pytorch/个人教程/img/febe7e5dc5d5b9a5004d15c50d3228c1.png diff --git a/pytorch/img/fedaa24e2fcad876c77a2038c2d8d14d.png b/pytorch/个人教程/img/fedaa24e2fcad876c77a2038c2d8d14d.png similarity index 100% rename from pytorch/img/fedaa24e2fcad876c77a2038c2d8d14d.png rename to pytorch/个人教程/img/fedaa24e2fcad876c77a2038c2d8d14d.png diff --git a/pytorch/img/ffeedc89cc695e61aa6e941c1c696a39.png b/pytorch/个人教程/img/ffeedc89cc695e61aa6e941c1c696a39.png similarity index 100% rename from pytorch/img/ffeedc89cc695e61aa6e941c1c696a39.png rename to pytorch/个人教程/img/ffeedc89cc695e61aa6e941c1c696a39.png diff --git a/pytorch/官方教程/01.md b/pytorch/官方教程/01.md new file mode 100644 index 00000000..fef39340 --- /dev/null +++ b/pytorch/官方教程/01.md @@ -0,0 +1 @@ +# 学习 PyTorch \ No newline at end of file diff --git a/pytorch/官方教程/02.md b/pytorch/官方教程/02.md new file mode 100644 index 00000000..ef79c60d --- /dev/null +++ b/pytorch/官方教程/02.md @@ -0,0 +1,39 @@ +# PyTorch 深度学习:60分钟快速入门 + +> 原文: + +**作者**: [Soumith Chintala](http://soumith.ch) + + + +## 什么是 PyTorch? + +PyTorch 是基于以下两个目的而打造的python科学计算框架: + +* 无缝替换NumPy,并且通过利用GPU的算力来实现神经网络的加速。 +* 通过自动微分机制,来让神经网络的实现变得更加容易。 + +## 本次教程的目标: + +* 深入了解PyTorch的张量单元以及如何使用Pytorch来搭建神经网络。 +* 自己动手训练一个小型神经网络来实现图像的分类。 + +注意 + +确保已安装[`torch`](https://github.com/pytorch/pytorch)和[`torchvision`](https://github.com/pytorch/vision)包。 + +![../_img/tensor_illustration_flat.png](img/0c7a402331744a44f5e17575b1607904.png) + +[张量](blitz/tensor_tutorial.html#sphx-glr-beginner-blitz-tensor-tutorial-py) + +![../_img/autodiff.png](img/0a7a97c39d6dfc0e08d2701eb7a49231.png) + +[`torch.autograd`的简要介绍](blitz/autograd_tutorial.html#sphx-glr-beginner-blitz-autograd-tutorial-py) + +![../_img/mnist1.png](img/be60e8e1f4baa0de87cf9d37c5325525.png) + +[神经网络简介](blitz/neural_networks_tutorial.html#sphx-glr-beginner-blitz-neural-networks-tutorial-py) + +![../_img/cifar101.png](img/7a28f697e6bab9f3d9b1e8da4a5a5249.png) + +[自己动手训练一个图像分类器](blitz/cifar10_tutorial.html#sphx-glr-beginner-blitz-cifar10-tutorial-py) diff --git a/pytorch/官方教程/03.md b/pytorch/官方教程/03.md new file mode 100644 index 00000000..52ae4ff1 --- /dev/null +++ b/pytorch/官方教程/03.md @@ -0,0 +1,292 @@ +# 张量 + +>原文: + +张量如同数组和矩阵一样, 是一种特殊的数据结构。在`PyTorch`中, 神经网络的输入、输出以及网络的参数等数据, 都是使用张量来进行描述。 + +张量的使用和`Numpy`中的`ndarrays`很类似, 区别在于张量可以在`GPU`或其它专用硬件上运行, 这样可以得到更快的加速效果。如果你对`ndarrays`很熟悉的话, 张量的使用对你来说就很容易了。如果不太熟悉的话, 希望这篇有关张量`API`的快速入门教程能够帮到你。 + +```python +import torch +import numpy as np +``` + +## 张量初始化 + +张量有很多种不同的初始化方法, 先来看看四个简单的例子: + +**1. 直接生成张量** + +由原始数据直接生成张量, 张量类型由原始数据类型决定。 + +```python +data = [[1, 2], [3, 4]] +x_data = torch.tensor(data) +``` + +**2. 通过Numpy数组来生成张量** + +由已有的`Numpy`数组来生成张量(反过来也可以由张量来生成`Numpy`数组, 参考[张量与Numpy之间的转换](#jump))。 + +```python +np_array = np.array(data) +x_np = torch.from_numpy(np_array) +``` +**3. 通过已有的张量来生成新的张量** + +新的张量将继承已有张量的数据属性(结构、类型), 也可以重新指定新的数据类型。 + +```python +x_ones = torch.ones_like(x_data) # 保留 x_data 的属性 +print(f"Ones Tensor: \n {x_ones} \n") + +x_rand = torch.rand_like(x_data, dtype=torch.float) # 重写 x_data 的数据类型 + int -> float +print(f"Random Tensor: \n {x_rand} \n") +``` + +显示: + +```python +Ones Tensor: + tensor([[1, 1], + [1, 1]]) + +Random Tensor: + tensor([[0.0381, 0.5780], + [0.3963, 0.0840]]) +``` +**4. 通过指定数据维度来生成张量** + +`shape`是元组类型, 用来描述张量的维数, 下面3个函数通过传入`shape`来指定生成张量的维数。 + +```python +shape = (2,3,) +rand_tensor = torch.rand(shape) +ones_tensor = torch.ones(shape) +zeros_tensor = torch.zeros(shape) + +print(f"Random Tensor: \n {rand_tensor} \n") +print(f"Ones Tensor: \n {ones_tensor} \n") +print(f"Zeros Tensor: \n {zeros_tensor}") +``` + +显示: + +```python +Random Tensor: + tensor([[0.0266, 0.0553, 0.9843], + [0.0398, 0.8964, 0.3457]]) + +Ones Tensor: + tensor([[1., 1., 1.], + [1., 1., 1.]]) + +Zeros Tensor: + tensor([[0., 0., 0.], + [0., 0., 0.]]) +``` + +## 张量属性 + +从张量属性我们可以得到张量的维数、数据类型以及它们所存储的设备(CPU或GPU)。 + +来看一个简单的例子: + +```python +tensor = torch.rand(3,4) + +print(f"Shape of tensor: {tensor.shape}") +print(f"Datatype of tensor: {tensor.dtype}") +print(f"Device tensor is stored on: {tensor.device}") +``` + +显示: + +```python +Shape of tensor: torch.Size([3, 4]) # 维数 +Datatype of tensor: torch.float32 # 数据类型 +Device tensor is stored on: cpu # 存储设备 +``` + +## 张量运算 + +有超过100种张量相关的运算操作, 例如转置、索引、切片、数学运算、线性代数、随机采样等。更多的运算可以在这里[查看](https://pytorch.org/docs/stable/torch.html)。 + +所有这些运算都可以在GPU上运行(相对于CPU来说可以达到更高的运算速度)。如果你使用的是Google的Colab环境, 可以通过 `Edit > Notebook Settings` 来分配一个GPU使用。 + +```python +# 判断当前环境GPU是否可用, 然后将tensor导入GPU内运行 +if torch.cuda.is_available(): + tensor = tensor.to('cuda') +``` + +光说不练假把式, 接下来的例子一定要动手跑一跑。如果你对Numpy的运算非常熟悉的话, 那tensor的运算对你来说就是小菜一碟。 + +**1. 张量的索引和切片** + +```python +tensor = torch.ones(4, 4) +tensor[:,1] = 0 # 将第1列(从0开始)的数据全部赋值为0 +print(tensor) +``` + +显示: + +```python +tensor([[1., 0., 1., 1.], + [1., 0., 1., 1.], + [1., 0., 1., 1.], + [1., 0., 1., 1.]]) +``` + +**2. 张量的拼接** + +你可以通过`torch.cat`方法将一组张量按照指定的维度进行拼接, 也可以参考[`torch.stack`](https://pytorch.org/docs/stable/generated/torch.stack.html)方法。这个方法也可以实现拼接操作, 但和`torch.cat`稍微有点不同。 + +```python +t1 = torch.cat([tensor, tensor, tensor], dim=1) +print(t1) +``` + + 显示: + +``` +tensor([[1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.], + [1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.], + [1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.], + [1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.]]) +``` + +**3. 张量的乘积和矩阵乘法** + +```python +# 逐个元素相乘结果 +print(f"tensor.mul(tensor): \n {tensor.mul(tensor)} \n") +# 等价写法: +print(f"tensor * tensor: \n {tensor * tensor}") +``` + +显示: + +```python +tensor.mul(tensor): + tensor([[1., 0., 1., 1.], + [1., 0., 1., 1.], + [1., 0., 1., 1.], + [1., 0., 1., 1.]]) + +tensor * tensor: + tensor([[1., 0., 1., 1.], + [1., 0., 1., 1.], + [1., 0., 1., 1.], + [1., 0., 1., 1.]]) +``` + +下面写法表示张量与张量的矩阵乘法: + +```python +print(f"tensor.matmul(tensor.T): \n {tensor.matmul(tensor.T)} \n") +# 等价写法: +print(f"tensor @ tensor.T: \n {tensor @ tensor.T}") +``` + +显示: + +```python +tensor.matmul(tensor.T): + tensor([[3., 3., 3., 3.], + [3., 3., 3., 3.], + [3., 3., 3., 3.], + [3., 3., 3., 3.]]) + +tensor @ tensor.T: + tensor([[3., 3., 3., 3.], + [3., 3., 3., 3.], + [3., 3., 3., 3.], + [3., 3., 3., 3.]]) +``` + +**4. 自动赋值运算** + +自动赋值运算通常在方法后有 `_` 作为后缀, 例如: `x.copy_(y)`, `x.t_()`操作会改变 `x` 的取值。 + +```python +print(tensor, "\n") +tensor.add_(5) +print(tensor) +``` + +显示: + +```python +tensor([[1., 0., 1., 1.], + [1., 0., 1., 1.], + [1., 0., 1., 1.], + [1., 0., 1., 1.]]) + +tensor([[6., 5., 6., 6.], + [6., 5., 6., 6.], + [6., 5., 6., 6.], + [6., 5., 6., 6.]]) +``` + +> 注意: +> +> 自动赋值运算虽然可以节省内存, 但在求导时会因为丢失了中间过程而导致一些问题, 所以我们并不鼓励使用它。 + +## Tensor与Numpy的转化 +张量和`Numpy array`数组在CPU上可以共用一块内存区域, 改变其中一个另一个也会随之改变。 +**1. 由张量变换为Numpy array数组** +```python +t = torch.ones(5) +print(f"t: {t}") +n = t.numpy() +print(f"n: {n}") +``` +显示: +```python +t: tensor([1., 1., 1., 1., 1.]) +n: [1. 1. 1. 1. 1.] +``` +修改张量的值,则`Numpy array`数组值也会随之改变。 +```python +t.add_(1) +print(f"t: {t}") +print(f"n: {n}") +``` +显示: +```python +t: tensor([2., 2., 2., 2., 2.]) +n: [2. 2. 2. 2. 2.] +``` + +**2. 由Numpy array数组转为张量** + +```python +n = np.ones(5) +t = torch.from_numpy(n) +``` + +修改`Numpy array`数组的值,则张量值也会随之改变。 + +```python +np.add(n, 1, out=n) +print(f"t: {t}") +print(f"n: {n}") +``` + +显示: + +```python +t: tensor([2., 2., 2., 2., 2.], dtype=torch.float64) +n: [2. 2. 2. 2. 2.] +``` + +**脚本的总运行时间**:(0 分钟 0.045 秒) + +[下载 Python 源码:`tensor_tutorial.py`](https://pytorch.org/tutorials/_downloads/092fba3c36cb2ab226bfdaa78248b310/tensor_tutorial.py) + +[下载 Jupyter 笔记本:`tensor_tutorial.ipynb`](https://pytorch.org/tutorials/_downloads/3c2b25b8a9f72db7780a6bf9b5fc9f62/tensor_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/04.md b/pytorch/官方教程/04.md new file mode 100644 index 00000000..9e3aab7d --- /dev/null +++ b/pytorch/官方教程/04.md @@ -0,0 +1,236 @@ +# `torch.autograd`的简要介绍 + +> 原文: + +`torch.autograd`是 PyTorch 的自动差分引擎,可为神经网络训练提供支持。 在本节中,您将获得有关 Autograd 如何帮助神经网络训练的概念性理解。 + +## 背景 + +神经网络(NN)是在某些输入数据上执行的嵌套函数的集合。 这些函数由*参数*(由权重和偏差组成)定义,这些参数在 PyTorch 中存储在张量中。 + +训练 NN 分为两个步骤: + +**正向传播**:在正向传播中,NN 对正确的输出进行最佳猜测。 它通过其每个函数运行输入数据以进行猜测。 + +**反向传播**:在反向传播中,NN 根据其猜测中的误差调整其参数。 它通过从输出向后遍历,收集有关函数参数(*梯度*)的误差导数并使用梯度下降来优化参数来实现。 有关反向传播的更详细的演练,请查看 3Blue1Brown 的[视频](https://www.youtube.com/watch?v=tIeHLnjs5U8)。 + +## 在 PyTorch 中的用法 + +让我们来看一个训练步骤。 对于此示例,我们从`torchvision`加载了经过预训练的 resnet18 模型。 我们创建一个随机数据张量来表示具有 3 个通道的单个图像,高度&宽度为 64,其对应的`label`初始化为一些随机值。 + +```py +import torch, torchvision +model = torchvision.models.resnet18(pretrained=True) +data = torch.rand(1, 3, 64, 64) +labels = torch.rand(1, 1000) + +``` + +接下来,我们通过模型的每一层运行输入数据以进行预测。 这是**正向传播**。 + +```py +prediction = model(data) # forward pass + +``` + +我们使用模型的预测和相应的标签来计算误差(`loss`)。 下一步是通过网络反向传播此误差。 当我们在误差张量上调用`.backward()`时,开始反向传播。 然后,Autograd 会为每个模型参数计算梯度并将其存储在参数的`.grad`属性中。 + +```py +loss = (prediction - labels).sum() +loss.backward() # backward pass + +``` + +接下来,我们加载一个优化器,在本例中为 SGD,学习率为 0.01,动量为 0.9。 我们在优化器中注册模型的所有参数。 + +```py +optim = torch.optim.SGD(model.parameters(), lr=1e-2, momentum=0.9) + +``` + +最后,我们调用`.step()`启动梯度下降。 优化器通过`.grad`中存储的梯度来调整每个参数。 + +```py +optim.step() #gradient descent + +``` + +至此,您已经具备了训练神经网络所需的一切。 以下各节详细介绍了 Autograd 的工作原理-随时跳过它们。 + +* * * + +## Autograd 的微分 + +让我们来看看`autograd`如何收集梯度。 我们用`requires_grad=True`创建两个张量`a`和`b`。 这向`autograd`发出信号,应跟踪对它们的所有操作。 + +```py +import torch + +a = torch.tensor([2., 3.], requires_grad=True) +b = torch.tensor([6., 4.], requires_grad=True) + +``` + +我们从`a`和`b`创建另一个张量`Q`。 + +![](img/tex4-1.gif) + +```py +Q = 3*a**3 - b**2 + +``` + +假设`a`和`b`是神经网络的参数,`Q`是误差。 在 NN 训练中,我们想要相对于参数的误差,即 + +![](img/tex4-2.gif) + +![](img/tex4-3.gif) + +当我们在`Q`上调用`.backward()`时,Autograd 将计算这些梯度并将其存储在各个张量的`.grad`属性中。 + +我们需要在`Q.backward()`中显式传递`gradient`参数,因为它是向量。 `gradient`是与`Q`形状相同的张量,它表示`Q`相对于本身的梯度,即 + +![](img/tex4-4.gif) + +同样,我们也可以将`Q`聚合为一个标量,然后隐式地向后调用,例如`Q.sum().backward()`。 + +```py +external_grad = torch.tensor([1., 1.]) +Q.backward(gradient=external_grad) + +``` + +梯度现在沉积在`a.grad`和`b.grad`中 + +```py +# check if collected gradients are correct +print(9*a**2 == a.grad) +print(-2*b == b.grad) + +``` + +出: + +```py +tensor([True, True]) +tensor([True, True]) + +``` + +### 可选阅读-使用`autograd`的向量微积分 + +从数学上讲,如果您具有向量值函数`y = f(x)`,则`y`相对于`x`的雅可比矩阵`J`: + +![](img/tex4-5.gif) + +一般来说,`torch.autograd`是用于计算向量雅可比积的引擎。 也就是说,给定任何向量`v`,计算乘积`J^T · v` + +如果`v`恰好是标量函数的梯度 + +![](img/tex4-6.gif) + +然后根据链式规则,向量-雅可比积将是`l`相对于`x`的梯度: + +![](img/tex4-7.gif) + +上面的示例中使用的是 vector-Jacobian 乘积的这一特征。 `external_grad`表示`v`。 + +## 计算图 + +从概念上讲,Autograd 在由[函数](https://pytorch.org/docs/stable/autograd.html#torch.autograd.Function)对象组成的有向无环图(DAG)中记录数据(张量)和所有已执行的操作(以及由此产生的新张量)。 在此 DAG 中,叶子是输入张量,根是输出张量。 通过从根到叶跟踪此图,可以使用链式规则自动计算梯度。 + +在正向传播中,Autograd 同时执行两项操作: + +* 运行请求的操作以计算结果张量,并且 +* 在 DAG 中维护操作的*梯度函数*。 + +当在 DAG 根目录上调用`.backward()`时,后退通道开始。 `autograd`然后: + +* 从每个`.grad_fn`计算梯度, +* 将它们累积在各自的张量的`.grad`属性中,然后 +* 使用链式规则,一直传播到叶子张量。 + +下面是我们示例中 DAG 的直观表示。 在图中,箭头指向前进的方向。 节点代表正向传播中每个操作的反向函数。 蓝色的叶节点代表我们的叶张量`a`和`b`。 + +![../../_img/dag_autograd.png](img/1270bde38f2cfccd4900a5df8ac70a7d.png) + +注意 + +**DAG 在 PyTorch 中是动态的**。要注意的重要一点是,图是从头开始重新创建的; 在每个`.backward()`调用之后,Autograd 开始填充新图。 这正是允许您在模型中使用控制流语句的原因。 您可以根据需要在每次迭代中更改形状,大小和操作。 + +### 从 DAG 中排除 + +`torch.autograd`跟踪所有将其`requires_grad`标志设置为`True`的张量的操作。 对于不需要梯度的张量,将此属性设置为`False`会将其从梯度计算 DAG 中排除。 + +即使只有一个输入张量具有`requires_grad=True`,操作的输出张量也将需要梯度。 + +```py +x = torch.rand(5, 5) +y = torch.rand(5, 5) +z = torch.rand((5, 5), requires_grad=True) + +a = x + y +print(f"Does `a` require gradients? : {a.requires_grad}") +b = x + z +print(f"Does `b` require gradients?: {b.requires_grad}") + +``` + +出: + +```py +Does `a` require gradients? : False +Does `b` require gradients?: True + +``` + +在 NN 中,不计算梯度的参数通常称为**冻结参数**。 如果事先知道您不需要这些参数的梯度,则“冻结”模型的一部分很有用(通过减少自动梯度计算,这会带来一些表现优势)。 + +从 DAG 中排除很重要的另一个常见用例是[调整预训练网络](https://pytorch.org/tutorials/beginner/finetuning_torchvision_models_tutorial.html) + +在微调中,我们冻结了大部分模型,通常仅修改分类器层以对新标签进行预测。 让我们来看一个小例子来说明这一点。 和以前一样,我们加载一个预训练的 resnet18 模型,并冻结所有参数。 + +```py +from torch import nn, optim + +model = torchvision.models.resnet18(pretrained=True) + +# Freeze all the parameters in the network +for param in model.parameters(): + param.requires_grad = False + +``` + +假设我们要在具有 10 个标签的新数据集中微调模型。 在 resnet 中,分类器是最后一个线性层`model.fc`。 我们可以简单地将其替换为充当我们的分类器的新线性层(默认情况下未冻结)。 + +```py +model.fc = nn.Linear(512, 10) + +``` + +现在,除了`model.fc`的参数外,模型中的所有参数都将冻结。 计算梯度的唯一参数是`model.fc`的权重和偏差。 + +```py +# Optimize only the classifier +optimizer = optim.SGD(model.fc.parameters(), lr=1e-2, momentum=0.9) + +``` + +请注意,尽管我们在优化器中注册了所有参数,但唯一可计算梯度的参数(因此会在梯度下降中进行更新)是分类器的权重和偏差。 + +[`torch.no_grad()`](https://pytorch.org/docs/stable/generated/torch.no_grad.html)中的上下文管理器可以使用相同的排除功能。 + +* * * + +## 进一步阅读: + +* [原地操作&多线程 Autograd](https://pytorch.org/docs/stable/notes/autograd.html) +* [反向模式自动微分](https://colab.research.google.com/drive/1VpeE6UvEPRz9HmsHh1KS0XxXjYu533EC) 的示例实现 + +**脚本的总运行时间**:(0 分钟 5.184 秒) + +[下载 Python 源码:`autograd_tutorial.py`](https://pytorch.org/tutorials/_downloads/00a1ac60985c7481f4250bafeae15ffa/autograd_tutorial.py) + +[下载 Jupyter 笔记本:`autograd_tutorial.ipynb`](https://pytorch.org/tutorials/_downloads/009cea8b0f40dfcb55e3280f73b06cc2/autograd_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 diff --git a/pytorch/官方教程/05.md b/pytorch/官方教程/05.md new file mode 100644 index 00000000..06eac934 --- /dev/null +++ b/pytorch/官方教程/05.md @@ -0,0 +1,292 @@ +# 神经网络 + +> 原文: + +可以使用`torch.nn`包构建神经网络。 + +现在您已经了解了`autograd`,`nn`依赖于`autograd`来定义模型并对其进行微分。 `nn.Module`包含层,以及返回`output`的方法`forward(input)`。 + +例如,查看以下对数字图像进行分类的网络: + +![convnet](img/3250cbba812d68265cf7815d987bcd1b.png) + +卷积网 + +这是一个简单的前馈网络。 它获取输入,将其一层又一层地馈入,然后最终给出输出。 + +神经网络的典型训练过程如下: + +* 定义具有一些可学习参数(或权重)的神经网络 +* 遍历输入数据集 +* 通过网络处理输入 +* 计算损失(输出正确的距离有多远) +* 将梯度传播回网络参数 +* 通常使用简单的更新规则来更新网络的权重:`weight = weight - learning_rate * gradient` + +## 定义网络 + +让我们定义这个网络: + +```py +import torch +import torch.nn as nn +import torch.nn.functional as F + +class Net(nn.Module): + + def __init__(self): + super(Net, self).__init__() + # 1 input image channel, 6 output channels, 3x3 square convolution + # kernel + self.conv1 = nn.Conv2d(1, 6, 3) + self.conv2 = nn.Conv2d(6, 16, 3) + # an affine operation: y = Wx + b + self.fc1 = nn.Linear(16 * 6 * 6, 120) # 6*6 from image dimension + self.fc2 = nn.Linear(120, 84) + self.fc3 = nn.Linear(84, 10) + + def forward(self, x): + # Max pooling over a (2, 2) window + x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2)) + # If the size is a square you can only specify a single number + x = F.max_pool2d(F.relu(self.conv2(x)), 2) + x = x.view(-1, self.num_flat_features(x)) + x = F.relu(self.fc1(x)) + x = F.relu(self.fc2(x)) + x = self.fc3(x) + return x + + def num_flat_features(self, x): + size = x.size()[1:] # all dimensions except the batch dimension + num_features = 1 + for s in size: + num_features *= s + return num_features + +net = Net() +print(net) + +``` + +出: + +```py +Net( + (conv1): Conv2d(1, 6, kernel_size=(3, 3), stride=(1, 1)) + (conv2): Conv2d(6, 16, kernel_size=(3, 3), stride=(1, 1)) + (fc1): Linear(in_features=576, out_features=120, bias=True) + (fc2): Linear(in_features=120, out_features=84, bias=True) + (fc3): Linear(in_features=84, out_features=10, bias=True) +) + +``` + +您只需要定义`forward`函数,就可以使用`autograd`为您自动定义`backward`函数(计算梯度)。 您可以在`forward`函数中使用任何张量操作。 + +模型的可学习参数由`net.parameters()`返回 + +```py +params = list(net.parameters()) +print(len(params)) +print(params[0].size()) # conv1's .weight + +``` + +出: + +```py +10 +torch.Size([6, 1, 3, 3]) + +``` + +让我们尝试一个`32x32`随机输入。 注意:该网络的预期输入大小(LeNet)为`32x32`。 要在 MNIST 数据集上使用此网络,请将图像从数据集中调整为`32x32`。 + +```py +input = torch.randn(1, 1, 32, 32) +out = net(input) +print(out) + +``` + +出: + +```py +tensor([[ 0.1002, -0.0694, -0.0436, 0.0103, 0.0488, -0.0429, -0.0941, -0.0146, + -0.0031, -0.0923]], grad_fn=) + +``` + +使用随机梯度将所有参数和反向传播的梯度缓冲区归零: + +```py +net.zero_grad() +out.backward(torch.randn(1, 10)) + +``` + +注意 + +`torch.nn`仅支持小批量。 整个`torch.nn`包仅支持作为微型样本而不是单个样本的输入。 + +例如,`nn.Conv2d`将采用`nSamples x nChannels x Height x Width`的 4D 张量。 + +如果您只有一个样本,只需使用`input.unsqueeze(0)`添加一个假批量尺寸。 + +在继续之前,让我们回顾一下到目前为止所看到的所有类。 + +**回顾**: + +* `torch.Tensor`-一个*多维数组*,支持诸如`backward()`的自动微分操作。 同样,保持相对于张量的梯度。 +* `nn.Module`-神经网络模块。 *封装参数*的便捷方法,并带有将其移动到 GPU,导出,加载等的帮助器。 +* `nn.Parameter`-一种张量,即将其分配为`Module`的属性时,自动注册为参数。 +* `autograd.Function`-实现自动微分操作的正向和反向定义。 每个`Tensor`操作都会创建至少一个`Function`节点,该节点连接到创建`Tensor`的函数,并且编码其历史记录。 + +**目前为止,我们涵盖了**: + +* 定义神经网络 +* 处理输入并向后调用 + +**仍然剩下**: + +* 计算损失 +* 更新网络的权重 + +## 损失函数 + +损失函数采用一对(输出,目标)输入,并计算一个值,该值估计输出与目标之间的距离。 + +`nn`包下有几种不同的[损失函数](https://pytorch.org/docs/nn.html#loss-functions)。 一个简单的损失是:`nn.MSELoss`,它计算输入和目标之间的均方误差。 + +例如: + +```py +output = net(input) +target = torch.randn(10) # a dummy target, for example +target = target.view(1, -1) # make it the same shape as output +criterion = nn.MSELoss() + +loss = criterion(output, target) +print(loss) + +``` + +出: + +```py +tensor(0.4969, grad_fn=) + +``` + +现在,如果使用`.grad_fn`属性向后跟随`loss`,您将看到一个计算图,如下所示: + +```py +input -> conv2d -> relu -> maxpool2d -> conv2d -> relu -> maxpool2d + -> view -> linear -> relu -> linear -> relu -> linear + -> MSELoss + -> loss + +``` + +因此,当我们调用`loss.backward()`时,整个图将被微分。 损失,并且图中具有`requires_grad=True`的所有张量将随梯度累积其`.grad`张量。 + +为了说明,让我们向后走几步: + +```py +print(loss.grad_fn) # MSELoss +print(loss.grad_fn.next_functions[0][0]) # Linear +print(loss.grad_fn.next_functions[0][0].next_functions[0][0]) # ReLU + +``` + +出: + +```py + + + + +``` + +## 反向传播 + +要反向传播误差,我们要做的只是对`loss.backward()`。 不过,您需要清除现有的梯度,否则梯度将累积到现有的梯度中。 + +现在,我们将其称为`loss.backward()`,然后看一下向后前后`conv1`的偏差梯度。 + +```py +net.zero_grad() # zeroes the gradient buffers of all parameters + +print('conv1.bias.grad before backward') +print(net.conv1.bias.grad) + +loss.backward() + +print('conv1.bias.grad after backward') +print(net.conv1.bias.grad) + +``` + +出: + +```py +conv1.bias.grad before backward +tensor([0., 0., 0., 0., 0., 0.]) +conv1.bias.grad after backward +tensor([ 0.0111, -0.0064, 0.0053, -0.0047, 0.0026, -0.0153]) + +``` + +现在,我们已经看到了如何使用损失函数。 + +**稍后阅读**: + +> 神经网络包包含各种模块和损失函数,这些模块和损失函数构成了深度神经网络的构建块。 带有文档的完整列表位于此处。 + +**唯一需要学习的是**: + +> * 更新网络的权重 + +## 更新权重 + +实践中使用的最简单的更新规则是随机梯度下降(SGD): + +> `weight = weight - learning_rate * gradient` + +我们可以使用简单的 Python 代码实现此目标: + +```py +learning_rate = 0.01 +for f in net.parameters(): + f.data.sub_(f.grad.data * learning_rate) + +``` + +但是,在使用神经网络时,您希望使用各种不同的更新规则,例如 SGD,Nesterov-SGD,Adam,RMSProp 等。为实现此目的,我们构建了一个小包装:`torch.optim`,可实现所有这些方法。 使用它非常简单: + +```py +import torch.optim as optim + +# create your optimizer +optimizer = optim.SGD(net.parameters(), lr=0.01) + +# in your training loop: +optimizer.zero_grad() # zero the gradient buffers +output = net(input) +loss = criterion(output, target) +loss.backward() +optimizer.step() # Does the update + +``` + +注意 + +观察如何使用`optimizer.zero_grad()`将梯度缓冲区手动设置为零。 这是因为如[反向传播](#backprop)部分中所述累积了梯度。 + +**脚本的总运行时间**:(0 分钟 3.778 秒) + +[下载 Python 源码:`neural_networks_tutorial.py`](https://pytorch.org/tutorials/_downloads/3665741da15f111de82da3227a615699/neural_networks_tutorial.py) + +[下载 Jupyter 笔记本:`neural_networks_tutorial.ipynb`](https://pytorch.org/tutorials/_downloads/97abb4c06a586d45ef3fc4b4b9634406/neural_networks_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/06.md b/pytorch/官方教程/06.md new file mode 100644 index 00000000..157f7097 --- /dev/null +++ b/pytorch/官方教程/06.md @@ -0,0 +1,421 @@ +# 训练分类器 + +> 原文: + +就是这个。 您已经了解了如何定义神经网络,计算损失并更新网络的权重。 + +现在您可能在想, + +## 数据呢? + +通常,当您必须处理图像,文本,音频或视频数据时,可以使用将数据加载到 NumPy 数组中的标准 Python 包。 然后,您可以将该数组转换为`torch.*Tensor`。 + +* 对于图像,Pillow,OpenCV 等包很有用 +* 对于音频,请使用 SciPy 和 librosa 等包 +* 对于文本,基于 Python 或 Cython 的原始加载,或者 NLTK 和 SpaCy 很有用 + +专门针对视觉,我们创建了一个名为`torchvision`的包,其中包含用于常见数据集(例如 Imagenet,CIFAR10,MNIST 等)的数据加载器,以及用于图像(即`torchvision.datasets`和`torch.utils.data.DataLoader`)的数据转换器。 + +这提供了极大的便利,并且避免了编写样板代码。 + +在本教程中,我们将使用 CIFAR10 数据集。 它具有以下类别:“飞机”,“汽车”,“鸟”,“猫”,“鹿”,“狗”,“青蛙”,“马”,“船”,“卡车”。 CIFAR-10 中的图像尺寸为`3x32x32`,即尺寸为`32x32`像素的 3 通道彩色图像。 + +![cifar10](img/ae800707f2489607d51d67499071db16.png) + +cifar10 + +## 训练图像分类器 + +我们将按顺序执行以下步骤: + +1. 使用`torchvision`加载并标准化 CIFAR10 训练和测试数据集 +2. 定义卷积神经网络 +3. 定义损失函数 +4. 根据训练数据训练网络 +5. 在测试数据上测试网络 + +### 1.加载并标准化 CIFAR10 + +使用`torchvision`,加载 CIFAR10 非常容易。 + +```py +import torch +import torchvision +import torchvision.transforms as transforms + +``` + +TorchVision 数据集的输出是`[0, 1]`范围的`PILImage`图像。 我们将它们转换为归一化范围`[-1, 1]`的张量。 .. 注意: + +```py +If running on Windows and you get a BrokenPipeError, try setting +the num_worker of torch.utils.data.DataLoader() to 0. + +``` + +```py +transform = transforms.Compose( + [transforms.ToTensor(), + transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) + +trainset = torchvision.datasets.CIFAR10(root='./data', train=True, + download=True, transform=transform) +trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, + shuffle=True, num_workers=2) + +testset = torchvision.datasets.CIFAR10(root='./data', train=False, + download=True, transform=transform) +testloader = torch.utils.data.DataLoader(testset, batch_size=4, + shuffle=False, num_workers=2) + +classes = ('plane', 'car', 'bird', 'cat', + 'deer', 'dog', 'frog', 'horse', 'ship', 'truck') + +``` + +出: + +```py +Downloading https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to ./data/cifar-10-python.tar.gz +Extracting ./data/cifar-10-python.tar.gz to ./data +Files already downloaded and verified + +``` + +让我们展示一些训练图像,很有趣。 + +```py +import matplotlib.pyplot as plt +import numpy as np + +# functions to show an image + +def imshow(img): + img = img / 2 + 0.5 # unnormalize + npimg = img.numpy() + plt.imshow(np.transpose(npimg, (1, 2, 0))) + plt.show() + +# get some random training images +dataiter = iter(trainloader) +images, labels = dataiter.next() + +# show images +imshow(torchvision.utils.make_grid(images)) +# print labels +print(' '.join('%5s' % classes[labels[j]] for j in range(4))) + +``` + +![../../_img/sphx_glr_cifar10_tutorial_001.png](img/aaf8c905effc5044cb9691420e5261fa.png) + +出: + +```py +dog truck frog horse + +``` + +### 2.定义卷积神经网络 + +之前从“神经网络”部分复制神经网络,然后对其进行修改以获取 3 通道图像(而不是定义的 1 通道图像)。 + +```py +import torch.nn as nn +import torch.nn.functional as F + +class Net(nn.Module): + def __init__(self): + super(Net, self).__init__() + self.conv1 = nn.Conv2d(3, 6, 5) + self.pool = nn.MaxPool2d(2, 2) + self.conv2 = nn.Conv2d(6, 16, 5) + self.fc1 = nn.Linear(16 * 5 * 5, 120) + self.fc2 = nn.Linear(120, 84) + self.fc3 = nn.Linear(84, 10) + + def forward(self, x): + x = self.pool(F.relu(self.conv1(x))) + x = self.pool(F.relu(self.conv2(x))) + x = x.view(-1, 16 * 5 * 5) + x = F.relu(self.fc1(x)) + x = F.relu(self.fc2(x)) + x = self.fc3(x) + return x + +net = Net() + +``` + +### 3.定义损失函数和优化器 + +让我们使用分类交叉熵损失和带有动量的 SGD。 + +```py +import torch.optim as optim + +criterion = nn.CrossEntropyLoss() +optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) + +``` + +### 4.训练网络 + +这是事情开始变得有趣的时候。 我们只需要遍历数据迭代器,然后将输入馈送到网络并进行优化即可。 + +```py +for epoch in range(2): # loop over the dataset multiple times + + running_loss = 0.0 + for i, data in enumerate(trainloader, 0): + # get the inputs; data is a list of [inputs, labels] + inputs, labels = data + + # zero the parameter gradients + optimizer.zero_grad() + + # forward + backward + optimize + outputs = net(inputs) + loss = criterion(outputs, labels) + loss.backward() + optimizer.step() + + # print statistics + running_loss += loss.item() + if i % 2000 == 1999: # print every 2000 mini-batches + print('[%d, %5d] loss: %.3f' % + (epoch + 1, i + 1, running_loss / 2000)) + running_loss = 0.0 + +print('Finished Training') + +``` + +出: + +```py +[1, 2000] loss: 2.196 +[1, 4000] loss: 1.849 +[1, 6000] loss: 1.671 +[1, 8000] loss: 1.589 +[1, 10000] loss: 1.547 +[1, 12000] loss: 1.462 +[2, 2000] loss: 1.382 +[2, 4000] loss: 1.389 +[2, 6000] loss: 1.369 +[2, 8000] loss: 1.332 +[2, 10000] loss: 1.304 +[2, 12000] loss: 1.288 +Finished Training + +``` + +让我们快速保存我们训练过的模型: + +```py +PATH = './cifar_net.pth' +torch.save(net.state_dict(), PATH) + +``` + +有关保存 PyTorch 模型的更多详细信息,请参见[此处](https://pytorch.org/docs/stable/notes/serialization.html)。 + +### 5.根据测试数据测试网络 + +我们已经在训练数据集中对网络进行了 2 次训练。 但是我们需要检查网络是否学到了什么。 + +我们将通过预测神经网络输出的类别标签并根据实际情况进行检查来进行检查。 如果预测正确,则将样本添加到正确预测列表中。 + +好的,第一步。 让我们显示测试集中的图像以使其熟悉。 + +```py +dataiter = iter(testloader) +images, labels = dataiter.next() + +# print images +imshow(torchvision.utils.make_grid(images)) +print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4))) + +``` + +![../../_img/sphx_glr_cifar10_tutorial_002.png](img/d148a5bd51a3278e9698bba522cbc34a.png) + +出: + +```py +GroundTruth: cat ship ship plane + +``` + +接下来,让我们重新加载保存的模型(注意:这里不需要保存和重新加载模型,我们只是为了说明如何这样做): + +```py +net = Net() +net.load_state_dict(torch.load(PATH)) + +``` + +好的,现在让我们看看神经网络对以上这些示例的看法: + +```py +outputs = net(images) + +``` + +输出是 10 类的能量。 一个类别的能量越高,网络就认为该图像属于特定类别。 因此,让我们获取最高能量的指数: + +```py +_, predicted = torch.max(outputs, 1) + +print('Predicted: ', ' '.join('%5s' % classes[predicted[j]] + for j in range(4))) + +``` + +出: + +```py +Predicted: cat ship ship plane + +``` + +结果似乎还不错。 + +让我们看一下网络在整个数据集上的表现。 + +```py +correct = 0 +total = 0 +with torch.no_grad(): + for data in testloader: + images, labels = data + outputs = net(images) + _, predicted = torch.max(outputs.data, 1) + total += labels.size(0) + correct += (predicted == labels).sum().item() + +print('Accuracy of the network on the 10000 test images: %d %%' % ( + 100 * correct / total)) + +``` + +出: + +```py +Accuracy of the network on the 10000 test images: 53 % + +``` + +看起来比偶然更好,准确率是 10%(从 10 个类中随机选择一个类)。 好像网络学到了一些东西。 + +嗯,哪些类的表现良好,哪些类的表现不佳: + +```py +class_correct = list(0\. for i in range(10)) +class_total = list(0\. for i in range(10)) +with torch.no_grad(): + for data in testloader: + images, labels = data + outputs = net(images) + _, predicted = torch.max(outputs, 1) + c = (predicted == labels).squeeze() + for i in range(4): + label = labels[i] + class_correct[label] += c[i].item() + class_total[label] += 1 + +for i in range(10): + print('Accuracy of %5s : %2d %%' % ( + classes[i], 100 * class_correct[i] / class_total[i])) + +``` + +出: + +```py +Accuracy of plane : 50 % +Accuracy of car : 62 % +Accuracy of bird : 51 % +Accuracy of cat : 32 % +Accuracy of deer : 31 % +Accuracy of dog : 35 % +Accuracy of frog : 77 % +Accuracy of horse : 70 % +Accuracy of ship : 71 % +Accuracy of truck : 52 % + +``` + +好的,那下一步呢? + +我们如何在 GPU 上运行这些神经网络? + +## 在 GPU 上进行训练 + +就像将张量转移到 GPU 上一样,您也将神经网络转移到 GPU 上。 + +如果可以使用 CUDA,首先将我们的设备定义为第一个可见的 cuda 设备: + +```py +device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") + +# Assuming that we are on a CUDA machine, this should print a CUDA device: + +print(device) + +``` + +出: + +```py +cuda:0 + +``` + +本节的其余部分假定`device`是 CUDA 设备。 + +然后,这些方法将递归遍历所有模块,并将其参数和缓冲区转换为 CUDA 张量: + +```py +net.to(device) + +``` + +请记住,您还必须将每一步的输入和目标也发送到 GPU: + +```py +inputs, labels = data[0].to(device), data[1].to(device) + +``` + +与 CPU 相比,为什么我没有注意到 MASSIVE 加速? 因为您的网络真的很小。 + +**练习**:尝试增加网络的宽度(第一个`nn.Conv2d`的参数 2 和第二个`nn.Conv2d`的参数 1 –它们必须是相同的数字),看看您可以得到哪种加速。 + +**已实现的目标**: + +* 全面了解 PyTorch 的张量库和神经网络。 +* 训练一个小型神经网络对图像进行分类 + +## 在多个 GPU 上进行训练 + +如果您想使用所有 GPU 来获得更大的大规模加速,请查看[可选:数据并行](data_parallel_tutorial.html)。 + +## 我下一步要去哪里? + +* [训练神经网络玩视频游戏](../../intermediate/reinforcement_q_learning.html) +* [在 imagenet 上训练最先进的 ResNet 网络](https://github.com/pytorch/examples/tree/master/imagenet) +* [使用生成对抗网络训练人脸生成器](https://github.com/pytorch/examples/tree/master/dcgan) +* [使用递归 LSTM 网络训练单词级语言模型](https://github.com/pytorch/examples/tree/master/word_language_model) +* [更多示例](https://github.com/pytorch/examples) +* [更多教程](https://github.com/pytorch/tutorials) +* [在论坛上讨论 PyTorch](https://discuss.pytorch.org/) +* [在 Slack 上与其他用户聊天](https://pytorch.slack.com/messages/beginner/) + +**脚本的总运行时间**:(2 分钟 39.965 秒) + +[下载 Python 源码:`cifar10_tutorial.py`](https://pytorch.org/tutorials/_downloads/ba100c1433c3c42a16709bb6a2ed0f85/cifar10_tutorial.py) + +[下载 Jupyter 笔记本:`cifar10_tutorial.ipynb`](https://pytorch.org/tutorials/_downloads/17a7c7cb80916fcdf921097825a0f562/cifar10_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/07.md b/pytorch/官方教程/07.md new file mode 100644 index 00000000..4cedfe0b --- /dev/null +++ b/pytorch/官方教程/07.md @@ -0,0 +1,631 @@ +# 通过示例学习 PyTorch + +> 原文: + +**作者**:[Justin Johnson](https://github.com/jcjohnson/pytorch-examples) + +本教程通过独立的示例介绍 [PyTorch](https://github.com/pytorch/pytorch) 的基本概念。 + +PyTorch 的核心是提供两个主要功能: + +* n 维张量,类似于 NumPy,但可以在 GPU 上运行 +* 用于构建和训练神经网络的自动微分 + +我们将使用将三阶多项式拟合`y = sin(x)`的问题作为运行示例。 该网络将具有四个参数,并且将通过使网络输出与实际输出之间的欧几里德距离最小化来进行梯度下降训练,以适应随机数据。 + +注意 + +您可以在[本页](#examples-download)浏览各个示例。 + +## 张量 + +### 预热:NumPy + +在介绍 PyTorch 之前,我们将首先使用 numpy 实现网络。 + +Numpy 提供了一个 n 维数组对象,以及许多用于操纵这些数组的函数。 Numpy 是用于科学计算的通用框架。 它对计算图,深度学习或梯度一无所知。 但是,通过使用 numpy 操作手动实现网络的前向和后向传递,我们可以轻松地使用 numpy 使三阶多项式适合正弦函数: + +```py +# -*- coding: utf-8 -*- +import numpy as np +import math + +# Create random input and output data +x = np.linspace(-math.pi, math.pi, 2000) +y = np.sin(x) + +# Randomly initialize weights +a = np.random.randn() +b = np.random.randn() +c = np.random.randn() +d = np.random.randn() + +learning_rate = 1e-6 +for t in range(2000): + # Forward pass: compute predicted y + # y = a + b x + c x^2 + d x^3 + y_pred = a + b * x + c * x ** 2 + d * x ** 3 + + # Compute and print loss + loss = np.square(y_pred - y).sum() + if t % 100 == 99: + print(t, loss) + + # Backprop to compute gradients of a, b, c, d with respect to loss + grad_y_pred = 2.0 * (y_pred - y) + grad_a = grad_y_pred.sum() + grad_b = (grad_y_pred * x).sum() + grad_c = (grad_y_pred * x ** 2).sum() + grad_d = (grad_y_pred * x ** 3).sum() + + # Update weights + a -= learning_rate * grad_a + b -= learning_rate * grad_b + c -= learning_rate * grad_c + d -= learning_rate * grad_d + +print(f'Result: y = {a} + {b} x + {c} x^2 + {d} x^3') + +``` + +### PyTorch:张量 + +Numpy 是一个很棒的框架,但是它不能利用 GPU 来加速其数值计算。 对于现代深度神经网络,GPU 通常会提供 [50 倍或更高](https://github.com/jcjohnson/cnn-benchmarks)的加速,因此遗憾的是,numpy 不足以实现现代深度学习。 + +在这里,我们介绍最基本的 PyTorch 概念:**张量**。 PyTorch 张量在概念上与 numpy 数组相同:张量是 n 维数组,PyTorch 提供了许多在这些张量上进行操作的函数。 在幕后,张量可以跟踪计算图和梯度,但它们也可用作科学计算的通用工具。 + +与 numpy 不同,PyTorch 张量可以利用 GPU 加速其数字计算。 要在 GPU 上运行 PyTorch 张量,您只需要指定正确的设备即可。 + +在这里,我们使用 PyTorch 张量将三阶多项式拟合为正弦函数。 像上面的 numpy 示例一样,我们需要手动实现通过网络的正向和反向传递: + +```py +# -*- coding: utf-8 -*- + +import torch +import math + +dtype = torch.float +device = torch.device("cpu") +# device = torch.device("cuda:0") # Uncomment this to run on GPU + +# Create random input and output data +x = torch.linspace(-math.pi, math.pi, 2000, device=device, dtype=dtype) +y = torch.sin(x) + +# Randomly initialize weights +a = torch.randn((), device=device, dtype=dtype) +b = torch.randn((), device=device, dtype=dtype) +c = torch.randn((), device=device, dtype=dtype) +d = torch.randn((), device=device, dtype=dtype) + +learning_rate = 1e-6 +for t in range(2000): + # Forward pass: compute predicted y + y_pred = a + b * x + c * x ** 2 + d * x ** 3 + + # Compute and print loss + loss = (y_pred - y).pow(2).sum().item() + if t % 100 == 99: + print(t, loss) + + # Backprop to compute gradients of a, b, c, d with respect to loss + grad_y_pred = 2.0 * (y_pred - y) + grad_a = grad_y_pred.sum() + grad_b = (grad_y_pred * x).sum() + grad_c = (grad_y_pred * x ** 2).sum() + grad_d = (grad_y_pred * x ** 3).sum() + + # Update weights using gradient descent + a -= learning_rate * grad_a + b -= learning_rate * grad_b + c -= learning_rate * grad_c + d -= learning_rate * grad_d + +print(f'Result: y = {a.item()} + {b.item()} x + {c.item()} x^2 + {d.item()} x^3') + +``` + +## Autograd + +### PyTorch:张量和 Autograd + +在上述示例中,我们必须手动实现神经网络的前向和后向传递。 对于小型的两层网络,手动实现反向传递并不是什么大问题,但是对于大型的复杂网络来说,可以很快变得非常麻烦。 + +幸运的是,我们可以使用[自动微分](https://en.wikipedia.org/wiki/Automatic_differentiation)来自动计算神经网络中的反向传递。 PyTorch 中的 **Autograd** 包正是提供了此功能。 使用 Autograd 时,网络的正向传播将定义**计算图**; 图中的节点为张量,边为从输入张量产生输出张量的函数。 然后通过该图进行反向传播,可以轻松计算梯度。 + +这听起来很复杂,在实践中非常简单。 每个张量代表计算图中的一个节点。 如果`x`是具有`x.requires_grad=True`的张量,则`x.grad`是另一个张量,其保持`x`相对于某个标量值的梯度。 + +在这里,我们使用 PyTorch 张量和 Autograd 来实现我们的正弦波与三阶多项式示例; 现在我们不再需要通过网络手动实现反向传递: + +```py +# -*- coding: utf-8 -*- +import torch +import math + +dtype = torch.float +device = torch.device("cpu") +# device = torch.device("cuda:0") # Uncomment this to run on GPU + +# Create Tensors to hold input and outputs. +# By default, requires_grad=False, which indicates that we do not need to +# compute gradients with respect to these Tensors during the backward pass. +x = torch.linspace(-math.pi, math.pi, 2000, device=device, dtype=dtype) +y = torch.sin(x) + +# Create random Tensors for weights. For a third order polynomial, we need +# 4 weights: y = a + b x + c x^2 + d x^3 +# Setting requires_grad=True indicates that we want to compute gradients with +# respect to these Tensors during the backward pass. +a = torch.randn((), device=device, dtype=dtype, requires_grad=True) +b = torch.randn((), device=device, dtype=dtype, requires_grad=True) +c = torch.randn((), device=device, dtype=dtype, requires_grad=True) +d = torch.randn((), device=device, dtype=dtype, requires_grad=True) + +learning_rate = 1e-6 +for t in range(2000): + # Forward pass: compute predicted y using operations on Tensors. + y_pred = a + b * x + c * x ** 2 + d * x ** 3 + + # Compute and print loss using operations on Tensors. + # Now loss is a Tensor of shape (1,) + # loss.item() gets the scalar value held in the loss. + loss = (y_pred - y).pow(2).sum() + if t % 100 == 99: + print(t, loss.item()) + + # Use autograd to compute the backward pass. This call will compute the + # gradient of loss with respect to all Tensors with requires_grad=True. + # After this call a.grad, b.grad. c.grad and d.grad will be Tensors holding + # the gradient of the loss with respect to a, b, c, d respectively. + loss.backward() + + # Manually update weights using gradient descent. Wrap in torch.no_grad() + # because weights have requires_grad=True, but we don't need to track this + # in autograd. + with torch.no_grad(): + a -= learning_rate * a.grad + b -= learning_rate * b.grad + c -= learning_rate * c.grad + d -= learning_rate * d.grad + + # Manually zero the gradients after updating weights + a.grad = None + b.grad = None + c.grad = None + d.grad = None + +print(f'Result: y = {a.item()} + {b.item()} x + {c.item()} x^2 + {d.item()} x^3') + +``` + +### PyTorch:定义新的 Autograd 函数 + +在幕后,每个原始的 Autograd 运算符实际上都是在张量上运行的两个函数。 **正向**函数从输入张量计算输出张量。 **反向**函数接收相对于某个标量值的输出张量的梯度,并计算相对于相同标量值的输入张量的梯度。 + +在 PyTorch 中,我们可以通过定义`torch.autograd.Function`的子类并实现`forward`和`backward`函数来轻松定义自己的 Autograd 运算符。 然后,我们可以通过构造实例并像调用函数一样调用新的 Autograd 运算符,并传递包含输入数据的张量。 + +在此示例中,我们将模型定义为`y = a + b P[3](c + dx)`而不是`y = a + bx + cx ^ 2 + dx ^ 3`,其中`P[3](x) = 1/2 (5x ^ 3 - 3x)`是三次的[勒让德多项式](https://en.wikipedia.org/wiki/Legendre_polynomials)。 我们编写了自己的自定义 Autograd 函数来计算`P[3]`的前进和后退,并使用它来实现我们的模型: + +```py +# -*- coding: utf-8 -*- +import torch +import math + +class LegendrePolynomial3(torch.autograd.Function): + """ + We can implement our own custom autograd Functions by subclassing + torch.autograd.Function and implementing the forward and backward passes + which operate on Tensors. + """ + + @staticmethod + def forward(ctx, input): + """ + In the forward pass we receive a Tensor containing the input and return + a Tensor containing the output. ctx is a context object that can be used + to stash information for backward computation. You can cache arbitrary + objects for use in the backward pass using the ctx.save_for_backward method. + """ + ctx.save_for_backward(input) + return 0.5 * (5 * input ** 3 - 3 * input) + + @staticmethod + def backward(ctx, grad_output): + """ + In the backward pass we receive a Tensor containing the gradient of the loss + with respect to the output, and we need to compute the gradient of the loss + with respect to the input. + """ + input, = ctx.saved_tensors + return grad_output * 1.5 * (5 * input ** 2 - 1) + +dtype = torch.float +device = torch.device("cpu") +# device = torch.device("cuda:0") # Uncomment this to run on GPU + +# Create Tensors to hold input and outputs. +# By default, requires_grad=False, which indicates that we do not need to +# compute gradients with respect to these Tensors during the backward pass. +x = torch.linspace(-math.pi, math.pi, 2000, device=device, dtype=dtype) +y = torch.sin(x) + +# Create random Tensors for weights. For this example, we need +# 4 weights: y = a + b * P3(c + d * x), these weights need to be initialized +# not too far from the correct result to ensure convergence. +# Setting requires_grad=True indicates that we want to compute gradients with +# respect to these Tensors during the backward pass. +a = torch.full((), 0.0, device=device, dtype=dtype, requires_grad=True) +b = torch.full((), -1.0, device=device, dtype=dtype, requires_grad=True) +c = torch.full((), 0.0, device=device, dtype=dtype, requires_grad=True) +d = torch.full((), 0.3, device=device, dtype=dtype, requires_grad=True) + +learning_rate = 5e-6 +for t in range(2000): + # To apply our Function, we use Function.apply method. We alias this as 'P3'. + P3 = LegendrePolynomial3.apply + + # Forward pass: compute predicted y using operations; we compute + # P3 using our custom autograd operation. + y_pred = a + b * P3(c + d * x) + + # Compute and print loss + loss = (y_pred - y).pow(2).sum() + if t % 100 == 99: + print(t, loss.item()) + + # Use autograd to compute the backward pass. + loss.backward() + + # Update weights using gradient descent + with torch.no_grad(): + a -= learning_rate * a.grad + b -= learning_rate * b.grad + c -= learning_rate * c.grad + d -= learning_rate * d.grad + + # Manually zero the gradients after updating weights + a.grad = None + b.grad = None + c.grad = None + d.grad = None + +print(f'Result: y = {a.item()} + {b.item()} * P3({c.item()} + {d.item()} x)') + +``` + +## `nn`模块 + +### PyTorch:`nn` + +计算图和 Autograd 是定义复杂运算符并自动采用导数的非常强大的范例。 但是对于大型神经网络,原始的 Autograd 可能会太低级。 + +在构建神经网络时,我们经常想到将计算安排在**层**中,其中某些层具有**可学习的参数**,这些参数会在学习期间进行优化。 + +在 TensorFlow 中,像 [Keras](https://github.com/fchollet/keras) , [TensorFlow-Slim](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/slim) 和 [TFLearn](http://tflearn.org/) 之类的包在原始计算图上提供了更高层次的抽象,可用于构建神经网络。 + +在 PyTorch 中,`nn`包也达到了相同的目的。 `nn`包定义了一组**模块**,它们大致等效于神经网络层。 模块接收输入张量并计算输出张量,但也可以保持内部状态,例如包含可学习参数的张量。 `nn`包还定义了一组有用的损失函数,这些函数通常在训练神经网络时使用。 + +在此示例中,我们使用`nn`包来实现我们的多项式模型网络: + +```py +# -*- coding: utf-8 -*- +import torch +import math + +# Create Tensors to hold input and outputs. +x = torch.linspace(-math.pi, math.pi, 2000) +y = torch.sin(x) + +# For this example, the output y is a linear function of (x, x^2, x^3), so +# we can consider it as a linear layer neural network. Let's prepare the +# tensor (x, x^2, x^3). +p = torch.tensor([1, 2, 3]) +xx = x.unsqueeze(-1).pow(p) + +# In the above code, x.unsqueeze(-1) has shape (2000, 1), and p has shape +# (3,), for this case, broadcasting semantics will apply to obtain a tensor +# of shape (2000, 3) + +# Use the nn package to define our model as a sequence of layers. nn.Sequential +# is a Module which contains other Modules, and applies them in sequence to +# produce its output. The Linear Module computes output from input using a +# linear function, and holds internal Tensors for its weight and bias. +# The Flatten layer flatens the output of the linear layer to a 1D tensor, +# to match the shape of `y`. +model = torch.nn.Sequential( + torch.nn.Linear(3, 1), + torch.nn.Flatten(0, 1) +) + +# The nn package also contains definitions of popular loss functions; in this +# case we will use Mean Squared Error (MSE) as our loss function. +loss_fn = torch.nn.MSELoss(reduction='sum') + +learning_rate = 1e-6 +for t in range(2000): + + # Forward pass: compute predicted y by passing x to the model. Module objects + # override the __call__ operator so you can call them like functions. When + # doing so you pass a Tensor of input data to the Module and it produces + # a Tensor of output data. + y_pred = model(xx) + + # Compute and print loss. We pass Tensors containing the predicted and true + # values of y, and the loss function returns a Tensor containing the + # loss. + loss = loss_fn(y_pred, y) + if t % 100 == 99: + print(t, loss.item()) + + # Zero the gradients before running the backward pass. + model.zero_grad() + + # Backward pass: compute gradient of the loss with respect to all the learnable + # parameters of the model. Internally, the parameters of each Module are stored + # in Tensors with requires_grad=True, so this call will compute gradients for + # all learnable parameters in the model. + loss.backward() + + # Update the weights using gradient descent. Each parameter is a Tensor, so + # we can access its gradients like we did before. + with torch.no_grad(): + for param in model.parameters(): + param -= learning_rate * param.grad + +# You can access the first layer of `model` like accessing the first item of a list +linear_layer = model[0] + +# For linear layer, its parameters are stored as `weight` and `bias`. +print(f'Result: y = {linear_layer.bias.item()} + {linear_layer.weight[:, 0].item()} x + {linear_layer.weight[:, 1].item()} x^2 + {linear_layer.weight[:, 2].item()} x^3') + +``` + +### PyTorch:`optim` + +到目前为止,我们已经通过使用`torch.no_grad()`手动更改持有可学习参数的张量来更新模型的权重。 对于像随机梯度下降这样的简单优化算法来说,这并不是一个巨大的负担,但是在实践中,我们经常使用更复杂的优化器(例如 AdaGrad,RMSProp,Adam 等)来训练神经网络。 + +PyTorch 中的`optim`包抽象了优化算法的思想,并提供了常用优化算法的实现。 + +在此示例中,我们将使用`nn`包像以前一样定义我们的模型,但是我们将使用`optim`包提供的 RMSprop 算法来优化模型: + +```py +# -*- coding: utf-8 -*- +import torch +import math + +# Create Tensors to hold input and outputs. +x = torch.linspace(-math.pi, math.pi, 2000) +y = torch.sin(x) + +# Prepare the input tensor (x, x^2, x^3). +p = torch.tensor([1, 2, 3]) +xx = x.unsqueeze(-1).pow(p) + +# Use the nn package to define our model and loss function. +model = torch.nn.Sequential( + torch.nn.Linear(3, 1), + torch.nn.Flatten(0, 1) +) +loss_fn = torch.nn.MSELoss(reduction='sum') + +# Use the optim package to define an Optimizer that will update the weights of +# the model for us. Here we will use RMSprop; the optim package contains many other +# optimization algorithms. The first argument to the RMSprop constructor tells the +# optimizer which Tensors it should update. +learning_rate = 1e-3 +optimizer = torch.optim.RMSprop(model.parameters(), lr=learning_rate) +for t in range(2000): + # Forward pass: compute predicted y by passing x to the model. + y_pred = model(xx) + + # Compute and print loss. + loss = loss_fn(y_pred, y) + if t % 100 == 99: + print(t, loss.item()) + + # Before the backward pass, use the optimizer object to zero all of the + # gradients for the variables it will update (which are the learnable + # weights of the model). This is because by default, gradients are + # accumulated in buffers( i.e, not overwritten) whenever .backward() + # is called. Checkout docs of torch.autograd.backward for more details. + optimizer.zero_grad() + + # Backward pass: compute gradient of the loss with respect to model + # parameters + loss.backward() + + # Calling the step function on an Optimizer makes an update to its + # parameters + optimizer.step() + +linear_layer = model[0] +print(f'Result: y = {linear_layer.bias.item()} + {linear_layer.weight[:, 0].item()} x + {linear_layer.weight[:, 1].item()} x^2 + {linear_layer.weight[:, 2].item()} x^3') + +``` + +### PyTorch:自定义`nn`模块 + +有时,您将需要指定比一系列现有模块更复杂的模型。 对于这些情况,您可以通过子类化`nn.Module`并定义一个`forward`来定义自己的模块,该模块使用其他模块或在 Tensors 上的其他自动转换操作来接收输入 Tensors 并生成输出 Tensors。 + +在此示例中,我们将三阶多项式实现为自定义`Module`子类: + +```py +# -*- coding: utf-8 -*- +import torch +import math + +class Polynomial3(torch.nn.Module): + def __init__(self): + """ + In the constructor we instantiate four parameters and assign them as + member parameters. + """ + super().__init__() + self.a = torch.nn.Parameter(torch.randn(())) + self.b = torch.nn.Parameter(torch.randn(())) + self.c = torch.nn.Parameter(torch.randn(())) + self.d = torch.nn.Parameter(torch.randn(())) + + def forward(self, x): + """ + In the forward function we accept a Tensor of input data and we must return + a Tensor of output data. We can use Modules defined in the constructor as + well as arbitrary operators on Tensors. + """ + return self.a + self.b * x + self.c * x ** 2 + self.d * x ** 3 + + def string(self): + """ + Just like any class in Python, you can also define custom method on PyTorch modules + """ + return f'y = {self.a.item()} + {self.b.item()} x + {self.c.item()} x^2 + {self.d.item()} x^3' + +# Create Tensors to hold input and outputs. +x = torch.linspace(-math.pi, math.pi, 2000) +y = torch.sin(x) + +# Construct our model by instantiating the class defined above +model = Polynomial3() + +# Construct our loss function and an Optimizer. The call to model.parameters() +# in the SGD constructor will contain the learnable parameters of the nn.Linear +# module which is members of the model. +criterion = torch.nn.MSELoss(reduction='sum') +optimizer = torch.optim.SGD(model.parameters(), lr=1e-6) +for t in range(2000): + # Forward pass: Compute predicted y by passing x to the model + y_pred = model(x) + + # Compute and print loss + loss = criterion(y_pred, y) + if t % 100 == 99: + print(t, loss.item()) + + # Zero gradients, perform a backward pass, and update the weights. + optimizer.zero_grad() + loss.backward() + optimizer.step() + +print(f'Result: {model.string()}') + +``` + +### PyTorch:控制流 + 权重共享 + +作为动态图和权重共享的示例,我们实现了一个非常奇怪的模型:一个三阶多项式,在每个正向传播中选择 3 到 5 之间的一个随机数,并使用该阶数,多次使用相同的权重重复计算四和五阶。 + +对于此模型,我们可以使用常规的 Python 流控制来实现循环,并且可以通过在定义正向传播时简单地多次重复使用相同的参数来实现权重共享。 + +我们可以轻松地将此模型实现为`Module`子类: + +```py +# -*- coding: utf-8 -*- +import random +import torch +import math + +class DynamicNet(torch.nn.Module): + def __init__(self): + """ + In the constructor we instantiate five parameters and assign them as members. + """ + super().__init__() + self.a = torch.nn.Parameter(torch.randn(())) + self.b = torch.nn.Parameter(torch.randn(())) + self.c = torch.nn.Parameter(torch.randn(())) + self.d = torch.nn.Parameter(torch.randn(())) + self.e = torch.nn.Parameter(torch.randn(())) + + def forward(self, x): + """ + For the forward pass of the model, we randomly choose either 4, 5 + and reuse the e parameter to compute the contribution of these orders. + + Since each forward pass builds a dynamic computation graph, we can use normal + Python control-flow operators like loops or conditional statements when + defining the forward pass of the model. + + Here we also see that it is perfectly safe to reuse the same parameter many + times when defining a computational graph. + """ + y = self.a + self.b * x + self.c * x ** 2 + self.d * x ** 3 + for exp in range(4, random.randint(4, 6)): + y = y + self.e * x ** exp + return y + + def string(self): + """ + Just like any class in Python, you can also define custom method on PyTorch modules + """ + return f'y = {self.a.item()} + {self.b.item()} x + {self.c.item()} x^2 + {self.d.item()} x^3 + {self.e.item()} x^4 ? + {self.e.item()} x^5 ?' + +# Create Tensors to hold input and outputs. +x = torch.linspace(-math.pi, math.pi, 2000) +y = torch.sin(x) + +# Construct our model by instantiating the class defined above +model = DynamicNet() + +# Construct our loss function and an Optimizer. Training this strange model with +# vanilla stochastic gradient descent is tough, so we use momentum +criterion = torch.nn.MSELoss(reduction='sum') +optimizer = torch.optim.SGD(model.parameters(), lr=1e-8, momentum=0.9) +for t in range(30000): + # Forward pass: Compute predicted y by passing x to the model + y_pred = model(x) + + # Compute and print loss + loss = criterion(y_pred, y) + if t % 2000 == 1999: + print(t, loss.item()) + + # Zero gradients, perform a backward pass, and update the weights. + optimizer.zero_grad() + loss.backward() + optimizer.step() + +print(f'Result: {model.string()}') + +``` + +## 示例 + +您可以在此处浏览以上示例。 + +### 张量 + +![../_img/sphx_glr_polynomial_numpy_thumb.png](img/ea0bddb69dfbd67215b823007544ab8f.png) + +[热身:NumPy](examples_tensor/polynomial_numpy.html#sphx-glr-beginner-examples-tensor-polynomial-numpy-py) + +![../_img/sphx_glr_polynomial_tensor_thumb.png](img/04ee335faf821b337dba0c4d7ccb0b67.png) + +[PyTorch:张量](examples_tensor/polynomial_tensor.html#sphx-glr-beginner-examples-tensor-polynomial-tensor-py) + +### Autograd + +![../_img/sphx_glr_polynomial_autograd_thumb.png](img/ffad28c33f8a48d06521421f1aa441ed.png) + +[PyTorch:张量和 Autograd](examples_autograd/polynomial_autograd.html#sphx-glr-beginner-examples-autograd-polynomial-autograd-py) + +![../_img/sphx_glr_polynomial_custom_function_thumb.png](img/a5c5d931ed12e34bf68476f4f157b780.png) + +[PyTorch:定义新的 Autograd 函数](examples_autograd/polynomial_custom_function.html#sphx-glr-beginner-examples-autograd-polynomial-custom-function-py) + +### `nn`模块 + +![../_img/sphx_glr_polynomial_nn_thumb.png](img/335fb81e535f98bfda7cbdb3e50d8832.png) + +[PyTorch:`nn`](examples_nn/polynomial_nn.html#sphx-glr-beginner-examples-nn-polynomial-nn-py) + +![../_img/sphx_glr_polynomial_optim_thumb.png](img/87aa5017f5f0ba9a29d66e74ac6b3d1a.png) + +[PyTorch:`optim`](examples_nn/polynomial_optim.html#sphx-glr-beginner-examples-nn-polynomial-optim-py) + +![../_img/sphx_glr_polynomial_module_thumb.png](img/b3f0b96ed8ba751fee4a5fc7ca878eb1.png) + +[PyTorch:自定义`nn`模块](examples_nn/polynomial_module.html#sphx-glr-beginner-examples-nn-polynomial-module-py) + +![../_img/sphx_glr_dynamic_net_thumb.png](img/bf0b252ce2d39ba6da26c16bee984d39.png) + +[PyTorch:控制流 + 权重共享](examples_nn/dynamic_net.html#sphx-glr-beginner-examples-nn-dynamic-net-py) \ No newline at end of file diff --git a/pytorch/官方教程/08.md b/pytorch/官方教程/08.md new file mode 100644 index 00000000..d78d6eb0 --- /dev/null +++ b/pytorch/官方教程/08.md @@ -0,0 +1,59 @@ +# 热身:NumPy + +> 原文: + +经过训练的三阶多项式,可以通过最小化平方的欧几里得距离来预测`y = sin(x)`从`-pi`到`pi`。 + +此实现使用 numpy 手动计算正向传播,损失和后向通过。 + +numpy 数组是通用的 n 维数组; 它对深度学习,梯度或计算图一无所知,而只是执行通用数值计算的一种方法。 + +```py +import numpy as np +import math + +# Create random input and output data +x = np.linspace(-math.pi, math.pi, 2000) +y = np.sin(x) + +# Randomly initialize weights +a = np.random.randn() +b = np.random.randn() +c = np.random.randn() +d = np.random.randn() + +learning_rate = 1e-6 +for t in range(2000): + # Forward pass: compute predicted y + # y = a + b x + c x^2 + d x^3 + y_pred = a + b * x + c * x ** 2 + d * x ** 3 + + # Compute and print loss + loss = np.square(y_pred - y).sum() + if t % 100 == 99: + print(t, loss) + + # Backprop to compute gradients of a, b, c, d with respect to loss + grad_y_pred = 2.0 * (y_pred - y) + grad_a = grad_y_pred.sum() + grad_b = (grad_y_pred * x).sum() + grad_c = (grad_y_pred * x ** 2).sum() + grad_d = (grad_y_pred * x ** 3).sum() + + # Update weights + a -= learning_rate * grad_a + b -= learning_rate * grad_b + c -= learning_rate * grad_c + d -= learning_rate * grad_d + +print(f'Result: y = {a} + {b} x + {c} x^2 + {d} x^3') + +``` + +**脚本的总运行时间**:(0 分钟 0.000 秒) + +[下载 Python 源码:`polynomial_numpy.py`](https://pytorch.org/tutorials/_downloads/6287cd68dd239d4f34ac75d774a66e23/polynomial_numpy.py) + +[下载 Jupyter 笔记本:`polynomial_numpy.ipynb`](https://pytorch.org/tutorials/_downloads/d4cfaf6a36486a5e37afb34266028d9e/polynomial_numpy.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/09.md b/pytorch/官方教程/09.md new file mode 100644 index 00000000..709223d7 --- /dev/null +++ b/pytorch/官方教程/09.md @@ -0,0 +1,64 @@ +# PyTorch:张量 + +> 原文: + +经过训练的三阶多项式,可以通过最小化平方的欧几里得距离来预测`y = sin(x)`从`-pi`到`pi`。 + +此实现使用 PyTorch 张量手动计算正向传播,损失和后向通过。 + +PyTorch 张量基本上与 numpy 数组相同:它对深度学习或计算图或梯度一无所知,只是用于任意数值计算的通用 n 维数组。 + +numpy 数组和 PyTorch 张量之间的最大区别是 PyTorch 张量可以在 CPU 或 GPU 上运行。 要在 GPU 上运行操作,只需将张量转换为 cuda 数据类型。 + +```py +import torch +import math + +dtype = torch.float +device = torch.device("cpu") +# device = torch.device("cuda:0") # Uncomment this to run on GPU + +# Create random input and output data +x = torch.linspace(-math.pi, math.pi, 2000, device=device, dtype=dtype) +y = torch.sin(x) + +# Randomly initialize weights +a = torch.randn((), device=device, dtype=dtype) +b = torch.randn((), device=device, dtype=dtype) +c = torch.randn((), device=device, dtype=dtype) +d = torch.randn((), device=device, dtype=dtype) + +learning_rate = 1e-6 +for t in range(2000): + # Forward pass: compute predicted y + y_pred = a + b * x + c * x ** 2 + d * x ** 3 + + # Compute and print loss + loss = (y_pred - y).pow(2).sum().item() + if t % 100 == 99: + print(t, loss) + + # Backprop to compute gradients of a, b, c, d with respect to loss + grad_y_pred = 2.0 * (y_pred - y) + grad_a = grad_y_pred.sum() + grad_b = (grad_y_pred * x).sum() + grad_c = (grad_y_pred * x ** 2).sum() + grad_d = (grad_y_pred * x ** 3).sum() + + # Update weights using gradient descent + a -= learning_rate * grad_a + b -= learning_rate * grad_b + c -= learning_rate * grad_c + d -= learning_rate * grad_d + +print(f'Result: y = {a.item()} + {b.item()} x + {c.item()} x^2 + {d.item()} x^3') + +``` + +**脚本的总运行时间**:(0 分钟 0.000 秒) + +[下载 Python 源码:`polynomial_tensor.py`](https://pytorch.org/tutorials/_downloads/38bc029908996abe0c601bcf0f5fd9d8/polynomial_tensor.py) + +[下载 Jupyter 笔记本:`polynomial_tensor.ipynb`](https://pytorch.org/tutorials/_downloads/1c715a0888ae0e33279df327e1653329/polynomial_tensor.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/10.md b/pytorch/官方教程/10.md new file mode 100644 index 00000000..da742903 --- /dev/null +++ b/pytorch/官方教程/10.md @@ -0,0 +1,77 @@ +# PyTorch:张量和 Autograd + +> 原文: + +经过训练的三阶多项式,可以通过最小化平方的欧几里得距离来预测`y = sin(x)`从`-pi`到`pi`。 + +此实现使用 PyTorch 张量上的运算来计算正向传播,并使用 PyTorch Autograd 来计算梯度。 + +PyTorch 张量表示计算图中的一个节点。 如果`x`是具有`x.requires_grad=True`的张量,则`x.grad`是另一个张量,其保持`x`相对于某个标量值的梯度。 + +```py +import torch +import math + +dtype = torch.float +device = torch.device("cpu") +# device = torch.device("cuda:0") # Uncomment this to run on GPU + +# Create Tensors to hold input and outputs. +# By default, requires_grad=False, which indicates that we do not need to +# compute gradients with respect to these Tensors during the backward pass. +x = torch.linspace(-math.pi, math.pi, 2000, device=device, dtype=dtype) +y = torch.sin(x) + +# Create random Tensors for weights. For a third order polynomial, we need +# 4 weights: y = a + b x + c x^2 + d x^3 +# Setting requires_grad=True indicates that we want to compute gradients with +# respect to these Tensors during the backward pass. +a = torch.randn((), device=device, dtype=dtype, requires_grad=True) +b = torch.randn((), device=device, dtype=dtype, requires_grad=True) +c = torch.randn((), device=device, dtype=dtype, requires_grad=True) +d = torch.randn((), device=device, dtype=dtype, requires_grad=True) + +learning_rate = 1e-6 +for t in range(2000): + # Forward pass: compute predicted y using operations on Tensors. + y_pred = a + b * x + c * x ** 2 + d * x ** 3 + + # Compute and print loss using operations on Tensors. + # Now loss is a Tensor of shape (1,) + # loss.item() gets the scalar value held in the loss. + loss = (y_pred - y).pow(2).sum() + if t % 100 == 99: + print(t, loss.item()) + + # Use autograd to compute the backward pass. This call will compute the + # gradient of loss with respect to all Tensors with requires_grad=True. + # After this call a.grad, b.grad. c.grad and d.grad will be Tensors holding + # the gradient of the loss with respect to a, b, c, d respectively. + loss.backward() + + # Manually update weights using gradient descent. Wrap in torch.no_grad() + # because weights have requires_grad=True, but we don't need to track this + # in autograd. + with torch.no_grad(): + a -= learning_rate * a.grad + b -= learning_rate * b.grad + c -= learning_rate * c.grad + d -= learning_rate * d.grad + + # Manually zero the gradients after updating weights + a.grad = None + b.grad = None + c.grad = None + d.grad = None + +print(f'Result: y = {a.item()} + {b.item()} x + {c.item()} x^2 + {d.item()} x^3') + +``` + +**脚本的总运行时间**:(0 分钟 0.000 秒) + +[下载 Python 源码:`polynomial_autograd.py`](https://pytorch.org/tutorials/_downloads/2956e289de4f5fdd59114171805b23d2/polynomial_autograd.py) + +[下载 Jupyter 笔记本:`polynomial_autograd.ipynb`](https://pytorch.org/tutorials/_downloads/e1d4d0ca7bd75ea2fff8032fcb79076e/polynomial_autograd.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/11.md b/pytorch/官方教程/11.md new file mode 100644 index 00000000..a7cda6fa --- /dev/null +++ b/pytorch/官方教程/11.md @@ -0,0 +1,103 @@ +# PyTorch:定义新的 Autograd 函数 + +> 原文: + +经过训练的三阶多项式,可以通过最小化平方的欧几里得距离来预测`y = sin(x)`从`-pi`到`pi`。 而不是将多项式写为`y = a + bx + cx ^ 2 + dx ^ 3`,我们将多项式写为`y = a + b P[3](c + dx)`其中`P[3](x) = 1/2 (5x ^ 3 - 3x)`是三次的[勒让德多项式](https://en.wikipedia.org/wiki/Legendre_polynomials)。 + +此实现使用 PyTorch 张量上的运算来计算正向传播,并使用 PyTorch Autograd 来计算梯度。 + +在此实现中,我们实现了自己的自定义 Autograd 函数来执行`P'[3](x)`。 通过数学,`P'[3](x) = 3/2 (5x ^ 2 - 1)`: + +```py +import torch +import math + +class LegendrePolynomial3(torch.autograd.Function): + """ + We can implement our own custom autograd Functions by subclassing + torch.autograd.Function and implementing the forward and backward passes + which operate on Tensors. + """ + + @staticmethod + def forward(ctx, input): + """ + In the forward pass we receive a Tensor containing the input and return + a Tensor containing the output. ctx is a context object that can be used + to stash information for backward computation. You can cache arbitrary + objects for use in the backward pass using the ctx.save_for_backward method. + """ + ctx.save_for_backward(input) + return 0.5 * (5 * input ** 3 - 3 * input) + + @staticmethod + def backward(ctx, grad_output): + """ + In the backward pass we receive a Tensor containing the gradient of the loss + with respect to the output, and we need to compute the gradient of the loss + with respect to the input. + """ + input, = ctx.saved_tensors + return grad_output * 1.5 * (5 * input ** 2 - 1) + +dtype = torch.float +device = torch.device("cpu") +# device = torch.device("cuda:0") # Uncomment this to run on GPU + +# Create Tensors to hold input and outputs. +# By default, requires_grad=False, which indicates that we do not need to +# compute gradients with respect to these Tensors during the backward pass. +x = torch.linspace(-math.pi, math.pi, 2000, device=device, dtype=dtype) +y = torch.sin(x) + +# Create random Tensors for weights. For this example, we need +# 4 weights: y = a + b * P3(c + d * x), these weights need to be initialized +# not too far from the correct result to ensure convergence. +# Setting requires_grad=True indicates that we want to compute gradients with +# respect to these Tensors during the backward pass. +a = torch.full((), 0.0, device=device, dtype=dtype, requires_grad=True) +b = torch.full((), -1.0, device=device, dtype=dtype, requires_grad=True) +c = torch.full((), 0.0, device=device, dtype=dtype, requires_grad=True) +d = torch.full((), 0.3, device=device, dtype=dtype, requires_grad=True) + +learning_rate = 5e-6 +for t in range(2000): + # To apply our Function, we use Function.apply method. We alias this as 'P3'. + P3 = LegendrePolynomial3.apply + + # Forward pass: compute predicted y using operations; we compute + # P3 using our custom autograd operation. + y_pred = a + b * P3(c + d * x) + + # Compute and print loss + loss = (y_pred - y).pow(2).sum() + if t % 100 == 99: + print(t, loss.item()) + + # Use autograd to compute the backward pass. + loss.backward() + + # Update weights using gradient descent + with torch.no_grad(): + a -= learning_rate * a.grad + b -= learning_rate * b.grad + c -= learning_rate * c.grad + d -= learning_rate * d.grad + + # Manually zero the gradients after updating weights + a.grad = None + b.grad = None + c.grad = None + d.grad = None + +print(f'Result: y = {a.item()} + {b.item()} * P3({c.item()} + {d.item()} x)') + +``` + +**脚本的总运行时间**:(0 分钟 0.000 秒) + +[下载 Python 源码:`polynomial_custom_function.py`](https://pytorch.org/tutorials/_downloads/b7ec15fd7bec1ca3f921104cfb6a54ed/polynomial_custom_function.py) + +[下载 Jupyter 笔记本:`polynomial_custom_function.ipynb`](https://pytorch.org/tutorials/_downloads/0a64809624bf2f3eb497d30d5303a9a0/polynomial_custom_function.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/12.md b/pytorch/官方教程/12.md new file mode 100644 index 00000000..9dc0b70d --- /dev/null +++ b/pytorch/官方教程/12.md @@ -0,0 +1,87 @@ +# PyTorch:`nn` + +> 原文: + +经过训练的三阶多项式,可以通过最小化平方的欧几里得距离来预测`y = sin(x)`从`-pi`到`pi`。 + +此实现使用来自 PyTorch 的`nn`包来构建网络。 PyTorch Autograd 使定义计算图和获取梯度变得容易,但是原始的 Autograd 对于定义复杂的神经网络来说可能太低了。 这是`nn`包可以提供帮助的地方。 `nn`包定义了一组模块,您可以将其视为神经网络层,该神经网络层从输入产生输出并且可能具有一些可训练的权重。 + +```py +import torch +import math + +# Create Tensors to hold input and outputs. +x = torch.linspace(-math.pi, math.pi, 2000) +y = torch.sin(x) + +# For this example, the output y is a linear function of (x, x^2, x^3), so +# we can consider it as a linear layer neural network. Let's prepare the +# tensor (x, x^2, x^3). +p = torch.tensor([1, 2, 3]) +xx = x.unsqueeze(-1).pow(p) + +# In the above code, x.unsqueeze(-1) has shape (2000, 1), and p has shape +# (3,), for this case, broadcasting semantics will apply to obtain a tensor +# of shape (2000, 3) + +# Use the nn package to define our model as a sequence of layers. nn.Sequential +# is a Module which contains other Modules, and applies them in sequence to +# produce its output. The Linear Module computes output from input using a +# linear function, and holds internal Tensors for its weight and bias. +# The Flatten layer flatens the output of the linear layer to a 1D tensor, +# to match the shape of `y`. +model = torch.nn.Sequential( + torch.nn.Linear(3, 1), + torch.nn.Flatten(0, 1) +) + +# The nn package also contains definitions of popular loss functions; in this +# case we will use Mean Squared Error (MSE) as our loss function. +loss_fn = torch.nn.MSELoss(reduction='sum') + +learning_rate = 1e-6 +for t in range(2000): + + # Forward pass: compute predicted y by passing x to the model. Module objects + # override the __call__ operator so you can call them like functions. When + # doing so you pass a Tensor of input data to the Module and it produces + # a Tensor of output data. + y_pred = model(xx) + + # Compute and print loss. We pass Tensors containing the predicted and true + # values of y, and the loss function returns a Tensor containing the + # loss. + loss = loss_fn(y_pred, y) + if t % 100 == 99: + print(t, loss.item()) + + # Zero the gradients before running the backward pass. + model.zero_grad() + + # Backward pass: compute gradient of the loss with respect to all the learnable + # parameters of the model. Internally, the parameters of each Module are stored + # in Tensors with requires_grad=True, so this call will compute gradients for + # all learnable parameters in the model. + loss.backward() + + # Update the weights using gradient descent. Each parameter is a Tensor, so + # we can access its gradients like we did before. + with torch.no_grad(): + for param in model.parameters(): + param -= learning_rate * param.grad + +# You can access the first layer of `model` like accessing the first item of a list +linear_layer = model[0] + +# For linear layer, its parameters are stored as `weight` and `bias`. +print(f'Result: y = {linear_layer.bias.item()} + {linear_layer.weight[:, 0].item()} x + {linear_layer.weight[:, 1].item()} x^2 + {linear_layer.weight[:, 2].item()} x^3') + +``` + +**脚本的总运行时间**:(0 分钟 0.000 秒) + +[下载 Python 源码:`polynomial_nn.py`](https://pytorch.org/tutorials/_downloads/b4767df4367deade63dc8a0d3712c1d4/polynomial_nn.py) + +[下载 Jupyter 笔记本:`polynomial_nn.ipynb`](https://pytorch.org/tutorials/_downloads/7bc167d8b8308ae65a717d7461d838fa/polynomial_nn.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/13.md b/pytorch/官方教程/13.md new file mode 100644 index 00000000..ac2d8a92 --- /dev/null +++ b/pytorch/官方教程/13.md @@ -0,0 +1,71 @@ +# PyTorch:`optim` + +> 原文: + +经过训练的三阶多项式,可以通过最小化平方的欧几里得距离来预测`y = sin(x)`从`-pi`到`pi`。 + +此实现使用来自 PyTorch 的`nn`包来构建网络。 + +与其像以前那样手动更新模型的权重,不如使用`optim`包定义一个优化器,该优化器将为我们更新权重。 `optim`包定义了许多深度学习常用的优化算法,包括 SGD + 动量,RMSProp,Adam 等。 + +```py +import torch +import math + +# Create Tensors to hold input and outputs. +x = torch.linspace(-math.pi, math.pi, 2000) +y = torch.sin(x) + +# Prepare the input tensor (x, x^2, x^3). +p = torch.tensor([1, 2, 3]) +xx = x.unsqueeze(-1).pow(p) + +# Use the nn package to define our model and loss function. +model = torch.nn.Sequential( + torch.nn.Linear(3, 1), + torch.nn.Flatten(0, 1) +) +loss_fn = torch.nn.MSELoss(reduction='sum') + +# Use the optim package to define an Optimizer that will update the weights of +# the model for us. Here we will use RMSprop; the optim package contains many other +# optimization algorithms. The first argument to the RMSprop constructor tells the +# optimizer which Tensors it should update. +learning_rate = 1e-3 +optimizer = torch.optim.RMSprop(model.parameters(), lr=learning_rate) +for t in range(2000): + # Forward pass: compute predicted y by passing x to the model. + y_pred = model(xx) + + # Compute and print loss. + loss = loss_fn(y_pred, y) + if t % 100 == 99: + print(t, loss.item()) + + # Before the backward pass, use the optimizer object to zero all of the + # gradients for the variables it will update (which are the learnable + # weights of the model). This is because by default, gradients are + # accumulated in buffers( i.e, not overwritten) whenever .backward() + # is called. Checkout docs of torch.autograd.backward for more details. + optimizer.zero_grad() + + # Backward pass: compute gradient of the loss with respect to model + # parameters + loss.backward() + + # Calling the step function on an Optimizer makes an update to its + # parameters + optimizer.step() + +linear_layer = model[0] +print(f'Result: y = {linear_layer.bias.item()} + {linear_layer.weight[:, 0].item()} x + {linear_layer.weight[:, 1].item()} x^2 + {linear_layer.weight[:, 2].item()} x^3') + +``` + +**脚本的总运行时间**:(0 分钟 0.000 秒) + +[下载 Python 源码:`polynomial_optim.py`](https://pytorch.org/tutorials/_downloads/bcfec6f02e0fe747a42dbd1579267469/polynomial_optim.py) + +[下载 Jupyter 笔记本:`polynomial_optim.ipynb`](https://pytorch.org/tutorials/_downloads/8ef669b2c61c6c5aa47c54dceac4979e/polynomial_optim.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/14.md b/pytorch/官方教程/14.md new file mode 100644 index 00000000..619ffac4 --- /dev/null +++ b/pytorch/官方教程/14.md @@ -0,0 +1,75 @@ +# PyTorch:自定义`nn`模块 + +> 原文: + +经过训练的三阶多项式,可以通过最小化平方的欧几里得距离来预测`y = sin(x)`从`-pi`到`pi`。 + +此实现将模型定义为自定义`Module`子类。 每当您想要一个比现有模块的简单序列更复杂的模型时,都需要以这种方式定义模型。 + +```py +import torch +import math + +class Polynomial3(torch.nn.Module): + def __init__(self): + """ + In the constructor we instantiate four parameters and assign them as + member parameters. + """ + super().__init__() + self.a = torch.nn.Parameter(torch.randn(())) + self.b = torch.nn.Parameter(torch.randn(())) + self.c = torch.nn.Parameter(torch.randn(())) + self.d = torch.nn.Parameter(torch.randn(())) + + def forward(self, x): + """ + In the forward function we accept a Tensor of input data and we must return + a Tensor of output data. We can use Modules defined in the constructor as + well as arbitrary operators on Tensors. + """ + return self.a + self.b * x + self.c * x ** 2 + self.d * x ** 3 + + def string(self): + """ + Just like any class in Python, you can also define custom method on PyTorch modules + """ + return f'y = {self.a.item()} + {self.b.item()} x + {self.c.item()} x^2 + {self.d.item()} x^3' + +# Create Tensors to hold input and outputs. +x = torch.linspace(-math.pi, math.pi, 2000) +y = torch.sin(x) + +# Construct our model by instantiating the class defined above +model = Polynomial3() + +# Construct our loss function and an Optimizer. The call to model.parameters() +# in the SGD constructor will contain the learnable parameters of the nn.Linear +# module which is members of the model. +criterion = torch.nn.MSELoss(reduction='sum') +optimizer = torch.optim.SGD(model.parameters(), lr=1e-6) +for t in range(2000): + # Forward pass: Compute predicted y by passing x to the model + y_pred = model(x) + + # Compute and print loss + loss = criterion(y_pred, y) + if t % 100 == 99: + print(t, loss.item()) + + # Zero gradients, perform a backward pass, and update the weights. + optimizer.zero_grad() + loss.backward() + optimizer.step() + +print(f'Result: {model.string()}') + +``` + +**脚本的总运行时间**:(0 分钟 0.000 秒) + +[下载 Python 源码:`polynomial_module.py`](https://pytorch.org/tutorials/_downloads/916a9c460c899330dbc53216cc775358/polynomial_module.py) + +[下载 Jupyter 笔记本:`polynomial_module.ipynb`](https://pytorch.org/tutorials/_downloads/19f4ecdd2763dd4b90693df4d6e10ebe/polynomial_module.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/15.md b/pytorch/官方教程/15.md new file mode 100644 index 00000000..50fb29a1 --- /dev/null +++ b/pytorch/官方教程/15.md @@ -0,0 +1,82 @@ +# PyTorch:控制流 + 权重共享 + +> 原文: + +为了展示 PyTorch 动态图的强大功能,我们将实现一个非常奇怪的模型:一个三阶多项式,在每个正向传播中选择 3 到 5 之间的一个随机数,并使用该数量的阶次,多次使用相同的权重重复计算四和五阶。 + +```py +import random +import torch +import math + +class DynamicNet(torch.nn.Module): + def __init__(self): + """ + In the constructor we instantiate five parameters and assign them as members. + """ + super().__init__() + self.a = torch.nn.Parameter(torch.randn(())) + self.b = torch.nn.Parameter(torch.randn(())) + self.c = torch.nn.Parameter(torch.randn(())) + self.d = torch.nn.Parameter(torch.randn(())) + self.e = torch.nn.Parameter(torch.randn(())) + + def forward(self, x): + """ + For the forward pass of the model, we randomly choose either 4, 5 + and reuse the e parameter to compute the contribution of these orders. + + Since each forward pass builds a dynamic computation graph, we can use normal + Python control-flow operators like loops or conditional statements when + defining the forward pass of the model. + + Here we also see that it is perfectly safe to reuse the same parameter many + times when defining a computational graph. + """ + y = self.a + self.b * x + self.c * x ** 2 + self.d * x ** 3 + for exp in range(4, random.randint(4, 6)): + y = y + self.e * x ** exp + return y + + def string(self): + """ + Just like any class in Python, you can also define custom method on PyTorch modules + """ + return f'y = {self.a.item()} + {self.b.item()} x + {self.c.item()} x^2 + {self.d.item()} x^3 + {self.e.item()} x^4 ? + {self.e.item()} x^5 ?' + +# Create Tensors to hold input and outputs. +x = torch.linspace(-math.pi, math.pi, 2000) +y = torch.sin(x) + +# Construct our model by instantiating the class defined above +model = DynamicNet() + +# Construct our loss function and an Optimizer. Training this strange model with +# vanilla stochastic gradient descent is tough, so we use momentum +criterion = torch.nn.MSELoss(reduction='sum') +optimizer = torch.optim.SGD(model.parameters(), lr=1e-8, momentum=0.9) +for t in range(30000): + # Forward pass: Compute predicted y by passing x to the model + y_pred = model(x) + + # Compute and print loss + loss = criterion(y_pred, y) + if t % 2000 == 1999: + print(t, loss.item()) + + # Zero gradients, perform a backward pass, and update the weights. + optimizer.zero_grad() + loss.backward() + optimizer.step() + +print(f'Result: {model.string()}') + +``` + +**脚本的总运行时间**:(0 分钟 0.000 秒) + +[下载 Python 源码:`dynamic_net.py`](https://pytorch.org/tutorials/_downloads/3900c903cde097dc0088c3b06d588c0b/dynamic_net.py) + +[下载 Jupyter 笔记本:`dynamic_net.ipynb`](https://pytorch.org/tutorials/_downloads/ad230923bd9eb0d42576725b63ad8d91/dynamic_net.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/16.md b/pytorch/官方教程/16.md new file mode 100644 index 00000000..e6867d85 --- /dev/null +++ b/pytorch/官方教程/16.md @@ -0,0 +1,971 @@ +# `torch.nn`到底是什么? + +> 原文: + +作者:Jeremy Howard,[fast.ai](https://www.fast.ai)。 感谢 Rachel Thomas 和 Francisco Ingham。 + +我们建议将本教程作为笔记本而不是脚本来运行。 要下载笔记本(`.ipynb`)文件,请单击页面顶部的链接。 + +PyTorch 提供设计精美的模块和类[`torch.nn`](https://pytorch.org/docs/stable/nn.html),[`torch.optim`](https://pytorch.org/docs/stable/optim.html),[`Dataset`](https://pytorch.org/docs/stable/data.html?highlight=dataset#torch.utils.data.Dataset)和[`DataLoader`](https://pytorch.org/docs/stable/data.html?highlight=dataloader#torch.utils.data.DataLoader)神经网络。 为了充分利用它们的功能并针对您的问题对其进行自定义,您需要真正了解它们在做什么。 为了建立这种理解,我们将首先在 MNIST 数据集上训练基本神经网络,而无需使用这些模型的任何功能。 我们最初将仅使用最基本的 PyTorch 张量函数。 然后,我们将一次从`torch.nn`,`torch.optim`,`Dataset`或`DataLoader`中逐个添加一个函数,以准确显示每个函数,以及如何使代码更简洁或更有效。 灵活。 + +**本教程假定您已经安装了 PyTorch,并且熟悉张量操作的基础知识。** (如果您熟悉 Numpy 数组操作,将会发现此处使用的 PyTorch 张量操作几乎相同)。 + +## MNIST 数据集 + +我们将使用经典的 [MNIST](http://deeplearning.net/data/mnist/) 数据集,该数据集由手绘数字的黑白图像组成(0 到 9 之间)。 + +我们将使用[`pathlib`](https://docs.python.org/3/library/pathlib.html)处理路径(Python 3 标准库的一部分),并使用[`requests`](http://docs.python-requests.org/en/master/)下载数据集。 我们只会在使用模块时才导入它们,因此您可以确切地看到每个位置上正在使用的模块。 + +```py +from pathlib import Path +import requests + +DATA_PATH = Path("data") +PATH = DATA_PATH / "mnist" + +PATH.mkdir(parents=True, exist_ok=True) + +URL = "https://github.com/pytorch/tutorials/raw/master/_static/" +FILENAME = "mnist.pkl.gz" + +if not (PATH / FILENAME).exists(): + content = requests.get(URL + FILENAME).content + (PATH / FILENAME).open("wb").write(content) + +``` + +该数据集为 numpy 数组格式,并已使用`pickle`(一种用于序列化数据的 python 特定格式)存储。 + +```py +import pickle +import gzip + +with gzip.open((PATH / FILENAME).as_posix(), "rb") as f: + ((x_train, y_train), (x_valid, y_valid), _) = pickle.load(f, encoding="latin-1") + +``` + +每个图像为`28 x 28`,并存储为长度为`784 = 28x28`的扁平行。 让我们来看一个; 我们需要先将其重塑为 2d。 + +```py +from matplotlib import pyplot +import numpy as np + +pyplot.imshow(x_train[0].reshape((28, 28)), cmap="gray") +print(x_train.shape) + +``` + +![../_img/sphx_glr_nn_tutorial_001.png](img/7c783def0bbe536f41ed172041b7e89e.png) + +出: + +```py +(50000, 784) + +``` + +PyTorch 使用`torch.tensor`而不是 numpy 数组,因此我们需要转换数据。 + +```py +import torch + +x_train, y_train, x_valid, y_valid = map( + torch.tensor, (x_train, y_train, x_valid, y_valid) +) +n, c = x_train.shape +x_train, x_train.shape, y_train.min(), y_train.max() +print(x_train, y_train) +print(x_train.shape) +print(y_train.min(), y_train.max()) + +``` + +出: + +```py +tensor([[0., 0., 0., ..., 0., 0., 0.], + [0., 0., 0., ..., 0., 0., 0.], + [0., 0., 0., ..., 0., 0., 0.], + ..., + [0., 0., 0., ..., 0., 0., 0.], + [0., 0., 0., ..., 0., 0., 0.], + [0., 0., 0., ..., 0., 0., 0.]]) tensor([5, 0, 4, ..., 8, 4, 8]) +torch.Size([50000, 784]) +tensor(0) tensor(9) + +``` + +## 从零开始的神经网络(没有`torch.nn`) + +首先,我们仅使用 PyTorch 张量操作创建模型。 我们假设您已经熟悉神经网络的基础知识。 (如果不是,则可以在 [course.fast.ai](https://course.fast.ai) 中学习它们)。 + +PyTorch 提供了创建随机或零填充张量的方法,我们将使用它们来为简单的线性模型创建权重和偏差。 这些只是常规张量,还有一个非常特殊的附加值:我们告诉 PyTorch 它们需要梯度。 这使 PyTorch 记录了在张量上完成的所有操作,因此它可以在反向传播时*自动计算*的梯度! + +**对于权重,我们在初始化之后设置`requires_grad`,因为我们不希望该步骤包含在梯度中。 (请注意,PyTorch 中的尾随`_`表示该操作是原地执行的。)** + +注意 + +我们在这里用 [Xavier 初始化](http://proceedings.mlr.press/v9/glorot10a/glorot10a.pdf)(通过乘以`1 / sqrt(n)`)来初始化权重。 + +```py +import math + +weights = torch.randn(784, 10) / math.sqrt(784) +weights.requires_grad_() +bias = torch.zeros(10, requires_grad=True) + +``` + +由于 PyTorch 具有自动计算梯度的功能,我们可以将任何标准的 Python 函数(或可调用对象)用作模型! 因此,我们只需编写一个普通矩阵乘法和广播加法即可创建一个简单的线性模型。 我们还需要激活函数,因此我们将编写并使用`log_softmax`。 请记住:尽管 PyTorch 提供了许多预写的损失函数,激活函数等,但是您可以使用纯 Python 轻松编写自己的函数。 PyTorch 甚至会自动为您的函数创建快速 GPU 或向量化的 CPU 代码。 + +```py +def log_softmax(x): + return x - x.exp().sum(-1).log().unsqueeze(-1) + +def model(xb): + return log_softmax(xb @ weights + bias) + +``` + +在上面,`@`代表点积运算。 我们将对一批数据(在本例中为 64 张图像)调用函数。 这是一个*正向传播*。 请注意,由于我们从随机权重开始,因此在这一阶段,我们的预测不会比随机预测更好。 + +```py +bs = 64 # batch size + +xb = x_train[0:bs] # a mini-batch from x +preds = model(xb) # predictions +preds[0], preds.shape +print(preds[0], preds.shape) + +``` + +出: + +```py +tensor([-2.5964, -2.3153, -2.1321, -2.4480, -2.2930, -1.9507, -2.1289, -2.4175, + -2.5332, -2.3967], grad_fn=) torch.Size([64, 10]) + +``` + +如您所见,`preds`张量不仅包含张量值,还包含梯度函数。 稍后我们将使用它进行反向传播。 + +让我们实现负对数可能性作为损失函数(同样,我们只能使用标准 Python): + +```py +def nll(input, target): + return -input[range(target.shape[0]), target].mean() + +loss_func = nll + +``` + +让我们使用随机模型来检查损失,以便我们稍后查看反向传播后是否可以改善我们的损失。 + +```py +yb = y_train[0:bs] +print(loss_func(preds, yb)) + +``` + +出: + +```py +tensor(2.3735, grad_fn=) + +``` + +我们还实现一个函数来计算模型的准确率。 对于每个预测,如果具有最大值的索引与目标值匹配,则该预测是正确的。 + +```py +def accuracy(out, yb): + preds = torch.argmax(out, dim=1) + return (preds == yb).float().mean() + +``` + +让我们检查一下随机模型的准确率,以便我们可以看出随着损失的增加,准确率是否有所提高。 + +```py +print(accuracy(preds, yb)) + +``` + +出: + +```py +tensor(0.0938) + +``` + +现在,我们可以运行一个训练循环。 对于每次迭代,我们将: + +* 选择一个小批量数据(大小为`bs`) +* 使用模型进行预测 +* 计算损失 +* `loss.backward()`更新模型的梯度,在这种情况下为`weights`和`bias`。 + +现在,我们使用这些梯度来更新权重和偏差。 我们在`torch.no_grad()`上下文管理器中执行此操作,因为我们不希望在下一步的梯度计算中记录这些操作。 [您可以在这里阅读有关 PyTorch 的 Autograd 如何记录操作的更多信息](https://pytorch.org/docs/stable/notes/autograd.html)。 + +然后,将梯度设置为零,以便为下一个循环做好准备。 否则,我们的梯度会记录所有已发生操作的运行记录(即`loss.backward()`将梯度添加到已存储的内容中,而不是替换它们)。 + +小费 + +您可以使用标准的 python 调试器逐步浏览 PyTorch 代码,从而可以在每一步检查各种变量值。 取消注释以下`set_trace()`即可尝试。 + +```py +from IPython.core.debugger import set_trace + +lr = 0.5 # learning rate +epochs = 2 # how many epochs to train for + +for epoch in range(epochs): + for i in range((n - 1) // bs + 1): + # set_trace() + start_i = i * bs + end_i = start_i + bs + xb = x_train[start_i:end_i] + yb = y_train[start_i:end_i] + pred = model(xb) + loss = loss_func(pred, yb) + + loss.backward() + with torch.no_grad(): + weights -= weights.grad * lr + bias -= bias.grad * lr + weights.grad.zero_() + bias.grad.zero_() + +``` + +就是这样:我们完全从头开始创建并训练了一个最小的神经网络(在这种情况下,是逻辑回归,因为我们没有隐藏的层)! + +让我们检查损失和准确率,并将其与我们之前获得的进行比较。 我们希望损失会减少,准确率会增加,而且确实如此。 + +```py +print(loss_func(model(xb), yb), accuracy(model(xb), yb)) + +``` + +出: + +```py +tensor(0.0811, grad_fn=) tensor(1.) + +``` + +## 使用`torch.nn.functional` + +现在,我们将重构代码,使其执行与以前相同的操作,只是我们将开始利用 PyTorch 的`nn`类使其更加简洁和灵活。 从这里开始的每一步,我们都应该使代码中的一个或多个:更短,更易理解和/或更灵活。 + +第一步也是最简单的步骤,就是用`torch.nn.functional`(通常按照惯例将其导入到名称空间`F`中)替换我们的手写激活和损失函数,从而缩短代码长度。 该模块包含`torch.nn`库中的所有函数(而该库的其他部分包含类)。 除了广泛的损失和激活函数外,您还会在这里找到一些方便的函数来创建神经网络,例如合并函数。 (还有一些用于进行卷积,线性层等的函数,但是正如我们将看到的那样,通常可以使用库的其他部分来更好地处理这些函数。) + +如果您使用的是负对数似然损失和对数 softmax 激活,那么 Pytorch 会提供结合了两者的单一函数`F.cross_entropy`。 因此,我们甚至可以从模型中删除激活函数。 + +```py +import torch.nn.functional as F + +loss_func = F.cross_entropy + +def model(xb): + return xb @ weights + bias + +``` + +请注意,我们不再在`model`函数中调用`log_softmax`。 让我们确认我们的损失和准确率与以前相同: + +```py +print(loss_func(model(xb), yb), accuracy(model(xb), yb)) + +``` + +出: + +```py +tensor(0.0811, grad_fn=) tensor(1.) + +``` + +## 使用`nn.Module`重构 + +接下来,我们将使用`nn.Module`和`nn.Parameter`进行更清晰,更简洁的训练循环。 我们将`nn.Module`子类化(它本身是一个类并且能够跟踪状态)。 在这种情况下,我们要创建一个类,该类包含前进步骤的权重,偏置和方法。 `nn.Module`具有许多我们将要使用的属性和方法(例如`.parameters()`和`.zero_grad()`)。 + +注意 + +`nn.Module`(大写`M`)是 PyTorch 的特定概念,并且是我们将经常使用的一类。 不要将`nn.Module`与[模块](https://docs.python.org/3/tutorial/modules.html)(小写`m`)的 Python 概念混淆,该模块是可以导入的 Python 代码文件。 + +```py +from torch import nn + +class Mnist_Logistic(nn.Module): + def __init__(self): + super().__init__() + self.weights = nn.Parameter(torch.randn(784, 10) / math.sqrt(784)) + self.bias = nn.Parameter(torch.zeros(10)) + + def forward(self, xb): + return xb @ self.weights + self.bias + +``` + +由于我们现在使用的是对象而不是仅使用函数,因此我们首先必须实例化模型: + +```py +model = Mnist_Logistic() + +``` + +现在我们可以像以前一样计算损失。 请注意,`nn.Module`对象的使用就好像它们是函数一样(即,它们是*可调用的*),但是在后台 Pytorch 会自动调用我们的`forward`方法。 + +```py +print(loss_func(model(xb), yb)) + +``` + +出: + +```py +tensor(2.3903, grad_fn=) + +``` + +以前,在我们的训练循环中,我们必须按名称更新每个参数的值,并手动将每个参数的梯度分别归零,如下所示: + +```py +with torch.no_grad(): + weights -= weights.grad * lr + bias -= bias.grad * lr + weights.grad.zero_() + bias.grad.zero_() + +``` + +现在我们可以利用`model.parameters()`和`model.zero_grad()`(它们都由 PyTorch 为`nn.Module`定义)来使这些步骤更简洁,并且更不会出现忘记某些参数的错误,尤其是当我们有一个更复杂的模型的时候: + +```py +with torch.no_grad(): + for p in model.parameters(): p -= p.grad * lr + model.zero_grad() + +``` + +我们将把小的训练循环包装在`fit`函数中,以便稍后再运行。 + +```py +def fit(): + for epoch in range(epochs): + for i in range((n - 1) // bs + 1): + start_i = i * bs + end_i = start_i + bs + xb = x_train[start_i:end_i] + yb = y_train[start_i:end_i] + pred = model(xb) + loss = loss_func(pred, yb) + + loss.backward() + with torch.no_grad(): + for p in model.parameters(): + p -= p.grad * lr + model.zero_grad() + +fit() + +``` + +让我们仔细检查一下我们的损失是否减少了: + +```py +print(loss_func(model(xb), yb)) + +``` + +出: + +```py +tensor(0.0808, grad_fn=) + +``` + +## 使用`nn.Linear`重构 + +我们继续重构我们的代码。 代替手动定义和初始化`self.weights`和`self.bias`并计算`xb  @ self.weights + self.bias`,我们将对线性层使用 Pytorch 类[`nn.Linear`](https://pytorch.org/docs/stable/nn.html#linear-layers),这将为我们完成所有工作。 Pytorch 具有许多类型的预定义层,可以大大简化我们的代码,并且通常也可以使其速度更快。 + +```py +class Mnist_Logistic(nn.Module): + def __init__(self): + super().__init__() + self.lin = nn.Linear(784, 10) + + def forward(self, xb): + return self.lin(xb) + +``` + +我们以与以前相同的方式实例化模型并计算损失: + +```py +model = Mnist_Logistic() +print(loss_func(model(xb), yb)) + +``` + +出: + +```py +tensor(2.4215, grad_fn=) + +``` + +我们仍然可以使用与以前相同的`fit`方法。 + +```py +fit() + +print(loss_func(model(xb), yb)) + +``` + +出: + +```py +tensor(0.0824, grad_fn=) + +``` + +## 使用`optim`重构 + +Pytorch 还提供了一个包含各种优化算法的包`torch.optim`。 我们可以使用优化器中的`step`方法采取向前的步骤,而不是手动更新每个参数。 + +这将使我们替换之前的手动编码优化步骤: + +```py +with torch.no_grad(): + for p in model.parameters(): p -= p.grad * lr + model.zero_grad() + +``` + +而是只使用: + +```py +opt.step() +opt.zero_grad() + +``` + +(`optim.zero_grad()`将梯度重置为 0,我们需要在计算下一个小批量的梯度之前调用它。) + +```py +from torch import optim + +``` + +我们将定义一个小函数来创建模型和优化器,以便将来重用。 + +```py +def get_model(): + model = Mnist_Logistic() + return model, optim.SGD(model.parameters(), lr=lr) + +model, opt = get_model() +print(loss_func(model(xb), yb)) + +for epoch in range(epochs): + for i in range((n - 1) // bs + 1): + start_i = i * bs + end_i = start_i + bs + xb = x_train[start_i:end_i] + yb = y_train[start_i:end_i] + pred = model(xb) + loss = loss_func(pred, yb) + + loss.backward() + opt.step() + opt.zero_grad() + +print(loss_func(model(xb), yb)) + +``` + +出: + +```py +tensor(2.2999, grad_fn=) +tensor(0.0823, grad_fn=) + +``` + +## 使用`Dataset`重构 + +PyTorch 有一个抽象的`Dataset`类。 数据集可以是具有`__len__`函数(由 Python 的标准`len`函数调用)和具有`__getitem__`函数作为对其进行索引的一种方法。 [本教程](https://pytorch.org/tutorials/beginner/data_loading_tutorial.html)演示了一个不错的示例,该示例创建一个自定义`FacialLandmarkDataset`类作为`Dataset`的子类。 + +PyTorch 的[`TensorDataset`](https://pytorch.org/docs/stable/_modules/torch/utils/data/dataset.html#TensorDataset)是一个数据集包装张量。 通过定义索引的长度和方式,这也为我们提供了沿张量的第一维进行迭代,索引和切片的方法。 这将使我们在训练的同一行中更容易访问自变量和因变量。 + +```py +from torch.utils.data import TensorDataset + +``` + +`x_train`和`y_train`都可以合并为一个`TensorDataset`,这将更易于迭代和切片。 + +```py +train_ds = TensorDataset(x_train, y_train) + +``` + +以前,我们不得不分别遍历`x`和`y`值的小批量: + +```py +xb = x_train[start_i:end_i] +yb = y_train[start_i:end_i] + +``` + +现在,我们可以一起执行以下两个步骤: + +```py +xb,yb = train_ds[i*bs : i*bs+bs] + +``` + +```py +model, opt = get_model() + +for epoch in range(epochs): + for i in range((n - 1) // bs + 1): + xb, yb = train_ds[i * bs: i * bs + bs] + pred = model(xb) + loss = loss_func(pred, yb) + + loss.backward() + opt.step() + opt.zero_grad() + +print(loss_func(model(xb), yb)) + +``` + +出: + +```py +tensor(0.0819, grad_fn=) + +``` + +## 使用`DataLoader`重构 + +Pytorch 的`DataLoader`负责批量管理。 您可以从任何`Dataset`创建一个`DataLoader`。 `DataLoader`使迭代迭代变得更加容易。 不必使用`train_ds[i*bs : i*bs+bs]`,`DataLoader`会自动为我们提供每个小批量。 + +```py +from torch.utils.data import DataLoader + +train_ds = TensorDataset(x_train, y_train) +train_dl = DataLoader(train_ds, batch_size=bs) + +``` + +以前,我们的循环遍历如下批量`(xb, yb)`: + +```py +for i in range((n-1)//bs + 1): + xb,yb = train_ds[i*bs : i*bs+bs] + pred = model(xb) + +``` + +现在,我们的循环更加简洁了,因为`(xb, yb)`是从数据加载器自动加载的: + +```py +for xb,yb in train_dl: + pred = model(xb) + +``` + +```py +model, opt = get_model() + +for epoch in range(epochs): + for xb, yb in train_dl: + pred = model(xb) + loss = loss_func(pred, yb) + + loss.backward() + opt.step() + opt.zero_grad() + +print(loss_func(model(xb), yb)) + +``` + +出: + +```py +tensor(0.0821, grad_fn=) + +``` + +得益于 Pytorch 的`nn.Module`,`nn.Parameter`,`Dataset`和`DataLoader`,我们的训练循环现在变得更小,更容易理解。 现在,让我们尝试添加在实践中创建有效模型所需的基本功能。 + +## 添加验证 + +在第 1 节中,我们只是试图建立一个合理的训练循环以用于我们的训练数据。 实际上,您也应该**始终**具有[验证集](https://www.fast.ai/2017/11/13/validation-sets/),以便识别您是否过拟合。 + +[对训练数据进行打乱](https://www.quora.com/Does-the-order-of-training-data-matter-when-training-neural-networks)对于防止批量与过拟合之间的相关性很重要。 另一方面,无论我们是否打乱验证集,验证损失都是相同的。 由于打乱需要花费更多时间,因此打乱验证数据没有任何意义。 + +我们将验证集的批量大小设为训练集的两倍。 这是因为验证集不需要反向传播,因此占用的内存更少(不需要存储梯度)。 我们利用这一优势来使用更大的批量,并更快地计算损失。 + +```py +train_ds = TensorDataset(x_train, y_train) +train_dl = DataLoader(train_ds, batch_size=bs, shuffle=True) + +valid_ds = TensorDataset(x_valid, y_valid) +valid_dl = DataLoader(valid_ds, batch_size=bs * 2) + +``` + +我们将在每个周期结束时计算并打印验证损失。 + +(请注意,我们总是在训练之前调用`model.train()`,并在推理之前调用`model.eval()`,因为诸如`nn.BatchNorm2d`和`nn.Dropout`之类的层会使用它们,以确保这些不同阶段的行为正确。) + +```py +model, opt = get_model() + +for epoch in range(epochs): + model.train() + for xb, yb in train_dl: + pred = model(xb) + loss = loss_func(pred, yb) + + loss.backward() + opt.step() + opt.zero_grad() + + model.eval() + with torch.no_grad(): + valid_loss = sum(loss_func(model(xb), yb) for xb, yb in valid_dl) + + print(epoch, valid_loss / len(valid_dl)) + +``` + +出: + +```py +0 tensor(0.3743) +1 tensor(0.3316) + +``` + +## 创建`fit()`和`get_data()` + +现在,我们将自己进行一些重构。 由于我们经历了两次相似的过程来计算训练集和验证集的损失,因此我们将其设为自己的函数`loss_batch`,该函数可计算一批损失。 + +我们将优化器传入训练集中,然后使用它执行反向传播。 对于验证集,我们没有通过优化程序,因此该方法不会执行反向传播。 + +```py +def loss_batch(model, loss_func, xb, yb, opt=None): + loss = loss_func(model(xb), yb) + + if opt is not None: + loss.backward() + opt.step() + opt.zero_grad() + + return loss.item(), len(xb) + +``` + +`fit`运行必要的操作来训练我们的模型,并计算每个周期的训练和验证损失。 + +```py +import numpy as np + +def fit(epochs, model, loss_func, opt, train_dl, valid_dl): + for epoch in range(epochs): + model.train() + for xb, yb in train_dl: + loss_batch(model, loss_func, xb, yb, opt) + + model.eval() + with torch.no_grad(): + losses, nums = zip( + *[loss_batch(model, loss_func, xb, yb) for xb, yb in valid_dl] + ) + val_loss = np.sum(np.multiply(losses, nums)) / np.sum(nums) + + print(epoch, val_loss) + +``` + +`get_data`返回训练和验证集的数据加载器。 + +```py +def get_data(train_ds, valid_ds, bs): + return ( + DataLoader(train_ds, batch_size=bs, shuffle=True), + DataLoader(valid_ds, batch_size=bs * 2), + ) + +``` + +现在,我们获取数据加载器和拟合模型的整个过程可以在 3 行代码中运行: + +```py +train_dl, valid_dl = get_data(train_ds, valid_ds, bs) +model, opt = get_model() +fit(epochs, model, loss_func, opt, train_dl, valid_dl) + +``` + +出: + +```py +0 0.3120644524335861 +1 0.28915613491535186 + +``` + +您可以使用这些基本的 3 行代码来训练各种各样的模型。 让我们看看是否可以使用它们来训练卷积神经网络(CNN)! + +## 切换到 CNN + +现在,我们将构建具有三个卷积层的神经网络。 由于上一节中的任何功能都不假设任何有关模型形式的信息,因此我们将能够使用它们来训练 CNN,而无需进行任何修改。 + +我们将使用 Pytorch 的预定义[`Conv2d`](https://pytorch.org/docs/stable/nn.html#torch.nn.Conv2d)类作为我们的卷积层。 我们定义了具有 3 个卷积层的 CNN。 每个卷积后跟一个 ReLU。 最后,我们执行平均池化。 (请注意,`view`是 numpy 的`reshape`的 PyTorch 版本) + +```py +class Mnist_CNN(nn.Module): + def __init__(self): + super().__init__() + self.conv1 = nn.Conv2d(1, 16, kernel_size=3, stride=2, padding=1) + self.conv2 = nn.Conv2d(16, 16, kernel_size=3, stride=2, padding=1) + self.conv3 = nn.Conv2d(16, 10, kernel_size=3, stride=2, padding=1) + + def forward(self, xb): + xb = xb.view(-1, 1, 28, 28) + xb = F.relu(self.conv1(xb)) + xb = F.relu(self.conv2(xb)) + xb = F.relu(self.conv3(xb)) + xb = F.avg_pool2d(xb, 4) + return xb.view(-1, xb.size(1)) + +lr = 0.1 + +``` + +[动量](https://cs231n.github.io/neural-networks-3/#sgd)是随机梯度下降的一种变体,它也考虑了以前的更新,通常可以加快训练速度。 + +```py +model = Mnist_CNN() +opt = optim.SGD(model.parameters(), lr=lr, momentum=0.9) + +fit(epochs, model, loss_func, opt, train_dl, valid_dl) + +``` + +出: + +```py +0 0.32337012240886687 +1 0.25021172934770586 + +``` + +## `nn.Sequential` + +`torch.nn`还有另一个方便的类,可以用来简化我们的代码:[`Sequential`](https://pytorch.org/docs/stable/nn.html#torch.nn.Sequential)。 `Sequential`对象以顺序方式运行其中包含的每个模块。 这是编写神经网络的一种简单方法。 + +为了利用这一点,我们需要能够从给定的函数轻松定义**自定义层**。 例如,PyTorch 没有视层,我们需要为我们的网络创建一个层。 `Lambda`将创建一个层,然后在使用`Sequential`定义网络时可以使用该层。 + +```py +class Lambda(nn.Module): + def __init__(self, func): + super().__init__() + self.func = func + + def forward(self, x): + return self.func(x) + +def preprocess(x): + return x.view(-1, 1, 28, 28) + +``` + +用`Sequential`创建的模型很简单: + +```py +model = nn.Sequential( + Lambda(preprocess), + nn.Conv2d(1, 16, kernel_size=3, stride=2, padding=1), + nn.ReLU(), + nn.Conv2d(16, 16, kernel_size=3, stride=2, padding=1), + nn.ReLU(), + nn.Conv2d(16, 10, kernel_size=3, stride=2, padding=1), + nn.ReLU(), + nn.AvgPool2d(4), + Lambda(lambda x: x.view(x.size(0), -1)), +) + +opt = optim.SGD(model.parameters(), lr=lr, momentum=0.9) + +fit(epochs, model, loss_func, opt, train_dl, valid_dl) + +``` + +出: + +```py +0 0.30119081069231035 +1 0.25335356528759 + +``` + +## 包装`DataLoader` + +Our CNN is fairly concise, but it only works with MNIST, because: + +* 假设输入为`28 * 28`长向量 +* 假设 CNN 的最终网格尺寸为`4 * 4`(因为这是平均值 + +我们使用的合并核大小) + +让我们摆脱这两个假设,因此我们的模型适用于任何 2d 单通道图像。 首先,我们可以删除初始的 Lambda 层,但将数据预处理移至生成器中: + +```py +def preprocess(x, y): + return x.view(-1, 1, 28, 28), y + +class WrappedDataLoader: + def __init__(self, dl, func): + self.dl = dl + self.func = func + + def __len__(self): + return len(self.dl) + + def __iter__(self): + batches = iter(self.dl) + for b in batches: + yield (self.func(*b)) + +train_dl, valid_dl = get_data(train_ds, valid_ds, bs) +train_dl = WrappedDataLoader(train_dl, preprocess) +valid_dl = WrappedDataLoader(valid_dl, preprocess) + +``` + +接下来,我们可以将`nn.AvgPool2d`替换为`nn.AdaptiveAvgPool2d`,这使我们能够定义所需的*输出*张量的大小,而不是所需的*输入*张量的大小。 结果,我们的模型将适用于任何大小的输入。 + +```py +model = nn.Sequential( + nn.Conv2d(1, 16, kernel_size=3, stride=2, padding=1), + nn.ReLU(), + nn.Conv2d(16, 16, kernel_size=3, stride=2, padding=1), + nn.ReLU(), + nn.Conv2d(16, 10, kernel_size=3, stride=2, padding=1), + nn.ReLU(), + nn.AdaptiveAvgPool2d(1), + Lambda(lambda x: x.view(x.size(0), -1)), +) + +opt = optim.SGD(model.parameters(), lr=lr, momentum=0.9) + +``` + +试试看: + +```py +fit(epochs, model, loss_func, opt, train_dl, valid_dl) + +``` + +出: + +```py +0 0.327303307390213 +1 0.2181092014491558 + +``` + +## 使用您的 GPU + +如果您足够幸运地能够使用具有 CUDA 功能的 GPU(可以从大多数云提供商处以每小时 0.50 美元的价格租用一个),则可以使用它来加速代码。 首先检查您的 GPU 是否在 Pytorch 中正常工作: + +```py +print(torch.cuda.is_available()) + +``` + +出: + +```py +True + +``` + +然后为其创建一个设备对象: + +```py +dev = torch.device( + "cuda") if torch.cuda.is_available() else torch.device("cpu") + +``` + +让我们更新`preprocess`,将批量移至 GPU: + +```py +def preprocess(x, y): + return x.view(-1, 1, 28, 28).to(dev), y.to(dev) + +train_dl, valid_dl = get_data(train_ds, valid_ds, bs) +train_dl = WrappedDataLoader(train_dl, preprocess) +valid_dl = WrappedDataLoader(valid_dl, preprocess) + +``` + +最后,我们可以将模型移至 GPU。 + +```py +model.to(dev) +opt = optim.SGD(model.parameters(), lr=lr, momentum=0.9) + +``` + +您应该发现它现在运行得更快: + +```py +fit(epochs, model, loss_func, opt, train_dl, valid_dl) + +``` + +出: + +```py +0 0.1833980613708496 +1 0.17365939717292786 + +``` + +## 总结 + +现在,我们有了一个通用的数据管道和训练循环,您可以将其用于使用 Pytorch 训练许多类型的模型。 要了解现在可以轻松进行模型训练,请查看`mnist_sample`示例笔记本。 + +当然,您需要添加很多内容,例如数据扩充,超参数调整,监控训练,迁移学习等。 这些功能可在 fastai 库中使用,该库是使用本教程中所示的相同设计方法开发的,为希望进一步推广其模型的从业人员提供了自然的下一步。 + +我们承诺在本教程开始时将通过示例分别说明`torch.nn`,`torch.optim`,`Dataset`和`DataLoader`。 因此,让我们总结一下我们所看到的: + +> * `torch.nn` +> * `Module`:创建一个行为类似于函数的可调用对象,但也可以包含状态(例如神经网络层权重)。 它知道其中包含的 `Parameter` ,并且可以将其所有坡度归零,遍历它们以进行权重更新等。 +> * `Parameter`:张量的包装器,用于告知 `Module` 具有在反向传播期间需要更新的权重。 仅更新具有`require_grad`属性集的张量 +> * `functional`:一个模块(通常按照惯例导入到 `F` 名称空间中),其中包含激活函数,损失函数等。 以及卷积和线性层等层的无状态版本。 +> * `torch.optim`:包含诸如 `SGD` 的优化程序,这些优化程序在后退步骤 +> * `Dataset` 中更新 `Parameter` 的权重。 具有 `__len__` 和 `__getitem__` 的对象,包括 Pytorch 提供的类,例如 `TensorDataset` +> * `DataLoader`:获取任何 `Dataset` 并创建一个迭代器,该迭代器返回批量数据。 + +**脚本的总运行时间**:(0 分钟 57.062 秒) + +[下载 Python 源码:`nn_tutorial.py`](../_downloads/a6246751179fbfb7cad9222ef1c16617/nn_tutorial.py) + +[下载 Jupyter 笔记本:`nn_tutorial.ipynb`](../_downloads/5ddab57bb7482fbcc76722617dd47324/nn_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/17.md b/pytorch/官方教程/17.md new file mode 100644 index 00000000..12d5eeb4 --- /dev/null +++ b/pytorch/官方教程/17.md @@ -0,0 +1,348 @@ +# 使用 TensorBoard 可视化模型,数据和训练 + +> 原文: + +在 [60 分钟突击](https://pytorch.org/tutorials/beginner/deep_learning_60min_blitz.html)中,我们向您展示了如何加载数据,如何通过定义为`nn.Module`子类的模型提供数据,如何在训练数据上训练该模型以及在测试数据上对其进行测试。 为了了解发生的情况,我们在模型训练期间打印一些统计数据,以了解训练是否在进行中。 但是,我们可以做得更好:PyTorch 与 TensorBoard 集成在一起,TensorBoard 是一种工具,用于可视化神经网络训练运行的结果。 本教程使用 [Fashion-MNIST 数据集](https://github.com/zalandoresearch/fashion-mnist)说明了其某些功能,可以使用`torchvision.datasets`将其读入 PyTorch。 + +在本教程中,我们将学习如何: + +> 1. 读取数据并进行适当的转换(与先前的教程几乎相同)。 +> 2. 设置 TensorBoard。 +> 3. 写入 TensorBoard。 +> 4. 使用 TensorBoard 检查模型架构。 +> 5. 使用 TensorBoard 来创建我们在上一个教程中创建的可视化的交互式版本,并使用较少的代码 + +具体来说,在第 5 点,我们将看到: + +> * 有两种方法可以检查我们的训练数据 +> * 在训练模型时如何跟踪其表现 +> * 在训练后如何评估模型的表现。 + +我们将从 [CIFAR-10 教程](https://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html)中类似的样板代码开始: + +```py +# imports +import matplotlib.pyplot as plt +import numpy as np + +import torch +import torchvision +import torchvision.transforms as transforms + +import torch.nn as nn +import torch.nn.functional as F +import torch.optim as optim + +# transforms +transform = transforms.Compose( + [transforms.ToTensor(), + transforms.Normalize((0.5,), (0.5,))]) + +# datasets +trainset = torchvision.datasets.FashionMNIST('./data', + download=True, + train=True, + transform=transform) +testset = torchvision.datasets.FashionMNIST('./data', + download=True, + train=False, + transform=transform) + +# dataloaders +trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, + shuffle=True, num_workers=2) + +testloader = torch.utils.data.DataLoader(testset, batch_size=4, + shuffle=False, num_workers=2) + +# constant for classes +classes = ('T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', + 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle Boot') + +# helper function to show an image +# (used in the `plot_classes_preds` function below) +def matplotlib_imshow(img, one_channel=False): + if one_channel: + img = img.mean(dim=0) + img = img / 2 + 0.5 # unnormalize + npimg = img.numpy() + if one_channel: + plt.imshow(npimg, cmap="Greys") + else: + plt.imshow(np.transpose(npimg, (1, 2, 0))) + +``` + +我们将在该教程中定义一个类似的模型架构,仅需进行少量修改即可解决以下事实:图像现在是一个通道而不是三个通道,而图像是`28x28`而不是`32x32`: + +```py +class Net(nn.Module): + def __init__(self): + super(Net, self).__init__() + self.conv1 = nn.Conv2d(1, 6, 5) + self.pool = nn.MaxPool2d(2, 2) + self.conv2 = nn.Conv2d(6, 16, 5) + self.fc1 = nn.Linear(16 * 4 * 4, 120) + self.fc2 = nn.Linear(120, 84) + self.fc3 = nn.Linear(84, 10) + + def forward(self, x): + x = self.pool(F.relu(self.conv1(x))) + x = self.pool(F.relu(self.conv2(x))) + x = x.view(-1, 16 * 4 * 4) + x = F.relu(self.fc1(x)) + x = F.relu(self.fc2(x)) + x = self.fc3(x) + return x + +net = Net() + +``` + +我们将在之前定义相同的`optimizer`和`criterion`: + +```py +criterion = nn.CrossEntropyLoss() +optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) + +``` + +## 1\. TensorBoard 设置 + +现在,我们将设置 TensorBoard,从`torch.utils`导入`tensorboard`并定义`SummaryWriter`,这是将信息写入 TensorBoard 的关键对象。 + +```py +from torch.utils.tensorboard import SummaryWriter + +# default `log_dir` is "runs" - we'll be more specific here +writer = SummaryWriter('runs/fashion_mnist_experiment_1') + +``` + +请注意,仅此行会创建一个`runs/fashion_mnist_experiment_1`文件夹。 + +## 2\. 写入 TensorBoard + +现在,使用[`make_grid`](https://pytorch.org/docs/stable/torchvision/utils.html#torchvision.utils.make_grid)将图像写入到 TensorBoard 中,具体来说就是网格。 + +```py +# get some random training images +dataiter = iter(trainloader) +images, labels = dataiter.next() + +# create grid of images +img_grid = torchvision.utils.make_grid(images) + +# show images +matplotlib_imshow(img_grid, one_channel=True) + +# write to tensorboard +writer.add_image('four_fashion_mnist_images', img_grid) + +``` + +正在运行 + +```py +tensorboard --logdir=runs + +``` + +从命令行,然后导航到`https://localhost:6006`应该显示以下内容。 + +![intermediate/../../_static/img/tensorboard_first_view.png](img/8b09d6361316e495383ceedf9b8407ea.png) + +现在您知道如何使用 TensorBoard 了! 但是,此示例可以在 Jupyter 笔记本中完成-TensorBoard 真正擅长的地方是创建交互式可视化。 接下来,我们将介绍其中之一,并在本教程结束时介绍更多内容。 + +## 3\. 使用 TensorBoard 检查模型 + +TensorBoard 的优势之一是其可视化复杂模型结构的能力。 让我们可视化我们构建的模型。 + +```py +writer.add_graph(net, images) +writer.close() + +``` + +现在刷新 TensorBoard 后,您应该会看到一个`Graphs`标签,如下所示: + +![intermediate/../../_static/img/tensorboard_model_viz.png](img/8f596b99dbb3c262b61db267d5db2d63.png) + +继续并双击`Net`以展开它,查看构成模型的各个操作的详细视图。 + +TensorBoard 具有非常方便的功能,可在低维空间中可视化高维数据,例如图像数据。 接下来我们将介绍这一点。 + +## 4\. 在 TensorBoard 中添加“投影仪” + +我们可以通过[`add_embedding`](https://pytorch.org/docs/stable/tensorboard.html#torch.utils.tensorboard.writer.SummaryWriter.add_embedding)方法可视化高维数据的低维表示 + +```py +# helper function +def select_n_random(data, labels, n=100): + ''' + Selects n random datapoints and their corresponding labels from a dataset + ''' + assert len(data) == len(labels) + + perm = torch.randperm(len(data)) + return data[perm][:n], labels[perm][:n] + +# select random images and their target indices +images, labels = select_n_random(trainset.data, trainset.targets) + +# get the class labels for each image +class_labels = [classes[lab] for lab in labels] + +# log embeddings +features = images.view(-1, 28 * 28) +writer.add_embedding(features, + metadata=class_labels, + label_img=images.unsqueeze(1)) +writer.close() + +``` + +现在,在 TensorBoard 的“投影仪”选项卡中,您可以看到这 100 张图像-每个图像 784 维-向下投影到三维空间中。 此外,这是交互式的:您可以单击并拖动以旋转三维投影。 最后,一些技巧可以使可视化效果更容易看到:选择左上方的“颜色:标签”,以及启用“夜间模式”,这将使图像更容易看到,因为它们的背景是白色的: + +![intermediate/../../_static/img/tensorboard_projector.png](img/f4990a0920dff7e4647a23cfc1639a8a.png) + +现在我们已经彻底检查了我们的数据,让我们展示了 TensorBoard 如何从训练开始就可以使跟踪模型的训练和评估更加清晰。 + +## 5\. 使用 TensorBoard 跟踪模型训练 + +在前面的示例中,我们仅*每 2000 次迭代*打印该模型的运行损失。 现在,我们将运行损失记录到 TensorBoard 中,并通过`plot_classes_preds`函数查看模型所做的预测。 + +```py +# helper functions + +def images_to_probs(net, images): + ''' + Generates predictions and corresponding probabilities from a trained + network and a list of images + ''' + output = net(images) + # convert output probabilities to predicted class + _, preds_tensor = torch.max(output, 1) + preds = np.squeeze(preds_tensor.numpy()) + return preds, [F.softmax(el, dim=0)[i].item() for i, el in zip(preds, output)] + +def plot_classes_preds(net, images, labels): + ''' + Generates matplotlib Figure using a trained network, along with images + and labels from a batch, that shows the network's top prediction along + with its probability, alongside the actual label, coloring this + information based on whether the prediction was correct or not. + Uses the "images_to_probs" function. + ''' + preds, probs = images_to_probs(net, images) + # plot the images in the batch, along with predicted and true labels + fig = plt.figure(figsize=(12, 48)) + for idx in np.arange(4): + ax = fig.add_subplot(1, 4, idx+1, xticks=[], yticks=[]) + matplotlib_imshow(images[idx], one_channel=True) + ax.set_title("{0}, {1:.1f}%\n(label: {2})".format( + classes[preds[idx]], + probs[idx] * 100.0, + classes[labels[idx]]), + color=("green" if preds[idx]==labels[idx].item() else "red")) + return fig + +``` + +最后,让我们使用与之前教程相同的模型训练代码来训练模型,但是每 1000 批将结果写入 TensorBoard,而不是打印到控制台。 这是通过[`add_scalar`](https://pytorch.org/docs/stable/tensorboard.html#torch.utils.tensorboard.writer.SummaryWriter.add_scalar)函数完成的。 + +此外,在训练过程中,我们将生成一幅图像,显示该批量中包含的四幅图像的模型预测与实际结果。 + +```py +running_loss = 0.0 +for epoch in range(1): # loop over the dataset multiple times + + for i, data in enumerate(trainloader, 0): + + # get the inputs; data is a list of [inputs, labels] + inputs, labels = data + + # zero the parameter gradients + optimizer.zero_grad() + + # forward + backward + optimize + outputs = net(inputs) + loss = criterion(outputs, labels) + loss.backward() + optimizer.step() + + running_loss += loss.item() + if i % 1000 == 999: # every 1000 mini-batches... + + # ...log the running loss + writer.add_scalar('training loss', + running_loss / 1000, + epoch * len(trainloader) + i) + + # ...log a Matplotlib Figure showing the model's predictions on a + # random mini-batch + writer.add_figure('predictions vs. actuals', + plot_classes_preds(net, inputs, labels), + global_step=epoch * len(trainloader) + i) + running_loss = 0.0 +print('Finished Training') + +``` + +现在,您可以查看“标量”选项卡,以查看在 15,000 次训练迭代中绘制的运行损失: + +![intermediate/../../_static/img/tensorboard_scalar_runs.png](img/afda8238ecd1f547d61be4d155844f68.png) + +此外,我们可以查看整个学习过程中模型在任意批量上所做的预测。 查看“图像”选项卡,然后在“预测与实际”可视化条件下向下滚动以查看此内容; 这表明,例如,仅经过 3000 次训练迭代,该模型就已经能够区分出视觉上截然不同的类,例如衬衫,运动鞋和外套,尽管它并没有像后来的训练那样有信心: + +![intermediate/../../_static/img/tensorboard_images.png](img/d5ab1f07cb4a9d9200c2a2d3b238340d.png) + +在之前的教程中,我们研究了模型训练后的每类准确率; 在这里,我们将使用 TensorBoard 绘制每个类别的精确调用曲线([在这里解释](https://www.scikit-yb.org/en/latest/api/classifier/prcurve.html))。 + +## 6\. 使用 TensorBoard 评估经过训练的模型 + +```py +# 1\. gets the probability predictions in a test_size x num_classes Tensor +# 2\. gets the preds in a test_size Tensor +# takes ~10 seconds to run +class_probs = [] +class_preds = [] +with torch.no_grad(): + for data in testloader: + images, labels = data + output = net(images) + class_probs_batch = [F.softmax(el, dim=0) for el in output] + _, class_preds_batch = torch.max(output, 1) + + class_probs.append(class_probs_batch) + class_preds.append(class_preds_batch) + +test_probs = torch.cat([torch.stack(batch) for batch in class_probs]) +test_preds = torch.cat(class_preds) + +# helper function +def add_pr_curve_tensorboard(class_index, test_probs, test_preds, global_step=0): + ''' + Takes in a "class_index" from 0 to 9 and plots the corresponding + precision-recall curve + ''' + tensorboard_preds = test_preds == class_index + tensorboard_probs = test_probs[:, class_index] + + writer.add_pr_curve(classes[class_index], + tensorboard_preds, + tensorboard_probs, + global_step=global_step) + writer.close() + +# plot all the pr curves +for i in range(len(classes)): + add_pr_curve_tensorboard(i, test_probs, test_preds) + +``` + +现在,您将看到一个`PR Curves`选项卡,其中包含每个类别的精确调用曲线。 继续四处戳; 您会发现在某些类别中,模型的“曲线下面积”接近 100%,而在另一些类别中,该面积更低: + +![intermediate/../../_static/img/tensorboard_pr_curves.png](img/d15de2be2b754f9a4f46418764232b5e.png) + +这是 TensorBoard 和 PyTorch 与之集成的介绍。 当然,您可以在 Jupyter 笔记本中完成 TensorBoard 的所有操作,但是使用 TensorBoard 时,默认情况下会获得交互式的视觉效果。 \ No newline at end of file diff --git a/pytorch/官方教程/18.md b/pytorch/官方教程/18.md new file mode 100644 index 00000000..410648d1 --- /dev/null +++ b/pytorch/官方教程/18.md @@ -0,0 +1 @@ +# 图片/视频 \ No newline at end of file diff --git a/pytorch/官方教程/19.md b/pytorch/官方教程/19.md new file mode 100644 index 00000000..d37340e7 --- /dev/null +++ b/pytorch/官方教程/19.md @@ -0,0 +1,453 @@ +# `torchvision`对象检测微调教程 + +> 原文: + +小费 + +为了充分利用本教程,我们建议使用此 [Colab 版本](https://colab.research.google.com/github/pytorch/vision/blob/temp-tutorial/tutorials/torchvision_finetuning_instance_segmentation.ipynb)。 这将使您可以尝试以下信息。 + +在本教程中,我们将对 [Penn-Fudan 数据库](https://www.cis.upenn.edu/~jshi/ped_html/)中的行人检测和分割,使用预训练的 [Mask R-CNN](https://arxiv.org/abs/1703.06870) 模型进行微调。 它包含 170 个图像和 345 个行人实例,我们将用它来说明如何在`torchvision`中使用新功能,以便在自定义数据集上训练实例细分模型。 + +## 定义数据集 + +用于训练对象检测,实例细分和人员关键点检测的参考脚本可轻松支持添加新的自定义数据集。 数据集应继承自标准`torch.utils.data.Dataset`类,并实现`__len__`和`__getitem__`。 + +我们唯一需要的特异性是数据集`__getitem__`应该返回: + +* 图像:大小为`(H, W)`的 PIL 图像 +* 目标:包含以下字段的字典 + * `boxes (FloatTensor[N, 4])`:`[x0, y0, x1, y1]`格式的`N`边界框的坐标,范围从`0`至`W`,从`0`至`H` + * `labels (Int64Tensor[N])`:每个边界框的标签。 `0`始终代表背景类。 + * `image_id (Int64Tensor[1])`:图像标识符。 它在数据集中的所有图像之间应该是唯一的,并在评估过程中使用 + * `area (Tensor[N])`:边界框的区域。 在使用 COCO 度量进行评估时,可使用此值来区分小盒子,中盒子和大盒子之间的度量得分。 + * `iscrowd (UInt8Tensor[N])`:`iscrowd = True`的实例在评估期间将被忽略。 + * (可选)`masks (UInt8Tensor[N, H, W])`:每个对象的分割蒙版 + * (可选)`keypoints (FloatTensor[N, K, 3])`:对于 N 个对象中的每一个,它包含`[x, y, visibility]`格式的 K 个关键点,以定义对象。 可见性为 0 表示关键点不可见。 请注意,对于数据扩充,翻转关键点的概念取决于数据表示形式,您可能应该将`references/detection/transforms.py`修改为新的关键点表示形式 + +如果您的模型返回上述方法,则它们将使其适用于训练和评估,并将使用`pycocotools`中的评估脚本。 + +注意 + +对于 Windows,请使用命令从[`gautamchitnis`](https://github.com/gautamchitnis/cocoapi)安装`pycocotools` + +`pip install git+https://github.com/gautamchitnis/cocoapi.git@cocodataset-master#subdirectory=PythonAPI` + +关于`labels`的注解。 该模型将`0`类作为背景。 如果您的数据集不包含背景类,则`labels`中不应包含`0`。 例如,假设您只有*猫*和*狗*两类,则可以定义`1`来表示*猫*和`0`代表*狗*。 因此,例如,如果其中一个图像同时具有两个类,则您的`labels`张量应类似于`[1,2]`。 + +此外,如果要在训练过程中使用宽高比分组(以便每个批量仅包含具有相似长宽比的图像),则建议您还实现`get_height_and_width`方法,该方法返回图像的高度和宽度。 如果未提供此方法,我们将通过`__getitem__`查询数据集的所有元素,这会将图像加载到内存中,并且比提供自定义方法慢。 + +### 为 PennFudan 编写自定义数据集 + +让我们为 PennFudan 数据集编写一个数据集。 在[下载并解压缩 zip 文件](https://www.cis.upenn.edu/~jshi/ped_html/PennFudanPed.zip)之后,我们具有以下文件夹结构: + +```py +PennFudanPed/ + PedMasks/ + FudanPed00001_mask.png + FudanPed00002_mask.png + FudanPed00003_mask.png + FudanPed00004_mask.png + ... + PNGimg/ + FudanPed00001.png + FudanPed00002.png + FudanPed00003.png + FudanPed00004.png + +``` + +这是一对图像和分割蒙版的一个示例 + +![intermediate/../../_static/img/tv_tutorial/tv_image01.png](img/342d5d0add3b5754dae73ff222bbc543.png) ![intermediate/../../_static/img/tv_tutorial/tv_image02.png](img/c814c5c2350e00cf5fc0d883acf0843c.png) + +因此,每个图像都有一个对应的分割蒙版,其中每个颜色对应一个不同的实例。 让我们为此数据集编写一个`torch.utils.data.Dataset`类。 + +```py +import os +import numpy as np +import torch +from PIL import Image + +class PennFudanDataset(object): + def __init__(self, root, transforms): + self.root = root + self.transforms = transforms + # load all image files, sorting them to + # ensure that they are aligned + self.imgs = list(sorted(os.listdir(os.path.join(root, "PNGImages")))) + self.masks = list(sorted(os.listdir(os.path.join(root, "PedMasks")))) + + def __getitem__(self, idx): + # load images ad masks + img_path = os.path.join(self.root, "PNGImages", self.imgs[idx]) + mask_path = os.path.join(self.root, "PedMasks", self.masks[idx]) + img = Image.open(img_path).convert("RGB") + # note that we haven't converted the mask to RGB, + # because each color corresponds to a different instance + # with 0 being background + mask = Image.open(mask_path) + # convert the PIL Image into a numpy array + mask = np.array(mask) + # instances are encoded as different colors + obj_ids = np.unique(mask) + # first id is the background, so remove it + obj_ids = obj_ids[1:] + + # split the color-encoded mask into a set + # of binary masks + masks = mask == obj_ids[:, None, None] + + # get bounding box coordinates for each mask + num_objs = len(obj_ids) + boxes = [] + for i in range(num_objs): + pos = np.where(masks[i]) + xmin = np.min(pos[1]) + xmax = np.max(pos[1]) + ymin = np.min(pos[0]) + ymax = np.max(pos[0]) + boxes.append([xmin, ymin, xmax, ymax]) + + # convert everything into a torch.Tensor + boxes = torch.as_tensor(boxes, dtype=torch.float32) + # there is only one class + labels = torch.ones((num_objs,), dtype=torch.int64) + masks = torch.as_tensor(masks, dtype=torch.uint8) + + image_id = torch.tensor([idx]) + area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0]) + # suppose all instances are not crowd + iscrowd = torch.zeros((num_objs,), dtype=torch.int64) + + target = {} + target["boxes"] = boxes + target["labels"] = labels + target["masks"] = masks + target["image_id"] = image_id + target["area"] = area + target["iscrowd"] = iscrowd + + if self.transforms is not None: + img, target = self.transforms(img, target) + + return img, target + + def __len__(self): + return len(self.imgs) + +``` + +这就是数据集的全部内容。 现在,我们定义一个可以对该数据集执行预测的模型。 + +## 定义模型 + +在本教程中,我们将基于 [Faster R-CNN](https://arxiv.org/abs/1506.01497) 使用 [Mask R-CNN](https://arxiv.org/abs/1703.06870) 。 Faster R-CNN 是可预测图像中潜在对象的边界框和类分数的模型。 + +![intermediate/../../_static/img/tv_tutorial/tv_image03.png](img/611c2725bdfb89e258da9a99fca53433.png) + +Mask R-CNN 在 Faster R-CNN 中增加了一个分支,该分支还可以预测每个实例的分割掩码。 + +![intermediate/../../_static/img/tv_tutorial/tv_image04.png](img/afd408b97567c661cc8cb8a80c7c777c.png) + +在两种常见情况下,可能要修改`torchvision`模型动物园中的可用模型之一。 首先是当我们想从预先训练的模型开始,然后微调最后一层时。 另一个是当我们想要用另一个模型替换主干时(例如,为了更快的预测)。 + +在以下各节中,让我们看看如何做一个或另一个。 + +### 1-将预训练模型用于微调 + +假设您要从在 COCO 上经过预训练的模型开始,并希望针对您的特定类对其进行微调。 这是一种可行的方法: + +```py +import torchvision +from torchvision.models.detection.faster_rcnn import FastRCNNPredictor + +# load a model pre-trained pre-trained on COCO +model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True) + +# replace the classifier with a new one, that has +# num_classes which is user-defined +num_classes = 2 # 1 class (person) + background +# get number of input features for the classifier +in_features = model.roi_heads.box_predictor.cls_score.in_features +# replace the pre-trained head with a new one +model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes) + +``` + +### 2-修改模型以添加其他主干 + +```py +import torchvision +from torchvision.models.detection import FasterRCNN +from torchvision.models.detection.rpn import AnchorGenerator + +# load a pre-trained model for classification and return +# only the features +backbone = torchvision.models.mobilenet_v2(pretrained=True).features +# FasterRCNN needs to know the number of +# output channels in a backbone. For mobilenet_v2, it's 1280 +# so we need to add it here +backbone.out_channels = 1280 + +# let's make the RPN generate 5 x 3 anchors per spatial +# location, with 5 different sizes and 3 different aspect +# ratios. We have a Tuple[Tuple[int]] because each feature +# map could potentially have different sizes and +# aspect ratios +anchor_generator = AnchorGenerator(sizes=((32, 64, 128, 256, 512),), + aspect_ratios=((0.5, 1.0, 2.0),)) + +# let's define what are the feature maps that we will +# use to perform the region of interest cropping, as well as +# the size of the crop after rescaling. +# if your backbone returns a Tensor, featmap_names is expected to +# be [0]. More generally, the backbone should return an +# OrderedDict[Tensor], and in featmap_names you can choose which +# feature maps to use. +roi_pooler = torchvision.ops.MultiScaleRoIAlign(featmap_names=[0], + output_size=7, + sampling_ratio=2) + +# put the pieces together inside a FasterRCNN model +model = FasterRCNN(backbone, + num_classes=2, + rpn_anchor_generator=anchor_generator, + box_roi_pool=roi_pooler) + +``` + +### PennFudan 数据集的实例细分模型 + +在我们的案例中,由于我们的数据集非常小,我们希望从预训练模型中进行微调,因此我们将遵循方法 1。 + +这里我们还想计算实例分割掩码,因此我们将使用 Mask R-CNN: + +```py +import torchvision +from torchvision.models.detection.faster_rcnn import FastRCNNPredictor +from torchvision.models.detection.mask_rcnn import MaskRCNNPredictor + +def get_model_instance_segmentation(num_classes): + # load an instance segmentation model pre-trained pre-trained on COCO + model = torchvision.models.detection.maskrcnn_resnet50_fpn(pretrained=True) + + # get number of input features for the classifier + in_features = model.roi_heads.box_predictor.cls_score.in_features + # replace the pre-trained head with a new one + model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes) + + # now get the number of input features for the mask classifier + in_features_mask = model.roi_heads.mask_predictor.conv5_mask.in_channels + hidden_layer = 256 + # and replace the mask predictor with a new one + model.roi_heads.mask_predictor = MaskRCNNPredictor(in_features_mask, + hidden_layer, + num_classes) + + return model + +``` + +就是这样,这将使`model`随时可以在您的自定义数据集上进行训练和评估。 + +## 将所有内容放在一起 + +在`references/detection/`中,我们提供了许多帮助程序功能来简化训练和评估检测模型。 在这里,我们将使用`references/detection/engine.py`,`references/detection/utils.py`和`references/detection/transforms.py`。 只需将它们复制到您的文件夹中,然后在此处使用它们即可。 + +让我们写一些辅助函数来进行数据扩充/转换: + +```py +import transforms as T + +def get_transform(train): + transforms = [] + transforms.append(T.ToTensor()) + if train: + transforms.append(T.RandomHorizontalFlip(0.5)) + return T.Compose(transforms) + +``` + +## 测试`forward()`方法(可选) + +在遍历数据集之前,最好先查看模型在训练过程中的期望值以及对样本数据的推断时间。 + +```py +model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True) +dataset = PennFudanDataset('PennFudanPed', get_transform(train=True)) +data_loader = torch.utils.data.DataLoader( + dataset, batch_size=2, shuffle=True, num_workers=4, + collate_fn=utils.collate_fn) +# For Training +images,targets = next(iter(data_loader)) +images = list(image for image in images) +targets = [{k: v for k, v in t.items()} for t in targets] +output = model(images,targets) # Returns losses and detections +# For inference +model.eval() +x = [torch.rand(3, 300, 400), torch.rand(3, 500, 400)] +predictions = model(x) # Returns predictions + +``` + +现在,我们编写执行训练和验证的`main`函数: + +```py +from engine import train_one_epoch, evaluate +import utils + +def main(): + # train on the GPU or on the CPU, if a GPU is not available + device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu') + + # our dataset has two classes only - background and person + num_classes = 2 + # use our dataset and defined transformations + dataset = PennFudanDataset('PennFudanPed', get_transform(train=True)) + dataset_test = PennFudanDataset('PennFudanPed', get_transform(train=False)) + + # split the dataset in train and test set + indices = torch.randperm(len(dataset)).tolist() + dataset = torch.utils.data.Subset(dataset, indices[:-50]) + dataset_test = torch.utils.data.Subset(dataset_test, indices[-50:]) + + # define training and validation data loaders + data_loader = torch.utils.data.DataLoader( + dataset, batch_size=2, shuffle=True, num_workers=4, + collate_fn=utils.collate_fn) + + data_loader_test = torch.utils.data.DataLoader( + dataset_test, batch_size=1, shuffle=False, num_workers=4, + collate_fn=utils.collate_fn) + + # get the model using our helper function + model = get_model_instance_segmentation(num_classes) + + # move model to the right device + model.to(device) + + # construct an optimizer + params = [p for p in model.parameters() if p.requires_grad] + optimizer = torch.optim.SGD(params, lr=0.005, + momentum=0.9, weight_decay=0.0005) + # and a learning rate scheduler + lr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer, + step_size=3, + gamma=0.1) + + # let's train it for 10 epochs + num_epochs = 10 + + for epoch in range(num_epochs): + # train for one epoch, printing every 10 iterations + train_one_epoch(model, optimizer, data_loader, device, epoch, print_freq=10) + # update the learning rate + lr_scheduler.step() + # evaluate on the test dataset + evaluate(model, data_loader_test, device=device) + + print("That's it!") + +``` + +您应该获得第一个周期的输出: + +```py +Epoch: [0] [ 0/60] eta: 0:01:18 lr: 0.000090 loss: 2.5213 (2.5213) loss_classifier: 0.8025 (0.8025) loss_box_reg: 0.2634 (0.2634) loss_mask: 1.4265 (1.4265) loss_objectness: 0.0190 (0.0190) loss_rpn_box_reg: 0.0099 (0.0099) time: 1.3121 data: 0.3024 max mem: 3485 +Epoch: [0] [10/60] eta: 0:00:20 lr: 0.000936 loss: 1.3007 (1.5313) loss_classifier: 0.3979 (0.4719) loss_box_reg: 0.2454 (0.2272) loss_mask: 0.6089 (0.7953) loss_objectness: 0.0197 (0.0228) loss_rpn_box_reg: 0.0121 (0.0141) time: 0.4198 data: 0.0298 max mem: 5081 +Epoch: [0] [20/60] eta: 0:00:15 lr: 0.001783 loss: 0.7567 (1.1056) loss_classifier: 0.2221 (0.3319) loss_box_reg: 0.2002 (0.2106) loss_mask: 0.2904 (0.5332) loss_objectness: 0.0146 (0.0176) loss_rpn_box_reg: 0.0094 (0.0123) time: 0.3293 data: 0.0035 max mem: 5081 +Epoch: [0] [30/60] eta: 0:00:11 lr: 0.002629 loss: 0.4705 (0.8935) loss_classifier: 0.0991 (0.2517) loss_box_reg: 0.1578 (0.1957) loss_mask: 0.1970 (0.4204) loss_objectness: 0.0061 (0.0140) loss_rpn_box_reg: 0.0075 (0.0118) time: 0.3403 data: 0.0044 max mem: 5081 +Epoch: [0] [40/60] eta: 0:00:07 lr: 0.003476 loss: 0.3901 (0.7568) loss_classifier: 0.0648 (0.2022) loss_box_reg: 0.1207 (0.1736) loss_mask: 0.1705 (0.3585) loss_objectness: 0.0018 (0.0113) loss_rpn_box_reg: 0.0075 (0.0112) time: 0.3407 data: 0.0044 max mem: 5081 +Epoch: [0] [50/60] eta: 0:00:03 lr: 0.004323 loss: 0.3237 (0.6703) loss_classifier: 0.0474 (0.1731) loss_box_reg: 0.1109 (0.1561) loss_mask: 0.1658 (0.3201) loss_objectness: 0.0015 (0.0093) loss_rpn_box_reg: 0.0093 (0.0116) time: 0.3379 data: 0.0043 max mem: 5081 +Epoch: [0] [59/60] eta: 0:00:00 lr: 0.005000 loss: 0.2540 (0.6082) loss_classifier: 0.0309 (0.1526) loss_box_reg: 0.0463 (0.1405) loss_mask: 0.1568 (0.2945) loss_objectness: 0.0012 (0.0083) loss_rpn_box_reg: 0.0093 (0.0123) time: 0.3489 data: 0.0042 max mem: 5081 +Epoch: [0] Total time: 0:00:21 (0.3570 s / it) +creating index... +index created! +Test: [ 0/50] eta: 0:00:19 model_time: 0.2152 (0.2152) evaluator_time: 0.0133 (0.0133) time: 0.4000 data: 0.1701 max mem: 5081 +Test: [49/50] eta: 0:00:00 model_time: 0.0628 (0.0687) evaluator_time: 0.0039 (0.0064) time: 0.0735 data: 0.0022 max mem: 5081 +Test: Total time: 0:00:04 (0.0828 s / it) +Averaged stats: model_time: 0.0628 (0.0687) evaluator_time: 0.0039 (0.0064) +Accumulating evaluation results... +DONE (t=0.01s). +Accumulating evaluation results... +DONE (t=0.01s). +IoU metric: bbox + Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.606 + Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.984 + Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.780 + Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.313 + Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.582 + Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.612 + Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.270 + Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.672 + Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.672 + Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.650 + Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.755 + Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.664 +IoU metric: segm + Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.704 + Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.979 + Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.871 + Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.325 + Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.488 + Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.727 + Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.316 + Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.748 + Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.749 + Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.650 + Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.673 + Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.758 + +``` + +因此,经过一个周期的训练,我们获得了 60.6 的 COCO 风格 mAP 和 70.4 的遮罩 mAP。 + +经过 10 个周期的训练,我得到了以下指标 + +```py +IoU metric: bbox + Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.799 + Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.969 + Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.935 + Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.349 + Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.592 + Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.831 + Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.324 + Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.844 + Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.844 + Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.400 + Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.777 + Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.870 +IoU metric: segm + Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.761 + Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.969 + Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.919 + Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.341 + Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.464 + Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.788 + Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.303 + Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.799 + Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.799 + Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.400 + Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.769 + Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.818 + +``` + +但是这些预测是什么样的? 让我们在数据集中拍摄一张图像并进行验证 + +![intermediate/../../_static/img/tv_tutorial/tv_image05.png](img/85fee85630aaace1c60fe5ba0df8c795.png) + +经过训练的模型会在此图片中预测 9 个人物实例,让我们看看其中的几个: + +![intermediate/../../_static/img/tv_tutorial/tv_image06.png](img/c9d3ddd13da5858e2cb03b53753ece3c.png) ![intermediate/../../_static/img/tv_tutorial/tv_image07.png](img/5c33a15f9b0da3f9377dc63f70bb58a7.png) + +结果看起来还不错! + +## 总结 + +在本教程中,您学习了如何在自定义数据集上为实例细分模型创建自己的训练管道。 为此,您编写了一个`torch.utils.data.Dataset`类,该类返回图像以及真实情况框和分段蒙版。 您还利用了在 COCO train2017 上预先训练的 Mask R-CNN 模型,以便对该新数据集执行迁移学习。 + +对于更完整的示例(包括多机/多 GPU 训练),请检查在`torchvision`存储库中存在的`references/detection/train.py`。 + +[您可以在此处下载本教程的完整源文件](https://pytorch.org/tutorials/_static/tv-training-code.py)。 \ No newline at end of file diff --git a/pytorch/官方教程/20.md b/pytorch/官方教程/20.md new file mode 100644 index 00000000..e6ddbb8e --- /dev/null +++ b/pytorch/官方教程/20.md @@ -0,0 +1,590 @@ +# 计算机视觉的迁移学习教程 + +> 原文: + +**作者**: [Sasank Chilamkurthy](https://chsasank.github.io) + +在本教程中,您将学习如何使用迁移学习训练卷积神经网络进行图像分类。 您可以在 [cs231n 笔记](https://cs231n.github.io/transfer-learning/)中阅读有关转学的更多信息。 + +引用这些注解, + +> 实际上,很少有人从头开始训练整个卷积网络(使用随机初始化),因为拥有足够大小的数据集相对很少。 相反,通常在非常大的数据集上对 ConvNet 进行预训练(例如 ImageNet,其中包含 120 万个具有 1000 个类别的图像),然后将 ConvNet 用作初始化或固定特征提取器以完成感兴趣的任务。 + +这两个主要的迁移学习方案如下所示: + +* **卷积网络的微调**:代替随机初始化,我们使用经过预训练的网络初始化网络,例如在 imagenet 1000 数据集上进行训练的网络。 其余的训练照常进行。 +* **作为固定特征提取器的 ConvNet**:在这里,我们将冻结除最终全连接层之外的所有网络的权重。 最后一个全连接层将替换为具有随机权重的新层,并且仅训练该层。 + +```py +# License: BSD +# Author: Sasank Chilamkurthy + +from __future__ import print_function, division + +import torch +import torch.nn as nn +import torch.optim as optim +from torch.optim import lr_scheduler +import numpy as np +import torchvision +from torchvision import datasets, models, transforms +import matplotlib.pyplot as plt +import time +import os +import copy + +plt.ion() # interactive mode + +``` + +## 加载数据 + +我们将使用`torchvision`和`torch.utils.data`包来加载数据。 + +我们今天要解决的问题是训练一个模型来对**蚂蚁**和**蜜蜂**进行分类。 我们为蚂蚁和蜜蜂提供了大约 120 张训练图像。 每个类别有 75 个验证图像。 通常,如果从头开始训练的话,这是一个非常小的数据集。 由于我们正在使用迁移学习,因此我们应该能够很好地概括。 + +该数据集是 imagenet 的很小一部分。 + +注意 + +从的下载数据,并将其提取到当前目录。 + +```py +# Data augmentation and normalization for training +# Just normalization for validation +data_transforms = { + 'train': transforms.Compose([ + transforms.RandomResizedCrop(224), + transforms.RandomHorizontalFlip(), + transforms.ToTensor(), + transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) + ]), + 'val': transforms.Compose([ + transforms.Resize(256), + transforms.CenterCrop(224), + transforms.ToTensor(), + transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) + ]), +} + +data_dir = 'data/hymenoptera_data' +image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x), + data_transforms[x]) + for x in ['train', 'val']} +dataloaders = {x: torch.utils.data.DataLoader(image_datasets[x], batch_size=4, + shuffle=True, num_workers=4) + for x in ['train', 'val']} +dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val']} +class_names = image_datasets['train'].classes + +device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") + +``` + +### 可视化一些图像 + +让我们可视化一些训练图像,以了解数据扩充。 + +```py +def imshow(inp, title=None): + """Imshow for Tensor.""" + inp = inp.numpy().transpose((1, 2, 0)) + mean = np.array([0.485, 0.456, 0.406]) + std = np.array([0.229, 0.224, 0.225]) + inp = std * inp + mean + inp = np.clip(inp, 0, 1) + plt.imshow(inp) + if title is not None: + plt.title(title) + plt.pause(0.001) # pause a bit so that plots are updated + +# Get a batch of training data +inputs, classes = next(iter(dataloaders['train'])) + +# Make a grid from batch +out = torchvision.utils.make_grid(inputs) + +imshow(out, title=[class_names[x] for x in classes]) + +``` + +![../_img/sphx_glr_transfer_learning_tutorial_001.png](img/be538c850b645a41a7a77ff388954e14.png) + +## 训练模型 + +现在,让我们编写一个通用函数来训练模型。 在这里,我们将说明: + +* 安排学习率 +* 保存最佳模型 + +以下,参数`scheduler`是来自`torch.optim.lr_scheduler`的 LR 调度器对象。 + +```py +def train_model(model, criterion, optimizer, scheduler, num_epochs=25): + since = time.time() + + best_model_wts = copy.deepcopy(model.state_dict()) + best_acc = 0.0 + + for epoch in range(num_epochs): + print('Epoch {}/{}'.format(epoch, num_epochs - 1)) + print('-' * 10) + + # Each epoch has a training and validation phase + for phase in ['train', 'val']: + if phase == 'train': + model.train() # Set model to training mode + else: + model.eval() # Set model to evaluate mode + + running_loss = 0.0 + running_corrects = 0 + + # Iterate over data. + for inputs, labels in dataloaders[phase]: + inputs = inputs.to(device) + labels = labels.to(device) + + # zero the parameter gradients + optimizer.zero_grad() + + # forward + # track history if only in train + with torch.set_grad_enabled(phase == 'train'): + outputs = model(inputs) + _, preds = torch.max(outputs, 1) + loss = criterion(outputs, labels) + + # backward + optimize only if in training phase + if phase == 'train': + loss.backward() + optimizer.step() + + # statistics + running_loss += loss.item() * inputs.size(0) + running_corrects += torch.sum(preds == labels.data) + if phase == 'train': + scheduler.step() + + epoch_loss = running_loss / dataset_sizes[phase] + epoch_acc = running_corrects.double() / dataset_sizes[phase] + + print('{} Loss: {:.4f} Acc: {:.4f}'.format( + phase, epoch_loss, epoch_acc)) + + # deep copy the model + if phase == 'val' and epoch_acc > best_acc: + best_acc = epoch_acc + best_model_wts = copy.deepcopy(model.state_dict()) + + print() + + time_elapsed = time.time() - since + print('Training complete in {:.0f}m {:.0f}s'.format( + time_elapsed // 60, time_elapsed % 60)) + print('Best val Acc: {:4f}'.format(best_acc)) + + # load best model weights + model.load_state_dict(best_model_wts) + return model + +``` + +### 可视化模型预测 + +通用函数,显示一些图像的预测 + +```py +def visualize_model(model, num_images=6): + was_training = model.training + model.eval() + images_so_far = 0 + fig = plt.figure() + + with torch.no_grad(): + for i, (inputs, labels) in enumerate(dataloaders['val']): + inputs = inputs.to(device) + labels = labels.to(device) + + outputs = model(inputs) + _, preds = torch.max(outputs, 1) + + for j in range(inputs.size()[0]): + images_so_far += 1 + ax = plt.subplot(num_img//2, 2, images_so_far) + ax.axis('off') + ax.set_title('predicted: {}'.format(class_names[preds[j]])) + imshow(inputs.cpu().data[j]) + + if images_so_far == num_images: + model.train(mode=was_training) + return + model.train(mode=was_training) + +``` + +## 微调 ConvNet + +加载预训练的模型并重置最终的全连接层。 + +```py +model_ft = models.resnet18(pretrained=True) +num_ftrs = model_ft.fc.in_features +# Here the size of each output sample is set to 2. +# Alternatively, it can be generalized to nn.Linear(num_ftrs, len(class_names)). +model_ft.fc = nn.Linear(num_ftrs, 2) + +model_ft = model_ft.to(device) + +criterion = nn.CrossEntropyLoss() + +# Observe that all parameters are being optimized +optimizer_ft = optim.SGD(model_ft.parameters(), lr=0.001, momentum=0.9) + +# Decay LR by a factor of 0.1 every 7 epochs +exp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1) + +``` + +### 训练和评估 + +在 CPU 上大约需要 15-25 分钟。 但是在 GPU 上,此过程不到一分钟。 + +```py +model_ft = train_model(model_ft, criterion, optimizer_ft, exp_lr_scheduler, + num_epochs=25) + +``` + +出: + +```py +Epoch 0/24 +---------- +train Loss: 0.6303 Acc: 0.6926 +val Loss: 0.1492 Acc: 0.9346 + +Epoch 1/24 +---------- +train Loss: 0.5511 Acc: 0.7869 +val Loss: 0.2577 Acc: 0.8889 + +Epoch 2/24 +---------- +train Loss: 0.4885 Acc: 0.8115 +val Loss: 0.3390 Acc: 0.8758 + +Epoch 3/24 +---------- +train Loss: 0.5158 Acc: 0.7992 +val Loss: 0.5070 Acc: 0.8366 + +Epoch 4/24 +---------- +train Loss: 0.5878 Acc: 0.7992 +val Loss: 0.2706 Acc: 0.8758 + +Epoch 5/24 +---------- +train Loss: 0.4396 Acc: 0.8279 +val Loss: 0.2870 Acc: 0.8954 + +Epoch 6/24 +---------- +train Loss: 0.4612 Acc: 0.8238 +val Loss: 0.2809 Acc: 0.9150 + +Epoch 7/24 +---------- +train Loss: 0.4387 Acc: 0.8402 +val Loss: 0.1853 Acc: 0.9281 + +Epoch 8/24 +---------- +train Loss: 0.2998 Acc: 0.8648 +val Loss: 0.1926 Acc: 0.9085 + +Epoch 9/24 +---------- +train Loss: 0.3383 Acc: 0.9016 +val Loss: 0.1762 Acc: 0.9281 + +Epoch 10/24 +---------- +train Loss: 0.2969 Acc: 0.8730 +val Loss: 0.1872 Acc: 0.8954 + +Epoch 11/24 +---------- +train Loss: 0.3117 Acc: 0.8811 +val Loss: 0.1807 Acc: 0.9150 + +Epoch 12/24 +---------- +train Loss: 0.3005 Acc: 0.8770 +val Loss: 0.1930 Acc: 0.9085 + +Epoch 13/24 +---------- +train Loss: 0.3129 Acc: 0.8689 +val Loss: 0.2184 Acc: 0.9150 + +Epoch 14/24 +---------- +train Loss: 0.3776 Acc: 0.8607 +val Loss: 0.1869 Acc: 0.9216 + +Epoch 15/24 +---------- +train Loss: 0.2245 Acc: 0.9016 +val Loss: 0.1742 Acc: 0.9346 + +Epoch 16/24 +---------- +train Loss: 0.3105 Acc: 0.8607 +val Loss: 0.2056 Acc: 0.9216 + +Epoch 17/24 +---------- +train Loss: 0.2729 Acc: 0.8893 +val Loss: 0.1722 Acc: 0.9085 + +Epoch 18/24 +---------- +train Loss: 0.3210 Acc: 0.8730 +val Loss: 0.1977 Acc: 0.9281 + +Epoch 19/24 +---------- +train Loss: 0.3231 Acc: 0.8566 +val Loss: 0.1811 Acc: 0.9216 + +Epoch 20/24 +---------- +train Loss: 0.3206 Acc: 0.8648 +val Loss: 0.2033 Acc: 0.9150 + +Epoch 21/24 +---------- +train Loss: 0.2917 Acc: 0.8648 +val Loss: 0.1694 Acc: 0.9150 + +Epoch 22/24 +---------- +train Loss: 0.2412 Acc: 0.8852 +val Loss: 0.1757 Acc: 0.9216 + +Epoch 23/24 +---------- +train Loss: 0.2508 Acc: 0.8975 +val Loss: 0.1662 Acc: 0.9281 + +Epoch 24/24 +---------- +train Loss: 0.3283 Acc: 0.8566 +val Loss: 0.1761 Acc: 0.9281 + +Training complete in 1m 10s +Best val Acc: 0.934641 + +``` + +```py +visualize_model(model_ft) + +``` + +![../_img/sphx_glr_transfer_learning_tutorial_002.png](img/ebec7787362bc53fe2289e5740da5756.png) + +## 作为固定特征提取器的 ConvNet + +在这里,我们需要冻结除最后一层之外的所有网络。 我们需要设置`requires_grad == False`冻结参数,以便不在`backward()`中计算梯度。 + +[您可以在文档中阅读有关此内容的更多信息](https://pytorch.org/docs/notes/autograd.html#excluding-subgraphs-from-backward)。 + +```py +model_conv = torchvision.models.resnet18(pretrained=True) +for param in model_conv.parameters(): + param.requires_grad = False + +# Parameters of newly constructed modules have requires_grad=True by default +num_ftrs = model_conv.fc.in_features +model_conv.fc = nn.Linear(num_ftrs, 2) + +model_conv = model_conv.to(device) + +criterion = nn.CrossEntropyLoss() + +# Observe that only parameters of final layer are being optimized as +# opposed to before. +optimizer_conv = optim.SGD(model_conv.fc.parameters(), lr=0.001, momentum=0.9) + +# Decay LR by a factor of 0.1 every 7 epochs +exp_lr_scheduler = lr_scheduler.StepLR(optimizer_conv, step_size=7, gamma=0.1) + +``` + +### 训练和评估 + +与以前的方案相比,在 CPU 上将花费大约一半的时间。 这是可以预期的,因为不需要为大多数网络计算梯度。 但是,确实需要计算正向。 + +```py +model_conv = train_model(model_conv, criterion, optimizer_conv, + exp_lr_scheduler, num_epochs=25) + +``` + +出: + +```py +Epoch 0/24 +---------- +train Loss: 0.7258 Acc: 0.6148 +val Loss: 0.2690 Acc: 0.9020 + +Epoch 1/24 +---------- +train Loss: 0.5342 Acc: 0.7500 +val Loss: 0.1905 Acc: 0.9412 + +Epoch 2/24 +---------- +train Loss: 0.4262 Acc: 0.8320 +val Loss: 0.1903 Acc: 0.9412 + +Epoch 3/24 +---------- +train Loss: 0.4103 Acc: 0.8197 +val Loss: 0.2658 Acc: 0.8954 + +Epoch 4/24 +---------- +train Loss: 0.3938 Acc: 0.8115 +val Loss: 0.2871 Acc: 0.8954 + +Epoch 5/24 +---------- +train Loss: 0.4623 Acc: 0.8361 +val Loss: 0.1651 Acc: 0.9346 + +Epoch 6/24 +---------- +train Loss: 0.5348 Acc: 0.7869 +val Loss: 0.1944 Acc: 0.9477 + +Epoch 7/24 +---------- +train Loss: 0.3827 Acc: 0.8402 +val Loss: 0.1846 Acc: 0.9412 + +Epoch 8/24 +---------- +train Loss: 0.3655 Acc: 0.8443 +val Loss: 0.1873 Acc: 0.9412 + +Epoch 9/24 +---------- +train Loss: 0.3275 Acc: 0.8525 +val Loss: 0.2091 Acc: 0.9412 + +Epoch 10/24 +---------- +train Loss: 0.3375 Acc: 0.8320 +val Loss: 0.1798 Acc: 0.9412 + +Epoch 11/24 +---------- +train Loss: 0.3077 Acc: 0.8648 +val Loss: 0.1942 Acc: 0.9346 + +Epoch 12/24 +---------- +train Loss: 0.4336 Acc: 0.7787 +val Loss: 0.1934 Acc: 0.9346 + +Epoch 13/24 +---------- +train Loss: 0.3149 Acc: 0.8566 +val Loss: 0.2062 Acc: 0.9281 + +Epoch 14/24 +---------- +train Loss: 0.3617 Acc: 0.8320 +val Loss: 0.1761 Acc: 0.9412 + +Epoch 15/24 +---------- +train Loss: 0.3066 Acc: 0.8361 +val Loss: 0.1799 Acc: 0.9281 + +Epoch 16/24 +---------- +train Loss: 0.3952 Acc: 0.8443 +val Loss: 0.1666 Acc: 0.9346 + +Epoch 17/24 +---------- +train Loss: 0.3552 Acc: 0.8443 +val Loss: 0.1928 Acc: 0.9412 + +Epoch 18/24 +---------- +train Loss: 0.3106 Acc: 0.8648 +val Loss: 0.1964 Acc: 0.9346 + +Epoch 19/24 +---------- +train Loss: 0.3675 Acc: 0.8566 +val Loss: 0.1813 Acc: 0.9346 + +Epoch 20/24 +---------- +train Loss: 0.3565 Acc: 0.8320 +val Loss: 0.1758 Acc: 0.9346 + +Epoch 21/24 +---------- +train Loss: 0.2922 Acc: 0.8566 +val Loss: 0.2295 Acc: 0.9216 + +Epoch 22/24 +---------- +train Loss: 0.3283 Acc: 0.8402 +val Loss: 0.2267 Acc: 0.9281 + +Epoch 23/24 +---------- +train Loss: 0.2875 Acc: 0.8770 +val Loss: 0.1878 Acc: 0.9346 + +Epoch 24/24 +---------- +train Loss: 0.3172 Acc: 0.8689 +val Loss: 0.1849 Acc: 0.9412 + +Training complete in 0m 34s +Best val Acc: 0.947712 + +``` + +```py +visualize_model(model_conv) + +plt.ioff() +plt.show() + +``` + +![../_img/sphx_glr_transfer_learning_tutorial_003.png](img/54625e60404f9c98f34cf32ca56bb118.png) + +## 进一步学习 + +如果您想了解有关迁移学习的更多信息,请查看我们的[计算机视觉教程的量化迁移学习](https://pytorch.org/tutorials/intermediate/quantized_transfer_learning_tutorial.html)。 + +**脚本的总运行时间**:(1 分钟 56.157 秒) + +[下载 Python 源码:`transfer_learning_tutorial.py`](../_downloads/07d5af1ef41e43c07f848afaf5a1c3cc/transfer_learning_tutorial.py) + +[下载 Jupyter 笔记本:`transfer_learning_tutorial.ipynb`](../_downloads/62840b1eece760d5e42593187847261f/transfer_learning_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/21.md b/pytorch/官方教程/21.md new file mode 100644 index 00000000..94744e06 --- /dev/null +++ b/pytorch/官方教程/21.md @@ -0,0 +1,301 @@ +# 对抗示例生成 + +> 原文: + +**作者:** [Nathan Inkawhich](https://github.com/inkawhich) + +如果您正在阅读本文,希望您能体会到某些机器学习模型的有效性。 研究不断推动 ML 模型更快,更准确和更高效。 但是,设计和训练模型的一个经常被忽略的方面是安全性和鲁棒性,尤其是在面对想要欺骗模型的对手的情况下。 + +本教程将提高您对 ML 模型的安全漏洞的认识,并深入了解对抗性机器学习的热门话题。 您可能会惊讶地发现,*在图像上添加无法察觉的扰动会导致完全不同的模型表现*。 鉴于这是一个教程,我们将通过图像分类器上的示例来探讨该主题。 具体而言,我们将使用最流行的一种攻击方法,即快速梯度符号攻击(FGSM)来欺骗 MNIST 分类器。 + +## 威胁模型 + +就上下文而言,有多种类型的对抗性攻击,每种攻击者的目标和假设都不同。 但是,总的来说,总体目标是向输入数据添加最少的扰动,以引起所需的错误分类。 攻击者的知识有几种假设,其中两种是:**白盒**和**黑盒**。 *白盒*攻击假定攻击者具有完全的知识并可以访问模型,包括架构,输入,输出和权重。 *黑盒*攻击假定攻击者只能访问模型的输入和输出,并且对底层架构或权重一无所知。 目标也有几种类型,包括**错误分类**和**源/目标错误分类**。 *错误分类*意味着对手只希望输出分类错误,而不在乎新分类是什么。 *源/目标错误分类*意味着对手想要更改最初属于特定源类别的图像,以便将其分类为特定目标类别。 + +在这种情况下,FGSM 攻击是*白盒*攻击,目标是*错误分类*。 有了这些背景信息,我们现在可以详细讨论攻击了。 + +## 快速梯度符号攻击 + +迄今为止,最早的也是最流行的对抗性攻击之一被称为*快速梯度符号攻击(FGSM)*,由[《解释和利用对抗性示例》](https://arxiv.org/abs/1412.6572)(Goodfellow 等)描述。 攻击非常强大,而且直观。 它旨在利用神经网络学习*梯度*的方式来攻击神经网络。 这个想法很简单,不是通过基于反向传播的梯度来调整权重来使损失最小化,攻击会基于相同的反向传播的梯度来调整输入数据,以使损失最大化。 换句话说,攻击使用损失相对于输入数据的梯度,然后调整输入数据以使损失最大化。 + +在进入代码之前,让我们看一下著名的 [FGSM](https://arxiv.org/abs/1412.6572) Pandas 示例,并提取一些符号。 + +![fgsm_panda_image](img/d74012096c3134b776b5e9f70e8178f3.png) + +从图中,`x`是正确分类为“Pandas”的原始输入图像,`y`是`x`的输出,`θ`表示模型参数,而`J(θ, x, y)`是用于训练网络的损失。 攻击会将梯度反向传播回输入数据,以计算`ᐁ[x] J(θ, x, y)`。 然后,它会沿方向(即`ᐁ[x] J(θ)`)沿一小步(图片中的`ε`或`0.007`)调整输入数据,`(x, y)`,这将使损失最大化。 然后,当目标图像仍明显是“Pandas”时,目标网络将它们误分类为“长臂猿”。 + +希望本教程的动机已经明确,所以让我们跳入实现过程。 + +```py +from __future__ import print_function +import torch +import torch.nn as nn +import torch.nn.functional as F +import torch.optim as optim +from torchvision import datasets, transforms +import numpy as np +import matplotlib.pyplot as plt + +``` + +## 实现 + +在本节中,我们将讨论本教程的输入参数,定义受到攻击的模型,然后编写攻击代码并运行一些测试。 + +### 输入 + +本教程只有三个输入,定义如下: + +* `epsilons`-用于运行的`ε`值列表。 在列表中保留 0 很重要,因为它表示原始测试集上的模型表现。 同样,从直觉上讲,我们期望`ε`越大,扰动越明显,但是从降低模型准确率的角度来看,攻击越有效。 由于此处的数据范围为`[0,1]`,因此`ε`值不得超过 1。 +* `pretrained_model`-使用[`pytorch/examples/mnist`](https://github.com/pytorch/examples/tree/master/mnist)训练的 MNIST 模型的路径。 为简单起见,[请在此处下载预训练模型](https://drive.google.com/drive/folders/1fn83DF14tWmit0RTKWRhPq5uVXt73e0h?usp=sharing)。 +* `use_cuda`-布尔标志,如果需要和可用,则使用 CUDA。 请注意,具有 CUDA 的 GPU 在本教程中并不重要,因为 CPU 不会花费很多时间。 + +```py +epsilons = [0, .05, .1, .15, .2, .25, .3] +pretrained_model = "data/lenet_mnist_model.pth" +use_cuda=True + +``` + +### 受到攻击的模型 + +如前所述,受到攻击的模型与[`pytorch/examples/mnist`](https://github.com/pytorch/examples/tree/master/mnist)中的 MNIST 模型相同。 您可以训练并保存自己的 MNIST 模型,也可以下载并使用提供的模型。 这里的*网络*定义和测试数据加载器已从 MNIST 示例中复制而来。 本部分的目的是定义模型和数据加载器,然后初始化模型并加载预训练的权重。 + +```py +# LeNet Model definition +class Net(nn.Module): + def __init__(self): + super(Net, self).__init__() + self.conv1 = nn.Conv2d(1, 10, kernel_size=5) + self.conv2 = nn.Conv2d(10, 20, kernel_size=5) + self.conv2_drop = nn.Dropout2d() + self.fc1 = nn.Linear(320, 50) + self.fc2 = nn.Linear(50, 10) + + def forward(self, x): + x = F.relu(F.max_pool2d(self.conv1(x), 2)) + x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2)) + x = x.view(-1, 320) + x = F.relu(self.fc1(x)) + x = F.dropout(x, training=self.training) + x = self.fc2(x) + return F.log_softmax(x, dim=1) + +# MNIST Test dataset and dataloader declaration +test_loader = torch.utils.data.DataLoader( + datasets.MNIST('../data', train=False, download=True, transform=transforms.Compose([ + transforms.ToTensor(), + ])), + batch_size=1, shuffle=True) + +# Define what device we are using +print("CUDA Available: ",torch.cuda.is_available()) +device = torch.device("cuda" if (use_cuda and torch.cuda.is_available()) else "cpu") + +# Initialize the network +model = Net().to(device) + +# Load the pretrained model +model.load_state_dict(torch.load(pretrained_model, map_location='cpu')) + +# Set the model in evaluation mode. In this case this is for the Dropout layers +model.eval() + +``` + +出: + +```py +Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz to ../data/MNIST/raw/train-images-idx3-ubyte.gz +Extracting ../data/MNIST/raw/train-images-idx3-ubyte.gz to ../data/MNIST/raw +Downloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz to ../data/MNIST/raw/train-labels-idx1-ubyte.gz +Extracting ../data/MNIST/raw/train-labels-idx1-ubyte.gz to ../data/MNIST/raw +Downloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz to ../data/MNIST/raw/t10k-images-idx3-ubyte.gz +Extracting ../data/MNIST/raw/t10k-images-idx3-ubyte.gz to ../data/MNIST/raw +Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz to ../data/MNIST/raw/t10k-labels-idx1-ubyte.gz +Extracting ../data/MNIST/raw/t10k-labels-idx1-ubyte.gz to ../data/MNIST/raw +Processing... +Done! +CUDA Available: True + +``` + +### FGSM 攻击 + +现在,我们可以通过干扰原始输入来定义创建对抗示例的函数。 `fgsm_attack`函数接受三个输入,`image`是原始的干净图像(`x`),`epsilon`是像素级扰动量`ε`,`data_grad`是输入图像损失的梯度(`ᐁ[x] J(θ, x, y)`)。 该函数然后创建扰动图像为 + +![](img/tex21-1.gif) + +最后,为了维持数据的原始范围,将被扰动的图像裁剪到范围`[0,1]`。 + +```py +# FGSM attack code +def fgsm_attack(image, epsilon, data_grad): + # Collect the element-wise sign of the data gradient + sign_data_grad = data_grad.sign() + # Create the perturbed image by adjusting each pixel of the input image + perturbed_image = image + epsilon*sign_data_grad + # Adding clipping to maintain [0,1] range + perturbed_image = torch.clamp(perturbed_image, 0, 1) + # Return the perturbed image + return perturbed_image + +``` + +### 测试函数 + +最后,本教程的主要结果来自`test`函数。 每次调用此测试函数都会在 MNIST 测试集上执行完整的测试步骤,并报告最终精度。 但是,请注意,此函数还需要`epsilon`输入。 这是因为`test`函数报告实力为`ε`的来自对手的攻击模型的准确率。 更具体地说,对于测试集中的每个样本,函数都会计算输入数据`data_grad`的损失梯度,并使用`fgsm_attack`创建一个扰动图像`perturbed_data`,然后检查受干扰的示例是否具有对抗性。 除了测试模型的准确率外,该函数还保存并返回了一些成功的对抗示例,以供以后可视化。 + +```py +def test( model, device, test_loader, epsilon ): + + # Accuracy counter + correct = 0 + adv_examples = [] + + # Loop over all examples in test set + for data, target in test_loader: + + # Send the data and label to the device + data, target = data.to(device), target.to(device) + + # Set requires_grad attribute of tensor. Important for Attack + data.requires_grad = True + + # Forward pass the data through the model + output = model(data) + init_pred = output.max(1, keepdim=True)[1] # get the index of the max log-probability + + # If the initial prediction is wrong, dont bother attacking, just move on + if init_pred.item() != target.item(): + continue + + # Calculate the loss + loss = F.nll_loss(output, target) + + # Zero all existing gradients + model.zero_grad() + + # Calculate gradients of model in backward pass + loss.backward() + + # Collect datagrad + data_grad = data.grad.data + + # Call FGSM Attack + perturbed_data = fgsm_attack(data, epsilon, data_grad) + + # Re-classify the perturbed image + output = model(perturbed_data) + + # Check for success + final_pred = output.max(1, keepdim=True)[1] # get the index of the max log-probability + if final_pred.item() == target.item(): + correct += 1 + # Special case for saving 0 epsilon examples + if (epsilon == 0) and (len(adv_examples) < 5): + adv_ex = perturbed_data.squeeze().detach().cpu().numpy() + adv_examples.append( (init_pred.item(), final_pred.item(), adv_ex) ) + else: + # Save some adv examples for visualization later + if len(adv_examples) < 5: + adv_ex = perturbed_data.squeeze().detach().cpu().numpy() + adv_examples.append( (init_pred.item(), final_pred.item(), adv_ex) ) + + # Calculate final accuracy for this epsilon + final_acc = correct/float(len(test_loader)) + print("Epsilon: {}\tTest Accuracy = {} / {} = {}".format(epsilon, correct, len(test_loader), final_acc)) + + # Return the accuracy and an adversarial example + return final_acc, adv_examples + +``` + +### 运行攻击 + +实现的最后一部分是实际运行攻击。 在这里,我们为`epsilon`输入中的每个`ε`值运行完整的测试步骤。 对于每个`ε`,我们还保存最终精度,并在接下来的部分中绘制一些成功的对抗示例。 请注意,随着ε值的增加,打印的精度如何降低。 另外,请注意`ε = 0`表示原始测试准确率,没有受到攻击。 + +```py +accuracies = [] +examples = [] + +# Run test for each epsilon +for eps in epsilons: + acc, ex = test(model, device, test_loader, eps) + accuracies.append(acc) + examples.append(ex) + +``` + +出: + +```py +Epsilon: 0 Test Accuracy = 9810 / 10000 = 0.981 +Epsilon: 0.05 Test Accuracy = 9426 / 10000 = 0.9426 +Epsilon: 0.1 Test Accuracy = 8510 / 10000 = 0.851 +Epsilon: 0.15 Test Accuracy = 6826 / 10000 = 0.6826 +Epsilon: 0.2 Test Accuracy = 4301 / 10000 = 0.4301 +Epsilon: 0.25 Test Accuracy = 2082 / 10000 = 0.2082 +Epsilon: 0.3 Test Accuracy = 869 / 10000 = 0.0869 + +``` + +## 结果 + +### 准确率与`ε` + +第一个结果是精度与`ε`曲线的关系。 如前所述,随着`ε`的增加,我们预计测试精度会降低。 这是因为更大的ε意味着我们朝着将损失最大化的方向迈出了更大的一步。 请注意,即使`ε`值是线性间隔的,曲线中的趋势也不是线性的。 例如,`ε = 0.05`处的精度仅比`ε = 0`低约 4%,但`ε = 0.2`处的精度比`ε = 0.15`。 另外,请注意,模型的准确率在`ε = 0.25`和`ε = 0.3`之间达到 10 类分类器的随机准确率。 + +```py +plt.figure(figsize=(5,5)) +plt.plot(epsilons, accuracies, "*-") +plt.yticks(np.arange(0, 1.1, step=0.1)) +plt.xticks(np.arange(0, .35, step=0.05)) +plt.title("Accuracy vs Epsilon") +plt.xlabel("Epsilon") +plt.ylabel("Accuracy") +plt.show() + +``` + +![../_img/sphx_glr_fgsm_tutorial_001.png](img/7633144b009ac008488a6bd051f404c9.png) + +### 对抗示例样本 + +还记得没有免费午餐的想法吗? 在这种情况下,随着`ε`的增加,测试精度降低,但扰动变得更容易察觉。 实际上,在攻击者必须考虑的准确率下降和可感知性之间要进行权衡。 在这里,我们展示了每个`ε`值下成功对抗示例的一些示例。 绘图的每一行显示不同的`ε`值。 第一行是`ε = 0`示例,这些示例表示没有干扰的原始“干净”图像。 每张图片的标题均显示“原始分类->对抗分类”。 注意,扰动在`ε = 0.15`处开始变得明显,而在`ε = 0.3`处则非常明显。 但是,在所有情况下,尽管增加了噪音,人类仍然能够识别正确的类别。 + +```py +# Plot several examples of adversarial samples at each epsilon +cnt = 0 +plt.figure(figsize=(8,10)) +for i in range(len(epsilons)): + for j in range(len(examples[i])): + cnt += 1 + plt.subplot(len(epsilons),len(examples[0]),cnt) + plt.xticks([], []) + plt.yticks([], []) + if j == 0: + plt.ylabel("Eps: {}".format(epsilons[i]), fontsize=14) + orig,adv,ex = examples[i][j] + plt.title("{} -> {}".format(orig, adv)) + plt.imshow(ex, cmap="gray") +plt.tight_layout() +plt.show() + +``` + +![../_img/sphx_glr_fgsm_tutorial_002.png](img/049e79b05a41598709a2aeef166e4a2a.png) + +## 接下来要去哪里? + +希望本教程对对抗性机器学习主题有所了解。 从这里可以找到许多潜在的方向。 这种攻击代表了对抗性攻击研究的最开始,并且由于随后有许多关于如何攻击和防御来自对手的 ML 模型的想法。 实际上,在 NIPS 2017 上有一个对抗性的攻击和防御竞赛,并且本文描述了该竞赛中使用的许多方法:[《对抗性的攻击与防御竞赛》](https://arxiv.org/pdf/1804.00097.pdf)。 防御方面的工作还引发了使机器学习模型总体上更*健壮*的想法,以适应自然扰动和对抗性输入。 + +另一个方向是不同领域的对抗性攻击和防御。 对抗性研究不仅限于图像领域,请查看[对语音到文本模型的这种攻击](https://arxiv.org/pdf/1801.01944.pdf)。 但是,也许更多地了解对抗性机器学习的最好方法是动手。 尝试实现与 NIPS 2017 竞赛不同的攻击,并查看它与 FGSM 有何不同。 然后,尝试保护模型免受自己的攻击。 + +**脚本的总运行时间**:(4 分钟 22.519 秒) + +[下载 Python 源码:`fgsm_tutorial.py`](../_downloads/c9aee5c8955d797c051f02c07927b0c0/fgsm_tutorial.py) + +[下载 Jupyter 笔记本:`fgsm_tutorial.ipynb`](../_downloads/fba7866856a418520404ba3a11142335/fgsm_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/22.md b/pytorch/官方教程/22.md new file mode 100644 index 00000000..040604c0 --- /dev/null +++ b/pytorch/官方教程/22.md @@ -0,0 +1,735 @@ +# DCGAN 教程 + +> 原文: + +**作者**: [Nathan Inkawhich](https://github.com/inkawhich) + +## 简介 + +本教程将通过一个示例对 DCGAN 进行介绍。 在向其展示许多真实名人的照片后,我们将训练一个生成对抗网络(GAN)来产生新名人。 此处的大多数代码来自[`pytorch/examples`](https://github.com/pytorch/examples)中的 dcgan 实现,并且本文档将对该实现进行详尽的解释,并阐明此模型的工作方式和原因。 但请放心,不需要 GAN 的先验知识,但这可能需要新手花一些时间来推理幕后实际发生的事情。 同样,为了节省时间,拥有一两个 GPU 也将有所帮助。 让我们从头开始。 + +## 生成对抗网络 + +### 什么是 GAN? + +GAN 是用于教授 DL 模型以捕获训练数据分布的框架,因此我们可以从同一分布中生成新数据。 GAN 由 Ian Goodfellow 于 2014 年发明,并在论文[《生成对抗网络》](https://papers.nips.cc/paper/5423-generative-adversarial-nets.pdf)中首次进行了描述。 它们由两个不同的模型组成:*生成器*和*判别器*。 生成器的工作是生成看起来像训练图像的“假”图像。 判别器的工作是查看图像并从生成器输出它是真实的训练图像还是伪图像。 在训练过程中,生成器不断尝试通过生成越来越好的伪造品而使判别器的表现超过智者,而判别器正在努力成为更好的侦探并正确地对真实和伪造图像进行分类。 博弈的平衡点是当生成器生成的伪造品看起来像直接来自训练数据时,而判别器则总是猜测生成器输出是真实还是伪造品的 50% 置信度。 + +现在,让我们从判别器开始定义一些在整个教程中使用的符号。 令`x`为代表图像的数据。 `D(x)`是判别器网络,其输出`x`来自训练数据而不是生成器的(标量)概率。 在这里,由于我们要处理图像,因此`D(x)`的输入是 CHW 大小为`3x64x64`的图像。 直观地,当`x`来自训练数据时,`D(x)`应该为高,而当`x`来自生成器时,它应该为低。 `D(x)`也可以被认为是传统的二分类器。 + +对于生成器的表示法,令`z`是从标准正态分布中采样的潜在空间向量。 `G(z)`表示将隐向量`z`映射到数据空间的生成器函数。 `G`的目标是估计训练数据来自`p_data`的分布,以便它可以从该估计分布(`p_g`)生成假样本。 + +因此,`D(G(z))`是生成器`G`的输出是真实图像的概率(标量)。 如 [Goodfellow 的论文](https://papers.nips.cc/paper/5423-generative-adversarial-nets.pdf)中所述,`D`和`G`玩一个 minimax 游戏,其中`D`试图最大化其正确分类实物和假物`log D(x)`,并且`G`尝试最小化`D`预测其输出为假的概率`log(1 - D(G(g(x))))`。 从本文来看,GAN 损失函数为 + +![](img/tex22-1.gif) + +从理论上讲,此极小极大游戏的解决方案是`p_g = p_data`,判别器会随机猜测输入是真实的还是假的。 但是,GAN 的收敛理论仍在积极研究中,实际上,模型并不总是能达到这一目的。 + +### 什么是 DCGAN? + +DCGAN 是上述 GAN 的直接扩展,不同之处在于,DCGAN 分别在判别器和生成器中分别使用卷积和卷积转置层。 它最早由 Radford 等人,在论文[《使用深度卷积生成对抗网络的无监督表示学习》](https://arxiv.org/pdf/1511.06434.pdf)中描述。 判别器由分层的[卷积层](https://pytorch.org/docs/stable/nn.html#torch.nn.Conv2d),[批量规范层](https://pytorch.org/docs/stable/nn.html#torch.nn.BatchNorm2d)和 [LeakyReLU](https://pytorch.org/docs/stable/nn.html#torch.nn.LeakyReLU) 激活组成。 输入是`3x64x64`的输入图像,输出是输入来自真实数据分布的标量概率。 生成器由[转置卷积层](https://pytorch.org/docs/stable/nn.html#torch.nn.ConvTranspose2d),批量规范层和 [ReLU](https://pytorch.org/docs/stable/nn.html#relu) 激活组成。 输入是从标准正态分布中提取的潜向量`z`,输出是`3x64x64` RGB 图像。 跨步的转置层使潜向量可以转换为具有与图像相同形状的体积。 在本文中,作者还提供了一些有关如何设置优化器,如何计算损失函数以及如何初始化模型权重的提示,所有这些都将在接下来的部分中进行解释。 + +```py +from __future__ import print_function +#%matplotlib inline +import argparse +import os +import random +import torch +import torch.nn as nn +import torch.nn.parallel +import torch.backends.cudnn as cudnn +import torch.optim as optim +import torch.utils.data +import torchvision.datasets as dset +import torchvision.transforms as transforms +import torchvision.utils as vutils +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.animation as animation +from IPython.display import HTML + +# Set random seed for reproducibility +manualSeed = 999 +#manualSeed = random.randint(1, 10000) # use if you want new results +print("Random Seed: ", manualSeed) +random.seed(manualSeed) +torch.manual_seed(manualSeed) + +``` + +出: + +```py +Random Seed: 999 + +``` + +## 输入 + +让我们为跑步定义一些输入: + +* `dataroot`-数据集文件夹根目录的路径。 我们将在下一节中进一步讨论数据集 +* `worker`-使用`DataLoader`加载数据的工作线程数 +* `batch_size`-训练中使用的批量大小。 DCGAN 纸使用的批量大小为 128 +* `image_size`-用于训练的图像的空间大小。 此实现默认为`64x64`。 如果需要其他尺寸,则必须更改`D`和`G`的结构。 有关更多详细信息,请参见[此处](https://github.com/pytorch/examples/issues/70)。 +* `nc`-输入图像中的彩色通道数。 对于彩色图像,这是 3 +* `nz`-潜向量的长度 +* `ngf`-与通过生成器传送的特征映射的深度有关 +* `ndf`-设置通过判别器传播的特征映射的深度 +* `num_epochs`-要运行的训练周期数。 训练更长的时间可能会导致更好的结果,但也会花费更长的时间 +* `lr`-训练的学习率。 如 DCGAN 文件中所述,此数字应为 0.0002 +* `beta1`-Adam 优化器的`beta1`超参数。 如论文所述,该数字应为 0.5 +* `ngpu`-可用的 GPU 数量。 如果为 0,则代码将在 CPU 模式下运行。 如果此数字大于 0,它将在该数量的 GPU 上运行 + +```py +# Root directory for dataset +dataroot = "data/celeba" + +# Number of workers for dataloader +workers = 2 + +# Batch size during training +batch_size = 128 + +# Spatial size of training images. All images will be resized to this +# size using a transformer. +image_size = 64 + +# Number of channels in the training images. For color images this is 3 +nc = 3 + +# Size of z latent vector (i.e. size of generator input) +nz = 100 + +# Size of feature maps in generator +ngf = 64 + +# Size of feature maps in discriminator +ndf = 64 + +# Number of training epochs +num_epochs = 5 + +# Learning rate for optimizers +lr = 0.0002 + +# Beta1 hyperparam for Adam optimizers +beta1 = 0.5 + +# Number of GPUs available. Use 0 for CPU mode. +ngpu = 1 + +``` + +## 数据 + +在本教程中,我们将使用 [Celeb-A Faces 数据集](http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html),该数据集可在链接的站点或 [Google 云端硬盘](https://drive.google.com/drive/folders/0B7EVK8r0v71pTUZsaXdaSnZBZzg)中下载。 数据集将下载为名为`img_align_celeba.zip`的文件。 下载完成后,创建一个名为`celeba`的目录,并将 zip 文件解压缩到该目录中。 然后,将此笔记本的`dataroot `输入设置为刚创建的`celeba`目录。 结果目录结构应为: + +```py +/path/to/celeba + -> img_align_celeba + -> 188242.jpg + -> 173822.jpg + -> 284702.jpg + -> 537394.jpg + ... + +``` + +这是重要的一步,因为我们将使用`ImageFolder`数据集类,该类要求数据集的根文件夹中有子目录。 现在,我们可以创建数据集,创建数据加载器,将设备设置为可以运行,并最终可视化一些训练数据。 + +```py +# We can use an image folder dataset the way we have it setup. +# Create the dataset +dataset = dset.ImageFolder(root=dataroot, + transform=transforms.Compose([ + transforms.Resize(image_size), + transforms.CenterCrop(image_size), + transforms.ToTensor(), + transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), + ])) +# Create the dataloader +dataloader = torch.utils.data.DataLoader(dataset, batch_size=batch_size, + shuffle=True, num_workers=workers) + +# Decide which device we want to run on +device = torch.device("cuda:0" if (torch.cuda.is_available() and ngpu > 0) else "cpu") + +# Plot some training images +real_batch = next(iter(dataloader)) +plt.figure(figsize=(8,8)) +plt.axis("off") +plt.title("Training Images") +plt.imshow(np.transpose(vutils.make_grid(real_batch[0].to(device)[:64], padding=2, normalize=True).cpu(),(1,2,0))) + +``` + +![../_img/sphx_glr_dcgan_faces_tutorial_001.png](img/04fb3a8ed8e63cf7cffb5f29224decca.png) + +## 实现 + +设置好输入参数并准备好数据集后,我们现在可以进入实现了。 我们将从权重初始化策略开始,然后详细讨论生成器,判别器,损失函数和训练循环。 + +### 权重初始化 + +在 DCGAN 论文中,作者指定所有模型权重均应从均值为 0,`stdev = 0.02`的正态分布中随机初始化。 `weights_init`函数采用已初始化的模型作为输入,并重新初始化所有卷积,卷积转置和批量归一化层以满足此标准。 初始化后立即将此函数应用于模型。 + +```py +# custom weights initialization called on netG and netD +def weights_init(m): + classname = m.__class__.__name__ + if classname.find('Conv') != -1: + nn.init.normal_(m.weight.data, 0.0, 0.02) + elif classname.find('BatchNorm') != -1: + nn.init.normal_(m.weight.data, 1.0, 0.02) + nn.init.constant_(m.bias.data, 0) + +``` + +### 生成器 + +生成器`G`用于将潜在空间向量(`z`)映射到数据空间。 由于我们的数据是图像,因此将`z`转换为数据空间意味着最终创建与训练图像大小相同的 RGB 图像(即`3x64x64`)。 在实践中,这是通过一系列跨步的二维卷积转置层来完成的,每个层都与 2d 批量规范层和 relu 激活配对。 生成器的输出通过 tanh 函数馈送,以使其返回到输入数据范围`[-1,1]`。 值得注意的是,在卷积转置层之后存在批量规范函数,因为这是 DCGAN 论文的关键贡献。 这些层有助于训练过程中的梯度流动。 DCGAN 纸生成的图像如下所示。 + +![dcgan_generator](img/85974d98be6202902f21ce274418953f.png) + +请注意,我们在输入部分中设置的输入(`nz`,`ngf`和`nc`)如何影响代码中的生成器架构。 `nz`是`z`输入向量的长度,`ngf`与通过生成器传播的特征映射的大小有关, `nc`是输出图像中的通道(对于 RGB 图像设置为 3)。 下面是生成器的代码。 + +```py +# Generator Code + +class Generator(nn.Module): + def __init__(self, ngpu): + super(Generator, self).__init__() + self.ngpu = ngpu + self.main = nn.Sequential( + # input is Z, going into a convolution + nn.ConvTranspose2d( nz, ngf * 8, 4, 1, 0, bias=False), + nn.BatchNorm2d(ngf * 8), + nn.ReLU(True), + # state size. (ngf*8) x 4 x 4 + nn.ConvTranspose2d(ngf * 8, ngf * 4, 4, 2, 1, bias=False), + nn.BatchNorm2d(ngf * 4), + nn.ReLU(True), + # state size. (ngf*4) x 8 x 8 + nn.ConvTranspose2d( ngf * 4, ngf * 2, 4, 2, 1, bias=False), + nn.BatchNorm2d(ngf * 2), + nn.ReLU(True), + # state size. (ngf*2) x 16 x 16 + nn.ConvTranspose2d( ngf * 2, ngf, 4, 2, 1, bias=False), + nn.BatchNorm2d(ngf), + nn.ReLU(True), + # state size. (ngf) x 32 x 32 + nn.ConvTranspose2d( ngf, nc, 4, 2, 1, bias=False), + nn.Tanh() + # state size. (nc) x 64 x 64 + ) + + def forward(self, input): + return self.main(input) + +``` + +现在,我们可以实例化生成器并应用`weights_init`函数。 签出打印的模型以查看生成器对象的结构。 + +```py +# Create the generator +netG = Generator(ngpu).to(device) + +# Handle multi-gpu if desired +if (device.type == 'cuda') and (ngpu > 1): + netG = nn.DataParallel(netG, list(range(ngpu))) + +# Apply the weights_init function to randomly initialize all weights +# to mean=0, stdev=0.2. +netG.apply(weights_init) + +# Print the model +print(netG) + +``` + +出: + +```py +Generator( + (main): Sequential( + (0): ConvTranspose2d(100, 512, kernel_size=(4, 4), stride=(1, 1), bias=False) + (1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) + (2): ReLU(inplace=True) + (3): ConvTranspose2d(512, 256, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False) + (4): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) + (5): ReLU(inplace=True) + (6): ConvTranspose2d(256, 128, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False) + (7): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) + (8): ReLU(inplace=True) + (9): ConvTranspose2d(128, 64, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False) + (10): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) + (11): ReLU(inplace=True) + (12): ConvTranspose2d(64, 3, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False) + (13): Tanh() + ) +) + +``` + +### 判别器 + +如前所述,判别器`D`是一个二分类网络,将图像作为输入并输出标量概率,即输入图像是真实的(与假的相对)。 在这里,`D`拍摄`3x64x64`的输入图像,通过一系列的`Conv2d`,`BatchNorm2d`和`LeakyReLU`层对其进行处理,然后通过 Sigmoid 激活函数输出最终概率。 如果需要解决此问题,可以用更多层扩展此架构,但是使用跨步卷积,`BatchNorm`和`LeakyReLU`仍然很重要。 DCGAN 论文提到,使用跨步卷积而不是通过池化来进行下采样是一个好习惯,因为它可以让网络学习自己的池化特征。 批量规范和泄漏 ReLU 函数还可以促进健康的梯度流,这对于`G`和`D`的学习过程都是至关重要的。 + +鉴别码 + +```py +class Discriminator(nn.Module): + def __init__(self, ngpu): + super(Discriminator, self).__init__() + self.ngpu = ngpu + self.main = nn.Sequential( + # input is (nc) x 64 x 64 + nn.Conv2d(nc, ndf, 4, 2, 1, bias=False), + nn.LeakyReLU(0.2, inplace=True), + # state size. (ndf) x 32 x 32 + nn.Conv2d(ndf, ndf * 2, 4, 2, 1, bias=False), + nn.BatchNorm2d(ndf * 2), + nn.LeakyReLU(0.2, inplace=True), + # state size. (ndf*2) x 16 x 16 + nn.Conv2d(ndf * 2, ndf * 4, 4, 2, 1, bias=False), + nn.BatchNorm2d(ndf * 4), + nn.LeakyReLU(0.2, inplace=True), + # state size. (ndf*4) x 8 x 8 + nn.Conv2d(ndf * 4, ndf * 8, 4, 2, 1, bias=False), + nn.BatchNorm2d(ndf * 8), + nn.LeakyReLU(0.2, inplace=True), + # state size. (ndf*8) x 4 x 4 + nn.Conv2d(ndf * 8, 1, 4, 1, 0, bias=False), + nn.Sigmoid() + ) + + def forward(self, input): + return self.main(input) + +``` + +现在,与生成器一样,我们可以创建判别器,应用`weights_init`函数,并打印模型的结构。 + +```py +# Create the Discriminator +netD = Discriminator(ngpu).to(device) + +# Handle multi-gpu if desired +if (device.type == 'cuda') and (ngpu > 1): + netD = nn.DataParallel(netD, list(range(ngpu))) + +# Apply the weights_init function to randomly initialize all weights +# to mean=0, stdev=0.2. +netD.apply(weights_init) + +# Print the model +print(netD) + +``` + +出: + +```py +Discriminator( + (main): Sequential( + (0): Conv2d(3, 64, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False) + (1): LeakyReLU(negative_slope=0.2, inplace=True) + (2): Conv2d(64, 128, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False) + (3): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) + (4): LeakyReLU(negative_slope=0.2, inplace=True) + (5): Conv2d(128, 256, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False) + (6): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) + (7): LeakyReLU(negative_slope=0.2, inplace=True) + (8): Conv2d(256, 512, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False) + (9): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) + (10): LeakyReLU(negative_slope=0.2, inplace=True) + (11): Conv2d(512, 1, kernel_size=(4, 4), stride=(1, 1), bias=False) + (12): Sigmoid() + ) +) + +``` + +### 损失函数和优化器 + +使用`D`和`G`设置,我们可以指定它们如何通过损失函数和优化器学习。 我们将使用在 PyTorch 中定义的二进制交叉熵损失([BCELoss](https://pytorch.org/docs/stable/nn.html#torch.nn.BCELoss))函数: + +![](img/tex22-2.gif) + +请注意,此函数如何提供目标函数中两个对数分量的计算(即`log D(x)`和`log(1 - D(G(z)))`)。 我们可以指定`y`输入使用 BCE 方程的哪一部分。 这是在即将到来的训练循环中完成的,但重要的是要了解我们如何仅通过更改`y`(即`GT`标签)即可选择希望计算的分量。 + +接下来,我们将实际标签定义为 1,将假标签定义为 0。这些标签将在计算`D`和`G`的损失时使用,这也是 GAN 原始论文中使用的惯例 。 最后,我们设置了两个单独的优化器,一个用于`D`,另一个用于`G`。 如 DCGAN 论文中所指定,这两个都是学习速度为 0.0002 和`Beta1 = 0.5`的 Adam 优化器。 为了跟踪生成器的学习进度,我们将生成一批固定的潜在向量,这些向量是从高斯分布(即`fixed_noise`)中提取的。 在训练循环中,我们将定期将此`fixed_noise`输入到`G`中,并且在迭代过程中,我们将看到图像形成于噪声之外。 + +```py +# Initialize BCELoss function +criterion = nn.BCELoss() + +# Create batch of latent vectors that we will use to visualize +# the progression of the generator +fixed_noise = torch.randn(64, nz, 1, 1, device=device) + +# Establish convention for real and fake labels during training +real_label = 1. +fake_label = 0. + +# Setup Adam optimizers for both G and D +optimizerD = optim.Adam(netD.parameters(), lr=lr, betas=(beta1, 0.999)) +optimizerG = optim.Adam(netG.parameters(), lr=lr, betas=(beta1, 0.999)) + +``` + +### 训练 + +最后,既然我们已经定义了 GAN 框架的所有部分,我们就可以对其进行训练。 请注意,训练 GAN 某种程度上是一种艺术形式,因为不正确的超参数设置会导致模式崩溃,而对失败的原因几乎没有解释。 在这里,我们将严格遵循 Goodfellow 论文中的算法 1,同时遵守[`ganhacks`](https://github.com/soumith/ganhacks)中显示的一些最佳做法。 即,我们将“为真实和伪造构建不同的小批量”图像,并调整`G`的目标函数以最大化`log D(G(z))`。 训练分为两个主要部分。 第 1 部分更新了判别器,第 2 部分更新了生成器。 + +**第 1 部分-训练判别器** + +回想一下,训练判别器的目的是最大程度地提高将给定输入正确分类为真实或伪造的可能性。 就古德费罗而言,我们希望“通过提高其随机梯度来更新判别器”。 实际上,我们要最大化`log D(x) + log(1 - D(G(z))`。 由于 ganhacks 提出了单独的小批量建议,因此我们将分两步进行计算。 首先,我们将从训练集中构造一批真实样本,向前通过`D`,计算损失(`log D(x)`),然后在向后通过中计算梯度。 其次,我们将使用当前生成器构造一批假样本,将这批伪造通过`D`,计算损失(`log(1 - D(G(z)))`),然后*反向累积*梯度。 现在,利用全批量和全批量的累积梯度,我们称之为判别器优化程序的一个步骤。 + +**第 2 部分-训练生成器** + +如原始论文所述,我们希望通过最小化`log(1 - D(G(z)))`来训练生成器,以产生更好的假货。 如前所述,Goodfellow 证明这不能提供足够的梯度,尤其是在学习过程的早期。 作为解决方法,我们希望最大化`log D(G(z))`。 在代码中,我们通过以下步骤来实现此目的:将第 1 部分的生成器输出与判别器进行分类,使用实数标签`GT`计算`G`的损失,反向计算`G`的梯度,最后使用优化器步骤更新`G`的参数。 将真实标签用作损失函数的`GT`标签似乎是违反直觉的,但这使我们可以使用 BCELoss 的`log(x)`部分(而不是`log(1 - x)`部分),这正是我们想要的。 + +最后,我们将进行一些统计报告,并在每个周期结束时,将我们的`fixed_noise`批量推送到生成器中,以直观地跟踪`G`的训练进度。 报告的训练统计数据是: + +* `Loss_D`-判别器损失,计算为所有真实批量和所有假批量的损失总和(`log D(x) + log D(G(z))`)。 +* `Loss_G`-生成器损失计算为`log D(G(z))` +* `D(x)`-所有真实批量的判别器的平均输出(整个批量)。 这应该从接近 1 开始,然后在`G`变得更好时理论上收敛到 0.5。 想想这是为什么。 +* `D(G(z))`-所有假批量的平均判别器输出。 第一个数字在`D`更新之前,第二个数字在`D`更新之后。 这些数字应从 0 开始,并随着`G`的提高收敛到 0.5。 想想这是为什么。 + +**注意**:此步骤可能需要一段时间,具体取决于您运行了多少个周期以及是否从数据集中删除了一些数据。 + +```py +# Training Loop + +# Lists to keep track of progress +img_list = [] +G_losses = [] +D_losses = [] +iters = 0 + +print("Starting Training Loop...") +# For each epoch +for epoch in range(num_epochs): + # For each batch in the dataloader + for i, data in enumerate(dataloader, 0): + + ############################ + # (1) Update D network: maximize log(D(x)) + log(1 - D(G(z))) + ########################### + ## Train with all-real batch + netD.zero_grad() + # Format batch + real_cpu = data[0].to(device) + b_size = real_cpu.size(0) + label = torch.full((b_size,), real_label, dtype=torch.float, device=device) + # Forward pass real batch through D + output = netD(real_cpu).view(-1) + # Calculate loss on all-real batch + errD_real = criterion(output, label) + # Calculate gradients for D in backward pass + errD_real.backward() + D_x = output.mean().item() + + ## Train with all-fake batch + # Generate batch of latent vectors + noise = torch.randn(b_size, nz, 1, 1, device=device) + # Generate fake image batch with G + fake = netG(noise) + label.fill_(fake_label) + # Classify all fake batch with D + output = netD(fake.detach()).view(-1) + # Calculate D's loss on the all-fake batch + errD_fake = criterion(output, label) + # Calculate the gradients for this batch + errD_fake.backward() + D_G_z1 = output.mean().item() + # Add the gradients from the all-real and all-fake batches + errD = errD_real + errD_fake + # Update D + optimizerD.step() + + ############################ + # (2) Update G network: maximize log(D(G(z))) + ########################### + netG.zero_grad() + label.fill_(real_label) # fake labels are real for generator cost + # Since we just updated D, perform another forward pass of all-fake batch through D + output = netD(fake).view(-1) + # Calculate G's loss based on this output + errG = criterion(output, label) + # Calculate gradients for G + errG.backward() + D_G_z2 = output.mean().item() + # Update G + optimizerG.step() + + # Output training stats + if i % 50 == 0: + print('[%d/%d][%d/%d]\tLoss_D: %.4f\tLoss_G: %.4f\tD(x): %.4f\tD(G(z)): %.4f / %.4f' + % (epoch, num_epochs, i, len(dataloader), + errD.item(), errG.item(), D_x, D_G_z1, D_G_z2)) + + # Save Losses for plotting later + G_losses.append(errG.item()) + D_losses.append(errD.item()) + + # Check how the generator is doing by saving G's output on fixed_noise + if (iters % 500 == 0) or ((epoch == num_epochs-1) and (i == len(dataloader)-1)): + with torch.no_grad(): + fake = netG(fixed_noise).detach().cpu() + img_list.append(vutils.make_grid(fake, padding=2, normalize=True)) + + iters += 1 + +``` + +出: + +```py +Starting Training Loop... +[0/5][0/1583] Loss_D: 1.9847 Loss_G: 5.5914 D(x): 0.6004 D(G(z)): 0.6680 / 0.0062 +[0/5][50/1583] Loss_D: 0.7168 Loss_G: 35.7954 D(x): 0.7127 D(G(z)): 0.0000 / 0.0000 +[0/5][100/1583] Loss_D: 0.0007 Loss_G: 28.2580 D(x): 0.9994 D(G(z)): 0.0000 / 0.0000 +[0/5][150/1583] Loss_D: 0.0001 Loss_G: 42.5731 D(x): 0.9999 D(G(z)): 0.0000 / 0.0000 +[0/5][200/1583] Loss_D: 0.0138 Loss_G: 42.3603 D(x): 0.9933 D(G(z)): 0.0000 / 0.0000 +[0/5][250/1583] Loss_D: 0.0010 Loss_G: 42.2029 D(x): 0.9991 D(G(z)): 0.0000 / 0.0000 +[0/5][300/1583] Loss_D: 0.0000 Loss_G: 41.9521 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[0/5][350/1583] Loss_D: 0.0000 Loss_G: 41.7962 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[0/5][400/1583] Loss_D: 0.0000 Loss_G: 41.6345 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[0/5][450/1583] Loss_D: 0.0000 Loss_G: 41.6058 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[0/5][500/1583] Loss_D: 0.0001 Loss_G: 41.6208 D(x): 0.9999 D(G(z)): 0.0000 / 0.0000 +[0/5][550/1583] Loss_D: 0.0000 Loss_G: 41.3979 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[0/5][600/1583] Loss_D: 0.0000 Loss_G: 41.2545 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[0/5][650/1583] Loss_D: 0.0000 Loss_G: 41.0200 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[0/5][700/1583] Loss_D: 0.0000 Loss_G: 39.6461 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[0/5][750/1583] Loss_D: 0.0000 Loss_G: 38.8834 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[0/5][800/1583] Loss_D: 0.0000 Loss_G: 38.5914 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[0/5][850/1583] Loss_D: 0.0000 Loss_G: 38.8209 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[0/5][900/1583] Loss_D: 0.0000 Loss_G: 38.9713 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[0/5][950/1583] Loss_D: 0.0000 Loss_G: 38.4995 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[0/5][1000/1583] Loss_D: 0.0001 Loss_G: 38.5549 D(x): 0.9999 D(G(z)): 0.0000 / 0.0000 +[0/5][1050/1583] Loss_D: 0.0000 Loss_G: 39.1773 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[0/5][1100/1583] Loss_D: 0.0000 Loss_G: 39.0142 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[0/5][1150/1583] Loss_D: 0.0000 Loss_G: 38.6368 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[0/5][1200/1583] Loss_D: 0.0000 Loss_G: 38.7159 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[0/5][1250/1583] Loss_D: 0.0000 Loss_G: 38.7660 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[0/5][1300/1583] Loss_D: 0.0000 Loss_G: 38.5522 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[0/5][1350/1583] Loss_D: 0.0001 Loss_G: 38.6703 D(x): 0.9999 D(G(z)): 0.0000 / 0.0000 +[0/5][1400/1583] Loss_D: 0.0000 Loss_G: 38.5487 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[0/5][1450/1583] Loss_D: 0.0000 Loss_G: 38.0378 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[0/5][1500/1583] Loss_D: 0.0000 Loss_G: 38.1258 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[0/5][1550/1583] Loss_D: 0.0000 Loss_G: 38.3473 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[1/5][0/1583] Loss_D: 0.0000 Loss_G: 37.8825 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[1/5][50/1583] Loss_D: 0.0000 Loss_G: 38.2248 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[1/5][100/1583] Loss_D: 0.0000 Loss_G: 38.2204 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[1/5][150/1583] Loss_D: 0.0000 Loss_G: 38.0967 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[1/5][200/1583] Loss_D: 0.0000 Loss_G: 38.0669 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[1/5][250/1583] Loss_D: 0.0000 Loss_G: 37.4736 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[1/5][300/1583] Loss_D: 0.0000 Loss_G: 37.0766 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[1/5][350/1583] Loss_D: 0.0000 Loss_G: 36.6055 D(x): 1.0000 D(G(z)): 0.0000 / 0.0000 +[1/5][400/1583] Loss_D: 2.5403 Loss_G: 12.8251 D(x): 0.8672 D(G(z)): 0.8088 / 0.0000 +[1/5][450/1583] Loss_D: 1.3779 Loss_G: 2.0631 D(x): 0.5850 D(G(z)): 0.4734 / 0.1820 +[1/5][500/1583] Loss_D: 1.0299 Loss_G: 2.4048 D(x): 0.5165 D(G(z)): 0.1698 / 0.1333 +[1/5][550/1583] Loss_D: 1.4922 Loss_G: 3.2383 D(x): 0.5854 D(G(z)): 0.4773 / 0.0888 +[1/5][600/1583] Loss_D: 0.9283 Loss_G: 1.8533 D(x): 0.6231 D(G(z)): 0.2962 / 0.2153 +[1/5][650/1583] Loss_D: 0.8065 Loss_G: 2.9684 D(x): 0.6684 D(G(z)): 0.2624 / 0.0715 +[1/5][700/1583] Loss_D: 0.6909 Loss_G: 2.8746 D(x): 0.7910 D(G(z)): 0.3013 / 0.0819 +[1/5][750/1583] Loss_D: 1.3242 Loss_G: 2.5236 D(x): 0.7183 D(G(z)): 0.5300 / 0.1090 +[1/5][800/1583] Loss_D: 1.0871 Loss_G: 2.0203 D(x): 0.4993 D(G(z)): 0.1716 / 0.1727 +[1/5][850/1583] Loss_D: 1.7561 Loss_G: 4.9674 D(x): 0.8542 D(G(z)): 0.7052 / 0.0133 +[1/5][900/1583] Loss_D: 0.8294 Loss_G: 2.5024 D(x): 0.6913 D(G(z)): 0.2910 / 0.1178 +[1/5][950/1583] Loss_D: 0.9390 Loss_G: 2.2087 D(x): 0.5508 D(G(z)): 0.1638 / 0.1617 +[1/5][1000/1583] Loss_D: 1.8202 Loss_G: 1.2178 D(x): 0.2535 D(G(z)): 0.0684 / 0.3527 +[1/5][1050/1583] Loss_D: 0.9816 Loss_G: 3.7976 D(x): 0.7310 D(G(z)): 0.3944 / 0.0343 +[1/5][1100/1583] Loss_D: 0.9798 Loss_G: 2.0990 D(x): 0.5963 D(G(z)): 0.2328 / 0.1660 +[1/5][1150/1583] Loss_D: 0.7173 Loss_G: 2.7879 D(x): 0.6385 D(G(z)): 0.1424 / 0.1057 +[1/5][1200/1583] Loss_D: 0.8903 Loss_G: 2.3547 D(x): 0.7371 D(G(z)): 0.3589 / 0.1251 +[1/5][1250/1583] Loss_D: 0.6137 Loss_G: 2.1031 D(x): 0.7491 D(G(z)): 0.2062 / 0.1588 +[1/5][1300/1583] Loss_D: 1.0179 Loss_G: 5.0280 D(x): 0.7465 D(G(z)): 0.4325 / 0.0129 +[1/5][1350/1583] Loss_D: 0.7131 Loss_G: 3.6670 D(x): 0.7931 D(G(z)): 0.3270 / 0.0398 +[1/5][1400/1583] Loss_D: 1.0736 Loss_G: 4.2392 D(x): 0.8172 D(G(z)): 0.4861 / 0.0351 +[1/5][1450/1583] Loss_D: 0.6050 Loss_G: 2.6052 D(x): 0.7590 D(G(z)): 0.2240 / 0.1019 +[1/5][1500/1583] Loss_D: 1.3370 Loss_G: 1.9105 D(x): 0.3786 D(G(z)): 0.0405 / 0.2013 +[1/5][1550/1583] Loss_D: 0.6698 Loss_G: 2.3040 D(x): 0.6444 D(G(z)): 0.1071 / 0.1372 +[2/5][0/1583] Loss_D: 1.3043 Loss_G: 2.1213 D(x): 0.4073 D(G(z)): 0.0423 / 0.1682 +[2/5][50/1583] Loss_D: 1.3636 Loss_G: 3.4322 D(x): 0.7959 D(G(z)): 0.6129 / 0.0510 +[2/5][100/1583] Loss_D: 0.8047 Loss_G: 3.4262 D(x): 0.9067 D(G(z)): 0.4371 / 0.0536 +[2/5][150/1583] Loss_D: 0.7103 Loss_G: 2.4974 D(x): 0.6212 D(G(z)): 0.0862 / 0.1273 +[2/5][200/1583] Loss_D: 0.8335 Loss_G: 2.9292 D(x): 0.7340 D(G(z)): 0.3396 / 0.0772 +[2/5][250/1583] Loss_D: 1.4766 Loss_G: 1.4532 D(x): 0.3469 D(G(z)): 0.0140 / 0.3162 +[2/5][300/1583] Loss_D: 0.8063 Loss_G: 2.5363 D(x): 0.6939 D(G(z)): 0.2714 / 0.1160 +[2/5][350/1583] Loss_D: 2.4655 Loss_G: 1.7710 D(x): 0.1625 D(G(z)): 0.0049 / 0.2345 +[2/5][400/1583] Loss_D: 0.9256 Loss_G: 1.4698 D(x): 0.5101 D(G(z)): 0.1192 / 0.2926 +[2/5][450/1583] Loss_D: 0.7932 Loss_G: 3.1267 D(x): 0.8831 D(G(z)): 0.4330 / 0.0657 +[2/5][500/1583] Loss_D: 1.0515 Loss_G: 1.8415 D(x): 0.4922 D(G(z)): 0.0817 / 0.2372 +[2/5][550/1583] Loss_D: 1.1575 Loss_G: 2.3904 D(x): 0.8286 D(G(z)): 0.5113 / 0.1394 +[2/5][600/1583] Loss_D: 0.8667 Loss_G: 4.0253 D(x): 0.8805 D(G(z)): 0.4499 / 0.0329 +[2/5][650/1583] Loss_D: 0.9943 Loss_G: 3.0625 D(x): 0.8224 D(G(z)): 0.4700 / 0.0678 +[2/5][700/1583] Loss_D: 0.7634 Loss_G: 3.7297 D(x): 0.7855 D(G(z)): 0.3507 / 0.0369 +[2/5][750/1583] Loss_D: 0.6280 Loss_G: 2.7439 D(x): 0.7664 D(G(z)): 0.2518 / 0.0897 +[2/5][800/1583] Loss_D: 0.9011 Loss_G: 1.3725 D(x): 0.5495 D(G(z)): 0.1341 / 0.3033 +[2/5][850/1583] Loss_D: 0.4595 Loss_G: 3.0410 D(x): 0.8186 D(G(z)): 0.1808 / 0.0721 +[2/5][900/1583] Loss_D: 0.8331 Loss_G: 1.3725 D(x): 0.5696 D(G(z)): 0.1528 / 0.3128 +[2/5][950/1583] Loss_D: 1.2701 Loss_G: 4.4360 D(x): 0.9365 D(G(z)): 0.6218 / 0.0226 +[2/5][1000/1583] Loss_D: 0.5165 Loss_G: 3.2817 D(x): 0.7543 D(G(z)): 0.1460 / 0.0651 +[2/5][1050/1583] Loss_D: 0.5562 Loss_G: 2.5533 D(x): 0.8034 D(G(z)): 0.2385 / 0.1047 +[2/5][1100/1583] Loss_D: 0.9842 Loss_G: 3.5247 D(x): 0.7936 D(G(z)): 0.4511 / 0.0446 +[2/5][1150/1583] Loss_D: 0.6793 Loss_G: 3.2208 D(x): 0.8038 D(G(z)): 0.3133 / 0.0571 +[2/5][1200/1583] Loss_D: 1.8110 Loss_G: 5.4461 D(x): 0.8337 D(G(z)): 0.7185 / 0.0090 +[2/5][1250/1583] Loss_D: 0.6310 Loss_G: 2.8066 D(x): 0.7859 D(G(z)): 0.2644 / 0.0822 +[2/5][1300/1583] Loss_D: 0.6009 Loss_G: 1.6727 D(x): 0.6759 D(G(z)): 0.1297 / 0.2422 +[2/5][1350/1583] Loss_D: 0.5156 Loss_G: 3.5893 D(x): 0.8552 D(G(z)): 0.2686 / 0.0385 +[2/5][1400/1583] Loss_D: 0.7672 Loss_G: 1.0321 D(x): 0.5755 D(G(z)): 0.0938 / 0.4195 +[2/5][1450/1583] Loss_D: 0.6583 Loss_G: 2.0611 D(x): 0.6727 D(G(z)): 0.1675 / 0.1591 +[2/5][1500/1583] Loss_D: 1.2956 Loss_G: 3.7047 D(x): 0.9324 D(G(z)): 0.6345 / 0.0479 +[2/5][1550/1583] Loss_D: 0.8555 Loss_G: 3.0119 D(x): 0.8243 D(G(z)): 0.4237 / 0.0696 +[3/5][0/1583] Loss_D: 0.7295 Loss_G: 2.0605 D(x): 0.7051 D(G(z)): 0.2466 / 0.1671 +[3/5][50/1583] Loss_D: 0.6551 Loss_G: 3.0267 D(x): 0.8502 D(G(z)): 0.3419 / 0.0676 +[3/5][100/1583] Loss_D: 0.9209 Loss_G: 1.3069 D(x): 0.5238 D(G(z)): 0.1032 / 0.3367 +[3/5][150/1583] Loss_D: 0.6289 Loss_G: 1.8684 D(x): 0.6835 D(G(z)): 0.1555 / 0.1994 +[3/5][200/1583] Loss_D: 1.0600 Loss_G: 1.3343 D(x): 0.4512 D(G(z)): 0.0575 / 0.3259 +[3/5][250/1583] Loss_D: 0.7251 Loss_G: 1.7242 D(x): 0.6128 D(G(z)): 0.1340 / 0.2269 +[3/5][300/1583] Loss_D: 0.7097 Loss_G: 1.7072 D(x): 0.7143 D(G(z)): 0.2623 / 0.2238 +[3/5][350/1583] Loss_D: 0.8045 Loss_G: 2.7455 D(x): 0.7958 D(G(z)): 0.3825 / 0.0901 +[3/5][400/1583] Loss_D: 0.8351 Loss_G: 1.6116 D(x): 0.5394 D(G(z)): 0.1106 / 0.2425 +[3/5][450/1583] Loss_D: 1.4829 Loss_G: 0.5346 D(x): 0.3523 D(G(z)): 0.0987 / 0.6289 +[3/5][500/1583] Loss_D: 0.6972 Loss_G: 2.1915 D(x): 0.7656 D(G(z)): 0.2987 / 0.1450 +[3/5][550/1583] Loss_D: 0.7369 Loss_G: 1.7250 D(x): 0.6402 D(G(z)): 0.1899 / 0.2224 +[3/5][600/1583] Loss_D: 0.8170 Loss_G: 2.6806 D(x): 0.7843 D(G(z)): 0.3880 / 0.0929 +[3/5][650/1583] Loss_D: 1.1531 Loss_G: 0.9077 D(x): 0.4340 D(G(z)): 0.1224 / 0.4550 +[3/5][700/1583] Loss_D: 0.8751 Loss_G: 1.0230 D(x): 0.5587 D(G(z)): 0.1808 / 0.4021 +[3/5][750/1583] Loss_D: 0.7169 Loss_G: 2.1268 D(x): 0.6690 D(G(z)): 0.2219 / 0.1588 +[3/5][800/1583] Loss_D: 0.9772 Loss_G: 3.1279 D(x): 0.8451 D(G(z)): 0.5081 / 0.0632 +[3/5][850/1583] Loss_D: 0.6574 Loss_G: 1.9605 D(x): 0.7010 D(G(z)): 0.2120 / 0.1775 +[3/5][900/1583] Loss_D: 0.6153 Loss_G: 2.8981 D(x): 0.8399 D(G(z)): 0.3197 / 0.0697 +[3/5][950/1583] Loss_D: 0.9155 Loss_G: 1.1091 D(x): 0.5482 D(G(z)): 0.1730 / 0.3799 +[3/5][1000/1583] Loss_D: 0.9873 Loss_G: 3.9150 D(x): 0.8838 D(G(z)): 0.5423 / 0.0284 +[3/5][1050/1583] Loss_D: 0.8369 Loss_G: 2.1366 D(x): 0.8039 D(G(z)): 0.4067 / 0.1533 +[3/5][1100/1583] Loss_D: 0.9522 Loss_G: 3.4744 D(x): 0.8732 D(G(z)): 0.5049 / 0.0412 +[3/5][1150/1583] Loss_D: 0.6371 Loss_G: 2.1278 D(x): 0.7648 D(G(z)): 0.2672 / 0.1424 +[3/5][1200/1583] Loss_D: 1.0349 Loss_G: 2.7710 D(x): 0.7604 D(G(z)): 0.4512 / 0.0920 +[3/5][1250/1583] Loss_D: 0.9350 Loss_G: 2.7946 D(x): 0.8007 D(G(z)): 0.4649 / 0.0805 +[3/5][1300/1583] Loss_D: 0.7655 Loss_G: 2.7838 D(x): 0.7965 D(G(z)): 0.3724 / 0.0803 +[3/5][1350/1583] Loss_D: 0.7623 Loss_G: 2.2647 D(x): 0.7979 D(G(z)): 0.3641 / 0.1414 +[3/5][1400/1583] Loss_D: 0.9361 Loss_G: 3.1341 D(x): 0.8601 D(G(z)): 0.4938 / 0.0628 +[3/5][1450/1583] Loss_D: 0.7966 Loss_G: 3.1544 D(x): 0.8568 D(G(z)): 0.4211 / 0.0623 +[3/5][1500/1583] Loss_D: 1.0768 Loss_G: 3.8304 D(x): 0.8364 D(G(z)): 0.5348 / 0.0353 +[3/5][1550/1583] Loss_D: 0.8528 Loss_G: 3.3978 D(x): 0.8824 D(G(z)): 0.4788 / 0.0491 +[4/5][0/1583] Loss_D: 0.8361 Loss_G: 1.9086 D(x): 0.6756 D(G(z)): 0.2975 / 0.1872 +[4/5][50/1583] Loss_D: 0.7666 Loss_G: 2.3647 D(x): 0.7698 D(G(z)): 0.3487 / 0.1232 +[4/5][100/1583] Loss_D: 0.7536 Loss_G: 1.6556 D(x): 0.6398 D(G(z)): 0.2084 / 0.2423 +[4/5][150/1583] Loss_D: 0.8390 Loss_G: 1.7737 D(x): 0.6400 D(G(z)): 0.2714 / 0.2181 +[4/5][200/1583] Loss_D: 0.8608 Loss_G: 2.5683 D(x): 0.7898 D(G(z)): 0.4126 / 0.1009 +[4/5][250/1583] Loss_D: 0.8651 Loss_G: 1.8416 D(x): 0.6033 D(G(z)): 0.2312 / 0.1954 +[4/5][300/1583] Loss_D: 0.8790 Loss_G: 1.2224 D(x): 0.5099 D(G(z)): 0.0960 / 0.3501 +[4/5][350/1583] Loss_D: 2.0809 Loss_G: 0.5006 D(x): 0.1907 D(G(z)): 0.0415 / 0.6501 +[4/5][400/1583] Loss_D: 1.0178 Loss_G: 2.6912 D(x): 0.7134 D(G(z)): 0.4299 / 0.0977 +[4/5][450/1583] Loss_D: 0.7773 Loss_G: 1.5577 D(x): 0.6859 D(G(z)): 0.2705 / 0.2527 +[4/5][500/1583] Loss_D: 1.0217 Loss_G: 2.8968 D(x): 0.8227 D(G(z)): 0.5103 / 0.0755 +[4/5][550/1583] Loss_D: 0.6428 Loss_G: 2.8346 D(x): 0.8293 D(G(z)): 0.3290 / 0.0793 +[4/5][600/1583] Loss_D: 1.7683 Loss_G: 4.1924 D(x): 0.9236 D(G(z)): 0.7656 / 0.0211 +[4/5][650/1583] Loss_D: 0.8692 Loss_G: 2.2491 D(x): 0.7046 D(G(z)): 0.3386 / 0.1336 +[4/5][700/1583] Loss_D: 0.8933 Loss_G: 1.5814 D(x): 0.6256 D(G(z)): 0.2963 / 0.2476 +[4/5][750/1583] Loss_D: 1.2154 Loss_G: 2.6798 D(x): 0.8082 D(G(z)): 0.5792 / 0.0862 +[4/5][800/1583] Loss_D: 0.7252 Loss_G: 1.6059 D(x): 0.6257 D(G(z)): 0.1717 / 0.2486 +[4/5][850/1583] Loss_D: 0.6888 Loss_G: 2.4141 D(x): 0.7470 D(G(z)): 0.2786 / 0.1207 +[4/5][900/1583] Loss_D: 1.0490 Loss_G: 1.1737 D(x): 0.4731 D(G(z)): 0.1746 / 0.3528 +[4/5][950/1583] Loss_D: 1.1517 Loss_G: 0.5954 D(x): 0.4083 D(G(z)): 0.0727 / 0.5876 +[4/5][1000/1583] Loss_D: 0.7451 Loss_G: 2.1440 D(x): 0.7385 D(G(z)): 0.3118 / 0.1455 +[4/5][1050/1583] Loss_D: 1.2439 Loss_G: 0.8178 D(x): 0.3806 D(G(z)): 0.0852 / 0.4825 +[4/5][1100/1583] Loss_D: 0.8468 Loss_G: 3.3432 D(x): 0.8220 D(G(z)): 0.4289 / 0.0484 +[4/5][1150/1583] Loss_D: 0.9824 Loss_G: 0.8542 D(x): 0.4712 D(G(z)): 0.1120 / 0.4808 +[4/5][1200/1583] Loss_D: 1.1658 Loss_G: 3.3930 D(x): 0.8771 D(G(z)): 0.5939 / 0.0450 +[4/5][1250/1583] Loss_D: 0.8152 Loss_G: 1.3158 D(x): 0.5988 D(G(z)): 0.1721 / 0.3111 +[4/5][1300/1583] Loss_D: 0.7013 Loss_G: 2.0752 D(x): 0.6751 D(G(z)): 0.2173 / 0.1596 +[4/5][1350/1583] Loss_D: 0.8809 Loss_G: 3.0340 D(x): 0.8292 D(G(z)): 0.4574 / 0.0636 +[4/5][1400/1583] Loss_D: 0.7911 Loss_G: 2.7713 D(x): 0.7982 D(G(z)): 0.3830 / 0.0829 +[4/5][1450/1583] Loss_D: 1.0299 Loss_G: 2.8774 D(x): 0.7987 D(G(z)): 0.4941 / 0.0761 +[4/5][1500/1583] Loss_D: 0.8572 Loss_G: 2.5340 D(x): 0.7273 D(G(z)): 0.3717 / 0.1009 +[4/5][1550/1583] Loss_D: 0.8135 Loss_G: 1.6428 D(x): 0.5799 D(G(z)): 0.1693 / 0.2267 + +``` + +## 结果 + +最后,让我们看看我们是如何做到的。 在这里,我们将看三个不同的结果。 首先,我们将了解`D`和`G`的损失在训练过程中如何变化。 其次,我们将在每个周期将`G`的输出显示为`fixed_noise`批量。 第三,我们将查看一批真实数据以及来自`G`的一批伪数据。 + +**损失与训练迭代** + +下面是`D&G`的损失与训练迭代的关系图。 + +```py +plt.figure(figsize=(10,5)) +plt.title("Generator and Discriminator Loss During Training") +plt.plot(G_losses,label="G") +plt.plot(D_losses,label="D") +plt.xlabel("iterations") +plt.ylabel("Loss") +plt.legend() +plt.show() + +``` + +![../_img/sphx_glr_dcgan_faces_tutorial_002.png](img/097cd68a7de6371c697afbe4230ef328.png) + +**可视化`G`的进度** + +请记住,在每次训练之后,我们如何将生成器的输出保存为`fixed_noise`批量。 现在,我们可以用动画形象化`G`的训练进度。 按下播放按钮开始动画。 + +```py +#%%capture +fig = plt.figure(figsize=(8,8)) +plt.axis("off") +ims = [[plt.imshow(np.transpose(i,(1,2,0)), animated=True)] for i in img_list] +ani = animation.ArtistAnimation(fig, ims, interval=1000, repeat_delay=1000, blit=True) + +HTML(ani.to_jshtml()) + +``` + +![../_img/sphx_glr_dcgan_faces_tutorial_003.png](img/2a31b55ef7bfff0c24c35bc635656078.png) + +**真实图像和伪图像** + +最后,让我们并排查看一些真实图像和伪图像。 + +```py +# Grab a batch of real images from the dataloader +real_batch = next(iter(dataloader)) + +# Plot the real images +plt.figure(figsize=(15,15)) +plt.subplot(1,2,1) +plt.axis("off") +plt.title("Real Images") +plt.imshow(np.transpose(vutils.make_grid(real_batch[0].to(device)[:64], padding=5, normalize=True).cpu(),(1,2,0))) + +# Plot the fake images from the last epoch +plt.subplot(1,2,2) +plt.axis("off") +plt.title("Fake Images") +plt.imshow(np.transpose(img_list[-1],(1,2,0))) +plt.show() + +``` + +![../_img/sphx_glr_dcgan_faces_tutorial_004.png](img/c0f8a413c1f6dd23bb137d8adff1adda.png) + +## 下一步去哪里 + +我们已经走到了旅程的尽头,但是您可以从这里到达几个地方。 你可以: + +* 训练更长的时间,看看效果如何 +* 修改此模型以采用其他数据集,并可能更改图像的大小和模型架构 +* 查看其他一些不错的 GAN 项目 +* [创建可生成音乐的 GAN](https://deepmind.com/blog/wavenet-generative-model-raw-audio/) + +**脚本的总运行时间**:(29 分钟 17.480 秒) + +[下载 Python 源码:`dcgan_faces_tutorial.py`](../_downloads/dc0e6f475c6735eb8d233374f8f462eb/dcgan_faces_tutorial.py) + +[下载 Jupyter 笔记本:`dcgan_faces_tutorial.ipynb`](../_downloads/e9c8374ecc202120dc94db26bf08a00f/dcgan_faces_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/23.md b/pytorch/官方教程/23.md new file mode 100644 index 00000000..562a9f26 --- /dev/null +++ b/pytorch/官方教程/23.md @@ -0,0 +1 @@ +# 音频 \ No newline at end of file diff --git a/pytorch/官方教程/24.md b/pytorch/官方教程/24.md new file mode 100644 index 00000000..96fec4a3 --- /dev/null +++ b/pytorch/官方教程/24.md @@ -0,0 +1,499 @@ +# 音频 I/O 和`torchaudio`的预处理 + +> 原文: + +PyTorch 是一个开源深度学习平台,提供了从研究原型到具有 GPU 支持的生产部署的无缝路径。 + +解决机器学习问题的重要工作是准备数据。 `torchaudio`充分利用了 PyTorch 的 GPU 支持,并提供了许多工具来简化数据加载并使其更具可读性。 在本教程中,我们将看到如何从简单的数据集中加载和预处理数据。 请访问[音频 I/O 和`torchaudio`](https://pytorch.org/tutorials/beginner/audio_preprocessing_tutorial.html)的预处理,以了解更多信息。 + +对于本教程,请确保已安装`matplotlib`包,以便于查看。 + +```py +# Uncomment the following line to run in Google Colab +# !pip install torchaudio +import torch +import torchaudio +import requests +import matplotlib.pyplot as plt + +``` + +## 打开文件 + +`torchaudio`还支持以 wav 和 mp3 格式加载声音文件。 我们将波形称为原始音频信号。 + +```py +url = "https://pytorch.org/tutorials/_static/img/steam-train-whistle-daniel_simon-converted-from-mp3.wav" +r = requests.get(url) + +with open('steam-train-whistle-daniel_simon-converted-from-mp3.wav', 'wb') as f: + f.write(r.content) + +filename = "steam-train-whistle-daniel_simon-converted-from-mp3.wav" +waveform, sample_rate = torchaudio.load(filename) + +print("Shape of waveform: {}".format(waveform.size())) +print("Sample rate of waveform: {}".format(sample_rate)) + +plt.figure() +plt.plot(waveform.t().numpy()) + +``` + +![../_img/sphx_glr_audio_preprocessing_tutorial_001.png](img/90c999fe7ccda5e8a8fb0f86000d887f.png) + +出: + +```py +Shape of waveform: torch.Size([2, 276858]) +Sample rate of waveform: 44100 + +``` + +在`torchaudio`中加载文件时,可以选择指定后端以通过`torchaudio.set_audio_backend`使用 [SoX](https://pypi.org/project/sox/) 或 [SoundFile](https://pypi.org/project/SoundFile/) 。 这些后端在需要时会延迟加载。 + +`torchaudio`还使 JIT 编译对于函数是可选的,并在可能的情况下使用`nn.Module`。 + +## 转换 + +`torchaudio`支持不断增长的[转换列表](https://pytorch.org/audio/stable/transforms.html)。 + +* `Resample`:将波形重采样为其他采样率。 +* `Spectrogram`:从波形创建频谱图。 +* `GriffinLim`:使用 Griffin-Lim 变换从线性比例幅度谱图计算波形。 +* `ComputeDeltas`:计算张量(通常是声谱图)的增量系数。 +* `ComplexNorm`:计算复数张量的范数。 +* `MelScale`:使用转换矩阵将正常 STFT 转换为 Mel 频率 STFT。 +* `AmplitudeToDB`:这将频谱图从功率/振幅标度变为分贝标度。 +* `MFCC`:从波形创建梅尔频率倒谱系数。 +* `MelSpectrogram`:使用 PyTorch 中的 STFT 特征从波形创建 MEL 频谱图。 +* `MuLawEncoding`:基于 mu-law 压扩对波形进行编码。 +* `MuLawDecoding`:解码 mu-law 编码波形。 +* `TimeStretch`:在不更改给定速率的音调的情况下,及时拉伸频谱图。 +* `FrequencyMasking`:在频域中对频谱图应用屏蔽。 +* `TimeMasking`:在时域中对频谱图应用屏蔽。 + +每个变换都支持批量:您可以对单个原始音频信号或频谱图或许多相同形状的信号执行变换。 + +由于所有变换都是`nn.Modules`或`jit.ScriptModules`,因此它们可以随时用作神经网络的一部分。 + +首先,我们可以以对数刻度查看频谱图的对数。 + +```py +specgram = torchaudio.transforms.Spectrogram()(waveform) + +print("Shape of spectrogram: {}".format(specgram.size())) + +plt.figure() +plt.imshow(specgram.log2()[0,:,:].numpy(), cmap='gray') + +``` + +![../_img/sphx_glr_audio_preprocessing_tutorial_002.png](img/e21cb5ec883a2e5dceeff4064add3acd.png) + +出: + +```py +Shape of spectrogram: torch.Size([2, 201, 1385]) + +``` + +或者我们可以以对数刻度查看梅尔光谱图。 + +```py +specgram = torchaudio.transforms.MelSpectrogram()(waveform) + +print("Shape of spectrogram: {}".format(specgram.size())) + +plt.figure() +p = plt.imshow(specgram.log2()[0,:,:].detach().numpy(), cmap='gray') + +``` + +![../_img/sphx_glr_audio_preprocessing_tutorial_003.png](img/4262b5e808a503bf338ce30fb37e6db9.png) + +出: + +```py +Shape of spectrogram: torch.Size([2, 128, 1385]) + +``` + +我们可以一次对一个通道重新采样波形。 + +```py +new_sample_rate = sample_rate/10 + +# Since Resample applies to a single channel, we resample first channel here +channel = 0 +transformed = torchaudio.transforms.Resample(sample_rate, new_sample_rate)(waveform[channel,:].view(1,-1)) + +print("Shape of transformed waveform: {}".format(transformed.size())) + +plt.figure() +plt.plot(transformed[0,:].numpy()) + +``` + +![../_img/sphx_glr_audio_preprocessing_tutorial_004.png](img/1af46e992c93618e7ba22e311f063d1b.png) + +出: + +```py +Shape of transformed waveform: torch.Size([1, 27686]) + +``` + +作为变换的另一个示例,我们可以基于 Mu-Law 编码对信号进行编码。 但是要这样做,我们需要信号在 -1 和 1 之间。由于张量只是常规的 PyTorch 张量,因此我们可以在其上应用标准运算符。 + +```py +# Let's check if the tensor is in the interval [-1,1] +print("Min of waveform: {}\nMax of waveform: {}\nMean of waveform: {}".format(waveform.min(), waveform.max(), waveform.mean())) + +``` + +出: + +```py +Min of waveform: -0.572845458984375 +Max of waveform: 0.575958251953125 +Mean of waveform: 9.293758921558037e-05 + +``` + +由于波形已经在 -1 和 1 之间,因此我们不需要对其进行归一化。 + +```py +def normalize(tensor): + # Subtract the mean, and scale to the interval [-1,1] + tensor_minusmean = tensor - tensor.mean() + return tensor_minusmean/tensor_minusmean.abs().max() + +# Let's normalize to the full interval [-1,1] +# waveform = normalize(waveform) + +``` + +让我们对波形进行编码。 + +```py +transformed = torchaudio.transforms.MuLawEncoding()(waveform) + +print("Shape of transformed waveform: {}".format(transformed.size())) + +plt.figure() +plt.plot(transformed[0,:].numpy()) + +``` + +![../_img/sphx_glr_audio_preprocessing_tutorial_005.png](img/9ae42af4b6629f7493bc1bc150af6355.png) + +出: + +```py +Shape of transformed waveform: torch.Size([2, 276858]) + +``` + +现在解码。 + +```py +reconstructed = torchaudio.transforms.MuLawDecoding()(transformed) + +print("Shape of recovered waveform: {}".format(reconstructed.size())) + +plt.figure() +plt.plot(reconstructed[0,:].numpy()) + +``` + +![../_img/sphx_glr_audio_preprocessing_tutorial_006.png](img/97b434ffec8449a196f698b23197df05.png) + +出: + +```py +Shape of recovered waveform: torch.Size([2, 276858]) + +``` + +我们最终可以将原始波形与其重构版本进行比较。 + +```py +# Compute median relative difference +err = ((waveform-reconstructed).abs() / waveform.abs()).median() + +print("Median relative difference between original and MuLaw reconstucted signals: {:.2%}".format(err)) + +``` + +出: + +```py +Median relative difference between original and MuLaw reconstucted signals: 1.28% + +``` + +## 函数 + +上面看到的转换依赖于较低级别的无状态函数进行计算。 这些函数在`torchaudio.functional`下可用。 完整列表在[此处](https://pytorch.org/audio/functional.html),包括: + +* `istft`:短期傅立叶逆变换。 +* `gain`:对整个波形进行放大或衰减。 +* `dither`:增加以特定位深度存储的音频的动态范围。 +* `compute_deltas`:计算张量的增量系数。 +* `equalizer_biquad`:设计双二阶峰值均衡器过滤器并执行滤波。 +* `lowpass_biquad`:设计双二阶低通过滤器并执行滤波。 +* `highpass_biquad`:设计双二阶高通过滤器并执行滤波。 + +例如,让我们尝试`mu_law_encoding`函数: + +```py +mu_law_encoding_waveform = torchaudio.functional.mu_law_encoding(waveform, quantization_channels=256) + +print("Shape of transformed waveform: {}".format(mu_law_encoding_waveform.size())) + +plt.figure() +plt.plot(mu_law_encoding_waveform[0,:].numpy()) + +``` + +![../_img/sphx_glr_audio_preprocessing_tutorial_007.png](img/62754b628ac962d094ed602f9067fcf2.png) + +出: + +```py +Shape of transformed waveform: torch.Size([2, 276858]) + +``` + +您可以看到`torchaudio.functional.mu_law_encoding`的输出与`torchaudio.transforms.MuLawEncoding`的输出相同。 + +现在让我们尝试其他一些函数,并可视化其输出。 通过我们的频谱图,我们可以计算出其增量: + +```py +computed = torchaudio.functional.compute_deltas(specgram.contiguous(), win_length=3) +print("Shape of computed deltas: {}".format(computed.shape)) + +plt.figure() +plt.imshow(computed.log2()[0,:,:].detach().numpy(), cmap='gray') + +``` + +![../_img/sphx_glr_audio_preprocessing_tutorial_008.png](img/45cf97ab2bd8f85e41c99cd60c565619.png) + +出: + +```py +Shape of computed deltas: torch.Size([2, 128, 1385]) + +``` + +我们可以获取原始波形并对其应用不同的效果。 + +```py +gain_waveform = torchaudio.functional.gain(waveform, gain_db=5.0) +print("Min of gain_waveform: {}\nMax of gain_waveform: {}\nMean of gain_waveform: {}".format(gain_waveform.min(), gain_waveform.max(), gain_waveform.mean())) + +dither_waveform = torchaudio.functional.dither(waveform) +print("Min of dither_waveform: {}\nMax of dither_waveform: {}\nMean of dither_waveform: {}".format(dither_waveform.min(), dither_waveform.max(), dither_waveform.mean())) + +``` + +出: + +```py +Min of gain_waveform: -1.0186792612075806 +Max of gain_waveform: 1.024214744567871 +Mean of gain_waveform: 0.00016526899707969278 +Min of dither_waveform: -0.572784423828125 +Max of dither_waveform: 0.575927734375 +Mean of dither_waveform: 0.00010744280007202178 + +``` + +`torchaudio.functional`中函数的另一个示例是将过滤器应用于我们的波形。 将低通双二阶过滤器应用于我们的波形,将输出修改了频率信号的新波形。 + +```py +lowpass_waveform = torchaudio.functional.lowpass_biquad(waveform, sample_rate, cutoff_freq=3000) + +print("Min of lowpass_waveform: {}\nMax of lowpass_waveform: {}\nMean of lowpass_waveform: {}".format(lowpass_waveform.min(), lowpass_waveform.max(), lowpass_waveform.mean())) + +plt.figure() +plt.plot(lowpass_waveform.t().numpy()) + +``` + +![../_img/sphx_glr_audio_preprocessing_tutorial_009.png](img/063cdb1f0b70bc4c83494b9819c6a3f5.png) + +出: + +```py +Min of lowpass_waveform: -0.5595059990882874 +Max of lowpass_waveform: 0.5595012307167053 +Mean of lowpass_waveform: 9.293757466366515e-05 + +``` + +我们还可以使用高通双二阶过滤器可视化波形。 + +```py +highpass_waveform = torchaudio.functional.highpass_biquad(waveform, sample_rate, cutoff_freq=2000) + +print("Min of highpass_waveform: {}\nMax of highpass_waveform: {}\nMean of highpass_waveform: {}".format(highpass_waveform.min(), highpass_waveform.max(), highpass_waveform.mean())) + +plt.figure() +plt.plot(highpass_waveform.t().numpy()) + +``` + +![../_img/sphx_glr_audio_preprocessing_tutorial_010.png](img/a2eafa804c5b1d5c8564675a255507b2.png) + +出: + +```py +Min of highpass_waveform: -0.11269102990627289 +Max of highpass_waveform: 0.10451897978782654 +Mean of highpass_waveform: 1.8138147234170177e-11 + +``` + +## 从 Kaldi 迁移到`torchaudio` + +用户可能熟悉 [Kaldi](http://github.com/kaldi-asr/kaldi) (一种用于语音识别的工具包)。 `torchaudio`提供与`torchaudio.kaldi_io`中的兼容性。 实际上,它可以通过以下方式从 kaldi scp 或 ark 文件或流中读取: + +* `read_vec_int_ark` +* `read_vec_flt_scp` +* `read_vec_flt_arkfile`/流 +* `read_mat_scp` +* `read_mat_ark` + +`torchaudio`为`spectrogram`,`fbank`,`mfcc`和 Kaldi [提供兼容的转换](#id2)。 `resample_waveform`受益于 GPU 支持,有关更多信息,请参见[此处](compliance.kaldi.html)。 + +```py +n_fft = 400.0 +frame_length = n_fft / sample_rate * 1000.0 +frame_shift = frame_length / 2.0 + +params = { + "channel": 0, + "dither": 0.0, + "window_type": "hanning", + "frame_length": frame_length, + "frame_shift": frame_shift, + "remove_dc_offset": False, + "round_to_power_of_two": False, + "sample_frequency": sample_rate, +} + +specgram = torchaudio.compliance.kaldi.spectrogram(waveform, **params) + +print("Shape of spectrogram: {}".format(specgram.size())) + +plt.figure() +plt.imshow(specgram.t().numpy(), cmap='gray') + +``` + +![../_img/sphx_glr_audio_preprocessing_tutorial_011.png](img/8879aed8539537d699fb0d155b55b403.png) + +出: + +```py +Shape of spectrogram: torch.Size([1383, 201]) + +``` + +我们还支持根据波形计算过滤器组特征,以匹配 Kaldi 的实现。 + +```py +fbank = torchaudio.compliance.kaldi.fbank(waveform, **params) + +print("Shape of fbank: {}".format(fbank.size())) + +plt.figure() +plt.imshow(fbank.t().numpy(), cmap='gray') + +``` + +![../_img/sphx_glr_audio_preprocessing_tutorial_012.png](img/d0d82c063f83a0ba4bb8df4dcec57138.png) + +出: + +```py +Shape of fbank: torch.Size([1383, 23]) + +``` + +您可以从原始音频信号创建梅尔频率倒谱系数,这与 Kaldi 的 compute-mfcc-feats 的输入/输出相匹配。 + +```py +mfcc = torchaudio.compliance.kaldi.mfcc(waveform, **params) + +print("Shape of mfcc: {}".format(mfcc.size())) + +plt.figure() +plt.imshow(mfcc.t().numpy(), cmap='gray') + +``` + +![../_img/sphx_glr_audio_preprocessing_tutorial_013.png](img/8130c72979511b4b2daddcb2d909388a.png) + +出: + +```py +Shape of mfcc: torch.Size([1383, 13]) + +``` + +## 可用数据集 + +如果您不想创建自己的数据集来训练模型,则`torchaudio`提供了统一的数据集接口。 该接口支持将文件延迟加载到内存,下载和提取函数以及数据集以构建模型。 + +当前支持的数据集`torchaudio`为: + +* **VCTK**:109 位以英语为母语的母语者说的语音数据,带有各种重音([在此处详细了解](https://homepages.inf.ed.ac.uk/jyamagis/page3/page58/page58.html))。 +* **Yesno**:一个人在希伯来语中说是或否的 60 张唱片; 每个记录长 8 个字([在此处了解更多](https://www.openslr.org/1/))。 +* **Common Voice**:开源的多语言语音数据集,任何人都可以用来训练启用语音的应用([在此处了解更多](https://voice.mozilla.org/en/datasets))。 +* **LibriSpeech**:阅读英语语音的大型语料库(1000 小时)([在此处详细了解](http://www.openslr.org/12))。 + +```py +yesno_data = torchaudio.datasets.YESNO('./', download=True) + +# A data point in Yesno is a tuple (waveform, sample_rate, labels) where labels is a list of integers with 1 for yes and 0 for no. + +# Pick data point number 3 to see an example of the the yesno_data: +n = 3 +waveform, sample_rate, labels = yesno_data[n] + +print("Waveform: {}\nSample rate: {}\nLabels: {}".format(waveform, sample_rate, labels)) + +plt.figure() +plt.plot(waveform.t().numpy()) + +``` + +![../_img/sphx_glr_audio_preprocessing_tutorial_014.png](img/901c72128f102e0be23409cd1d103a9b.png) + +出: + +```py +Waveform: tensor([[ 3.0518e-05, 6.1035e-05, 3.0518e-05, ..., -1.8311e-04, + 4.2725e-04, 6.7139e-04]]) +Sample rate: 8000 +Labels: [0, 0, 1, 0, 0, 0, 1, 0] + +``` + +现在,每当您从数据集中请求声音文件时,仅当您请求声音文件时,它才会加载到内存中。 这意味着,数据集仅加载所需的项目并将其保留在内存中,并保存在内存中。 + +## 总结 + +我们使用示例原始音频信号或波形来说明如何使用`torchaudio`打开音频文件,以及如何对该波形进行预处理,变换和应用函数。 我们还演示了如何使用熟悉的 Kaldi 函数以及如何利用内置数据集构建模型。 鉴于`torchaudio`是基于 PyTorch 构建的,因此这些技术可以在利用 GPU 的同时,用作语音识别等更高级音频应用的构建块。 + +**脚本的总运行时间**:(0 分钟 18.821 秒) + +[下载 Python 源码:`audio_preprocessing_tutorial.py`](../_downloads/5ffe15ce830e55b3a9e9c294d04ab41c/audio_preprocessing_tutorial.py) + +[下载 Jupyter 笔记本:`audio_preprocessing_tutorial.ipynb`](../_downloads/7303ce3181f4dbc9a50bc1ed5bb3218f/audio_preprocessing_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/25.md b/pytorch/官方教程/25.md new file mode 100644 index 00000000..782ae420 --- /dev/null +++ b/pytorch/官方教程/25.md @@ -0,0 +1,456 @@ +# 使用`torchaudio`的语音命令识别 + +> 原文: + +本教程将向您展示如何正确设置音频数据集的格式,然后在数据集上训练/测试音频分类器网络。 + +Colab 提供了 GPU 选项。 在菜单选项卡中,选择“运行系统”,然后选择“更改运行系统类型”。 在随后的弹出窗口中,您可以选择 GPU。 更改之后,运行时应自动重新启动(这意味着来自已执行单元的信息会消失)。 + +首先,让我们导入常见的 Torch 包,例如[`torchaudio`](https://github.com/pytorch/audio),可以按照网站上的说明进行安装。 + +```py +# Uncomment the following line to run in Google Colab + +# CPU: +# !pip install torch==1.7.0+cpu torchvision==0.8.1+cpu torchaudio==0.7.0 -f https://download.pytorch.org/whl/torch_stable.html + +# GPU: +# !pip install torch==1.7.0+cu101 torchvision==0.8.1+cu101 torchaudio==0.7.0 -f https://download.pytorch.org/whl/torch_stable.html + +# For interactive demo at the end: +# !pip install pydub + +import torch +import torch.nn as nn +import torch.nn.functional as F +import torch.optim as optim +import torchaudio + +import matplotlib.pyplot as plt +import IPython.display as ipd +from tqdm.notebook import tqdm + +``` + +让我们检查一下 CUDA GPU 是否可用,然后选择我们的设备。 在 GPU 上运行网络将大大减少训练/测试时间。 + +```py +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") +print(device) + +``` + +## 导入数据集 + +我们使用`torchaudio`下载并表示数据集。 在这里,我们使用 [SpeechCommands](https://arxiv.org/abs/1804.03209),它是由不同人员说出的 35 个命令的数据集。 数据集`SPEECHCOMMANDS`是数据集的`torch.utils.data.Dataset`版本。 在此数据集中,所有音频文件的长度约为 1 秒(因此约为 16000 个时间帧)。 + +实际的加载和格式化步骤是在访问数据点时发生的,`torchaudio`负责将音频文件转换为张量。 如果想直接加载音频文件,可以使用`torchaudio.load()`。 它返回一个包含新创建的张量的元组以及音频文件的采样频率(`SpeechCommands`为 16kHz)。 + +回到数据集,这里我们创建一个子类,将其分为标准训练,验证和测试子集。 + +```py +from torchaudio.datasets import SPEECHCOMMANDS +import os + +class SubsetSC(SPEECHCOMMANDS): + def __init__(self, subset: str = None): + super().__init__("./", download=True) + + def load_list(filename): + filepath = os.path.join(self._path, filename) + with open(filepath) as fileobj: + return [os.path.join(self._path, line.strip()) for line in fileobj] + + if subset == "validation": + self._walker = load_list("validation_list.txt") + elif subset == "testing": + self._walker = load_list("testing_list.txt") + elif subset == "training": + excludes = load_list("validation_list.txt") + load_list("testing_list.txt") + excludes = set(excludes) + self._walker = [w for w in self._walker if w not in excludes] + +# Create training and testing split of the data. We do not use validation in this tutorial. +train_set = SubsetSC("training") +test_set = SubsetSC("testing") + +waveform, sample_rate, label, speaker_id, utterance_number = train_set[0] + +``` + +`SPEECHCOMMANDS`数据集中的数据点是一个由波形(音频信号),采样率,发声(标签),讲话者的 ID,发声数组成的元组。 + +```py +print("Shape of waveform: {}".format(waveform.size())) +print("Sample rate of waveform: {}".format(sample_rate)) + +plt.plot(waveform.t().numpy()); + +``` + +让我们找到数据集中可用的标签列表。 + +```py +labels = sorted(list(set(datapoint[2] for datapoint in train_set))) +labels + +``` + +35 个音频标签是用户说的命令。 前几个文件是人们所说的`marvin`。 + +```py +waveform_first, *_ = train_set[0] +ipd.Audio(waveform_first.numpy(), rate=sample_rate) + +waveform_second, *_ = train_set[1] +ipd.Audio(waveform_second.numpy(), rate=sample_rate) + +``` + +最后一个文件是有人说“视觉”。 + +```py +waveform_last, *_ = train_set[-1] +ipd.Audio(waveform_last.numpy(), rate=sample_rate) + +``` + +## 格式化数据 + +这是将转换应用于数据的好地方。 对于波形,我们对音频进行下采样以进行更快的处理,而不会损失太多的分类能力。 + +我们无需在此应用其他转换。 对于某些数据集,通常必须通过沿通道维度取平均值或仅保留其中一个通道来减少通道数量(例如,从立体声到单声道)。 由于`SpeechCommands`使用单个通道进行音频,因此此处不需要。 + +```py +new_sample_rate = 8000 +transform = torchaudio.transforms.Resample(orig_freq=sample_rate, new_freq=new_sample_rate) +transformed = transform(waveform) + +ipd.Audio(transformed.numpy(), rate=new_sample_rate) + +``` + +我们使用标签列表中的每个索引对每个单词进行编码。 + +```py +def label_to_index(word): + # Return the position of the word in labels + return torch.tensor(labels.index(word)) + +def index_to_label(index): + # Return the word corresponding to the index in labels + # This is the inverse of label_to_index + return labels[index] + +word_start = "yes" +index = label_to_index(word_start) +word_recovered = index_to_label(index) + +print(word_start, "-->", index, "-->", word_recovered) + +``` + +为了将由录音和语音构成的数据点列表转换为该模型的两个成批张量,我们实现了整理函数,PyTorch `DataLoader`使用了该函数,允许我们分批迭代数据集。 有关使用整理函数的更多信息,请参见[文档](https://pytorch.org/docs/stable/data.html#working-with-collate-fn)。 + +在整理函数中,我们还应用了重采样和文本编码。 + +```py +def pad_sequence(batch): + # Make all tensor in a batch the same length by padding with zeros + batch = [item.t() for item in batch] + batch = torch.nn.utils.rnn.pad_sequence(batch, batch_first=True, padding_value=0.) + return batch.permute(0, 2, 1) + +def collate_fn(batch): + + # A data tuple has the form: + # waveform, sample_rate, label, speaker_id, utterance_number + + tensors, targets = [], [] + + # Gather in lists, and encode labels as indices + for waveform, _, label, *_ in batch: + tensors += [waveform] + targets += [label_to_index(label)] + + # Group the list of tensors into a batched tensor + tensors = pad_sequence(tensors) + targets = torch.stack(targets) + + return tensors, targets + +batch_size = 256 + +if device == "cuda": + num_workers = 1 + pin_memory = True +else: + num_workers = 0 + pin_memory = False + +train_loader = torch.utils.data.DataLoader( + train_set, + batch_size=batch_size, + shuffle=True, + collate_fn=collate_fn, + num_workers=num_workers, + pin_memory=pin_memory, +) +test_loader = torch.utils.data.DataLoader( + test_set, + batch_size=batch_size, + shuffle=False, + drop_last=False, + collate_fn=collate_fn, + num_workers=num_workers, + pin_memory=pin_memory, +) + +``` + +## 定义网络 + +在本教程中,我们将使用卷积神经网络来处理原始音频数据。 通常,更高级的转换将应用于音频数据,但是 CNN 可以用于准确处理原始数据。 具体架构是根据[本文](https://arxiv.org/pdf/1610.00087.pdf)中描述的 M5 网络架构建模的。 模型处理原始音频数据的一个重要方面是其第一层过滤器的接收范围。 我们模型的第一个过滤器长度为 80,因此在处理以 8kHz 采样的音频时,接收场约为 10ms(而在 4kHz 时约为 20ms)。 此大小类似于语音处理应用,该应用通常使用 20ms 到 40ms 的接收域。 + +```py +class M5(nn.Module): + def __init__(self, n_input=1, n_output=35, stride=16, n_channel=32): + super().__init__() + self.conv1 = nn.Conv1d(n_input, n_channel, kernel_size=80, stride=stride) + self.bn1 = nn.BatchNorm1d(n_channel) + self.pool1 = nn.MaxPool1d(4) + self.conv2 = nn.Conv1d(n_channel, n_channel, kernel_size=3) + self.bn2 = nn.BatchNorm1d(n_channel) + self.pool2 = nn.MaxPool1d(4) + self.conv3 = nn.Conv1d(n_channel, 2 * n_channel, kernel_size=3) + self.bn3 = nn.BatchNorm1d(2 * n_channel) + self.pool3 = nn.MaxPool1d(4) + self.conv4 = nn.Conv1d(2 * n_channel, 2 * n_channel, kernel_size=3) + self.bn4 = nn.BatchNorm1d(2 * n_channel) + self.pool4 = nn.MaxPool1d(4) + self.fc1 = nn.Linear(2 * n_channel, n_output) + + def forward(self, x): + x = self.conv1(x) + x = F.relu(self.bn1(x)) + x = self.pool1(x) + x = self.conv2(x) + x = F.relu(self.bn2(x)) + x = self.pool2(x) + x = self.conv3(x) + x = F.relu(self.bn3(x)) + x = self.pool3(x) + x = self.conv4(x) + x = F.relu(self.bn4(x)) + x = self.pool4(x) + x = F.avg_pool1d(x, x.shape[-1]) + x = x.permute(0, 2, 1) + x = self.fc1(x) + return F.log_softmax(x, dim=2) + +model = M5(n_input=transformed.shape[0], n_output=len(labels)) +model.to(device) +print(model) + +def count_parameters(model): + return sum(p.numel() for p in model.parameters() if p.requires_grad) + +n = count_parameters(model) +print("Number of parameters: %s" % n) + +``` + +我们将使用与本文相同的优化技术,将权重衰减设置为 0.0001 的 Adam 优化器。 首先,我们将以 0.01 的学习率进行训练,但是在 20 个周期后的训练过程中,我们将使用`scheduler`将其降低到 0.001。 + +```py +optimizer = optim.Adam(model.parameters(), lr=0.01, weight_decay=0.0001) +scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=20, gamma=0.1) # reduce the learning after 20 epochs by a factor of 10 + +``` + +## 训练和测试网络 + +现在,我们定义一个训练函数,它将训练数据输入模型中,并执行反向传播和优化步骤。 对于训练,我们将使用的损失是负对数可能性。 然后,在每个周期之后将对网络进行测试,以查看训练期间准确率如何变化。 + +```py +def train(model, epoch, log_interval): + model.train() + for batch_idx, (data, target) in enumerate(train_loader): + + data = data.to(device) + target = target.to(device) + + # apply transform and model on whole batch directly on device + data = transform(data) + output = model(data) + + # negative log-likelihood for a tensor of size (batch x 1 x n_output) + loss = F.nll_loss(output.squeeze(), target) + + optimizer.zero_grad() + loss.backward() + optimizer.step() + + # print training stats + if batch_idx % log_interval == 0: + print(f"Train Epoch: {epoch} [{batch_idx * len(data)}/{len(train_loader.dataset)} ({100\. * batch_idx / len(train_loader):.0f}%)]\tLoss: {loss.item():.6f}") + + # update progress bar + pbar.update(pbar_update) + # record loss + losses.append(loss.item()) + +``` + +现在我们有了训练函数,我们需要制作一个用于测试网络准确率的函数。 我们将模型设置为`eval()`模式,然后对测试数据集进行推断。 调用`eval()`将网络中所有模块中的训练变量设置为`false`。 某些层(例如批量归一化层和丢弃层)在训练期间的行为会有所不同,因此此步骤对于获取正确的结果至关重要。 + +```py +def number_of_correct(pred, target): + # count number of correct predictions + return pred.squeeze().eq(target).sum().item() + +def get_likely_index(tensor): + # find most likely label index for each element in the batch + return tensor.argmax(dim=-1) + +def test(model, epoch): + model.eval() + correct = 0 + for data, target in test_loader: + + data = data.to(device) + target = target.to(device) + + # apply transform and model on whole batch directly on device + data = transform(data) + output = model(data) + + pred = get_likely_index(output) + correct += number_of_correct(pred, target) + + # update progress bar + pbar.update(pbar_update) + + print(f"\nTest Epoch: {epoch}\tAccuracy: {correct}/{len(test_loader.dataset)} ({100\. * correct / len(test_loader.dataset):.0f}%)\n") + +``` + +最后,我们可以训练和测试网络。 我们将训练网络十个周期,然后降低学习率,再训练十个周期。 在每个周期之后将对网络进行测试,以查看训练过程中准确率如何变化。 + +```py +log_interval = 20 +n_epoch = 2 + +pbar_update = 1 / (len(train_loader) + len(test_loader)) +losses = [] + +# The transform needs to live on the same device as the model and the data. +transform = transform.to(device) +with tqdm(total=n_epoch) as pbar: + for epoch in range(1, n_epoch + 1): + train(model, epoch, log_interval) + test(model, epoch) + scheduler.step() + +# Let's plot the training loss versus the number of iteration. +# plt.plot(losses); +# plt.title("training loss"); + +``` + +2 个周期后,测试集的网络准确率应超过 65%,而 21 个周期后,网络应达到 85%。 让我们看一下训练集中的最后几句话,看看模型是如何做到的。 + +```py +def predict(tensor): + # Use the model to predict the label of the waveform + tensor = tensor.to(device) + tensor = transform(tensor) + tensor = model(tensor.unsqueeze(0)) + tensor = get_likely_index(tensor) + tensor = index_to_label(tensor.squeeze()) + return tensor + +waveform, sample_rate, utterance, *_ = train_set[-1] +ipd.Audio(waveform.numpy(), rate=sample_rate) + +print(f"Expected: {utterance}. Predicted: {predict(waveform)}.") + +``` + +如果有一个示例,我们来寻找一个分类错误的示例。 + +```py +for i, (waveform, sample_rate, utterance, *_) in enumerate(test_set): + output = predict(waveform) + if output != utterance: + ipd.Audio(waveform.numpy(), rate=sample_rate) + print(f"Data point #{i}. Expected: {utterance}. Predicted: {output}.") + break +else: + print("All examples in this dataset were correctly classified!") + print("In this case, let's just look at the last data point") + ipd.Audio(waveform.numpy(), rate=sample_rate) + print(f"Data point #{i}. Expected: {utterance}. Predicted: {output}.") + +``` + +随意尝试使用其中一个标签的自己的录音! 例如,使用 Colab,在执行下面的单元格时说“ Go”。 这将录制一秒钟的音频并尝试对其进行分类。 + +```py +from google.colab import output as colab_output +from base64 import b64decode +from io import BytesIO +from pydub import AudioSegment + +RECORD = """ +const sleep = time => new Promise(resolve => setTimeout(resolve, time)) +const b2text = blob => new Promise(resolve => { + const reader = new FileReader() + reader.onloadend = e => resolve(e.srcElement.result) + reader.readAsDataURL(blob) +}) +var record = time => new Promise(async resolve => { + stream = await navigator.mediaDevices.getUserMedia({ audio: true }) + recorder = new MediaRecorder(stream) + chunks = [] + recorder.ondataavailable = e => chunks.push(e.data) + recorder.start() + await sleep(time) + recorder.onstop = async ()=>{ + blob = new Blob(chunks) + text = await b2text(blob) + resolve(text) + } + recorder.stop() +}) +""" + +def record(seconds=1): + display(ipd.Javascript(RECORD)) + print(f"Recording started for {seconds} seconds.") + s = colab_output.eval_js("record(%d)" % (seconds * 1000)) + print("Recording ended.") + b = b64decode(s.split(",")[1]) + + fileformat = "wav" + filename = f"_audio.{fileformat}" + AudioSegment.from_file(BytesIO(b)).export(filename, format=fileformat) + return torchaudio.load(filename) + +waveform, sample_rate = record() +print(f"Predicted: {predict(waveform)}.") +ipd.Audio(waveform.numpy(), rate=sample_rate) + +``` + +## 总结 + +在本教程中,我们使用了`torchaudio`来加载数据集并对信号进行重新采样。 然后,我们定义了经过训练的神经网络,以识别给定命令。 还有其他数据预处理方法,例如找到梅尔频率倒谱系数(MFCC),可以减小数据集的大小。 此变换也可以在`torchaudio`中作为`torchaudio.transforms.MFCC`使用。 + +**脚本的总运行时间**:(0 分钟 0.000 秒) + +[下载 Python 源码:`speech_command_recognition_with_torchaudio.py`](../_downloads/4cbc77c0f631ff7a80a046f57b97a075/speech_command_recognition_with_torchaudio.py) + +[下载 Jupyter 笔记本:`speech_command_recognition_with_torchaudio.ipynb`](../_downloads/d87597d0062580c9ec699193e951e3f4/speech_command_recognition_with_torchaudio.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/26.md b/pytorch/官方教程/26.md new file mode 100644 index 00000000..584a81a7 --- /dev/null +++ b/pytorch/官方教程/26.md @@ -0,0 +1 @@ +# 文本 \ No newline at end of file diff --git a/pytorch/官方教程/27.md b/pytorch/官方教程/27.md new file mode 100644 index 00000000..1c888aa6 --- /dev/null +++ b/pytorch/官方教程/27.md @@ -0,0 +1,329 @@ +# 使用`nn.Transformer`和`torchtext`的序列到序列建模 + +> 原文: + +这是一个有关如何训练使用[`nn.Transformer`](https://pytorch.org/docs/master/nn.html?highlight=nn%20transformer#torch.nn.Transformer)模块的序列到序列模型的教程。 + +PyTorch 1.2 版本包括一个基于[论文](https://arxiv.org/pdf/1706.03762.pdf)的标准转换器模块。 事实证明,该转换器模型在许多序列间问题上具有较高的质量,同时具有更高的可并行性。 `nn.Transformer`模块完全依赖于注意力机制(另一个最近实现为[`nn.MultiheadAttention`](https://pytorch.org/docs/master/nn.html?highlight=multiheadattention#torch.nn.MultiheadAttention)的模块)来绘制输入和输出之间的全局依存关系。 `nn.Transformer`模块现已高度模块化,因此可以轻松地修改/组成单个组件(如本教程中的[`nn.TransformerEncoder`](https://pytorch.org/docs/master/nn.html?highlight=nn%20transformerencoder#torch.nn.TransformerEncoder))。 + +![../_img/transformer_architecture.jpg](img/4b79dddf1ff54b9384754144d8246d9b.png) + +## 定义模型 + +在本教程中,我们将在语言建模任务上训练`nn.TransformerEncoder`模型。 语言建模任务是为给定单词(或单词序列)遵循单词序列的可能性分配概率。 标记序列首先传递到嵌入层,然后传递到位置编码层以说明单词的顺序(有关更多详细信息,请参见下一段)。 `nn.TransformerEncoder`由多层[`nn.TransformerEncoderLayer`](https://pytorch.org/docs/master/nn.html?highlight=transformerencoderlayer#torch.nn.TransformerEncoderLayer)组成。 与输入序列一起,还需要一个正方形的注意掩码,因为`nn.TransformerEncoder`中的自注意层仅允许出现在该序列中的较早位置。 对于语言建模任务,应屏蔽将来头寸上的所有标记。 为了获得实际的单词,将`nn.TransformerEncoder`模型的输出发送到最终的`Linear`层,然后是对数 Softmax 函数。 + +```py +import math +import torch +import torch.nn as nn +import torch.nn.functional as F + +class TransformerModel(nn.Module): + + def __init__(self, ntoken, ninp, nhead, nhid, nlayers, dropout=0.5): + super(TransformerModel, self).__init__() + from torch.nn import TransformerEncoder, TransformerEncoderLayer + self.model_type = 'Transformer' + self.pos_encoder = PositionalEncoding(ninp, dropout) + encoder_layers = TransformerEncoderLayer(ninp, nhead, nhid, dropout) + self.transformer_encoder = TransformerEncoder(encoder_layers, nlayers) + self.encoder = nn.Embedding(ntoken, ninp) + self.ninp = ninp + self.decoder = nn.Linear(ninp, ntoken) + + self.init_weights() + + def generate_square_subsequent_mask(self, sz): + mask = (torch.triu(torch.ones(sz, sz)) == 1).transpose(0, 1) + mask = mask.float().masked_fill(mask == 0, float('-inf')).masked_fill(mask == 1, float(0.0)) + return mask + + def init_weights(self): + initrange = 0.1 + self.encoder.weight.data.uniform_(-initrange, initrange) + self.decoder.bias.data.zero_() + self.decoder.weight.data.uniform_(-initrange, initrange) + + def forward(self, src, src_mask): + src = self.encoder(src) * math.sqrt(self.ninp) + src = self.pos_encoder(src) + output = self.transformer_encoder(src, src_mask) + output = self.decoder(output) + return output + +``` + +`PositionalEncoding`模块注入一些有关标记在序列中的相对或绝对位置的信息。 位置编码的尺寸与嵌入的尺寸相同,因此可以将两者相加。 在这里,我们使用不同频率的`sine`和`cosine`函数。 + +```py +class PositionalEncoding(nn.Module): + + def __init__(self, d_model, dropout=0.1, max_len=5000): + super(PositionalEncoding, self).__init__() + self.dropout = nn.Dropout(p=dropout) + + pe = torch.zeros(max_len, d_model) + position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1) + div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model)) + pe[:, 0::2] = torch.sin(position * div_term) + pe[:, 1::2] = torch.cos(position * div_term) + pe = pe.unsqueeze(0).transpose(0, 1) + self.register_buffer('pe', pe) + + def forward(self, x): + x = x + self.pe[:x.size(0), :] + return self.dropout(x) + +``` + +## 加载和批量数据 + +本教程使用`torchtext`生成 Wikitext-2 数据集。 `vocab`对象是基于训练数据集构建的,用于将标记数字化为张量。 从序列数据开始,`batchify()`函数将数据集排列为列,以修剪掉数据分成大小为`batch_size`的批量后剩余的所有标记。 例如,以字母为序列(总长度为 26)并且批大小为 4,我们将字母分为 4 个长度为 6 的序列: + +![](img/tex27-1.gif) + +这些列被模型视为独立的,这意味着无法了解`G`和`F`的依赖性,但可以进行更有效的批量。 + +```py +import io +import torch +from torchtext.utils import download_from_url, extract_archive +from torchtext.data.utils import get_tokenizer +from torchtext.vocab import build_vocab_from_iterator + +url = 'https://s3.amazonaws.com/research.metamind.io/wikitext/wikitext-2-v1.zip' +test_filepath, valid_filepath, train_filepath = extract_archive(download_from_url(url)) +tokenizer = get_tokenizer('basic_english') +vocab = build_vocab_from_iterator(map(tokenizer, + iter(io.open(train_filepath, + encoding="utf8")))) + +def data_process(raw_text_iter): + data = [torch.tensor([vocab[token] for token in tokenizer(item)], + dtype=torch.long) for item in raw_text_iter] + return torch.cat(tuple(filter(lambda t: t.numel() > 0, data))) + +train_data = data_process(iter(io.open(train_filepath, encoding="utf8"))) +val_data = data_process(iter(io.open(valid_filepath, encoding="utf8"))) +test_data = data_process(iter(io.open(test_filepath, encoding="utf8"))) + +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + +def batchify(data, bsz): + # Divide the dataset into bsz parts. + nbatch = data.size(0) // bsz + # Trim off any extra elements that wouldn't cleanly fit (remainders). + data = data.narrow(0, 0, nbatch * bsz) + # Evenly divide the data across the bsz batches. + data = data.view(bsz, -1).t().contiguous() + return data.to(device) + +batch_size = 20 +eval_batch_size = 10 +train_data = batchify(train_data, batch_size) +val_data = batchify(val_data, eval_batch_size) +test_data = batchify(test_data, eval_batch_size) + +``` + +### 生成输入序列和目标序列的函数 + +`get_batch()`函数为转换器模型生成输入和目标序列。 它将源数据细分为长度为`bptt`的块。 对于语言建模任务,模型需要以下单词作为`Target`。 例如,如果`bptt`值为 2,则`i = 0`时,我们将获得以下两个变量: + +![../_img/transformer_input_target.png](img/20ef8681366b44461cf49d1ab98ab8f2.png) + +应该注意的是,这些块沿着维度 0,与`Transformer`模型中的`S`维度一致。 批量尺寸`N`沿尺寸 1。 + +```py +bptt = 35 +def get_batch(source, i): + seq_len = min(bptt, len(source) - 1 - i) + data = source[i:i+seq_len] + target = source[i+1:i+1+seq_len].reshape(-1) + return data, target + +``` + +## 启动实例 + +使用下面的超参数建立模型。 `vocab`的大小等于`vocab`对象的长度。 + +```py +ntokens = len(vocab.stoi) # the size of vocabulary +emsize = 200 # embedding dimension +nhid = 200 # the dimension of the feedforward network model in nn.TransformerEncoder +nlayers = 2 # the number of nn.TransformerEncoderLayer in nn.TransformerEncoder +nhead = 2 # the number of heads in the multiheadattention models +dropout = 0.2 # the dropout value +model = TransformerModel(ntokens, emsize, nhead, nhid, nlayers, dropout).to(device) + +``` + +## 运行模型 + +[`CrossEntropyLoss`](https://pytorch.org/docs/master/nn.html?highlight=crossentropyloss#torch.nn.CrossEntropyLoss)用于跟踪损失,[`SGD`](https://pytorch.org/docs/master/optim.html?highlight=sgd#torch.optim.SGD)实现随机梯度下降方法作为优化器。 初始学习率设置为 5.0。 [`StepLR`](https://pytorch.org/docs/master/optim.html?highlight=steplr#torch.optim.lr_scheduler.StepLR)用于通过历时调整学习率。 在训练期间,我们使用[`nn.utils.clip_grad_norm_`](https://pytorch.org/docs/master/nn.html?highlight=nn%20utils%20clip_grad_norm#torch.nn.utils.clip_grad_norm_)函数将所有梯度缩放在一起,以防止爆炸。 + +```py +criterion = nn.CrossEntropyLoss() +lr = 5.0 # learning rate +optimizer = torch.optim.SGD(model.parameters(), lr=lr) +scheduler = torch.optim.lr_scheduler.StepLR(optimizer, 1.0, gamma=0.95) + +import time +def train(): + model.train() # Turn on the train mode + total_loss = 0. + start_time = time.time() + src_mask = model.generate_square_subsequent_mask(bptt).to(device) + for batch, i in enumerate(range(0, train_data.size(0) - 1, bptt)): + data, targets = get_batch(train_data, i) + optimizer.zero_grad() + if data.size(0) != bptt: + src_mask = model.generate_square_subsequent_mask(data.size(0)).to(device) + output = model(data, src_mask) + loss = criterion(output.view(-1, ntokens), targets) + loss.backward() + torch.nn.utils.clip_grad_norm_(model.parameters(), 0.5) + optimizer.step() + + total_loss += loss.item() + log_interval = 200 + if batch % log_interval == 0 and batch > 0: + cur_loss = total_loss / log_interval + elapsed = time.time() - start_time + print('| epoch {:3d} | {:5d}/{:5d} batches | ' + 'lr {:02.2f} | ms/batch {:5.2f} | ' + 'loss {:5.2f} | ppl {:8.2f}'.format( + epoch, batch, len(train_data) // bptt, scheduler.get_lr()[0], + elapsed * 1000 / log_interval, + cur_loss, math.exp(cur_loss))) + total_loss = 0 + start_time = time.time() + +def evaluate(eval_model, data_source): + eval_model.eval() # Turn on the evaluation mode + total_loss = 0. + src_mask = model.generate_square_subsequent_mask(bptt).to(device) + with torch.no_grad(): + for i in range(0, data_source.size(0) - 1, bptt): + data, targets = get_batch(data_source, i) + if data.size(0) != bptt: + src_mask = model.generate_square_subsequent_mask(data.size(0)).to(device) + output = eval_model(data, src_mask) + output_flat = output.view(-1, ntokens) + total_loss += len(data) * criterion(output_flat, targets).item() + return total_loss / (len(data_source) - 1) + +``` + +循环遍历。 如果验证损失是迄今为止迄今为止最好的,请保存模型。 在每个周期之后调整学习率。 + +```py +best_val_loss = float("inf") +epochs = 3 # The number of epochs +best_model = None + +for epoch in range(1, epochs + 1): + epoch_start_time = time.time() + train() + val_loss = evaluate(model, val_data) + print('-' * 89) + print('| end of epoch {:3d} | time: {:5.2f}s | valid loss {:5.2f} | ' + 'valid ppl {:8.2f}'.format(epoch, (time.time() - epoch_start_time), + val_loss, math.exp(val_loss))) + print('-' * 89) + + if val_loss < best_val_loss: + best_val_loss = val_loss + best_model = model + + scheduler.step() + +``` + +出: + +```py +| epoch 1 | 200/ 2928 batches | lr 5.00 | ms/batch 30.78 | loss 8.03 | ppl 3085.47 +| epoch 1 | 400/ 2928 batches | lr 5.00 | ms/batch 29.85 | loss 6.83 | ppl 929.53 +| epoch 1 | 600/ 2928 batches | lr 5.00 | ms/batch 29.92 | loss 6.41 | ppl 610.71 +| epoch 1 | 800/ 2928 batches | lr 5.00 | ms/batch 29.88 | loss 6.29 | ppl 539.54 +| epoch 1 | 1000/ 2928 batches | lr 5.00 | ms/batch 29.95 | loss 6.17 | ppl 479.92 +| epoch 1 | 1200/ 2928 batches | lr 5.00 | ms/batch 29.95 | loss 6.15 | ppl 468.35 +| epoch 1 | 1400/ 2928 batches | lr 5.00 | ms/batch 29.95 | loss 6.11 | ppl 450.25 +| epoch 1 | 1600/ 2928 batches | lr 5.00 | ms/batch 29.95 | loss 6.10 | ppl 445.77 +| epoch 1 | 1800/ 2928 batches | lr 5.00 | ms/batch 29.97 | loss 6.02 | ppl 409.90 +| epoch 1 | 2000/ 2928 batches | lr 5.00 | ms/batch 29.92 | loss 6.01 | ppl 408.66 +| epoch 1 | 2200/ 2928 batches | lr 5.00 | ms/batch 29.94 | loss 5.90 | ppl 363.89 +| epoch 1 | 2400/ 2928 batches | lr 5.00 | ms/batch 29.94 | loss 5.96 | ppl 388.68 +| epoch 1 | 2600/ 2928 batches | lr 5.00 | ms/batch 29.94 | loss 5.95 | ppl 382.60 +| epoch 1 | 2800/ 2928 batches | lr 5.00 | ms/batch 29.95 | loss 5.88 | ppl 358.87 +----------------------------------------------------------------------------------------- +| end of epoch 1 | time: 91.45s | valid loss 5.85 | valid ppl 348.17 +----------------------------------------------------------------------------------------- +| epoch 2 | 200/ 2928 batches | lr 4.51 | ms/batch 30.09 | loss 5.86 | ppl 351.70 +| epoch 2 | 400/ 2928 batches | lr 4.51 | ms/batch 29.97 | loss 5.85 | ppl 347.85 +| epoch 2 | 600/ 2928 batches | lr 4.51 | ms/batch 29.98 | loss 5.67 | ppl 288.80 +| epoch 2 | 800/ 2928 batches | lr 4.51 | ms/batch 29.92 | loss 5.70 | ppl 299.81 +| epoch 2 | 1000/ 2928 batches | lr 4.51 | ms/batch 29.95 | loss 5.65 | ppl 285.57 +| epoch 2 | 1200/ 2928 batches | lr 4.51 | ms/batch 29.99 | loss 5.68 | ppl 293.48 +| epoch 2 | 1400/ 2928 batches | lr 4.51 | ms/batch 29.96 | loss 5.69 | ppl 296.90 +| epoch 2 | 1600/ 2928 batches | lr 4.51 | ms/batch 29.96 | loss 5.72 | ppl 303.83 +| epoch 2 | 1800/ 2928 batches | lr 4.51 | ms/batch 29.93 | loss 5.66 | ppl 285.90 +| epoch 2 | 2000/ 2928 batches | lr 4.51 | ms/batch 29.93 | loss 5.67 | ppl 289.58 +| epoch 2 | 2200/ 2928 batches | lr 4.51 | ms/batch 29.97 | loss 5.55 | ppl 257.20 +| epoch 2 | 2400/ 2928 batches | lr 4.51 | ms/batch 29.96 | loss 5.65 | ppl 283.92 +| epoch 2 | 2600/ 2928 batches | lr 4.51 | ms/batch 29.95 | loss 5.65 | ppl 283.76 +| epoch 2 | 2800/ 2928 batches | lr 4.51 | ms/batch 29.95 | loss 5.60 | ppl 269.90 +----------------------------------------------------------------------------------------- +| end of epoch 2 | time: 91.37s | valid loss 5.60 | valid ppl 270.66 +----------------------------------------------------------------------------------------- +| epoch 3 | 200/ 2928 batches | lr 4.29 | ms/batch 30.12 | loss 5.60 | ppl 269.95 +| epoch 3 | 400/ 2928 batches | lr 4.29 | ms/batch 29.92 | loss 5.62 | ppl 274.84 +| epoch 3 | 600/ 2928 batches | lr 4.29 | ms/batch 29.96 | loss 5.41 | ppl 222.98 +| epoch 3 | 800/ 2928 batches | lr 4.29 | ms/batch 29.93 | loss 5.48 | ppl 240.15 +| epoch 3 | 1000/ 2928 batches | lr 4.29 | ms/batch 29.94 | loss 5.43 | ppl 229.16 +| epoch 3 | 1200/ 2928 batches | lr 4.29 | ms/batch 29.94 | loss 5.48 | ppl 239.42 +| epoch 3 | 1400/ 2928 batches | lr 4.29 | ms/batch 29.95 | loss 5.49 | ppl 242.87 +| epoch 3 | 1600/ 2928 batches | lr 4.29 | ms/batch 29.93 | loss 5.52 | ppl 250.16 +| epoch 3 | 1800/ 2928 batches | lr 4.29 | ms/batch 29.93 | loss 5.47 | ppl 237.70 +| epoch 3 | 2000/ 2928 batches | lr 4.29 | ms/batch 29.94 | loss 5.49 | ppl 241.36 +| epoch 3 | 2200/ 2928 batches | lr 4.29 | ms/batch 29.92 | loss 5.36 | ppl 211.91 +| epoch 3 | 2400/ 2928 batches | lr 4.29 | ms/batch 29.95 | loss 5.47 | ppl 237.16 +| epoch 3 | 2600/ 2928 batches | lr 4.29 | ms/batch 29.94 | loss 5.47 | ppl 236.47 +| epoch 3 | 2800/ 2928 batches | lr 4.29 | ms/batch 29.92 | loss 5.41 | ppl 223.08 +----------------------------------------------------------------------------------------- +| end of epoch 3 | time: 91.32s | valid loss 5.61 | valid ppl 272.10 +----------------------------------------------------------------------------------------- + +``` + +## 使用测试数据集评估模型 + +应用最佳模型以检查测试数据集的结果。 + +```py +test_loss = evaluate(best_model, test_data) +print('=' * 89) +print('| End of training | test loss {:5.2f} | test ppl {:8.2f}'.format( + test_loss, math.exp(test_loss))) +print('=' * 89) + +``` + +出: + +```py +========================================================================================= +| End of training | test loss 5.52 | test ppl 249.05 +========================================================================================= + +``` + +**脚本的总运行时间**:(4 分钟 50.218 秒) + +[下载 Python 源码:`transformer_tutorial.py`](../_downloads/f53285338820248a7c04a947c5110f7b/transformer_tutorial.py) + +[下载 Jupyter 笔记本:`transformer_tutorial.ipynb`](../_downloads/dca13261bbb4e9809d1a3aa521d22dd7/transformer_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/28.md b/pytorch/官方教程/28.md new file mode 100644 index 00000000..8176c3f1 --- /dev/null +++ b/pytorch/官方教程/28.md @@ -0,0 +1,555 @@ +# 从零开始的 NLP:使用字符级 RNN 分类名称 + +> 原文: + +**作者**: [Sean Robertson](https://github.com/spro/practical-pytorch) + +我们将建立和训练基本的字符级 RNN 对单词进行分类。 本教程与以下两个教程一起,展示了如何“从头开始”进行 NLP 建模的预处理数据,特别是不使用`torchtext`的许多便利函数,因此您可以了解 NLP 建模的预处理如何在低水平上工作。 + +字符级 RNN 将单词作为一系列字符读取-在每个步骤输出预测和“隐藏状态”,将其先前的隐藏状态输入到每个下一步。 我们将最终的预测作为输出,即单词属于哪个类别。 + +具体来说,我们将训练来自 18 种起源语言的数千种姓氏,并根据拼写方式预测名称的来源: + +```py +$ python predict.py Hinton +(-0.47) Scottish +(-1.52) English +(-3.57) Irish + +$ python predict.py Schmidhuber +(-0.19) German +(-2.48) Czech +(-2.68) Dutch + +``` + +**推荐读物**: + +我假设您至少已经安装了 PyTorch,Python 和 Tensors: + +* [安装说明](https://pytorch.org/) +* [使用 PyTorch 进行深度学习:60 分钟的突击](../beginner/deep_learning_60min_blitz.html)通常开始使用 PyTorch +* [使用示例学习 PyTorch](../beginner/pytorch_with_examples.html) +* [PyTorch(面向以前的 Torch 用户)](../beginner/former_torchies_tutorial.html)(如果您以前是 Lua Torch 用户) + +了解 RNN 及其工作方式也将很有用: + +* [《循环神经网络的不合理有效性》](https://karpathy.github.io/2015/05/21/rnn-effectiveness/)显示了许多现实生活中的例子 +* [《了解 LSTM 网络》](https://colah.github.io/posts/2015-08-Understanding-LSTMs/)特别是关于 LSTM 的,但一般来说也有关 RNN 的 + +## 准备数据 + +注意 + +从的下载数据,并将其提取到当前目录。 + +`data/names`目录中包含 18 个文本文件,名称为`[Language].txt`。 每个文件包含一堆名称,每行一个名称,大多数是罗马化的(但我们仍然需要从 Unicode 转换为 ASCII)。 + +我们将得到一个字典,其中列出了每种语言的名称列表`{language: [names ...]}`。 通用变量“类别”和“行”(在本例中为语言和名称)用于以后的扩展。 + +```py +from __future__ import unicode_literals, print_function, division +from io import open +import glob +import os + +def findFiles(path): return glob.glob(path) + +print(findFiles('data/names/*.txt')) + +import unicodedata +import string + +all_letters = string.ascii_letters + " .,;'" +n_letters = len(all_letters) + +# Turn a Unicode string to plain ASCII, thanks to https://stackoverflow.com/a/518232/2809427 +def unicodeToAscii(s): + return ''.join( + c for c in unicodedata.normalize('NFD', s) + if unicodedata.category(c) != 'Mn' + and c in all_letters + ) + +print(unicodeToAscii('Ślusàrski')) + +# Build the category_lines dictionary, a list of names per language +category_lines = {} +all_categories = [] + +# Read a file and split into lines +def readLines(filename): + lines = open(filename, encoding='utf-8').read().strip().split('\n') + return [unicodeToAscii(line) for line in lines] + +for filename in findFiles('data/names/*.txt'): + category = os.path.splitext(os.path.basename(filename))[0] + all_categories.append(category) + lines = readLines(filename) + category_lines[category] = lines + +n_categories = len(all_categories) + +``` + +出: + +```py +['data/names/French.txt', 'data/names/Czech.txt', 'data/names/Dutch.txt', 'data/names/Polish.txt', 'data/names/Scottish.txt', 'data/names/Chinese.txt', 'data/names/English.txt', 'data/names/Italian.txt', 'data/names/Portuguese.txt', 'data/names/Japanese.txt', 'data/names/German.txt', 'data/names/Russian.txt', 'data/names/Korean.txt', 'data/names/Arabic.txt', 'data/names/Greek.txt', 'data/names/Vietnamese.txt', 'data/names/Spanish.txt', 'data/names/Irish.txt'] +Slusarski + +``` + +现在我们有了`category_lines`,这是一个字典,将每个类别(语言)映射到行(名称)列表。 我们还跟踪了`all_categories`(只是语言列表)和`n_categories`,以供以后参考。 + +```py +print(category_lines['Italian'][:5]) + +``` + +出: + +```py +['Abandonato', 'Abatangelo', 'Abatantuono', 'Abate', 'Abategiovanni'] + +``` + +### 将名称转换为张量 + +现在我们已经组织了所有名称,我们需要将它们转换为张量以使用它们。 + +为了表示单个字母,我们使用大小为`<1 x n_letters>`的单热向量。 单热向量用 0 填充,但当前字母的索引处的数字为 1,例如 `"b" = <0 1 0 0 0 ...>`。 + +为了制造一个单词,我们将其中的一些连接成 2D 矩阵``。 + +额外的 1 维是因为 PyTorch 假定所有内容都是成批的-在这里我们仅使用 1 的批量大小。 + +```py +import torch + +# Find letter index from all_letters, e.g. "a" = 0 +def letterToIndex(letter): + return all_letters.find(letter) + +# Just for demonstration, turn a letter into a <1 x n_letters> Tensor +def letterToTensor(letter): + tensor = torch.zeros(1, n_letters) + tensor[0][letterToIndex(letter)] = 1 + return tensor + +# Turn a line into a , +# or an array of one-hot letter vectors +def lineToTensor(line): + tensor = torch.zeros(len(line), 1, n_letters) + for li, letter in enumerate(line): + tensor[li][0][letterToIndex(letter)] = 1 + return tensor + +print(letterToTensor('J')) + +print(lineToTensor('Jones').size()) + +``` + +出: + +```py +tensor([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., + 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., + 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., + 0., 0., 0.]]) +torch.Size([5, 1, 57]) + +``` + +## 创建网络 + +在进行自动微分之前,在 Torch 中创建一个循环神经网络涉及在多个时间步长上克隆层的参数。 层保留了隐藏状态和梯度,这些层现在完全由图本身处理。 这意味着您可以非常“纯”的方式将 RNN 用作常规前馈层。 + +该 RNN 模块(主要从[面向 Torch 用户的 PyTorch 教程](https://pytorch.org/tutorials/beginner/former_torchies/nn_tutorial.html#example-2-recurrent-net)复制)只有两个线性层,它们在输入和隐藏状态下运行,在输出之后是`LogSoftmax`层。 + +![](img/592fae78143370fffc1d0c7957706384.png) + +```py +import torch.nn as nn + +class RNN(nn.Module): + def __init__(self, input_size, hidden_size, output_size): + super(RNN, self).__init__() + + self.hidden_size = hidden_size + + self.i2h = nn.Linear(input_size + hidden_size, hidden_size) + self.i2o = nn.Linear(input_size + hidden_size, output_size) + self.softmax = nn.LogSoftmax(dim=1) + + def forward(self, input, hidden): + combined = torch.cat((input, hidden), 1) + hidden = self.i2h(combined) + output = self.i2o(combined) + output = self.softmax(output) + return output, hidden + + def initHidden(self): + return torch.zeros(1, self.hidden_size) + +n_hidden = 128 +rnn = RNN(n_letters, n_hidden, n_categories) + +``` + +要运行此网络的步骤,我们需要传递输入(在本例中为当前字母的张量)和先前的隐藏状态(首先将其初始化为零)。 我们将返回输出(每种语言的概率)和下一个隐藏状态(我们将其保留用于下一步)。 + +```py +input = letterToTensor('A') +hidden =torch.zeros(1, n_hidden) + +output, next_hidden = rnn(input, hidden) + +``` + +为了提高效率,我们不想为每个步骤创建一个新的张量,因此我们将使用`lineToTensor`而不是`letterToTensor`并使用切片。 这可以通过预先计算一批张量来进一步优化。 + +```py +input = lineToTensor('Albert') +hidden = torch.zeros(1, n_hidden) + +output, next_hidden = rnn(input[0], hidden) +print(output) + +``` + +出: + +```py +tensor([[-2.8934, -2.7991, -2.8549, -2.8915, -2.9122, -2.9010, -2.8979, -2.8875, + -2.8256, -2.8792, -2.8712, -2.8465, -2.9582, -3.0171, -2.8308, -2.9629, + -2.9233, -2.8979]], grad_fn=) + +``` + +如您所见,输出为`<1 x n_categories>`张量,其中每个项目都是该类别的可能性(可能性更大)。 + +## 训练 + +### 准备训练 + +在接受训练之前,我们应该做一些辅助函数。 首先是解释网络的输出,我们知道这是每个类别的可能性。 我们可以使用`Tensor.topk`获得最大值的索引: + +```py +def categoryFromOutput(output): + top_n, top_i = output.topk(1) + category_i = top_i[0].item() + return all_categories[category_i], category_i + +print(categoryFromOutput(output)) + +``` + +出: + +```py +('Czech', 1) + +``` + +我们还将希望有一种快速的方法来获取训练示例(名称及其语言): + +```py +import random + +def randomChoice(l): + return l[random.randint(0, len(l) - 1)] + +def randomTrainingExample(): + category = randomChoice(all_categories) + line = randomChoice(category_lines[category]) + category_tensor = torch.tensor([all_categories.index(category)], dtype=torch.long) + line_tensor = lineToTensor(line) + return category, line, category_tensor, line_tensor + +for i in range(10): + category, line, category_tensor, line_tensor = randomTrainingExample() + print('category =', category, '/ line =', line) + +``` + +出: + +```py +category = Chinese / line = Jia +category = Korean / line = Son +category = Czech / line = Matocha +category = Dutch / line = Nifterik +category = German / line = Dreschner +category = Irish / line = Names +category = French / line = Charpentier +category = Italian / line = Carboni +category = Irish / line = Shannon +category = German / line = Adam + +``` + +### 训练网络 + +现在,训练该网络所需要做的就是向它展示大量示例,进行猜测,并告诉它是否错误。 + +对于损失函数,`nn.NLLLoss`是适当的,因为 RNN 的最后一层是`nn.LogSoftmax`。 + +```py +criterion = nn.NLLLoss() + +``` + +每个训练循环将: + +* 创建输入和目标张量 +* 创建归零的初始隐藏状态 +* 阅读每个字母 + * 保存下一个字母的隐藏状态 +* 比较最终输出与目标 +* 反向传播 +* 返回输出和损失 + +```py +learning_rate = 0.005 # If you set this too high, it might explode. If too low, it might not learn + +def train(category_tensor, line_tensor): + hidden = rnn.initHidden() + + rnn.zero_grad() + + for i in range(line_tensor.size()[0]): + output, hidden = rnn(line_tensor[i], hidden) + + loss = criterion(output, category_tensor) + loss.backward() + + # Add parameters' gradients to their values, multiplied by learning rate + for p in rnn.parameters(): + p.data.add_(p.grad.data, alpha=-learning_rate) + + return output, loss.item() + +``` + +现在,我们只需要运行大量示例。 由于`train`函数返回输出和损失,因此我们可以打印其猜测并跟踪作图的损失。 因为有 1000 个示例,所以我们仅打印每个`print_every`示例,并对损失进行平均。 + +```py +import time +import math + +n_iters = 100000 +print_every = 5000 +plot_every = 1000 + +# Keep track of losses for plotting +current_loss = 0 +all_losses = [] + +def timeSince(since): + now = time.time() + s = now - since + m = math.floor(s / 60) + s -= m * 60 + return '%dm %ds' % (m, s) + +start = time.time() + +for iter in range(1, n_iters + 1): + category, line, category_tensor, line_tensor = randomTrainingExample() + output, loss = train(category_tensor, line_tensor) + current_loss += loss + + # Print iter number, loss, name and guess + if iter % print_every == 0: + guess, guess_i = categoryFromOutput(output) + correct = '✓' if guess == category else '✗ (%s)' % category + print('%d %d%% (%s) %.4f %s / %s %s' % (iter, iter / n_iters * 100, timeSince(start), loss, line, guess, correct)) + + # Add current loss avg to list of losses + if iter % plot_every == 0: + all_losses.append(current_loss / plot_every) + current_loss = 0 + +``` + +出: + +```py +5000 5% (0m 15s) 2.5667 Ly / Chinese ✗ (Vietnamese) +10000 10% (0m 26s) 2.3171 Rocha / Japanese ✗ (Portuguese) +15000 15% (0m 37s) 2.2941 Gouveia / Spanish ✗ (Portuguese) +20000 20% (0m 49s) 1.3015 Lippi / Italian ✓ +25000 25% (1m 1s) 0.7693 Thuy / Vietnamese ✓ +30000 30% (1m 13s) 1.9341 Murray / Arabic ✗ (Scottish) +35000 35% (1m 25s) 2.3633 Busto / Scottish ✗ (Italian) +40000 40% (1m 38s) 1.0401 Chung / Chinese ✗ (Korean) +45000 45% (1m 50s) 0.0499 Filipowski / Polish ✓ +50000 50% (2m 2s) 0.2598 Mccallum / Scottish ✓ +55000 55% (2m 14s) 4.5375 Mozdzierz / German ✗ (Polish) +60000 60% (2m 26s) 1.7194 Talalihin / Irish ✗ (Russian) +65000 65% (2m 38s) 0.1150 Ziemniak / Polish ✓ +70000 70% (2m 51s) 1.8548 Pharlain / Scottish ✗ (Irish) +75000 75% (3m 3s) 2.1362 Prehatney / Russian ✗ (Czech) +80000 80% (3m 15s) 0.4166 Leclerc / French ✓ +85000 85% (3m 27s) 1.4189 Elford / English ✓ +90000 90% (3m 39s) 2.1959 Gagnon / Scottish ✗ (French) +95000 95% (3m 51s) 0.1622 Bukoski / Polish ✓ +100000 100% (4m 3s) 1.3180 Faucheux / French ✓ + +``` + +### 绘制结果 + +从`all_losses`绘制历史损失可显示网络学习情况: + +```py +import matplotlib.pyplot as plt +import matplotlib.ticker as ticker + +plt.figure() +plt.plot(all_losses) + +``` + +![../_img/sphx_glr_char_rnn_classification_tutorial_001.png](img/cc57a36a43d450df4bfc1d1d1b1ce274.png) + +## 评估结果 + +为了查看网络在不同类别上的表现如何,我们将创建一个混淆矩阵,为每种实际语言(行)指示网络猜测(列)哪种语言。 为了计算混淆矩阵,使用`evaluate()`通过网络运行一堆样本,该样本等于`train()`减去反向传播器。 + +```py +# Keep track of correct guesses in a confusion matrix +confusion = torch.zeros(n_categories, n_categories) +n_confusion = 10000 + +# Just return an output given a line +def evaluate(line_tensor): + hidden = rnn.initHidden() + + for i in range(line_tensor.size()[0]): + output, hidden = rnn(line_tensor[i], hidden) + + return output + +# Go through a bunch of examples and record which are correctly guessed +for i in range(n_confusion): + category, line, category_tensor, line_tensor = randomTrainingExample() + output = evaluate(line_tensor) + guess, guess_i = categoryFromOutput(output) + category_i = all_categories.index(category) + confusion[category_i][guess_i] += 1 + +# Normalize by dividing every row by its sum +for i in range(n_categories): + confusion[i] = confusion[i] / confusion[i].sum() + +# Set up plot +fig = plt.figure() +ax = fig.add_subplot(111) +cax = ax.matshow(confusion.numpy()) +fig.colorbar(cax) + +# Set up axes +ax.set_xticklabels([''] + all_categories, rotation=90) +ax.set_yticklabels([''] + all_categories) + +# Force label at every tick +ax.xaxis.set_major_locator(ticker.MultipleLocator(1)) +ax.yaxis.set_major_locator(ticker.MultipleLocator(1)) + +# sphinx_gallery_thumbnail_number = 2 +plt.show() + +``` + +![../_img/sphx_glr_char_rnn_classification_tutorial_002.png](img/029a9d26725997aae97e9e3f6f10067f.png) + +您可以从主轴上挑出一些亮点,以显示它猜错了哪些语言,例如中文(朝鲜语)和西班牙语(意大利语)。 它似乎与希腊语搭配得很好,而与英语搭配得很差(可能是因为与其他语言重叠)。 + +### 在用户输入上运行 + +```py +def predict(input_line, n_predictions=3): + print('\n> %s' % input_line) + with torch.no_grad(): + output = evaluate(lineToTensor(input_line)) + + # Get top N categories + topv, topi = output.topk(n_predictions, 1, True) + predictions = [] + + for i in range(n_predictions): + value = topv[0][i].item() + category_index = topi[0][i].item() + print('(%.2f) %s' % (value, all_categories[category_index])) + predictions.append([value, all_categories[category_index]]) + +predict('Dovesky') +predict('Jackson') +predict('Satoshi') + +``` + +出: + +```py +> Dovesky +(-0.82) Russian +(-1.06) Czech +(-2.22) Polish + +> Jackson +(-0.63) English +(-1.75) Scottish +(-1.75) Russian + +> Satoshi +(-0.97) Japanese +(-1.50) Polish +(-2.13) Italian + +``` + +实际 PyTorch 存储库中的脚本的[最终版本](https://github.com/spro/practical-pytorch/tree/master/char-rnn-classification)将上述代码分成几个文件: + +* `data.py`(加载文件) +* `model.py`(定义 RNN) +* `train.py`(进行训练) +* `predict.py`(使用命令行参数运行`predict()`) +* `server.py`(通过`bottle.py`将预测用作 JSON API) + +运行`train.py`训练并保存网络。 + +使用名称运行`predict.py`以查看预测: + +```py +$ python predict.py Hazaki +(-0.42) Japanese +(-1.39) Polish +(-3.51) Czech + +``` + +运行`server.py`并访问`http://localhost:5533/Yourname`以获取预测的 JSON 输出。 + +## 练习 + +* 尝试使用行 -> 类别的其他数据集,例如: + * 任何单词 -> 语言 + * 名称 -> 性别 + * 角色名称 -> 作家 + * 页面标题 -> 博客或 subreddit +* 通过更大和/或形状更好的网络获得更好的结果 + * 添加更多线性层 + * 尝试`nn.LSTM`和`nn.GRU`层 + * 将多个这些 RNN 合并为更高级别的网络 + +**脚本的总运行时间**:(4 分钟 15.239 秒) + +[下载 Python 源码:`char_rnn_classification_tutorial.py`](../_downloads/ccb15f8365bdae22a0a019e57216d7c6/char_rnn_classification_tutorial.py) + +[下载 Jupyter 笔记本:`char_rnn_classification_tutorial.ipynb`](../_downloads/977c14818c75427641ccb85ad21ed6dc/char_rnn_classification_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/29.md b/pytorch/官方教程/29.md new file mode 100644 index 00000000..c3a04041 --- /dev/null +++ b/pytorch/官方教程/29.md @@ -0,0 +1,426 @@ +# 从零开始的 NLP:使用字符级 RNN 生成名称 + +> 原文: + +**作者**: [Sean Robertson](https://github.com/spro/practical-pytorch) + +这是我们关于“从零开始的 NLP”的三个教程中的第二个。 在第一个教程`/intermediate/char_rnn_classification_tutorial`中,我们使用了 RNN 将名称分类为源语言。 这次,我们将转过来并使用语言生成名称。 + +```py +> python sample.py Russian RUS +Rovakov +Uantov +Shavakov + +> python sample.py German GER +Gerren +Ereng +Rosher + +> python sample.py Spanish SPA +Salla +Parer +Allan + +> python sample.py Chinese CHI +Chan +Hang +Iun + +``` + +我们仍在手工制作带有一些线性层的小型 RNN。 最大的区别在于,我们无需输入名称中的所有字母即可预测类别,而是输入类别并一次输出一个字母。 反复预测字符以形成语言(这也可以用单词或其他高阶结构来完成)通常称为“语言模型”。 + +**推荐读物**: + +我假设您至少已经安装了 PyTorch,Python 和张量: + +* [安装说明](https://pytorch.org/) +* [使用 PyTorch 进行深度学习:60 分钟的突击](../beginner/deep_learning_60min_blitz.html)通常开始使用 PyTorch +* [使用示例学习 PyTorch](../beginner/pytorch_with_examples.html) +* [PyTorch(面向以前的 Torch 用户)](../beginner/former_torchies_tutorial.html)(如果您以前是 Lua Torch 用户) + +了解 RNN 及其工作方式也将很有用: + +* [《循环神经网络的不合理有效性》](https://karpathy.github.io/2015/05/21/rnn-effectiveness/)显示了许多现实生活中的例子 +* [《了解 LSTM 网络》](https://colah.github.io/posts/2015-08-Understanding-LSTMs/)特别是关于 LSTM 的,但一般来说也有关 RNN 的 + +我还建议上一教程[《从零开始的 NLP:使用字符级 RNN 对名称进行分类》](char_rnn_classification_tutorial.html) + +## 准备数据 + +注意 + +从的下载数据,并将其提取到当前目录。 + +有关此过程的更多详细信息,请参见上一教程。 简而言之,有一堆纯文本文件`data/names/[Language].txt`,每行都有一个名称。 我们将行拆分成一个数组,将 Unicode 转换为 ASCII,最后得到一个字典`{language: [names ...]}`。 + +```py +from __future__ import unicode_literals, print_function, division +from io import open +import glob +import os +import unicodedata +import string + +all_letters = string.ascii_letters + " .,;'-" +n_letters = len(all_letters) + 1 # Plus EOS marker + +def findFiles(path): return glob.glob(path) + +# Turn a Unicode string to plain ASCII, thanks to https://stackoverflow.com/a/518232/2809427 +def unicodeToAscii(s): + return ''.join( + c for c in unicodedata.normalize('NFD', s) + if unicodedata.category(c) != 'Mn' + and c in all_letters + ) + +# Read a file and split into lines +def readLines(filename): + lines = open(filename, encoding='utf-8').read().strip().split('\n') + return [unicodeToAscii(line) for line in lines] + +# Build the category_lines dictionary, a list of lines per category +category_lines = {} +all_categories = [] +for filename in findFiles('data/names/*.txt'): + category = os.path.splitext(os.path.basename(filename))[0] + all_categories.append(category) + lines = readLines(filename) + category_lines[category] = lines + +n_categories = len(all_categories) + +if n_categories == 0: + raise RuntimeError('Data not found. Make sure that you downloaded data ' + 'from https://download.pytorch.org/tutorial/data.zip and extract it to ' + 'the current directory.') + +print('# categories:', n_categories, all_categories) +print(unicodeToAscii("O'Néàl")) + +``` + +出: + +```py +# categories: 18 ['French', 'Czech', 'Dutch', 'Polish', 'Scottish', 'Chinese', 'English', 'Italian', 'Portuguese', 'Japanese', 'German', 'Russian', 'Korean', 'Arabic', 'Greek', 'Vietnamese', 'Spanish', 'Irish'] +O'Neal + +``` + +## 创建网络 + +该网络扩展[最后一个教程](#Creating-the-Network)的 RNN,并为类别张量附加了一个参数,该参数与其他张量连接在一起。 类别张量就像字母输入一样是一个单向向量。 + +我们将输出解释为下一个字母的概率。 采样时,最可能的输出字母用作下一个输入字母。 + +我添加了第二个线性层`o2o`(在合并了隐藏和输出之后),以使其有更多的肌肉可以使用。 还有一个丢弃层,[以给定的概率](https://arxiv.org/abs/1207.0580)(此处为 0.1)将输入的部分随机归零,通常用于模糊输入以防止过拟合。 在这里,我们在网络的末端使用它来故意添加一些混乱并增加采样种类。 + +![](img/28a4f1426695fb55f1f6bc86278f6547.png) + +```py +import torch +import torch.nn as nn + +class RNN(nn.Module): + def __init__(self, input_size, hidden_size, output_size): + super(RNN, self).__init__() + self.hidden_size = hidden_size + + self.i2h = nn.Linear(n_categories + input_size + hidden_size, hidden_size) + self.i2o = nn.Linear(n_categories + input_size + hidden_size, output_size) + self.o2o = nn.Linear(hidden_size + output_size, output_size) + self.dropout = nn.Dropout(0.1) + self.softmax = nn.LogSoftmax(dim=1) + + def forward(self, category, input, hidden): + input_combined = torch.cat((category, input, hidden), 1) + hidden = self.i2h(input_combined) + output = self.i2o(input_combined) + output_combined = torch.cat((hidden, output), 1) + output = self.o2o(output_combined) + output = self.dropout(output) + output = self.softmax(output) + return output, hidden + + def initHidden(self): + return torch.zeros(1, self.hidden_size) + +``` + +## 训练 + +### 准备训练 + +首先,辅助函数获取随机对(类别,行): + +```py +import random + +# Random item from a list +def randomChoice(l): + return l[random.randint(0, len(l) - 1)] + +# Get a random category and random line from that category +def randomTrainingPair(): + category = randomChoice(all_categories) + line = randomChoice(category_lines[category]) + return category, line + +``` + +对于每个时间步(即,对于训练词中的每个字母),网络的输入将为`(category, current letter, hidden state)`,而输出将为`(next letter, next hidden state)`。 因此,对于每个训练集,我们都需要类别,一组输入字母和一组输出/目标字母。 + +由于我们正在预测每个时间步中当前字母的下一个字母,因此字母对是该行中连续字母的组-例如对于`"ABCD"`,我们将创建`('A', 'B'), ('B', 'C'), ('C', 'D'), ('D', 'EOS')`。 + +![](img/3fae03d85aed3a2237fd4b2f7fb7b480.png) + +类别张量是大小为`<1 x n_categories>`的[单热张量](https://en.wikipedia.org/wiki/One-hot)。 训练时,我们会随时随地将其馈送到网络中-这是一种设计选择,它可能已作为初始隐藏状态或某些其他策略的一部分包含在内。 + +```py +# One-hot vector for category +def categoryTensor(category): + li = all_categories.index(category) + tensor = torch.zeros(1, n_categories) + tensor[0][li] = 1 + return tensor + +# One-hot matrix of first to last letters (not including EOS) for input +def inputTensor(line): + tensor = torch.zeros(len(line), 1, n_letters) + for li in range(len(line)): + letter = line[li] + tensor[li][0][all_letters.find(letter)] = 1 + return tensor + +# LongTensor of second letter to end (EOS) for target +def targetTensor(line): + letter_indexes = [all_letters.find(line[li]) for li in range(1, len(line))] + letter_indexes.append(n_letters - 1) # EOS + return torch.LongTensor(letter_indexes) + +``` + +为了方便训练,我们将使用`randomTrainingExample`函数来获取随机(类别,行)对,并将其转换为所需的(类别,输入,目标)张量。 + +```py +# Make category, input, and target tensors from a random category, line pair +def randomTrainingExample(): + category, line = randomTrainingPair() + category_tensor = categoryTensor(category) + input_line_tensor = inputTensor(line) + target_line_tensor = targetTensor(line) + return category_tensor, input_line_tensor, target_line_tensor + +``` + +### 训练网络 + +与仅使用最后一个输出的分类相反,我们在每个步骤进行预测,因此在每个步骤都计算损失。 + +Autograd 的神奇之处在于,您可以简单地在每个步骤中对这些损失进行求和,然后在末尾调用。 + +```py +criterion = nn.NLLLoss() + +learning_rate = 0.0005 + +def train(category_tensor, input_line_tensor, target_line_tensor): + target_line_tensor.unsqueeze_(-1) + hidden = rnn.initHidden() + + rnn.zero_grad() + + loss = 0 + + for i in range(input_line_tensor.size(0)): + output, hidden = rnn(category_tensor, input_line_tensor[i], hidden) + l = criterion(output, target_line_tensor[i]) + loss += l + + loss.backward() + + for p in rnn.parameters(): + p.data.add_(p.grad.data, alpha=-learning_rate) + + return output, loss.item() / input_line_tensor.size(0) + +``` + +为了跟踪训练需要多长时间,我添加了一个`timeSince(timestamp)`函数,该函数返回人类可读的字符串: + +```py +import time +import math + +def timeSince(since): + now = time.time() + s = now - since + m = math.floor(s / 60) + s -= m * 60 + return '%dm %ds' % (m, s) + +``` + +训练照常进行-召集训练多次并等待几分钟,每`print_every`个示例打印当前时间和损失,并在`all_losses`中保存每个`plot_every`实例的平均损失以供以后绘制。 + +```py +rnn = RNN(n_letters, 128, n_letters) + +n_iters = 100000 +print_every = 5000 +plot_every = 500 +all_losses = [] +total_loss = 0 # Reset every plot_every iters + +start = time.time() + +for iter in range(1, n_iters + 1): + output, loss = train(*randomTrainingExample()) + total_loss += loss + + if iter % print_every == 0: + print('%s (%d %d%%) %.4f' % (timeSince(start), iter, iter / n_iters * 100, loss)) + + if iter % plot_every == 0: + all_losses.append(total_loss / plot_every) + total_loss = 0 + +``` + +出: + +```py +0m 26s (5000 5%) 3.2265 +0m 51s (10000 10%) 3.0171 +1m 16s (15000 15%) 2.1535 +1m 41s (20000 20%) 2.0806 +2m 7s (25000 25%) 2.3842 +2m 32s (30000 30%) 2.5014 +2m 57s (35000 35%) 2.2441 +3m 22s (40000 40%) 2.2113 +3m 47s (45000 45%) 2.1184 +4m 13s (50000 50%) 1.3983 +4m 38s (55000 55%) 2.5881 +5m 3s (60000 60%) 1.8033 +5m 29s (65000 65%) 2.4285 +5m 54s (70000 70%) 2.4198 +6m 20s (75000 75%) 2.9660 +6m 45s (80000 80%) 1.9752 +7m 11s (85000 85%) 3.7507 +7m 36s (90000 90%) 2.2044 +8m 2s (95000 95%) 2.8938 +8m 27s (100000 100%) 2.2471 + +``` + +### 绘制损失图 + +绘制`all_loss`的历史损失可显示网络学习情况: + +```py +import matplotlib.pyplot as plt +import matplotlib.ticker as ticker + +plt.figure() +plt.plot(all_losses) + +``` + +![../_img/sphx_glr_char_rnn_generation_tutorial_001.png](img/5ad82e2b23a82287af2caa2fe4b316b3.png) + +## 网络采样 + +为了示例,我们给网络一个字母,询问下一个字母是什么,将其作为下一个字母输入,并重复直到 EOS 标记。 + +* 为输入类别,起始字母和空隐藏状态创建张量 +* 用起始字母创建一个字符串`output_name` +* 直到最大输出长度, + * 将当前字母输入网络 + * 从最高输出中获取下一个字母,以及下一个隐藏状态 + * 如果字母是`EOS`,请在此处停止 + * 如果是普通字母,请添加到`output_name`并继续 +* 返回姓氏 + +注意 + +不必给它起一个开始字母,另一种策略是在训练中包括一个“字符串开始”标记,并让网络选择自己的开始字母。 + +```py +max_length = 20 + +# Sample from a category and starting letter +def sample(category, start_letter='A'): + with torch.no_grad(): # no need to track history in sampling + category_tensor = categoryTensor(category) + input = inputTensor(start_letter) + hidden = rnn.initHidden() + + output_name = start_letter + + for i in range(max_length): + output, hidden = rnn(category_tensor, input[0], hidden) + topv, topi = output.topk(1) + topi = topi[0][0] + if topi == n_letters - 1: + break + else: + letter = all_letters[topi] + output_name += letter + input = inputTensor(letter) + + return output_name + +# Get multiple samples from one category and multiple starting letters +def samples(category, start_letters='ABC'): + for start_letter in start_letters: + print(sample(category, start_letter)) + +samples('Russian', 'RUS') + +samples('German', 'GER') + +samples('Spanish', 'SPA') + +samples('Chinese', 'CHI') + +``` + +出: + +```py +Rovanov +Uarinov +Santovov +Gangerten +Erer +Roure +Salla +Parera +Allan +Chin +Han +Iun + +``` + +## 练习 + +* 尝试使用类别 -> 行的其他数据集,例如: + * 虚构序列 -> 角色名称 + * 词性 -> 词 + * 国家 -> 城市 +* 使用“句子开头”标记,以便无需选择开始字母即可进行采样 +* 通过更大和/或形状更好的网络获得更好的结果 + * 尝试`nn.LSTM`和`nn.GRU`层 + * 将多个这些 RNN 合并为更高级别的网络 + +**脚本的总运行时间**:(8 分钟 27.431 秒) + +[下载 Python 源码:`char_rnn_generation_tutorial.py`](../_downloads/8167177b6dd8ddf05bb9fe58744ac406/char_rnn_generation_tutorial.py) + +[下载 Jupyter 笔记本:`char_rnn_generation_tutorial.ipynb`](../_downloads/a35c00bb5afae3962e1e7869c66872fa/char_rnn_generation_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/30.md b/pytorch/官方教程/30.md new file mode 100644 index 00000000..6cf9743b --- /dev/null +++ b/pytorch/官方教程/30.md @@ -0,0 +1,794 @@ +# 从零开始的 NLP:使用序列到序列网络和注意力的翻译 + +> 原文: + +**作者**: [Sean Robertson](https://github.com/spro/practical-pytorch) + +这是关于“从头开始进行 NLP”的第三篇也是最后一篇教程,我们在其中编写自己的类和函数来预处理数据以完成 NLP 建模任务。 我们希望在完成本教程后,您将继续学习紧接着本教程的三本教程,`torchtext`如何为您处理许多此类预处理。 + +在这个项目中,我们将教授将法语翻译成英语的神经网络。 + +```py +[KEY: > input, = target, < output] + +> il est en train de peindre un tableau . += he is painting a picture . +< he is painting a picture . + +> pourquoi ne pas essayer ce vin delicieux ? += why not try that delicious wine ? +< why not try that delicious wine ? + +> elle n est pas poete mais romanciere . += she is not a poet but a novelist . +< she not not a poet but a novelist . + +> vous etes trop maigre . += you re too skinny . +< you re all alone . + +``` + +……取得不同程度的成功。 + +通过[序列到序列网络](https://arxiv.org/abs/1409.3215)的简单但强大的构想,使这成为可能,其中两个循环神经网络协同工作,将一个序列转换为另一个序列。 编码器网络将输入序列压缩为一个向量,而解码器网络将该向量展开为一个新序列。 + +![](img/b01274082109b1019682274a0d4ca4d8.png) + +为了改进此模型,我们将使用[注意力机制](https://arxiv.org/abs/1409.0473),该机制可使解码器学会专注于输入序列的特定范围。 + +**推荐读物**: + +我假设您至少已经安装了 PyTorch,Python 和张量: + +* [安装说明](https://pytorch.org/) +* [使用 PyTorch 进行深度学习:60 分钟的突击](../beginner/deep_learning_60min_blitz.html)通常开始使用 PyTorch +* [使用示例]学习 PyTorch(../beginner/pytorch_with_examples.html) +* [PyTorch(面向以前的 Torch 用户)](../beginner/former_torchies_tutorial.html)(如果您以前是 Lua Torch 用户) + +了解序列到序列网络及其工作方式也将很有用: + +* [《使用 RNN 编解码器学习短语表示法进行统计机器翻译》](https://arxiv.org/abs/1406.1078) +* [《序列到神经网络的序列学习》](https://arxiv.org/abs/1409.3215) +* [《通过共同学习对齐和翻译的神经机器翻译》](https://arxiv.org/abs/1409.0473) +* [《神经对话模型》](https://arxiv.org/abs/1506.05869) + +您还将找到有关[《从零开始的 NLP:使用字符级 RNN 分类名称》](char_rnn_classification_tutorial.html)和[《从零开始的 NLP:使用字符级 RNN 生成名称》](char_rnn_generation_tutorial.html)的先前教程。 分别与编码器和解码器模型非常相似。 + +有关更多信息,请阅读介绍以下主题的论文: + +* [《使用 RNN 编解码器学习短语表示法进行统计机器翻译》](https://arxiv.org/abs/1406.1078) +* [《序列到序列神经网络的学习》](https://arxiv.org/abs/1409.3215) +* [《通过共同学习对齐和翻译的神经机器翻译》](https://arxiv.org/abs/1409.0473) +* [《神经对话模型》](https://arxiv.org/abs/1506.05869) + +**要求** + +```py +from __future__ import unicode_literals, print_function, division +from io import open +import unicodedata +import string +import re +import random + +import torch +import torch.nn as nn +from torch import optim +import torch.nn.functional as F + +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + +``` + +## 加载数据文件 + +该项目的数据是成千上万的英语到法语翻译对的集合。 + +[开放数据栈交换](https://opendata.stackexchange.com/questions/3888/dataset-of-sentences-translated-into-many-languages)上的这个问题使我指向[开放翻译站点](https://tatoeba.org/) ,该站点可从[这里](https://tatoeba.org/eng/downloads)下载。更好的是,有人在这里做了一些额外的工作,[将语言对拆分为单独的文本文件](https://www.manythings.org/anki/)。 + +英文对法文对太大,无法包含在仓库中,因此请先下载到`data/eng-fra.txt`,然后再继续。 该文件是制表符分隔的翻译对列表: + +```py +I am cold. J'ai froid. + +``` + +注意 + +从的下载数据,并将其提取到当前目录。 + +与字符级 RNN 教程中使用的字符编码类似,我们将一种语言中的每个单词表示为一个单向向量,或零个大向量(除单个单向索引外)(在单词的索引处)。 与某种语言中可能存在的数十个字符相比,单词更多很多,因此编码向量要大得多。 但是,我们将作弊并整理数据以使每种语言仅使用几千个单词。 + +![](img/7fa129004e942671707f8f2d4fb80a20.png) + +我们将需要每个单词一个唯一的索引,以便以后用作网络的输入和目标。 为了跟踪所有这些,我们将使用一个名为`Lang`的帮助程序类,该类具有单词→索引(`word2index`)和索引→单词(`index2word`)字典,以及每个要使用的单词`word2count`的计数,以便以后替换稀有词。 + +```py +SOS_token = 0 +EOS_token = 1 + +class Lang: + def __init__(self, name): + self.name = name + self.word2index = {} + self.word2count = {} + self.index2word = {0: "SOS", 1: "EOS"} + self.n_words = 2 # Count SOS and EOS + + def addSentence(self, sentence): + for word in sentence.split(' '): + self.addWord(word) + + def addWord(self, word): + if word not in self.word2index: + self.word2index[word] = self.n_words + self.word2count[word] = 1 + self.index2word[self.n_words] = word + self.n_words += 1 + else: + self.word2count[word] += 1 + +``` + +文件全部为 Unicode,为简化起见,我们将 Unicode 字符转换为 ASCII,将所有内容都转换为小写,并修剪大多数标点符号。 + +```py +# Turn a Unicode string to plain ASCII, thanks to +# https://stackoverflow.com/a/518232/2809427 +def unicodeToAscii(s): + return ''.join( + c for c in unicodedata.normalize('NFD', s) + if unicodedata.category(c) != 'Mn' + ) + +# Lowercase, trim, and remove non-letter characters + +def normalizeString(s): + s = unicodeToAscii(s.lower().strip()) + s = re.sub(r"([.!?])", r" \1", s) + s = re.sub(r"[^a-zA-Z.!?]+", r" ", s) + return s + +``` + +要读取数据文件,我们将文件拆分为几行,然后将几行拆分为两对。 这些文件都是英语→其他语言的,因此,如果我们要从其他语言→英语进行翻译,我添加了`reverse`标志来反转对。 + +```py +def readLangs(lang1, lang2, reverse=False): + print("Reading lines...") + + # Read the file and split into lines + lines = open('data/%s-%s.txt' % (lang1, lang2), encoding='utf-8').\ + read().strip().split('\n') + + # Split every line into pairs and normalize + pairs = [[normalizeString(s) for s in l.split('\t')] for l in lines] + + # Reverse pairs, make Lang instances + if reverse: + pairs = [list(reversed(p)) for p in pairs] + input_lang = Lang(lang2) + output_lang = Lang(lang1) + else: + input_lang = Lang(lang1) + output_lang = Lang(lang2) + + return input_lang, output_lang, pairs + +``` + +由于示例句子有很多,并且我们想快速训练一些东西,因此我们将数据集修剪为仅相对简短的句子。 在这里,最大长度为 10 个字(包括结尾的标点符号),我们正在过滤翻译成“我是”或“他是”等形式的句子(考虑到前面已替换掉撇号的情况)。 + +```py +MAX_LENGTH = 10 + +eng_prefixes = ( + "i am ", "i m ", + "he is", "he s ", + "she is", "she s ", + "you are", "you re ", + "we are", "we re ", + "they are", "they re " +) + +def filterPair(p): + return len(p[0].split(' ')) < MAX_LENGTH and \ + len(p[1].split(' ')) < MAX_LENGTH and \ + p[1].startswith(eng_prefixes) + +def filterPairs(pairs): + return [pair for pair in pairs if filterPair(pair)] + +``` + +准备数据的完整过程是: + +* 读取文本文件并拆分为行,将行拆分为偶对 +* 规范文本,按长度和内容过滤 +* 成对建立句子中的单词列表 + +```py +def prepareData(lang1, lang2, reverse=False): + input_lang, output_lang, pairs = readLangs(lang1, lang2, reverse) + print("Read %s sentence pairs" % len(pairs)) + pairs = filterPairs(pairs) + print("Trimmed to %s sentence pairs" % len(pairs)) + print("Counting words...") + for pair in pairs: + input_lang.addSentence(pair[0]) + output_lang.addSentence(pair[1]) + print("Counted words:") + print(input_lang.name, input_lang.n_words) + print(output_lang.name, output_lang.n_words) + return input_lang, output_lang, pairs + +input_lang, output_lang, pairs = prepareData('eng', 'fra', True) +print(random.choice(pairs)) + +``` + +出: + +```py +Reading lines... +Read 135842 sentence pairs +Trimmed to 10599 sentence pairs +Counting words... +Counted words: +fra 4345 +eng 2803 +['il a l habitude des ordinateurs .', 'he is familiar with computers .'] + +``` + +## Seq2Seq 模型 + +循环神经网络(RNN)是在序列上运行并将其自身的输出用作后续步骤的输入的网络。 + +[序列到序列网络](https://arxiv.org/abs/1409.3215)或 seq2seq 网络或[编码器解码器网络](https://arxiv.org/pdf/1406.1078v3.pdf)是由两个称为编码器和解码器的 RNN 组成的模型。 编码器读取输入序列并输出单个向量,而解码器读取该向量以产生输出序列。 + +![](img/b01274082109b1019682274a0d4ca4d8.png) + +与使用单个 RNN 进行序列预测(每个输入对应一个输出)不同,seq2seq 模型使我们摆脱了序列长度和顺序的限制,这使其非常适合两种语言之间的翻译。 + +考虑一下句子`Je ne suis pas le chat noir -> I am not the black cat`。 输入句子中的大多数单词在输出句子中具有直接翻译,但是顺序略有不同,例如`chat noir`和`black cat`。 由于采用`ne/pas`结构,因此在输入句子中还有一个单词。 直接从输入单词的序列中产生正确的翻译将是困难的。 + +使用 seq2seq 模型,编码器创建单个向量,在理想情况下,该向量将输入序列的“含义”编码为单个向量—在句子的 N 维空间中的单个点。 + +### 编码器 + +seq2seq 网络的编码器是 RNN,它为输入句子中的每个单词输出一些值。 对于每个输入字,编码器输出一个向量和一个隐藏状态,并将隐藏状态用于下一个输入字。 + +![](img/9b7e299515676cf41cd2c0fd6ab1295d.png) + +```py +class EncoderRNN(nn.Module): + def __init__(self, input_size, hidden_size): + super(EncoderRNN, self).__init__() + self.hidden_size = hidden_size + + self.embedding = nn.Embedding(input_size, hidden_size) + self.gru = nn.GRU(hidden_size, hidden_size) + + def forward(self, input, hidden): + embedded = self.embedding(input).view(1, 1, -1) + output = embedded + output, hidden = self.gru(output, hidden) + return output, hidden + + def initHidden(self): + return torch.zeros(1, 1, self.hidden_size, device=device) + +``` + +### 解码器 + +解码器是另一个 RNN,它采用编码器输出向量并输出单词序列来创建翻译。 + +#### 简单解码器 + +在最简单的 seq2seq 解码器中,我们仅使用编码器的最后一个输出。 该最后的输出有时称为*上下文向量*,因为它从整个序列中编码上下文。 该上下文向量用作解码器的初始隐藏状态。 + +在解码的每个步骤中,为解码器提供输入标记和隐藏状态。 初始输入标记是字符串开始``标记,第一个隐藏状态是上下文向量(编码器的最后一个隐藏状态)。 + +![](img/34b376e0c7299810f7349ab99c2c5497.png) + +```py +class DecoderRNN(nn.Module): + def __init__(self, hidden_size, output_size): + super(DecoderRNN, self).__init__() + self.hidden_size = hidden_size + + self.embedding = nn.Embedding(output_size, hidden_size) + self.gru = nn.GRU(hidden_size, hidden_size) + self.out = nn.Linear(hidden_size, output_size) + self.softmax = nn.LogSoftmax(dim=1) + + def forward(self, input, hidden): + output = self.embedding(input).view(1, 1, -1) + output = F.relu(output) + output, hidden = self.gru(output, hidden) + output = self.softmax(self.out(output[0])) + return output, hidden + + def initHidden(self): + return torch.zeros(1, 1, self.hidden_size, device=device) + +``` + +我鼓励您训练并观察该模型的结果,但是为了节省空间,我们将直接努力并引入注意力机制。 + +#### 注意力解码器 + +如果仅上下文向量在编码器和解码器之间传递,则该单个向量承担对整个句子进行编码的负担。 + +注意使解码器网络可以针对解码器自身输出的每一步,“专注”于编码器输出的不同部分。 首先,我们计算一组*注意力权重*。 将这些与编码器输出向量相乘以创建加权组合。 结果(在代码中称为`attn_applied`)应包含有关输入序列特定部分的信息,从而帮助解码器选择正确的输出字。 + +![](img/3313f4800c7d01049e2a2ef2079e5905.png) + +另一个前馈层`attn`使用解码器的输入和隐藏状态作为输入来计算注意力权重。 由于训练数据中包含各种大小的句子,因此要实际创建和训练该层,我们必须选择可以应用的最大句子长度(输入长度​​,用于编码器输出)。 最大长度的句子将使用所有注意权重,而较短的句子将仅使用前几个。 + +![](img/32ec68a6e0d29efae32b0f50db877598.png) + +```py +class AttnDecoderRNN(nn.Module): + def __init__(self, hidden_size, output_size, dropout_p=0.1, max_length=MAX_LENGTH): + super(AttnDecoderRNN, self).__init__() + self.hidden_size = hidden_size + self.output_size = output_size + self.dropout_p = dropout_p + self.max_length = max_length + + self.embedding = nn.Embedding(self.output_size, self.hidden_size) + self.attn = nn.Linear(self.hidden_size * 2, self.max_length) + self.attn_combine = nn.Linear(self.hidden_size * 2, self.hidden_size) + self.dropout = nn.Dropout(self.dropout_p) + self.gru = nn.GRU(self.hidden_size, self.hidden_size) + self.out = nn.Linear(self.hidden_size, self.output_size) + + def forward(self, input, hidden, encoder_outputs): + embedded = self.embedding(input).view(1, 1, -1) + embedded = self.dropout(embedded) + + attn_weights = F.softmax( + self.attn(torch.cat((embedded[0], hidden[0]), 1)), dim=1) + attn_applied = torch.bmm(attn_weights.unsqueeze(0), + encoder_outputs.unsqueeze(0)) + + output = torch.cat((embedded[0], attn_applied[0]), 1) + output = self.attn_combine(output).unsqueeze(0) + + output = F.relu(output) + output, hidden = self.gru(output, hidden) + + output = F.log_softmax(self.out(output[0]), dim=1) + return output, hidden, attn_weights + + def initHidden(self): + return torch.zeros(1, 1, self.hidden_size, device=device) + +``` + +注意 + +还有其他形式的注意,可以通过使用相对位置方法来解决长度限制问题。 在[《基于注意力的神经机器翻译的有效方法》](https://arxiv.org/abs/1508.04025)中阅读“本地注意力”。 + +## 训练 + +### 准备训练数据 + +为了训练,对于每一对,我们将需要一个输入张量(输入句子中单词的索引)和目标张量(目标句子中单词的索引)。 创建这些向量时,我们会将`EOS`标记附加到两个序列上。 + +```py +def indexesFromSentence(lang, sentence): + return [lang.word2index[word] for word in sentence.split(' ')] + +def tensorFromSentence(lang, sentence): + indexes = indexesFromSentence(lang, sentence) + indexes.append(EOS_token) + return torch.tensor(indexes, dtype=torch.long, device=device).view(-1, 1) + +def tensorsFromPair(pair): + input_tensor = tensorFromSentence(input_lang, pair[0]) + target_tensor = tensorFromSentence(output_lang, pair[1]) + return (input_tensor, target_tensor) + +``` + +### 训练模型 + +为了训练,我们通过编码器运行输入语句,并跟踪每个输出和最新的隐藏状态。 然后,为解码器提供``标记作为其第一个输入,为编码器提供最后的隐藏状态作为其第一个隐藏状态。 + +“教师强制”的概念是使用实际目标输出作为每个下一个输入,而不是使用解码器的猜测作为下一个输入。 使用教师强制会导致其收敛更快,但是当使用受过训练的网络时,[可能会显示不稳定](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.378.4095&rep=rep1&type=pdf)。 + +您可以观察到以教师为主导的网络的输出,这些输出阅读的是连贯的语法,但是却偏离了正确的翻译-直观地,它已经学会了代表输出语法,并且一旦老师说了最初的几个单词就可以“理解”含义,但是首先,它还没有正确地学习如何从翻译中创建句子。 + +由于 PyTorch 的 Autograd 具有给我们的自由,我们可以通过简单的`if`语句随意选择是否使用教师强迫。 调高`teacher_forcing_ratio`以使用更多。 + +```py +teacher_forcing_ratio = 0.5 + +def train(input_tensor, target_tensor, encoder, decoder, encoder_optimizer, decoder_optimizer, criterion, max_length=MAX_LENGTH): + encoder_hidden = encoder.initHidden() + + encoder_optimizer.zero_grad() + decoder_optimizer.zero_grad() + + input_length = input_tensor.size(0) + target_length = target_tensor.size(0) + + encoder_outputs = torch.zeros(max_length, encoder.hidden_size, device=device) + + loss = 0 + + for ei in range(input_length): + encoder_output, encoder_hidden = encoder( + input_tensor[ei], encoder_hidden) + encoder_outputs[ei] = encoder_output[0, 0] + + decoder_input = torch.tensor([[SOS_token]], device=device) + + decoder_hidden = encoder_hidden + + use_teacher_forcing = True if random.random() < teacher_forcing_ratio else False + + if use_teacher_forcing: + # Teacher forcing: Feed the target as the next input + for di in range(target_length): + decoder_output, decoder_hidden, decoder_attention = decoder( + decoder_input, decoder_hidden, encoder_outputs) + loss += criterion(decoder_output, target_tensor[di]) + decoder_input = target_tensor[di] # Teacher forcing + + else: + # Without teacher forcing: use its own predictions as the next input + for di in range(target_length): + decoder_output, decoder_hidden, decoder_attention = decoder( + decoder_input, decoder_hidden, encoder_outputs) + topv, topi = decoder_output.topk(1) + decoder_input = topi.squeeze().detach() # detach from history as input + + loss += criterion(decoder_output, target_tensor[di]) + if decoder_input.item() == EOS_token: + break + + loss.backward() + + encoder_optimizer.step() + decoder_optimizer.step() + + return loss.item() / target_length + +``` + +这是一个帮助函数,用于在给定当前时间和进度% 的情况下打印经过的时间和估计的剩余时间。 + +```py +import time +import math + +def asMinutes(s): + m = math.floor(s / 60) + s -= m * 60 + return '%dm %ds' % (m, s) + +def timeSince(since, percent): + now = time.time() + s = now - since + es = s / (percent) + rs = es - s + return '%s (- %s)' % (asMinutes(s), asMinutes(rs)) + +``` + +整个训练过程如下所示: + +* 启动计时器 +* 初始化优化器和标准 +* 创建一组训练对 +* 启动空损失数组进行绘图 + +然后,我们多次调用`train`,并偶尔打印进度(示例的百分比,到目前为止的时间,估计的时间)和平均损失。 + +```py +def trainIters(encoder, decoder, n_iters, print_every=1000, plot_every=100, learning_rate=0.01): + start = time.time() + plot_losses = [] + print_loss_total = 0 # Reset every print_every + plot_loss_total = 0 # Reset every plot_every + + encoder_optimizer = optim.SGD(encoder.parameters(), lr=learning_rate) + decoder_optimizer = optim.SGD(decoder.parameters(), lr=learning_rate) + training_pairs = [tensorsFromPair(random.choice(pairs)) + for i in range(n_iters)] + criterion = nn.NLLLoss() + + for iter in range(1, n_iters + 1): + training_pair = training_pairs[iter - 1] + input_tensor = training_pair[0] + target_tensor = training_pair[1] + + loss = train(input_tensor, target_tensor, encoder, + decoder, encoder_optimizer, decoder_optimizer, criterion) + print_loss_total += loss + plot_loss_total += loss + + if iter % print_every == 0: + print_loss_avg = print_loss_total / print_every + print_loss_total = 0 + print('%s (%d %d%%) %.4f' % (timeSince(start, iter / n_iters), + iter, iter / n_iters * 100, print_loss_avg)) + + if iter % plot_every == 0: + plot_loss_avg = plot_loss_total / plot_every + plot_losses.append(plot_loss_avg) + plot_loss_total = 0 + + showPlot(plot_losses) + +``` + +### 绘制结果 + +使用训练时保存的损失值数组`plot_losses`,使用 matplotlib 进行绘制。 + +```py +import matplotlib.pyplot as plt +plt.switch_backend('agg') +import matplotlib.ticker as ticker +import numpy as np + +def showPlot(points): + plt.figure() + fig, ax = plt.subplots() + # this locator puts ticks at regular intervals + loc = ticker.MultipleLocator(base=0.2) + ax.yaxis.set_major_locator(loc) + plt.plot(points) + +``` + +## 评估 + +评估与训练基本相同,但是没有目标,因此我们只需将解码器的预测反馈给每一步。 每当它预测一个单词时,我们都会将其添加到输出字符串中,如果它预测到`EOS`标记,我们将在此处停止。 我们还将存储解码器的注意输出,以供以后显示。 + +```py +def evaluate(encoder, decoder, sentence, max_length=MAX_LENGTH): + with torch.no_grad(): + input_tensor = tensorFromSentence(input_lang, sentence) + input_length = input_tensor.size()[0] + encoder_hidden = encoder.initHidden() + + encoder_outputs = torch.zeros(max_length, encoder.hidden_size, device=device) + + for ei in range(input_length): + encoder_output, encoder_hidden = encoder(input_tensor[ei], + encoder_hidden) + encoder_outputs[ei] += encoder_output[0, 0] + + decoder_input = torch.tensor([[SOS_token]], device=device) # SOS + + decoder_hidden = encoder_hidden + + decoded_words = [] + decoder_attentions = torch.zeros(max_length, max_length) + + for di in range(max_length): + decoder_output, decoder_hidden, decoder_attention = decoder( + decoder_input, decoder_hidden, encoder_outputs) + decoder_attentions[di] = decoder_attention.data + topv, topi = decoder_output.data.topk(1) + if topi.item() == EOS_token: + decoded_words.append('') + break + else: + decoded_words.append(output_lang.index2word[topi.item()]) + + decoder_input = topi.squeeze().detach() + + return decoded_words, decoder_attentions[:di + 1] + +``` + +我们可以从训练集中评估随机句子,并打印出输入,目标和输出以做出一些主观的质量判断: + +```py +def evaluateRandomly(encoder, decoder, n=10): + for i in range(n): + pair = random.choice(pairs) + print('>', pair[0]) + print('=', pair[1]) + output_words, attentions = evaluate(encoder, decoder, pair[0]) + output_sentence = ' '.join(output_words) + print('<', output_sentence) + print('') + +``` + +## 训练和评估 + +有了所有这些辅助函数(看起来像是额外的工作,但它使运行多个实验更加容易),我们实际上可以初始化网络并开始训练。 + +请记住,输入语句已被大量过滤。 对于这个小的数据集,我们可以使用具有 256 个隐藏节点和单个 GRU 层的相对较小的网络。 在 MacBook CPU 上运行约 40 分钟后,我们会得到一些合理的结果。 + +注意 + +如果运行此笔记本,则可以进行训练,中断内核,评估并在以后继续训练。 注释掉编码器和解码器已初始化的行,然后再次运行`trainIters`。 + +```py +hidden_size = 256 +encoder1 = EncoderRNN(input_lang.n_words, hidden_size).to(device) +attn_decoder1 = AttnDecoderRNN(hidden_size, output_lang.n_words, dropout_p=0.1).to(device) + +trainIters(encoder1, attn_decoder1, 75000, print_every=5000) + +``` + +* ![../_img/sphx_glr_seq2seq_translation_tutorial_001.png](img/5015200eb4481feb8a71a658b384ec39.png) +* ![../_img/sphx_glr_seq2seq_translation_tutorial_002.png](img/89adff7333b116436cf785388029ba1a.png) + +出: + +```py +2m 6s (- 29m 28s) (5000 6%) 2.8538 +4m 7s (- 26m 49s) (10000 13%) 2.3035 +6m 10s (- 24m 40s) (15000 20%) 1.9812 +8m 13s (- 22m 37s) (20000 26%) 1.7083 +10m 15s (- 20m 31s) (25000 33%) 1.5199 +12m 17s (- 18m 26s) (30000 40%) 1.3580 +14m 18s (- 16m 20s) (35000 46%) 1.2002 +16m 18s (- 14m 16s) (40000 53%) 1.0832 +18m 21s (- 12m 14s) (45000 60%) 0.9719 +20m 22s (- 10m 11s) (50000 66%) 0.8879 +22m 23s (- 8m 8s) (55000 73%) 0.8130 +24m 25s (- 6m 6s) (60000 80%) 0.7509 +26m 27s (- 4m 4s) (65000 86%) 0.6524 +28m 27s (- 2m 1s) (70000 93%) 0.6007 +30m 30s (- 0m 0s) (75000 100%) 0.5699 + +``` + +```py +evaluateRandomly(encoder1, attn_decoder1) + +``` + +出: + +```py +> nous sommes desolees . += we re sorry . +< we re sorry . + +> tu plaisantes bien sur . += you re joking of course . +< you re joking of course . + +> vous etes trop stupide pour vivre . += you re too stupid to live . +< you re too stupid to live . + +> c est un scientifique de niveau international . += he s a world class scientist . +< he is a successful person . + +> j agis pour mon pere . += i am acting for my father . +< i m trying to my father . + +> ils courent maintenant . += they are running now . +< they are running now . + +> je suis tres heureux d etre ici . += i m very happy to be here . +< i m very happy to be here . + +> vous etes bonne . += you re good . +< you re good . + +> il a peur de la mort . += he is afraid of death . +< he is afraid of death . + +> je suis determine a devenir un scientifique . += i am determined to be a scientist . +< i m ready to make a cold . + +``` + +### 可视化注意力 + +注意力机制的一个有用特性是其高度可解释的输出。 因为它用于加权输入序列的特定编码器输出,所以我们可以想象一下在每个时间步长上网络最关注的位置。 + +您可以简单地运行`plt.matshow(attentions)`以将注意力输出显示为矩阵,其中列为输入步骤,行为输出步骤: + +```py +output_words, attentions = evaluate( + encoder1, attn_decoder1, "je suis trop froid .") +plt.matshow(attentions.numpy()) + +``` + +![../_img/sphx_glr_seq2seq_translation_tutorial_003.png](img/5412faceb18bc6fa2823be3ae1bdfd8d.png) + +为了获得更好的观看体验,我们将做一些额外的工作来添加轴和标签: + +```py +def showAttention(input_sentence, output_words, attentions): + # Set up figure with colorbar + fig = plt.figure() + ax = fig.add_subplot(111) + cax = ax.matshow(attentions.numpy(), cmap='bone') + fig.colorbar(cax) + + # Set up axes + ax.set_xticklabels([''] + input_sentence.split(' ') + + [''], rotation=90) + ax.set_yticklabels([''] + output_words) + + # Show label at every tick + ax.xaxis.set_major_locator(ticker.MultipleLocator(1)) + ax.yaxis.set_major_locator(ticker.MultipleLocator(1)) + + plt.show() + +def evaluateAndShowAttention(input_sentence): + output_words, attentions = evaluate( + encoder1, attn_decoder1, input_sentence) + print('input =', input_sentence) + print('output =', ' '.join(output_words)) + showAttention(input_sentence, output_words, attentions) + +evaluateAndShowAttention("elle a cinq ans de moins que moi .") + +evaluateAndShowAttention("elle est trop petit .") + +evaluateAndShowAttention("je ne crains pas de mourir .") + +evaluateAndShowAttention("c est un jeune directeur plein de talent .") + +``` + +* ![../_img/sphx_glr_seq2seq_translation_tutorial_004.png](img/6e09db671ada03c61bdd1f32b6a7624b.png) +* ![../_img/sphx_glr_seq2seq_translation_tutorial_005.png](img/08bcfed65e8ab03ac7f380e20d421434.png) +* ![../_img/sphx_glr_seq2seq_translation_tutorial_006.png](img/b1ba956974f3e844b0b0cea490cc1148.png) +* ![../_img/sphx_glr_seq2seq_translation_tutorial_007.png](img/1226e2e8b7633b50c2c45ce699d8f71f.png) + +出: + +```py +input = elle a cinq ans de moins que moi . +output = she s five years younger than i am . +input = elle est trop petit . +output = she s too loud . +input = je ne crains pas de mourir . +output = i m not scared to die . +input = c est un jeune directeur plein de talent . +output = he s a talented young writer . + +``` + +## 练习 + +* 尝试使用其他数据集 + * 另一对语言 + * 人机 → 机器(例如 IOT 命令) + * 聊天 → 回复 + * 问题 → 答案 +* 用预训练的单词嵌入(例如 word2vec 或 GloVe)替换嵌入 +* 尝试使用更多的层,更多的隐藏单元和更多的句子。 比较训练时间和结果。 +* 如果您使用翻译对,其中成对具有两个相同的词组(`I am test \t I am test`),则可以将其用作自编码器。 尝试这个: + * 训练为自编码器 + * 仅保存编码器网络 + * 从那里训练新的解码器进行翻译 + +**脚本的总运行时间**:(30 分钟 37.929 秒) + +[下载 Python 源码:`seq2seq_translation_tutorial.py`](../_downloads/a96a2daac1918ec72f68233dfe3f2c47/seq2seq_translation_tutorial.py) + +[下载 Jupyter 笔记本:`seq2seq_translation_tutorial.ipynb`](../_downloads/a60617788061539b5449701ae76aee56/seq2seq_translation_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/31.md b/pytorch/官方教程/31.md new file mode 100644 index 00000000..45173424 --- /dev/null +++ b/pytorch/官方教程/31.md @@ -0,0 +1,348 @@ +# 使用`torchtext`的文本分类 + +> 原文: + +本教程说明如何使用`torchtext`中的文本分类数据集,包括 + +```py +- AG_NEWS, +- SogouNews, +- DBpedia, +- YelpReviewPolarity, +- YelpReviewFull, +- YahooAnswers, +- AmazonReviewPolarity, +- AmazonReviewFull + +``` + +此示例显示了如何使用这些`TextClassification`数据集之一训练用于分类的监督学习算法。 + +## 使用 N 元组加载数据 + +一袋 N 元组特征用于捕获有关本地单词顺序的一些部分信息。 在实践中,应用二元语法或三元语法作为单词组比仅一个单词提供更多的好处。 一个例子: + +```py +"load data with ngrams" +Bi-grams results: "load data", "data with", "with ngrams" +Tri-grams results: "load data with", "data with ngrams" + +``` + +`TextClassification`数据集支持`ngrams`方法。 通过将`ngrams`设置为 2,数据集中的示例文本将是一个单字加二元组字符串的列表。 + +```py +import torch +import torchtext +from torchtext.datasets import text_classification +NGRAMS = 2 +import os +if not os.path.isdir('./.data'): + os.mkdir('./.data') +train_dataset, test_dataset = text_classification.DATASETS['AG_NEWS']( + root='./.data', ngrams=NGRAMS, vocab=None) +BATCH_SIZE = 16 +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + +``` + +## 定义模型 + +该模型由[`EmbeddingBag`](https://pytorch.org/docs/stable/nn.html?highlight=embeddingbag#torch.nn.EmbeddingBag)层和线性层组成(请参见下图)。 `nn.EmbeddingBag`计算嵌入“袋”的平均值。 此处的文本条目具有不同的长度。 `nn.EmbeddingBag`此处不需要填充,因为文本长度以偏移量保存。 + +另外,由于`nn.EmbeddingBag`会动态累积嵌入中的平均值,因此`nn.EmbeddingBag`可以提高性能和存储效率,以处理张量序列。 + +![../_img/text_sentiment_ngrams_model.png](img/30f766e7717c0e45a583a4f58ebc322a.png) + +```py +import torch.nn as nn +import torch.nn.functional as F +class TextSentiment(nn.Module): + def __init__(self, vocab_size, embed_dim, num_class): + super().__init__() + self.embedding = nn.EmbeddingBag(vocab_size, embed_dim, sparse=True) + self.fc = nn.Linear(embed_dim, num_class) + self.init_weights() + + def init_weights(self): + initrange = 0.5 + self.embedding.weight.data.uniform_(-initrange, initrange) + self.fc.weight.data.uniform_(-initrange, initrange) + self.fc.bias.data.zero_() + + def forward(self, text, offsets): + embedded = self.embedding(text, offsets) + return self.fc(embedded) + +``` + +## 启动实例 + +`AG_NEWS`数据集具有四个标签,因此类别数是四个。 + +```py +1 : World +2 : Sports +3 : Business +4 : Sci/Tec + +``` + +词汇的大小等于词汇的长度(包括单个单词和 N 元组)。 类的数量等于标签的数量,在`AG_NEWS`情况下为 4。 + +```py +VOCAB_SIZE = len(train_dataset.get_vocab()) +EMBED_DIM = 32 +NUN_CLASS = len(train_dataset.get_labels()) +model = TextSentiment(VOCAB_SIZE, EMBED_DIM, NUN_CLASS).to(device) + +``` + +## 用于生成批量的函数 + +由于文本条目的长度不同,因此使用自定义函数`generate_batch()`生成数据批和偏移量。 该函数被传递到`torch.utils.data.DataLoader`中的`collate_fn`。 `collate_fn`的输入是张量列表,其大小为`batch_size`,`collate_fn`函数将它们打包成一个小批量。 请注意此处,并确保将`collate_fn`声明为顶级`def`。 这样可以确保该函数在每个工作程序中均可用。 + +原始数据批量输入中的文本条目打包到一个列表中,并作为单个张量级联,作为`nn.EmbeddingBag`的输入。 偏移量是定界符的张量,表示文本张量中各个序列的起始索引。 `Label`是一个张量,用于保存单个文本条目的标签。 + +```py +def generate_batch(batch): + label = torch.tensor([entry[0] for entry in batch]) + text = [entry[1] for entry in batch] + offsets = [0] + [len(entry) for entry in text] + # torch.Tensor.cumsum returns the cumulative sum + # of elements in the dimension dim. + # torch.Tensor([1.0, 2.0, 3.0]).cumsum(dim=0) + + offsets = torch.tensor(offsets[:-1]).cumsum(dim=0) + text = torch.cat(text) + return text, offsets, label + +``` + +## 定义函数来训练模型并评估结果 + +建议 PyTorch 用户使用[`torch.utils.data.DataLoader`](https://pytorch.org/docs/stable/data.html?highlight=dataloader#torch.utils.data.DataLoader),它可以轻松地并行加载数据([教程在这里](https://pytorch.org/tutorials/beginner/data_loading_tutorial.html))。 我们在此处使用`DataLoader`加载`AG_NEWS`数据集,并将其发送到模型以进行训练/验证。 + +```py +from torch.utils.data import DataLoader + +def train_func(sub_train_): + + # Train the model + train_loss = 0 + train_acc = 0 + data = DataLoader(sub_train_, batch_size=BATCH_SIZE, shuffle=True, + collate_fn=generate_batch) + for i, (text, offsets, cls) in enumerate(data): + optimizer.zero_grad() + text, offsets, cls = text.to(device), offsets.to(device), cls.to(device) + output = model(text, offsets) + loss = criterion(output, cls) + train_loss += loss.item() + loss.backward() + optimizer.step() + train_acc += (output.argmax(1) == cls).sum().item() + + # Adjust the learning rate + scheduler.step() + + return train_loss / len(sub_train_), train_acc / len(sub_train_) + +def test(data_): + loss = 0 + acc = 0 + data = DataLoader(data_, batch_size=BATCH_SIZE, collate_fn=generate_batch) + for text, offsets, cls in data: + text, offsets, cls = text.to(device), offsets.to(device), cls.to(device) + with torch.no_grad(): + output = model(text, offsets) + loss = criterion(output, cls) + loss += loss.item() + acc += (output.argmax(1) == cls).sum().item() + + return loss / len(data_), acc / len(data_) + +``` + +## 分割数据集并运行模型 + +由于原始的`AG_NEWS`没有有效的数据集,因此我们将训练数据集分为训练/有效集,其分割比率为 0.95(训练)和 0.05(有效)。 在这里,我们在 PyTorch 核心库中使用[`torch.utils.data.dataset.random_split`](https://pytorch.org/docs/stable/data.html?highlight=random_split#torch.utils.data.random_split)函数。 + +[`CrossEntropyLoss`](https://pytorch.org/docs/stable/nn.html?highlight=crossentropyloss#torch.nn.CrossEntropyLoss)标准将`nn.LogSoftmax()`和`nn.NLLLoss()`合并到一个类中。 在训练带有`C`类的分类问题时很有用。 [`SGD`](https://pytorch.org/docs/stable/_modules/torch/optim/sgd.html)实现了随机梯度下降方法作为优化程序。 初始学习率设置为 4.0。 [`StepLR`](https://pytorch.org/docs/master/_modules/torch/optim/lr_scheduler.html#StepLR)在此处用于通过历时调整学习率。 + +```py +import time +from torch.utils.data.dataset import random_split +N_EPOCHS = 5 +min_valid_loss = float('inf') + +criterion = torch.nn.CrossEntropyLoss().to(device) +optimizer = torch.optim.SGD(model.parameters(), lr=4.0) +scheduler = torch.optim.lr_scheduler.StepLR(optimizer, 1, gamma=0.9) + +train_len = int(len(train_dataset) * 0.95) +sub_train_, sub_valid_ = \ + random_split(train_dataset, [train_len, len(train_dataset) - train_len]) + +for epoch in range(N_EPOCHS): + + start_time = time.time() + train_loss, train_acc = train_func(sub_train_) + valid_loss, valid_acc = test(sub_valid_) + + secs = int(time.time() - start_time) + mins = secs / 60 + secs = secs % 60 + + print('Epoch: %d' %(epoch + 1), " | time in %d minutes, %d seconds" %(mins, secs)) + print(f'\tLoss: {train_loss:.4f}(train)\t|\tAcc: {train_acc * 100:.1f}%(train)') + print(f'\tLoss: {valid_loss:.4f}(valid)\t|\tAcc: {valid_acc * 100:.1f}%(valid)') + +``` + +出: + +```py +Epoch: 1 | time in 0 minutes, 11 seconds + Loss: 0.0262(train) | Acc: 84.7%(train) + Loss: 0.0002(valid) | Acc: 89.3%(valid) +Epoch: 2 | time in 0 minutes, 11 seconds + Loss: 0.0119(train) | Acc: 93.6%(train) + Loss: 0.0002(valid) | Acc: 89.6%(valid) +Epoch: 3 | time in 0 minutes, 11 seconds + Loss: 0.0069(train) | Acc: 96.3%(train) + Loss: 0.0000(valid) | Acc: 91.8%(valid) +Epoch: 4 | time in 0 minutes, 11 seconds + Loss: 0.0038(train) | Acc: 98.1%(train) + Loss: 0.0000(valid) | Acc: 91.5%(valid) +Epoch: 5 | time in 0 minutes, 11 seconds + Loss: 0.0022(train) | Acc: 99.0%(train) + Loss: 0.0000(valid) | Acc: 91.4%(valid) + +``` + +使用以下信息在 GPU 上运行模型: + +周期:1 | 时间在 0 分 11 秒内 + +```py +Loss: 0.0263(train) | Acc: 84.5%(train) +Loss: 0.0001(valid) | Acc: 89.0%(valid) + +``` + +周期:2 | 时间在 0 分钟 10 秒内 + +```py +Loss: 0.0119(train) | Acc: 93.6%(train) +Loss: 0.0000(valid) | Acc: 89.6%(valid) + +``` + +周期:3 | 时间在 0 分钟 9 秒内 + +```py +Loss: 0.0069(train) | Acc: 96.4%(train) +Loss: 0.0000(valid) | Acc: 90.5%(valid) + +``` + +周期:4 | 时间在 0 分 11 秒内 + +```py +Loss: 0.0038(train) | Acc: 98.2%(train) +Loss: 0.0000(valid) | Acc: 90.4%(valid) + +``` + +周期:5 | 时间在 0 分 11 秒内 + +```py +Loss: 0.0022(train) | Acc: 99.0%(train) +Loss: 0.0000(valid) | Acc: 91.0%(valid) + +``` + +## 使用测试数据集评估模型 + +```py +print('Checking the results of test dataset...') +test_loss, test_acc = test(test_dataset) +print(f'\tLoss: {test_loss:.4f}(test)\t|\tAcc: {test_acc * 100:.1f}%(test)') + +``` + +出: + +```py +Checking the results of test dataset... + Loss: 0.0002(test) | Acc: 90.9%(test) + +``` + +正在检查测试数据集的结果… + +```py +Loss: 0.0237(test) | Acc: 90.5%(test) + +``` + +## 测试随机新闻 + +使用到目前为止最好的模型并测试高尔夫新闻。 标签信息在[这里](https://pytorch.org/text/datasets.html?highlight=ag_news#torchtext.datasets.AG_NEWS)。 + +```py +import re +from torchtext.data.utils import ngrams_iterator +from torchtext.data.utils import get_tokenizer + +ag_news_label = {1 : "World", + 2 : "Sports", + 3 : "Business", + 4 : "Sci/Tec"} + +def predict(text, model, vocab, ngrams): + tokenizer = get_tokenizer("basic_english") + with torch.no_grad(): + text = torch.tensor([vocab[token] + for token in ngrams_iterator(tokenizer(text), ngrams)]) + output = model(text, torch.tensor([0])) + return output.argmax(1).item() + 1 + +ex_text_str = "MEMPHIS, Tenn. – Four days ago, Jon Rahm was \ + enduring the season's worst weather conditions on Sunday at The \ + Open on his way to a closing 75 at Royal Portrush, which \ + considering the wind and the rain was a respectable showing. \ + Thursday's first round at the WGC-FedEx St. Jude Invitational \ + was another story. With temperatures in the mid-80s and hardly any \ + wind, the Spaniard was 13 strokes better in a flawless round. \ + Thanks to his best putting performance on the PGA Tour, Rahm \ + finished with an 8-under 62 for a three-stroke lead, which \ + was even more impressive considering he'd never played the \ + front nine at TPC Southwind." + +vocab = train_dataset.get_vocab() +model = model.to("cpu") + +print("This is a %s news" %ag_news_label[predict(ex_text_str, model, vocab, 2)]) + +``` + +出: + +```py +This is a Sports news + +``` + +这是体育新闻 + +[您可以在此处找到本说明中显示的代码示例](https://github.com/pytorch/text/tree/master/examples/text_classification)。 + +**脚本的总运行时间**:(1 分 38.483 秒) + +[下载 Python 源码:`text_sentiment_ngrams_tutorial.py`](../_downloads/1824f32965271d21829e1739cc434729/text_sentiment_ngrams_tutorial.py) + +[下载 Jupyter 笔记本:`text_sentiment_ngrams_tutorial.ipynb`](../_downloads/27bd42079e7f46673b53e90153168529/text_sentiment_ngrams_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/32.md b/pytorch/官方教程/32.md new file mode 100644 index 00000000..2fd00207 --- /dev/null +++ b/pytorch/官方教程/32.md @@ -0,0 +1,501 @@ +# `torchtext`语言翻译 + +> 原文: + +本教程介绍了如何使用`torchtext`预处理包含英语和德语句子的著名数据集的数据,并使用它来训练序列到序列模型,并能将德语句子翻译成英语。 + +它基于 PyTorch 社区成员 [Ben Trevett](https://github.com/bentrevett) 的本教程,并获得 Ben 的许可。 我们通过删除一些旧代码来更新教程。 + +在本教程结束时,您将可以将句子预处理为张量以用于 NLP 建模,并可以使用[`torch.utils.data.DataLoader`](https://pytorch.org/docs/stable/data.html?highlight=dataloader#torch.utils.data.DataLoader)来训练和验证模型。 + +## 数据处理 + +`torchtext`具有工具,可用于创建可以轻松迭代的数据集,以创建语言翻译模型。 在此示例中,我们展示了如何对原始文本句子进行标记,构建词汇表以及将标记数字化为张量。 + +注意:本教程中的分词需要 [Spacy](https://spacy.io) 我们使用 Spacy 是因为它为英语以外的其他语言的分词提供了强大的支持。 `torchtext`提供了`basic_english`标记器,并支持其他英语标记器(例如 [Moses](https://bitbucket.org/luismsgomes/mosestokenizer/src/default/)),但对于语言翻译(需要多种语言),Spacy 是您的最佳选择。 + +要运行本教程,请先使用`pip`或`conda`安装`spacy`。 接下来,下载英语和德语 Spacy 分词器的原始数据: + +```py +python -m spacy download en +python -m spacy download de + +``` + +```py +import torchtext +import torch +from torchtext.data.utils import get_tokenizer +from collections import Counter +from torchtext.vocab import Vocab +from torchtext.utils import download_from_url, extract_archive +import io + +url_base = 'https://raw.githubusercontent.com/multi30k/dataset/master/data/task1/raw/' +train_urls = ('train.de.gz', 'train.en.gz') +val_urls = ('val.de.gz', 'val.en.gz') +test_urls = ('test_2016_flickr.de.gz', 'test_2016_flickr.en.gz') + +train_filepaths = [extract_archive(download_from_url(url_base + url))[0] for url in train_urls] +val_filepaths = [extract_archive(download_from_url(url_base + url))[0] for url in val_urls] +test_filepaths = [extract_archive(download_from_url(url_base + url))[0] for url in test_urls] + +de_tokenizer = get_tokenizer('spacy', language='de') +en_tokenizer = get_tokenizer('spacy', language='en') + +def build_vocab(filepath, tokenizer): + counter = Counter() + with io.open(filepath, encoding="utf8") as f: + for string_ in f: + counter.update(tokenizer(string_)) + return Vocab(counter, specials=['', '', '', '']) + +de_vocab = build_vocab(train_filepaths[0], de_tokenizer) +en_vocab = build_vocab(train_filepaths[1], en_tokenizer) + +def data_process(filepaths): + raw_de_iter = iter(io.open(filepaths[0], encoding="utf8")) + raw_en_iter = iter(io.open(filepaths[1], encoding="utf8")) + data = [] + for (raw_de, raw_en) in zip(raw_de_iter, raw_en_iter): + de_tensor_ = torch.tensor([de_vocab[token] for token in de_tokenizer(raw_de)], + dtype=torch.long) + en_tensor_ = torch.tensor([en_vocab[token] for token in en_tokenizer(raw_en)], + dtype=torch.long) + data.append((de_tensor_, en_tensor_)) + return data + +train_data = data_process(train_filepaths) +val_data = data_process(val_filepaths) +test_data = data_process(test_filepaths) + +``` + +## `DataLoader` + +我们将使用的最后`torch`个特定函数是`DataLoader`,它易于使用,因为它将数据作为第一个参数。 具体来说,正如文档所说:`DataLoader`结合了一个数据集和一个采样器,并在给定的数据集上提供了可迭代的。 `DataLoader`支持映射样式和可迭代样式的数据集,具有单进程或多进程加载,自定义加载顺序以及可选的自动批量(归类)和内存固定。 + +请注意`collate_fn`(可选),它将合并样本列表以形成张量的小批量。 在从映射样式数据集中使用批量加载时使用。 + +```py +import torch + +device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') + +BATCH_SIZE = 128 +PAD_IDX = de_vocab[''] +BOS_IDX = de_vocab[''] +EOS_IDX = de_vocab[''] + +from torch.nn.utils.rnn import pad_sequence +from torch.utils.data import DataLoader + +def generate_batch(data_batch): + de_batch, en_batch = [], [] + for (de_item, en_item) in data_batch: + de_batch.append(torch.cat([torch.tensor([BOS_IDX]), de_item, torch.tensor([EOS_IDX])], dim=0)) + en_batch.append(torch.cat([torch.tensor([BOS_IDX]), en_item, torch.tensor([EOS_IDX])], dim=0)) + de_batch = pad_sequence(de_batch, padding_value=PAD_IDX) + en_batch = pad_sequence(en_batch, padding_value=PAD_IDX) + return de_batch, en_batch + +train_iter = DataLoader(train_data, batch_size=BATCH_SIZE, + shuffle=True, collate_fn=generate_batch) +valid_iter = DataLoader(val_data, batch_size=BATCH_SIZE, + shuffle=True, collate_fn=generate_batch) +test_iter = DataLoader(test_data, batch_size=BATCH_SIZE, + shuffle=True, collate_fn=generate_batch) + +``` + +## 定义我们的`nn.Module`和`Optimizer` + +这大部分是从`torchtext`角度出发的:构建了数据集并定义了迭代器,本教程的其余部分仅将模型定义为`nn.Module`以及`Optimizer`,然后对其进行训练。 + +具体来说,我们的模型遵循[此处描述的架构](https://arxiv.org/abs/1409.0473)(您可以在[这里](https://github.com/SethHWeidman/pytorch-seq2seq/blob/master/3%20-%20Neural%20Machine%20Translation%20by%20Jointly%20Learning%20to%20Align%20and%20Translate.ipynb)找到注释更多的版本。 + +注意:此模型只是可用于语言翻译的示例模型; 我们选择它是因为它是任务的标准模型,而不是因为它是用于翻译的推荐模型。 如您所知,目前最先进的模型基于“转换器”; 您可以看到 PyTorch 的实现[`Transformer`](https://pytorch.org/docs/stable/nn.html#transformer-layers)层的功能; 特别是,以下模型中使用的“注意”与转换器模型中存在的多头自我注意不同。 + +```py +import random +from typing import Tuple + +import torch.nn as nn +import torch.optim as optim +import torch.nn.functional as F +from torch import Tensor + +class Encoder(nn.Module): + def __init__(self, + input_dim: int, + emb_dim: int, + enc_hid_dim: int, + dec_hid_dim: int, + dropout: float): + super().__init__() + + self.input_dim = input_dim + self.emb_dim = emb_dim + self.enc_hid_dim = enc_hid_dim + self.dec_hid_dim = dec_hid_dim + self.dropout = dropout + + self.embedding = nn.Embedding(input_dim, emb_dim) + + self.rnn = nn.GRU(emb_dim, enc_hid_dim, bidirectional = True) + + self.fc = nn.Linear(enc_hid_dim * 2, dec_hid_dim) + + self.dropout = nn.Dropout(dropout) + + def forward(self, + src: Tensor) -> Tuple[Tensor]: + + embedded = self.dropout(self.embedding(src)) + + outputs, hidden = self.rnn(embedded) + + hidden = torch.tanh(self.fc(torch.cat((hidden[-2,:,:], hidden[-1,:,:]), dim = 1))) + + return outputs, hidden + +class Attention(nn.Module): + def __init__(self, + enc_hid_dim: int, + dec_hid_dim: int, + attn_dim: int): + super().__init__() + + self.enc_hid_dim = enc_hid_dim + self.dec_hid_dim = dec_hid_dim + + self.attn_in = (enc_hid_dim * 2) + dec_hid_dim + + self.attn = nn.Linear(self.attn_in, attn_dim) + + def forward(self, + decoder_hidden: Tensor, + encoder_outputs: Tensor) -> Tensor: + + src_len = encoder_outputs.shape[0] + + repeated_decoder_hidden = decoder_hidden.unsqueeze(1).repeat(1, src_len, 1) + + encoder_outputs = encoder_outputs.permute(1, 0, 2) + + energy = torch.tanh(self.attn(torch.cat(( + repeated_decoder_hidden, + encoder_outputs), + dim = 2))) + + attention = torch.sum(energy, dim=2) + + return F.softmax(attention, dim=1) + +class Decoder(nn.Module): + def __init__(self, + output_dim: int, + emb_dim: int, + enc_hid_dim: int, + dec_hid_dim: int, + dropout: int, + attention: nn.Module): + super().__init__() + + self.emb_dim = emb_dim + self.enc_hid_dim = enc_hid_dim + self.dec_hid_dim = dec_hid_dim + self.output_dim = output_dim + self.dropout = dropout + self.attention = attention + + self.embedding = nn.Embedding(output_dim, emb_dim) + + self.rnn = nn.GRU((enc_hid_dim * 2) + emb_dim, dec_hid_dim) + + self.out = nn.Linear(self.attention.attn_in + emb_dim, output_dim) + + self.dropout = nn.Dropout(dropout) + + def _weighted_encoder_rep(self, + decoder_hidden: Tensor, + encoder_outputs: Tensor) -> Tensor: + + a = self.attention(decoder_hidden, encoder_outputs) + + a = a.unsqueeze(1) + + encoder_outputs = encoder_outputs.permute(1, 0, 2) + + weighted_encoder_rep = torch.bmm(a, encoder_outputs) + + weighted_encoder_rep = weighted_encoder_rep.permute(1, 0, 2) + + return weighted_encoder_rep + + def forward(self, + input: Tensor, + decoder_hidden: Tensor, + encoder_outputs: Tensor) -> Tuple[Tensor]: + + input = input.unsqueeze(0) + + embedded = self.dropout(self.embedding(input)) + + weighted_encoder_rep = self._weighted_encoder_rep(decoder_hidden, + encoder_outputs) + + rnn_input = torch.cat((embedded, weighted_encoder_rep), dim = 2) + + output, decoder_hidden = self.rnn(rnn_input, decoder_hidden.unsqueeze(0)) + + embedded = embedded.squeeze(0) + output = output.squeeze(0) + weighted_encoder_rep = weighted_encoder_rep.squeeze(0) + + output = self.out(torch.cat((output, + weighted_encoder_rep, + embedded), dim = 1)) + + return output, decoder_hidden.squeeze(0) + +class Seq2Seq(nn.Module): + def __init__(self, + encoder: nn.Module, + decoder: nn.Module, + device: torch.device): + super().__init__() + + self.encoder = encoder + self.decoder = decoder + self.device = device + + def forward(self, + src: Tensor, + trg: Tensor, + teacher_forcing_ratio: float = 0.5) -> Tensor: + + batch_size = src.shape[1] + max_len = trg.shape[0] + trg_vocab_size = self.decoder.output_dim + + outputs = torch.zeros(max_len, batch_size, trg_vocab_size).to(self.device) + + encoder_outputs, hidden = self.encoder(src) + + # first input to the decoder is the token + output = trg[0,:] + + for t in range(1, max_len): + output, hidden = self.decoder(output, hidden, encoder_outputs) + outputs[t] = output + teacher_force = random.random() < teacher_forcing_ratio + top1 = output.max(1)[1] + output = (trg[t] if teacher_force else top1) + + return outputs + +INPUT_DIM = len(de_vocab) +OUTPUT_DIM = len(en_vocab) +# ENC_EMB_DIM = 256 +# DEC_EMB_DIM = 256 +# ENC_HID_DIM = 512 +# DEC_HID_DIM = 512 +# ATTN_DIM = 64 +# ENC_DROPOUT = 0.5 +# DEC_DROPOUT = 0.5 + +ENC_EMB_DIM = 32 +DEC_EMB_DIM = 32 +ENC_HID_DIM = 64 +DEC_HID_DIM = 64 +ATTN_DIM = 8 +ENC_DROPOUT = 0.5 +DEC_DROPOUT = 0.5 + +enc = Encoder(INPUT_DIM, ENC_EMB_DIM, ENC_HID_DIM, DEC_HID_DIM, ENC_DROPOUT) + +attn = Attention(ENC_HID_DIM, DEC_HID_DIM, ATTN_DIM) + +dec = Decoder(OUTPUT_DIM, DEC_EMB_DIM, ENC_HID_DIM, DEC_HID_DIM, DEC_DROPOUT, attn) + +model = Seq2Seq(enc, dec, device).to(device) + +def init_weights(m: nn.Module): + for name, param in m.named_parameters(): + if 'weight' in name: + nn.init.normal_(param.data, mean=0, std=0.01) + else: + nn.init.constant_(param.data, 0) + +model.apply(init_weights) + +optimizer = optim.Adam(model.parameters()) + +def count_parameters(model: nn.Module): + return sum(p.numel() for p in model.parameters() if p.requires_grad) + +print(f'The model has {count_parameters(model):,} trainable parameters') + +``` + +出: + +```py +The model has 3,491,552 trainable parameters + +``` + +注意:特别是对语言翻译模型的表现进行评分时,我们必须告诉`nn.CrossEntropyLoss`函数忽略仅填充目标的索引。 + +```py +PAD_IDX = en_vocab.stoi[''] + +criterion = nn.CrossEntropyLoss(ignore_index=PAD_IDX) + +``` + +最后,我们可以训练和评估该模型: + +```py +import math +import time + +def train(model: nn.Module, + iterator: torch.utils.data.DataLoader, + optimizer: optim.Optimizer, + criterion: nn.Module, + clip: float): + + model.train() + + epoch_loss = 0 + + for _, (src, trg) in enumerate(iterator): + src, trg = src.to(device), trg.to(device) + + optimizer.zero_grad() + + output = model(src, trg) + + output = output[1:].view(-1, output.shape[-1]) + trg = trg[1:].view(-1) + + loss = criterion(output, trg) + + loss.backward() + + torch.nn.utils.clip_grad_norm_(model.parameters(), clip) + + optimizer.step() + + epoch_loss += loss.item() + + return epoch_loss / len(iterator) + +def evaluate(model: nn.Module, + iterator: torch.utils.data.DataLoader, + criterion: nn.Module): + + model.eval() + + epoch_loss = 0 + + with torch.no_grad(): + + for _, (src, trg) in enumerate(iterator): + src, trg = src.to(device), trg.to(device) + + output = model(src, trg, 0) #turn off teacher forcing + + output = output[1:].view(-1, output.shape[-1]) + trg = trg[1:].view(-1) + + loss = criterion(output, trg) + + epoch_loss += loss.item() + + return epoch_loss / len(iterator) + +def epoch_time(start_time: int, + end_time: int): + elapsed_time = end_time - start_time + elapsed_mins = int(elapsed_time / 60) + elapsed_secs = int(elapsed_time - (elapsed_mins * 60)) + return elapsed_mins, elapsed_secs + +N_EPOCHS = 10 +CLIP = 1 + +best_valid_loss = float('inf') + +for epoch in range(N_EPOCHS): + + start_time = time.time() + + train_loss = train(model, train_iter, optimizer, criterion, CLIP) + valid_loss = evaluate(model, valid_iter, criterion) + + end_time = time.time() + + epoch_mins, epoch_secs = epoch_time(start_time, end_time) + + print(f'Epoch: {epoch+1:02} | Time: {epoch_mins}m {epoch_secs}s') + print(f'\tTrain Loss: {train_loss:.3f} | Train PPL: {math.exp(train_loss):7.3f}') + print(f'\t Val. Loss: {valid_loss:.3f} | Val. PPL: {math.exp(valid_loss):7.3f}') + +test_loss = evaluate(model, test_iter, criterion) + +print(f'| Test Loss: {test_loss:.3f} | Test PPL: {math.exp(test_loss):7.3f} |') + +``` + +出: + +```py +Epoch: 01 | Time: 0m 59s + Train Loss: 5.790 | Train PPL: 327.039 + Val. Loss: 5.250 | Val. PPL: 190.532 +Epoch: 02 | Time: 0m 59s + Train Loss: 4.762 | Train PPL: 116.990 + Val. Loss: 5.037 | Val. PPL: 153.939 +Epoch: 03 | Time: 0m 59s + Train Loss: 4.527 | Train PPL: 92.475 + Val. Loss: 4.924 | Val. PPL: 137.525 +Epoch: 04 | Time: 0m 59s + Train Loss: 4.344 | Train PPL: 76.977 + Val. Loss: 4.801 | Val. PPL: 121.673 +Epoch: 05 | Time: 0m 59s + Train Loss: 4.210 | Train PPL: 67.356 + Val. Loss: 4.758 | Val. PPL: 116.536 +Epoch: 06 | Time: 0m 59s + Train Loss: 4.125 | Train PPL: 61.875 + Val. Loss: 4.691 | Val. PPL: 109.004 +Epoch: 07 | Time: 0m 59s + Train Loss: 4.043 | Train PPL: 56.979 + Val. Loss: 4.639 | Val. PPL: 103.446 +Epoch: 08 | Time: 0m 59s + Train Loss: 3.947 | Train PPL: 51.771 + Val. Loss: 4.589 | Val. PPL: 98.396 +Epoch: 09 | Time: 0m 59s + Train Loss: 3.874 | Train PPL: 48.135 + Val. Loss: 4.514 | Val. PPL: 91.324 +Epoch: 10 | Time: 0m 59s + Train Loss: 3.785 | Train PPL: 44.021 + Val. Loss: 4.467 | Val. PPL: 87.126 +| Test Loss: 4.433 | Test PPL: 84.168 | + +``` + +## 后续步骤 + +* 查看其余的 [Ben Trevett](https://github.com/bentrevett/) 的`torchtext`使用教程。 +* 敬请关注使用其他`torchtext`函数以及`nn.Transformer`通过下一个单词预测进行语言建模的教程! + +**脚本的总运行时间**:(10 分钟 13.398 秒) + +[下载 Python 源码:`torchtext_translation_tutorial.py`](../_downloads/96d6dc961c7477af88e16ca6c9592240/torchtext_translation_tutorial.py) + +[下载 Jupyter 笔记本:`torchtext_translation_tutorial.ipynb`](../_downloads/05baddac9b2f50d639a62ea5fa6e21e4/torchtext_translation_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/33.md b/pytorch/官方教程/33.md new file mode 100644 index 00000000..f9d86906 --- /dev/null +++ b/pytorch/官方教程/33.md @@ -0,0 +1 @@ +# 强化学习 \ No newline at end of file diff --git a/pytorch/官方教程/34.md b/pytorch/官方教程/34.md new file mode 100644 index 00000000..a2ff08cc --- /dev/null +++ b/pytorch/官方教程/34.md @@ -0,0 +1,396 @@ +# 强化学习(DQN)教程 + +> 原文: + +**作者**: [Adam Paszke](https://github.com/apaszke) + +本教程说明如何使用 PyTorch 在 [OpenAI Gym](https://gym.openai.com/) 上的 CartPole-v0 任务上训练深度 Q 学习(DQN)智能体。 + +**任务** + +智能体必须在两个动作之间做出决定-向左或向右移动推车-以便使与之相连的杆子保持直立。 您可以在 [Gym 网站](https://gym.openai.com/envs/CartPole-v0)上找到具有各种算法和可视化效果的官方排行榜。 + +![cartpole](img/fed25c69a6015a90b6e9406e4ac6e01c.png) + +卡特波尔 + +当智能体观察环境的当前状态并选择一个动作时,环境*会转换为*到新状态,并且还会返回表示该动作后果的奖励。 在此任务中,每增加一个时间步长,奖励为 +1,并且如果杆子掉落得太远或手推车离中心的距离超过 2.4 个单位,则环境终止。 这意味着表现更好的方案将持续更长的时间,从而积累更大的回报。 + +对 CartPole 任务进行了设计,以使对智能体的输入是代表环境状态(位置,速度等)的 4 个实际值。 但是,神经网络可以完全通过查看场景来解决任务,因此我们将以推车为中心的一部分屏幕作为输入。 因此,我们的结果无法直接与官方排行榜上的结果进行比较-我们的任务更加艰巨。 不幸的是,这确实减慢了训练速度,因为我们必须渲染所有帧。 + +严格来说,我们将状态显示为当前屏幕补丁与前一个屏幕补丁之间的差异。 这将允许智能体从一张图像中考虑极点的速度。 + +**包** + +首先,让我们导入所需的包。 首先,我们需要针对环境的 [Gym](https://gym.openai.com/docs)(使用`pip install Gym`进行安装)。 我们还将使用 PyTorch 中的以下内容: + +* 神经网络(`torch.nn`) +* 优化(`torch.optim`) +* 自动微分(`torch.autograd`) +* 视觉任务的工具(`torchvision`-[单独的包](https://github.com/pytorch/vision))。 + +```py +import gym +import math +import random +import numpy as np +import matplotlib +import matplotlib.pyplot as plt +from collections import namedtuple +from itertools import count +from PIL import Image + +import torch +import torch.nn as nn +import torch.optim as optim +import torch.nn.functional as F +import torchvision.transforms as T + +env = gym.make('CartPole-v0').unwrapped + +# set up matplotlib +is_ipython = 'inline' in matplotlib.get_backend() +if is_ipython: + from IPython import display + +plt.ion() + +# if gpu is to be used +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + +``` + +## 回放记忆 + +我们将使用经验回放记忆来训练我们的 DQN。 它存储智能体观察到的转换,使我们以后可以重用此数据。 通过从中随机采样,可以构建批量的转换相关。 已经表明,这极大地稳定和改善了 DQN 训练程序。 + +为此,我们将需要两个类: + +* `Transition`-表示我们环境中单个过渡的命名元组。 它本质上将(状态,动作)对映射到其(下一个状态,奖励)结果,该状态是屏幕差异图像,如下所述。 +* `ReplayMemory`-有界大小的循环缓冲区,用于保存最近观察到的转换。 它还实现了`.sample()`方法,用于选择随机的过渡批量进行训练。 + +```py +Transition = namedtuple('Transition', + ('state', 'action', 'next_state', 'reward')) + +class ReplayMemory(object): + + def __init__(self, capacity): + self.capacity = capacity + self.memory = [] + self.position = 0 + + def push(self, *args): + """Saves a transition.""" + if len(self.memory) < self.capacity: + self.memory.append(None) + self.memory[self.position] = Transition(*args) + self.position = (self.position + 1) % self.capacity + + def sample(self, batch_size): + return random.sample(self.memory, batch_size) + + def __len__(self): + return len(self.memory) + +``` + +现在,让我们定义我们的模型。 但是首先,让我们快速回顾一下 DQN 是什么。 + +## DQN 算法 + +我们的环境是确定性的,因此为简单起见,此处介绍的所有方程式也都确定性地制定。 在强化学习文献中,它们还将包含对环境中随机转变的期望。 + +我们的目标是制定一种策略,尝试最大化折扣的累积奖励`R[t[0]] = Σ γ^(t - t[0]) r[t], t = t[0] -> ∞`,其中`R[t[0]]`也称为*回报*。 折扣`γ`应该是`0`和`1`之间的常数,以确保总和收敛。 这使得来自不确定的遥远未来的回报对我们的智能体而言不如可以对其充满信心的近期回报重要。 + +Q 学习的主要思想是,如果我们有一个函数`Q*:State x Action => R`,这可以告诉我们,如果我们在给定状态下采取行动,那么我们就可以轻松地制定出使我们的回报最大化的策略: + +![](img/tex34-1.gif) + +但是,我们对世界一无所知,因此无法访问`Q*`。 但是,由于神经网络是通用函数逼近器,因此我们可以简单地创建一个并将其训练为类似于`Q*`的函数。 + +对于我们的训练更新规则,我们将使用一个事实,即某些策略的每个`Q`函数都遵循贝尔曼方程: + +![](img/tex34-2.gif) + +等式两侧之间的差异称为时间差异误差`delta`: + +![](img/tex34-3.gif) + +为了最小化此误差,我们将使用 [Huber 损失](https://en.wikipedia.org/wiki/Huber_loss)。 当误差较小时,Huber 损失的作用类似于均方误差,而当误差较大时,则表现为平均绝对误差-当`Q`的估计值非常嘈杂时,这使它对异常值的鲁棒性更高。 我们通过从重播内存中采样的一批过渡`B`来计算: + +![](img/tex34-4.gif) + +### Q 网络 + +我们的模型将是一个卷积神经网络,该卷积神经网络将吸收当前屏幕补丁和先前屏幕补丁之间的差异。 它有两个输出,分别代表`Q(s, left)`和`Q(s, right)`(其中`s`是网络的输入)。 实际上,网络正在尝试预测在给定当前输入的情况下执行每个操作的*预期收益*。 + +```py +class DQN(nn.Module): + + def __init__(self, h, w, outputs): + super(DQN, self).__init__() + self.conv1 = nn.Conv2d(3, 16, kernel_size=5, stride=2) + self.bn1 = nn.BatchNorm2d(16) + self.conv2 = nn.Conv2d(16, 32, kernel_size=5, stride=2) + self.bn2 = nn.BatchNorm2d(32) + self.conv3 = nn.Conv2d(32, 32, kernel_size=5, stride=2) + self.bn3 = nn.BatchNorm2d(32) + + # Number of Linear input connections depends on output of conv2d layers + # and therefore the input image size, so compute it. + def conv2d_size_out(size, kernel_size = 5, stride = 2): + return (size - (kernel_size - 1) - 1) // stride + 1 + convw = conv2d_size_out(conv2d_size_out(conv2d_size_out(w))) + convh = conv2d_size_out(conv2d_size_out(conv2d_size_out(h))) + linear_input_size = convw * convh * 32 + self.head = nn.Linear(linear_input_size, outputs) + + # Called with either one element to determine next action, or a batch + # during optimization. Returns tensor([[left0exp,right0exp]...]). + def forward(self, x): + x = F.relu(self.bn1(self.conv1(x))) + x = F.relu(self.bn2(self.conv2(x))) + x = F.relu(self.bn3(self.conv3(x))) + return self.head(x.view(x.size(0), -1)) + +``` + +### 输入提取 + +以下代码是用于从环境中提取和处理渲染图像的工具。 它使用`torchvision`包,可轻松组成图像变换。 一旦运行单元,它将显示它提取的示例补丁。 + +```py +resize = T.Compose([T.ToPILImage(), + T.Resize(40, interpolation=Image.CUBIC), + T.ToTensor()]) + +def get_cart_location(screen_width): + world_width = env.x_threshold * 2 + scale = screen_width / world_width + return int(env.state[0] * scale + screen_width / 2.0) # MIDDLE OF CART + +def get_screen(): + # Returned screen requested by gym is 400x600x3, but is sometimes larger + # such as 800x1200x3\. Transpose it into torch order (CHW). + screen = env.render(mode='rgb_array').transpose((2, 0, 1)) + # Cart is in the lower half, so strip off the top and bottom of the screen + _, screen_height, screen_width = screen.shape + screen = screen[:, int(screen_height*0.4):int(screen_height * 0.8)] + view_width = int(screen_width * 0.6) + cart_location = get_cart_location(screen_width) + if cart_location < view_width // 2: + slice_range = slice(view_width) + elif cart_location > (screen_width - view_width // 2): + slice_range = slice(-view_width, None) + else: + slice_range = slice(cart_location - view_width // 2, + cart_location + view_width // 2) + # Strip off the edges, so that we have a square image centered on a cart + screen = screen[:, :, slice_range] + # Convert to float, rescale, convert to torch tensor + # (this doesn't require a copy) + screen = np.ascontiguousarray(screen, dtype=np.float32) / 255 + screen = torch.from_numpy(screen) + # Resize, and add a batch dimension (BCHW) + return resize(screen).unsqueeze(0).to(device) + +env.reset() +plt.figure() +plt.imshow(get_screen().cpu().squeeze(0).permute(1, 2, 0).numpy(), + interpolation='none') +plt.title('Example extracted screen') +plt.show() + +``` + +## 训练 + +### 超参数和工具 + +该单元实例化我们的模型及其优化器,并定义一些工具: + +* `select_action`-将根据 ε 贪婪策略选择一个动作。 简而言之,有时我们会使用模型来选择操作,有时我们会统一采样。 选择随机动作的可能性将从`EPS_START`开始,并朝`EPS_END`呈指数衰减。 `EPS_DECAY`控制衰减率。 +* `plot_durations`-绘制剧集持续时间以及最近 100 个剧集的平均值(官方评估中使用的度量)的助手。 该图将在包含主要训练循环的单元下面,并且将在每个剧集之后更新。 + +```py +BATCH_SIZE = 128 +GAMMA = 0.999 +EPS_START = 0.9 +EPS_END = 0.05 +EPS_DECAY = 200 +TARGET_UPDATE = 10 + +# Get screen size so that we can initialize layers correctly based on shape +# returned from AI gym. Typical dimensions at this point are close to 3x40x90 +# which is the result of a clamped and down-scaled render buffer in get_screen() +init_screen = get_screen() +_, _, screen_height, screen_width = init_screen.shape + +# Get number of actions from gym action space +n_actions = env.action_space.n + +policy_net = DQN(screen_height, screen_width, n_actions).to(device) +target_net = DQN(screen_height, screen_width, n_actions).to(device) +target_net.load_state_dict(policy_net.state_dict()) +target_net.eval() + +optimizer = optim.RMSprop(policy_net.parameters()) +memory = ReplayMemory(10000) + +steps_done = 0 + +def select_action(state): + global steps_done + sample = random.random() + eps_threshold = EPS_END + (EPS_START - EPS_END) * \ + math.exp(-1\. * steps_done / EPS_DECAY) + steps_done += 1 + if sample > eps_threshold: + with torch.no_grad(): + # t.max(1) will return largest column value of each row. + # second column on max result is index of where max element was + # found, so we pick action with the larger expected reward. + return policy_net(state).max(1)[1].view(1, 1) + else: + return torch.tensor([[random.randrange(n_actions)]], device=device, dtype=torch.long) + +episode_durations = [] + +def plot_durations(): + plt.figure(2) + plt.clf() + durations_t = torch.tensor(episode_durations, dtype=torch.float) + plt.title('Training...') + plt.xlabel('Episode') + plt.ylabel('Duration') + plt.plot(durations_t.numpy()) + # Take 100 episode averages and plot them too + if len(durations_t) >= 100: + means = durations_t.unfold(0, 100, 1).mean(1).view(-1) + means = torch.cat((torch.zeros(99), means)) + plt.plot(means.numpy()) + + plt.pause(0.001) # pause a bit so that plots are updated + if is_ipython: + display.clear_output(wait=True) + display.display(plt.gcf()) + +``` + +### 训练循环 + +最后,是训练模型的代码。 + +在这里,您可以找到执行优化步骤的`optimize_model`函数。 它首先对一批进行采样,将所有张量连接为一个张量,计算`Q(s[t], a[t])`和`V(s[t+1])= max[a] Q(s[t+1], a)`,并将其合并为我们的损失。 根据定义,如果`s`为终端状态,则设置`V(s) = 0`。 我们还使用目标网络来计算`V(s[t+1])`,以提高稳定性。 目标网络的权重大部分时间保持冻结状态,但经常更新以策略网络的权重。 通常这是一组固定的步骤,但是为了简单起见,我们将使用剧集。 + +```py +def optimize_model(): + if len(memory) < BATCH_SIZE: + return + transitions = memory.sample(BATCH_SIZE) + # Transpose the batch (see https://stackoverflow.com/a/19343/3343043 for + # detailed explanation). This converts batch-array of Transitions + # to Transition of batch-arrays. + batch = Transition(*zip(*transitions)) + + # Compute a mask of non-final states and concatenate the batch elements + # (a final state would've been the one after which simulation ended) + non_final_mask = torch.tensor(tuple(map(lambda s: s is not None, + batch.next_state)), device=device, dtype=torch.bool) + non_final_next_states = torch.cat([s for s in batch.next_state + if s is not None]) + state_batch = torch.cat(batch.state) + action_batch = torch.cat(batch.action) + reward_batch = torch.cat(batch.reward) + + # Compute Q(s_t, a) - the model computes Q(s_t), then we select the + # columns of actions taken. These are the actions which would've been taken + # for each batch state according to policy_net + state_action_values = policy_net(state_batch).gather(1, action_batch) + + # Compute V(s_{t+1}) for all next states. + # Expected values of actions for non_final_next_states are computed based + # on the "older" target_net; selecting their best reward with max(1)[0]. + # This is merged based on the mask, such that we'll have either the expected + # state value or 0 in case the state was final. + next_state_values = torch.zeros(BATCH_SIZE, device=device) + next_state_values[non_final_mask] = target_net(non_final_next_states).max(1)[0].detach() + # Compute the expected Q values + expected_state_action_values = (next_state_values * GAMMA) + reward_batch + + # Compute Huber loss + loss = F.smooth_l1_loss(state_action_values, expected_state_action_values.unsqueeze(1)) + + # Optimize the model + optimizer.zero_grad() + loss.backward() + for param in policy_net.parameters(): + param.grad.data.clamp_(-1, 1) + optimizer.step() + +``` + +在下面,您可以找到主要的训练循环。 首先,我们重置环境并初始化`state`张量。 然后,我们采样一个动作,执行它,观察下一个屏幕和奖励(总是 1),并一次优化我们的模型。 当剧集结束(我们的模型失败)时,我们重新开始循环。 + +下面,将`num_episodes`设置得较小。 您应该下载笔记本并运行更多的片段,例如 300 多个片段,才能显着改善持续时间。 + +```py +num_episodes = 50 +for i_episode in range(num_episodes): + # Initialize the environment and state + env.reset() + last_screen = get_screen() + current_screen = get_screen() + state = current_screen - last_screen + for t in count(): + # Select and perform an action + action = select_action(state) + _, reward, done, _ = env.step(action.item()) + reward = torch.tensor([reward], device=device) + + # Observe new state + last_screen = current_screen + current_screen = get_screen() + if not done: + next_state = current_screen - last_screen + else: + next_state = None + + # Store the transition in memory + memory.push(state, action, next_state, reward) + + # Move to the next state + state = next_state + + # Perform one step of the optimization (on the target network) + optimize_model() + if done: + episode_durations.append(t + 1) + plot_durations() + break + # Update the target network, copying all weights and biases in DQN + if i_episode % TARGET_UPDATE == 0: + target_net.load_state_dict(policy_net.state_dict()) + +print('Complete') +env.render() +env.close() +plt.ioff() +plt.show() + +``` + +这是说明总体结果数据流的图。 + +![../_img/reinforcement_learning_diagram.jpg](img/8ec7228e178647ed9c25273de4b9a270.png) + +可以随机选择或根据策略选择动作,从健身环境中获取下一步样本。 我们将结果记录在重播内存中,并在每次迭代时运行优化步骤。 优化会从重播内存中随机抽取一批来进行新策略的训练。 “较旧”的`target_net`也用于优化计算期望的 Q 值; 有时会对其进行更新以使其保持最新状态。 + +**脚本的总运行时间**:(0 分钟 0.000 秒) + +[下载 Python 源码:`reinforcement_q_learning.py`](../_downloads/b8954cc7b372cac10a92b8c6183846a3/reinforcement_q_learning.py) + +[下载 Jupyter 笔记本:`reinforcement_q_learning.ipynb`](../_downloads/2b3f06b04b5e96e4772746c20fcb4dcc/reinforcement_q_learning.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/35.md b/pytorch/官方教程/35.md new file mode 100644 index 00000000..667e6fdf --- /dev/null +++ b/pytorch/官方教程/35.md @@ -0,0 +1,671 @@ +# 训练玩马里奥的 RL 智能体 + +> 原文: + +Authors: [Yuansong Feng](https://github.com/YuansongFeng) , [Suraj Subramanian](https://github.com/suraj813) , [Howard Wang](https://github.com/hw26) , [Steven Guo](https://github.com/GuoYuzhang) . + +本教程将向您介绍深度强化学习的基础知识。 最后,您将实现一个 AI 驱动的马里奥(使用[双重深度 Q 网络](https://arxiv.org/pdf/1509.06461.pdf)),它可以自己玩游戏。 + +尽管本教程不需要任何有关 RL 的先验知识,但是您可以熟悉这些 RL [概念](https://spinningup.openai.com/en/latest/spinningup/rl_intro.html),并将此方便的[备忘单](https://colab.research.google.com/drive/1eN33dPVtdPViiS1njTW_-r-IYCDTFU7N)作为您的伴侣。[完整代码可在此处获得](https://github.com/yuansongFeng/MadMario/)。 + +![mario](img/e46d7dbb0cc58ac0895589bf255444be.png) + +```py +# !pip install gym-super-mario-bros==7.3.0 + +import torch +from torch import nn +from torchvision import transforms as T +from PIL import Image +import numpy as np +from pathlib import Path +from collections import deque +import random, datetime, os, copy + +# Gym is an OpenAI toolkit for RL +import gym +from gym.spaces import Box +from gym.wrappers import FrameStack + +# NES Emulator for OpenAI Gym +from nes_py.wrappers import JoypadSpace + +# Super Mario environment for OpenAI Gym +import gym_super_mario_bros + +``` + +## RL 定义 + +**环境**:智能体与之交互并学习的世界。 + +**操作**`a`:智能体如何响应环境。 所有可能动作的集合称为*动作空间*。 + +**状态**`s`:环境的当前特征。 环境可以处于的所有可能状态的集合称为*状态空间*。 + +**奖励**`r`:奖励是从环境到智能体的关键反馈。 这是驱动智能体学习并改变其未来行动的动力。 多个时间步长上的奖励汇总称为**回报**。 + +**最佳操作的值函数**`Q*(s, a)`:如果您以状态`s`开始,执行任意操作`a`并给出期望的回报, 然后针对每个未来时间步长采取使收益最大化的行动。 可以说`Q`代表状态中动作的“质量”。 我们尝试近似该函数。 + +## 环境 + +### 初始化环境 + +在马里奥,环境由试管,蘑菇和其他成分组成。 + +当马里奥采取行动时,环境会以已更改的(下一个)状态,奖励和其他信息作为响应。 + +```py +# Initialize Super Mario environment +env = gym_super_mario_bros.make("SuperMarioBros-1-1-v0") + +# Limit the action-space to +# 0\. walk right +# 1\. jump right +env = JoypadSpace(env, [["right"], ["right", "A"]]) + +env.reset() +next_state, reward, done, info = env.step(action=0) +print(f"{next_state.shape},\n {reward},\n {done},\n {info}") + +``` + +出: + +```py +(240, 256, 3), + 0, + False, + {'coins': 0, 'flag_get': False, 'life': 2, 'score': 0, 'stage': 1, 'status': 'small', 'time': 400, 'world': 1, 'x_pos': 40, 'x_pos_screen': 40, 'y_pos': 79} + +``` + +### 预处理环境 + +环境数据在`next_state`中返回给智能体。 正如您在上面看到的,每个状态都由`[3, 240, 256]`大小数组表示。 通常,这比我们的智能体需要的信息更多; 例如,马里奥的举动并不取决于管道或天空的颜色! + +我们使用**包装程序**在将环境数据发送到智能体之前对其进行预处理。 + +`GrayScaleObservation`是将 RGB 图像转换为灰度的通用包装器; 这样做可以减少状态表示的大小,而不会丢失有用的信息。 现在每个状态的大小:`[1, 240, 256]` + +`ResizeObservation`将每个观察值下采样为正方形图像。 新尺寸:`[1, 84, 84]` + +`SkipFrame`是一个自定义包装器,它继承自`gym.Wrapper`并实现了`step()`函数。 由于连续的帧变化不大,因此我们可以跳过 n 个中间帧而不会丢失太多信息。 第 n 帧聚集在每个跳过的帧上累积的奖励。 + +`FrameStack`是一个包装器,它使我们可以将环境的连续帧压缩到单个观察点中,以提供给我们的学习模型。 这样,我们可以根据前几个帧中马里奥的运动方向来确定马里奥是在降落还是跳跃。 + +```py +class SkipFrame(gym.Wrapper): + def __init__(self, env, skip): + """Return only every `skip`-th frame""" + super().__init__(env) + self._skip = skip + + def step(self, action): + """Repeat action, and sum reward""" + total_reward = 0.0 + done = False + for i in range(self._skip): + # Accumulate reward and repeat the same action + obs, reward, done, info = self.env.step(action) + total_reward += reward + if done: + break + return obs, total_reward, done, info + +class GrayScaleObservation(gym.ObservationWrapper): + def __init__(self, env): + super().__init__(env) + obs_shape = self.observation_space.shape[:2] + self.observation_space = Box(low=0, high=255, shape=obs_shape, dtype=np.uint8) + + def permute_orientation(self, observation): + # permute [H, W, C] array to [C, H, W] tensor + observation = np.transpose(observation, (2, 0, 1)) + observation = torch.tensor(observation.copy(), dtype=torch.float) + return observation + + def observation(self, observation): + observation = self.permute_orientation(observation) + transform = T.Grayscale() + observation = transform(observation) + return observation + +class ResizeObservation(gym.ObservationWrapper): + def __init__(self, env, shape): + super().__init__(env) + if isinstance(shape, int): + self.shape = (shape, shape) + else: + self.shape = tuple(shape) + + obs_shape = self.shape + self.observation_space.shape[2:] + self.observation_space = Box(low=0, high=255, shape=obs_shape, dtype=np.uint8) + + def observation(self, observation): + transforms = T.Compose( + [T.Resize(self.shape), T.Normalize(0, 255)] + ) + observation = transforms(observation).squeeze(0) + return observation + +# Apply Wrappers to environment +env = SkipFrame(env, skip=4) +env = GrayScaleObservation(env) +env = ResizeObservation(env, shape=84) +env = FrameStack(env, num_stack=4) + +``` + +将上述包装纸应用于环境后,最终的包装状态由 4 个灰度连续的帧堆叠在一起组成,如左图所示。 每次马里奥采取行动时,环境都会以这种结构的状态做出响应。 该结构由大小为`[4, 84, 84]`的 3D 数组表示。 + +![picture](img/ad48ffbd1cfc0475d744b8b89a0d962a.png) + +## 智能体 + +我们创建一个类`Mario`来表示我们的智能体在游戏中。 马里奥应该能够: + +* **根据(环境的)当前状态,执行最佳操作策略**。 +* **记住**经验。 经验为(当前状态,当前动作,奖励,下一个状态)。 马里奥*缓存*并且后来*回忆起*他的经验来更新其行动策略。 +* **逐步了解**更好的操作策略 + +```py +class Mario: + def __init__(): + pass + + def act(self, state): + """Given a state, choose an epsilon-greedy action""" + pass + + def cache(self, experience): + """Add the experience to memory""" + pass + + def recall(self): + """Sample experiences from memory""" + pass + + def learn(self): + """Update online action value (Q) function with a batch of experiences""" + pass + +``` + +在以下各节中,我们将填充马里奥的参数并定义其函数。 + +### 行动 + +对于任何给定状态,智能体都可以选择执行最佳操作(**利用**)或执行随机操作(**探索**)。 + +马里奥随机发掘并发`self.exploration_rate` 当他选择利用时,他依靠`MarioNet`(在`Learn`部分中实现)提供最佳操作。 + +```py +class Mario: + def __init__(self, state_dim, action_dim, save_dir): + self.state_dim = state_dim + self.action_dim = action_dim + self.save_dir = save_dir + + self.use_cuda = torch.cuda.is_available() + + # Mario's DNN to predict the most optimal action - we implement this in the Learn section + self.net = MarioNet(self.state_dim, self.action_dim).float() + if self.use_cuda: + self.net = self.net.to(device="cuda") + + self.exploration_rate = 1 + self.exploration_rate_decay = 0.99999975 + self.exploration_rate_min = 0.1 + self.curr_step = 0 + + self.save_every = 5e5 # no. of experiences between saving Mario Net + + def act(self, state): + """ + Given a state, choose an epsilon-greedy action and update value of step. + + Inputs: + state(LazyFrame): A single observation of the current state, dimension is (state_dim) + Outputs: + action_idx (int): An integer representing which action Mario will perform + """ + # EXPLORE + if np.random.rand() < self.exploration_rate: + action_idx = np.random.randint(self.action_dim) + + # EXPLOIT + else: + state = state.__array__() + if self.use_cuda: + state = torch.tensor(state).cuda() + else: + state = torch.tensor(state) + state = state.unsqueeze(0) + action_values = self.net(state, model="online") + action_idx = torch.argmax(action_values, axis=1).item() + + # decrease exploration_rate + self.exploration_rate *= self.exploration_rate_decay + self.exploration_rate = max(self.exploration_rate_min, self.exploration_rate) + + # increment step + self.curr_step += 1 + return action_idx + +``` + +### 缓存和回忆 + +这两个函数是马里奥的“记忆”过程。 + +`cache()`:每次马里奥执行操作时,都会将`experience`存储到他的内存中。 他的经验包括当前*状态*,*动作*,*从动作中获得的奖励*,*下一个状态*以及游戏是否为*完成*。 + +`recall()`:马里奥从他的记忆中随机抽取一批经验,并以此来学习游戏。 + +```py +class Mario(Mario): # subclassing for continuity + def __init__(self, state_dim, action_dim, save_dir): + super().__init__(state_dim, action_dim, save_dir) + self.memory = deque(maxlen=100000) + self.batch_size = 32 + + def cache(self, state, next_state, action, reward, done): + """ + Store the experience to self.memory (replay buffer) + + Inputs: + state (LazyFrame), + next_state (LazyFrame), + action (int), + reward (float), + done(bool)) + """ + state = state.__array__() + next_state = next_state.__array__() + + if self.use_cuda: + state = torch.tensor(state).cuda() + next_state = torch.tensor(next_state).cuda() + action = torch.tensor([action]).cuda() + reward = torch.tensor([reward]).cuda() + done = torch.tensor([done]).cuda() + else: + state = torch.tensor(state) + next_state = torch.tensor(next_state) + action = torch.tensor([action]) + reward = torch.tensor([reward]) + done = torch.tensor([done]) + + self.memory.append((state, next_state, action, reward, done,)) + + def recall(self): + """ + Retrieve a batch of experiences from memory + """ + batch = random.sample(self.memory, self.batch_size) + state, next_state, action, reward, done = map(torch.stack, zip(*batch)) + return state, next_state, action.squeeze(), reward.squeeze(), done.squeeze() + +``` + +### 学习 + +马里奥在后台使用 [DDQN 算法](https://arxiv.org/pdf/1509.06461)。 DDQN 使用两个 ConvNet-`Q_online`和`Q_target`-独立地逼近最佳作用值函数。 + +在我们的实现中,我们在`Q_online`和`Q_target`之间共享特征生成器`features`,但是为每个特征维护单独的 FC 分类器。 `θ_target`(`Q_target`的参数)被冻结,以防止反向传播进行更新。 而是定期与`θ_online`同步(稍后会对此进行详细介绍)。 + +#### 神经网络 + +```py +class MarioNet(nn.Module): + """mini cnn structure + input -> (conv2d + relu) x 3 -> flatten -> (dense + relu) x 2 -> output + """ + + def __init__(self, input_dim, output_dim): + super().__init__() + c, h, w = input_dim + + if h != 84: + raise ValueError(f"Expecting input height: 84, got: {h}") + if w != 84: + raise ValueError(f"Expecting input width: 84, got: {w}") + + self.online = nn.Sequential( + nn.Conv2d(in_channels=c, out_channels=32, kernel_size=8, stride=4), + nn.ReLU(), + nn.Conv2d(in_channels=32, out_channels=64, kernel_size=4, stride=2), + nn.ReLU(), + nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, stride=1), + nn.ReLU(), + nn.Flatten(), + nn.Linear(3136, 512), + nn.ReLU(), + nn.Linear(512, output_dim), + ) + + self.target = copy.deepcopy(self.online) + + # Q_target parameters are frozen. + for p in self.target.parameters(): + p.requires_grad = False + + def forward(self, input, model): + if model == "online": + return self.online(input) + elif model == "target": + return self.target(input) + +``` + +#### TD 估计和 TD 目标 + +学习涉及两个值: + +**TD 估计**-给定状态`s`的预测最佳`Q*` + +![](img/tex34-5.gif) + +**TD 目标**-当前奖励和下一状态`s'`中的估计`Q*`的汇总 + +![](img/tex34-6.gif) + +![](img/tex34-7.gif) + +由于我们不知道下一个动作`a'`是什么,因此我们在下一个状态`s'`中使用动作`a'`最大化`Q_online`。 + +请注意,我们在`td_target()`上使用了[`@torch.no_grad()`](https://pytorch.org/docs/stable/generated/torch.no_grad.html#no-grad)装饰器来禁用梯度计算(因为我们无需在`θ_target`上进行反向传播。) + +```py +class Mario(Mario): + def __init__(self, state_dim, action_dim, save_dir): + super().__init__(state_dim, action_dim, save_dir) + self.gamma = 0.9 + + def td_estimate(self, state, action): + current_Q = self.net(state, model="online")[ + np.arange(0, self.batch_size), action + ] # Q_online(s,a) + return current_Q + + @torch.no_grad() + def td_target(self, reward, next_state, done): + next_state_Q = self.net(next_state, model="online") + best_action = torch.argmax(next_state_Q, axis=1) + next_Q = self.net(next_state, model="target")[ + np.arange(0, self.batch_size), best_action + ] + return (reward + (1 - done.float()) * self.gamma * next_Q).float() + +``` + +#### 更新模型 + +当马里奥从其重播缓冲区中采样输入时,我们计算`TD_t`和`TD_e`并反向传播该损失`Q_online`以更新其参数`θ_online`(\ (\ alpha \)是传递给`optimizer`的学习率`lr`) + +![](img/tex34-8.gif) + +`θ_target`不会通过反向传播进行更新。 相反,我们会定期将`θ_online`复制到`θ_target` + +![](img/tex34-9.gif) + +```py +class Mario(Mario): + def __init__(self, state_dim, action_dim, save_dir): + super().__init__(state_dim, action_dim, save_dir) + self.optimizer = torch.optim.Adam(self.net.parameters(), lr=0.00025) + self.loss_fn = torch.nn.SmoothL1Loss() + + def update_Q_online(self, td_estimate, td_target): + loss = self.loss_fn(td_estimate, td_target) + self.optimizer.zero_grad() + loss.backward() + self.optimizer.step() + return loss.item() + + def sync_Q_target(self): + self.net.target.load_state_dict(self.net.online.state_dict()) + +``` + +#### 保存检查点 + +```py +class Mario(Mario): + def save(self): + save_path = ( + self.save_dir / f"mario_net_{int(self.curr_step // self.save_every)}.chkpt" + ) + torch.save( + dict(model=self.net.state_dict(), exploration_rate=self.exploration_rate), + save_path, + ) + print(f"MarioNet saved to {save_path} at step {self.curr_step}") + +``` + +#### 全部放在一起 + +```py +class Mario(Mario): + def __init__(self, state_dim, action_dim, save_dir): + super().__init__(state_dim, action_dim, save_dir) + self.burnin = 1e4 # min. experiences before training + self.learn_every = 3 # no. of experiences between updates to Q_online + self.sync_every = 1e4 # no. of experiences between Q_target & Q_online sync + + def learn(self): + if self.curr_step % self.sync_every == 0: + self.sync_Q_target() + + if self.curr_step % self.save_every == 0: + self.save() + + if self.curr_step < self.burnin: + return None, None + + if self.curr_step % self.learn_every != 0: + return None, None + + # Sample from memory + state, next_state, action, reward, done = self.recall() + + # Get TD Estimate + td_est = self.td_estimate(state, action) + + # Get TD Target + td_tgt = self.td_target(reward, next_state, done) + + # Backpropagate loss through Q_online + loss = self.update_Q_online(td_est, td_tgt) + + return (td_est.mean().item(), loss) + +``` + +### 日志记录 + +```py +import numpy as np +import time, datetime +import matplotlib.pyplot as plt + +class MetricLogger: + def __init__(self, save_dir): + self.save_log = save_dir / "log" + with open(self.save_log, "w") as f: + f.write( + f"{'Episode':>8}{'Step':>8}{'Epsilon':>10}{'MeanReward':>15}" + f"{'MeanLength':>15}{'MeanLoss':>15}{'MeanQValue':>15}" + f"{'TimeDelta':>15}{'Time':>20}\n" + ) + self.ep_rewards_plot = save_dir / "reward_plot.jpg" + self.ep_lengths_plot = save_dir / "length_plot.jpg" + self.ep_avg_losses_plot = save_dir / "loss_plot.jpg" + self.ep_avg_qs_plot = save_dir / "q_plot.jpg" + + # History metrics + self.ep_rewards = [] + self.ep_lengths = [] + self.ep_avg_losses = [] + self.ep_avg_qs = [] + + # Moving averages, added for every call to record() + self.moving_avg_ep_rewards = [] + self.moving_avg_ep_lengths = [] + self.moving_avg_ep_avg_losses = [] + self.moving_avg_ep_avg_qs = [] + + # Current episode metric + self.init_episode() + + # Timing + self.record_time = time.time() + + def log_step(self, reward, loss, q): + self.curr_ep_reward += reward + self.curr_ep_length += 1 + if loss: + self.curr_ep_loss += loss + self.curr_ep_q += q + self.curr_ep_loss_length += 1 + + def log_episode(self): + "Mark end of episode" + self.ep_rewards.append(self.curr_ep_reward) + self.ep_lengths.append(self.curr_ep_length) + if self.curr_ep_loss_length == 0: + ep_avg_loss = 0 + ep_avg_q = 0 + else: + ep_avg_loss = np.round(self.curr_ep_loss / self.curr_ep_loss_length, 5) + ep_avg_q = np.round(self.curr_ep_q / self.curr_ep_loss_length, 5) + self.ep_avg_losses.append(ep_avg_loss) + self.ep_avg_qs.append(ep_avg_q) + + self.init_episode() + + def init_episode(self): + self.curr_ep_reward = 0.0 + self.curr_ep_length = 0 + self.curr_ep_loss = 0.0 + self.curr_ep_q = 0.0 + self.curr_ep_loss_length = 0 + + def record(self, episode, epsilon, step): + mean_ep_reward = np.round(np.mean(self.ep_rewards[-100:]), 3) + mean_ep_length = np.round(np.mean(self.ep_lengths[-100:]), 3) + mean_ep_loss = np.round(np.mean(self.ep_avg_losses[-100:]), 3) + mean_ep_q = np.round(np.mean(self.ep_avg_qs[-100:]), 3) + self.moving_avg_ep_rewards.append(mean_ep_reward) + self.moving_avg_ep_lengths.append(mean_ep_length) + self.moving_avg_ep_avg_losses.append(mean_ep_loss) + self.moving_avg_ep_avg_qs.append(mean_ep_q) + + last_record_time = self.record_time + self.record_time = time.time() + time_since_last_record = np.round(self.record_time - last_record_time, 3) + + print( + f"Episode {episode} - " + f"Step {step} - " + f"Epsilon {epsilon} - " + f"Mean Reward {mean_ep_reward} - " + f"Mean Length {mean_ep_length} - " + f"Mean Loss {mean_ep_loss} - " + f"Mean Q Value {mean_ep_q} - " + f"Time Delta {time_since_last_record} - " + f"Time {datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S')}" + ) + + with open(self.save_log, "a") as f: + f.write( + f"{episode:8d}{step:8d}{epsilon:10.3f}" + f"{mean_ep_reward:15.3f}{mean_ep_length:15.3f}{mean_ep_loss:15.3f}{mean_ep_q:15.3f}" + f"{time_since_last_record:15.3f}" + f"{datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S'):>20}\n" + ) + + for metric in ["ep_rewards", "ep_lengths", "ep_avg_losses", "ep_avg_qs"]: + plt.plot(getattr(self, f"moving_avg_{metric}")) + plt.savefig(getattr(self, f"{metric}_plot")) + plt.clf() + +``` + +## 开始吧! + +在此示例中,我们运行了 10 个剧集的训练循环,但是对于马里奥要真正了解他的世界的方式,我们建议运行至少 40,000 个剧集的循环! + +```py +use_cuda = torch.cuda.is_available() +print(f"Using CUDA: {use_cuda}") +print() + +save_dir = Path("checkpoints") / datetime.datetime.now().strftime("%Y-%m-%dT%H-%M-%S") +save_dir.mkdir(parents=True) + +mario = Mario(state_dim=(4, 84, 84), action_dim=env.action_space.n, save_dir=save_dir) + +logger = MetricLogger(save_dir) + +episodes = 10 +for e in range(episodes): + + state = env.reset() + + # Play the game! + while True: + + # Run agent on the state + action = mario.act(state) + + # Agent performs action + next_state, reward, done, info = env.step(action) + + # Remember + mario.cache(state, next_state, action, reward, done) + + # Learn + q, loss = mario.learn() + + # Logging + logger.log_step(reward, loss, q) + + # Update state + state = next_state + + # Check if end of game + if done or info["flag_get"]: + break + + logger.log_episode() + + if e % 20 == 0: + logger.record(episode=e, epsilon=mario.exploration_rate, step=mario.curr_step) + +``` + +![../_img/sphx_glr_mario_rl_tutorial_001.png](img/4d4a02b1af752dcb28b536a50d0f9ee4.png) + +出: + +```py +Using CUDA: True + +Episode 0 - Step 40 - Epsilon 0.9999900000487484 - Mean Reward 231.0 - Mean Length 40.0 - Mean Loss 0.0 - Mean Q Value 0.0 - Time Delta 0.444 - Time 2021-01-05T20:23:08 + +``` + +## 总结 + +在本教程中,我们看到了如何使用 PyTorch 来训练玩游戏的 AI。 您可以使用相同的方法训练 AI 在 [OpenAI Gym](https://gym.openai.com/)上玩任何游戏。 希望您喜欢本教程,请随时通过[我们的 Github](https://github.com/yuansongFeng/MadMario/) 与我们联系! + +**脚本的总运行时间**:(0 分钟 21.485 秒) + +[下载 Python 源码:`mario_rl_tutorial.py`](../_downloads/5f9fbaa1fe608e9c6ceeeae4c9bea7ed/mario_rl_tutorial.py) + +[下载 Jupyter 笔记本:`mario_rl_tutorial.ipynb`](../_downloads/54f5097c720c6f2656219ab14a4e7431/mario_rl_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/36.md b/pytorch/官方教程/36.md new file mode 100644 index 00000000..4876704a --- /dev/null +++ b/pytorch/官方教程/36.md @@ -0,0 +1 @@ +# 在生产中部署 PyTorch 模型 \ No newline at end of file diff --git a/pytorch/官方教程/37.md b/pytorch/官方教程/37.md new file mode 100644 index 00000000..4f6d134f --- /dev/null +++ b/pytorch/官方教程/37.md @@ -0,0 +1,319 @@ +# 通过使用 Flask 的 REST API 在 Python 中部署 PyTorch + +> 原文: + +**作者**: [Avinash Sajjanshetty](https://avi.im) + +在本教程中,我们将使用 Flask 部署 PyTorch 模型,并公开用于模型推理的 REST API。 特别是,我们将部署预训练的 DenseNet 121 模型来检测图像。 + +小费 + +此处使用的所有代码均以 MIT 许可发布,可在 [Github](https://github.com/avinassh/pytorch-flask-api) 上找到。 + +这是在生产中部署 PyTorch 模型的系列教程中的第一篇。 到目前为止,以这种方式使用 Flask 是开始为 PyTorch 模型提供服务的最简单方法,但不适用于具有高性能要求的用例。 为了那个原因: + +> * 如果您已经熟悉 TorchScript,则可以直接进入我们的[通过 C++ 加载 TorchScript 模型](https://pytorch.org/tutorials/advanced/cpp_export.html)的教程。 +> * 如果您首先需要在 TorchScript 上进行复习,请查看我们的 [TorchScript 入门](https://pytorch.org/tutorials/beginner/Intro_to_TorchScript_tutorial.html)教程。 + +## API 定义 + +我们将首先定义 API 端点,请求和响应类型。 我们的 API 端点将位于`/predict`,它通过包含图片的`file`参数接受 HTTP POST 请求。 响应将是包含预测的 JSON 响应: + +```py +{"class_id": "n02124075", "class_name": "Egyptian_cat"} + +``` + +## 依赖项 + +通过运行以下命令来安装所需的依赖项: + +```py +$ pip install Flask==1.0.3 torchvision-0.3.0 + +``` + +## 简单的 Web 服务器 + +以下是一个简单的网络服务器,摘自 Flask 的文档 + +```py +from flask import Flask +app = Flask(__name__) + +@app.route('/') +def hello(): + return 'Hello World!' + +``` + +将以上代码段保存在名为`app.py`的文件中,您现在可以通过输入以下内容来运行 Flask 开发服务器: + +```py +$ FLASK_ENV=development FLASK_APP=app.py flask run + +``` + +当您在网络浏览器中访问`http://localhost:5000/`时,您会看到`Hello World!`文字 + +我们将对上面的代码片段进行一些更改,以使其适合我们的 API 定义。 首先,我们将方法重命名为`predict`。 我们将端点路径更新为`/predict`。 由于图像文件将通过 HTTP POST 请求发送,因此我们将对其进行更新,使其也仅接受 POST 请求: + +```py +@app.route('/predict', methods=['POST']) +def predict(): + return 'Hello World!' + +``` + +我们还将更改响应类型,以使其返回包含 ImageNet 类 ID 和名称的 JSON 响应。 更新后的`app.py`文件现在为: + +```py +from flask import Flask, jsonify +app = Flask(__name__) + +@app.route('/predict', methods=['POST']) +def predict(): + return jsonify({'class_id': 'IMAGE_NET_XXX', 'class_name': 'Cat'}) + +``` + +## 推断 + +在下一部分中,我们将重点介绍编写推理代码。 这将涉及两部分,第一部分是准备图像,以便可以将其馈送到 DenseNet;第二部分,我们将编写代码以从模型中获取实际的预测。 + +### 准备图像 + +DenseNet 模型要求图像为尺寸为`224 x 224`的 3 通道 RGB 图像。我们还将使用所需的均值和标准差值对图像张量进行归一化。 您可以在上阅读有关它的更多信息。 + +我们将使用`torchvision`库中的`transforms`并建立一个转换管道,该转换管道可根据需要转换图像。 [您可以这里阅读有关转换的更多信息](https://pytorch.org/docs/stable/torchvision/transforms.html)。 + +```py +import io + +import torchvision.transforms as transforms +from PIL import Image + +def transform_image(image_bytes): + my_transforms = transforms.Compose([transforms.Resize(255), + transforms.CenterCrop(224), + transforms.ToTensor(), + transforms.Normalize( + [0.485, 0.456, 0.406], + [0.229, 0.224, 0.225])]) + image = Image.open(io.BytesIO(image_bytes)) + return my_transforms(image).unsqueeze(0) + +``` + +上面的方法以字节为单位获取图像数据,应用一系列变换并返回张量。 要测试上述方法,请以字节模式读取图像文件(首先将`../_static/img/sample_file.jpeg`替换为计算机上文件的实际路径),然后查看是否取回张量: + +```py +with open("../_static/img/sample_file.jpeg", 'rb') as f: + image_bytes = f.read() + tensor = transform_image(image_bytes=image_bytes) + print(tensor) + +``` + +出: + +```py +tensor([[[[ 0.4508, 0.4166, 0.3994, ..., -1.3473, -1.3302, -1.3473], + [ 0.5364, 0.4851, 0.4508, ..., -1.2959, -1.3130, -1.3302], + [ 0.7077, 0.6392, 0.6049, ..., -1.2959, -1.3302, -1.3644], + ..., + [ 1.3755, 1.3927, 1.4098, ..., 1.1700, 1.3584, 1.6667], + [ 1.8893, 1.7694, 1.4440, ..., 1.2899, 1.4783, 1.5468], + [ 1.6324, 1.8379, 1.8379, ..., 1.4783, 1.7352, 1.4612]], + + [[ 0.5728, 0.5378, 0.5203, ..., -1.3704, -1.3529, -1.3529], + [ 0.6604, 0.6078, 0.5728, ..., -1.3004, -1.3179, -1.3354], + [ 0.8529, 0.7654, 0.7304, ..., -1.3004, -1.3354, -1.3704], + ..., + [ 1.4657, 1.4657, 1.4832, ..., 1.3256, 1.5357, 1.8508], + [ 2.0084, 1.8683, 1.5182, ..., 1.4657, 1.6583, 1.7283], + [ 1.7458, 1.9384, 1.9209, ..., 1.6583, 1.9209, 1.6408]], + + [[ 0.7228, 0.6879, 0.6531, ..., -1.6476, -1.6302, -1.6476], + [ 0.8099, 0.7576, 0.7228, ..., -1.6476, -1.6476, -1.6650], + [ 1.0017, 0.9145, 0.8797, ..., -1.6476, -1.6650, -1.6999], + ..., + [ 1.6291, 1.6291, 1.6465, ..., 1.6291, 1.8208, 2.1346], + [ 2.1868, 2.0300, 1.6814, ..., 1.7685, 1.9428, 2.0125], + [ 1.9254, 2.0997, 2.0823, ..., 1.9428, 2.2043, 1.9080]]]]) + +``` + +### 预测 + +现在将使用预训练的 DenseNet 121 模型来预测图像类别。 我们将使用`torchvision`库中的一个,加载模型并进行推断。 在此示例中,我们将使用预训练模型,但您可以对自己的模型使用相同的方法。 在此[教程](../beginner/saving_loading_models.html)中查看有关加载模型的更多信息。 + +```py +from torchvision import models + +# Make sure to pass `pretrained` as `True` to use the pretrained weights: +model = models.densenet121(pretrained=True) +# Since we are using our model only for inference, switch to `eval` mode: +model.eval() + +def get_prediction(image_bytes): + tensor = transform_image(image_bytes=image_bytes) + outputs = model.forward(tensor) + _, y_hat = outputs.max(1) + return y_hat + +``` + +张量`y_hat`将包含预测的类 ID 的索引。 但是,我们需要一个人类可读的类名。 为此,我们需要一个类 ID 来进行名称映射。 将[这个文件](https://s3.amazonaws.com/deep-learning-models/image-models/imagenet_class_index.json)下载为`imagenet_class_index.json`,并记住它的保存位置(或者,如果您按照本教程中的确切步骤操作,请将其保存在`tutorials/_static`中)。 此文件包含 ImageNet 类 ID 到 ImageNet 类名称的映射。 我们将加载此 JSON 文件并获取预测索引的类名称。 + +```py +import json + +imagenet_class_index = json.load(open('../_static/imagenet_class_index.json')) + +def get_prediction(image_bytes): + tensor = transform_image(image_bytes=image_bytes) + outputs = model.forward(tensor) + _, y_hat = outputs.max(1) + predicted_idx = str(y_hat.item()) + return imagenet_class_index[predicted_idx] + +``` + +在使用`imagenet_class_index`字典之前,首先我们将张量值转换为字符串值,因为`imagenet_class_index`字典中的键是字符串。 我们将测试上述方法: + +```py +with open("../_static/img/sample_file.jpeg", 'rb') as f: + image_bytes = f.read() + print(get_prediction(image_bytes=image_bytes)) + +``` + +出: + +```py +['n02124075', 'Egyptian_cat'] + +``` + +您应该得到如下响应: + +```py +['n02124075', 'Egyptian_cat'] + +``` + +数组中的第一项是 ImageNet 类 ID,第二项是人类可读的名称。 + +注意 + +您是否注意到`model`变量不属于`get_prediction`方法? 还是为什么模型是全局变量? 就内存和计算而言,加载模型可能是一项昂贵的操作。 如果我们以`get_prediction`方法加载模型,则每次调用该方法时都会不必要地加载该模型。 由于我们正在构建一个 Web 服务器,因此每秒可能有成千上万的请求,因此我们不应该浪费时间为每个推断重复加载模型。 因此,我们仅将模型加载到内存中一次。 在生产系统中,必须高效使用计算以能够大规模处理请求,因此通常应在处理请求之前加载模型。 + +## 将模型集成到我们的 API 服务器中 + +在最后一部分中,我们将模型添加到 Flask API 服务器中。 由于我们的 API 服务器应该获取图像文件,因此我们将更新`predict`方法以从请求中读取文件: + +```py +from flask import request + +@app.route('/predict', methods=['POST']) +def predict(): + if request.method == 'POST': + # we will get the file from the request + file = request.files['file'] + # convert that to bytes + img_bytes = file.read() + class_id, class_name = get_prediction(image_bytes=img_bytes) + return jsonify({'class_id': class_id, 'class_name': class_name}) + +``` + +`app.py`文件现在完成。 以下是完整版本; 将路径替换为保存文件的路径,它应运行: + +```py +import io +import json + +from torchvision import models +import torchvision.transforms as transforms +from PIL import Image +from flask import Flask, jsonify, request + +app = Flask(__name__) +imagenet_class_index = json.load(open('/imagenet_class_index.json')) +model = models.densenet121(pretrained=True) +model.eval() + +def transform_image(image_bytes): + my_transforms = transforms.Compose([transforms.Resize(255), + transforms.CenterCrop(224), + transforms.ToTensor(), + transforms.Normalize( + [0.485, 0.456, 0.406], + [0.229, 0.224, 0.225])]) + image = Image.open(io.BytesIO(image_bytes)) + return my_transforms(image).unsqueeze(0) + +def get_prediction(image_bytes): + tensor = transform_image(image_bytes=image_bytes) + outputs = model.forward(tensor) + _, y_hat = outputs.max(1) + predicted_idx = str(y_hat.item()) + return imagenet_class_index[predicted_idx] + +@app.route('/predict', methods=['POST']) +def predict(): + if request.method == 'POST': + file = request.files['file'] + img_bytes = file.read() + class_id, class_name = get_prediction(image_bytes=img_bytes) + return jsonify({'class_id': class_id, 'class_name': class_name}) + +if __name__ == '__main__': + app.run() + +``` + +让我们测试一下我们的网络服务器! 跑: + +```py +$ FLASK_ENV=development FLASK_APP=app.py flask run + +``` + +我们可以使用[`requests`](https://pypi.org/project/requests/)库向我们的应用发送 POST 请求: + +```py +import requests + +resp = requests.post("http://localhost:5000/predict", + files={"file": open('/cat.jpg','rb')}) + +``` + +现在打印`resp.json()`将显示以下内容: + +```py +{"class_id": "n02124075", "class_name": "Egyptian_cat"} + +``` + +## 后续步骤 + +我们编写的服务器非常琐碎,可能无法完成生产应用所需的一切。 因此,您可以采取一些措施来改善它: + +* 端点`/predict`假定请求中始终会有一个图像文件。 这可能并不适用于所有请求。 我们的用户可能发送带有其他参数的图像,或者根本不发送任何图像。 +* 用户也可以发送非图像类型的文件。 由于我们没有处理错误,因此这将破坏我们的服务器。 添加显式的错误处理路径将引发异常,这将使我们能够更好地处理错误的输入 +* 即使模型可以识别大量类别的图像,也可能无法识别所有图像。 增强实现以处理模型无法识别图像中的任何情况的情况。 +* 我们在开发模式下运行 Flask 服务器,该服务器不适合在生产中进行部署。 您可以查看[本教程](https://flask.palletsprojects.com/en/1.1.x/tutorial/deploy/),以便在生产环境中部署 Flask 服务器。 +* 您还可以通过创建一个带有表单的页面来添加 UI,该表单可以拍摄图像并显示预测。 查看类似项目的[演示](https://pytorch-imagenet.herokuapp.com/)及其[源代码](https://github.com/avinassh/pytorch-flask-api-heroku)。 +* 在本教程中,我们仅展示了如何构建可以一次返回单个图像预测的服务。 我们可以修改服务以能够一次返回多个图像的预测。 此外,[service-streamer](https://github.com/ShannonAI/service-streamer) 库自动将对服务的请求排队,并将请求采样到微型批量中,这些微型批量可输入模型中。 您可以查看[本教程](https://github.com/ShannonAI/service-streamer/wiki/Vision-Recognition-Service-with-Flask-and-service-streamer)。 +* 最后,我们鼓励您在页面顶部查看链接到的其他 PyTorch 模型部署教程。 + +**脚本的总运行时间**:(0 分钟 1.232 秒) + +[下载 Python 源码:`flask_rest_api_tutorial.py`](../_downloads/146c514e84d7e33f2a302bcc3ae793cb/flask_rest_api_tutorial.py) + +[下载 Jupyter 笔记本:`flask_rest_api_tutorial.ipynb`](../_downloads/6c042f3d39855d2a2de414758e5f9836/flask_rest_api_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/38.md b/pytorch/官方教程/38.md new file mode 100644 index 00000000..c37b2170 --- /dev/null +++ b/pytorch/官方教程/38.md @@ -0,0 +1,480 @@ +# TorchScript 简介 + +> 原文: + +*James Reed (jamesreed@fb.com),Michael Suo (suo@fb.com)*,修订 2 + +本教程是 TorchScript 的简介,TorchScript 是 PyTorch 模型(`nn.Module`的子类)的中间表示,可以在高性能环境(例如 C++)中运行。 + +在本教程中,我们将介绍: + +1. PyTorch 中模型创作的基础,包括: + +* 模组 +* 定义`forward`函数 +* 将模块组成模块的层次结构 + +2. 将 PyTorch 模块转换为 TorchScript(我们的高性能部署运行时)的特定方法 + +* 跟踪现有模块 +* 使用脚本直接编译模块 +* 如何组合两种方法 +* 保存和加载 TorchScript 模块 + +我们希望在完成本教程之后,您将继续学习[后续教程](https://pytorch.org/tutorials/advanced/cpp_export.html),该教程将引导您完成一个从 C++ 实际调用 TorchScript 模型的示例。 + +```py +import torch # This is all you need to use both PyTorch and TorchScript! +print(torch.__version__) + +``` + +出: + +```py +1.7.1 + +``` + +## PyTorch 模型创建基础 + +首先定义一个简单的`Module`。 `Module`是 PyTorch 中组成的基本单位。 它包含: + +1. 为调用准备模块的构造器 +2. 一组`Parameters`和子`Modules`。 这些由构造器初始化,并且可以在调用期间由模块使用。 +3. `forward`函数。 这是调用模块时运行的代码。 + +我们来看一个小例子: + +```py +class MyCell(torch.nn.Module): + def __init__(self): + super(MyCell, self).__init__() + + def forward(self, x, h): + new_h = torch.tanh(x + h) + return new_h, new_h + +my_cell = MyCell() +x = torch.rand(3, 4) +h = torch.rand(3, 4) +print(my_cell(x, h)) + +``` + +出: + +```py +(tensor([[0.8837, 0.5372, 0.4951, 0.9124], + [0.6124, 0.7072, 0.6395, 0.9585], + [0.6178, 0.8701, 0.8071, 0.2415]]), tensor([[0.8837, 0.5372, 0.4951, 0.9124], + [0.6124, 0.7072, 0.6395, 0.9585], + [0.6178, 0.8701, 0.8071, 0.2415]])) + +``` + +因此,我们已经: + +1. 创建了一个子类`torch.nn.Module`的类。 +2. 定义一个构造器。 构造器没有做很多事情,只是调用`super`的构造器。 +3. 定义了`forward`函数,该函数具有两个输入并返回两个输出。 `forward`函数的实际内容并不是很重要,但它是一种伪造的 [RNN 单元](https://colah.github.io/posts/2015-08-Understanding-LSTMs/),即,该函数应用于循环。 + +我们实例化了该模块,并制作了`x`和`y`,它们只是`3x4`随机值矩阵。 然后,我们使用`my_cell(x, h)`调用该单元格。 这依次调用我们的`forward`函数。 + +让我们做一些更有趣的事情: + +```py +class MyCell(torch.nn.Module): + def __init__(self): + super(MyCell, self).__init__() + self.linear = torch.nn.Linear(4, 4) + + def forward(self, x, h): + new_h = torch.tanh(self.linear(x) + h) + return new_h, new_h + +my_cell = MyCell() +print(my_cell) +print(my_cell(x, h)) + +``` + +出: + +```py +MyCell( + (linear): Linear(in_features=4, out_features=4, bias=True) +) +(tensor([[ 0.5042, 0.8137, -0.1593, 0.4167], + [ 0.1716, 0.8078, -0.2267, 0.7011], + [ 0.5616, 0.8753, 0.1597, -0.3899]], grad_fn=), tensor([[ 0.5042, 0.8137, -0.1593, 0.4167], + [ 0.1716, 0.8078, -0.2267, 0.7011], + [ 0.5616, 0.8753, 0.1597, -0.3899]], grad_fn=)) + +``` + +我们已经重新定义了模块`MyCell`,但是这次我们添加了`self.linear`属性,并且在`forward`函数中调用了`self.linear`。 + +这里到底发生了什么? `torch.nn.Linear`是 PyTorch 标准库中的`Module`。 就像`MyCell`一样,可以使用调用语法来调用它。 我们正在建立`Module`的层次结构。 + +`Module`上的`print`将直观地表示`Module`的子类层次结构。 在我们的示例中,我们可以看到`Linear`子类及其参数。 + +通过以这种方式组成`Module`,我们可以简洁易读地编写具有可重用组件的模型。 + +您可能已经在输出上注意到`grad_fn`。 这是 PyTorch 自动微分方法的详细信息,称为 [autograd](https://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html) 。 简而言之,该系统允许我们通过潜在的复杂程序来计算导数。 该设计为模型创作提供了极大的灵活性。 + +现在,让我们检查一下灵活性: + +```py +class MyDecisionGate(torch.nn.Module): + def forward(self, x): + if x.sum() > 0: + return x + else: + return -x + +class MyCell(torch.nn.Module): + def __init__(self): + super(MyCell, self).__init__() + self.dg = MyDecisionGate() + self.linear = torch.nn.Linear(4, 4) + + def forward(self, x, h): + new_h = torch.tanh(self.dg(self.linear(x)) + h) + return new_h, new_h + +my_cell = MyCell() +print(my_cell) +print(my_cell(x, h)) + +``` + +出: + +```py +MyCell( + (dg): MyDecisionGate() + (linear): Linear(in_features=4, out_features=4, bias=True) +) +(tensor([[0.8636, 0.5572, 0.6262, 0.8546], + [0.7766, 0.5056, 0.5357, 0.8360], + [0.7293, 0.7581, 0.7117, 0.2432]], grad_fn=), tensor([[0.8636, 0.5572, 0.6262, 0.8546], + [0.7766, 0.5056, 0.5357, 0.8360], + [0.7293, 0.7581, 0.7117, 0.2432]], grad_fn=)) + +``` + +我们再次重新定义了`MyCell`类,但是在这里我们定义了`MyDecisionGate`。 该模块利用**控制流**。 控制流包括循环和`if`语句之类的内容。 + +给定完整的程序表示形式,许多框架都采用计算符号派生的方法。 但是,在 PyTorch 中,我们使用梯度色带。 我们记录发生的操作,并在计算派生时向后回放。 这样,框架不必为语言中的所有构造显式定义派生类。 + +![How autograd works](img/beccc5ac5df1571304e11d6b12772a99.png) + +Autograd 的工作原理 + +## TorchScript 的基础 + +现在,让我们以正在运行的示例为例,看看如何应用 TorchScript。 + +简而言之,即使 PyTorch 具有灵活和动态的特性,TorchScript 也提供了捕获模型定义的工具。 让我们开始研究所谓的**跟踪**。 + +### 跟踪`Modules` + +```py +class MyCell(torch.nn.Module): + def __init__(self): + super(MyCell, self).__init__() + self.linear = torch.nn.Linear(4, 4) + + def forward(self, x, h): + new_h = torch.tanh(self.linear(x) + h) + return new_h, new_h + +my_cell = MyCell() +x, h = torch.rand(3, 4), torch.rand(3, 4) +traced_cell = torch.jit.trace(my_cell, (x, h)) +print(traced_cell) +traced_cell(x, h) + +``` + +出: + +```py +MyCell( + original_name=MyCell + (linear): Linear(original_name=Linear) +) + +``` + +我们倒退了一点,并学习了`MyCell`类的第二版。 和以前一样,我们实例化了它,但是这一次,我们调用了`torch.jit.trace`,将其传递给`Module`,并传递给了*示例输入*,网络可能会看到。 + +这到底是做什么的? 它调用了`Module`,记录了运行`Module`时发生的操作,并创建了`torch.jit.ScriptModule`的实例(其中`TracedModule`是实例) + +TorchScript 将其定义记录在中间表示(或 IR)中,在深度学习中通常称为*图*。 我们可以检查带有`.graph`属性的图: + +```py +print(traced_cell.graph) + +``` + +出: + +```py +graph(%self.1 : __torch__.MyCell, + %input : Float(3:4, 4:1, requires_grad=0, device=cpu), + %h : Float(3:4, 4:1, requires_grad=0, device=cpu)): + %19 : __torch__.torch.nn.modules.linear.Linear = prim::GetAttr[name="linear"](%self.1) + %21 : Tensor = prim::CallMethod[name="forward"](%19, %input) + %12 : int = prim::Constant[value=1]() # /var/lib/jenkins/workspace/beginner_source/Intro_to_TorchScript_tutorial.py:188:0 + %13 : Float(3:4, 4:1, requires_grad=1, device=cpu) = aten::add(%21, %h, %12) # /var/lib/jenkins/workspace/beginner_source/Intro_to_TorchScript_tutorial.py:188:0 + %14 : Float(3:4, 4:1, requires_grad=1, device=cpu) = aten::tanh(%13) # /var/lib/jenkins/workspace/beginner_source/Intro_to_TorchScript_tutorial.py:188:0 + %15 : (Float(3:4, 4:1, requires_grad=1, device=cpu), Float(3:4, 4:1, requires_grad=1, device=cpu)) = prim::TupleConstruct(%14, %14) + return (%15) + +``` + +但是,这是一个非常低级的表示形式,图中包含的大多数信息对最终用户没有用。 相反,我们可以使用`.code`属性来给出代码的 Python 语法解释: + +```py +print(traced_cell.code) + +``` + +出: + +```py +def forward(self, + input: Tensor, + h: Tensor) -> Tuple[Tensor, Tensor]: + _0 = torch.add((self.linear).forward(input, ), h, alpha=1) + _1 = torch.tanh(_0) + return (_1, _1) + +``` + +那么**为什么我们要进行所有这些操作? 有以下几个原因**: + +1. TorchScript 代码可以在其自己的解释器中调用,该解释器基本上是受限制的 Python 解释器。 该解释器不获取全局解释器锁定,因此可以在同一实例上同时处理许多请求。 +2. 这种格式允许我们将整个模型保存到磁盘上,然后将其加载到另一个环境中,例如在以 Python 以外的语言编写的服务器中 +3. TorchScript 为我们提供了一种表示形式,其中我们可以对代码进行编译器优化以提供更有效的执行 +4. TorchScript 允许我们与许多后端/设备运行时进行交互,与单个运算符相比,它们要求更广泛的程序视图。 + +我们可以看到,调用`traced_cell`会产生与 Python 模块相同的结果: + +```py +print(my_cell(x, h)) +print(traced_cell(x, h)) + +``` + +出: + +```py +(tensor([[-0.3869, 0.0678, 0.5692, 0.6332], + [ 0.1230, 0.4653, 0.8051, 0.3346], + [-0.5288, 0.2767, 0.9063, 0.4727]], grad_fn=), tensor([[-0.3869, 0.0678, 0.5692, 0.6332], + [ 0.1230, 0.4653, 0.8051, 0.3346], + [-0.5288, 0.2767, 0.9063, 0.4727]], grad_fn=)) +(tensor([[-0.3869, 0.0678, 0.5692, 0.6332], + [ 0.1230, 0.4653, 0.8051, 0.3346], + [-0.5288, 0.2767, 0.9063, 0.4727]], grad_fn=), tensor([[-0.3869, 0.0678, 0.5692, 0.6332], + [ 0.1230, 0.4653, 0.8051, 0.3346], + [-0.5288, 0.2767, 0.9063, 0.4727]], grad_fn=)) + +``` + +## 使用脚本转换模块 + +有一个原因是我们使用了模块的第二版,而不是使用带有大量控制流的子模块。 现在让我们检查一下: + +```py +class MyDecisionGate(torch.nn.Module): + def forward(self, x): + if x.sum() > 0: + return x + else: + return -x + +class MyCell(torch.nn.Module): + def __init__(self, dg): + super(MyCell, self).__init__() + self.dg = dg + self.linear = torch.nn.Linear(4, 4) + + def forward(self, x, h): + new_h = torch.tanh(self.dg(self.linear(x)) + h) + return new_h, new_h + +my_cell = MyCell(MyDecisionGate()) +traced_cell = torch.jit.trace(my_cell, (x, h)) +print(traced_cell.code) + +``` + +出: + +```py +def forward(self, + input: Tensor, + h: Tensor) -> Tuple[Tensor, Tensor]: + _0 = self.dg + _1 = (self.linear).forward(input, ) + _2 = (_0).forward(_1, ) + _3 = torch.tanh(torch.add(_1, h, alpha=1)) + return (_3, _3) + +``` + +查看`.code`输出,可以发现找不到`if-else`分支! 为什么? 跟踪完全按照我们所说的去做:运行代码,记录发生的操作,并构造一个执行此操作的`ScriptModule`。 不幸的是,诸如控制流之类的东西被擦除了。 + +我们如何在 TorchScript 中忠实地表示此模块? 我们提供了**脚本编译器**,它可以直接分析您的 Python 源代码以将其转换为 TorchScript。 让我们使用脚本编译器转换`MyDecisionGate`: + +```py +scripted_gate = torch.jit.script(MyDecisionGate()) + +my_cell = MyCell(scripted_gate) +traced_cell = torch.jit.script(my_cell) +print(traced_cell.code) + +``` + +出: + +```py +def forward(self, + x: Tensor, + h: Tensor) -> Tuple[Tensor, Tensor]: + _0 = (self.dg).forward((self.linear).forward(x, ), ) + new_h = torch.tanh(torch.add(_0, h, alpha=1)) + return (new_h, new_h) + +``` + +万岁! 现在,我们已经忠实地捕获了我们在 TorchScript 中程序的行为。 现在,让我们尝试运行该程序: + +```py +# New inputs +x, h = torch.rand(3, 4), torch.rand(3, 4) +traced_cell(x, h) + +``` + +### 混合脚本和跟踪 + +在某些情况下,需要使用跟踪而不是脚本(例如,一个模块具有许多基于不变的 Python 值做出的架构决策,而我们不希望它们出现在 TorchScript 中)。 在这种情况下,可以通过跟踪来编写脚本:`torch.jit.script`将内联被跟踪模块的代码,而跟踪将内联脚本模块的代码。 + +第一种情况的示例: + +```py +class MyRNNLoop(torch.nn.Module): + def __init__(self): + super(MyRNNLoop, self).__init__() + self.cell = torch.jit.trace(MyCell(scripted_gate), (x, h)) + + def forward(self, xs): + h, y = torch.zeros(3, 4), torch.zeros(3, 4) + for i in range(xs.size(0)): + y, h = self.cell(xs[i], h) + return y, h + +rnn_loop = torch.jit.script(MyRNNLoop()) +print(rnn_loop.code) + +``` + +出: + +```py +def forward(self, + xs: Tensor) -> Tuple[Tensor, Tensor]: + h = torch.zeros([3, 4], dtype=None, layout=None, device=None, pin_memory=None) + y = torch.zeros([3, 4], dtype=None, layout=None, device=None, pin_memory=None) + y0 = y + h0 = h + for i in range(torch.size(xs, 0)): + _0 = (self.cell).forward(torch.select(xs, 0, i), h0, ) + y1, h1, = _0 + y0, h0 = y1, h1 + return (y0, h0) + +``` + +还有第二种情况的示例: + +```py +class WrapRNN(torch.nn.Module): + def __init__(self): + super(WrapRNN, self).__init__() + self.loop = torch.jit.script(MyRNNLoop()) + + def forward(self, xs): + y, h = self.loop(xs) + return torch.relu(y) + +traced = torch.jit.trace(WrapRNN(), (torch.rand(10, 3, 4))) +print(traced.code) + +``` + +出: + +```py +def forward(self, + argument_1: Tensor) -> Tensor: + _0, h, = (self.loop).forward(argument_1, ) + return torch.relu(h) + +``` + +这样,当情况需要它们时,可以使用脚本和跟踪并将它们一起使用。 + +## 保存和加载模型 + +我们提供 API,以存档格式将 TorchScript 模块保存到磁盘或从磁盘加载 TorchScript 模块。 这种格式包括代码,参数,属性和调试信息,这意味着归档文件是模型的独立表示形式,可以在完全独立的过程中加载。 让我们保存并加载包装好的 RNN 模块: + +```py +traced.save('wrapped_rnn.zip') + +loaded = torch.jit.load('wrapped_rnn.zip') + +print(loaded) +print(loaded.code) + +``` + +出: + +```py +RecursiveScriptModule( + original_name=WrapRNN + (loop): RecursiveScriptModule( + original_name=MyRNNLoop + (cell): RecursiveScriptModule( + original_name=MyCell + (dg): RecursiveScriptModule(original_name=MyDecisionGate) + (linear): RecursiveScriptModule(original_name=Linear) + ) + ) +) +def forward(self, + argument_1: Tensor) -> Tensor: + _0, h, = (self.loop).forward(argument_1, ) + return torch.relu(h) + +``` + +如您所见,序列化保留了模块层次结构和我们一直在研究的代码。 [也可以将模型加载到 C++ 中](https://pytorch.org/tutorials/advanced/cpp_export.html),以实现不依赖 Python 的执行。 + +### 进一步阅读 + +我们已经完成了教程! 有关更多涉及的演示,[请查看 NeurIPS 演示来使用 TorchScript 转换机器翻译模型](https://colab.research.google.com/drive/1HiICg6jRkBnr5hvK2-VnMi88Vi9pUzEJ)。 + +**脚本的总运行时间**:(0 分钟 0.269 秒) + +[下载 Python 源码:`Intro_to_TorchScript_tutorial.py`](../_downloads/bf4ee4ef1ffde8b469d9ed4001a28ee8/Intro_to_TorchScript_tutorial.py) + +[下载 Jupyter 笔记本:`Intro_to_TorchScript_tutorial.ipynb`](../_downloads/0fd9e9bc92ac80a422914e974021c007/Intro_to_TorchScript_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/39.md b/pytorch/官方教程/39.md new file mode 100644 index 00000000..6d569ec1 --- /dev/null +++ b/pytorch/官方教程/39.md @@ -0,0 +1,298 @@ +# 在 C++ 中加载 TorchScript 模型 + +> 原文: + +顾名思义,PyTorch 的主要接口是 Python 编程语言。 尽管 Python 是许多需要动态性和易于迭代的场景的合适且首选的语言,但是在同样许多情况下,Python 的这些属性恰恰是不利的。 后者经常应用的一种环境是*生产* –低延迟和严格部署要求的土地。 对于生产场景,即使仅将 C++ 绑定到 Java,Rust 或 Go 之类的另一种语言中,它也是经常选择的语言。 以下各段将概述 PyTorch 提供的从现有 Python 模型到序列化表示形式的路径,该序列化表示形式可以完全由 C++ *加载*和*执行*,不依赖于 Python。 + +## 第 1 步:将 PyTorch 模型转换为 Torch 脚本 + +PyTorch 模型从 Python 到 C++ 的旅程由 [Torch 脚本](https://pytorch.org/docs/master/jit.html)启用,它是 PyTorch 模型的一种表示形式,可以由 Torch 脚本编译器理解,编译和序列化。 如果您从使用原始“渴望” API 编写的现有 PyTorch 模型开始,则必须首先将模型转换为 Torch 脚本。 在最常见的情况下(如下所述),只需很少的努力。 如果您已经有了 Torch 脚本模块,则可以跳到本教程的下一部分。 + +有两种将 PyTorch 模型转换为 Torch 脚本的方法。 第一种称为*跟踪*,该机制通过使用示例输入对模型的结构进行一次评估,并记录这些输入在模型中的流量来捕获模型的结构。 这适用于有限使用控制流的模型。 第二种方法是在模型中添加显式注解,以告知 TorchScript 编译器可以根据 Torch Script 语言施加的约束直接解析和编译模型代码。 + +小费 + +您可以在官方 [Torch 脚本参考](https://pytorch.org/docs/master/jit.html)中找到这两种方法的完整文档以及使用方法的进一步指导。 + +### 通过跟踪转换为 Torch 脚本 + +要将 PyTorch 模型通过跟踪转换为 Torch 脚本,必须将模型的实例以及示例输入传递给`torch.jit.trace`函数。 这将产生一个`torch.jit.ScriptModule`对象,并将模型评估的轨迹嵌入到模块的`forward`方法中: + +```py +import torch +import torchvision + +# An instance of your model. +model = torchvision.models.resnet18() + +# An example input you would normally provide to your model's forward() method. +example = torch.rand(1, 3, 224, 224) + +# Use torch.jit.trace to generate a torch.jit.ScriptModule via tracing. +traced_script_module = torch.jit.trace(model, example) + +``` + +现在可以对跟踪的`ScriptModule`进行评估,使其与常规 PyTorch 模块相同: + +```py +In[1]: output = traced_script_module(torch.ones(1, 3, 224, 224)) +In[2]: output[0, :5] +Out[2]: tensor([-0.2698, -0.0381, 0.4023, -0.3010, -0.0448], grad_fn=) + +``` + +### 通过注解转换为 Torch 脚本 + +在某些情况下,例如,如果模型采用特定形式的控制流,则可能需要直接在 Torch 脚本中编写模型并相应地注解模型。 例如,假设您具有以下原始 Pytorch 模型: + +```py +import torch + +class MyModule(torch.nn.Module): + def __init__(self, N, M): + super(MyModule, self).__init__() + self.weight = torch.nn.Parameter(torch.rand(N, M)) + + def forward(self, input): + if input.sum() > 0: + output = self.weight.mv(input) + else: + output = self.weight + input + return output + +``` + +因为此模块的`forward`方法使用取决于输入的控制流,所以它不适合跟踪。 相反,我们可以将其转换为`ScriptModule`。 为了将模块转换为`ScriptModule`,需要使用`torch.jit.script`编译模块,如下所示: + +```py +class MyModule(torch.nn.Module): + def __init__(self, N, M): + super(MyModule, self).__init__() + self.weight = torch.nn.Parameter(torch.rand(N, M)) + + def forward(self, input): + if input.sum() > 0: + output = self.weight.mv(input) + else: + output = self.weight + input + return output + +my_module = MyModule(10,20) +sm = torch.jit.script(my_module) + +``` + +如果您需要在`nn.Module`中排除某些方法,因为它们使用的是 TorchScript 不支持的 Python 函数,则可以使用`@torch.jit.ignore`来注解这些方法 + +`my_module`是已准备好进行序列化的`ScriptModule`的实例。 + +## 第 2 步:将脚本模块序列化为文件 + +跟踪或注解 PyTorch 模型后,一旦有了`ScriptModule`,就可以将其序列化为文件了。 稍后,您将能够使用 C++ 从此文件加载模块并执行它,而无需依赖 Python。 假设我们要序列化先前在跟踪示例中显示的`ResNet18`模型。 要执行此序列化,只需在模块上调用[`save`](https://pytorch.org/docs/master/jit.html#torch.jit.ScriptModule.save)并为其传递文件名: + +```py +traced_script_module.save("traced_resnet_model.pt") + +``` + +这将在您的工作目录中生成一个`traced_resnet_model.pt`文件。 如果您还想序列化`my_module`,请致电`my_module.save("my_module_model.pt")`。我们现在已经正式离开 Python 领域,并准备跨入 C++ 领域。 + +## 第 3 步:在 C++ 中加载脚本模块 + +要在 C++ 中加载序列化的 PyTorch 模型,您的应用必须依赖于 PyTorch C++ API –也称为 *LibTorch* 。 LibTorch 发行版包含共享库,头文件和 CMake 构建配置文件的集合。 虽然 CMake 不是依赖 LibTorch 的要求,但它是推荐的方法,将来会得到很好的支持。 对于本教程,我们将使用 CMake 和 LibTorch 构建一个最小的 C++ 应用,该应用简单地加载并执行序列化的 PyTorch 模型。 + +### 最小的 C++ 应用 + +让我们从讨论加载模块的代码开始。 以下将已经做: + +```py +#include // One-stop header. + +#include +#include + +int main(int argc, const char* argv[]) { + if (argc != 2) { + std::cerr << "usage: example-app \n"; + return -1; + } + + torch::jit::script::Module module; + try { + // Deserialize the ScriptModule from a file using torch::jit::load(). + module = torch::jit::load(argv[1]); + } + catch (const c10::Error& e) { + std::cerr << "error loading the model\n"; + return -1; + } + + std::cout << "ok\n"; +} + +``` + +``标头包含了运行示例所需的 LibTorch 库中的所有相关包含。 我们的应用接受序列化的 PyTorch `ScriptModule`的文件路径作为其唯一的命令行参数,然后继续使用`torch::jit::load()`函数对该模块进行反序列化,该函数将该文件路径作为输入。 作为回报,我们收到一个`torch::jit::script::Module`对象。 我们将稍后讨论如何执行它。 + +### 依赖 LibTorch 并构建应用 + +假设我们将以上代码存储到名为`example-app.cpp`的文件中。 最小的`CMakeLists.txt`构建起来看起来很简单: + +```py +cmake_minimum_required(VERSION 3.0 FATAL_ERROR) +project(custom_ops) + +find_package(Torch REQUIRED) + +add_executable(example-app example-app.cpp) +target_link_libraries(example-app "${TORCH_LIBRARIES}") +set_property(TARGET example-app PROPERTY CXX_STANDARD 14) + +``` + +建立示例应用的最后一件事是 LibTorch 发行版。 您可以随时从 PyTorch 网站上的[下载页面](https://pytorch.org/)获取最新的稳定版本。 如果下载并解压缩最新的归档文件,则应该收到具有以下目录结构的文件夹: + +```py +libtorch/ + bin/ + include/ + lib/ + share/ + +``` + +* `lib/`文件夹包含您必须链接的共享库, +* `include/`文件夹包含程序需要包含的头文件, +* `share/`文件夹包含必要的 CMake 配置,以启用上面的简单`find_package(Torch)`命令。 + +小费 + +在 Windows 上,调试和发行版本不兼容 ABI。 如果计划以调试模式构建项目,请尝试使用 LibTorch 的调试版本。 另外,请确保在下面的`cmake --build .`行中指定正确的配置。 + +最后一步是构建应用。 为此,假定示例目录的布局如下: + +```py +example-app/ + CMakeLists.txt + example-app.cpp + +``` + +现在,我们可以运行以下命令从`example-app/`文件夹中构建应用: + +```py +mkdir build +cd build +cmake -DCMAKE_PREFIX_PATH=/path/to/libtorch .. +cmake --build . --config Release + +``` + +其中`/path/to/libtorch`应该是解压缩的 LibTorch 发行版的完整路径。 如果一切顺利,它将看起来像这样: + +```py +root@4b5a67132e81:/example-app# mkdir build +root@4b5a67132e81:/example-app# cd build +root@4b5a67132e81:/example-app/build# cmake -DCMAKE_PREFIX_PATH=/path/to/libtorch .. +-- The C compiler identification is GNU 5.4.0 +-- The CXX compiler identification is GNU 5.4.0 +-- Check for working C compiler: /usr/bin/cc +-- Check for working C compiler: /usr/bin/cc -- works +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - done +-- Detecting C compile features +-- Detecting C compile features - done +-- Check for working CXX compiler: /usr/bin/c++ +-- Check for working CXX compiler: /usr/bin/c++ -- works +-- Detecting CXX compiler ABI info +-- Detecting CXX compiler ABI info - done +-- Detecting CXX compile features +-- Detecting CXX compile features - done +-- Looking for pthread.h +-- Looking for pthread.h - found +-- Looking for pthread_create +-- Looking for pthread_create - not found +-- Looking for pthread_create in pthreads +-- Looking for pthread_create in pthreads - not found +-- Looking for pthread_create in pthread +-- Looking for pthread_create in pthread - found +-- Found Threads: TRUE +-- Configuring done +-- Generating done +-- Build files have been written to: /example-app/build +root@4b5a67132e81:/example-app/build# make +Scanning dependencies of target example-app +[ 50%] Building CXX object CMakeFiles/example-app.dir/example-app.cpp.o +[100%] Linking CXX executable example-app +[100%] Built target example-app + +``` + +如果我们提供到先前创建的跟踪`ResNet18`模型`traced_resnet_model.pt`到生成的`example-app`二进制文件的路径,则应该以友好的“确定”来回报。 请注意,如果尝试使用`my_module_model.pt`运行此示例,则会收到一条错误消息,提示您输入的形状不兼容。 `my_module_model.pt`期望使用 1D 而不是 4D。 + +```py +root@4b5a67132e81:/example-app/build# ./example-app /traced_resnet_model.pt +ok + +``` + +## 步骤 4:在 C++ 中执行脚本模块 + +在用 C++ 成功加载序列化的`ResNet18`之后,我们现在离执行它仅几行代码了! 让我们将这些行添加到 C++ 应用的`main()`函数中: + +```py +// Create a vector of inputs. +std::vector inputs; +inputs.push_back(torch::ones({1, 3, 224, 224})); + +// Execute the model and turn its output into a tensor. +at::Tensor output = module.forward(inputs).toTensor(); +std::cout << output.slice(/*dim=*/1, /*start=*/0, /*end=*/5) << '\n'; + +``` + +前两行设置了模型的输入。 我们创建一个`torch::jit::IValue`的向量(类型擦除的值类型`script::Module`方法接受并返回),并添加单个输入。 要创建输入张量,我们使用`torch::ones()`,等效于 C++ API 中的`torch.ones`。 然后,我们运行`script::Module`的`forward`方法,并将其传递给我们创建的输入向量。 作为回报,我们得到了一个新的`IValue`,我们可以通过调用`toTensor()`将其转换为张量。 + +小费 + +要总体上了解有关`torch::ones`和 PyTorch C++ API 之类的功能的更多信息,请参阅[这个页面](https://pytorch.org/cppdocs)上的文档。 PyTorch C++ API 提供了与 Python API 几乎相同的功能,使您可以像在 Python 中一样进一步操纵和处理张量。 + +在最后一行,我们打印输出的前五个条目。 由于在本教程前面的部分中,我们为 Python 中的模型提供了相同的输入,因此理想情况下,我们应该看到相同的输出。 让我们通过重新编译我们的应用并以相同的序列化模型运行它来进行尝试: + +```py +root@4b5a67132e81:/example-app/build# make +Scanning dependencies of target example-app +[ 50%] Building CXX object CMakeFiles/example-app.dir/example-app.cpp.o +[100%] Linking CXX executable example-app +[100%] Built target example-app +root@4b5a67132e81:/example-app/build# ./example-app traced_resnet_model.pt +-0.2698 -0.0381 0.4023 -0.3010 -0.0448 +[ Variable[CPUFloatType]{1,5} ] + +``` + +作为参考,Python 以前的输出为: + +```py +tensor([-0.2698, -0.0381, 0.4023, -0.3010, -0.0448], grad_fn=) + +``` + +看起来很不错! + +小费 + +要将模型移至 GPU 内存,可以编写`model.to(at::kCUDA);`。 通过调用`tensor.to(at::kCUDA)`来确保模型的输入也位于 CUDA 内存中,这将在 CUDA 内存中返回新的张量。 + +## 第 5 步:获得帮助并探索 API + +本教程有望使您对 PyTorch 模型从 Python 到 C++ 的路径有一个大致的了解。 利用本教程中介绍的概念,您应该能够从原始的“急切的” PyTorch 模型,到 Python 中的已编译`ScriptModule`,再到磁盘上的序列化文件,以及–结束循环–到可执行文件`script::Module`在 C++ 中。 + +当然,有许多我们没有介绍的概念。 例如,您可能会发现自己想要扩展使用 C++ 或 CUDA 实现的自定义运算符来扩展`ScriptModule`,并希望在纯 C++ 生产环境中加载的`ScriptModule`内执行该自定义运算符。 好消息是:这是可能的,并且得到了很好的支持! 现在,您可以浏览[这个](https://github.com/pytorch/pytorch/tree/master/test/custom_operator)文件夹作为示例,我们将很快提供一个教程。 目前,以下链接通常可能会有所帮助: + +* [Torch 脚本参考](https://pytorch.org/docs/master/jit.html) +* [PyTorch C++ API 文档](https://pytorch.org/cppdocs/) +* [PyTorch Python API 文档](https://pytorch.org/docs/) + +与往常一样,如果您遇到任何问题或疑问,可以使用我们的[论坛](https://discuss.pytorch.org/)或 [GitHub ISSUE](https://github.com/pytorch/pytorch/issues) 进行联系。 \ No newline at end of file diff --git a/pytorch/官方教程/40.md b/pytorch/官方教程/40.md new file mode 100644 index 00000000..c0c8e0f6 --- /dev/null +++ b/pytorch/官方教程/40.md @@ -0,0 +1,219 @@ +# 将模型从 PyTorch 导出到 ONNX 并使用 ONNX 运行时运行它(可选) + +> 原文: + +在本教程中,我们描述了如何将 PyTorch 中定义的模型转换为 ONNX 格式,然后在 ONNX 运行时中运行它。 + +ONNX 运行时是针对 ONNX 模型的以性能为中心的引擎,可在多个平台和硬件(Windows,Linux 和 Mac 以及 CPU 和 GPU 上)高效地进行推理。 事实证明,如[此处](https://cloudblogs.microsoft.com/opensource/2019/05/22/onnx-runtime-machine-learning-inferencing-0-4-release)所述,ONNX 运行时大大提高了多个模型的性能。 + +对于本教程,您将需要安装 [ONNX](https://github.com/onnx/onnx) 和 [ONNX 运行时](https://github.com/microsoft/onnxruntime)。 您可以使用`pip install onnx onnxruntime`获得 ONNX 和 ONNX 运行时的二进制版本。 请注意,ONNX 运行时与 Python 3.5 至 3.7 版本兼容。 + +`NOTE`:本教程需要 PyTorch `master`分支,[可以按照此处的说明进行安装](https://github.com/pytorch/pytorch#from-source) + +```py +# Some standard imports +import io +import numpy as np + +from torch import nn +import torch.utils.model_zoo as model_zoo +import torch.onnx + +``` + +超分辨率是一种提高图像,视频分辨率的方法,广泛用于图像处理或视频编辑中。 在本教程中,我们将使用一个小的超分辨率模型。 + +首先,让我们在 PyTorch 中创建一个`SuperResolution`模型。 该模型使用了[《使用高效的子像素卷积神经网络的实时单幅图像和视频超分辨率》](https://arxiv.org/abs/1609.05158)(Shi 等人)中所述的高效子像素卷积层来提高图像的分辨率受向上缩放因子的影响。 该模型期望图像的 YCbCr 的 Y 分量作为输入,并以超分辨率输出放大的 Y 分量。 + +[模型](https://github.com/pytorch/examples/blob/master/super_resolution/model.py)直接来自 PyTorch 的示例,未经修改: + +```py +# Super Resolution model definition in PyTorch +import torch.nn as nn +import torch.nn.init as init + +class SuperResolutionNet(nn.Module): + def __init__(self, upscale_factor, inplace=False): + super(SuperResolutionNet, self).__init__() + + self.relu = nn.ReLU(inplace=inplace) + self.conv1 = nn.Conv2d(1, 64, (5, 5), (1, 1), (2, 2)) + self.conv2 = nn.Conv2d(64, 64, (3, 3), (1, 1), (1, 1)) + self.conv3 = nn.Conv2d(64, 32, (3, 3), (1, 1), (1, 1)) + self.conv4 = nn.Conv2d(32, upscale_factor ** 2, (3, 3), (1, 1), (1, 1)) + self.pixel_shuffle = nn.PixelShuffle(upscale_factor) + + self._initialize_weights() + + def forward(self, x): + x = self.relu(self.conv1(x)) + x = self.relu(self.conv2(x)) + x = self.relu(self.conv3(x)) + x = self.pixel_shuffle(self.conv4(x)) + return x + + def _initialize_weights(self): + init.orthogonal_(self.conv1.weight, init.calculate_gain('relu')) + init.orthogonal_(self.conv2.weight, init.calculate_gain('relu')) + init.orthogonal_(self.conv3.weight, init.calculate_gain('relu')) + init.orthogonal_(self.conv4.weight) + +# Create the super-resolution model by using the above model definition. +torch_model = SuperResolutionNet(upscale_factor=3) + +``` + +通常,您现在将训练此模型。 但是,在本教程中,我们将下载一些预训练的权重。 请注意,此模型未经过充分训练以提供良好的准确率,此处仅用于演示目的。 + +在导出模型之前,请先调用`torch_model.eval()`或`torch_model.train(False)`,以将模型转换为推理模式,这一点很重要。 这是必需的,因为像`dropout`或`batchnorm`这样的运算符在推断和训练模式下的行为会有所不同。 + +```py +# Load pretrained model weights +model_url = 'https://s3.amazonaws.com/pytorch/test_data/export/superres_epoch100-44c6958e.pth' +batch_size = 1 # just a random number + +# Initialize model with the pretrained weights +map_location = lambda storage, loc: storage +if torch.cuda.is_available(): + map_location = None +torch_model.load_state_dict(model_zoo.load_url(model_url, map_location=map_location)) + +# set the model to inference mode +torch_model.eval() + +``` + +在 PyTorch 中导出模型是通过跟踪或脚本编写的。 本教程将以通过跟踪导出的模型为例。 要导出模型,我们调用`torch.onnx.export()`函数。 这将执行模型,并记录使用什么运算符计算输出的轨迹。 因为`export`运行模型,所以我们需要提供输入张量`x`。 只要是正确的类型和大小,其中的值就可以是随机的。 请注意,除非指定为动态轴,否则输入尺寸将在导出的 ONNX 图中固定为所有输入尺寸。 在此示例中,我们使用输入`batch_size 1`导出模型,但随后在`torch.onnx.export()`的`dynamic_axes`参数中将第一维指定为动态。 因此,导出的模型将接受大小为`[batch_size, 1, 224, 224]`的输入,其中`batch_size`可以是可变的。 + +要了解有关 PyTorch 导出接口的更多详细信息,请查看[`torch.onnx`文档](https://pytorch.org/docs/master/onnx.html)。 + +```py +# Input to the model +x = torch.randn(batch_size, 1, 224, 224, requires_grad=True) +torch_out = torch_model(x) + +# Export the model +torch.onnx.export(torch_model, # model being run + x, # model input (or a tuple for multiple inputs) + "super_resolution.onnx", # where to save the model (can be a file or file-like object) + export_params=True, # store the trained parameter weights inside the model file + opset_version=10, # the ONNX version to export the model to + do_constant_folding=True, # whether to execute constant folding for optimization + input_names = ['input'], # the model's input names + output_names = ['output'], # the model's output names + dynamic_axes={'input' : {0 : 'batch_size'}, # variable lenght axes + 'output' : {0 : 'batch_size'}}) + +``` + +我们还计算了`torch_out`(模型之后的输出),我们将用来验证导出的模型在 ONNX 运行时中运行时是否计算出相同的值。 + +但是,在通过 ONNX 运行时验证模型的输出之前,我们将使用 ONNX 的 API 检查 ONNX 模型。 首先,`onnx.load("super_resolution.onnx")`将加载保存的模型并输出`onnx.ModelProto`结构(用于捆绑 ML 模型的顶级文件/容器格式。有关更多信息,请参见[`onnx.proto`文档](https://github.com/onnx/onnx/blob/master/onnx/onnx.proto)。 然后,`onnx.checker.check_model(onnx_model)`将验证模型的结构并确认模型具有有效的架构。 通过检查模型的版本,图的结构以及节点及其输入和输出,可以验证 ONNX 图的有效性。 + +```py +import onnx + +onnx_model = onnx.load("super_resolution.onnx") +onnx.checker.check_model(onnx_model) + +``` + +现在,我们使用 ONNX 运行时的 Python API 计算输出。 这部分通常可以在单独的过程中或在另一台机器上完成,但是我们将继续同一过程,以便我们可以验证 ONNX 运行时和 PyTorch 正在为网络计算相同的值。 + +为了使用 ONNX 运行时运行模型,我们需要使用所选的配置参数为模型创建一个推理会话(此处使用默认配置)。 创建会话后,我们将使用`run()` API 评估模型。 此调用的输出是一个列表,其中包含由 ONNX 运行时计算的模型的输出。 + +```py +import onnxruntime + +ort_session = onnxruntime.InferenceSession("super_resolution.onnx") + +def to_numpy(tensor): + return tensor.detach().cpu().numpy() if tensor.requires_grad else tensor.cpu().numpy() + +# compute ONNX Runtime output prediction +ort_inputs = {ort_session.get_inputs()[0].name: to_numpy(x)} +ort_outs = ort_session.run(None, ort_inputs) + +# compare ONNX Runtime and PyTorch results +np.testing.assert_allclose(to_numpy(torch_out), ort_outs[0], rtol=1e-03, atol=1e-05) + +print("Exported model has been tested with ONNXRuntime, and the result looks good!") + +``` + +我们应该看到 PyTorch 和 ONNX 运行时的输出在数值上与给定的精度匹配(`rtol = 1e-03`和`atol = 1e-05`)。 附带说明一下,如果它们不匹配,则说明 ONNX 导出器中存在问题,因此请与我们联系。 + +## 使用 ONNX 运行时在图像上运行模型 + +到目前为止,我们已经从 PyTorch 导出了一个模型,并演示了如何使用虚拟张量作为输入在 ONNX 运行时中加载和运行该模型。 + +在本教程中,我们将使用广泛使用的著名猫图像,如下图所示 + +![cat](img/35d54d0c48ca1c52d56850a202a2c160.png) + +首先,让我们加载图片,然后使用标准的 PIL python 库对其进行预处理。 请注意,此预处理是处理数据以训练/测试神经网络的标准做法。 + +我们首先调整图像大小以适合模型输入的大小(`224x224`)。 然后,我们将图像分为 Y,Cb 和 Cr 分量。 这些分量代表灰度图像(Y),以及蓝差(Cb)和红差(Cr)色度分量。 Y 分量对人眼更敏感,我们对将要转换的这个分量很感兴趣。 提取 Y 分量后,我们将其转换为张量,这将是模型的输入。 + +```py +from PIL import Image +import torchvision.transforms as transforms + +img = Image.open("./_static/img/cat.jpg") + +resize = transforms.Resize([224, 224]) +img = resize(img) + +img_ycbcr = img.convert('YCbCr') +img_y, img_cb, img_cr = img_ycbcr.split() + +to_tensor = transforms.ToTensor() +img_y = to_tensor(img_y) +img_y.unsqueeze_(0) + +``` + +现在,作为下一步,让我们使用代表灰度尺寸调整后的猫图像的张量,并按照先前的说明在 ONNX 运行时中运行超分辨率模型。 + +```py +ort_inputs = {ort_session.get_inputs()[0].name: to_numpy(img_y)} +ort_outs = ort_session.run(None, ort_inputs) +img_out_y = ort_outs[0] + +``` + +此时,模型的输出为张量。 现在,我们将处理模型的输出,以根据输出张量构造最终的输出图像,并保存图像。 采用了来自此处的[超分辨率模型的 PyTorch 实现](https://github.com/pytorch/examples/blob/master/super_resolution/super_resolve.py)的后处理步骤。 + +```py +img_out_y = Image.fromarray(np.uint8((img_out_y[0] * 255.0).clip(0, 255)[0]), mode='L') + +# get the output image follow post-processing step from PyTorch implementation +final_img = Image.merge( + "YCbCr", [ + img_out_y, + img_cb.resize(img_out_y.size, Image.BICUBIC), + img_cr.resize(img_out_y.size, Image.BICUBIC), + ]).convert("RGB") + +# Save the image, we will compare this with the output image from mobile device +final_img.save("./_static/img/cat_superres_with_ort.jpg") + +``` + +![output\_cat](img/efb29904552d032a076d8512d4e60b95.png) + +ONNX 运行时是跨平台引擎,您可以在多个平台上以及在 CPU 和 GPU 上运行它。 + +还可以使用 Azure 机器学习服务将 ONNX 运行时部署到云中以进行模型推断。 更多信息在[此处](https://docs.microsoft.com/en-us/azure/machine-learning/service/concept-onnx)。 + +[在这里了解有关 ONNX 运行时性能的更多信息](https://github.com/microsoft/onnxruntime#high-performance)。 + +有关 ONNX 运行时的更多信息,[请点击这里](https://github.com/microsoft/onnxruntime)。 + +**脚本的总运行时间**:(0 分钟 0.000 秒) + +[下载 Python 源码:`super_resolution_with_onnxruntime.py`](../_downloads/58ce6e85b9b9e9647d302d6b48feccb0/super_resolution_with_onnxruntime.py) + +[下载 Jupyter 笔记本:`super_resolution_with_onnxruntime.ipynb`](../_downloads/8c7f0be1e1c3803fcb4c41bcd9f4226b/super_resolution_with_onnxruntime.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/41.md b/pytorch/官方教程/41.md new file mode 100644 index 00000000..4f909d3e --- /dev/null +++ b/pytorch/官方教程/41.md @@ -0,0 +1 @@ +# 前端 API \ No newline at end of file diff --git a/pytorch/官方教程/42.md b/pytorch/官方教程/42.md new file mode 100644 index 00000000..64d1de4f --- /dev/null +++ b/pytorch/官方教程/42.md @@ -0,0 +1,607 @@ +# PyTorch 中的命名张量简介(原型) + +> 原文: + +**作者**: [Richard Zou](https://github.com/zou3519) + +命名张量旨在通过允许用户将显式名称与张量维度相关联来使张量更易于使用。 在大多数情况下,采用尺寸参数的操作将接受尺寸名称,而无需按位置跟踪尺寸。 此外,命名张量使用名称来自动检查运行时是否正确使用了 API,从而提供了额外的安全性。 名称也可以用于重新排列尺寸,例如,支持“按名称广播”而不是“按位置广播”。 + +本教程旨在作为 1.3 启动中将包含的功能的指南。 到最后,您将能够: + +* 创建具有命名尺寸的张量,以及删除或重命名这些尺寸 +* 了解操作如何传播维度名称的基础 +* 了解命名尺寸如何在两个关键区域实现更清晰的代码: + + * 广播操作 + * 重塑和展开尺寸 + +最后,我们将通过使用命名张量编写一个多头注意力模块来将其付诸实践。 + +PyTorch 中的命名张量受 [Sasha Rush](https://tech.cornell.edu/people/alexander-rush/) 的启发并与之合作。 Sasha 在他的 [2019 年 1 月博客文章](http://nlp.seas.harvard.edu/NamedTensor)中提出了最初的想法和概念证明。 + +## 基础知识:命名维度 + +PyTorch 现在允许张量具有命名维度; 工厂函数采用新的名称参数,该参数将名称与每个维度相关联。 这适用于大多数工厂函数,例如 + +* `tensor` +* `empty` +* `ones` +* `zeros` +* `randn` +* `rand` + +这里我们用名字构造一个张量: + +```py +import torch +imgs = torch.randn(1, 2, 2, 3, names=('N', 'C', 'H', 'W')) +print(imgs.names) + +``` + +出: + +```py +('N', 'C', 'H', 'W') + +``` + +与[命名张量的原始博客文章](http://nlp.seas.harvard.edu/NamedTensor)不同,命名维度是有序的:`tensor.names[i]`是`tensor`的第`i`个维度的名称。 + +重命名`Tensor`尺寸的方法有两种: + +```py +# Method #1: set the .names attribute (this changes name in-place) +imgs.names = ['batch', 'channel', 'width', 'height'] +print(imgs.names) + +# Method #2: specify new names (this changes names out-of-place) +imgs = imgs.rename(channel='C', width='W', height='H') +print(imgs.names) + +``` + +出: + +```py +('batch', 'channel', 'width', 'height') +('batch', 'C', 'W', 'H') + +``` + +删除名称的首选方法是调用`tensor.rename(None)`: + +```py +imgs = imgs.rename(None) +print(imgs.names) + +``` + +出: + +```py +(None, None, None, None) + +``` + +未命名的张量(没有命名尺寸的张量)仍然可以正常工作,并且在其`repr`中没有名称。 + +```py +unnamed = torch.randn(2, 1, 3) +print(unnamed) +print(unnamed.names) + +``` + +出: + +```py +tensor([[[-0.7420, -0.3646, 0.1424]], + + [[-0.6065, -1.4888, 0.2935]]]) +(None, None, None) + +``` + +命名张量不需要命名所有尺寸。 + +```py +imgs = torch.randn(3, 1, 1, 2, names=('N', None, None, None)) +print(imgs.names) + +``` + +出: + +```py +('N', None, None, None) + +``` + +由于命名张量可以与未命名张量共存,因此我们需要一种不错的方式来编写可识别命名张量的代码,该代码可用于命名张量和未命名张量。 使用`tensor.refine_names(*names)`优化尺寸并将未命名的暗淡提升为已命名的暗淡。 细化维度定义为“重命名”,并具有以下限制: + +* 可以将`None`暗号细化为任何名称 +* 命名的维度只能精简为具有相同的名称。 + +```py +imgs = torch.randn(3, 1, 1, 2) +named_imgs = imgs.refine_names('N', 'C', 'H', 'W') +print(named_imgs.names) + +# Refine the last two dims to 'H' and 'W'. In Python 2, use the string '...' +# instead of ... +named_imgs = imgs.refine_names(..., 'H', 'W') +print(named_imgs.names) + +def catch_error(fn): + try: + fn() + assert False + except RuntimeError as err: + err = str(err) + if len(err) > 180: + err = err[:180] + "..." + print(err) + +named_imgs = imgs.refine_names('N', 'C', 'H', 'W') + +# Tried to refine an existing name to a different name +catch_error(lambda: named_imgs.refine_names('N', 'C', 'H', 'width')) + +``` + +出: + +```py +('N', 'C', 'H', 'W') +(None, None, 'H', 'W') +refine_names: cannot coerce Tensor['N', 'C', 'H', 'W'] to Tensor['N', 'C', 'H', 'width'] because 'W' is different from 'width' at index 3 + +``` + +大多数简单的操作都会传播名称。 命名张量的最终目标是所有操作以合理,直观的方式传播名称。 在 1.3 版本发布时,已添加了对许多常用操作的支持。 例如,这里是`.abs()`: + +```py +print(named_imgs.abs().names) + +``` + +出: + +```py +('N', 'C', 'H', 'W') + +``` + +### 访问器和归约 + +可以使用尺寸名称来引用尺寸而不是位置尺寸。 这些操作还传播名称。 索引(基本索引和高级索引)尚未实现,但仍在规划中。 使用上面的`named_imgs`张量,我们可以执行以下操作: + +```py +output = named_imgs.sum('C') # Perform a sum over the channel dimension +print(output.names) + +img0 = named_imgs.select('N', 0) # get one image +print(img0.names) + +``` + +出: + +```py +('N', 'H', 'W') +('C', 'H', 'W') + +``` + +### 名称推断 + +名称在称为**名称推断**的两步过程中在操作上传播: + +1. **检查名称**:运算符可以在运行时执行自动检查,以检查某些尺寸名称是否匹配。 +2. **传播名称**:名称推断将输出名称传播到输出张量。 + +让我们看一个非常小的例子,添加 2 个一维张量,不进行广播。 + +```py +x = torch.randn(3, names=('X',)) +y = torch.randn(3) +z = torch.randn(3, names=('Z',)) + +``` + +**检查名称**:首先,我们将检查这两个张量的名称是否相匹配。 当且仅当两个名称相等(字符串相等)或至少一个为`None`(`None`本质上是一个特殊的通配符名称)时,两个名称才匹配。 因此,这三者中唯一会出错的是`x + z`: + +```py +catch_error(lambda: x + z) + +``` + +出: + +```py +Error when attempting to broadcast dims ['X'] and dims ['Z']: dim 'X' and dim 'Z' are at the same position from the right but do not match. + +``` + +**传播名称**:通过返回两个名称中最精确的名称来统一这两个名称。 使用`x + y`时,`X`比`None`更精细。 + +```py +print((x + y).names) + +``` + +出: + +```py +('X',) + +``` + +大多数名称推断规则都很简单明了,但是其中一些可能具有意想不到的语义。 让我们来看看您可能会遇到的一对:广播和矩阵乘法。 + +#### 广播 + +命名张量不会改变广播行为; 他们仍然按位置广播。 但是,在检查两个尺寸是否可以广播时,PyTorch 还会检查这些尺寸的名称是否匹配。 + +这导致命名张量防止广播操作期间意外对齐。 在下面的示例中,我们将`per_batch_scale`应用于`imgs`。 + +```py +imgs = torch.randn(2, 2, 2, 2, names=('N', 'C', 'H', 'W')) +per_batch_scale = torch.rand(2, names=('N',)) +catch_error(lambda: imgs * per_batch_scale) + +``` + +出: + +```py +Error when attempting to broadcast dims ['N', 'C', 'H', 'W'] and dims ['N']: dim 'W' and dim 'N' are at the same position from the right but do not match. + +``` + +如果没有`names`,则`per_batch_scale`张量与`imgs`的最后一个尺寸对齐,这不是我们想要的。 我们确实想通过将`per_batch_scale`与`imgs`的批量尺寸对齐来执行操作。 有关如何按名称对齐张量的信息,请参见新的“按名称显式广播”功能,如下所述。 + +#### 矩阵乘法 + +`torch.mm(A, B)`在`A`的第二个暗角和`B`的第一个暗角之间执行点积,返回具有`A`的第一个暗角和`B`的第二个暗角的张量。 (其他`matmul`函数,例如`torch.matmul`,`torch.mv`和`torch.dot`的行为类似)。 + +```py +markov_states = torch.randn(128, 5, names=('batch', 'D')) +transition_matrix = torch.randn(5, 5, names=('in', 'out')) + +# Apply one transition +new_state = markov_states @ transition_matrix +print(new_state.names) + +``` + +出: + +```py +('batch', 'out') + +``` + +如您所见,矩阵乘法不会检查收缩尺寸是否具有相同的名称。 + +接下来,我们将介绍命名张量启用的两个新行为:按名称的显式广播以及按名称的展平和展平尺寸 + +### 新行为:按名称显式广播 + +有关使用多个维度的主要抱怨之一是需要`unsqueeze`“虚拟”维度,以便可以进行操作。 例如,在之前的每批比例示例中,使用未命名的张量,我们将执行以下操作: + +```py +imgs = torch.randn(2, 2, 2, 2) # N, C, H, W +per_batch_scale = torch.rand(2) # N + +correct_result = imgs * per_batch_scale.view(2, 1, 1, 1) # N, C, H, W +incorrect_result = imgs * per_batch_scale.expand_as(imgs) +assert not torch.allclose(correct_result, incorrect_result) + +``` + +通过使用名称,我们可以使这些操作更安全(并且易于与尺寸数量无关)。 我们提供了一个新的`tensor.align_as(other)`操作,可以对张量的尺寸进行排列以匹配`other.names`中指定的顺序,并在适当的地方添加一个尺寸的尺寸(`tensor.align_to(*names)`也可以): + +```py +imgs = imgs.refine_names('N', 'C', 'H', 'W') +per_batch_scale = per_batch_scale.refine_names('N') + +named_result = imgs * per_batch_scale.align_as(imgs) +# note: named tensors do not yet work with allclose +assert torch.allclose(named_result.rename(None), correct_result) + +``` + +### 新行为:按名称展平或取消展平维度 + +一种常见的操作是展平和展平尺寸。 现在,用户可以使用`view`,`reshape`或`flatten`来执行此操作; 用例包括将批量尺寸展平以将张量发送到必须采用一定数量尺寸的输入的运算符(即`conv2d`采用 4D 输入)。 + +为了使这些操作比查看或整形更具语义意义,我们引入了一种新的`tensor.unflatten(dim, namedshape)`方法并更新`flatten`以使用名称:`tensor.flatten(dims, new_dim)`。 + +`flatten`只能展平相邻的尺寸,但也可以用于不连续的维度。 必须将名称和形状传递到`unflatten`中,该形状是`(dim, size)`元组的列表,以指定如何展开维度。 可以在`flatten`期间保存`unflatten`的尺寸,但我们尚未这样做。 + +```py +imgs = imgs.flatten(['C', 'H', 'W'], 'features') +print(imgs.names) + +imgs = imgs.unflatten('features', (('C', 2), ('H', 2), ('W', 2))) +print(imgs.names) + +``` + +出: + +```py +('N', 'features') +('N', 'C', 'H', 'W') + +``` + +### Autograd 支持 + +Autograd 当前会忽略所有张量上的名称,只是将它们视为常规张量。 梯度计算是正确的,但是我们失去了名称赋予我们的安全性。 在路线图上引入名称以自动微分的处理。 + +```py +x = torch.randn(3, names=('D',)) +weight = torch.randn(3, names=('D',), requires_grad=True) +loss = (x - weight).abs() +grad_loss = torch.randn(3) +loss.backward(grad_loss) + +correct_grad = weight.grad.clone() +print(correct_grad) # Unnamed for now. Will be named in the future + +weight.grad.zero_() +grad_loss = grad_loss.refine_names('C') +loss = (x - weight).abs() +# Ideally we'd check that the names of loss and grad_loss match, but we don't +# yet +loss.backward(grad_loss) + +print(weight.grad) # still unnamed +assert torch.allclose(weight.grad, correct_grad) + +``` + +出: + +```py +tensor([0.5398, 0.7907, 0.7784]) +tensor([0.5398, 0.7907, 0.7784]) + +``` + +### 其他受支持的(和不受支持的)功能 + +[有关 1.3 发行版支持的功能的详细分类,请参见此处](https://pytorch.org/docs/stable/named_tensor.html)。 + +特别是,我们要指出当前不支持的三个重要函数: + +* 通过`torch.save`或`torch.load`保存或加载命名张量 +* 通过`torch.multiprocessing`进行多重处理 +* JIT 支持; 例如,以下将错误 + +```py +imgs_named = torch.randn(1, 2, 2, 3, names=('N', 'C', 'H', 'W')) + +@torch.jit.script +def fn(x): + return x + +catch_error(lambda: fn(imgs_named)) + +``` + +出: + +```py +NYI: Named tensors are currently unsupported in TorchScript. As a workaround please drop names via `tensor = tensor.rename(None)`. + +``` + +解决方法是,在使用尚不支持命名张量的任何东西之前,请通过`tensor = tensor.rename(None)`删除名称。 + +### 更长的例子:多头关注 + +现在,我们将通过一个完整的示例来实现一个常见的 PyTorch `nn.Module`:多头注意。 我们假设读者已经熟悉多头注意; 要进行复习,请查看[此说明](https://nlp.seas.harvard.edu/2018/04/03/attention.html)或[此说明](http://jalammar.github.io/illustrated-transformer/)。 + +我们采用 [ParlAI](https://github.com/facebookresearch/ParlAI) 来实现多头注意力的实现; 具体来说[此处](https://github.com/facebookresearch/ParlAI/blob/f7db35cba3f3faf6097b3e6b208442cd564783d9/parlai/agents/transformer/modules.py#L907)。 阅读该示例中的代码; 然后,与下面的代码进行比较,注意有四个标记为(I),(II),(III)和(IV)的位置,使用命名张量可以使代码更易读; 在代码块之后,我们将深入探讨其中的每一个。 + +```py +import torch.nn as nn +import torch.nn.functional as F +import math + +class MultiHeadAttention(nn.Module): + def __init__(self, n_heads, dim, dropout=0): + super(MultiHeadAttention, self).__init__() + self.n_heads = n_heads + self.dim = dim + + self.attn_dropout = nn.Dropout(p=dropout) + self.q_lin = nn.Linear(dim, dim) + self.k_lin = nn.Linear(dim, dim) + self.v_lin = nn.Linear(dim, dim) + nn.init.xavier_normal_(self.q_lin.weight) + nn.init.xavier_normal_(self.k_lin.weight) + nn.init.xavier_normal_(self.v_lin.weight) + self.out_lin = nn.Linear(dim, dim) + nn.init.xavier_normal_(self.out_lin.weight) + + def forward(self, query, key=None, value=None, mask=None): + # (I) + query = query.refine_names(..., 'T', 'D') + self_attn = key is None and value is None + if self_attn: + mask = mask.refine_names(..., 'T') + else: + mask = mask.refine_names(..., 'T', 'T_key') # enc attn + + dim = query.size('D') + assert dim == self.dim, \ + f'Dimensions do not match: {dim} query vs {self.dim} configured' + assert mask is not None, 'Mask is None, please specify a mask' + n_heads = self.n_heads + dim_per_head = dim // n_heads + scale = math.sqrt(dim_per_head) + + # (II) + def prepare_head(tensor): + tensor = tensor.refine_names(..., 'T', 'D') + return (tensor.unflatten('D', [('H', n_heads), ('D_head', dim_per_head)]) + .align_to(..., 'H', 'T', 'D_head')) + + assert value is None + if self_attn: + key = value = query + elif value is None: + # key and value are the same, but query differs + key = key.refine_names(..., 'T', 'D') + value = key + dim = key.size('D') + + # Distinguish between query_len (T) and key_len (T_key) dims. + k = prepare_head(self.k_lin(key)).rename(T='T_key') + v = prepare_head(self.v_lin(value)).rename(T='T_key') + q = prepare_head(self.q_lin(query)) + + dot_prod = q.div_(scale).matmul(k.align_to(..., 'D_head', 'T_key')) + dot_prod.refine_names(..., 'H', 'T', 'T_key') # just a check + + # (III) + attn_mask = (mask == 0).align_as(dot_prod) + dot_prod.masked_fill_(attn_mask, -float(1e20)) + + attn_weights = self.attn_dropout(F.softmax(dot_prod / scale, + dim='T_key')) + + # (IV) + attentioned = ( + attn_weights.matmul(v).refine_names(..., 'H', 'T', 'D_head') + .align_to(..., 'T', 'H', 'D_head') + .flatten(['H', 'D_head'], 'D') + ) + + return self.out_lin(attentioned).refine_names(..., 'T', 'D') + +``` + +(I)细化输入张量维度 + +```py +def forward(self, query, key=None, value=None, mask=None): + # (I) + query = query.refine_names(..., 'T', 'D') + +``` + +`query = query.refine_names(..., 'T', 'D')`用作可执行的文档,并将输入尺寸提升为名称。 它检查最后两个维度是否可以调整为`['T', 'D']`,以防止在以后出现潜在的无声或混乱的尺寸不匹配错误。 + +(II)在`prepare_head`中操纵尺寸 + +```py +# (II) +def prepare_head(tensor): + tensor = tensor.refine_names(..., 'T', 'D') + return (tensor.unflatten('D', [('H', n_heads), ('D_head', dim_per_head)]) + .align_to(..., 'H', 'T', 'D_head')) + +``` + +首先要注意的是代码如何清楚地说明输入和输出尺寸:输入张量必须以`T`和`D`变暗结束,输出张量应以`H`,`T`和`D_head`维度结束。 + +要注意的第二件事是代码清楚地描述了正在发生的事情。 `prepare_head`获取键,查询和值,并将嵌入的维度拆分为多个头部,最后将维度顺序重新排列为`[..., 'H', 'T', 'D_head']`。 ParlAI 使用`view`和`transpose`操作实现以下`prepare_head`: + +```py +def prepare_head(tensor): + # input is [batch_size, seq_len, n_heads * dim_per_head] + # output is [batch_size * n_heads, seq_len, dim_per_head] + batch_size, seq_len, _ = tensor.size() + tensor = tensor.view(batch_size, tensor.size(1), n_heads, dim_per_head) + tensor = ( + tensor.transpose(1, 2) + .contiguous() + .view(batch_size * n_heads, seq_len, dim_per_head) + ) + return tensor + +``` + +我们命名的张量变量使用的操作虽然较为冗长,但比`view`和`transpose`具有更多的语义含义,并包含以名称形式出现的可执行文档。 + +(III)按名称显式广播 + +```py +def ignore(): + # (III) + attn_mask = (mask == 0).align_as(dot_prod) + dot_prod.masked_fill_(attn_mask, -float(1e20)) + +``` + +`mask`通常具有暗淡`[N, T]`(在自我关注的情况下)或`[N, T, T_key]`(对于编码器注意的情况),而`dot_prod`具有暗淡的`[N, H, T, T_key]`。 为了使`mask`与`dot_prod`正确广播,我们通常会在自注意的情况下将的调暗`1`和`-1`压下,在编码器的情况下,我们将`unsqueeze`调暗`unsqueeze` 。 使用命名张量,我们只需使用`align_as`将`attn_mask`与`dot_prod`对齐,而不必担心`unsqueeze`变暗的位置。 + +(IV)使用`align_to`和`flatten`进行更多尺寸操作 + +```py +def ignore(): + # (IV) + attentioned = ( + attn_weights.matmul(v).refine_names(..., 'H', 'T', 'D_head') + .align_to(..., 'T', 'H', 'D_head') + .flatten(['H', 'D_head'], 'D') + ) + +``` + +在这里,与(II)一样,`align_to`和`flatten`在语义上比`view`和`transpose`更有意义(尽管更冗长)。 + +### 运行示例 + +```py +n, t, d, h = 7, 5, 2 * 3, 3 +query = torch.randn(n, t, d, names=('N', 'T', 'D')) +mask = torch.ones(n, t, names=('N', 'T')) +attn = MultiHeadAttention(h, d) +output = attn(query, mask=mask) +# works as expected! +print(output.names) + +``` + +出: + +```py +('N', 'T', 'D') + +``` + +以上工作正常。 此外,请注意,在代码中我们根本没有提到批量维度的名称。 实际上,我们的`MultiHeadAttention`模块与批量尺寸的存在无关。 + +```py +query = torch.randn(t, d, names=('T', 'D')) +mask = torch.ones(t, names=('T',)) +output = attn(query, mask=mask) +print(output.names) + +``` + +出: + +```py +('T', 'D') + +``` + +### 总结 + +感谢您的阅读! 命名张量仍在发展中。 如果您有反馈和/或改进建议,请通过创建 [ISSUE](https://github.com/pytorch/pytorch/issues) 来通知我们。 + +**脚本的总运行时间**:(0 分钟 0.094 秒) + +[下载 Python 源码:`named_tensor_tutorial.py`](../_downloads/1e94d0ce96a0c8097f002bcbe94c35d7/named_tensor_tutorial.py) + +[下载 Jupyter 笔记本:`named_tensor_tutorial.ipynb`](../_downloads/90d6df7aa4b65bb035e19943c6f92ea0/named_tensor_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/43.md b/pytorch/官方教程/43.md new file mode 100644 index 00000000..6a73d07d --- /dev/null +++ b/pytorch/官方教程/43.md @@ -0,0 +1,416 @@ +# PyTorch 中通道在最后的内存格式(beta) + +> 原文: + +**作者**: [Vitaly Fedyunin](https://github.com/VitalyFedyunin) + +## 什么是通道在最后 + +通道在最后的内存格式是在保留内存尺寸的顺序中对 NCHW 张量进行排序的另一种方法。 通道最后一个张量的排序方式使通道成为最密集的维度(又称为每像素存储图像)。 + +例如,NCHW 张量的经典(连续)存储(在我们的示例中是具有 3 个颜色通道的两个`2x2`图像)如下所示: + +![classic_memory_format](img/77e0660b596f377125122a2409288181.png) + +通道最后的存储格式对数据的排序方式不同: + +![channels_last_memory_format](img/462373919a0dfe17cd816fa0d8af140c.png) + +Pytorch 通过使用现有的跨步结构支持内存格式(并提供与现有模型(包括 eager,JIT 和 TorchScript)的向后兼容性)。 例如,通道在最后的格式中的`10x3x16x16`批量的步幅等于`(768, 1, 48, 3)`。 + +通道最后一个存储格式仅适用于 4D NCWH 张量。 + +```py +import torch +N, C, H, W = 10, 3, 32, 32 + +``` + +## 内存格式 API + +这是在连续和通道最后存储格式之间转换张量的方法。 + +经典 PyTorch 连续张量 + +```py +x = torch.empty(N, C, H, W) +print(x.stride()) # Ouputs: (3072, 1024, 32, 1) + +``` + +出: + +```py +(3072, 1024, 32, 1) + +``` + +转换运算符 + +```py +x = x.contiguous(memory_format=torch.channels_last) +print(x.shape) # Outputs: (10, 3, 32, 32) as dimensions order preserved +print(x.stride()) # Outputs: (3072, 1, 96, 3) + +``` + +出: + +```py +torch.Size([10, 3, 32, 32]) +(3072, 1, 96, 3) + +``` + +返回连续 + +```py +x = x.contiguous(memory_format=torch.contiguous_format) +print(x.stride()) # Outputs: (3072, 1024, 32, 1) + +``` + +出: + +```py +(3072, 1024, 32, 1) + +``` + +替代选择 + +```py +x = x.to(memory_format=torch.channels_last) +print(x.stride()) # Ouputs: (3072, 1, 96, 3) + +``` + +出: + +```py +(3072, 1, 96, 3) + +``` + +格式检查 + +```py +print(x.is_contiguous(memory_format=torch.channels_last)) # Ouputs: True + +``` + +出: + +```py +True + +``` + +最后创建为渠道 + +```py +x = torch.empty(N, C, H, W, memory_format=torch.channels_last) +print(x.stride()) # Ouputs: (3072, 1, 96, 3) + +``` + +出: + +```py +(3072, 1, 96, 3) + +``` + +`clone`保留内存格式 + +```py +y = x.clone() +print(y.stride()) # Ouputs: (3072, 1, 96, 3) + +``` + +出: + +```py +(3072, 1, 96, 3) + +``` + +`to`,`cuda`,`float`…保留内存格式 + +```py +if torch.cuda.is_available(): + y = x.cuda() + print(y.stride()) # Ouputs: (3072, 1, 96, 3) + +``` + +出: + +```py +(3072, 1, 96, 3) + +``` + +`empty_like`和`*_like`运算符保留内存格式 + +```py +y = torch.empty_like(x) +print(y.stride()) # Ouputs: (3072, 1, 96, 3) + +``` + +出: + +```py +(3072, 1, 96, 3) + +``` + +点向运算符保留内存格式 + +```py +z = x + y +print(z.stride()) # Ouputs: (3072, 1, 96, 3) + +``` + +出: + +```py +(3072, 1, 96, 3) + +``` + +转换,`Batchnorm`模块支持通道在最后(仅适用于`CudNN >= 7.6`) + +```py +if torch.backends.cudnn.version() >= 7603: + input = torch.randint(1, 10, (2, 8, 4, 4), dtype=torch.float32, device="cuda", requires_grad=True) + model = torch.nn.Conv2d(8, 4, 3).cuda().float() + + input = input.contiguous(memory_format=torch.channels_last) + model = model.to(memory_format=torch.channels_last) # Module parameters need to be Channels Last + + out = model(input) + print(out.is_contiguous(memory_format=torch.channels_last)) # Ouputs: True + +``` + +出: + +```py +True + +``` + +## 性能提升 + +在具有张量核心支持的 Nvidia 硬件上观察到了最大的性能提升。 在运行 [Nvidia](https://github.com/NVIDIA/apex) 提供的 AMP(自动混合精度)训练脚本时,我们可以将性能提高 22% 以上。 + +`python main_amp.py -a resnet50 --b 200 --workers 16 --opt-level O2  ./data` + +```py +# opt_level = O2 +# keep_batchnorm_fp32 = None +# loss_scale = None +# CUDNN VERSION: 7603 +# => creating model 'resnet50' +# Selected optimization level O2: FP16 training with FP32 batchnorm and FP32 master weights. +# Defaults for this optimization level are: +# enabled : True +# opt_level : O2 +# cast_model_type : torch.float16 +# patch_torch_functions : False +# keep_batchnorm_fp32 : True +# master_weights : True +# loss_scale : dynamic +# Processing user overrides (additional kwargs that are not None)... +# After processing overrides, optimization options are: +# enabled : True +# opt_level : O2 +# cast_model_type : torch.float16 +# patch_torch_functions : False +# keep_batchnorm_fp32 : True +# master_weights : True +# loss_scale : dynamic +# Epoch: [0][10/125] Time 0.866 (0.866) Speed 230.949 (230.949) Loss 0.6735125184 (0.6735) Prec@1 61.000 (61.000) Prec@5 100.000 (100.000) +# Epoch: [0][20/125] Time 0.259 (0.562) Speed 773.481 (355.693) Loss 0.6968704462 (0.6852) Prec@1 55.000 (58.000) Prec@5 100.000 (100.000) +# Epoch: [0][30/125] Time 0.258 (0.461) Speed 775.089 (433.965) Loss 0.7877287269 (0.7194) Prec@1 51.500 (55.833) Prec@5 100.000 (100.000) +# Epoch: [0][40/125] Time 0.259 (0.410) Speed 771.710 (487.281) Loss 0.8285319805 (0.7467) Prec@1 48.500 (54.000) Prec@5 100.000 (100.000) +# Epoch: [0][50/125] Time 0.260 (0.380) Speed 770.090 (525.908) Loss 0.7370464802 (0.7447) Prec@1 56.500 (54.500) Prec@5 100.000 (100.000) +# Epoch: [0][60/125] Time 0.258 (0.360) Speed 775.623 (555.728) Loss 0.7592862844 (0.7472) Prec@1 51.000 (53.917) Prec@5 100.000 (100.000) +# Epoch: [0][70/125] Time 0.258 (0.345) Speed 774.746 (579.115) Loss 1.9698858261 (0.9218) Prec@1 49.500 (53.286) Prec@5 100.000 (100.000) +# Epoch: [0][80/125] Time 0.260 (0.335) Speed 770.324 (597.659) Loss 2.2505953312 (1.0879) Prec@1 50.500 (52.938) Prec@5 100.000 (100.000) + +``` + +传递`--channels-last true`允许以通道在最后的格式运行模型,观察到 22% 的表现增益。 + +`python main_amp.py -a resnet50 --b 200 --workers 16 --opt-level O2 --channels-last true ./data` + +```py +# opt_level = O2 +# keep_batchnorm_fp32 = None +# loss_scale = None +# +# CUDNN VERSION: 7603 +# +# => creating model 'resnet50' +# Selected optimization level O2: FP16 training with FP32 batchnorm and FP32 master weights. +# +# Defaults for this optimization level are: +# enabled : True +# opt_level : O2 +# cast_model_type : torch.float16 +# patch_torch_functions : False +# keep_batchnorm_fp32 : True +# master_weights : True +# loss_scale : dynamic +# Processing user overrides (additional kwargs that are not None)... +# After processing overrides, optimization options are: +# enabled : True +# opt_level : O2 +# cast_model_type : torch.float16 +# patch_torch_functions : False +# keep_batchnorm_fp32 : True +# master_weights : True +# loss_scale : dynamic +# +# Epoch: [0][10/125] Time 0.767 (0.767) Speed 260.785 (260.785) Loss 0.7579724789 (0.7580) Prec@1 53.500 (53.500) Prec@5 100.000 (100.000) +# Epoch: [0][20/125] Time 0.198 (0.482) Speed 1012.135 (414.716) Loss 0.7007197738 (0.7293) Prec@1 49.000 (51.250) Prec@5 100.000 (100.000) +# Epoch: [0][30/125] Time 0.198 (0.387) Speed 1010.977 (516.198) Loss 0.7113101482 (0.7233) Prec@1 55.500 (52.667) Prec@5 100.000 (100.000) +# Epoch: [0][40/125] Time 0.197 (0.340) Speed 1013.023 (588.333) Loss 0.8943189979 (0.7661) Prec@1 54.000 (53.000) Prec@5 100.000 (100.000) +# Epoch: [0][50/125] Time 0.198 (0.312) Speed 1010.541 (641.977) Loss 1.7113249302 (0.9551) Prec@1 51.000 (52.600) Prec@5 100.000 (100.000) +# Epoch: [0][60/125] Time 0.198 (0.293) Speed 1011.163 (683.574) Loss 5.8537774086 (1.7716) Prec@1 50.500 (52.250) Prec@5 100.000 (100.000) +# Epoch: [0][70/125] Time 0.198 (0.279) Speed 1011.453 (716.767) Loss 5.7595844269 (2.3413) Prec@1 46.500 (51.429) Prec@5 100.000 (100.000) +# Epoch: [0][80/125] Time 0.198 (0.269) Speed 1011.827 (743.883) Loss 2.8196096420 (2.4011) Prec@1 47.500 (50.938) Prec@5 100.000 (100.000) + +``` + +以下模型列表完全支持通道在最后,并在 Volta 设备上显示了 8%-35% 的表现增益:`alexnet`,`mnasnet0_5`,`mnasnet0_75`,`mnasnet1_0`,`mnasnet1_3`,`mobilenet_v2`,`resnet101`,`resnet152`,`resnet18`,`resnet34`,`resnet50`,`resnext50_32x4d`,`shufflenet_v2_x0_5`,`shufflenet_v2_x1_0`,`shufflenet_v2_x1_5`,`shufflenet_v2_x2_0`,`squeezenet1_0`,`squeezenet1_1`,`vgg11` ,`vgg11_bn`,`vgg13`,`vgg13_bn`,`vgg16`,`vgg16_bn`,`vgg19`,`vgg19_bn`,`wide_resnet101_2`,`wide_resnet50_2` + +## 转换现有模型 + +通道在最后支持不受现有模型的限制,因为只要输入格式正确,任何模型都可以转换为通道在最后,并通过图传播格式。 + +```py +# Need to be done once, after model initialization (or load) +model = model.to(memory_format=torch.channels_last) # Replace with your model + +# Need to be done for every input +input = input.to(memory_format=torch.channels_last) # Replace with your input +output = model(input) + +``` + +但是,并非所有运算符都完全转换为支持通道在最后(通常返回连续输出)。 这意味着您需要根据[支持的运算符列表](https://github.com/pytorch/pytorch/wiki/Operators-with-Channels-Last-support)来验证已使用运算符的列表,或将内存格式检查引入急切的执行模式并运行模型。 + +运行以下代码后,如果运算符的输出与输入的存储格式不匹配,运算符将引发异常。 + +```py +def contains_cl(args): + for t in args: + if isinstance(t, torch.Tensor): + if t.is_contiguous(memory_format=torch.channels_last) and not t.is_contiguous(): + return True + elif isinstance(t, list) or isinstance(t, tuple): + if contains_cl(list(t)): + return True + return False + +def print_inputs(args, indent=''): + for t in args: + if isinstance(t, torch.Tensor): + print(indent, t.stride(), t.shape, t.device, t.dtype) + elif isinstance(t, list) or isinstance(t, tuple): + print(indent, type(t)) + print_inputs(list(t), indent=indent + ' ') + else: + print(indent, t) + +def check_wrapper(fn): + name = fn.__name__ + + def check_cl(*args, **kwargs): + was_cl = contains_cl(args) + try: + result = fn(*args, **kwargs) + except Exception as e: + print("`{}` inputs are:".format(name)) + print_inputs(args) + print('-------------------') + raise e + failed = False + if was_cl: + if isinstance(result, torch.Tensor): + if result.dim() == 4 and not result.is_contiguous(memory_format=torch.channels_last): + print("`{}` got channels_last input, but output is not channels_last:".format(name), + result.shape, result.stride(), result.device, result.dtype) + failed = True + if failed and True: + print("`{}` inputs are:".format(name)) + print_inputs(args) + raise Exception( + 'Operator `{}` lost channels_last property'.format(name)) + return result + return check_cl + +old_attrs = dict() + +def attribute(m): + old_attrs[m] = dict() + for i in dir(m): + e = getattr(m, i) + exclude_functions = ['is_cuda', 'has_names', 'numel', + 'stride', 'Tensor', 'is_contiguous', '__class__'] + if i not in exclude_functions and not i.startswith('_') and '__call__' in dir(e): + try: + old_attrs[m][i] = e + setattr(m, i, check_wrapper(e)) + except Exception as e: + print(i) + print(e) + +attribute(torch.Tensor) +attribute(torch.nn.functional) +attribute(torch) + +``` + +出: + +```py +Optional +'_Optional' object has no attribute '__name__' + +``` + +如果您发现不支持通道在最后的张量的运算符并且想要贡献力量,请随时使用[以下开发人员指南](https://github.com/pytorch/pytorch/wiki/Writing-memory-format-aware-operators)。 + +下面的代码是恢复火炬的属性。 + +```py +for (m, attrs) in old_attrs.items(): + for (k,v) in attrs.items(): + setattr(m, k, v) + +``` + +## 要做的工作 + +仍有许多事情要做,例如: + +* 解决 N1HW 和 NC11 张量的歧义; +* 测试分布式训练支持; +* 提高运算符覆盖率。 + +如果您有反馈和/或改进建议,请通过创建 [ISSUE](https://github.com/pytorch/pytorch/issues) 来通知我们。 + +**脚本的总运行时间**:(0 分钟 2.300 秒) + +[下载 Python 源码:`memory_format_tutorial.py`](../_downloads/6c290a5fc635f734b10bbca97b52d2f1/memory_format_tutorial.py) + +[下载 Jupyter 笔记本:`memory_format_tutorial.ipynb`](../_downloads/6f7327daa2a9b857365f893069d0bace/memory_format_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/44.md b/pytorch/官方教程/44.md new file mode 100644 index 00000000..e34a4a5a --- /dev/null +++ b/pytorch/官方教程/44.md @@ -0,0 +1,965 @@ +# 使用 PyTorch C++ 前端 + +> 原文: + +PyTorch C++ 前端是 PyTorch 机器学习框架的纯 C++ 接口。 虽然 PyTorch 的主要接口自然是 Python,但此 Python API 位于强大的 C++ 代码库之上,提供基本的数据结构和功能,例如张量和自动微分。 C++ 前端公开了纯 C++ 11 API,该 API 使用机器学习训练和推理所需的工具扩展了此基础 C++ 代码库。 这包括用于神经网络建模的通用组件的内置集合; 使用自定义模块扩展此集合的 API; 一个流行的优化算法库,例如随机梯度下降; 具有 API 的并行数据加载器,用于定义和加载数据集; 序列化例程等。 + +本教程将引导您完成使用 C++ 前端训练模型的端到端示例。 具体来说,我们将训练 [DCGAN](https://arxiv.org/abs/1511.06434) (一种生成模型),以生成 MNIST 数字的图像。 虽然从概念上讲是一个简单的示例,但它足以使您对 PyTorch C++ 前端有个大概的了解,并且可以满足您训练更复杂模型的需求。 我们将从一些鼓舞人心的词开始,说明您为什么要使用 C++ 前端,然后直接深入定义和训练我们的模型。 + +小费 + +观看[来自 CppCon 2018 的简短演讲](https://www.youtube.com/watch?v=auRPXMMHJzc),获得有关 C++ 前端的快速(幽默)演示。 + +小费 + +[本笔记](https://pytorch.org/cppdocs/frontend.html)概述了 C++ 前端的组件和设计原理。 + +小费 + +有关 PyTorch C++ 生态系统的文档,请访问[这个页面](https://pytorch.org/cppdocs)。 您可以在此处找到高级描述以及 API 级文档。 + +## 动机 + +在我们开始 GAN 和 MNIST 数字的激动人心的旅程之前,让我们退后一步,讨论为什么要使用 C++ 前端而不是 Python。 我们(PyTorch 团队)创建了 C++ 前端,以便能够在无法使用 Python 或根本不适合该工具的环境中进行研究。 此类环境的示例包括: + +* **低延迟系统**:您可能希望在具有高每秒帧数和低延迟要求的纯 C++ 游戏引擎中进行强化学习研究。 与 Python 库相比,使用纯 C++ 库更适合这种环境。 由于 Python 解释器的缓慢性,Python 可能根本无法处理。 +* **高度多线程环境**:由于全局解释器锁定(GIL),Python 一次不能运行多个系统线程。 多处理是一种替代方法,但可伸缩性却不如它,并且存在很多缺点。 C++ 没有这样的约束,线程易于使用和创建。 需要重型并行化的模型,例如[深度神经演化](https://eng.uber.com/deep-neuroevolution/)中使用的模型,可以从中受益。 +* **现有 C++ 代码库**:您可能是现有 C++ 应用的所有者,该应用从事从后端服务器中的网页服务到照片编辑软件中的 3D 图形渲染等所有工作,并且希望将机器学习方法集成到您的系统中。 C++ 前端使您可以继续使用 C++,并避免在 Python 和 C++ 之间来回绑定的麻烦,同时保留了传统 PyTorch(Python)体验的大部分灵活性和直观性。 + +C++ 前端无意与 Python 前端竞争。 它是对它的补充。 我们知道研究人员和工程师都喜欢 PyTorch,因为它具有简单,灵活和直观的 API。 我们的目标是确保您可以在所有可能的环境(包括上述环境)中利用这些核心设计原则。 如果这些场景中的一种很好地描述了您的用例,或者您只是感兴趣或好奇,请在以下段落中继续研究 C++ 前端。 + +小费 + +C++ 前端试图提供一个与 Python 前端尽可能接近的 API。 如果您对 Python 前端有丰富的经验,并且问过自己“我如何使用 C++ 前端 X?”,请像在 Python 中那样编写代码,而且大多数情况下,相同的函数和方法也可以在 C++ 中使用,就像在 Python 中一样(只记得用双冒号替换点)。 + +## 编写基本应用 + +首先,编写一个最小的 C++ 应用,以验证我们是否在同一页面上了解我们的设置和构建环境。 首先,您需要获取 *LibTorch* 发行版的副本-我们现成的 zip 归档文件,其中打包了使用 C++ 前端所需的所有相关标头,库和 CMake 构建文件。 LibTorch 发行版可从 [PyTorch 网站](https://pytorch.org/get-started/locally/)下载,适用于 Linux,MacOS 和 Windows。 本教程的其余部分将假定基本的 Ubuntu Linux 环境,但是您也可以在 MacOS 或 Windows 上随意进行操作。 + +小费 + +有关[安装 PyTorch](https://pytorch.org/cppdocs/installing.html) 的 C++ 发行版的说明,更详细地描述了以下步骤。 + +小费 + +在 Windows 上,调试和发行版本不兼容 ABI。 如果计划以调试模式构建项目,请尝试使用 LibTorch 的调试版本。 另外,请确保在下面的`cmake --build .`行中指定正确的配置。 + +第一步是通过从 PyTorch 网站获取的链接在本地下载 LibTorch 发行版。 对于普通的 Ubuntu Linux 环境,这意味着运行: + +```py +# If you need e.g. CUDA 9.0 support, please replace "cpu" with "cu90" in the URL below. +wget https://download.pytorch.org/libtorch/nightly/cpu/libtorch-shared-with-deps-latest.zip +unzip libtorch-shared-with-deps-latest.zip + +``` + +接下来,让我们编写一个名为`dcgan.cpp`的小型 C++ 文件,其中包含`torch/torch.h`,现在只需打印出三乘三的标识矩阵即可: + +```py +#include +#include + +int main() { + torch::Tensor tensor = torch::eye(3); + std::cout << tensor << std::endl; +} + +``` + +稍后,为了构建这个小应用以及我们完整的训练脚本,我们将使用以下`CMakeLists.txt`文件: + +```py +cmake_minimum_required(VERSION 3.0 FATAL_ERROR) +project(dcgan) + +find_package(Torch REQUIRED) + +add_executable(dcgan dcgan.cpp) +target_link_libraries(dcgan "${TORCH_LIBRARIES}") +set_property(TARGET dcgan PROPERTY CXX_STANDARD 14) + +``` + +注意 + +虽然 CMake 是 LibTorch 的推荐构建系统,但这并不是硬性要求。 您还可以使用 Visual Studio 项目文件,QMake,普通 Makefile 或您认为合适的任何其他构建环境。 但是,我们不为此提供现成的支持。 + +在上面的 CMake 文件中记下第 4 行:`find_package(Torch REQUIRED)`。 这指示 CMake 查找 LibTorch 库的构建配置。 为了使 CMake 知道在哪里找到这些文件,调用`cmake`时必须设置`CMAKE_PREFIX_PATH`。 在执行此操作之前,让我们就`dcgan`应用的以下目录结构达成一致: + +```py +dcgan/ + CMakeLists.txt + dcgan.cpp + +``` + +此外,我将指向未压缩的 LibTorch 分布的路径称为`/path/to/libtorch`。 注意,它**必须是绝对路径**。 特别是,将`CMAKE_PREFIX_PATH`设置为`../../libtorch`之类的内容会以意想不到的方式中断。 而是写`$PWD/../../libtorch`以获取相应的绝对路径。 现在,我们准备构建我们的应用: + +```py +root@fa350df05ecf:/home# mkdir build +root@fa350df05ecf:/home# cd build +root@fa350df05ecf:/home/build# cmake -DCMAKE_PREFIX_PATH=/path/to/libtorch .. +-- The C compiler identification is GNU 5.4.0 +-- The CXX compiler identification is GNU 5.4.0 +-- Check for working C compiler: /usr/bin/cc +-- Check for working C compiler: /usr/bin/cc -- works +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - done +-- Detecting C compile features +-- Detecting C compile features - done +-- Check for working CXX compiler: /usr/bin/c++ +-- Check for working CXX compiler: /usr/bin/c++ -- works +-- Detecting CXX compiler ABI info +-- Detecting CXX compiler ABI info - done +-- Detecting CXX compile features +-- Detecting CXX compile features - done +-- Looking for pthread.h +-- Looking for pthread.h - found +-- Looking for pthread_create +-- Looking for pthread_create - not found +-- Looking for pthread_create in pthreads +-- Looking for pthread_create in pthreads - not found +-- Looking for pthread_create in pthread +-- Looking for pthread_create in pthread - found +-- Found Threads: TRUE +-- Found torch: /path/to/libtorch/lib/libtorch.so +-- Configuring done +-- Generating done +-- Build files have been written to: /home/build +root@fa350df05ecf:/home/build# cmake --build . --config Release +Scanning dependencies of target dcgan +[ 50%] Building CXX object CMakeFiles/dcgan.dir/dcgan.cpp.o +[100%] Linking CXX executable dcgan +[100%] Built target dcgan + +``` + +上面,我们首先在`dcgan`目录内创建一个`build`文件夹,进入该文件夹,运行`cmake`命令以生成必要的构建(Make)文件,最后通过运行`cmake --build . --config Release`成功编译该项目。 现在我们准备执行最小的二进制文件并完成有关基本项目配置的这一部分: + +```py +root@fa350df05ecf:/home/build# ./dcgan +1 0 0 +0 1 0 +0 0 1 +[ Variable[CPUFloatType]{3,3} ] + +``` + +在我看来就像一个身份矩阵! + +## 定义神经网络模型 + +现在我们已经配置了基本环境,我们可以深入研究本教程中更有趣的部分。 首先,我们将讨论如何在 C++ 前端中定义模块并与之交互。 我们将从基本的小规模示例模块开始,然后使用 C++ 前端提供的广泛的内置模块库来实现全面的 GAN。 + +### 模块 API 基础 + +与 Python 接口一致,基于 C++ 前端的神经网络由称为*模块*的可重用构建块组成。 有一个基础模块类,所有其他模块都从该基础类派生。 在 Python 中,此类为`torch.nn.Module`,在 C++ 中为`torch::nn::Module`。 除了实现模块封装的算法的`forward()`方法之外,模块通常还包含以下三种子对象中的任何一种:参数,缓冲区和子模块。 + +参数和缓冲区以张量的形式存储状态。 参数记录梯度,而缓冲区不记录。 参数通常是神经网络的可训练权重。 缓冲区的示例包括批量标准化的均值和方差。 为了重用特定的逻辑和状态块,PyTorch API 允许嵌套模块。 嵌套模块称为*子模块*。 + +参数,缓冲区和子模块必须显式注册。 注册后,可以使用`parameters()`或`buffers()`之类的方法来检索整个(嵌套)模块层次结构中所有参数的容器。 类似地,使用`to(...)`之类的方法,例如 `to(torch::kCUDA)`将所有参数和缓冲区从 CPU 移到 CUDA 内存,在整个模块层次结构上工作。 + +#### 定义模块和注册参数 + +为了将这些词写成代码,让我们考虑一下用 Python 接口编写的简单模块: + +```py +import torch + +class Net(torch.nn.Module): + def __init__(self, N, M): + super(Net, self).__init__() + self.W = torch.nn.Parameter(torch.randn(N, M)) + self.b = torch.nn.Parameter(torch.randn(M)) + + def forward(self, input): + return torch.addmm(self.b, input, self.W) + +``` + +在 C++ 中,它看起来像这样: + +```py +#include + +struct Net : torch::nn::Module { + Net(int64_t N, int64_t M) { + W = register_parameter("W", torch::randn({N, M})); + b = register_parameter("b", torch::randn(M)); + } + torch::Tensor forward(torch::Tensor input) { + return torch::addmm(b, input, W); + } + torch::Tensor W, b; +}; + +``` + +就像在 Python 中一样,我们定义了一个名为`Net`的类(为简单起见,这里是`struct`而不是`class`),然后从模块基类派生它。 在构造器内部,我们使用`torch::randn`创建张量,就像在 Python 中使用`torch.randn`一样。 一个有趣的区别是我们如何注册参数。 在 Python 中,我们用`torch.nn.Parameter`类包装了张量,而在 C++ 中,我们不得不通过`register_parameter`方法传递张量。 这样做的原因是 Python API 可以检测到属性为`torch.nn.Parameter`类型并自动注册此类张量。 在 C++ 中,反射非常受限制,因此提供了一种更传统(且不太神奇)的方法。 + +#### 注册子模块并遍历模块层次结构 + +以相同的方式我们可以注册参数,我们也可以注册子模块。 在 Python 中,将子模块分配为模块的属性时,会自动检测并注册这些子模块: + +```py +class Net(torch.nn.Module): + def __init__(self, N, M): + super(Net, self).__init__() + # Registered as a submodule behind the scenes + self.linear = torch.nn.Linear(N, M) + self.another_bias = torch.nn.Parameter(torch.rand(M)) + + def forward(self, input): + return self.linear(input) + self.another_bias + +``` + +例如,这允许使用`parameters()`方法来递归访问模块层次结构中的所有参数: + +```py +>>> net = Net(4, 5) +>>> print(list(net.parameters())) +[Parameter containing: +tensor([0.0808, 0.8613, 0.2017, 0.5206, 0.5353], requires_grad=True), Parameter containing: +tensor([[-0.3740, -0.0976, -0.4786, -0.4928], + [-0.1434, 0.4713, 0.1735, -0.3293], + [-0.3467, -0.3858, 0.1980, 0.1986], + [-0.1975, 0.4278, -0.1831, -0.2709], + [ 0.3730, 0.4307, 0.3236, -0.0629]], requires_grad=True), Parameter containing: +tensor([ 0.2038, 0.4638, -0.2023, 0.1230, -0.0516], requires_grad=True)] + +``` + +要在 C++ 中注册子模块,请使用恰当命名的`register_module()`方法注册类似`torch::nn::Linear`的模块: + +```py +struct Net : torch::nn::Module { + Net(int64_t N, int64_t M) + : linear(register_module("linear", torch::nn::Linear(N, M))) { + another_bias = register_parameter("b", torch::randn(M)); + } + torch::Tensor forward(torch::Tensor input) { + return linear(input) + another_bias; + } + torch::nn::Linear linear; + torch::Tensor another_bias; +}; + +``` + +小费 + +您可以在[`torch::nn`命名空间的文档](https://pytorch.org/cppdocs/api/namespace_torch__nn.html)中找到可用的内置模块的完整列表,例如`torch::nn::Linear`,`torch::nn::Dropout`或`torch::nn::Conv2d`。 + +关于上述代码的一个微妙之处在于,为什么在构造器的初始值设定项列表中创建子模块,而在构造器的主体内部创建参数。 这是有充分的理由的,我们将在下面有关“C++ 前端所有权模型”的部分中对此进行介绍。 但是,最终结果是,就像 Python 中一样,我们可以递归访问模块树的参数。 调用`parameters()`返回一个`std::vector`,我们可以对其进行迭代: + +```py +int main() { + Net net(4, 5); + for (const auto& p : net.parameters()) { + std::cout << p << std::endl; + } +} + +``` + +打印: + +```py +root@fa350df05ecf:/home/build# ./dcgan +0.0345 +1.4456 +-0.6313 +-0.3585 +-0.4008 +[ Variable[CPUFloatType]{5} ] +-0.1647 0.2891 0.0527 -0.0354 +0.3084 0.2025 0.0343 0.1824 +-0.4630 -0.2862 0.2500 -0.0420 +0.3679 -0.1482 -0.0460 0.1967 +0.2132 -0.1992 0.4257 0.0739 +[ Variable[CPUFloatType]{5,4} ] +0.01 * +3.6861 +-10.1166 +-45.0333 +7.9983 +-20.0705 +[ Variable[CPUFloatType]{5} ] + +``` + +具有三个参数,就像在 Python 中一样。 为了也查看这些参数的名称,C++ API 提供了`named_parameters()`方法,该方法返回`OrderedDict`就像在 Python 中一样: + +```py +Net net(4, 5); +for (const auto& pair : net.named_parameters()) { + std::cout << pair.key() << ": " << pair.value() << std::endl; +} + +``` + +我们可以再次执行以查看输出: + +```py +root@fa350df05ecf:/home/build# make && ./dcgan 11:13:48 +Scanning dependencies of target dcgan +[ 50%] Building CXX object CMakeFiles/dcgan.dir/dcgan.cpp.o +[100%] Linking CXX executable dcgan +[100%] Built target dcgan +b: -0.1863 +-0.8611 +-0.1228 +1.3269 +0.9858 +[ Variable[CPUFloatType]{5} ] +linear.weight: 0.0339 0.2484 0.2035 -0.2103 +-0.0715 -0.2975 -0.4350 -0.1878 +-0.3616 0.1050 -0.4982 0.0335 +-0.1605 0.4963 0.4099 -0.2883 +0.1818 -0.3447 -0.1501 -0.0215 +[ Variable[CPUFloatType]{5,4} ] +linear.bias: -0.0250 +0.0408 +0.3756 +-0.2149 +-0.3636 +[ Variable[CPUFloatType]{5} ] + +``` + +注意 + +[`torch::nn::Module`的文档](https://pytorch.org/cppdocs/api/classtorch_1_1nn_1_1_module.html#exhale-class-classtorch-1-1nn-1-1-module)包含在模块层次结构上运行的方法的完整列表。 + +#### 在正向模式下运行网络 + +要使用 C++ 执行网络,我们只需调用我们自己定义的`forward()`方法: + +```py +int main() { + Net net(4, 5); + std::cout << net.forward(torch::ones({2, 4})) << std::endl; +} + +``` + +打印类似: + +```py +root@fa350df05ecf:/home/build# ./dcgan +0.8559 1.1572 2.1069 -0.1247 0.8060 +0.8559 1.1572 2.1069 -0.1247 0.8060 +[ Variable[CPUFloatType]{2,5} ] + +``` + +#### 模块所有权 + +至此,我们知道了如何使用 C++ 定义模块,注册参数,注册子模块,通过`parameters()`之类的方法遍历模块层次结构并最终运行模块的`forward()`方法。 尽管在 C++ API 中还有很多方法,类和主题需要使用,但我将为您提供完整菜单的[文档](https://pytorch.org/cppdocs/api/namespace_torch__nn.html)。 我们将在稍后实现 DCGAN 模型和端到端训练管道的过程中,涉及更多概念。 在我们这样做之前,让我简要介绍一下 C++ 前端为`torch::nn::Module`的子类提供的*所有权模型*。 + +在本次讨论中,所有权模型是指模块的存储和传递方式-确定特定模块实例的所有者或所有者。 在 Python 中,对象始终是动态分配的(在堆上),并且具有引用语义。 这是非常容易使用且易于理解的。 实际上,在 Python 中,您可以很大程度上忽略对象的位置以及如何引用它们,而将精力集中在完成事情上。 + +C++ 是一种较低级的语言,它在此领域提供了更多选择。 这增加了复杂性,并严重影响了 C++ 前端的设计和人体工程学。 特别是,对于 C++ 前端中的模块,我们可以选择使用*值语义*或*引用语义*。 第一种情况是最简单的,并且在到目前为止的示例中已进行了展示:模块对象在栈上分配,并在传递给函数时可以被复制,移动(使用`std::move`)或通过引用或指针获取: + +```py +struct Net : torch::nn::Module { }; + +void a(Net net) { } +void b(Net& net) { } +void c(Net* net) { } + +int main() { + Net net; + a(net); + a(std::move(net)); + b(net); + c(&net); +} + +``` + +对于第二种情况-引用语义-我们可以使用`std::shared_ptr`。 引用语义的优势在于,就像在 Python 中一样,它减少了思考如何将模块传递给函数以及如何声明参数的认知开销(假设您在任何地方都使用`shared_ptr`)。 + +```py +struct Net : torch::nn::Module {}; + +void a(std::shared_ptr net) { } + +int main() { + auto net = std::make_shared(); + a(net); +} + +``` + +根据我们的经验,来自动态语言的研究人员非常喜欢引用语义而不是值语义,即使后者比 C++ 更“原生”。 同样重要的是要注意,`torch::nn::Module`的设计要与 Python API 的人体工程学保持紧密联系,因此要依靠共享所有权。 例如,采用我们较早的(此处为缩短的)`Net`定义: + +```py +struct Net : torch::nn::Module { + Net(int64_t N, int64_t M) + : linear(register_module("linear", torch::nn::Linear(N, M))) + { } + torch::nn::Linear linear; +}; + +``` + +为了使用`linear`子模块,我们想将其直接存储在我们的类中。 但是,我们还希望模块基类了解并有权访问此子模块。 为此,它必须存储对此子模块的引用。 至此,我们已经达到了共享所有权的需要。 `torch::nn::Module`类和具体的`Net`类都需要引用该子模块。 因此,基类将模块存储为`shared_ptr`,因此具体类也必须存储。 + +可是等等! 在上面的代码中我没有提到`shared_ptr`! 这是为什么? 好吧,因为`std::shared_ptr`实在令人难受。 为了保持研究人员的生产力,我们提出了一个精心设计的方案,以隐藏`shared_ptr`的提法-通常保留给值语义的好处-同时保留引用语义。 要了解它是如何工作的,我们可以看一下核心库中`torch::nn::Linear`模块的简化定义([完整定义在此处](https://github.com/pytorch/pytorch/blob/master/torch/csrc/api/include/torch/nn/modules/linear.h)): + +```py +struct LinearImpl : torch::nn::Module { + LinearImpl(int64_t in, int64_t out); + + Tensor forward(const Tensor& input); + + Tensor weight, bias; +}; + +TORCH_MODULE(Linear); + +``` + +简而言之:该模块不是`Linear`,而是`LinearImpl`。 然后,宏`TORCH_MODULE`定义了实际的`Linear`类。 这个“生成的”类实际上是`std::shared_ptr`的包装。 它是一个包装器,而不是简单的`typedef`,因此,除其他事项外,构造器仍可按预期工作,即,您仍然可以编写`torch::nn::Linear(3, 4)`而不是`std::make_shared(3, 4)`。 我们将由宏创建的类称为模块*所有者*。 与(共享)指针一样,您可以使用箭头运算符(例如`model->forward(...)`)访问基础对象。 最终结果是一个所有权模型,该模型非常类似于 Python API。 引用语义成为默认语义,但是没有额外输入`std::shared_ptr`或`std::make_shared`。 对于我们的`Net`,使用模块持有人 API 如下所示: + +```py +struct NetImpl : torch::nn::Module {}; +TORCH_MODULE(Net); + +void a(Net net) { } + +int main() { + Net net; + a(net); +} + +``` + +这里有一个微妙的问题值得一提。 默认构造的`std::shared_ptr`为“空”,即包含空指针。 什么是默认构造的`Linear`或`Net`? 好吧,这是一个棘手的选择。 我们可以说它应该是一个空(`null`)`std::shared_ptr`。 但是,请记住`Linear(3, 4)`与`std::make_shared(3, 4)`相同。 这意味着如果我们已确定`Linear linear;`应该为空指针,则将无法构造不采用任何构造器参数或都不使用所有缺省构造器的模块。 因此,在当前的 API 中,默认构造的模块持有人(如`Linear()`)将调用基础模块的默认构造器(`LinearImpl()`)。 如果基础模块没有默认构造器,则会出现编译器错误。 要构造空持有人,可以将`nullptr`传递给持有人的构造器。 + +实际上,这意味着您可以使用如先前所示的子模块,在*初始化器列表*中注册并构造该模块: + +```py +struct Net : torch::nn::Module { + Net(int64_t N, int64_t M) + : linear(register_module("linear", torch::nn::Linear(N, M))) + { } + torch::nn::Linear linear; +}; + +``` + +或者,您可以先使用空指针构造持有人,然后在构造器中为其分配值(Python 爱好者更熟悉): + +```py +struct Net : torch::nn::Module { + Net(int64_t N, int64_t M) { + linear = register_module("linear", torch::nn::Linear(N, M)); + } + torch::nn::Linear linear{nullptr}; // construct an empty holder +}; + +``` + +结论:您应该使用哪种所有权模型–哪种语义? C++ 前端的 API 最能支持模块所有者提供的所有权模型。 这种机制的唯一缺点是在模块声明下方多了一行样板。 也就是说,最简单的模型仍然是 C++ 模块简介中显示的值语义模型。 对于小的,简单的脚本,您也可以摆脱它。 但是,由于技术原因,您迟早会发现它并不总是受支持。 例如,序列化 API(`torch::save`和`torch::load`)仅支持模块支架(或普通`shared_ptr`)。 因此,建议使用模块持有人 API 和 C++ 前端定义模块,此后我们将在本教程中使用此 API。 + +### 定义 DCGAN 模块 + +现在,我们有必要的背景和简介来定义我们要在本文中解决的机器学习任务的模块。 回顾一下:我们的任务是从 [MNIST 数据集](http://yann.lecun.com/exdb/mnist/)生成数字图像。 我们想使用[生成对抗网络(GAN)](https://papers.nips.cc/paper/5423-generative-adversarial-nets.pdf)解决此任务。 特别是,我们将使用 [DCGAN 架构](https://arxiv.org/abs/1511.06434),这是同类中最早,最简单的架构之一,但完全可以完成此任务。 + +小费 + +[您可以在存储库中找到本教程中提供的完整源代码](https://github.com/pytorch/examples/tree/master/cpp/dcgan)。 + +#### 什么是 GAN aGAN? + +GAN 由两个不同的神经网络模型组成:*生成器*和*判别器*。 生成器从噪声分布中接收样本,其目的是将每个噪声样本转换为类似于目标分布的图像(在我们的情况下为 MNIST 数据集)。 判别器又从 MNIST 数据集接收*实际*图像,或从生成器接收*假*图像。 要求发出一个概率来判断特定图像的真实程度(接近`1`)或伪造(接近`0`)。 来自判别器的关于由生成器产生的图像有多真实的反馈被用来训练生成器。 判别器对真实性有多好的反馈将用于优化判别器。 从理论上讲,生成器和判别器之间的微妙平衡使它们连接起来得到改善,从而导致生成器生成与目标分布无法区分的图像,从而使判别器(那时)的敏锐眼睛冒出了散发`0.5`的真实和真实可能性。 假图片。 对我们来说,最终结果是一台接收噪声作为输入并生成逼真的数字图像作为其输出的机器。 + +#### 生成器模块 + +我们首先定义生成器模块,该模块由一系列转置的 2D 卷积,批量归一化和 ReLU 激活单元组成。 我们在定义自己的模块的`forward()`方法中显式地(在功能上)在模块之间传递输入: + +```py +struct DCGANGeneratorImpl : nn::Module { + DCGANGeneratorImpl(int kNoiseSize) + : conv1(nn::ConvTranspose2dOptions(kNoiseSize, 256, 4) + .bias(false)), + batch_norm1(256), + conv2(nn::ConvTranspose2dOptions(256, 128, 3) + .stride(2) + .padding(1) + .bias(false)), + batch_norm2(128), + conv3(nn::ConvTranspose2dOptions(128, 64, 4) + .stride(2) + .padding(1) + .bias(false)), + batch_norm3(64), + conv4(nn::ConvTranspose2dOptions(64, 1, 4) + .stride(2) + .padding(1) + .bias(false)) + { + // register_module() is needed if we want to use the parameters() method later on + register_module("conv1", conv1); + register_module("conv2", conv2); + register_module("conv3", conv3); + register_module("conv4", conv4); + register_module("batch_norm1", batch_norm1); + register_module("batch_norm2", batch_norm2); + register_module("batch_norm3", batch_norm3); + } + + torch::Tensor forward(torch::Tensor x) { + x = torch::relu(batch_norm1(conv1(x))); + x = torch::relu(batch_norm2(conv2(x))); + x = torch::relu(batch_norm3(conv3(x))); + x = torch::tanh(conv4(x)); + return x; + } + + nn::ConvTranspose2d conv1, conv2, conv3, conv4; + nn::BatchNorm2d batch_norm1, batch_norm2, batch_norm3; +}; +TORCH_MODULE(DCGANGenerator); + +DCGANGenerator generator(kNoiseSize); + +``` + +现在我们可以在`DCGANGenerator`上调用`forward()`将噪声样本映射到图像。 + +选择的特定模块,例如`nn::ConvTranspose2d`和`nn::BatchNorm2d`,遵循前面概述的结构。 `kNoiseSize`常数确定输入噪声向量的大小,并将其设置为`100`。 当然,超参数是通过研究生的血统发现的。 + +Attention + +No grad students were harmed in the discovery of hyperparameters. They were fed Soylent regularly. + +Note + +A brief word on the way options are passed to built-in modules like `Conv2d` in the C++ frontend: Every module has some required options, like the number of features for `BatchNorm2d`. If you only need to configure the required options, you can pass them directly to the module’s constructor, like `BatchNorm2d(128)` or `Dropout(0.5)` or `Conv2d(8, 4, 2)` (for input channel count, output channel count, and kernel size). If, however, you need to modify other options, which are normally defaulted, such as `bias` for `Conv2d`, you need to construct and pass an *options* object. Every module in the C++ frontend has an associated options struct, called `ModuleOptions` where `Module` is the name of the module, like `LinearOptions` for `Linear`. This is what we do for the `Conv2d` modules above. + +#### 判别器模块 + +The discriminator is similarly a sequence of convolutions, batch normalizations and activations. However, the convolutions are now regular ones instead of transposed, and we use a leaky ReLU with an alpha value of 0.2 instead of a vanilla ReLU. Also, the final activation becomes a Sigmoid, which squashes values into a range between 0 and 1\. We can then interpret these squashed values as the probabilities the discriminator assigns to images being real. + +To build the discriminator, we will try something different: a Sequential module. Like in Python, PyTorch here provides two APIs for model definition: a functional one where inputs are passed through successive functions (e.g. the generator module example), and a more object-oriented one where we build a Sequential module containing the entire model as submodules. Using Sequential, the discriminator would look like: + +```py +nn::Sequential discriminator( + // Layer 1 + nn::Conv2d( + nn::Conv2dOptions(1, 64, 4).stride(2).padding(1).bias(false)), + nn::LeakyReLU(nn::LeakyReLUOptions().negative_slope(0.2)), + // Layer 2 + nn::Conv2d( + nn::Conv2dOptions(64, 128, 4).stride(2).padding(1).bias(false)), + nn::BatchNorm2d(128), + nn::LeakyReLU(nn::LeakyReLUOptions().negative_slope(0.2)), + // Layer 3 + nn::Conv2d( + nn::Conv2dOptions(128, 256, 4).stride(2).padding(1).bias(false)), + nn::BatchNorm2d(256), + nn::LeakyReLU(nn::LeakyReLUOptions().negative_slope(0.2)), + // Layer 4 + nn::Conv2d( + nn::Conv2dOptions(256, 1, 3).stride(1).padding(0).bias(false)), + nn::Sigmoid()); + +``` + +Tip + +A `Sequential` module simply performs function composition. The output of the first submodule becomes the input of the second, the output of the third becomes the input of the fourth and so on. + +## 加载数据 + +Now that we have defined the generator and discriminator model, we need some data we can train these models with. The C++ frontend, like the Python one, comes with a powerful parallel data loader. This data loader can read batches of data from a dataset (which you can define yourself) and provides many configuration knobs. + +注意 + +While the Python data loader uses multi-processing, the C++ data loader is truly multi-threaded and does not launch any new processes. + +The data loader is part of the C++ frontend’s `data` api, contained in the `torch::data::` namespace. This API consists of a few different components: + +* 数据加载器类, +* 用于定义数据集的 API, +* 用于定义*转换*的 API,可以将其应用于数据集, +* 用于定义*采样器*的 API,该采样器会生成用于对数据集建立索引的索引, +* 现有数据集,变换和采样器的库。 + +For this tutorial, we can use the `MNIST` dataset that comes with the C++ frontend. Let’s instantiate a `torch::data::datasets::MNIST` for this, and apply two transformations: First, we normalize the images so that they are in the range of `-1` to `+1` (from an original range of `0` to `1`). Second, we apply the `Stack` *collation*, which takes a batch of tensors and stacks them into a single tensor along the first dimension: + +```py +auto dataset = torch::data::datasets::MNIST("./mnist") + .map(torch::data::transforms::Normalize<>(0.5, 0.5)) + .map(torch::data::transforms::Stack<>()); + +``` + +Note that the MNIST dataset should be located in the `./mnist` directory relative to wherever you execute the training binary from. You can use [this script](https://gist.github.com/goldsborough/6dd52a5e01ed73a642c1e772084bcd03) to download the MNIST dataset. + +接下来,我们创建一个数据加载器并将其传递给该数据集。 为了创建一个新的数据加载器,我们使用`torch::data::make_data_loader`,它返回正确类型的`std::unique_ptr`(取决于数据集的类型,采样器的类型以及其他一些实现细节): + +```py +auto data_loader = torch::data::make_data_loader(std::move(dataset)); + +``` + +数据加载器确实提供了很多选项。 [您可以在这里检查全套](https://github.com/pytorch/pytorch/blob/master/torch/csrc/api/include/torch/data/dataloader_options.h)。 例如,为了加快数据加载速度,我们可以增加工作器的数量。 默认数字为零,这意味着将使用主线程。 如果将`workers`设置为`2`,将产生两个线程并发加载数据。 我们还应该将批量大小从其默认值`1`增加到更合理的值,例如`64`(`kBatchSize`的值)。 因此,让我们创建一个`DataLoaderOptions`对象并设置适当的属性: + +```py +auto data_loader = torch::data::make_data_loader( + std::move(dataset), + torch::data::DataLoaderOptions().batch_size(kBatchSize).workers(2)); + +``` + +现在,我们可以编写一个循环来加载批量数据,目前我们仅将其打印到控制台: + +```py +for (torch::data::Example<>& batch : *data_loader) { + std::cout << "Batch size: " << batch.data.size(0) << " | Labels: "; + for (int64_t i = 0; i < batch.data.size(0); ++i) { + std::cout << batch.target[i].item() << " "; + } + std::cout << std::endl; +} + +``` + +在这种情况下,数据加载器返回的类型为`torch::data::Example`。 此类型是一种简单的结构,其中的`data`字段用于数据,而`target`字段用于标签。 因为我们之前应用了`Stack`归类,所以数据加载器仅返回一个这样的示例。 如果我们未应用排序规则,则数据加载器将改为生成`std::vector>`,批量中每个示例包含一个元素。 + +如果重建并运行此代码,则应看到类似以下内容的内容: + +```py +root@fa350df05ecf:/home/build# make +Scanning dependencies of target dcgan +[ 50%] Building CXX object CMakeFiles/dcgan.dir/dcgan.cpp.o +[100%] Linking CXX executable dcgan +[100%] Built target dcgan +root@fa350df05ecf:/home/build# make +[100%] Built target dcgan +root@fa350df05ecf:/home/build# ./dcgan +Batch size: 64 | Labels: 5 2 6 7 2 1 6 7 0 1 6 2 3 6 9 1 8 4 0 6 5 3 3 0 4 6 6 6 4 0 8 6 0 6 9 2 4 0 2 8 6 3 3 2 9 2 0 1 4 2 3 4 8 2 9 9 3 5 8 0 0 7 9 9 +Batch size: 64 | Labels: 2 2 4 7 1 2 8 8 6 9 0 2 2 9 3 6 1 3 8 0 4 4 8 8 8 9 2 6 4 7 1 5 0 9 7 5 4 3 5 4 1 2 8 0 7 1 9 6 1 6 5 3 4 4 1 2 3 2 3 5 0 1 6 2 +Batch size: 64 | Labels: 4 5 4 2 1 4 8 3 8 3 6 1 5 4 3 6 2 2 5 1 3 1 5 0 8 2 1 5 3 2 4 4 5 9 7 2 8 9 2 0 6 7 4 3 8 3 5 8 8 3 0 5 8 0 8 7 8 5 5 6 1 7 8 0 +Batch size: 64 | Labels: 3 3 7 1 4 1 6 1 0 3 6 4 0 2 5 4 0 4 2 8 1 9 6 5 1 6 3 2 8 9 2 3 8 7 4 5 9 6 0 8 3 0 0 6 4 8 2 5 4 1 8 3 7 8 0 0 8 9 6 7 2 1 4 7 +Batch size: 64 | Labels: 3 0 5 5 9 8 3 9 8 9 5 9 5 0 4 1 2 7 7 2 0 0 5 4 8 7 7 6 1 0 7 9 3 0 6 3 2 6 2 7 6 3 3 4 0 5 8 8 9 1 9 2 1 9 4 4 9 2 4 6 2 9 4 0 +Batch size: 64 | Labels: 9 6 7 5 3 5 9 0 8 6 6 7 8 2 1 9 8 8 1 1 8 2 0 7 1 4 1 6 7 5 1 7 7 4 0 3 2 9 0 6 6 3 4 4 8 1 2 8 6 9 2 0 3 1 2 8 5 6 4 8 5 8 6 2 +Batch size: 64 | Labels: 9 3 0 3 6 5 1 8 6 0 1 9 9 1 6 1 7 7 4 4 4 7 8 8 6 7 8 2 6 0 4 6 8 2 5 3 9 8 4 0 9 9 3 7 0 5 8 2 4 5 6 2 8 2 5 3 7 1 9 1 8 2 2 7 +Batch size: 64 | Labels: 9 1 9 2 7 2 6 0 8 6 8 7 7 4 8 6 1 1 6 8 5 7 9 1 3 2 0 5 1 7 3 1 6 1 0 8 6 0 8 1 0 5 4 9 3 8 5 8 4 8 0 1 2 6 2 4 2 7 7 3 7 4 5 3 +Batch size: 64 | Labels: 8 8 3 1 8 6 4 2 9 5 8 0 2 8 6 6 7 0 9 8 3 8 7 1 6 6 2 7 7 4 5 5 2 1 7 9 5 4 9 1 0 3 1 9 3 9 8 8 5 3 7 5 3 6 8 9 4 2 0 1 2 5 4 7 +Batch size: 64 | Labels: 9 2 7 0 8 4 4 2 7 5 0 0 6 2 0 5 9 5 9 8 8 9 3 5 7 5 4 7 3 0 5 7 6 5 7 1 6 2 8 7 6 3 2 6 5 6 1 2 7 7 0 0 5 9 0 0 9 1 7 8 3 2 9 4 +Batch size: 64 | Labels: 7 6 5 7 7 5 2 2 4 9 9 4 8 7 4 8 9 4 5 7 1 2 6 9 8 5 1 2 3 6 7 8 1 1 3 9 8 7 9 5 0 8 5 1 8 7 2 6 5 1 2 0 9 7 4 0 9 0 4 6 0 0 8 6 +... + +``` + +这意味着我们能够成功地从 MNIST 数据集中加载数据。 + +## 编写训练循环 + +现在,让我们完成示例的算法部分,并实现生成器和判别器之间的精妙舞蹈。 首先,我们将创建两个优化器,一个用于生成器,一个用于判别器。 我们使用的优化程序实现了 [Adam](https://arxiv.org/pdf/1412.6980.pdf) 算法: + +```py +torch::optim::Adam generator_optimizer( + generator->parameters(), torch::optim::AdamOptions(2e-4).beta1(0.5)); +torch::optim::Adam discriminator_optimizer( + discriminator->parameters(), torch::optim::AdamOptions(5e-4).beta1(0.5)); + +``` + +注意 + +在撰写本文时,C++ 前端提供了实现 Adagrad,Adam,LBBFG,RMSprop 和 SGD 的优化器。 [文档](https://pytorch.org/cppdocs/api/namespace_torch__optim.html)具有最新列表。 + +接下来,我们需要更新我们的训练循环。 我们将添加一个外循环以在每个周期耗尽数据加载器,然后编写 GAN 训练代码: + +```py +for (int64_t epoch = 1; epoch <= kNumberOfEpochs; ++epoch) { + int64_t batch_index = 0; + for (torch::data::Example<>& batch : *data_loader) { + // Train discriminator with real images. + discriminator->zero_grad(); + torch::Tensor real_images = batch.data; + torch::Tensor real_labels = torch::empty(batch.data.size(0)).uniform_(0.8, 1.0); + torch::Tensor real_output = discriminator->forward(real_images); + torch::Tensor d_loss_real = torch::binary_cross_entropy(real_output, real_labels); + d_loss_real.backward(); + + // Train discriminator with fake images. + torch::Tensor noise = torch::randn({batch.data.size(0), kNoiseSize, 1, 1}); + torch::Tensor fake_images = generator->forward(noise); + torch::Tensor fake_labels = torch::zeros(batch.data.size(0)); + torch::Tensor fake_output = discriminator->forward(fake_images.detach()); + torch::Tensor d_loss_fake = torch::binary_cross_entropy(fake_output, fake_labels); + d_loss_fake.backward(); + + torch::Tensor d_loss = d_loss_real + d_loss_fake; + discriminator_optimizer.step(); + + // Train generator. + generator->zero_grad(); + fake_labels.fill_(1); + fake_output = discriminator->forward(fake_images); + torch::Tensor g_loss = torch::binary_cross_entropy(fake_output, fake_labels); + g_loss.backward(); + generator_optimizer.step(); + + std::printf( + "\r[%2ld/%2ld][%3ld/%3ld] D_loss: %.4f | G_loss: %.4f", + epoch, + kNumberOfEpochs, + ++batch_index, + batches_per_epoch, + d_loss.item(), + g_loss.item()); + } +} + +``` + +上面,我们首先在真实图像上评估判别器,为此应为其分配较高的概率。 为此,我们使用`torch::empty(batch.data.size(0)).uniform_(0.8, 1.0)`作为目标概率。 + +注意 + +我们选择均匀分布在 0.8 到 1.0 之间的随机值,而不是各处的 1.0,以使判别器训练更可靠。 此技巧称为*标签平滑*。 + +在评估判别器之前,我们将其参数的梯度归零。 计算完损失后,我们通过调用`d_loss.backward()`来计算新的梯度,从而在网络中反向传播。 我们对虚假图像重复此步骤。 我们不使用数据集中的图像,而是让生成器通过为它提供一批随机噪声来为此创建伪造图像。 然后,我们将这些伪造图像转发给判别器。 这次,我们希望判别器发出低概率,最好是全零。 一旦计算了一批真实图像和一批伪造图像的判别器损失,我们就可以一步一步地进行判别器的优化程序,以更新其参数。 + +为了训练生成器,我们再次首先将其梯度归零,然后在伪图像上重新评估判别器。 但是,这一次,我们希望判别器将概率分配为非常接近的概率,这将表明生成器可以生成使判别器认为它们实际上是真实的图像(来自数据集)。 为此,我们用全部填充`fake_labels`张量。 最后,我们逐步使用生成器的优化器来更新其参数。 + +现在,我们应该准备在 CPU 上训练我们的模型。 我们还没有任何代码可以捕获状态或示例输出,但是我们稍后会添加。 现在,让我们观察一下我们的模型正在*做某事* –我们稍后将根据生成的图像来验证这是否有意义。 重建和运行应打印如下内容: + +```py +root@3c0711f20896:/home/build# make && ./dcgan +Scanning dependencies of target dcgan +[ 50%] Building CXX object CMakeFiles/dcgan.dir/dcgan.cpp.o +[100%] Linking CXX executable dcgan +[100%] Built target dcga +[ 1/10][100/938] D_loss: 0.6876 | G_loss: 4.1304 +[ 1/10][200/938] D_loss: 0.3776 | G_loss: 4.3101 +[ 1/10][300/938] D_loss: 0.3652 | G_loss: 4.6626 +[ 1/10][400/938] D_loss: 0.8057 | G_loss: 2.2795 +[ 1/10][500/938] D_loss: 0.3531 | G_loss: 4.4452 +[ 1/10][600/938] D_loss: 0.3501 | G_loss: 5.0811 +[ 1/10][700/938] D_loss: 0.3581 | G_loss: 4.5623 +[ 1/10][800/938] D_loss: 0.6423 | G_loss: 1.7385 +[ 1/10][900/938] D_loss: 0.3592 | G_loss: 4.7333 +[ 2/10][100/938] D_loss: 0.4660 | G_loss: 2.5242 +[ 2/10][200/938] D_loss: 0.6364 | G_loss: 2.0886 +[ 2/10][300/938] D_loss: 0.3717 | G_loss: 3.8103 +[ 2/10][400/938] D_loss: 1.0201 | G_loss: 1.3544 +[ 2/10][500/938] D_loss: 0.4522 | G_loss: 2.6545 +... + +``` + +## 移至 GPU + +虽然我们当前的脚本可以在 CPU 上正常运行,但是我们都知道卷积在 GPU 上要快得多。 让我们快速讨论如何将训练转移到 GPU 上。 为此,我们需要做两件事:将 GPU 设备规范传递给我们分配给自己的张量,并通过`to()`方法将所有其他张量明确复制到 C++ 前端中的所有张量和模块上。 实现这两者的最简单方法是在我们的训练脚本的顶层创建`torch::Device`的实例,然后将该设备传递给张量工厂函数,例如`torch::zeros`和`to()`方法。 我们可以从使用 CPU 设备开始: + +```py +// Place this somewhere at the top of your training script. +torch::Device device(torch::kCPU); + +``` + +新的张量分配,例如 + +```py +torch::Tensor fake_labels = torch::zeros(batch.data.size(0)); + +``` + +应该更新为以`device`作为最后一个参数: + +```py +torch::Tensor fake_labels = torch::zeros(batch.data.size(0), device); + +``` + +对于那些不在我们手中的张量,例如来自 MNIST 数据集的张量,我们必须插入显式的`to()`调用。 这表示 + +```py +torch::Tensor real_images = batch.data; + +``` + +变成 + +```py +torch::Tensor real_images = batch.data.to(device); + +``` + +并且我们的模型参数也应该移到正确的设备上: + +```py +generator->to(device); +discriminator->to(device); + +``` + +注意 + +如果张量已经存在于提供给`to()`的设备上,则该调用为空操作。 没有多余的副本。 + +至此,我们已经使之前的 CPU 代码更加明确了。 但是,现在将设备更改为 CUDA 设备也非常容易: + +```py +torch::Device device(torch::kCUDA) + +``` + +现在,所有张量都将驻留在 GPU 上,并调用快速 CUDA 内核进行所有操作,而无需我们更改任何下游代码。 如果我们想指定一个特定的设备索引,则可以将其作为第二个参数传递给`Device`构造器。 如果我们希望不同的张量驻留在不同的设备上,则可以传递单独的设备实例(例如,一个在 CUDA 设备 0 上,另一个在 CUDA 设备 1 上)。 我们甚至可以动态地进行此配置,这通常对于使我们的训练脚本更具可移植性很有用: + +```py +torch::Device device = torch::kCPU; +if (torch::cuda::is_available()) { + std::cout << "CUDA is available! Training on GPU." << std::endl; + device = torch::kCUDA; +} + +``` + +甚至 + +```py +torch::Device device(torch::cuda::is_available() ? torch::kCUDA : torch::kCPU); + +``` + +## 检查点和恢复训练状态 + +我们应该对训练脚本进行的最后扩充是定期保存模型参数的状态,优化器的状态以及一些生成的图像样本。 如果我们的计算机在训练过程中崩溃,则前两个将使我们能够恢复训练状态。 对于长期的训练过程,这是绝对必要的。 幸运的是,C++ 前端提供了一个 API,用于对模型和优化器状态以及单个张量进行序列化和反序列化。 + +为此的核心 API 是`torch::save(thing,filename)`和`torch::load(thing,filename)`,其中`thing`可以是`torch::nn::Module`子类,也可以是优化脚本实例,例如我们在训练脚本中拥有的`Adam`对象。 让我们更新训练循环,以一定间隔检查模型和优化器状态: + +```py +if (batch_index % kCheckpointEvery == 0) { + // Checkpoint the model and optimizer state. + torch::save(generator, "generator-checkpoint.pt"); + torch::save(generator_optimizer, "generator-optimizer-checkpoint.pt"); + torch::save(discriminator, "discriminator-checkpoint.pt"); + torch::save(discriminator_optimizer, "discriminator-optimizer-checkpoint.pt"); + // Sample the generator and save the images. + torch::Tensor samples = generator->forward(torch::randn({8, kNoiseSize, 1, 1}, device)); + torch::save((samples + 1.0) / 2.0, torch::str("dcgan-sample-", checkpoint_counter, ".pt")); + std::cout << "\n-> checkpoint " << ++checkpoint_counter << '\n'; +} + +``` + +其中`kCheckpointEvery`是设置为类似于`100`之类的整数,用于每批`100`批量检查点,而`checkpoint_counter`是每次创建检查点时都会增加的计数器。 + +要恢复训练状态,可以在创建所有模型和优化器之后但在训练循环之前添加如下代码: + +```py +torch::optim::Adam generator_optimizer( + generator->parameters(), torch::optim::AdamOptions(2e-4).beta1(0.5)); +torch::optim::Adam discriminator_optimizer( + discriminator->parameters(), torch::optim::AdamOptions(2e-4).beta1(0.5)); + +if (kRestoreFromCheckpoint) { + torch::load(generator, "generator-checkpoint.pt"); + torch::load(generator_optimizer, "generator-optimizer-checkpoint.pt"); + torch::load(discriminator, "discriminator-checkpoint.pt"); + torch::load( + discriminator_optimizer, "discriminator-optimizer-checkpoint.pt"); +} + +int64_t checkpoint_counter = 0; +for (int64_t epoch = 1; epoch <= kNumberOfEpochs; ++epoch) { + int64_t batch_index = 0; + for (torch::data::Example<>& batch : *data_loader) { + +``` + +## 检查生成的图像 + +我们的训练脚本现已完成。 我们准备在 CPU 或 GPU 上训练 GAN。 为了检查我们训练过程的中间输出,为此我们添加了将代码样本定期保存到`"dcgan-sample-xxx.pt"`文件的代码,我们可以编写一个小的 Python 脚本来加载张量并使用 matplotlib 显示它们: + +```py +from __future__ import print_function +from __future__ import unicode_literals + +import argparse + +import matplotlib.pyplot as plt +import torch + +parser = argparse.ArgumentParser() +parser.add_argument("-i", "--sample-file", required=True) +parser.add_argument("-o", "--out-file", default="out.png") +parser.add_argument("-d", "--dimension", type=int, default=3) +options = parser.parse_args() + +module = torch.jit.load(options.sample_file) +images = list(module.parameters())[0] + +for index in range(options.dimension * options.dimension): + image = images[index].detach().cpu().reshape(28, 28).mul(255).to(torch.uint8) + array = image.numpy() + axis = plt.subplot(options.dimension, options.dimension, 1 + index) + plt.imshow(array, cmap="gray") + axis.get_xaxis().set_visible(False) + axis.get_yaxis().set_visible(False) + +plt.savefig(options.out_file) +print("Saved ", options.out_file) + +``` + +现在,让我们训练模型约 30 个周期: + +```py +root@3c0711f20896:/home/build# make && ./dcgan 10:17:57 +Scanning dependencies of target dcgan +[ 50%] Building CXX object CMakeFiles/dcgan.dir/dcgan.cpp.o +[100%] Linking CXX executable dcgan +[100%] Built target dcgan +CUDA is available! Training on GPU. +[ 1/30][200/938] D_loss: 0.4953 | G_loss: 4.0195 +-> checkpoint 1 +[ 1/30][400/938] D_loss: 0.3610 | G_loss: 4.8148 +-> checkpoint 2 +[ 1/30][600/938] D_loss: 0.4072 | G_loss: 4.36760 +-> checkpoint 3 +[ 1/30][800/938] D_loss: 0.4444 | G_loss: 4.0250 +-> checkpoint 4 +[ 2/30][200/938] D_loss: 0.3761 | G_loss: 3.8790 +-> checkpoint 5 +[ 2/30][400/938] D_loss: 0.3977 | G_loss: 3.3315 +... +-> checkpoint 120 +[30/30][938/938] D_loss: 0.3610 | G_loss: 3.8084 + +``` + +并在图中显示图像: + +```py +root@3c0711f20896:/home/build# python display.py -i dcgan-sample-100.pt +Saved out.png + +``` + +应该看起来像这样: + +![digits](img/931dea1655c975ec616a9e22c80c242f.png) + +数字! 万岁! 现在,事情就在您的球场上了:您可以改进模型以使数字看起来更好吗? + +## 总结 + +希望本教程为您提供了 PyTorch C++ 前端的可摘要。 像 PyTorch 这样的机器学习库必然具有非常广泛的 API。 因此,有许多概念我们没有时间或空间来讨论。 但是,我建议您尝试一下 API,并在遇到问题时查阅[我们的文档](https://pytorch.org/cppdocs/),尤其是[库 API](https://pytorch.org/cppdocs/api/library_root.html) 部分。 另外,请记住,只要我们能够做到,就可以期望 C++ 前端遵循 Python 前端的设计和语义,因此您可以利用这一事实来提高学习率。 + +小费 + +[您可以在存储库中找到本教程中提供的完整源代码](https://github.com/pytorch/examples/tree/master/cpp/dcgan)。 + +与往常一样,如果您遇到任何问题或疑问,可以使用我们的[论坛](https://discuss.pytorch.org/)或 [GitHub ISSUE](https://github.com/pytorch/pytorch/issues) 进行联系。 \ No newline at end of file diff --git a/pytorch/官方教程/45.md b/pytorch/官方教程/45.md new file mode 100644 index 00000000..b2a58869 --- /dev/null +++ b/pytorch/官方教程/45.md @@ -0,0 +1,996 @@ +# 自定义 C++ 和 CUDA 扩展 + +> 原文: + +**作者**: [Peter Goldsborough](https://www.goldsborough.me/) + +PyTorch 提供了与神经网络,任意张量代数,数据整理和其他目的有关的大量操作。 但是,您仍然可能发现自己需要更多的自定义操作。 例如,您可能想使用论文中发现的新颖的激活函数,或者实现您在研究过程中开发的操作。 + +在 PyTorch 中集成这样的自定义操作的最简单方法是通过扩展[此处](https://pytorch.org/docs/master/notes/extending.html)概述的`Function`和`Module`来用 Python 编写它。 这为您提供了自动微分的全部功能(使您不必编写导函数)以及 Python 的通常表达能力。 但是,有时您的操作可以用 C++ 更好地实现。 例如,您的代码可能*确实*需要速度,因为在模型中它经常被调用,或者即使很少调用也很昂贵。 另一个合理的原因是它依赖于其他 C 或 C++ 库或与之交互。 为了解决这种情况,PyTorch 提供了一种非常简单的方式来编写自定义 *C++ 扩展*。 + +C++ 扩展是我们开发的一种机制,允许用户(您)创建源外定义的 PyTorch 运算符,即与 PyTorch 后端分开。 该方法不同于本机 PyTorch 操作的实现方式。 C++ 扩展旨在为您节省大量与将操作与 PyTorch 后端集成在一起相关的样板,同时为基于 PyTorch 的项目提供高度的灵活性。 但是,一旦将操作定义为 C++ 扩展,将其转换为本地 PyTorch 函数在很大程度上取决于代码组织,如果您决定在上游进行操作,则可以解决此问题。 + +## 动机和示例 + +本说明的其余部分将逐步介绍编写和使用 C++(和 CUDA)扩展的实际示例。 如果您被追捕,或者在一天结束前仍未完成该操作,就会有人开除您,则可以跳过本节,直接进入下一部分的实现细节。 + +假设您想出了一种新型的循环装置,发现与现有技术相比,它具有更好的表现。 该循环单元类似于 LSTM,但不同之处在于它缺少*遗忘门*,并使用*指数线性单元*(ELU)作为其内部激活函数。 由于此设备永远不会忘记,因此我们将其称为 *LLTM* 或*长期记忆*单元。 + +LLTM 与普通 LSTM 的两种区别非常重要,以至于我们无法为自己的目的配置 PyTorch 的`LSTMCell`,因此我们必须创建一个自定义单元。 这样做的第一个也是最简单的方法,并且在所有情况下都可能是一个好的第一步,是使用 Python 在纯 PyTorch 中实现我们所需的功能。 为此,我们需要子类`torch.nn.Module`并实现 LLTM 的正向传播。 看起来像这样: + +```py +class LLTM(torch.nn.Module): + def __init__(self, input_features, state_size): + super(LLTM, self).__init__() + self.input_features = input_features + self.state_size = state_size + # 3 * state_size for input gate, output gate and candidate cell gate. + # input_features + state_size because we will multiply with [input, h]. + self.weights = torch.nn.Parameter( + torch.empty(3 * state_size, input_features + state_size)) + self.bias = torch.nn.Parameter(torch.empty(3 * state_size)) + self.reset_parameters() + + def reset_parameters(self): + stdv = 1.0 / math.sqrt(self.state_size) + for weight in self.parameters(): + weight.data.uniform_(-stdv, +stdv) + + def forward(self, input, state): + old_h, old_cell = state + X = torch.cat([old_h, input], dim=1) + + # Compute the input, output and candidate cell gates with one MM. + gate_weights = F.linear(X, self.weights, self.bias) + # Split the combined gate weight matrix into its components. + gates = gate_weights.chunk(3, dim=1) + + input_gate = torch.sigmoid(gates[0]) + output_gate = torch.sigmoid(gates[1]) + # Here we use an ELU instead of the usual tanh. + candidate_cell = F.elu(gates[2]) + + # Compute the new cell state. + new_cell = old_cell + candidate_cell * input_gate + # Compute the new hidden state and output. + new_h = torch.tanh(new_cell) * output_gate + + return new_h, new_cell + +``` + +然后我们可以按预期使用: + +```py +import torch + +X = torch.randn(batch_size, input_features) +h = torch.randn(batch_size, state_size) +C = torch.randn(batch_size, state_size) + +rnn = LLTM(input_features, state_size) + +new_h, new_C = rnn(X, (h, C)) + +``` + +自然,如果可能的话,您应该使用这种方法扩展 PyTorch。 由于 PyTorch 对 CPU 和 GPU 的操作进行了高度优化的实现,并由 [NVIDIA cuDNN](https://developer.nvidia.com/cudnn),[Intel MKL](https://software.intel.com/en-us/mkl) 或 [NNPACK](https://github.com/Maratyszcza/NNPACK) 等库提供支持 ,上面的 PyTorch 代码通常会足够快。 但是,我们还可以看到为什么在某些情况下还有进一步改进性能的空间。 最明显的原因是 PyTorch 不了解您要实现的*算法*。 它仅知道您用于组成算法的单个操作。 因此,PyTorch 必须一个接一个地执行您的操作。 由于对操作的实现(或*核*)的每个单独调用(可能涉及 CUDA 内核的启动)都具有一定的开销,因此该开销在许多函数调用中可能变得很重要。 此外,运行我们的代码的 Python 解释器本身可能会使我们的程序变慢。 + +因此,一种确定的加速方法是用 C++(或 CUDA)和*熔断*特定操作组来重写零件。 融合是指将许多功能的实现组合为一个功能,这可以从更少的内核启动以及我们可以提高全局数据流可见性的情况下执行的其他优化中获利。 + +让我们看看如何使用 C++ 扩展来实现 LLTM 的*融合*版本。 首先,我们使用 [ATen](https://github.com/zdevito/ATen) 库以普通的 C++ 语言编写代码,该库为 PyTorch 的许多后端提供了强大的支持,并了解它如何使我们轻松转换 Python 代码。 然后,我们将模型的某些部分移至 CUDA 内核,以从 GPU 提供的大量并行处理中受益,从而进一步加快处理速度。 + +## 编写 C++ 扩展 + +C++ 扩展有两种形式:它们可以使用`setuptools`提前构建,也可以通过`torch.utils.cpp_extension.load()`适时构建。 我们将从第一种方法开始,稍后再讨论后者。 + +### 使用`setuptools`构建 + +为了“提前”,我们通过编写一个`setup.py`脚本来构建 C++ 扩展,该脚本使用`setuptools`编译我们的 C++ 代码。 对于 LLTM,它看起来像这样简单: + +```py +from setuptools import setup, Extension +from torch.utils import cpp_extension + +setup(name='lltm_cpp', + ext_modules=[cpp_extension.CppExtension('lltm_cpp', ['lltm.cpp'])], + cmdclass={'build_ext': cpp_extension.BuildExtension}) + +``` + +在此代码中,`CppExtension`是`setuptools.Extension`的便利包装,它传递正确的包含路径并将扩展的语言设置为 C++。 等效的`setuptools`原始代码如下: + +```py +Extension( + name='lltm_cpp', + sources=['lltm.cpp'], + include_dirs=cpp_extension.include_paths(), + language='c++') + +``` + +`BuildExtension`执行许多必需的配置步骤,并检查和管理混合 C++/CUDA 扩展的混合编译。 这就是我们现在真正需要了解的有关构建 C++ 扩展的全部信息! 现在让我们看一下`lltm.cpp`中 C++ 扩展的实现。 + +### 编写 C++ 操作 + +让我们开始以 C++ 实现 LLTM! 我们需要反向传播的一项函数是 Sigmoid 导数。 这是一小段代码,用于讨论编写 C++ 扩展时可供我们使用的总体环境: + +```py +#include + +#include + +torch::Tensor d_sigmoid(torch::Tensor z) { + auto s = torch::sigmoid(z); + return (1 - s) * s; +} + +``` + +``是一站式标头,包括编写 C++ 扩展的所有必需的 PyTorch 位。 这包括: + +* ATen 库,这是我们用于张量计算的主要 API, +* [`pybind11`](https://github.com/pybind/pybind11) ,这是我们为 C++ 代码创建 Python 绑定的方式, +* 标头,用于管理 ATen 与`pybind11`之间的交互的详细信息。 + +`d_sigmoid()`的实现显示了如何使用 ATen API。 PyTorch 的张量和变量接口是从 ATen 库自动生成的,因此我们可以或多或少地将 Python 实现 1:1 转换为 C++。 我们用于所有计算的主要数据类型将为`torch::Tensor`。 可以在此处检查其完整的 API。 还要注意,我们可以包括``或*任何其他 C 或 C++ 头文件* –我们拥有 C++ 11 的全部功能。 + +#### 正向传播 + +接下来,我们可以将整个正向传播到 C++: + +```py +#include + +std::vector lltm_forward( + torch::Tensor input, + torch::Tensor weights, + torch::Tensor bias, + torch::Tensor old_h, + torch::Tensor old_cell) { + auto X = torch::cat({old_h, input}, /*dim=*/1); + + auto gate_weights = torch::addmm(bias, X, weights.transpose(0, 1)); + auto gates = gate_weights.chunk(3, /*dim=*/1); + + auto input_gate = torch::sigmoid(gates[0]); + auto output_gate = torch::sigmoid(gates[1]); + auto candidate_cell = torch::elu(gates[2], /*alpha=*/1.0); + + auto new_cell = old_cell + candidate_cell * input_gate; + auto new_h = torch::tanh(new_cell) * output_gate; + + return {new_h, + new_cell, + input_gate, + output_gate, + candidate_cell, + X, + gate_weights}; +} + +``` + +#### 反向传播 + +C++ 扩展 API 当前不提供为我们自动生成向后函数的方法。 因此,我们还必须实现 LLTM 的后向传递,它计算相对于正向传播的每个输入的损失导数。 最终,我们将正向和反向函数放入`torch.autograd.Function`中,以创建一个不错的 Python 绑定。 向后函数的作用稍大一些,因此我们将不深入研究代码(如果您有兴趣,请阅读 [Alex Graves 的论文](https://www.cs.toronto.edu/~graves/phd.pdf),以获取有关此方面的更多信息): + +```py +// tanh'(z) = 1 - tanh^2(z) +torch::Tensor d_tanh(torch::Tensor z) { + return 1 - z.tanh().pow(2); +} + +// elu'(z) = relu'(z) + { alpha * exp(z) if (alpha * (exp(z) - 1)) < 0, else 0} +torch::Tensor d_elu(torch::Tensor z, torch::Scalar alpha = 1.0) { + auto e = z.exp(); + auto mask = (alpha * (e - 1)) < 0; + return (z > 0).type_as(z) + mask.type_as(z) * (alpha * e); +} + +std::vector lltm_backward( + torch::Tensor grad_h, + torch::Tensor grad_cell, + torch::Tensor new_cell, + torch::Tensor input_gate, + torch::Tensor output_gate, + torch::Tensor candidate_cell, + torch::Tensor X, + torch::Tensor gate_weights, + torch::Tensor weights) { + auto d_output_gate = torch::tanh(new_cell) * grad_h; + auto d_tanh_new_cell = output_gate * grad_h; + auto d_new_cell = d_tanh(new_cell) * d_tanh_new_cell + grad_cell; + + auto d_old_cell = d_new_cell; + auto d_candidate_cell = input_gate * d_new_cell; + auto d_input_gate = candidate_cell * d_new_cell; + + auto gates = gate_weights.chunk(3, /*dim=*/1); + d_input_gate *= d_sigmoid(gates[0]); + d_output_gate *= d_sigmoid(gates[1]); + d_candidate_cell *= d_elu(gates[2]); + + auto d_gates = + torch::cat({d_input_gate, d_output_gate, d_candidate_cell}, /*dim=*/1); + + auto d_weights = d_gates.t().mm(X); + auto d_bias = d_gates.sum(/*dim=*/0, /*keepdim=*/true); + + auto d_X = d_gates.mm(weights); + const auto state_size = grad_h.size(1); + auto d_old_h = d_X.slice(/*dim=*/1, 0, state_size); + auto d_input = d_X.slice(/*dim=*/1, state_size); + + return {d_old_h, d_input, d_weights, d_bias, d_old_cell}; +} + +``` + +### 绑定到 Python + +一旦用 C++ 和 ATen 编写了操作,就可以使用`pybind11`以非常简单的方式将 C++ 函数或类绑定到 Python 中。 您对 PyTorch C++ 扩展部分的疑问或问题将在[`pybind11`文档](https://pybind11.readthedocs.io/en/master/)中得到解决。 + +对于我们的扩展,必要的绑定代码仅跨越四行: + +```py +PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { + m.def("forward", &lltm_forward, "LLTM forward"); + m.def("backward", &lltm_backward, "LLTM backward"); +} + +``` + +这里要注意的一点是宏`TORCH_EXTENSION_NAME`。 火炬扩展程序构建会将其定义为您在`setup.py`脚本中为扩展程序指定的名称。 在这种情况下,`TORCH_EXTENSION_NAME`的值为`lltm`。 这是为了避免在两个位置(构建脚本和 C++ 代码)都保留扩展名,因为两者之间的不匹配会导致令人讨厌且难以跟踪的问题。 + +### 使用扩展程序 + +现在,我们准备将扩展名导入 PyTorch 中。 此时,您的目录结构可能如下所示: + +```py +pytorch/ + lltm-extension/ + lltm.cpp + setup.py + +``` + +现在,运行`python setup.py install`来构建和安装扩展程序。 看起来应该像这样: + +```py +running install +running bdist_egg +running egg_info +creating lltm_cpp.egg-info +writing lltm_cpp.egg-info/PKG-INFO +writing dependency_links to lltm_cpp.egg-info/dependency_links.txt +writing top-level names to lltm_cpp.egg-info/top_level.txt +writing manifest file 'lltm_cpp.egg-info/SOURCES.txt' +reading manifest file 'lltm_cpp.egg-info/SOURCES.txt' +writing manifest file 'lltm_cpp.egg-info/SOURCES.txt' +installing library code to build/bdist.linux-x86_64/egg +running install_lib +running build_ext +building 'lltm_cpp' extension +creating build +creating build/temp.linux-x86_64-3.7 +gcc -pthread -B ~/local/miniconda/compiler_compat -Wl,--sysroot=/ -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I~/local/miniconda/lib/python3.7/site-packages/torch/include -I~/local/miniconda/lib/python3.7/site-packages/torch/include/torch/csrc/api/include -I~/local/miniconda/lib/python3.7/site-packages/torch/include/TH -I~/local/miniconda/lib/python3.7/site-packages/torch/include/THC -I~/local/miniconda/include/python3.7m -c lltm.cpp -o build/temp.linux-x86_64-3.7/lltm.o -DTORCH_API_INCLUDE_EXTENSION_H -DTORCH_EXTENSION_NAME=lltm_cpp -D_GLIBCXX_USE_CXX11_ABI=1 -std=c++11 +cc1plus: warning: command line option '-Wstrict-prototypes' is valid for C/ObjC but not for C++ +creating build/lib.linux-x86_64-3.7 +g++ -pthread -shared -B ~/local/miniconda/compiler_compat -L~/local/miniconda/lib -Wl,-rpath=~/local/miniconda/lib -Wl,--no-as-needed -Wl,--sysroot=/ build/temp.linux-x86_64-3.7/lltm.o -o build/lib.linux-x86_64-3.7/lltm_cpp.cpython-37m-x86_64-linux-gnu.so +creating build/bdist.linux-x86_64 +creating build/bdist.linux-x86_64/egg +copying build/lib.linux-x86_64-3.7/lltm_cpp.cpython-37m-x86_64-linux-gnu.so -> build/bdist.linux-x86_64/egg +creating stub loader for lltm_cpp.cpython-37m-x86_64-linux-gnu.so +byte-compiling build/bdist.linux-x86_64/egg/lltm_cpp.py to lltm_cpp.cpython-37.pyc +creating build/bdist.linux-x86_64/egg/EGG-INFO +copying lltm_cpp.egg-info/PKG-INFO -> build/bdist.linux-x86_64/egg/EGG-INFO +copying lltm_cpp.egg-info/SOURCES.txt -> build/bdist.linux-x86_64/egg/EGG-INFO +copying lltm_cpp.egg-info/dependency_links.txt -> build/bdist.linux-x86_64/egg/EGG-INFO +copying lltm_cpp.egg-info/top_level.txt -> build/bdist.linux-x86_64/egg/EGG-INFO +writing build/bdist.linux-x86_64/egg/EGG-INFO/native_libs.txt +zip_safe flag not set; analyzing archive contents... +__pycache__.lltm_cpp.cpython-37: module references __file__ +creating 'dist/lltm_cpp-0.0.0-py3.7-linux-x86_64.egg' and adding 'build/bdist.linux-x86_64/egg' to it +removing 'build/bdist.linux-x86_64/egg' (and everything under it) +Processing lltm_cpp-0.0.0-py3.7-linux-x86_64.egg +removing '~/local/miniconda/lib/python3.7/site-packages/lltm_cpp-0.0.0-py3.7-linux-x86_64.egg' (and everything under it) +creating ~/local/miniconda/lib/python3.7/site-packages/lltm_cpp-0.0.0-py3.7-linux-x86_64.egg +Extracting lltm_cpp-0.0.0-py3.7-linux-x86_64.egg to ~/local/miniconda/lib/python3.7/site-packages +lltm-cpp 0.0.0 is already the active version in easy-install.pth + +Installed ~/local/miniconda/lib/python3.7/site-packages/lltm_cpp-0.0.0-py3.7-linux-x86_64.egg +Processing dependencies for lltm-cpp==0.0.0 +Finished processing dependencies for lltm-cpp==0.0.0 + +``` + +关于编译器的小提示:由于 ABI 版本问题,用于构建 C++ 扩展的编译器必须与 PyTorch 编译器兼容。 实际上,这意味着您必须在 Linux 上使用 GCC 4.9 及更高版本。 对于 Ubuntu 16.04 和其他较新的 Linux 发行版,这应该已经是默认的编译器。 在 MacOS 上,您必须使用 clang(它没有任何 ABI 版本控制问题)。 在最坏的情况下,您可以使用编译器从源代码构建 PyTorch,然后使用相同的编译器构建扩展。 + +扩展程序构建完成后,您可以使用`setup.py`脚本中指定的名称,将其简单地导入 Python。 只需确保先`import torch`,因为这将解决动态链接器必须看到的一些符号: + +```py +In [1]: import torch +In [2]: import lltm_cpp +In [3]: lltm_cpp.forward +Out[3]: + +``` + +如果我们在函数或模块上调用`help()`,则可以看到其签名与我们的 C++ 代码匹配: + +```py +In[4] help(lltm_cpp.forward) +forward(...) method of builtins.PyCapsule instance + forward(arg0: torch::Tensor, arg1: torch::Tensor, arg2: torch::Tensor, arg3: torch::Tensor, arg4: torch::Tensor) -> List[torch::Tensor] + + LLTM forward + +``` + +由于我们现在可以从 Python 调用 C++ 函数,因此可以将它们包装为`torch.autograd.Function`和`torch.nn.Module`以使其成为 PyTorch 的一等公民: + +```py +import math +import torch + +# Our module! +import lltm_cpp + +class LLTMFunction(torch.autograd.Function): + @staticmethod + def forward(ctx, input, weights, bias, old_h, old_cell): + outputs = lltm_cpp.forward(input, weights, bias, old_h, old_cell) + new_h, new_cell = outputs[:2] + variables = outputs[1:] + [weights] + ctx.save_for_backward(*variables) + + return new_h, new_cell + + @staticmethod + def backward(ctx, grad_h, grad_cell): + outputs = lltm_cpp.backward( + grad_h.contiguous(), grad_cell.contiguous(), *ctx.saved_variables) + d_old_h, d_input, d_weights, d_bias, d_old_cell = outputs + return d_input, d_weights, d_bias, d_old_h, d_old_cell + +class LLTM(torch.nn.Module): + def __init__(self, input_features, state_size): + super(LLTM, self).__init__() + self.input_features = input_features + self.state_size = state_size + self.weights = torch.nn.Parameter( + torch.empty(3 * state_size, input_features + state_size)) + self.bias = torch.nn.Parameter(torch.empty(3 * state_size)) + self.reset_parameters() + + def reset_parameters(self): + stdv = 1.0 / math.sqrt(self.state_size) + for weight in self.parameters(): + weight.data.uniform_(-stdv, +stdv) + + def forward(self, input, state): + return LLTMFunction.apply(input, self.weights, self.bias, *state) + +``` + +#### 性能比较 + +现在我们已经可以使用并从 PyTorch 调用 C++ 代码了,我们可以运行一个小型基准测试,以查看通过用 C++ 重写操作所获得的性能。 我们将向前和向后运行 LLTM 几次,并测量持续时间: + +```py +import time + +import torch + +batch_size = 16 +input_features = 32 +state_size = 128 + +X = torch.randn(batch_size, input_features) +h = torch.randn(batch_size, state_size) +C = torch.randn(batch_size, state_size) + +rnn = LLTM(input_features, state_size) + +forward = 0 +backward = 0 +for _ in range(100000): + start = time.time() + new_h, new_C = rnn(X, (h, C)) + forward += time.time() - start + + start = time.time() + (new_h.sum() + new_C.sum()).backward() + backward += time.time() - start + +print('Forward: {:.3f} us | Backward {:.3f} us'.format(forward * 1e6/1e5, backward * 1e6/1e5)) + +``` + +如果我们使用本文开头用纯 Python 编写的原始 LLTM 运行此代码,则会得到以下数字(在我的机器上): + +```py +Forward: 506.480 us | Backward 444.694 us + +``` + +以及我们的新 C++ 版本: + +```py +Forward: 349.335 us | Backward 443.523 us + +``` + +我们已经可以看到正向函数的明显提速(超过 30%)。 对于反向函数,可以看到加速,尽管不是很大。 我在上面编写的后向通行证没有特别优化,并且肯定可以改进。 而且,PyTorch 的自动微分引擎可以自动并行化计算图,可以整体上使用更高效的操作流程,并且也可以用 C++ 来实现,因此有望实现更快的速度。 不过,这是一个良好的开始。 + +#### GPU 设备上的性能 + +关于 PyTorch 的 *ATen* 后端的一个奇妙事实是,它抽象了您正在运行的计算设备。 这意味着我们为 CPU 编写的同一代码*也可以*在 GPU 上运行,并且各个操作将相应地分派到 GPU 优化的实现。 对于某些运算,例如矩阵乘法(例如`mm`或`addmm`),这是一个很大的胜利。 让我们看一下使用 CUDA 张量运行 C++ 代码所获得的性能。 无需更改实现,我们只需要将张量从 Python 放入 GPU 内存,即可在创建时添加`device=cuda_device`参数,或者在创建后使用`.to(cuda_device)`: + +```py +import torch + +assert torch.cuda.is_available() +cuda_device = torch.device("cuda") # device object representing GPU + +batch_size = 16 +input_features = 32 +state_size = 128 + +# Note the device=cuda_device arguments here +X = torch.randn(batch_size, input_features, device=cuda_device) +h = torch.randn(batch_size, state_size, device=cuda_device) +C = torch.randn(batch_size, state_size, device=cuda_device) + +rnn = LLTM(input_features, state_size).to(cuda_device) + +forward = 0 +backward = 0 +for _ in range(100000): + start = time.time() + new_h, new_C = rnn(X, (h, C)) + torch.cuda.synchronize() + forward += time.time() - start + + start = time.time() + (new_h.sum() + new_C.sum()).backward() + torch.cuda.synchronize() + backward += time.time() - start + +print('Forward: {:.3f} us | Backward {:.3f} us'.format(forward * 1e6/1e5, backward * 1e6/1e5)) + +``` + +再次将普通的 PyTorch 代码与 C++ 版本(现在都在 CUDA 设备上运行)进行比较,我们再次看到了性能提升。 对于 Python/PyTorch: + +```py +Forward: 187.719 us | Backward 410.815 us + +``` + +和 C++/ATen: + +```py +Forward: 149.802 us | Backward 393.458 us + +``` + +与非 CUDA 代码相比,这可以大大提高整体速度。 但是,通过编写自定义 CUDA 内核,我们可以从 C++ 代码中获得更多性能,我们将很快深入其中。 在此之前,让我们讨论构建 C++ 扩展的另一种方法。 + +### JIT 编译扩展 + +之前,我提到过有两种构建 C++ 扩展的方法:使用`setuptools`或即时(JIT)。 在介绍了前者之后,让我们详细介绍后者。 JIT 编译机制通过调用 PyTorch API 中称为`torch.utils.cpp_extension.load()`的简单函数,为您提供了一种动态编译和加载扩展的方式。 对于 LLTM,这看起来像这样简单: + +```py +from torch.utils.cpp_extension import load + +lltm_cpp = load(name="lltm_cpp", sources=["lltm.cpp"]) + +``` + +在此,我们为函数提供与`setuptools`相同的信息。 在后台,这将执行以下操作: + +1. 创建一个临时目录`/tmp/torch_extensions/lltm`, +2. 将 [Ninja](https://ninja-build.org/) 构建文件发送到该临时目录中, +3. 将您的源文件编译到共享库中, +4. 将此共享库导入为 Python 模块。 + +实际上,如果将`verbose=True`传递给`cpp_extension.load()`,则会通知您有关过程: + +```py +Using /tmp/torch_extensions as PyTorch extensions root... +Emitting ninja build file /tmp/torch_extensions/lltm_cpp/build.ninja... +Building extension module lltm_cpp... +Loading extension module lltm_cpp... + +``` + +生成的 Python 模块将与`setuptools`生成的模块完全相同,但是消除了必须维护单独的`setup.py`构建文件的要求。 如果您的设置更为复杂,并且确实需要`setuptools`的全部功能,则*可以*编写自己的`setup.py` –但是在许多情况下,这种 JIT 技术就可以了。 第一次运行此行时,将需要一些时间,因为扩展程序是在后台编译的。 由于我们使用 Ninja 构建系统来构建您的源代码,因此重新编译是增量的,因此在您第二次运行 Python 模块时重新加载扩展程序非常快捷,而且如果您不更改扩展程序的源文件,开销也很低。 + +## 编写混合的 C++/CUDA 扩展 + +为了将实现真正提升到一个新的水平,我们可以使用自定义 CUDA 内核来手写前进和后退通道的一部分。 对于 LLTM,这具有特别有效的前景,因为按顺序有大量的逐点运算,这些运算都可以在单个 CUDA 内核中融合和并行化。 让我们看看如何编写这种 CUDA 内核,并使用此扩展机制将其与 PyTorch 集成。 + +编写 CUDA 扩展的一般策略是首先编写一个 C++ 文件,该文件定义将从 Python 调用的函数,然后使用`pybind11`将这些函数绑定到 Python。 此外,此文件还将声明在 CUDA(`.cu`)文件中定义的函数。 然后,C++ 函数将进行一些检查,并最终将其调用转发给 CUDA 函数。 在 CUDA 文件中,我们编写了实际的 CUDA 内核。 然后`cpp_extension`包将负责使用`gcc`等 C++ 编译器来编译 C++ 源代码,并使用 NVIDIA 的`nvcc`编译器来编译 CUDA 源。 这样可以确保每个编译器都照顾最了解要编译的文件。 最终,它们将被链接到一个共享库中,该库可从 Python 代码中获得。 + +我们将从 C++ 文件开始,我们将其称为`lltm_cuda.cpp`,例如: + +```py +#include + +#include + +// CUDA forward declarations + +std::vector lltm_cuda_forward( + torch::Tensor input, + torch::Tensor weights, + torch::Tensor bias, + torch::Tensor old_h, + torch::Tensor old_cell); + +std::vector lltm_cuda_backward( + torch::Tensor grad_h, + torch::Tensor grad_cell, + torch::Tensor new_cell, + torch::Tensor input_gate, + torch::Tensor output_gate, + torch::Tensor candidate_cell, + torch::Tensor X, + torch::Tensor gate_weights, + torch::Tensor weights); + +// C++ interface + +#define CHECK_CUDA(x) TORCH_CHECK(x.type().is_cuda(), #x " must be a CUDA tensor") +#define CHECK_CONTIGUOUS(x) TORCH_CHECK(x.is_contiguous(), #x " must be contiguous") +#define CHECK_INPUT(x) CHECK_CUDA(x); CHECK_CONTIGUOUS(x) + +std::vector lltm_forward( + torch::Tensor input, + torch::Tensor weights, + torch::Tensor bias, + torch::Tensor old_h, + torch::Tensor old_cell) { + CHECK_INPUT(input); + CHECK_INPUT(weights); + CHECK_INPUT(bias); + CHECK_INPUT(old_h); + CHECK_INPUT(old_cell); + + return lltm_cuda_forward(input, weights, bias, old_h, old_cell); +} + +std::vector lltm_backward( + torch::Tensor grad_h, + torch::Tensor grad_cell, + torch::Tensor new_cell, + torch::Tensor input_gate, + torch::Tensor output_gate, + torch::Tensor candidate_cell, + torch::Tensor X, + torch::Tensor gate_weights, + torch::Tensor weights) { + CHECK_INPUT(grad_h); + CHECK_INPUT(grad_cell); + CHECK_INPUT(input_gate); + CHECK_INPUT(output_gate); + CHECK_INPUT(candidate_cell); + CHECK_INPUT(X); + CHECK_INPUT(gate_weights); + CHECK_INPUT(weights); + + return lltm_cuda_backward( + grad_h, + grad_cell, + new_cell, + input_gate, + output_gate, + candidate_cell, + X, + gate_weights, + weights); +} + +PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { + m.def("forward", &lltm_forward, "LLTM forward (CUDA)"); + m.def("backward", &lltm_backward, "LLTM backward (CUDA)"); +} + +``` + +如您所见,它主要是样板文件,检查并转发到我们将在 CUDA 文件中定义的功能。 我们将此文件命名为`lltm_cuda_kernel.cu`(请注意`.cu`扩展名!)。 NVCC 可以合理地编译 C++ 11,因此我们仍然可以使用 ATen 和 C++ 标准库(但不能使用`torch.h`)。 请注意,`setuptools`无法处理具有相同名称但扩展名不同的文件,因此,如果您使用`setup.py`方法而不是 JIT 方法,则必须给 CUDA 文件指定一个与 C++ 文件不同的名称(对于 JIT 方法, `lltm.cpp`和`lltm.cu`可以正常工作)。 让我们看一下该文件的外观: + +```py +#include + +#include +#include + +#include + +template +__device__ __forceinline__ scalar_t sigmoid(scalar_t z) { + return 1.0 / (1.0 + exp(-z)); +} + +``` + +在这里,我们看到了我刚刚描述的标头,以及我们正在使用特定于 CUDA 的声明,例如`__device__`和`__forceinline__`以及类似`exp`的事实。 让我们继续一些我们需要的辅助功​​能: + +```py +template +__device__ __forceinline__ scalar_t d_sigmoid(scalar_t z) { + const auto s = sigmoid(z); + return (1.0 - s) * s; +} + +template +__device__ __forceinline__ scalar_t d_tanh(scalar_t z) { + const auto t = tanh(z); + return 1 - (t * t); +} + +template +__device__ __forceinline__ scalar_t elu(scalar_t z, scalar_t alpha = 1.0) { + return fmax(0.0, z) + fmin(0.0, alpha * (exp(z) - 1.0)); +} + +template +__device__ __forceinline__ scalar_t d_elu(scalar_t z, scalar_t alpha = 1.0) { + const auto e = exp(z); + const auto d_relu = z < 0.0 ? 0.0 : 1.0; + return d_relu + (((alpha * (e - 1.0)) < 0.0) ? (alpha * e) : 0.0); +} + +``` + +现在,要真正实现一个函数,我们再次需要两件事:一个函数执行我们不想手工明确编写的操作并调用 CUDA 内核,然后是要加速的部分的实际 CUDA 内核。 。 对于正向传播,第一个函数应如下所示: + +```py +std::vector lltm_cuda_forward( + torch::Tensor input, + torch::Tensor weights, + torch::Tensor bias, + torch::Tensor old_h, + torch::Tensor old_cell) { + auto X = torch::cat({old_h, input}, /*dim=*/1); + auto gates = torch::addmm(bias, X, weights.transpose(0, 1)); + + const auto batch_size = old_cell.size(0); + const auto state_size = old_cell.size(1); + + auto new_h = torch::zeros_like(old_cell); + auto new_cell = torch::zeros_like(old_cell); + auto input_gate = torch::zeros_like(old_cell); + auto output_gate = torch::zeros_like(old_cell); + auto candidate_cell = torch::zeros_like(old_cell); + + const int threads = 1024; + const dim3 blocks((state_size + threads - 1) / threads, batch_size); + + AT_DISPATCH_FLOATING_TYPES(gates.type(), "lltm_forward_cuda", ([&] { + lltm_cuda_forward_kernel<<>>( + gates.data(), + old_cell.data(), + new_h.data(), + new_cell.data(), + input_gate.data(), + output_gate.data(), + candidate_cell.data(), + state_size); + })); + + return {new_h, new_cell, input_gate, output_gate, candidate_cell, X, gates}; +} + +``` + +这里的主要关注点是`AT_DISPATCH_FLOATING_TYPES`宏和内核启动(由`<<<...>>>`指示)。 尽管 ATen 提取了我们处理过的张量的设备和数据类型,但张量在运行时仍将由具体设备上具体类型的内存支持。 因此,我们需要一种在运行时确定张量是什么类型,然后有选择地调用具有相应正确类型签名的函数的方法。 手动完成后,(在概念上)将如下所示: + +```py +switch (tensor.type().scalarType()) { + case torch::ScalarType::Double: + return function(tensor.data()); + case torch::ScalarType::Float: + return function(tensor.data()); + ... +} + +``` + +`AT_DISPATCH_FLOATING_TYPES`的目的是为我们处理此调度。 它需要一个类型(在我们的例子中为`gates.type()`),一个名称(用于错误消息)和一个 lambda 函数。 在此 lambda 函数内部,类型别名`scalar_t`可用,并且定义为该上下文中张量实际上在运行时的类型。 这样,如果我们有一个模板函数(CUDA 内核将使用该模板函数),则可以使用此`scalar_t`别名实例化它,然后将调用正确的函数。 在这种情况下,我们还希望检索张量的数据指针作为`scalar_t`类型的指针。 如果您想分派所有类型而不只是浮点类型(`Float`和`Double`),则可以使用`AT_DISPATCH_ALL_TYPES`。 + +请注意,我们使用普通的 ATen 执行一些操作。 这些操作仍将在 GPU 上运行,但使用 ATen 的默认实现。 这是有道理的,因为 ATen 会针对矩阵乘法(例如`addmm`)或卷积使用高度优化的例程,而这将很难实现和改善。 + +至于内核启动本身,我们在这里指定每个 CUDA 块将具有 1024 个线程,并且将整个 GPU 网格分为所需的`1 x 1024`线程块,以便用每个组件一个线程填充矩阵。 例如,如果我们的状态大小为 2048,批量大小为 4,则我们将以每个 1024 个线程总共启动`4 x 2 = 8`块。 如果您以前从未听说过 CUDA 的“障碍”或“网格”,那么 [CUDA 简介](https://devblogs.nvidia.com/even-easier-introduction-cuda)可能会有所帮助。 + +实际的 CUDA 内核非常简单(如果您曾经编程过 GPU): + +```py +template +__global__ void lltm_cuda_forward_kernel( + const scalar_t* __restrict__ gates, + const scalar_t* __restrict__ old_cell, + scalar_t* __restrict__ new_h, + scalar_t* __restrict__ new_cell, + scalar_t* __restrict__ input_gate, + scalar_t* __restrict__ output_gate, + scalar_t* __restrict__ candidate_cell, + size_t state_size) { + const int column = blockIdx.x * blockDim.x + threadIdx.x; + const int index = blockIdx.y * state_size + column; + const int gates_row = blockIdx.y * (state_size * 3); + if (column < state_size) { + input_gate[index] = sigmoid(gates[gates_row + column]); + output_gate[index] = sigmoid(gates[gates_row + state_size + column]); + candidate_cell[index] = elu(gates[gates_row + 2 * state_size + column]); + new_cell[index] = + old_cell[index] + candidate_cell[index] * input_gate[index]; + new_h[index] = tanh(new_cell[index]) * output_gate[index]; + } +} + +``` + +这里最有趣的是,我们能够为门矩阵中的每个单独的组件完全并行地计算所有这些逐点运算。 如果您想象必须用一个串行的百万个元素的`for`大型循环来执行此操作,那么您会明白为什么这样做会更快。 + +### 使用访问器 + +您可以在 CUDA 内核中看到,我们直接处理正确类型的指针。 实际上,直接在 cuda 内核内部使用高级类型不可知张量会非常低效。 + +但是,这是以易于使用和可读性为代价的,尤其是对于高维数据。 在我们的示例中,例如,我们知道连续的`gates`张量具有 3 个维度: + +1. 批量,`batch_size`的大小和`3*state_size`的步幅 +2. `3`的行,大小和`state_size`的步幅 +3. 指数,`state_size`的大小和`1`的步幅 + +那么我们如何访问内核中的元素`gates[n][row][column]`? 事实证明,您需要通过一些简单的算法就可以大步访问元素。 + +```py +gates.data()[n`3`state_size + row*state_size + column] + +``` + +除了冗长之外,此表达式还需要跨步才能明确知道,并因此在其参数内传递给内核函数。 您会看到,在内核函数接受具有不同大小的多个张量的情况下,您将得到很长的参数列表。 + +对我们来说幸运的是,ATen 提供了通过动态检查张量是维度的类型和数量而创建的访问器。 然后,访问器公开一个 API,可以有效地访问张量元素,而不必转换为单个指针: + +```py +torch::Tensor foo = torch::rand({12, 12}); + +// assert foo is 2-dimensional and holds floats. +auto foo_a = foo.accessor(); +float trace = 0; + +for(int i = 0; i < foo_a.size(0); i++) { + // use the accessor foo_a to get tensor data. + trace += foo_a[i][i]; +} + +``` + +访问器对象具有相对较高级别的接口,具有`.size()`和`.stride()`方法以及多维索引。 `.accessor<>`接口旨在在 CPU 张量上有效访问数据。 CUDA 张量的等效项是`packed_accessor64<>`和`packed_accessor32<>`,它们产生具有 64 位或 32 位整数索引的压缩访问器。 + +与访问器的根本区别在于,打包的访问器在其结构内部复制大小和跨度数据,而不是指向它。 它允许我们将其传递给 CUDA 内核函数并在其中使用其接口。 + +我们可以设计一个使用压缩访问器而不是指针的函数。 + +```py +__global__ void lltm_cuda_forward_kernel( + const torch::PackedTensorAccessor32 gates, + const torch::PackedTensorAccessor32 old_cell, + torch::PackedTensorAccessor32 new_h, + torch::PackedTensorAccessor32 new_cell, + torch::PackedTensorAccessor32 input_gate, + torch::PackedTensorAccessor32 output_gate, + torch::PackedTensorAccessor32 candidate_cell) + +``` + +让我们分解一下这里使用的模板。 前两个参数`scalar_t`和`2`与常规访问器相同。 参数`torch::RestrictPtrTraits`指示必须使用`__restrict__`关键字。 另请注意,我们使用了`PackedAccessor32`变体,将变体和步幅存储在`int32_t`中。 这很重要,因为使用 64 位变体(`PackedAccessor64`)会使内核变慢。 + +函数声明变为 + +```py +template +__global__ void lltm_cuda_forward_kernel( + const torch::PackedTensorAccessor32 gates, + const torch::PackedTensorAccessor32 old_cell, + torch::PackedTensorAccessor32 new_h, + torch::PackedTensorAccessor32 new_cell, + torch::PackedTensorAccessor32 input_gate, + torch::PackedTensorAccessor32 output_gate, + torch::PackedTensorAccessor32 candidate_cell) { + //batch index + const int n = blockIdx.y; + // column index + const int c = blockIdx.x * blockDim.x + threadIdx.x; + if (c < gates.size(2)){ + input_gate[n][c] = sigmoid(gates[n][0][c]); + output_gate[n][c] = sigmoid(gates[n][1][c]); + candidate_cell[n][c] = elu(gates[n][2][c]); + new_cell[n][c] = + old_cell[n][c] + candidate_cell[n][c] * input_gate[n][c]; + new_h[n][c] = tanh(new_cell[n][c]) * output_gate[n][c]; + } +} + +``` + +该实现更具可读性! 然后,通过在主机函数内使用`.packed_accessor32<>`方法创建压缩访问器来调用此函数。 + +```py +std::vector lltm_cuda_forward( + torch::Tensor input, + torch::Tensor weights, + torch::Tensor bias, + torch::Tensor old_h, + torch::Tensor old_cell) { + auto X = torch::cat({old_h, input}, /*dim=*/1); + auto gate_weights = torch::addmm(bias, X, weights.transpose(0, 1)); + + const auto batch_size = old_cell.size(0); + const auto state_size = old_cell.size(1); + + auto gates = gate_weights.reshape({batch_size, 3, state_size}); + auto new_h = torch::zeros_like(old_cell); + auto new_cell = torch::zeros_like(old_cell); + auto input_gate = torch::zeros_like(old_cell); + auto output_gate = torch::zeros_like(old_cell); + auto candidate_cell = torch::zeros_like(old_cell); + + const int threads = 1024; + const dim3 blocks((state_size + threads - 1) / threads, batch_size); + + AT_DISPATCH_FLOATING_TYPES(gates.type(), "lltm_forward_cuda", ([&] { + lltm_cuda_forward_kernel<<>>( + gates.packed_accessor32(), + old_cell.packed_accessor32(), + new_h.packed_accessor32(), + new_cell.packed_accessor32(), + input_gate.packed_accessor32(), + output_gate.packed_accessor32(), + candidate_cell.packed_accessor32()); + })); + + return {new_h, new_cell, input_gate, output_gate, candidate_cell, X, gates}; +} + +``` + +反向传播遵循相同的模式,在此我不再赘述: + +```py +template +__global__ void lltm_cuda_backward_kernel( + torch::PackedTensorAccessor32 d_old_cell, + torch::PackedTensorAccessor32 d_gates, + const torch::PackedTensorAccessor32 grad_h, + const torch::PackedTensorAccessor32 grad_cell, + const torch::PackedTensorAccessor32 new_cell, + const torch::PackedTensorAccessor32 input_gate, + const torch::PackedTensorAccessor32 output_gate, + const torch::PackedTensorAccessor32 candidate_cell, + const torch::PackedTensorAccessor32 gate_weights) { + //batch index + const int n = blockIdx.y; + // column index + const int c = blockIdx.x * blockDim.x + threadIdx.x; + if (c < d_gates.size(2)){ + const auto d_output_gate = tanh(new_cell[n][c]) * grad_h[n][c]; + const auto d_tanh_new_cell = output_gate[n][c] * grad_h[n][c]; + const auto d_new_cell = + d_tanh(new_cell[n][c]) * d_tanh_new_cell + grad_cell[n][c]; + + d_old_cell[n][c] = d_new_cell; + const auto d_candidate_cell = input_gate[n][c] * d_new_cell; + const auto d_input_gate = candidate_cell[n][c] * d_new_cell; + + d_gates[n][0][c] = + d_input_gate * d_sigmoid(gate_weights[n][0][c]); + d_gates[n][1][c] = + d_output_gate * d_sigmoid(gate_weights[n][1][c]); + d_gates[n][2][c] = + d_candidate_cell * d_elu(gate_weights[n][2][c]); + } +} + +std::vector lltm_cuda_backward( + torch::Tensor grad_h, + torch::Tensor grad_cell, + torch::Tensor new_cell, + torch::Tensor input_gate, + torch::Tensor output_gate, + torch::Tensor candidate_cell, + torch::Tensor X, + torch::Tensor gates, + torch::Tensor weights) { + auto d_old_cell = torch::zeros_like(new_cell); + auto d_gates = torch::zeros_like(gates); + + const auto batch_size = new_cell.size(0); + const auto state_size = new_cell.size(1); + + const int threads = 1024; + const dim3 blocks((state_size + threads - 1) / threads, batch_size); + + AT_DISPATCH_FLOATING_TYPES(X.type(), "lltm_forward_cuda", ([&] { + lltm_cuda_backward_kernel<<>>( + d_old_cell.packed_accessor32(), + d_gates.packed_accessor32(), + grad_h.packed_accessor32(), + grad_cell.packed_accessor32(), + new_cell.packed_accessor32(), + input_gate.packed_accessor32(), + output_gate.packed_accessor32(), + candidate_cell.packed_accessor32(), + gates.packed_accessor32()); + })); + + auto d_gate_weights = d_gates.reshape({batch_size, 3*state_size}); + auto d_weights = d_gate_weights.t().mm(X); + auto d_bias = d_gate_weights.sum(/*dim=*/0, /*keepdim=*/true); + + auto d_X = d_gate_weights.mm(weights); + auto d_old_h = d_X.slice(/*dim=*/1, 0, state_size); + auto d_input = d_X.slice(/*dim=*/1, state_size); + + return {d_old_h, d_input, d_weights, d_bias, d_old_cell, d_gates}; +} + +``` + +### 将 C++/CUDA 操作与 PyTorch 集成 + +同样,将支持 CUDA 的操作与 PyTorch 集成非常简单。 如果要编写`setup.py`脚本,它可能看起来像这样: + +```py +from setuptools import setup +from torch.utils.cpp_extension import BuildExtension, CUDAExtension + +setup( + name='lltm', + ext_modules=[ + CUDAExtension('lltm_cuda', [ + 'lltm_cuda.cpp', + 'lltm_cuda_kernel.cu', + ]) + ], + cmdclass={ + 'build_ext': BuildExtension + }) + +``` + +现在,我们使用`CUDAExtension()`代替`CppExtension()`。 我们只需要指定`.cu`文件和`.cpp`文件即可–该库将为您解决所有麻烦。 JIT 机制甚至更简单: + +```py +from torch.utils.cpp_extension import load + +lltm = load(name='lltm', sources=['lltm_cuda.cpp', 'lltm_cuda_kernel.cu']) + +``` + +#### 性能比较 + +我们的希望是,将我们的代码的逐点操作与 CUDA 并行化和融合,将改善 LLTM 的性能。 让我们看看这是否成立。 我们可以运行前面列出的代码来运行基准测试。 我们之前最快的版本是基于 CUDA 的 C++ 代码: + +```py +Forward: 149.802 us | Backward 393.458 us + +``` + +现在使用我们的自定义 CUDA 内核: + +```py +Forward: 129.431 us | Backward 304.641 us + +``` + +更多性能提升! + +## 总结 + +现在,您应该对 PyTorch 的 C++ 扩展机制有了一个很好的了解,并有使用它们的动机。 [您可以在此处找到本说明中显示的代码示例](https://github.com/pytorch/extension-cpp)。 如有疑问,请使用[论坛](https://discuss.pytorch.org)。 另外,请务必查看我们的[常见问题解答](https://pytorch.org/cppdocs/notes/faq.html),以防遇到任何问题。 \ No newline at end of file diff --git a/pytorch/官方教程/46.md b/pytorch/官方教程/46.md new file mode 100644 index 00000000..6ec1d1a3 --- /dev/null +++ b/pytorch/官方教程/46.md @@ -0,0 +1,782 @@ +# 使用自定义 C++ 运算符扩展 TorchScript + +> 原文: + +PyTorch 1.0 版本向 PyTorch 引入了一种新的编程模型,称为 [TorchScript](https://pytorch.org/docs/master/jit.html) 。 TorchScript 是 Python 编程语言的子集,可以通过 TorchScript 编译器进行解析,编译和优化。 此外,已编译的 TorchScript 模型可以选择序列化为磁盘文件格式,然后可以从纯 C++(以及 Python)加载并运行该文件格式以进行推理。 + +TorchScript 支持`torch`包提供的大量操作子集,使您可以纯粹表示为 PyTorch 的“标准库”中的一系列张量操作来表示多种复杂模型。 但是,有时您可能需要使用自定义 C++ 或 CUDA 函数扩展 TorchScript。 虽然我们建议您仅在无法(简单有效地)将您的想法表达为简单的 Python 函数时才诉诸该选项,但我们确实提供了一个非常友好且简单的接口,用于使用 [ATen](https://pytorch.org/cppdocs/#aten) 定义自定义 C++ 和 CUDA 内核。 ,PyTorch 的高性能 C++ 张量库。 绑定到 TorchScript 后,您可以将这些自定义内核(或“操作”)嵌入到 TorchScript 模型中,并以 Python 或直接以 C++ 的序列化形式执行它们。 + +以下段落提供了一个编写 TorchScript 自定义操作以调用 [OpenCV](https://www.opencv.org) (使用 C++ 编写的计算机视觉库)的示例。 我们将讨论如何在 C++ 中使用张量,如何有效地将它们转换为第三方张量格式(在这种情况下为 OpenCV `Mat`),如何在 TorchScript 运行时中注册您的运算符,以及最后如何编译该运算符并在 Python 和 C++ 中使用它。 + +## 在 C++ 中实现自定义运算符 + +在本教程中,我们将公开[`warpPerspective`](https://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html#warpperspective)函数,该函数将透视转换应用于图像,从 OpenCV 到 TorchScript 作为自定义运算符。 第一步是用 C++ 编写自定义运算符的实现。 让我们将此实现的文件称为`op.cpp`,并使其如下所示: + +```py +torch::Tensor warp_perspective(torch::Tensor image, torch::Tensor warp) { + // BEGIN image_mat + cv::Mat image_mat(/*rows=*/image.size(0), + /*cols=*/image.size(1), + /*type=*/CV_32FC1, + /*data=*/image.data_ptr()); + // END image_mat + + // BEGIN warp_mat + cv::Mat warp_mat(/*rows=*/warp.size(0), + /*cols=*/warp.size(1), + /*type=*/CV_32FC1, + /*data=*/warp.data_ptr()); + // END warp_mat + + // BEGIN output_mat + cv::Mat output_mat; + cv::warpPerspective(image_mat, output_mat, warp_mat, /*dsize=*/{8, 8}); + // END output_mat + + // BEGIN output_tensor + torch::Tensor output = torch::from_blob(output_mat.ptr(), /*sizes=*/{8, 8}); + return output.clone(); + // END output_tensor +} + +``` + +该运算符的代码很短。 在文件顶部,我们包含 OpenCV 标头文件`opencv2/opencv.hpp`和`torch/script.h`标头,该标头暴露了 PyTorch C++ API 中所有需要编写自定义 TorchScript 运算符的必要特性。 我们的函数`warp_perspective`有两个参数:输入`image`和我们希望应用于图像的`warp`变换矩阵。 这些输入的类型是`torch::Tensor`,这是 C++ 中 PyTorch 的张量类型(也是 Python 中所有张量的基础类型)。 我们的`warp_perspective`函数的返回类型也将是`torch::Tensor`。 + +小费 + +有关 ATen 的更多信息,请参见[本说明](https://pytorch.org/cppdocs/notes/tensor_basics.html),ATen 是为 PyTorch 提供`Tensor`类的库。 此外,[本教程](https://pytorch.org/cppdocs/notes/tensor_creation.html)描述了如何在 C++ 中分配和初始化新的张量对象(此运算符不需要)。 + +注意 + +TorchScript 编译器了解固定数量的类型。 只有这些类型可以用作自定义运算符的参数。 当前这些类型是:`torch::Tensor`,`torch::Scalar`,`double`,`int64_t`和这些类型的`std::vector`。 请注意,只支持`double`而不是`float`,只支持`int64_t`而不是其他整数类型,例如`int`,`short`或`long`。 + +在函数内部,我们要做的第一件事就是将 PyTorch 张量转换为 OpenCV 矩阵,因为 OpenCV 的`warpPerspective`期望`cv::Mat`对象作为输入。 幸运的是,有一种方法可以执行它,而无需复制任何数据。 在前几行中 + +```py + cv::Mat image_mat(/*rows=*/image.size(0), + /*cols=*/image.size(1), + /*type=*/CV_32FC1, + /*data=*/image.data_ptr()); + +``` + +我们正在调用 [OpenCV `Mat`类的构造器](https://docs.opencv.org/trunk/d3/d63/classcv_1_1Mat.html#a922de793eabcec705b3579c5f95a643e),将张量转换为`Mat`对象。 我们向其传递原始`image`张量的行数和列数,数据类型(在此示例中,我们将其固定为`float32`),最后是指向基础数据的原始指针– `float*`。 `Mat`类的此构造器的特殊之处在于它不会复制输入数据。 取而代之的是,它将简单地引用此存储器来执行`Mat`上的所有操作。 如果在`image_mat`上执行原地操作,这将反映在原始`image`张量中(反之亦然)。 即使我们实际上将数据存储在 PyTorch 张量中,这也使我们能够使用库的本机矩阵类型调用后续的 OpenCV 例程。 我们重复此过程将`warp` PyTorch 张量转换为`warp_mat` OpenCV 矩阵: + +```py + cv::Mat warp_mat(/*rows=*/warp.size(0), + /*cols=*/warp.size(1), + /*type=*/CV_32FC1, + /*data=*/warp.data_ptr()); + +``` + +接下来,我们准备调用我们渴望在 TorchScript 中使用的 OpenCV 函数:`warpPerspective`。 为此,我们将`image_mat`和`warp_mat`矩阵以及称为`output_mat`的空输出矩阵传递给 OpenCV 函数。 我们还指定了我们希望输出矩阵(图像)为`dsize`的大小。 对于此示例,它被硬编码为`8 x 8`: + +```py + cv::Mat output_mat; + cv::warpPerspective(image_mat, output_mat, warp_mat, /*dsize=*/{8, 8}); + +``` + +我们的自定义运算符实现的最后一步是将`output_mat`转换回 PyTorch 张量,以便我们可以在 PyTorch 中进一步使用它。 这与我们先前在另一个方向进行转换的操作极为相似。 在这种情况下,PyTorch 提供了一种`torch::from_blob`方法。 在这种情况下, *blob* 的意思是指向我们要解释为 PyTorch 张量的不透明平面指针。 对`torch::from_blob`的调用如下所示: + +```py + torch::Tensor output = torch::from_blob(output_mat.ptr(), /*sizes=*/{8, 8}); + return output.clone(); + +``` + +我们在 OpenCV `Mat`类上使用`.ptr()`方法来获取指向基础数据的原始指针(就像之前的 PyTorch 张量的`.data_ptr()`一样)。 我们还指定了张量的输出形状,我们将其硬编码为`8 x 8`。 然后`torch::from_blob`的输出是`torch::Tensor`,指向 OpenCV 矩阵拥有的内存。 + +从我们的运算符实现返回此张量之前,我们必须在张量上调用`.clone()`以执行基础数据的存储副本。 这样做的原因是`torch::from_blob`返回了一个不拥有其数据的张量。 那时,数据仍归 OpenCV 矩阵所有。 但是,此 OpenCV 矩阵将超出范围,并在函数末尾重新分配。 如果我们按原样返回`output`张量,那么当我们在函数外部使用它时,它将指向无效的内存。 调用`.clone()`会返回一个新张量,其中包含新张量自己拥有的原始数据的副本。 因此,返回外部世界是安全的。 + +## 使用 TorchScript 注册自定义运算符 + +现在,已经在 C++ 中实现了自定义运算符,我们需要在 T​​orchScript 运行时和编译器中将其注册。 这将使 TorchScript 编译器可以在 TorchScript 代码中解析对我们自定义运算符的引用。 如果您曾经使用过`pybind11`库,则我们的注册语法非常类似于`pybind11`语法。 要注册一个函数,我们编写: + +```py +TORCH_LIBRARY(my_ops, m) { + m.def("warp_perspective", warp_perspective); +} + +``` + +在`op.cpp`文件顶层的某个位置。 `TORCH_LIBRARY`宏创建一个在程序启动时将被调用的函数。 库的名称(`my_ops`)作为第一个参数给出(不应用引号引起来)。 第二个参数(`m`)定义了`torch::Library`类型的变量,该变量是注册运算符的主要接口。 方法`Library::def`实际上创建了一个名为`warp_perspective`的运算符,将其同时暴露给 Python 和 TorchScript。 您可以通过多次调用`def`来定义任意数量的运算符。 + +在后台,`def`函数实际上正在做大量工作:它正在使用模板元编程来检查函数的类型签名,并将其转换为可在 TorchScript 的类型系统中指定操作符类型的操作符架构。 + +## 构建自定义运算符 + +现在,我们已经用 C++ 实现了自定义运算符并编写了其注册代码,是时候将该运算符构建到一个(共享的)库中了,可以将其加载到 Python 中进行研究和实验,或者加载到 C++ 中以在非 Python 中进行推理。 环境。 有多种方法可以使用纯 CMake 或`setuptools`之类的 Python 替代方法来构建我们的运算符。 为简洁起见,以下段落仅讨论 CMake 方法。 本教程的附录将深入探讨其他替代方法。 + +### 环境设置 + +我们需要安装 PyTorch 和 OpenCV。 实现这两者的最简单,最独立于平台的方法是通过 Conda: + +```py +conda install -c pytorch pytorch +conda install opencv + +``` + +### 将 CMake 用于构建 + +为了使用 [CMake](https://cmake.org) 构建系统将自定义运算符构建到共享库中,我们需要编写一个简短的`CMakeLists.txt`文件并将其与我们先前的`op.cpp`文件放置在一起。 为此,让我们就一个看起来像这样的目录结构达成一致: + +```py +warp-perspective/ + op.cpp + CMakeLists.txt + +``` + +我们的`CMakeLists.txt`文件的内容应为以下内容: + +```py +cmake_minimum_required(VERSION 3.1 FATAL_ERROR) +project(warp_perspective) + +find_package(Torch REQUIRED) +find_package(OpenCV REQUIRED) + +# Define our library target +add_library(warp_perspective SHARED op.cpp) +# Enable C++14 +target_compile_features(warp_perspective PRIVATE cxx_std_14) +# Link against LibTorch +target_link_libraries(warp_perspective "${TORCH_LIBRARIES}") +# Link against OpenCV +target_link_libraries(warp_perspective opencv_core opencv_imgproc) + +``` + +现在要构建我们的运算符,我们可以从`warp_perspective`文件夹中运行以下命令: + +```py +$ mkdir build +$ cd build +$ cmake -DCMAKE_PREFIX_PATH="$(python -c 'import torch.utils; print(torch.utils.cmake_prefix_path)')" .. +-- The C compiler identification is GNU 5.4.0 +-- The CXX compiler identification is GNU 5.4.0 +-- Check for working C compiler: /usr/bin/cc +-- Check for working C compiler: /usr/bin/cc -- works +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - done +-- Detecting C compile features +-- Detecting C compile features - done +-- Check for working CXX compiler: /usr/bin/c++ +-- Check for working CXX compiler: /usr/bin/c++ -- works +-- Detecting CXX compiler ABI info +-- Detecting CXX compiler ABI info - done +-- Detecting CXX compile features +-- Detecting CXX compile features - done +-- Looking for pthread.h +-- Looking for pthread.h - found +-- Looking for pthread_create +-- Looking for pthread_create - not found +-- Looking for pthread_create in pthreads +-- Looking for pthread_create in pthreads - not found +-- Looking for pthread_create in pthread +-- Looking for pthread_create in pthread - found +-- Found Threads: TRUE +-- Found torch: /libtorch/lib/libtorch.so +-- Configuring done +-- Generating done +-- Build files have been written to: /warp_perspective/build +$ make -j +Scanning dependencies of target warp_perspective +[ 50%] Building CXX object CMakeFiles/warp_perspective.dir/op.cpp.o +[100%] Linking CXX shared library libwarp_perspective.so +[100%] Built target warp_perspective + +``` + +这会将`libwarp_perspective.so`共享库文件放置在`build`文件夹中。 在上面的`cmake`命令中,我们使用帮助程序变量`torch.utils.cmake_prefix_path`方便地告诉我们 PyTorch 安装的 cmake 文件在哪里。 + +我们将在下面进一步探讨如何使用和调用我们的运算符,但为了早日获得成功,我们可以尝试在 Python 中运行以下代码: + +```py +import torch +torch.ops.load_library("build/libwarp_perspective.so") +print(torch.ops.my_ops.warp_perspective) + +``` + +如果一切顺利,则应打印如下内容: + +```py + + +``` + +这是我们稍后将用来调用自定义运算符的 Python 函数。 + +## 在 Python 中使用 TorchScript 自定义运算符 + +将我们的自定义运算符构建到共享库后,我们就可以在 Python 的 TorchScript 模型中使用此运算符了。 这有两个部分:首先将运算符加载到 Python 中,其次在 TorchScript 代码中使用运算符。 + +您已经了解了如何将运算符导入 Python:`torch.ops.load_library()`。 此函数采用包含自定义运算符的共享库的路径,并将其加载到当前进程中。 加载共享库也将执行`TORCH_LIBRARY`块。 这将在 TorchScript 编译器中注册我们的自定义运算符,并允许我们在 TorchScript 代码中使用该运算符。 + +您可以将已加载的运算符称为`torch.ops..`,其中``是运算符名称的名称空间部分,而``是运算符的函数名称。 对于我们上面编写的运算符,名称空间为`my_ops`,函数名称为`warp_perspective`,这意味着我们的运算符可以作为`torch.ops.my_ops.warp_perspective`使用。 虽然可以在脚本化或跟踪的 TorchScript 模块中使用此函数,但我们也可以仅在急切的 PyTorch 中使用它,并将其传递给常规 PyTorch 张量: + +```py +import torch +torch.ops.load_library("build/libwarp_perspective.so") +print(torch.ops.my_ops.warp_perspective(torch.randn(32, 32), torch.rand(3, 3))) + +``` + +生产: + +```py +tensor([[0.0000, 0.3218, 0.4611, ..., 0.4636, 0.4636, 0.4636], + [0.3746, 0.0978, 0.5005, ..., 0.4636, 0.4636, 0.4636], + [0.3245, 0.0169, 0.0000, ..., 0.4458, 0.4458, 0.4458], + ..., + [0.1862, 0.1862, 0.1692, ..., 0.0000, 0.0000, 0.0000], + [0.1862, 0.1862, 0.1692, ..., 0.0000, 0.0000, 0.0000], + [0.1862, 0.1862, 0.1692, ..., 0.0000, 0.0000, 0.0000]]) + +``` + +注意 + +幕后发生的事情是,您第一次使用 Python 访问`torch.ops.namespace.function`时,TorchScript 编译器(在 C++ 领域)将查看是否已注册函数`namespace::function`,如果已注册,则将 Python 句柄返回给该函数, 我们随后可以使用它从 Python 调用我们的 C++ 运算符实现。 这是 TorchScript 自定义运算符和 C++ 扩展之间的一个值得注意的区别:C++ 扩展是使用`pybind11`手动绑定的,而 TorchScript 自定义操作则是由 PyTorch 自己动态绑定的。`pybind11`在绑定到 Python 的类型和类方面为您提供了更大的灵活性,因此建议将其用于纯粹渴望的代码,但 TorchScript 操作不支持它。 + +从这里开始,您可以在脚本或跟踪代码中使用自定义运算符,就像`torch`包中的其他函数一样。 实际上,诸如`torch.matmul`之类的“标准库”函数在很大程度上与自定义运算符使用相同的注册路径,这使得自定义运算符在 TorchScript 中的使用方式和位置方面真正成为一流公民。 (但是,区别之一是标准库函数具有自定义的 Python 自变量解析逻辑,与`torch.ops`自变量解析不同。) + +### 在跟踪中使用自定义运算符 + +首先,将我们的运算符嵌入到跟踪函数中。 回想一下,为了进行跟踪,我们从一些原始的 Pytorch 代码开始: + +```py +def compute(x, y, z): + return x.matmul(y) + torch.relu(z) + +``` + +然后在其上调用`torch.jit.trace`。 我们进一步传递`torch.jit.trace`一些示例输入,它将输入到我们的实现中,以记录输入流过其中时发生的操作顺序。 这样的结果实际上是渴望的 PyTorch 程序的“冻结”版本,TorchScript 编译器可以对其进行进一步的分析,优化和序列化: + +```py +inputs = [torch.randn(4, 8), torch.randn(8, 5), torch.randn(4, 5)] +trace = torch.jit.trace(compute, inputs) +print(trace.graph) + +``` + +生产: + +```py +graph(%x : Float(4:8, 8:1), + %y : Float(8:5, 5:1), + %z : Float(4:5, 5:1)): + %3 : Float(4:5, 5:1) = aten::matmul(%x, %y) # test.py:10:0 + %4 : Float(4:5, 5:1) = aten::relu(%z) # test.py:10:0 + %5 : int = prim::Constant[value=1]() # test.py:10:0 + %6 : Float(4:5, 5:1) = aten::add(%3, %4, %5) # test.py:10:0 + return (%6) + +``` + +现在,令人兴奋的启示是,我们可以简单地将自定义运算符放到 PyTorch 跟踪中,就好像它是`torch.relu`或任何其他`torch`函数一样: + +```py +def compute(x, y, z): + x = torch.ops.my_ops.warp_perspective(x, torch.eye(3)) + return x.matmul(y) + torch.relu(z) + +``` + +然后像以前一样跟踪它: + +```py +inputs = [torch.randn(4, 8), torch.randn(8, 5), torch.randn(8, 5)] +trace = torch.jit.trace(compute, inputs) +print(trace.graph) + +``` + +生产: + +```py +graph(%x.1 : Float(4:8, 8:1), + %y : Float(8:5, 5:1), + %z : Float(8:5, 5:1)): + %3 : int = prim::Constant[value=3]() # test.py:25:0 + %4 : int = prim::Constant[value=6]() # test.py:25:0 + %5 : int = prim::Constant[value=0]() # test.py:25:0 + %6 : Device = prim::Constant[value="cpu"]() # test.py:25:0 + %7 : bool = prim::Constant[value=0]() # test.py:25:0 + %8 : Float(3:3, 3:1) = aten::eye(%3, %4, %5, %6, %7) # test.py:25:0 + %x : Float(8:8, 8:1) = my_ops::warp_perspective(%x.1, %8) # test.py:25:0 + %10 : Float(8:5, 5:1) = aten::matmul(%x, %y) # test.py:26:0 + %11 : Float(8:5, 5:1) = aten::relu(%z) # test.py:26:0 + %12 : int = prim::Constant[value=1]() # test.py:26:0 + %13 : Float(8:5, 5:1) = aten::add(%10, %11, %12) # test.py:26:0 + return (%13) + +``` + +如此简单地将 TorchScript 自定义操作集成到跟踪的 PyTorch 代码中! + +### 将自定义运算符与脚本一起使用 + +除了跟踪之外,获得 PyTorch 程序的 TorchScript 表示形式的另一种方法是直接在 TorchScript 中编写代码。 TorchScript 在很大程度上是 Python 语言的子集,它具有一些限制,使 TorchScript 编译器更容易推理程序。 您可以使用`@torch.jit.script`标记自由函数,使用`@torch.jit.script_method`标记类中的方法(也必须从`torch.jit.ScriptModule`派生),将常规 PyTorch 代码转换为 TorchScript。 有关 TorchScript 注解的更多详细信息,请参见[此处](https://pytorch.org/docs/master/jit.html)。 + +使用 TorchScript 而不是跟踪的一个特殊原因是,跟踪无法捕获 PyTorch 代码中的控制流。 因此,让我们考虑使用控制流的此函数: + +```py +def compute(x, y): + if bool(x[0][0] == 42): + z = 5 + else: + z = 10 + return x.matmul(y) + z + +``` + +要将此函数从原始 PyTorch 转换为 TorchScript,我们用`@torch.jit.script`对其进行注解: + +```py +@torch.jit.script +def compute(x, y): + if bool(x[0][0] == 42): + z = 5 + else: + z = 10 + return x.matmul(y) + z + +``` + +这将及时将`compute`函数编译成图形表示形式,我们可以在`compute.graph`属性中进行检查: + +```py +>>> compute.graph +graph(%x : Dynamic + %y : Dynamic) { + %14 : int = prim::Constant[value=1]() + %2 : int = prim::Constant[value=0]() + %7 : int = prim::Constant[value=42]() + %z.1 : int = prim::Constant[value=5]() + %z.2 : int = prim::Constant[value=10]() + %4 : Dynamic = aten::select(%x, %2, %2) + %6 : Dynamic = aten::select(%4, %2, %2) + %8 : Dynamic = aten::eq(%6, %7) + %9 : bool = prim::TensorToBool(%8) + %z : int = prim::If(%9) + block0() { + -> (%z.1) + } + block1() { + -> (%z.2) + } + %13 : Dynamic = aten::matmul(%x, %y) + %15 : Dynamic = aten::add(%13, %z, %14) + return (%15); +} + +``` + +现在,就像以前一样,我们可以像脚本代码中的任何其他函数一样使用自定义运算符: + +```py +torch.ops.load_library("libwarp_perspective.so") + +@torch.jit.script +def compute(x, y): + if bool(x[0] == 42): + z = 5 + else: + z = 10 + x = torch.ops.my_ops.warp_perspective(x, torch.eye(3)) + return x.matmul(y) + z + +``` + +当 TorchScript 编译器看到对`torch.ops.my_ops.warp_perspective`的引用时,它将找到我们通过 C++ 中的`TORCH_LIBRARY`函数注册的实现,并将其编译为图形表示形式: + +```py +>>> compute.graph +graph(%x.1 : Dynamic + %y : Dynamic) { + %20 : int = prim::Constant[value=1]() + %16 : int[] = prim::Constant[value=[0, -1]]() + %14 : int = prim::Constant[value=6]() + %2 : int = prim::Constant[value=0]() + %7 : int = prim::Constant[value=42]() + %z.1 : int = prim::Constant[value=5]() + %z.2 : int = prim::Constant[value=10]() + %13 : int = prim::Constant[value=3]() + %4 : Dynamic = aten::select(%x.1, %2, %2) + %6 : Dynamic = aten::select(%4, %2, %2) + %8 : Dynamic = aten::eq(%6, %7) + %9 : bool = prim::TensorToBool(%8) + %z : int = prim::If(%9) + block0() { + -> (%z.1) + } + block1() { + -> (%z.2) + } + %17 : Dynamic = aten::eye(%13, %14, %2, %16) + %x : Dynamic = my_ops::warp_perspective(%x.1, %17) + %19 : Dynamic = aten::matmul(%x, %y) + %21 : Dynamic = aten::add(%19, %z, %20) + return (%21); + } + +``` + +请特别注意图末尾对`my_ops::warp_perspective`的引用。 + +注意 + +TorchScript 图形表示仍可能更改。 不要依靠它看起来像这样。 + +在 Python 中使用自定义运算符时,确实如此。 简而言之,您可以使用`torch.ops.load_library`导入包含您的运算符的库,并像其他任何`torch`运算符一样,从跟踪或编写脚本的 TorchScript 代码中调用自定义操作。 + +## 在 C++ 中使用 TorchScript 自定义运算符 + +TorchScript 的一项有用功能是能够将模型序列化到磁盘文件中。 该文件可以通过有线方式发送,存储在文件系统中,或者更重要的是,可以动态反序列化和执行,而无需保留原始源代码。 这在 Python 中是可能的,但在 C++ 中也是可能的。 为此,PyTorch [提供了纯 C++ API](https://pytorch.org/cppdocs/),用于反序列化以及执行 TorchScript 模型。 如果您还没有的话,请阅读[在 C++ 中加载和运行序列化 TorchScript 模型](https://pytorch.org/tutorials/advanced/cpp_export.html)的教程,接下来的几段将基于该教程构建。 + +简而言之,即使从文件反序列化并以 C++ 运行,也可以像常规`torch`运算符一样执行自定义运算符。 唯一的要求是将我们先前构建的自定义运算符共享库与执行模型的 C++ 应用链接。 在 Python 中,只需调用`torch.ops.load_library`即可。 在 C++ 中,您需要在使用的任何构建系统中将共享库与主应用链接。 下面的示例将使用 CMake 展示这一点。 + +注意 + +从技术上讲,您还可以在运行时将共享库动态加载到 C++ 应用中,就像在 Python 中一样。 在 Linux 上,可以使用`dlopen`来执行此操作。 在其他平台上也存在等效项。 + +在上面链接的 C++ 执行教程的基础上,让我们从一个最小的 C++ 应用开始,在与自定义运算符不同的文件夹中的`main.cpp`文件中,该文件加载并执行序列化的 TorchScript 模型: + +```py +#include // One-stop header. + +#include +#include + +int main(int argc, const char* argv[]) { + if (argc != 2) { + std::cerr << "usage: example-app \n"; + return -1; + } + + // Deserialize the ScriptModule from a file using torch::jit::load(). + std::shared_ptr module = torch::jit::load(argv[1]); + + std::vector inputs; + inputs.push_back(torch::randn({4, 8})); + inputs.push_back(torch::randn({8, 5})); + + torch::Tensor output = module->forward(std::move(inputs)).toTensor(); + + std::cout << output << std::endl; +} + +``` + +以及一个小的`CMakeLists.txt`文件: + +```py +cmake_minimum_required(VERSION 3.1 FATAL_ERROR) +project(example_app) + +find_package(Torch REQUIRED) + +add_executable(example_app main.cpp) +target_link_libraries(example_app "${TORCH_LIBRARIES}") +target_compile_features(example_app PRIVATE cxx_range_for) + +``` + +在这一点上,我们应该能够构建应用: + +并在尚未通过模型的情况下运行它: + +接下来,让我们序列化我们之前编写的使用自定义运算符的脚本函数: + +```py +torch.ops.load_library("libwarp_perspective.so") + +@torch.jit.script +def compute(x, y): + if bool(x[0][0] == 42): + z = 5 + else: + z = 10 + x = torch.ops.my_ops.warp_perspective(x, torch.eye(3)) + return x.matmul(y) + z + +compute.save("example.pt") + +``` + +最后一行将脚本函数序列化为一个名为`example.pt`的文件。 如果我们随后将此序列化模型传递给 C++ 应用,则可以立即运行它: + +或者可能不是。 也许还没有。 当然! 我们尚未将自定义运算符库与我们的应用链接。 让我们立即执行此操作,并正确进行操作,让我们稍微更新一下文件组织,如下所示: + +```py +example_app/ + CMakeLists.txt + main.cpp + warp_perspective/ + CMakeLists.txt + op.cpp + +``` + +这将允许我们将`warp_perspective`库 CMake 目标添加为应用目标的子目录。 `example_app`文件夹中的顶级`CMakeLists.txt`应该如下所示: + +```py +cmake_minimum_required(VERSION 3.1 FATAL_ERROR) +project(example_app) + +find_package(Torch REQUIRED) + +add_subdirectory(warp_perspective) + +add_executable(example_app main.cpp) +target_link_libraries(example_app "${TORCH_LIBRARIES}") +target_link_libraries(example_app -Wl,--no-as-needed warp_perspective) +target_compile_features(example_app PRIVATE cxx_range_for) + +``` + +基本的 CMake 配置与以前非常相似,只是我们将`warp_perspective` CMake 构建添加为子目录。 一旦其 CMake 代码运行,我们将`example_app`应用与`warp_perspective`共享库链接。 + +注意 + +上面的示例中嵌入了一个关键细节:`warp_perspective`链接行的`-Wl,--no-as-needed`前缀。 这是必需的,因为我们实际上不会在应用代码中从`warp_perspective`共享库中调用任何函数。 我们只需要运行`TORCH_LIBRARY`函数。 麻烦的是,这使链接器感到困惑,并使其认为可以完全跳过与库的链接。 在 Linux 上,`-Wl,--no-as-needed`标志会强制链接发生(注意:此标志特定于 Linux!)。 还有其他解决方法。 最简单的方法是在运算符库中定义*一些函数*,您需要从主应用中调用该函数。 这可能就像在某个标头中声明的函数`void init();`一样简单,然后在运算符库中将其定义为`void init() { }`。 在主应用中调用此`init()`函数会给链接器以印象,这是一个值得链接的库。 不幸的是,这超出了我们的控制范围,我们宁愿让您知道其原因和简单的解决方法,而不是让您将一些不透明的宏放入代码中。 + +现在,由于我们现在在顶层找到了`Torch`包,因此`warp_perspective`子目录中的`CMakeLists.txt`文件可以缩短一些。 它看起来应该像这样: + +```py +find_package(OpenCV REQUIRED) +add_library(warp_perspective SHARED op.cpp) +target_compile_features(warp_perspective PRIVATE cxx_range_for) +target_link_libraries(warp_perspective PRIVATE "${TORCH_LIBRARIES}") +target_link_libraries(warp_perspective PRIVATE opencv_core opencv_photo) + +``` + +让我们重新构建示例应用,该应用还将与自定义运算符库链接。 在顶层`example_app`目录中: + +```py +$ mkdir build +$ cd build +$ cmake -DCMAKE_PREFIX_PATH="$(python -c 'import torch.utils; print(torch.utils.cmake_prefix_path)')" .. +-- The C compiler identification is GNU 5.4.0 +-- The CXX compiler identification is GNU 5.4.0 +-- Check for working C compiler: /usr/bin/cc +-- Check for working C compiler: /usr/bin/cc -- works +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - done +-- Detecting C compile features +-- Detecting C compile features - done +-- Check for working CXX compiler: /usr/bin/c++ +-- Check for working CXX compiler: /usr/bin/c++ -- works +-- Detecting CXX compiler ABI info +-- Detecting CXX compiler ABI info - done +-- Detecting CXX compile features +-- Detecting CXX compile features - done +-- Looking for pthread.h +-- Looking for pthread.h - found +-- Looking for pthread_create +-- Looking for pthread_create - not found +-- Looking for pthread_create in pthreads +-- Looking for pthread_create in pthreads - not found +-- Looking for pthread_create in pthread +-- Looking for pthread_create in pthread - found +-- Found Threads: TRUE +-- Found torch: /libtorch/lib/libtorch.so +-- Configuring done +-- Generating done +-- Build files have been written to: /warp_perspective/example_app/build +$ make -j +Scanning dependencies of target warp_perspective +[ 25%] Building CXX object warp_perspective/CMakeFiles/warp_perspective.dir/op.cpp.o +[ 50%] Linking CXX shared library libwarp_perspective.so +[ 50%] Built target warp_perspective +Scanning dependencies of target example_app +[ 75%] Building CXX object CMakeFiles/example_app.dir/main.cpp.o +[100%] Linking CXX executable example_app +[100%] Built target example_app + +``` + +如果现在运行`example_app`二进制文件并将其交给序列化模型,我们应该得出一个圆满的结局: + +```py +$ ./example_app example.pt +11.4125 5.8262 9.5345 8.6111 12.3997 + 7.4683 13.5969 9.0850 11.0698 9.4008 + 7.4597 15.0926 12.5727 8.9319 9.0666 + 9.4834 11.1747 9.0162 10.9521 8.6269 +10.0000 10.0000 10.0000 10.0000 10.0000 +10.0000 10.0000 10.0000 10.0000 10.0000 +10.0000 10.0000 10.0000 10.0000 10.0000 +10.0000 10.0000 10.0000 10.0000 10.0000 +[ Variable[CPUFloatType]{8,5} ] + +``` + +成功! 您现在可以推断了。 + +## 总结 + +本教程向您介绍了如何在 C++ 中实现自定义 TorchScript 运算符,如何将其构建到共享库中,如何在 Python 中使用它来定义 TorchScript 模型以及如何将其加载到 C++ 应用中以进行推理工作负载。 现在,您可以使用与第三方 C++ 库进行接口的 C++ 运算符扩展 TorchScript 模型,编写自定义的高性能 CUDA 内核,或实现任何其他需要 Python,TorchScript 和 C++ 之间的界线才能平稳融合的用例。 + +与往常一样,如果您遇到任何问题或疑问,可以使用我们的[论坛](https://discuss.pytorch.org/)或 [GitHub ISSUE](https://github.com/pytorch/pytorch/issues) 进行联系。 另外,我们的[常见问题解答(FAQ)页面](https://pytorch.org/cppdocs/notes/faq.html)可能包含有用的信息。 + +## 附录 A:建立自定义运算符的更多方法 + +“构建自定义运算符”一节介绍了如何使用 CMake 将自定义运算符构建到共享库中。 本附录概述了两种进一步的编译方法。 他们俩都使用 Python 作为编译过程的“驱动程序”或“接口”。 此外,两者都重用了[现有基础结构](https://pytorch.org/docs/stable/cpp_extension.html)。 PyTorch 提供了 [C++ 扩展](https://pytorch.org/tutorials/advanced/cpp_extension.html),它们依赖于[`pybind11`](https://github.com/pybind/pybind11)用于将函数从 C++ “显式”绑定到 Python。 + +第一种方法是使用 C++ 扩展程序的[方便的即时(JIT)编译接口](https://pytorch.org/docs/stable/cpp_extension.html#torch.utils.cpp_extension.load)在您首次运行 PyTorch 脚本时在后台编译代码。 第二种方法依赖于古老的`setuptools`包,并涉及编写单独的`setup.py`文件。 这样可以进行更高级的配置,并与其他基于`setuptools`的项目集成。 我们将在下面详细探讨这两种方法。 + +### 使用 JIT 编译的构建 + +PyTorch C++ 扩展工具包提供的 JIT 编译功能可将自定义运算符的编译直接嵌入到您的 Python 代码中,例如在训练脚本的顶部。 + +注意 + +这里的“ JIT 编译”与 TorchScript 编译器中用于优化程序的 JIT 编译无关。 这只是意味着您的自定义运算符 C++ 代码将在您首次导入时在系统`/tmp`目录下的文件夹中编译,就像您自己事先对其进行编译一样。 + +此 JIT 编译功能有两种形式。 首先,您仍然将运算符实现保留在单独的文件(`op.cpp`)中,然后使用`torch.utils.cpp_extension.load()`编译扩展名。 通常,此函数将返回暴露您的 C++ 扩展的 Python 模块。 但是,由于我们没有将自定义运算符编译到其自己的 Python 模块中,因此我们只想编译一个普通的共享库。 幸运的是,`torch.utils.cpp_extension.load()`有一个参数`is_python_module`,可以将其设置为`False`,以表明我们仅对构建共享库感兴趣,而对 Python 模块不感兴趣。 然后`torch.utils.cpp_extension.load()`将会编译并将共享库也加载到当前进程中,就像`torch.ops.load_library`之前所做的那样: + +```py +import torch.utils.cpp_extension + +torch.utils.cpp_extension.load( + name="warp_perspective", + sources=["op.cpp"], + extra_ldflags=["-lopencv_core", "-lopencv_imgproc"], + is_python_module=False, + verbose=True +) + +print(torch.ops.my_ops.warp_perspective) + +``` + +这应该大致打印: + +```py + + +``` + +JIT 编译的第二种形式使您可以将自定义 TorchScript 运算符的源代码作为字符串传递。 为此,请使用`torch.utils.cpp_extension.load_inline`: + +```py +import torch +import torch.utils.cpp_extension + +op_source = """ +#include +#include + +torch::Tensor warp_perspective(torch::Tensor image, torch::Tensor warp) { + cv::Mat image_mat(/*rows=*/image.size(0), + /*cols=*/image.size(1), + /*type=*/CV_32FC1, + /*data=*/image.data()); + cv::Mat warp_mat(/*rows=*/warp.size(0), + /*cols=*/warp.size(1), + /*type=*/CV_32FC1, + /*data=*/warp.data()); + + cv::Mat output_mat; + cv::warpPerspective(image_mat, output_mat, warp_mat, /*dsize=*/{64, 64}); + + torch::Tensor output = + torch::from_blob(output_mat.ptr(), /*sizes=*/{64, 64}); + return output.clone(); +} + +TORCH_LIBRARY(my_ops, m) { + m.def("warp_perspective", &warp_perspective); +} +""" + +torch.utils.cpp_extension.load_inline( + name="warp_perspective", + cpp_sources=op_source, + extra_ldflags=["-lopencv_core", "-lopencv_imgproc"], + is_python_module=False, + verbose=True, +) + +print(torch.ops.my_ops.warp_perspective) + +``` + +自然,最佳实践是仅在源代码相当短的情况下才使用`torch.utils.cpp_extension.load_inline`。 + +请注意,如果您在 Jupyter 笔记本中使用此功能,则不应多次执行单元格的注册,因为每次执行都会注册一个新库并重新注册自定义运算符。 如果需要重新执行它,请事先重新启动笔记本的 Python 内核。 + +### 使用`setuptools`构建 + +从 Python 专门构建自定义运算符的第二种方法是使用`setuptools`。 这样做的好处是`setuptools`具有相当强大而广泛的接口,可以用来构建用 C++ 编写的 Python 模块。 但是,由于`setuptools`实际上是用于构建 Python 模块而不是普通的共享库(它们没有 Python 期望从模块中获得的必要入口点),因此这种方法可能有点古怪。 也就是说,您需要的是一个`setup.py`文件来代替`CMakeLists.txt`,该文件看起来像这样: + +```py +from setuptools import setup +from torch.utils.cpp_extension import BuildExtension, CppExtension + +setup( + name="warp_perspective", + ext_modules=[ + CppExtension( + "warp_perspective", + ["example_app/warp_perspective/op.cpp"], + libraries=["opencv_core", "opencv_imgproc"], + ) + ], + cmdclass={"build_ext": BuildExtension.with_options(no_python_abi_suffix=True)}, +) + +``` + +请注意,我们在底部的`BuildExtension`中启用了`no_python_abi_suffix`选项。 这指示`setuptools`在产生的共享库的名称中省略任何特定于 Python-3 的 ABI 后缀。 否则,例如在 Python 3.7 上,该库可能被称为`warp_perspective.cpython-37m-x86_64-linux-gnu.so`,其中`cpython-37m-x86_64-linux-gnu`是 ABI 标签,但我们确实只是希望将其称为`warp_perspective.so` + +如果现在从`setup.py`所在的文件夹中的终端中运行`python setup.py build develop`,我们应该会看到类似以下内容的内容: + +```py +$ python setup.py build develop +running build +running build_ext +building 'warp_perspective' extension +creating build +creating build/temp.linux-x86_64-3.7 +gcc -pthread -B /root/local/miniconda/compiler_compat -Wl,--sysroot=/ -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/root/local/miniconda/lib/python3.7/site-packages/torch/lib/include -I/root/local/miniconda/lib/python3.7/site-packages/torch/lib/include/torch/csrc/api/include -I/root/local/miniconda/lib/python3.7/site-packages/torch/lib/include/TH -I/root/local/miniconda/lib/python3.7/site-packages/torch/lib/include/THC -I/root/local/miniconda/include/python3.7m -c op.cpp -o build/temp.linux-x86_64-3.7/op.o -DTORCH_API_INCLUDE_EXTENSION_H -DTORCH_EXTENSION_NAME=warp_perspective -D_GLIBCXX_USE_CXX11_ABI=0 -std=c++11 +cc1plus: warning: command line option '-Wstrict-prototypes' is valid for C/ObjC but not for C++ +creating build/lib.linux-x86_64-3.7 +g++ -pthread -shared -B /root/local/miniconda/compiler_compat -L/root/local/miniconda/lib -Wl,-rpath=/root/local/miniconda/lib -Wl,--no-as-needed -Wl,--sysroot=/ build/temp.linux-x86_64-3.7/op.o -lopencv_core -lopencv_imgproc -o build/lib.linux-x86_64-3.7/warp_perspective.so +running develop +running egg_info +creating warp_perspective.egg-info +writing warp_perspective.egg-info/PKG-INFO +writing dependency_links to warp_perspective.egg-info/dependency_links.txt +writing top-level names to warp_perspective.egg-info/top_level.txt +writing manifest file 'warp_perspective.egg-info/SOURCES.txt' +reading manifest file 'warp_perspective.egg-info/SOURCES.txt' +writing manifest file 'warp_perspective.egg-info/SOURCES.txt' +running build_ext +copying build/lib.linux-x86_64-3.7/warp_perspective.so -> +Creating /root/local/miniconda/lib/python3.7/site-packages/warp-perspective.egg-link (link to .) +Adding warp-perspective 0.0.0 to easy-install.pth file + +Installed /warp_perspective +Processing dependencies for warp-perspective==0.0.0 +Finished processing dependencies for warp-perspective==0.0.0 + +``` + +这将产生一个名为`warp_perspective.so`的共享库,我们可以像之前那样将其传递给`torch.ops.load_library`,以使我们的运算符对 TorchScript 可见: + +```py +>>> import torch +>>> torch.ops.load_library("warp_perspective.so") +>>> print(torch.ops.custom.warp_perspective) + + +``` \ No newline at end of file diff --git a/pytorch/官方教程/47.md b/pytorch/官方教程/47.md new file mode 100644 index 00000000..42fc08a2 --- /dev/null +++ b/pytorch/官方教程/47.md @@ -0,0 +1,529 @@ +# 使用自定义 C++ 类扩展 TorchScript + +> 原文: + +本教程是[自定义运算符](torch_script_custom_ops.html)教程的后续教程,并介绍了我们为将 C++ 类同时绑定到 TorchScript 和 Python 而构建的 API。 该 API 与[`pybind11`](https://github.com/pybind/pybind11)非常相似,如果您熟悉该系统,则大多数概念都将转移过来。 + +## 用 C++ 实现和绑定类 + +在本教程中,我们将定义一个简单的 C++ 类,该类在成员变量中保持持久状态。 + +```py +// This header is all you need to do the C++ portions of this +// tutorial +#include +// This header is what defines the custom class registration +// behavior specifically. script.h already includes this, but +// we include it here so you know it exists in case you want +// to look at the API or implementation. +#include + +#include +#include + +template +struct MyStackClass : torch::CustomClassHolder { + std::vector stack_; + MyStackClass(std::vector init) : stack_(init.begin(), init.end()) {} + + void push(T x) { + stack_.push_back(x); + } + T pop() { + auto val = stack_.back(); + stack_.pop_back(); + return val; + } + + c10::intrusive_ptr clone() const { + return c10::make_intrusive(stack_); + } + + void merge(const c10::intrusive_ptr& c) { + for (auto& elem : c->stack_) { + push(elem); + } + } +}; + +``` + +有几件事要注意: + +* `torch/custom_class.h`是您需要使用自定义类扩展 TorchScript 的标头。 +* 注意,无论何时使用自定义类的实例,我们都通过`c10::intrusive_ptr<>`的实例来实现。 可以将`intrusive_ptr`视为类似于`std::shared_ptr`的智能指针,但是引用计数直接存储在对象中,而不是单独的元数据块(如`std::shared_ptr`中所做的。`torch::Tensor`内部使用相同的指针类型 ;和自定义类也必须使用此指针类型,以便我们可以一致地管理不同的对象类型。 +* 注意的第二件事是用户定义的类必须继承`torch::CustomClassHolder`。 这样可以确保自定义类具有存储引用计数的空间。 + +现在让我们看一下如何使该类对 TorchScript 可见,该过程称为*绑定*该类: + +```py +// Notice a few things: +// - We pass the class to be registered as a template parameter to +// `torch::class_`. In this instance, we've passed the +// specialization of the MyStackClass class ``MyStackClass``. +// In general, you cannot register a non-specialized template +// class. For non-templated classes, you can just pass the +// class name directly as the template parameter. +// - The arguments passed to the constructor make up the "qualified name" +// of the class. In this case, the registered class will appear in +// Python and C++ as `torch.classes.my_classes.MyStackClass`. We call +// the first argument the "namespace" and the second argument the +// actual class name. +TORCH_LIBRARY(my_classes, m) { + m.class_>("MyStackClass") + // The following line registers the contructor of our MyStackClass + // class that takes a single `std::vector` argument, + // i.e. it exposes the C++ method `MyStackClass(std::vector init)`. + // Currently, we do not support registering overloaded + // constructors, so for now you can only `def()` one instance of + // `torch::init`. + .def(torch::init>()) + // The next line registers a stateless (i.e. no captures) C++ lambda + // function as a method. Note that a lambda function must take a + // `c10::intrusive_ptr` (or some const/ref version of that) + // as the first argument. Other arguments can be whatever you want. + .def("top", [](const c10::intrusive_ptr>& self) { + return self->stack_.back(); + }) + // The following four lines expose methods of the MyStackClass + // class as-is. `torch::class_` will automatically examine the + // argument and return types of the passed-in method pointers and + // expose these to Python and TorchScript accordingly. Finally, notice + // that we must take the *address* of the fully-qualified method name, + // i.e. use the unary `&` operator, due to C++ typing rules. + .def("push", &MyStackClass::push) + .def("pop", &MyStackClass::pop) + .def("clone", &MyStackClass::clone) + .def("merge", &MyStackClass::merge) + ; +} + +``` + +## 使用 CMake 将示例构建为 C++ 项目 + +现在,我们将使用 [CMake](https://cmake.org) 构建系统来构建上述 C++ 代码。 首先,将到目前为止介绍的所有 C++ 代码放入`class.cpp`文件中。 然后,编写一个简单的`CMakeLists.txt`文件并将其放在同一目录中。 `CMakeLists.txt`应该是这样的: + +```py +cmake_minimum_required(VERSION 3.1 FATAL_ERROR) +project(custom_class) + +find_package(Torch REQUIRED) + +# Define our library target +add_library(custom_class SHARED class.cpp) +set(CMAKE_CXX_STANDARD 14) +# Link against LibTorch +target_link_libraries(custom_class "${TORCH_LIBRARIES}") + +``` + +另外,创建一个`build`目录。 您的文件树应如下所示: + +```py +custom_class_project/ + class.cpp + CMakeLists.txt + build/ + +``` + +我们假设您已经按照[上一教程](torch_script_custom_ops.html)中所述的相同方式设置了环境。 继续并调用`cmake`,然后进行构建项目: + +```py +$ cd build +$ cmake -DCMAKE_PREFIX_PATH="$(python -c 'import torch.utils; print(torch.utils.cmake_prefix_path)')" .. + -- The C compiler identification is GNU 7.3.1 + -- The CXX compiler identification is GNU 7.3.1 + -- Check for working C compiler: /opt/rh/devtoolset-7/root/usr/bin/cc + -- Check for working C compiler: /opt/rh/devtoolset-7/root/usr/bin/cc -- works + -- Detecting C compiler ABI info + -- Detecting C compiler ABI info - done + -- Detecting C compile features + -- Detecting C compile features - done + -- Check for working CXX compiler: /opt/rh/devtoolset-7/root/usr/bin/c++ + -- Check for working CXX compiler: /opt/rh/devtoolset-7/root/usr/bin/c++ -- works + -- Detecting CXX compiler ABI info + -- Detecting CXX compiler ABI info - done + -- Detecting CXX compile features + -- Detecting CXX compile features - done + -- Looking for pthread.h + -- Looking for pthread.h - found + -- Looking for pthread_create + -- Looking for pthread_create - not found + -- Looking for pthread_create in pthreads + -- Looking for pthread_create in pthreads - not found + -- Looking for pthread_create in pthread + -- Looking for pthread_create in pthread - found + -- Found Threads: TRUE + -- Found torch: /torchbind_tutorial/libtorch/lib/libtorch.so + -- Configuring done + -- Generating done + -- Build files have been written to: /torchbind_tutorial/build +$ make -j + Scanning dependencies of target custom_class + [ 50%] Building CXX object CMakeFiles/custom_class.dir/class.cpp.o + [100%] Linking CXX shared library libcustom_class.so + [100%] Built target custom_class + +``` + +您会发现,构建目录中现在有一个动态库文件。 在 Linux 上,它可能名为`libcustom_class.so`。 因此,文件树应如下所示: + +```py +custom_class_project/ + class.cpp + CMakeLists.txt + build/ + libcustom_class.so + +``` + +## 从 Python 和 TorchScript 使用 C++ 类 + +现在我们已经将我们的类及其注册编译为`.so`文件,我们可以将`.so`加载到 Python 中并进行尝试。 这是一个演示脚本的脚本: + +```py +import torch + +# `torch.classes.load_library()` allows you to pass the path to your .so file +# to load it in and make the custom C++ classes available to both Python and +# TorchScript +torch.classes.load_library("build/libcustom_class.so") +# You can query the loaded libraries like this: +print(torch.classes.loaded_libraries) +# prints {'/custom_class_project/build/libcustom_class.so'} + +# We can find and instantiate our custom C++ class in python by using the +# `torch.classes` namespace: +# +# This instantiation will invoke the MyStackClass(std::vector init) +# constructor we registered earlier +s = torch.classes.my_classes.MyStackClass(["foo", "bar"]) + +# We can call methods in Python +s.push("pushed") +assert s.pop() == "pushed" + +# Returning and passing instances of custom classes works as you'd expect +s2 = s.clone() +s.merge(s2) +for expected in ["bar", "foo", "bar", "foo"]: + assert s.pop() == expected + +# We can also use the class in TorchScript +# For now, we need to assign the class's type to a local in order to +# annotate the type on the TorchScript function. This may change +# in the future. +MyStackClass = torch.classes.my_classes.MyStackClass + +@torch.jit.script +def do_stacks(s: MyStackClass): # We can pass a custom class instance + # We can instantiate the class + s2 = torch.classes.my_classes.MyStackClass(["hi", "mom"]) + s2.merge(s) # We can call a method on the class + # We can also return instances of the class + # from TorchScript function/methods + return s2.clone(), s2.top() + +stack, top = do_stacks(torch.classes.my_classes.MyStackClass(["wow"])) +assert top == "wow" +for expected in ["wow", "mom", "hi"]: + assert stack.pop() == expected + +``` + +## 使用自定义类保存,加载和运行 TorchScript 代码 + +我们还可以在使用 libtorch 的 C++ 进程中使用自定义注册的 C++ 类。 举例来说,让我们定义一个简单的`nn.Module`,它实例化并调用`MyStackClass`类上的方法: + +```py +import torch + +torch.classes.load_library('build/libcustom_class.so') + +class Foo(torch.nn.Module): + def __init__(self): + super().__init__() + + def forward(self, s: str) -> str: + stack = torch.classes.my_classes.MyStackClass(["hi", "mom"]) + return stack.pop() + s + +scripted_foo = torch.jit.script(Foo()) +print(scripted_foo.graph) + +scripted_foo.save('foo.pt') + +``` + +我们文件系统中的`foo.pt`现在包含我们刚刚定义的序列化 TorchScript 程序。 + +现在,我们将定义一个新的 CMake 项目,以展示如何加载此模型及其所需的`.so`文件。 有关如何执行此操作的完整说明,请查看[在 C++ 中加载 TorchScript 模型](https://pytorch.org/tutorials/advanced/cpp_export.html)的教程。 + +与之前类似,让我们创建一个包含以下内容的文件结构: + +```py +cpp_inference_example/ + infer.cpp + CMakeLists.txt + foo.pt + build/ + custom_class_project/ + class.cpp + CMakeLists.txt + build/ + +``` + +请注意,我们已经复制了序列化的`foo.pt`文件以及上面`custom_class_project`的源代码树。 我们将把`custom_class_project`作为依赖项添加到此 C++ 项目中,以便可以将自定义类构建到二进制文件中。 + +让我们用以下内容填充`infer.cpp`: + +```py +#include + +#include +#include + +int main(int argc, const char* argv[]) { + torch::jit::Module module; + try { + // Deserialize the ScriptModule from a file using torch::jit::load(). + module = torch::jit::load("foo.pt"); + } + catch (const c10::Error& e) { + std::cerr << "error loading the model\n"; + return -1; + } + + std::vector inputs = {"foobarbaz"}; + auto output = module.forward(inputs).toString(); + std::cout << output->string() << std::endl; +} + +``` + +同样,让我们​​定义`CMakeLists.txt`文件: + +```py +cmake_minimum_required(VERSION 3.1 FATAL_ERROR) +project(infer) + +find_package(Torch REQUIRED) + +add_subdirectory(custom_class_project) + +# Define our library target +add_executable(infer infer.cpp) +set(CMAKE_CXX_STANDARD 14) +# Link against LibTorch +target_link_libraries(infer "${TORCH_LIBRARIES}") +# This is where we link in our libcustom_class code, making our +# custom class available in our binary. +target_link_libraries(infer -Wl,--no-as-needed custom_class) + +``` + +您知道练习:`cd build`,`cmake`和`make`: + +```py +$ cd build +$ cmake -DCMAKE_PREFIX_PATH="$(python -c 'import torch.utils; print(torch.utils.cmake_prefix_path)')" .. + -- The C compiler identification is GNU 7.3.1 + -- The CXX compiler identification is GNU 7.3.1 + -- Check for working C compiler: /opt/rh/devtoolset-7/root/usr/bin/cc + -- Check for working C compiler: /opt/rh/devtoolset-7/root/usr/bin/cc -- works + -- Detecting C compiler ABI info + -- Detecting C compiler ABI info - done + -- Detecting C compile features + -- Detecting C compile features - done + -- Check for working CXX compiler: /opt/rh/devtoolset-7/root/usr/bin/c++ + -- Check for working CXX compiler: /opt/rh/devtoolset-7/root/usr/bin/c++ -- works + -- Detecting CXX compiler ABI info + -- Detecting CXX compiler ABI info - done + -- Detecting CXX compile features + -- Detecting CXX compile features - done + -- Looking for pthread.h + -- Looking for pthread.h - found + -- Looking for pthread_create + -- Looking for pthread_create - not found + -- Looking for pthread_create in pthreads + -- Looking for pthread_create in pthreads - not found + -- Looking for pthread_create in pthread + -- Looking for pthread_create in pthread - found + -- Found Threads: TRUE + -- Found torch: /local/miniconda3/lib/python3.7/site-packages/torch/lib/libtorch.so + -- Configuring done + -- Generating done + -- Build files have been written to: /cpp_inference_example/build +$ make -j + Scanning dependencies of target custom_class + [ 25%] Building CXX object custom_class_project/CMakeFiles/custom_class.dir/class.cpp.o + [ 50%] Linking CXX shared library libcustom_class.so + [ 50%] Built target custom_class + Scanning dependencies of target infer + [ 75%] Building CXX object CMakeFiles/infer.dir/infer.cpp.o + [100%] Linking CXX executable infer + [100%] Built target infer + +``` + +现在我们可以运行令人兴奋的 C++ 二进制文件: + +```py +$ ./infer + momfoobarbaz + +``` + +难以置信! + +## 将自定义类移入或移出`IValue` + +也可能需要将自定义类从自定义 C++ 类实例移入或移出`IValue`, such as when you take or return IValues from TorchScript methods or you want to instantiate a custom class attribute in C++. For creating an IValue: + +* `torch::make_custom_class()`提供类似于`c10::intrusive_ptr`的 API,因为它将采用您提供给它的任何参数集,调用与该参数集匹配的`T`的构造器,并包装该实例,然后返回。 但是,它不仅返回指向自定义类对象的指针,还返回包装对象的`IValue`。 然后,您可以将此`IValue`直接传递给 TorchScript。 +* 如果您已经有一个指向类的`intrusive_ptr`,则可以使用构造器`IValue(intrusive_ptr)`直接从其构造`IValue`。 + +要将`IValue`转换回自定义类: + +* `IValue::toCustomClass()`将返回一个`intrusive_ptr`,指向`IValue`包含的自定义类。 在内部,此函数正在检查`T`是否已注册为自定义类,并且`IValue`实际上确实包含一个自定义类。 您可以通过调用`isCustomClass()`来手动检查`IValue`是否包含自定义类。 + +## 为自定义 C++ 类定义序列化/反序列化方法 + +如果您尝试将具有自定义绑定 C++ 类的`ScriptModule`保存为属性,则会出现以下错误: + +```py +# export_attr.py +import torch + +torch.classes.load_library('build/libcustom_class.so') + +class Foo(torch.nn.Module): + def __init__(self): + super().__init__() + self.stack = torch.classes.my_classes.MyStackClass(["just", "testing"]) + + def forward(self, s: str) -> str: + return self.stack.pop() + s + +scripted_foo = torch.jit.script(Foo()) + +scripted_foo.save('foo.pt') +loaded = torch.jit.load('foo.pt') + +print(loaded.stack.pop()) + +``` + +```py +$ python export_attr.py +RuntimeError: Cannot serialize custom bound C++ class __torch__.torch.classes.my_classes.MyStackClass. Please define serialization methods via def_pickle for this class. (pushIValueImpl at ../torch/csrc/jit/pickler.cpp:128) + +``` + +这是因为 TorchScript 无法自动找出 C++ 类中保存的信息。 您必须手动指定。 这样做的方法是使用`class_`上的特殊`def_pickle`方法在类上定义`__getstate__`和`__setstate__`方法。 + +注意 + +TorchScript 中`__getstate__`和`__setstate__`的语义与 Python `pickle`模块的语义相同。 您可以[阅读更多](https://github.com/pytorch/pytorch/blob/master/torch/csrc/jit/docs/serialization.md#getstate-and-setstate)有关如何使用这些方法的信息。 + +这是`def_pickle`调用的示例,我们可以将其添加到`MyStackClass`的注册中以包括序列化方法: + +```py + // class_<>::def_pickle allows you to define the serialization + // and deserialization methods for your C++ class. + // Currently, we only support passing stateless lambda functions + // as arguments to def_pickle + .def_pickle( + // __getstate__ + // This function defines what data structure should be produced + // when we serialize an instance of this class. The function + // must take a single `self` argument, which is an intrusive_ptr + // to the instance of the object. The function can return + // any type that is supported as a return value of the TorchScript + // custom operator API. In this instance, we've chosen to return + // a std::vector as the salient data to preserve + // from the class. + [](const c10::intrusive_ptr>& self) + -> std::vector { + return self->stack_; + }, + // __setstate__ + // This function defines how to create a new instance of the C++ + // class when we are deserializing. The function must take a + // single argument of the same type as the return value of + // `__getstate__`. The function must return an intrusive_ptr + // to a new instance of the C++ class, initialized however + // you would like given the serialized state. + [](std::vector state) + -> c10::intrusive_ptr> { + // A convenient way to instantiate an object and get an + // intrusive_ptr to it is via `make_intrusive`. We use + // that here to allocate an instance of MyStackClass + // and call the single-argument std::vector + // constructor with the serialized state. + return c10::make_intrusive>(std::move(state)); + }); + +``` + +注意 + +我们在 Pickle API 中采用与`pybind11`不同的方法。`pybind11`作为传递给`class_::def()`的特殊函数`pybind11::pickle()`,为此我们有一个单独的方法`def_pickle`。 这是因为`torch::jit::pickle`这个名称已经被使用了,我们不想引起混淆。 + +以这种方式定义(反)序列化行为后,脚本现在可以成功运行: + +```py +$ python ../export_attr.py +testing + +``` + +## 定义接受或返回绑定 C++ 类的自定义运算符 + +定义自定义 C++ 类后,您还可以将该类用作自变量或从自定义运算符返回(即自由函数)。 假设您具有以下自由函数: + +```py +c10::intrusive_ptr> manipulate_instance(const c10::intrusive_ptr>& instance) { + instance->pop(); + return instance; +} + +``` + +您可以在`TORCH_LIBRARY`块中运行以下代码来注册它: + +```py + m.def( + "foo::manipulate_instance(__torch__.torch.classes.my_classes.MyStackClass x) -> __torch__.torch.classes.my_classes.MyStackClass Y", + manipulate_instance + ); + +``` + +有关注册 API 的更多详细信息,请参见[自定义操作教程](https://pytorch.org/tutorials/advanced/torch_script_custom_ops.html)。 + +完成此操作后,您可以像以下示例一样使用操作: + +```py +class TryCustomOp(torch.nn.Module): + def __init__(self): + super(TryCustomOp, self).__init__() + self.f = torch.classes.my_classes.MyStackClass(["foo", "bar"]) + + def forward(self): + return torch.ops.foo.manipulate_instance(self.f) + +``` + +注意 + +注册使用 C++ 类作为参数的运算符时,要求已注册自定义类。 您可以通过确保自定义类注册和您的自由函数定义在同一`TORCH_LIBRARY`块中,并确保自定义类注册位于第一位来强制实现此操作。 将来,我们可能会放宽此要求,以便可以按任何顺序进行注册。 + +## 总结 + +本教程向您介绍了如何向 TorchScript(以及扩展为 Python)公开 C++ 类,如何注册其方法,如何从 Python 和 TorchScript 使用该类以及如何使用该类保存和加载代码以及运行该代码。 在独立的 C++ 过程中。 现在,您可以使用与第三方 C++ 库连接的 C++ 类扩展 TorchScript 模型,或实现需要 Python,TorchScript 和 C++ 之间的界线平滑融合的任何其他用例。 + +与往常一样,如果您遇到任何问题或疑问,可以使用我们的[论坛](https://discuss.pytorch.org/)或 [GitHub ISSUE](https://github.com/pytorch/pytorch/issues) 进行联系。 另外,我们的[常见问题解答(FAQ)页面](https://pytorch.org/cppdocs/notes/faq.html)可能包含有用的信息。 \ No newline at end of file diff --git a/pytorch/官方教程/48.md b/pytorch/官方教程/48.md new file mode 100644 index 00000000..6c9882e5 --- /dev/null +++ b/pytorch/官方教程/48.md @@ -0,0 +1,233 @@ +# TorchScript 中的动态并行性 + +> 原文: + +在本教程中,我们介绍在 TorchScript 中执行*动态互操作并行化*的语法。 此并行性具有以下属性: + +* 动态-创建的并行任务的数量及其工作量可能取决于程序的控制流。 +* 互操作-并行性与并行运行 TorchScript 程序片段有关。 这与*运算内部并行化*不同,后者涉及拆分单个运算符并并行运行运算符工作的子集。 + +## 基本语法 + +动态并行的两个重要 API 是: + +* `torch.jit.fork(fn : Callable[..., T], *args, **kwargs) -> torch.jit.Future[T]` +* `torch.jit.wait(fut : torch.jit.Future[T]) -> T` + +通过示例来演示这些工作原理的好方法: + +```py +import torch + +def foo(x): + return torch.neg(x) + +@torch.jit.script +def example(x): + # Call `foo` using parallelism: + # First, we "fork" off a task. This task will run `foo` with argument `x` + future = torch.jit.fork(foo, x) + + # Call `foo` normally + x_normal = foo(x) + + # Second, we "wait" on the task. Since the task may be running in + # parallel, we have to "wait" for its result to become available. + # Notice that by having lines of code between the "fork()" and "wait()" + # call for a given Future, we can overlap computations so that they + # run in parallel. + x_parallel = torch.jit.wait(future) + + return x_normal, x_parallel + +print(example(torch.ones(1))) # (-1., -1.) + +``` + +`fork()`接受可调用`fn`以及该可调用`args`和`kwargs`的参数,并创建异步任务来执行`fn`。 `fn`可以是函数,方法或模块实例。 `fork()`返回对此执行结果的值的引用,称为`Future`。 因为`fork`在创建异步任务后立即返回,所以在执行`fork()`调用之后的代码行时可能尚未执行`fn`。 因此,`wait()`用于等待异步任务完成并返回值。 + +这些结构可用于重叠函数内语句的执行(如工作示例部分所示),或与其他语言结构(如循环)组合在一起: + +```py +import torch +from typing import List + +def foo(x): + return torch.neg(x) + +@torch.jit.script +def example(x): + futures : List[torch.jit.Future[torch.Tensor]] = [] + for _ in range(100): + futures.append(torch.jit.fork(foo, x)) + + results = [] + for future in futures: + results.append(torch.jit.wait(future)) + + return torch.sum(torch.stack(results)) + +print(example(torch.ones([]))) + +``` + +注意 + +当我们初始化一个空的期货列表时,我们需要在`futures`上添加一个显式类型注解。 在 TorchScript 中,空容器默认假定它们包含张量值,因此我们将列表构造器`#`注解为`List[torch.jit.Future[torch.Tensor]]`类型 + +本示例使用`fork()`启动函数`foo`的 100 个实例,等待 100 个任务完成,然后对结果求和,返回`-100.0`。 + +## 应用示例:双向 LSTM 的集成 + +让我们尝试将并行性应用于一个更现实的示例,看看我们可以从中获得什么样的性能。 首先,让我们定义基准模型:双向 LSTM 层的集合。 + +```py +import torch, time + +# In RNN parlance, the dimensions we care about are: +# # of time-steps (T) +# Batch size (B) +# Hidden size/number of "channels" (C) +T, B, C = 50, 50, 1024 + +# A module that defines a single "bidirectional LSTM". This is simply two +# LSTMs applied to the same sequence, but one in reverse +class BidirectionalRecurrentLSTM(torch.nn.Module): + def __init__(self): + super().__init__() + self.cell_f = torch.nn.LSTM(input_size=C, hidden_size=C) + self.cell_b = torch.nn.LSTM(input_size=C, hidden_size=C) + + def forward(self, x : torch.Tensor) -> torch.Tensor: + # Forward layer + output_f, _ = self.cell_f(x) + + # Backward layer. Flip input in the time dimension (dim 0), apply the + # layer, then flip the outputs in the time dimension + x_rev = torch.flip(x, dims=[0]) + output_b, _ = self.cell_b(torch.flip(x, dims=[0])) + output_b_rev = torch.flip(output_b, dims=[0]) + + return torch.cat((output_f, output_b_rev), dim=2) + +# An "ensemble" of `BidirectionalRecurrentLSTM` modules. The modules in the +# ensemble are run one-by-one on the same input then their results are +# stacked and summed together, returning the combined result. +class LSTMEnsemble(torch.nn.Module): + def __init__(self, n_models): + super().__init__() + self.n_models = n_models + self.models = torch.nn.ModuleList([ + BidirectionalRecurrentLSTM() for _ in range(self.n_models)]) + + def forward(self, x : torch.Tensor) -> torch.Tensor: + results = [] + for model in self.models: + results.append(model(x)) + return torch.stack(results).sum(dim=0) + +# For a head-to-head comparison to what we're going to do with fork/wait, let's +# instantiate the model and compile it with TorchScript +ens = torch.jit.script(LSTMEnsemble(n_models=4)) + +# Normally you would pull this input out of an embedding table, but for the +# purpose of this demo let's just use random data. +x = torch.rand(T, B, C) + +# Let's run the model once to warm up things like the memory allocator +ens(x) + +x = torch.rand(T, B, C) + +# Let's see how fast it runs! +s = time.time() +ens(x) +print('Inference took', time.time() - s, ' seconds') + +``` + +在我的机器上,该网络运行时间为`2.05`秒。 我们可以做得更好! + +## 并行化前向和后向层 + +我们可以做的一个非常简单的事情是在`BidirectionalRecurrentLSTM`中并行化前进和后退层。 为此,计算结构是静态的,因此我们实际上甚至不需要任何循环。 像这样重写`BidirectionalRecurrentLSTM`的`forward`方法: + +```py +def forward(self, x : torch.Tensor) -> torch.Tensor: + # Forward layer - fork() so this can run in parallel to the backward + # layer + future_f = torch.jit.fork(self.cell_f, x) + + # Backward layer. Flip input in the time dimension (dim 0), apply the + # layer, then flip the outputs in the time dimension + x_rev = torch.flip(x, dims=[0]) + output_b, _ = self.cell_b(torch.flip(x, dims=[0])) + output_b_rev = torch.flip(output_b, dims=[0]) + + # Retrieve the output from the forward layer. Note this needs to happen + # *after* the stuff we want to parallelize with + output_f, _ = torch.jit.wait(future_f) + + return torch.cat((output_f, output_b_rev), dim=2) + +``` + +在此示例中,`forward()`将`cell_f`的执行委派给另一个线程,而它继续执行`cell_b`。 这导致两个单元的执行彼此重叠。 + +通过简单的修改再次运行脚本会产生`1.71`秒的运行时间,从而改进了`17%`! + +## 旁注:可视化并行性 + +我们还没有完成模型的优化,但是值得介绍一下用于可视化性能的工具。 一种重要的工具是 [PyTorch 分析器](https://pytorch.org/docs/stable/autograd.html#profiler)。 + +让我们将分析器与 Chrome 跟踪导出功能一起使用,以可视化并行模型的性能: + +此代码段将写出名为`parallel.json`的文件。 如果您将 Google Chrome 浏览器导航到`chrome://tracing`,单击`Load`按钮,然后加载该 JSON 文件,则应该看到类似以下的时间轴: + +![](img/6b495cb0cd4336a2469d9f07696faa3e.png) + +时间轴的横轴表示时间,纵轴表示执行线程。 如我们所见,我们一次运行两个`lstm`实例。 这是我们辛勤工作使双向层平行的结果! + +## 集成中的并行化模型 + +您可能已经注意到,我们的代码中还有更多的并行化机会:我们还可以并行运行`LSTMEnsemble`中包含的模型。 做到这一点的方法很简单,这就是我们应该更改`LSTMEnsemble`的`forward`方法的方式: + +```py +def forward(self, x : torch.Tensor) -> torch.Tensor: + # Launch tasks for each model + futures : List[torch.jit.Future[torch.Tensor]] = [] + for model in self.models: + futures.append(torch.jit.fork(model, x)) + + # Collect the results from the launched tasks + results : List[torch.Tensor] = [] + for future in futures: + results.append(torch.jit.wait(future)) + + return torch.stack(results).sum(dim=0) + +``` + +或者,如果您重视简洁性,我们可以使用列表推导: + +```py +def forward(self, x : torch.Tensor) -> torch.Tensor: + futures = [torch.jit.fork(model, x) for model in self.models] + results = [torch.jit.wait(fut) for fut in futures] + return torch.stack(results).sum(dim=0) + +``` + +如介绍中所述,我们使用循环为集合中的每个模型分派任务。 然后,我们使用了另一个循环来等待所有任务完成。 这提供了更多的计算重叠。 + +通过此小更新,脚本将在`1.4`秒内运行,总速度为`32%`! 两行代码相当不错。 + +我们还可以再次使用 Chrome 跟踪器来查看运行情况: + +![](img/ac8752539498c11001a65c1ff470d696.png) + +现在我们可以看到所有`LSTM`实例都在完全并行运行。 + +## 总结 + +在本教程中,我们学习了`fork()`和`wait()`,这是在 TorchScript 中执行动态,互操作并行的基本 API。 我们看到了一些典型的使用模式,这些模式使用这些函数并行执行 TorchScript 代码中的函数,方法或`Modules`的执行。 最后,我们通过一个使用该技术优化模型的示例进行了研究,并探索了 PyTorch 中可用的性能测量和可视化工具。 \ No newline at end of file diff --git a/pytorch/官方教程/49.md b/pytorch/官方教程/49.md new file mode 100644 index 00000000..f2776e85 --- /dev/null +++ b/pytorch/官方教程/49.md @@ -0,0 +1,414 @@ +# C++ 前端中的 Autograd + +> 原文: + +`autograd`包对于在 PyTorch 中构建高度灵活和动态的神经网络至关重要。 PyTorch Python 前端中的大多数 autograd API 也可以在 C++ 前端中使用,从而可以轻松地将 Autograd 代码从 Python 转换为 C++。 + +在本教程中,我们将看几个在 PyTorch C++ 前端中进行 Autograd 的示例。 请注意,本教程假定您已经对 Python 前端中的 Autograd 有基本的了解。 如果不是这种情况,请先阅读 [Autograd:自动微分](https://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html)。 + +## 基本的 Autograd 操作 + +(改编自[本教程](https://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html#autograd-automatic-differentiation)) + +创建一个张量并设置`torch::requires_grad()`以跟踪它的计算 + +```py +auto x = torch::ones({2, 2}, torch::requires_grad()); +std::cout << x << std::endl; + +``` + +出: + +```py +1 1 +1 1 +[ CPUFloatType{2,2} ] + +``` + +进行张量运算: + +```py +auto y = x + 2; +std::cout << y << std::endl; + +``` + +出: + +```py + 3 3 + 3 3 +[ CPUFloatType{2,2} ] + +``` + +`y`是由于操作而创建的,因此具有`grad_fn`。 + +```py +std::cout << y.grad_fn()->name() << std::endl; + +``` + +出: + +```py +AddBackward1 + +``` + +在`y`上执行更多操作 + +```py +auto z = y * y * 3; +auto out = z.mean(); + +std::cout << z << std::endl; +std::cout << z.grad_fn()->name() << std::endl; +std::cout << out << std::endl; +std::cout << out.grad_fn()->name() << std::endl; + +``` + +出: + +```py + 27 27 + 27 27 +[ CPUFloatType{2,2} ] +MulBackward1 +27 +[ CPUFloatType{} ] +MeanBackward0 + +``` + +`.requires_grad_( ... )`原地更改现有张量的`requires_grad`标志。 + +```py +auto a = torch::randn({2, 2}); +a = ((a * 3) / (a - 1)); +std::cout << a.requires_grad() << std::endl; + +a.requires_grad_(true); +std::cout << a.requires_grad() << std::endl; + +auto b = (a * a).sum(); +std::cout << b.grad_fn()->name() << std::endl; + +``` + +出: + +```py +false +true +SumBackward0 + +``` + +现在让我们反向传播。 因为`out`包含单个标量,所以`out.backward()`等效于`out.backward(torch::tensor(1.))`。 + +```py +out.backward(); + +``` + +打印梯度`d(out) / dx` + +```py +std::cout << x.grad() << std::endl; + +``` + +出: + +```py + 4.5000 4.5000 + 4.5000 4.5000 +[ CPUFloatType{2,2} ] + +``` + +您应该具有`4.5`的矩阵。 有关如何获得此值的说明,请参见[本教程](https://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html#gradients)中的相应部分。 + +现在,让我们来看一个向量雅各布产品的示例: + +```py +x = torch::randn(3, torch::requires_grad()); + +y = x * 2; +while (y.norm().item() < 1000) { + y = y * 2; +} + +std::cout << y << std::endl; +std::cout << y.grad_fn()->name() << std::endl; + +``` + +出: + +```py +-1021.4020 + 314.6695 + -613.4944 +[ CPUFloatType{3} ] +MulBackward1 + +``` + +如果我们想要向量-Jacobian 乘积,请将向量作为参数传递给`backward`: + +```py +auto v = torch::tensor({0.1, 1.0, 0.0001}, torch::kFloat); +y.backward(v); + +std::cout << x.grad() << std::endl; + +``` + +出: + +```py + 102.4000 + 1024.0000 + 0.1024 +[ CPUFloatType{3} ] + +``` + +您也可以通过在代码块中放置`torch::NoGradGuard`来停止对需要梯度的张量的跟踪历史的自动定格 + +```py +std::cout << x.requires_grad() << std::endl; +std::cout << x.pow(2).requires_grad() << std::endl; + +{ + torch::NoGradGuard no_grad; + std::cout << x.pow(2).requires_grad() << std::endl; +} + +``` + +出: + +```py +true +true +false + +``` + +或者使用`.detach()`获得具有相同内容但不需要梯度的新张量: + +```py +std::cout << x.requires_grad() << std::endl; +y = x.detach(); +std::cout << y.requires_grad() << std::endl; +std::cout << x.eq(y).all().item() << std::endl; + +``` + +出: + +```py +true +false +true + +``` + +有关 C++ 张量自动梯度 API 的更多信息,例如`grad`/`requires_grad`/`is_leaf`/`backward`/`detach`/`detach_`/`register_hook`/`retain_grad`,请参见[相应的 C++ API 文档](https://pytorch.org/cppdocs/api/classat_1_1_tensor.html)。 + +## 用 C++ 计算高阶梯度 + +高阶梯度的应用之一是计算梯度罚分。 我们来看看使用`torch::autograd::grad`的示例: + +```py +#include + +auto model = torch::nn::Linear(4, 3); + +auto input = torch::randn({3, 4}).requires_grad_(true); +auto output = model(input); + +// Calculate loss +auto target = torch::randn({3, 3}); +auto loss = torch::nn::MSELoss()(output, target); + +// Use norm of gradients as penalty +auto grad_output = torch::ones_like(output); +auto gradient = torch::autograd::grad({output}, {input}, /*grad_outputs=*/{grad_output}, /*create_graph=*/true)[0]; +auto gradient_penalty = torch::pow((gradient.norm(2, /*dim=*/1) - 1), 2).mean(); + +// Add gradient penalty to loss +auto combined_loss = loss + gradient_penalty; +combined_loss.backward(); + +std::cout << input.grad() << std::endl; + +``` + +出: + +```py +-0.1042 -0.0638 0.0103 0.0723 +-0.2543 -0.1222 0.0071 0.0814 +-0.1683 -0.1052 0.0355 0.1024 +[ CPUFloatType{3,4} ] + +``` + +有关如何使用它们的更多信息,请参见[`torch::autograd::backward`](https://pytorch.org/cppdocs/api/function_namespacetorch_1_1autograd_1afa9b5d4329085df4b6b3d4b4be48914b.html)和[`torch::autograd::grad`](https://pytorch.org/cppdocs/api/function_namespacetorch_1_1autograd_1a1e03c42b14b40c306f9eb947ef842d9c.html)的文档。 + +## 在 C++ 中使用自定义 Autograd 函数 + +(改编自[本教程](https://pytorch.org/docs/stable/notes/extending.html#extending-torch-autograd)) + +向`torch::autograd`添加新的基本操作需要为每个操作实现一个新的`torch::autograd::Function`子类。 `torch::autograd::Function`用于`torch::autograd`计算结果和梯度,并对操作历史进行编码。 每个新函数都需要您实现两种方法:`forward`和`backward`,有关详细要求,请参见[此链接](https://pytorch.org/cppdocs/api/structtorch_1_1autograd_1_1_function.html)。 + +在下面,您可以从`torch::nn`找到`Linear`函数的代码: + +```py +#include + +using namespace torch::autograd; + +// Inherit from Function +class LinearFunction : public Function { + public: + // Note that both forward and backward are static functions + + // bias is an optional argument + static torch::Tensor forward( + AutogradContext *ctx, torch::Tensor input, torch::Tensor weight, torch::Tensor bias = torch::Tensor()) { + ctx->save_for_backward({input, weight, bias}); + auto output = input.mm(weight.t()); + if (bias.defined()) { + output += bias.unsqueeze(0).expand_as(output); + } + return output; + } + + static tensor_list backward(AutogradContext *ctx, tensor_list grad_outputs) { + auto saved = ctx->get_saved_variables(); + auto input = saved[0]; + auto weight = saved[1]; + auto bias = saved[2]; + + auto grad_output = grad_outputs[0]; + auto grad_input = grad_output.mm(weight); + auto grad_weight = grad_output.t().mm(input); + auto grad_bias = torch::Tensor(); + if (bias.defined()) { + grad_bias = grad_output.sum(0); + } + + return {grad_input, grad_weight, grad_bias}; + } +}; + +``` + +然后,我们可以通过以下方式使用`LinearFunction`: + +```py +auto x = torch::randn({2, 3}).requires_grad_(); +auto weight = torch::randn({4, 3}).requires_grad_(); +auto y = LinearFunction::apply(x, weight); +y.sum().backward(); + +std::cout << x.grad() << std::endl; +std::cout << weight.grad() << std::endl; + +``` + +出: + +```py + 0.5314 1.2807 1.4864 + 0.5314 1.2807 1.4864 +[ CPUFloatType{2,3} ] + 3.7608 0.9101 0.0073 + 3.7608 0.9101 0.0073 + 3.7608 0.9101 0.0073 + 3.7608 0.9101 0.0073 +[ CPUFloatType{4,3} ] + +``` + +在这里,我们给出了一个由非张量参数设置参数的函数的附加示例: + +```py +#include + +using namespace torch::autograd; + +class MulConstant : public Function { + public: + static torch::Tensor forward(AutogradContext *ctx, torch::Tensor tensor, double constant) { + // ctx is a context object that can be used to stash information + // for backward computation + ctx->saved_data["constant"] = constant; + return tensor * constant; + } + + static tensor_list backward(AutogradContext *ctx, tensor_list grad_outputs) { + // We return as many input gradients as there were arguments. + // Gradients of non-tensor arguments to forward must be `torch::Tensor()`. + return {grad_outputs[0] * ctx->saved_data["constant"].toDouble(), torch::Tensor()}; + } +}; + +``` + +然后,我们可以通过以下方式使用`MulConstant`: + +```py +auto x = torch::randn({2}).requires_grad_(); +auto y = MulConstant::apply(x, 5.5); +y.sum().backward(); + +std::cout << x.grad() << std::endl; + +``` + +出: + +```py + 5.5000 + 5.5000 +[ CPUFloatType{2} ] + +``` + +有关`torch::autograd::Function`的更多信息,请参见[其文档](https://pytorch.org/cppdocs/api/structtorch_1_1autograd_1_1_function.html)。 + +## 将 Autograd 代码从 Python 转换为 C++ + +在较高的层次上,在 C++ 中使用 Autograd 的最简单方法是先在 Python 中拥有可用的 Autograd 代码,然后使用下表将您的 Autograd 代码从 Python 转换为 C++: + +| Python | C++ | +| --- | --- | +| `torch.autograd.backward` | [`torch::autograd::backward`](https://pytorch.org/cppdocs/api/function_namespacetorch_1_1autograd_1afa9b5d4329085df4b6b3d4b4be48914b.html)) | +| `torch.autograd.grad` | [`torch::autograd::grad`](https://pytorch.org/cppdocs/api/function_namespacetorch_1_1autograd_1a1e03c42b14b40c306f9eb947ef842d9c.html)) | +| `torch.Tensor.detach` | [`torch::Tensor::detach`](https://pytorch.org/cppdocs/api/classat_1_1_tensor.html#_CPPv4NK2at6Tensor6detachEv)) | +| `torch.Tensor.detach_` | [`torch::Tensor::detach_`](https://pytorch.org/cppdocs/api/classat_1_1_tensor.html#_CPPv4NK2at6Tensor7detach_Ev)) | +| `torch.Tensor.backward` | [`torch::Tensor::backward`](https://pytorch.org/cppdocs/api/classat_1_1_tensor.html#_CPPv4NK2at6Tensor8backwardERK6Tensorbb)) | +| `torch.Tensor.register_hook` | [`torch::Tensor::register_hook`](https://pytorch.org/cppdocs/api/classat_1_1_tensor.html#_CPPv4I0ENK2at6Tensor13register_hookE18hook_return_void_tI1TERR1T)) | +| `torch.Tensor.requires_grad` | [`torch::Tensor::requires_grad_`](https://pytorch.org/cppdocs/api/classat_1_1_tensor.html#_CPPv4NK2at6Tensor14requires_grad_Eb)) | +| `torch.Tensor.retain_grad` | [`torch::Tensor::retain_grad`](https://pytorch.org/cppdocs/api/classat_1_1_tensor.html#_CPPv4NK2at6Tensor11retain_gradEv)) | +| `torch.Tensor.grad` | [`torch::Tensor::grad`](https://pytorch.org/cppdocs/api/classat_1_1_tensor.html#_CPPv4NK2at6Tensor4gradEv)) | +| `torch.Tensor.grad_fn` | [`torch::Tensor::grad_fn`](https://pytorch.org/cppdocs/api/classat_1_1_tensor.html#_CPPv4NK2at6Tensor7grad_fnEv)) | +| `torch.Tensor.set_data` | [`torch::Tensor::set_data`](https://pytorch.org/cppdocs/api/classat_1_1_tensor.html#_CPPv4NK2at6Tensor8set_dataERK6Tensor)) | +| `torch.Tensor.data` | [`torch::Tensor::data`](https://pytorch.org/cppdocs/api/classat_1_1_tensor.html#_CPPv4NK2at6Tensor4dataEv)) | +| `torch.Tensor.output_nr` | [`torch::Tensor::output_nr`](https://pytorch.org/cppdocs/api/classat_1_1_tensor.html#_CPPv4NK2at6Tensor9output_nrEv)) | +| `torch.Tensor.is_leaf` | [`torch::Tensor::is_leaf`](https://pytorch.org/cppdocs/api/classat_1_1_tensor.html#_CPPv4NK2at6Tensor7is_leafEv)) | + +翻译后,您的大多数 Python Autograd 代码都应仅在 C++ 中工作。 如果不是这种情况,请在 [GitHub ISSUE](https://github.com/pytorch/pytorch/issues) 中提交错误报告,我们将尽快对其进行修复。 + +## 总结 + +现在,您应该对 PyTorch 的 C++ autograd API 有了一个很好的了解。 [您可以在此处找到本说明中显示的代码示例](https://github.com/pytorch/examples/tree/master/cpp/autograd)。 与往常一样,如果您遇到任何问题或疑问,可以使用我们的[论坛](https://discuss.pytorch.org/)或 [GitHub ISSUE](https://github.com/pytorch/pytorch/issues) 进行联系。 \ No newline at end of file diff --git a/pytorch/官方教程/50.md b/pytorch/官方教程/50.md new file mode 100644 index 00000000..8328c266 --- /dev/null +++ b/pytorch/官方教程/50.md @@ -0,0 +1,244 @@ +# 在 C++ 中注册调度运算符 + +> 原文: + +调度器是 PyTorch 的内部组件,负责确定调用`torch::add`之类的函数时应实际运行哪些代码。 这是不平凡的,因为 PyTorch 操作需要处理很多交叉关注点,这些关注点“层叠”在另一个之上。 以下是其处理的一些示例: + +* 根据输入张量的设备,在运算符的 CPU 和 CUDA 实现之间切换。 +* 在运算符的自动微分和后端实现之间切换,这取决于是否需要自动微分处理。 +* 必要时应用自动广播来实现自动混合精度。 +* 当运算符在`vmap`调用下运行时,应用批量规则。 +* 如果要跟踪导出的模型,则跟踪操作的执行。 + +如果在[自定义运算符代码](torch_script_custom_ops)中发现自己手动编写了`if`语句来处理这些情况,则调度器 API 可以帮助组织代码。 (相反,如果您的自定义运算符非常简单并且仅用于 CPU 推断,则可能不需要使用调度器,只需使用基本 API。) + +在本教程中,我们将描述如何构造自定义运算符注册以使用调度器来组织各种组件。 我们假设您熟悉如何[注册运算符](torch_script_custom_ops)以及如何编写[自定义自动微分函数](cpp_autograd)。 + +## 定义模式和后端实现 + +调度器背后的一般原理是将一个运算符的实现分为多个内核,每个内核都为特定的*调度键*实现功能; 例如,CPU,CUDA 或 Autograd。 调度器在您调用运算符时确定最高优先级的调度键是什么(这通过查看张量参数和某些线程本地状态来完成),并将控制权传递给内核以使用该调度键。 最终结果是,当您调用运算符时,我们首先执行 Autograd 内核,然后根据传入的张量的设备类型将其重新分配到 CPU 或 CUDA 内核。 + +让我们看一下实现这一目标所涉及的各个部分。 首先,我们必须为所讨论的运算符定义架构。 与简单的`pybind11`样式的运算符注册不同,我们目前实际上并未提供运算符的实现; 我们只提供一个模式字符串,指定所有其他内核将遵守的运算符的类型签名: + +```py +TORCH_LIBRARY(myops, m) { + m.def("myadd(Tensor self, Tensor other) -> Tensor"); +} + +``` + +接下来,我们需要实际提供此运算符的一些实现。 具体来说,这是一个非常简单的 CPU 实现: + +```py +Tensor myadd_cpu(const Tensor& self_, const Tensor& other_) { + TORCH_CHECK(self_.sizes() == other_.sizes()); + TORCH_INTERNAL_ASSERT(self_.device().type() == DeviceType::CPU); + TORCH_INTERNAL_ASSERT(other_.device().type() == DeviceType::CPU); + Tensor self = self_.contiguous(); + Tensor other = other_.contiguous(); + Tensor result = torch::empty(self.sizes(), self.options()); + const float* self_ptr = self.data_ptr(); + const float* other_ptr = other.data_ptr(); + float* result_ptr = result.data_ptr(); + for (int64_t i = 0; i < result.numel(); i++) { + result_ptr[i] = self_ptr[i] + other_ptr[i]; + } + return result; +} + +``` + +我们想将此函数注册为`myops::myadd`的实现。 但是,简单的注册方法(`def("myadd", myadd_cpu)`)将注册内核以在所有情况下都可以运行,即使张量不是 CPU 张量! (在内部,我们将它们称为“全部捕获”内核,因为它们捕获所有情况。)为确保仅针对 CPU 张量运行`myadd_cpu`,我们可以使用`TORCH_LIBRARY_IMPL`宏: + +```py +TORCH_LIBRARY_IMPL(myops, CPU, m) { + m.impl("myadd", myadd_cpu); +} + +``` + +通过`TORCH_LIBRARY_IMPL`,我们可以在特定的调度键(在本例中为 CPU)上为运算符注册实现。 每次对`impl`的调用都会将 CPU 内核与相应的运算符(我们先前在`TORCH_LIBRARY`块中定义)相关联。 如果我们还有 CUDA 实现`myadd_cuda`,我们可以将其注册在单独的`TORCH_LIBRARY_IMPL`块中: + +```py +TORCH_LIBRARY_IMPL(myops, CUDA, m) { + m.impl("myadd", myadd_cuda); +} + +``` + +这些注册可以跨文件甚至跨库边界拆分; 因此,例如,您可以将这两个`TORCH_LIBRARY_IMPL`块编译为单独的`myops_cpu`和`myops_cuda`动态库。 一般来说,您的注册结构如下所示: + +1. 单个`TORCH_LIBRARY`在集中位置列出名称空间中的每个自定义运算符。 +2. 每个调度键的`TORCH_LIBRARY_IMPL`,用于注册该键的实现(例如,CPU 或 CUDA)。 如果愿意,可以按每个运算符将`TORCH_LIBRARY_IMPL`块进一步细分为一个块。 如果每个运算符的实现都有一个单独的文件,但是又不想在标头中显示运算符,这将很方便。 您只需将注册内容放入定义您的运算符的 cpp 文件中。 + +注意 + +您知道吗,您还可以为 PyTorch 中的现有核心运算符编写`TORCH_LIBRARY_IMPL`块? 这就是实现 XLA 对 PyTorch 的支持的方式:`torch_xla`库包含一个`TORCH_LIBRARY_IMPL`,该库为 XLA 调度键上的所有基本运算符提供实现。 + +## 添加 Autograd 支持 + +至此,我们有了一个同时具有 CPU 和 CUDA 实现的运算符。 我们如何为它添加 Autograd 支持? 您可能会猜到,我们将注册一个 Autograd 内核(类似于[自定义 Autograd 函数](cpp_autograd)教程中描述的内容)! 但是,有一个变数:与 CPU 和 CUDA 内核不同,Autograd 内核需要*重新分发*:它需要回调调度器才能到达最终的 CPU 和 CUDA 实现。 + +因此,在编写 Autograd 内核之前,让我们编写一个*调度函数*,该函数调用调度器以为您的运算符找到合适的内核。 该函数构成了供您的运算符使用的公共 C++ API,实际上,PyTorch C++ API 中的所有张量函数都在后台完全以相同的方式调用了调度器。 调度函数如下所示: + +```py +Tensor myadd(const Tensor& self, const Tensor& other) { + static auto op = torch::Dispatcher::singleton() + .findSchemaOrThrow("myops::myadd", "") + .typed(); + return op.call(self, other); +} + +``` + +让我们分解一下: + +* 在第一行中,我们从调度器中查找与要调度到的运算符相对应的类型化运算符句柄。 `findSchemaOrThrow`具有两个参数:运算符的(名称空间限定)名称和运算符的重载名称(通常只是空字符串)。 `typed`将动态类型的句柄转换为静态类型的句柄(进行运行时测试以确保您提供了正确的 C++ 类型),以便我们可以对其进行常规的 C++ 调用。 我们将其传递给`decltype(myadd)`,因为调度函数的类型与注册到调度器的基础内核的类型相同。 + + 为了提高性能,此计算是在静态变量中完成的,因此我们只需要进行一次(慢速)查找。 如果键入了要调用的运算符的名称,则第一次调用此函数时,此查找将出错。 + +* 在第二行中,我们只需将所有参数传递到调度函数中,就可以简单地`call`运算符句柄。 这实际上将调用调度器,最终控制权将转移到适合此调用的任何内核。 + +有了分发函数,我们现在可以编写 Autograd 内核: + +```py +class MyAddFunction : public torch::autograd::Function { + public: + static Tensor forward( + AutogradContext *ctx, torch::Tensor self, torch::Tensor other) { + at::AutoNonVariableTypeMode g; + return myadd(self, other); + } + + static tensor_list backward(AutogradContext *ctx, tensor_list grad_outputs) { + auto grad_output = grad_outputs[0]; + return {grad_output, grad_output}; + } +}; + +Tensor myadd_autograd(const Tensor& self, const Tensor& other) { + return MyAddFunction::apply(self, other)[0]; +} + +``` + +使用`torch::autograd::Function`正常编写 Autograd 函数,除了代替直接在`forward()`中编写实现,我们: + +1. 使用`at::AutoNonVariableTypeMode` RAII 保护器关闭 Autograd 处理,然后 +2. 调用调度函数`myadd`以回调调度器。 + +如果没有(1),您的调用将无限循环(并且栈溢出),因为`myadd`将使您返回此函数(因为最高优先级分配键仍将是自动微分的。)对于(1),自动微分从一组正在考虑的调度键中排除,我们将转到下一个处理器,即 CPU 和 CUDA。 + +现在,我们可以按照注册 CPU/CUDA 函数的相同方式注册此函数: + +```py +TORCH_LIBRARY_IMPL(myops, Autograd, m) { + m.impl("myadd", myadd_autograd); +} + +``` + +## 超越 Autograd + +从某种意义上说,调度员并没有做太多事情:它所做的只是实现一种美化的`if`语句,其方法如下: + +```py +class MyAddFunction : ... { +public: + static Tensor forward( + AutogradContext *ctx, torch::Tensor self, torch::Tensor other) { + + if (self.device().type() == DeviceType::CPU) { + return add_cpu(self, other); + } else if (self.device().type() == DeviceType::CUDA) { + return add_cuda(self, other); + } else { + TORCH_CHECK(0, "Unsupported device ", self.device().type()); + } + } + ... +} + +``` + +那么为什么要使用调度器呢? 有几个原因: + +1. 它是分散的。 您可以组装运算符的所有部分(CPU,CUDA,Autograd),而不必编写引用所有元素的集中式`if`语句。 重要的是,第三方可以注册其他方面的额外实现,而不必修补运算符的原始定义。 +2. 它比 CPU,CUDA 和 Autograd 支持更多的调度键。 您可以在`c10/core/DispatchKey.h`中查看 PyTorch 中当前实现的调度键的完整列表。 这些调度键为运算符实现了多种可选功能,如果您决定希望自定义运算符支持该功能,则只需为相应的键注册内核即可。 +3. 调度器实现对盒装后备函数的支持,后者是可以一次实现并应用于系统中所有运算符的函数。 盒装后备可用于提供调度键的默认行为。 如果您使用调度器来实现您的运算符,那么您还可以选择所有这些操作的备用。 + +这是一些特定的调度键,您可能需要为其定义一个运算符。 + +### Autocast + +Autocast 调度键实现对[自动混合精度(AMP)](https://pytorch.org/docs/stable/amp.html)的支持。 自动广播包装器内核通常会在运行操作之前将传入的`float16`或`float32` CUDA 张量转换为某些首选精度。 例如,浮点 CUDA 张量上的积和卷积通常运行得更快,并且在`float16`中使用较少的内存,而不会影响收敛。 自动广播包装器仅在[启用自动广播的上下文](https://pytorch.org/docs/stable/amp.html#torch.cuda.amp.autocast)中有效。 + +这是假设的自定义`Matmul`的自动广播包装器及其注册信息: + +```py +// Autocast-specific helper functions +#include + +Tensor mymatmul_autocast(const Tensor& self, const Tensor& other) { + c10::impl::ExcludeDispatchKeyGuard no_autocast(c10::DispatchKey::Autocast); + return mymatmul(at::autocast::cached_cast(at::kHalf, self), + at::autocast::cached_cast(at::kHalf, other)); +} + +TORCH_LIBRARY_IMPL(myops, Autocast, m) { + m.impl("mymatmul", mymatmul_autocast); +} + +``` + +如果`tensor`为 CUDA 和`float32`,则`cached_cast(kHalf, tensor)`将`tensor`强制转换为`float16`,否则,`tensor`保持不变(参见[资格策略](https://pytorch.org/docs/stable/amp.html#op-eligibility)对于本地自动播报的操作)。 这样可以确保网络是否在`float16`和`float32` CUDA 张量的任何混合形式上调用`mymatmul`,`mymatmul`在`float16`中运行。 同时,使用非 CUDA,整数类型或`float64`输入的对`mymatmul`的调用不受影响。 建议使用`cached_cast`在您自己的自动广播包装程序中遵循本机资格策略,但不是必需的。 例如,如果要对所有输入类型强制执行`float16`,则可以使用`return mymatmul(self.half(), other.half());`而不是使用`cached_cast`。 + +请注意,就像我们的 Autograd 内核一样,我们在重新分配之前从分配中排除`Autocast`键。 + +默认情况下,如果未提供自动广播包装器,我们将直接进入常规的运算符实现(不进行自动广播)。 (在此示例中,我们没有使用`myadd`,因为逐点加法不需要自动广播,因此应该会失败。) + +什么时候应该注册自动广播包装器? 不幸的是,对于运算符的首选精度并没有严格的规定。 通过查看[运算符列表](https://pytorch.org/docs/master/amp.html#op-specific-behavior),您可以了解某些本机运算符的首选精度。 一般指导: + +* 进行减少操作的操作可能应该在`float32`中执行, +* 在幕后进行卷积或宝石运算的任何操作都应在`float16`中执行,并且 +* 具有多个浮点张量输入的其他运算符应将它们标准化为通用精度(除非实现支持具有不同精度的输入)。 + +如果您的自定义操作属于第三类,则`promote_type`模板有助于找出输入张量中存在的最宽浮点类型,这是执行类型的最安全选择: + +```py +#include + +Tensor my_multiple_input_op_autocast(const Tensor& t0, const Tensor& t1) { + c10::impl::ExcludeDispatchKeyGuard no_autocast(c10::DispatchKey::Autocast); + // The required at::kHalf argument is an optimistic initial guess. + auto exec_type = at::autocast::promote_type(at::kHalf, t0, t1); + return my_multiple_input_op(at::autocast::cached_cast(exec_type, t0), + at::autocast::cached_cast(exec_type, t1)); +} + +``` + +如果您的自定义操作[已启用 Autograd](#autograd-support),则只需编写和注册自动广播包装器,其名称与注册自动梯度包装器的名称相同。 例如,如果您想为 Autograd 部分中显示的`myadd`函数使用自动广播包装,那么您所需要做的就是 + +```py +Tensor myadd_autocast(const Tensor& self, const Tensor& other) { + c10::impl::ExcludeDispatchKeyGuard no_autocast(c10::DispatchKey::Autocast); + return myadd(at::autocast::cached_cast(, self), + at::autocast::cached_cast(, other)); +} + +TORCH_LIBRARY_IMPL(myops, Autocast, m) { + m.impl("myadd", myadd_autocast); +} + +``` + +没有单独的体操可使后向方法自动广播兼容。 但是,在自定义 Autograd 函数中定义的向后方法将以与正向方法的自动广播集相同的`dtype`运行,因此您应该选择既适合于正向方法又适合于向后方法的``。 + +### 批量 + +批量张量允许您按示例方式编写代码,然后在`vmap`调用下运行时自动对其进行批量。 当前正在开发用于编写批量规则的 API,但是一旦稳定该 API,就可以通过在 Batched 调度键处注册内核来为运算符添加对`vmap`的支持。 + +### 追踪器 + +追踪器调度键实现了对在运行`torch.jit.trace`时将运算符调用记录到跟踪中的支持。 我们打算提供一个盒装后备,它将实现对任意操作的跟踪,请参阅 [ISSUE#41478](https://github.com/pytorch/pytorch/issues/41478) 以跟踪进度。 \ No newline at end of file diff --git a/pytorch/官方教程/51.md b/pytorch/官方教程/51.md new file mode 100644 index 00000000..e47eefb2 --- /dev/null +++ b/pytorch/官方教程/51.md @@ -0,0 +1 @@ +# 模型优化 \ No newline at end of file diff --git a/pytorch/官方教程/52.md b/pytorch/官方教程/52.md new file mode 100644 index 00000000..0c8c7991 --- /dev/null +++ b/pytorch/官方教程/52.md @@ -0,0 +1,285 @@ +# 分析您的 PyTorch 模块 + +> 原文: + +**作者:** [Suraj Subramanian](https://github.com/suraj813) + +PyTorch 包含一个探查器 API,可用于识别代码中各种 PyTorch 操作的时间和内存成本。 Profiler 可以轻松集成到您的代码中,结果可以打印为表格或在 JSON 跟踪文件中显示。 + +注意 + +Profiler 支持多线程模型。 Profiler 与该操作在同一线程中运行,但它还将对可能在另一个线程中运行的子运算符进行概要分析。 同时运行的探查器的作用域将限制在其自己的线程中,以防止结果混淆。 + +转到[此秘籍](https://pytorch.org/tutorials/recipes/recipes/profiler.html),可以更快地了解 Profiler API 的用法。 + +* * * + +```py +import torch +import numpy as np +from torch import nn +import torch.autograd.profiler as profiler + +``` + +## 使用 Profiler 的性能调试 + +Profiler 有助于识别模型中的性能瓶颈。 在此示例中,我们构建了一个自定义模块,该模块执行两个子任务: + +* 输入的线性变换,以及 +* 使用转换结果来获取遮罩张量上的索引。 + +我们使用`profiler.record_function("label")`将每个子任务的代码包装在单独的带标签的上下文管理器中。 在事件探查器输出中,子任务中所有操作的综合性能指标将显示在其相应的标签下。 + +请注意,使用 Profiler 会产生一些开销,并且最好仅用于调查代码。 如果要对运行时进行基准测试,请记住将其删除。 + +```py +class MyModule(nn.Module): + def __init__(self, in_features: int, out_features: int, bias: bool = True): + super(MyModule, self).__init__() + self.linear = nn.Linear(in_features, out_features, bias) + + def forward(self, input, mask): + with profiler.record_function("LINEAR PASS"): + out = self.linear(input) + + with profiler.record_function("MASK INDICES"): + threshold = out.sum(axis=1).mean().item() + hi_idx = np.argwhere(mask.cpu().numpy() > threshold) + hi_idx = torch.from_numpy(hi_idx).cuda() + + return out, hi_idx + +``` + +## 分析正向传播 + +我们初始化随机输入和蒙版张量以及模型。 + +在运行探查器之前,我们需要对 CUDA 进行预热,以确保进行准确的性能基准测试。 我们将模块的正向传播包装在`profiler.profile`上下文管理器中。 `with_stack=True`参数在跟踪中附加操作的文件和行号。 + +警告 + +`with_stack=True`会产生额外的开销,并且更适合于研究代码。 如果要对性能进行基准测试,请记住将其删除。 + +```py +model = MyModule(500, 10).cuda() +input = torch.rand(128, 500).cuda() +mask = torch.rand((500, 500, 500), dtype=torch.double).cuda() + +# warm-up +model(input, mask) + +with profiler.profile(with_stack=True, profile_memory=True) as prof: + out, idx = model(input, mask) + +``` + +## 打印分析器结果 + +最后,我们打印分析器结果。 `profiler.key_averages`通过运算符名称,以及可选地通过输入形状和/或栈跟踪事件来聚合结果。 按输入形状分组有助于识别模型使用哪些张量形状。 + +在这里,我们使用`group_by_stack_n=5`通过操作及其回溯(截断为最近的 5 个事件)聚合运行时,并按事件注册的顺序显示事件。 还可以通过传递`sort_by`参数对表进行排序(有关有效的排序键,请参阅[文档](https://pytorch.org/docs/stable/autograd.html#profiler))。 + +注意 + +在笔记本中运行 Profiler 时,您可能会在栈跟踪中看到`(13): forward`之类的条目,而不是文件名。 这些对应于`(line number): calling-function`。 + +```py +print(prof.key_averages(group_by_stack_n=5).table(sort_by='self_cpu_time_total', row_limit=5)) + +""" +(Some columns are omitted) + +------------- ------------ ------------ ------------ --------------------------------- + Name Self CPU % Self CPU Self CPU Mem Source Location +------------- ------------ ------------ ------------ --------------------------------- + MASK INDICES 87.88% 5.212s -953.67 Mb /mnt/xarfuse/.../torch/au + (10): forward + /mnt/xarfuse/.../torch/nn + (9): + /mnt/xarfuse/.../IPython/ + + aten::copy_ 12.07% 715.848ms 0 b (12): forward + /mnt/xarfuse/.../torch/nn + (9): + /mnt/xarfuse/.../IPython/ + /mnt/xarfuse/.../IPython/ + + LINEAR PASS 0.01% 350.151us -20 b /mnt/xarfuse/.../torch/au + (7): forward + /mnt/xarfuse/.../torch/nn + (9): + /mnt/xarfuse/.../IPython/ + + aten::addmm 0.00% 293.342us 0 b /mnt/xarfuse/.../torch/nn + /mnt/xarfuse/.../torch/nn + /mnt/xarfuse/.../torch/nn + (8): forward + /mnt/xarfuse/.../torch/nn + + aten::mean 0.00% 235.095us 0 b (11): forward + /mnt/xarfuse/.../torch/nn + (9): + /mnt/xarfuse/.../IPython/ + /mnt/xarfuse/.../IPython/ + +----------------------------- ------------ ---------- ---------------------------------- +Self CPU time total: 5.931s + +""" + +``` + +## 提高内存性能 + +请注意,就内存和时间而言,最昂贵的操作位于`forward (10)`,代表掩码索引中的操作。 让我们尝试先解决内存消耗问题。 我们可以看到第 12 行的`.to()`操作消耗 953.67 Mb。 该操作将`mask`复制到 CPU。 `mask`使用`torch.double`数据类型初始化。 我们可以通过将其转换为`torch.float`来减少内存占用吗? + +```py +model = MyModule(500, 10).cuda() +input = torch.rand(128, 500).cuda() +mask = torch.rand((500, 500, 500), dtype=torch.float).cuda() + +# warm-up +model(input, mask) + +with profiler.profile(with_stack=True, profile_memory=True) as prof: + out, idx = model(input, mask) + +print(prof.key_averages(group_by_stack_n=5).table(sort_by='self_cpu_time_total', row_limit=5)) + +""" +(Some columns are omitted) + +----------------- ------------ ------------ ------------ -------------------------------- + Name Self CPU % Self CPU Self CPU Mem Source Location +----------------- ------------ ------------ ------------ -------------------------------- + MASK INDICES 93.61% 5.006s -476.84 Mb /mnt/xarfuse/.../torch/au + (10): forward + /mnt/xarfuse/ /torch/nn + (9): + /mnt/xarfuse/.../IPython/ + + aten::copy_ 6.34% 338.759ms 0 b (12): forward + /mnt/xarfuse/.../torch/nn + (9): + /mnt/xarfuse/.../IPython/ + /mnt/xarfuse/.../IPython/ + + aten::as_strided 0.01% 281.808us 0 b (11): forward + /mnt/xarfuse/.../torch/nn + (9): + /mnt/xarfuse/.../IPython/ + /mnt/xarfuse/.../IPython/ + + aten::addmm 0.01% 275.721us 0 b /mnt/xarfuse/.../torch/nn + /mnt/xarfuse/.../torch/nn + /mnt/xarfuse/.../torch/nn + (8): forward + /mnt/xarfuse/.../torch/nn + + aten::_local 0.01% 268.650us 0 b (11): forward + _scalar_dense /mnt/xarfuse/.../torch/nn + (9): + /mnt/xarfuse/.../IPython/ + /mnt/xarfuse/.../IPython/ + +----------------- ------------ ------------ ------------ -------------------------------- +Self CPU time total: 5.347s + +""" + +``` + +此操作的 CPU 内存占用量减少了一半。 + +## 提高时间表现 + +虽然所消耗的时间也有所减少,但仍然太高。 原来,将矩阵从 CUDA 复制到 CPU 非常昂贵! `forward (12)`中的`aten::copy_`运算符将`mask`复制到 CPU,以便可以使用 NumPy `argwhere`函数。 `forward(13)`处的`aten::copy_`将数组作为张量复制回 CUDA。 如果我们在这里使用`torch`函数`nonzero()`,则可以消除这两个方面。 + +```py +class MyModule(nn.Module): + def __init__(self, in_features: int, out_features: int, bias: bool = True): + super(MyModule, self).__init__() + self.linear = nn.Linear(in_features, out_features, bias) + + def forward(self, input, mask): + with profiler.record_function("LINEAR PASS"): + out = self.linear(input) + + with profiler.record_function("MASK INDICES"): + threshold = out.sum(axis=1).mean() + hi_idx = (mask > threshold).nonzero(as_tuple=True) + + return out, hi_idx + +model = MyModule(500, 10).cuda() +input = torch.rand(128, 500).cuda() +mask = torch.rand((500, 500, 500), dtype=torch.float).cuda() + +# warm-up +model(input, mask) + +with profiler.profile(with_stack=True, profile_memory=True) as prof: + out, idx = model(input, mask) + +print(prof.key_averages(group_by_stack_n=5).table(sort_by='self_cpu_time_total', row_limit=5)) + +""" +(Some columns are omitted) + +-------------- ------------ ------------ ------------ --------------------------------- + Name Self CPU % Self CPU Self CPU Mem Source Location +-------------- ------------ ------------ ------------ --------------------------------- + aten::gt 57.17% 129.089ms 0 b (12): forward + /mnt/xarfuse/.../torch/nn + (25): + /mnt/xarfuse/.../IPython/ + /mnt/xarfuse/.../IPython/ + + aten::nonzero 37.38% 84.402ms 0 b (12): forward + /mnt/xarfuse/.../torch/nn + (25): + /mnt/xarfuse/.../IPython/ + /mnt/xarfuse/.../IPython/ + + INDEX SCORE 3.32% 7.491ms -119.21 Mb /mnt/xarfuse/.../torch/au + (10): forward + /mnt/xarfuse/.../torch/nn + (25): + /mnt/xarfuse/.../IPython/ + +aten::as_strided 0.20% 441.587us 0 b (12): forward + /mnt/xarfuse/.../torch/nn + (25): + /mnt/xarfuse/.../IPython/ + /mnt/xarfuse/.../IPython/ + + aten::nonzero + _numpy 0.18% 395.602us 0 b (12): forward + /mnt/xarfuse/.../torch/nn + (25): + /mnt/xarfuse/.../IPython/ + /mnt/xarfuse/.../IPython/ +-------------- ------------ ------------ ------------ --------------------------------- +Self CPU time total: 225.801ms + +""" + +``` + +## 进一步阅读 + +我们已经看到了 Profiler 如何用于调查 PyTorch 模型中的时间和内存瓶颈。 在此处阅读有关 Profiler 的更多信息: + +* [事件探查器使用秘籍](https://pytorch.org/tutorials/recipes/recipes/profiler.html) +* [分析基于 RPC 的工作负载](https://pytorch.org/tutorials/recipes/distributed_rpc_profiling.html) +* [Profiler API 文档](https://pytorch.org/docs/stable/autograd.html?highlight=profiler#profiler) + +**脚本的总运行时间**:(0 分钟 0.000 秒) + +[下载 Python 源码:`profiler.py`](../_downloads/390e82110dc76e71b26225b3f9020e14/profiler.py) + +[下载 Jupyter 笔记本:`profiler.ipynb`](../_downloads/28071a0f69f5106129ad8a68a47af061/profiler.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/53.md b/pytorch/官方教程/53.md new file mode 100644 index 00000000..b3c631b5 --- /dev/null +++ b/pytorch/官方教程/53.md @@ -0,0 +1,1711 @@ +# 使用 Ray Tune 的超参数调整 + +> 原文: + +超参数调整可以使平均模型与高精度模型有所不同。 通常,选择不同的学习率或更改网络层大小等简单的事情可能会对模型表现产生巨大影响。 + +幸运的是,有一些工具可以帮助您找到最佳的参数组合。 [Ray Tune](https://docs.ray.io/en/latest/tune.html) 是用于分布式超参数调整的行业标准工具。 Ray Tune 包含最新的超参数搜索算法,与 TensorBoard 和其他分析库集成,并通过 [Ray 的分布式机器学习引擎](https://ray.io/)本地支持分布式训练。 + +在本教程中,我们将向您展示如何将 Ray Tune 集成到 PyTorch 训练工作流程中。 我们将扩展 PyTorch 文档的[本教程](https://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html),以训练 CIFAR10 图像分类器。 + +如您所见,我们只需要添加一些细微的修改即可。 特别是,我们需要 + +1. 在函数中包装数据加载和训练, +2. 使一些网络参数可配置, +3. 添加检查点(可选), +4. 并定义用于模型调整的搜索空间 + +要运行本教程,请确保已安装以下包: + +* `ray[tune]`:分布式超参数调整库 +* `torchvision`:用于数据转换器 + +## 设置/导入 + +让我们从导入开始: + +```py +from functools import partial +import numpy as np +import os +import torch +import torch.nn as nn +import torch.nn.functional as F +import torch.optim as optim +from torch.utils.data import random_split +import torchvision +import torchvision.transforms as transforms +from ray import tune +from ray.tune import CLIReporter +from ray.tune.schedulers import ASHAScheduler + +``` + +建立 PyTorch 模型需要大多数导入产品。 Ray Tune 仅最后三个导入。 + +## 数据加载器 + +我们将数据加载器包装在它们自己的函数中,并传递一个全局数据目录。 这样,我们可以在不同的试验之间共享数据目录。 + +```py +def load_data(data_dir="./data"): + transform = transforms.Compose([ + transforms.ToTensor(), + transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) + ]) + + trainset = torchvision.datasets.CIFAR10( + root=data_dir, train=True, download=True, transform=transform) + + testset = torchvision.datasets.CIFAR10( + root=data_dir, train=False, download=True, transform=transform) + + return trainset, testset + +``` + +## 可配置的神经网络 + +我们只能调整那些可配置的参数。 在此示例中,我们可以指定全连接层的层大小: + +```py +class Net(nn.Module): + def __init__(self, l1=120, l2=84): + super(Net, self).__init__() + self.conv1 = nn.Conv2d(3, 6, 5) + self.pool = nn.MaxPool2d(2, 2) + self.conv2 = nn.Conv2d(6, 16, 5) + self.fc1 = nn.Linear(16 * 5 * 5, l1) + self.fc2 = nn.Linear(l1, l2) + self.fc3 = nn.Linear(l2, 10) + + def forward(self, x): + x = self.pool(F.relu(self.conv1(x))) + x = self.pool(F.relu(self.conv2(x))) + x = x.view(-1, 16 * 5 * 5) + x = F.relu(self.fc1(x)) + x = F.relu(self.fc2(x)) + x = self.fc3(x) + return x + +``` + +## 训练函数 + +现在变得有趣了,因为我们对 [PyTorch 文档中的示例](https://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html)进行了一些更改。 + +我们将训练脚本包装在函数`train_cifar(config, checkpoint_dir=None, data_dir=None)`中。 可以猜到,`config`参数将接收我们要训练的超参数。 `checkpoint_dir`参数用于还原检查点。 `data_dir`指定了我们加载和存储数据的目录,因此多次运行可以共享同一数据源。 + +```py +net = Net(config["l1"], config["l2"]) + +if checkpoint_dir: + model_state, optimizer_state = torch.load( + os.path.join(checkpoint_dir, "checkpoint")) + net.load_state_dict(model_state) + optimizer.load_state_dict(optimizer_state) + +``` + +优化器的学习率也可以配置: + +```py +optimizer = optim.SGD(net.parameters(), lr=config["lr"], momentum=0.9) + +``` + +我们还将训练数据分为训练和验证子集。 因此,我们训练了 80% 的数据,并计算了其余 20% 的验证损失。 我们遍历训练和测试集的批量大小也是可配置的。 + +### 通过`DataParallel`添加(多)GPU 支持 + +图像分类主要受益于 GPU。 幸运的是,我们可以继续在 Ray Tune 中使用 PyTorch 的抽象。 因此,我们可以将模型包装在`nn.DataParallel`中,以支持在多个 GPU 上进行数据并行训练: + +```py +device = "cpu" +if torch.cuda.is_available(): + device = "cuda:0" + if torch.cuda.device_count() > 1: + net = nn.DataParallel(net) +net.to(device) + +``` + +通过使用`device`变量,我们可以确保在没有 GPU 的情况下训练也能正常进行。 PyTorch 要求我们将数据显式发送到 GPU 内存,如下所示: + +```py +for i, data in enumerate(trainloader, 0): + inputs, labels = data + inputs, labels = inputs.to(device), labels.to(device) + +``` + +该代码现在支持在 CPU,单个 GPU 和多个 GPU 上进行训练。 值得注意的是,Ray 还支持[分数 GPU](https://docs.ray.io/en/master/using-ray-with-gpus.html#fractional-gpus) ,因此我们可以在试验之间共享 GPU,只要模型仍适合 GPU 内存即可。 我们稍后再讲。 + +### 与 Ray Tune 交流 + +最有趣的部分是与 Ray Tune 的交流: + +```py +with tune.checkpoint_dir(epoch) as checkpoint_dir: + path = os.path.join(checkpoint_dir, "checkpoint") + torch.save((net.state_dict(), optimizer.state_dict()), path) + +tune.report(loss=(val_loss / val_steps), accuracy=correct / total) + +``` + +在这里,我们首先保存一个检查点,然后将一些指标报告给 Ray Tune。 具体来说,我们将验证损失和准确率发送回 Ray Tune。 然后,Ray Tune 可以使用这些指标来决定哪种超参数配置可以带来最佳结果。 这些指标还可用于尽早停止效果不佳的试验,以避免浪费资源进行试验。 + +保存检查点是可选的,但是,如果我们想使用高级调度器,例如[基于总体的训练](https://docs.ray.io/en/master/tune/tutorials/tune-advanced-tutorial.html),则有必要。 另外,通过保存检查点,我们可以稍后加载经过训练的模型并在测试集上对其进行验证。 + +### 完整的训练函数 + +完整的代码示例如下所示: + +```py +def train_cifar(config, checkpoint_dir=None, data_dir=None): + net = Net(config["l1"], config["l2"]) + + device = "cpu" + if torch.cuda.is_available(): + device = "cuda:0" + if torch.cuda.device_count() > 1: + net = nn.DataParallel(net) + net.to(device) + + criterion = nn.CrossEntropyLoss() + optimizer = optim.SGD(net.parameters(), lr=config["lr"], momentum=0.9) + + if checkpoint_dir: + model_state, optimizer_state = torch.load( + os.path.join(checkpoint_dir, "checkpoint")) + net.load_state_dict(model_state) + optimizer.load_state_dict(optimizer_state) + + trainset, testset = load_data(data_dir) + + test_abs = int(len(trainset) * 0.8) + train_subset, val_subset = random_split( + trainset, [test_abs, len(trainset) - test_abs]) + + trainloader = torch.utils.data.DataLoader( + train_subset, + batch_size=int(config["batch_size"]), + shuffle=True, + num_workers=8) + valloader = torch.utils.data.DataLoader( + val_subset, + batch_size=int(config["batch_size"]), + shuffle=True, + num_workers=8) + + for epoch in range(10): # loop over the dataset multiple times + running_loss = 0.0 + epoch_steps = 0 + for i, data in enumerate(trainloader, 0): + # get the inputs; data is a list of [inputs, labels] + inputs, labels = data + inputs, labels = inputs.to(device), labels.to(device) + + # zero the parameter gradients + optimizer.zero_grad() + + # forward + backward + optimize + outputs = net(inputs) + loss = criterion(outputs, labels) + loss.backward() + optimizer.step() + + # print statistics + running_loss += loss.item() + epoch_steps += 1 + if i % 2000 == 1999: # print every 2000 mini-batches + print("[%d, %5d] loss: %.3f" % (epoch + 1, i + 1, + running_loss / epoch_steps)) + running_loss = 0.0 + + # Validation loss + val_loss = 0.0 + val_steps = 0 + total = 0 + correct = 0 + for i, data in enumerate(valloader, 0): + with torch.no_grad(): + inputs, labels = data + inputs, labels = inputs.to(device), labels.to(device) + + outputs = net(inputs) + _, predicted = torch.max(outputs.data, 1) + total += labels.size(0) + correct += (predicted == labels).sum().item() + + loss = criterion(outputs, labels) + val_loss += loss.cpu().numpy() + val_steps += 1 + + with tune.checkpoint_dir(epoch) as checkpoint_dir: + path = os.path.join(checkpoint_dir, "checkpoint") + torch.save((net.state_dict(), optimizer.state_dict()), path) + + tune.report(loss=(val_loss / val_steps), accuracy=correct / total) + print("Finished Training") + +``` + +如您所见,大多数代码直接来自原始示例。 + +## 测试集准确率 + +通常,机器学习模型的表现是在保持测试集上使用尚未用于训练模型的数据进行测试的。 我们还将其包装在一个函数中: + +```py +def test_accuracy(net, device="cpu"): + trainset, testset = load_data() + + testloader = torch.utils.data.DataLoader( + testset, batch_size=4, shuffle=False, num_workers=2) + + correct = 0 + total = 0 + with torch.no_grad(): + for data in testloader: + images, labels = data + images, labels = images.to(device), labels.to(device) + outputs = net(images) + _, predicted = torch.max(outputs.data, 1) + total += labels.size(0) + correct += (predicted == labels).sum().item() + + return correct / total + +``` + +该函数还需要一个`device`参数,因此我们可以在 GPU 上进行测试集验证。 + +## 配置搜索空间 + +最后,我们需要定义 Ray Tune 的搜索空间。 这是一个例子: + +```py +config = { + "l1": tune.sample_from(lambda _: 2**np.random.randint(2, 9)), + "l2": tune.sample_from(lambda _: 2**np.random.randint(2, 9)), + "lr": tune.loguniform(1e-4, 1e-1), + "batch_size": tune.choice([2, 4, 8, 16]) +} + +``` + +`tune.sample_from()`函数使您可以定义自己的采样方法以获得超参数。 在此示例中,`l1`和`l2`参数应为 4 到 256 之间的 2 的幂,因此应为 4、8、16、32、64、128 或 256。`lr`(学习率)应在 0.0001 和 0.1 之间均匀采样。 最后,批量大小可以在 2、4、8 和 16 之间选择。 + +现在,在每次试用中,Ray Tune 都会从这些搜索空间中随机抽取参数组合。 然后它将并行训练许多模型,并在其中找到表现最佳的模型。 我们还使用`ASHAScheduler`,它将尽早终止效果不佳的测试。 + +我们用`functools.partial`包装`train_cifar`函数以设置常量`data_dir`参数。 我们还可以告诉 Ray Tune 每个审判应提供哪些资源: + +```py +gpus_per_trial = 2 +# ... +result = tune.run( + partial(train_cifar, data_dir=data_dir), + resources_per_trial={"cpu": 8, "gpu": gpus_per_trial}, + config=config, + num_samples=num_samples, + scheduler=scheduler, + progress_reporter=reporter, + checkpoint_at_end=True) + +``` + +您可以指定 CPU 的数量,例如增加 PyTorch `DataLoader`实例的`num_workers`。 在每次试用中,选定数量的 GPU 对 PyTorch 都是可见的。 试用版无法访问未要求使用 GPU 的 GPU,因此您不必担心使用同一组资源进行两次试用。 + +在这里,我们还可以指定分数 GPU,因此`gpus_per_trial=0.5`之类的东西完全有效。 然后,试用版将彼此共享 GPU。 您只需要确保模型仍然适合 GPU 内存即可。 + +训练完模型后,我们将找到表现最好的模型,并从检查点文件中加载训练后的网络。 然后,我们获得测试仪的准确率,并通过打印报告一切。 + +完整的`main`函数如下: + +```py +def main(num_samples=10, max_num_epochs=10, gpus_per_trial=2): + data_dir = os.path.abspath("./data") + load_data(data_dir) + config = { + "l1": tune.sample_from(lambda _: 2 ** np.random.randint(2, 9)), + "l2": tune.sample_from(lambda _: 2 ** np.random.randint(2, 9)), + "lr": tune.loguniform(1e-4, 1e-1), + "batch_size": tune.choice([2, 4, 8, 16]) + } + scheduler = ASHAScheduler( + metric="loss", + mode="min", + max_t=max_num_epochs, + grace_period=1, + reduction_factor=2) + reporter = CLIReporter( + # parameter_columns=["l1", "l2", "lr", "batch_size"], + metric_columns=["loss", "accuracy", "training_iteration"]) + result = tune.run( + partial(train_cifar, data_dir=data_dir), + resources_per_trial={"cpu": 2, "gpu": gpus_per_trial}, + config=config, + num_samples=num_samples, + scheduler=scheduler, + progress_reporter=reporter) + + best_trial = result.get_best_trial("loss", "min", "last") + print("Best trial config: {}".format(best_trial.config)) + print("Best trial final validation loss: {}".format( + best_trial.last_result["loss"])) + print("Best trial final validation accuracy: {}".format( + best_trial.last_result["accuracy"])) + + best_trained_model = Net(best_trial.config["l1"], best_trial.config["l2"]) + device = "cpu" + if torch.cuda.is_available(): + device = "cuda:0" + if gpus_per_trial > 1: + best_trained_model = nn.DataParallel(best_trained_model) + best_trained_model.to(device) + + best_checkpoint_dir = best_trial.checkpoint.value + model_state, optimizer_state = torch.load(os.path.join( + best_checkpoint_dir, "checkpoint")) + best_trained_model.load_state_dict(model_state) + + test_acc = test_accuracy(best_trained_model, device) + print("Best trial test set accuracy: {}".format(test_acc)) + +if __name__ == "__main__": + # You can change the number of GPUs per trial here: + main(num_samples=10, max_num_epochs=10, gpus_per_trial=0) + +``` + +出: + +```py +Downloading https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to /var/lib/jenkins/workspace/beginner_source/data/cifar-10-python.tar.gz +Extracting /var/lib/jenkins/workspace/beginner_source/data/cifar-10-python.tar.gz to /var/lib/jenkins/workspace/beginner_source/data +Files already downloaded and verified +== Status == +Memory usage on this node: 4.0/240.1 GiB +Using AsyncHyperBand: num_stopped=0 +Bracket: Iter 8.000: None | Iter 4.000: None | Iter 2.000: None | Iter 1.000: None +Resources requested: 2/32 CPUs, 0/2 GPUs, 0.0/157.71 GiB heap, 0.0/49.37 GiB objects +Result logdir: /var/lib/jenkins/ray_results/DEFAULT_2021-01-05_20-23-08 +Number of trials: 1/10 (1 RUNNING) ++---------------------+----------+-------+--------------+------+------+-------------+ +| Trial name | status | loc | batch_size | l1 | l2 | lr | +|---------------------+----------+-------+--------------+------+------+-------------| +| DEFAULT_d3304_00000 | RUNNING | | 2 | 4 | 16 | 0.000111924 | ++---------------------+----------+-------+--------------+------+------+-------------+ + +[2m[36m(pid=1588)[0m Files already downloaded and verified +[2m[36m(pid=1568)[0m Files already downloaded and verified +[2m[36m(pid=1504)[0m Files already downloaded and verified +[2m[36m(pid=1575)[0m Files already downloaded and verified +[2m[36m(pid=1494)[0m Files already downloaded and verified +[2m[36m(pid=1572)[0m Files already downloaded and verified +[2m[36m(pid=1567)[0m Files already downloaded and verified +[2m[36m(pid=1585)[0m Files already downloaded and verified +[2m[36m(pid=1565)[0m Files already downloaded and verified +[2m[36m(pid=1505)[0m Files already downloaded and verified +[2m[36m(pid=1588)[0m Files already downloaded and verified +[2m[36m(pid=1568)[0m Files already downloaded and verified +[2m[36m(pid=1504)[0m Files already downloaded and verified +[2m[36m(pid=1575)[0m Files already downloaded and verified +[2m[36m(pid=1494)[0m Files already downloaded and verified +[2m[36m(pid=1572)[0m Files already downloaded and verified +[2m[36m(pid=1567)[0m Files already downloaded and verified +[2m[36m(pid=1565)[0m Files already downloaded and verified +[2m[36m(pid=1585)[0m Files already downloaded and verified +[2m[36m(pid=1505)[0m Files already downloaded and verified +[2m[36m(pid=1585)[0m [1, 2000] loss: 2.307 +[2m[36m(pid=1568)[0m [1, 2000] loss: 2.226 +[2m[36m(pid=1565)[0m [1, 2000] loss: 2.141 +[2m[36m(pid=1505)[0m [1, 2000] loss: 2.339 +[2m[36m(pid=1504)[0m [1, 2000] loss: 2.042 +[2m[36m(pid=1572)[0m [1, 2000] loss: 2.288 +[2m[36m(pid=1567)[0m [1, 2000] loss: 2.047 +[2m[36m(pid=1575)[0m [1, 2000] loss: 2.316 +[2m[36m(pid=1494)[0m [1, 2000] loss: 2.322 +[2m[36m(pid=1588)[0m [1, 2000] loss: 2.289 +[2m[36m(pid=1585)[0m [1, 4000] loss: 1.154 +[2m[36m(pid=1505)[0m [1, 4000] loss: 1.170 +[2m[36m(pid=1565)[0m [1, 4000] loss: 0.939 +[2m[36m(pid=1568)[0m [1, 4000] loss: 1.102 +[2m[36m(pid=1504)[0m [1, 4000] loss: 0.916 +[2m[36m(pid=1572)[0m [1, 4000] loss: 1.156 +Result for DEFAULT_d3304_00003: + accuracy: 0.226 + date: 2021-01-05_20-23-37 + done: false + experiment_id: d4b00469893d498ea65a729df202882a + experiment_tag: 3_batch_size=16,l1=32,l2=4,lr=0.0012023 + hostname: 1a844a452371 + iterations_since_restore: 1 + loss: 2.083958268547058 + node_ip: 172.17.0.2 + pid: 1588 + should_checkpoint: true + time_since_restore: 27.169169902801514 + time_this_iter_s: 27.169169902801514 + time_total_s: 27.169169902801514 + timestamp: 1609878217 + timesteps_since_restore: 0 + training_iteration: 1 + trial_id: d3304_00003 + +== Status == +Memory usage on this node: 9.2/240.1 GiB +Using AsyncHyperBand: num_stopped=0 +Bracket: Iter 8.000: None | Iter 4.000: None | Iter 2.000: None | Iter 1.000: -2.083958268547058 +Resources requested: 20/32 CPUs, 0/2 GPUs, 0.0/157.71 GiB heap, 0.0/49.37 GiB objects +Result logdir: /var/lib/jenkins/ray_results/DEFAULT_2021-01-05_20-23-08 +Number of trials: 10/10 (10 RUNNING) ++---------------------+----------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ +| Trial name | status | loc | batch_size | l1 | l2 | lr | loss | accuracy | training_iteration | +|---------------------+----------+-----------------+--------------+------+------+-------------+---------+------------+----------------------| +| DEFAULT_d3304_00000 | RUNNING | | 2 | 4 | 16 | 0.000111924 | | | | +| DEFAULT_d3304_00001 | RUNNING | | 8 | 16 | 32 | 0.077467 | | | | +| DEFAULT_d3304_00002 | RUNNING | | 4 | 8 | 128 | 0.00436986 | | | | +| DEFAULT_d3304_00003 | RUNNING | 172.17.0.2:1588 | 16 | 32 | 4 | 0.00120234 | 2.08396 | 0.226 | 1 | +| DEFAULT_d3304_00004 | RUNNING | | 4 | 16 | 32 | 0.016474 | | | | +| DEFAULT_d3304_00005 | RUNNING | | 4 | 128 | 64 | 0.00757252 | | | | +| DEFAULT_d3304_00006 | RUNNING | | 2 | 64 | 256 | 0.00177236 | | | | +| DEFAULT_d3304_00007 | RUNNING | | 8 | 8 | 8 | 0.000155891 | | | | +| DEFAULT_d3304_00008 | RUNNING | | 2 | 16 | 64 | 0.0310199 | | | | +| DEFAULT_d3304_00009 | RUNNING | | 4 | 4 | 32 | 0.0175239 | | | | ++---------------------+----------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ + +[2m[36m(pid=1567)[0m [1, 4000] loss: 0.943 +[2m[36m(pid=1494)[0m [1, 4000] loss: 1.155 +[2m[36m(pid=1575)[0m [1, 4000] loss: 1.162 +[2m[36m(pid=1585)[0m [1, 6000] loss: 0.768 +[2m[36m(pid=1505)[0m [1, 6000] loss: 0.780 +[2m[36m(pid=1565)[0m [1, 6000] loss: 0.582 +[2m[36m(pid=1504)[0m [1, 6000] loss: 0.587 +[2m[36m(pid=1568)[0m [1, 6000] loss: 0.770 +[2m[36m(pid=1572)[0m [1, 6000] loss: 0.771 +[2m[36m(pid=1567)[0m [1, 6000] loss: 0.615 +Result for DEFAULT_d3304_00007: + accuracy: 0.1011 + date: 2021-01-05_20-23-51 + done: true + experiment_id: 947614a8c2a74533be128b929f363bd1 + experiment_tag: 7_batch_size=8,l1=8,l2=8,lr=0.00015589 + hostname: 1a844a452371 + iterations_since_restore: 1 + loss: 2.3038805620193483 + node_ip: 172.17.0.2 + pid: 1494 + should_checkpoint: true + time_since_restore: 41.69914960861206 + time_this_iter_s: 41.69914960861206 + time_total_s: 41.69914960861206 + timestamp: 1609878231 + timesteps_since_restore: 0 + training_iteration: 1 + trial_id: d3304_00007 + +== Status == +Memory usage on this node: 9.1/240.1 GiB +Using AsyncHyperBand: num_stopped=1 +Bracket: Iter 8.000: None | Iter 4.000: None | Iter 2.000: None | Iter 1.000: -2.193919415283203 +Resources requested: 20/32 CPUs, 0/2 GPUs, 0.0/157.71 GiB heap, 0.0/49.37 GiB objects +Result logdir: /var/lib/jenkins/ray_results/DEFAULT_2021-01-05_20-23-08 +Number of trials: 10/10 (10 RUNNING) ++---------------------+----------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ +| Trial name | status | loc | batch_size | l1 | l2 | lr | loss | accuracy | training_iteration | +|---------------------+----------+-----------------+--------------+------+------+-------------+---------+------------+----------------------| +| DEFAULT_d3304_00000 | RUNNING | | 2 | 4 | 16 | 0.000111924 | | | | +| DEFAULT_d3304_00001 | RUNNING | | 8 | 16 | 32 | 0.077467 | | | | +| DEFAULT_d3304_00002 | RUNNING | | 4 | 8 | 128 | 0.00436986 | | | | +| DEFAULT_d3304_00003 | RUNNING | 172.17.0.2:1588 | 16 | 32 | 4 | 0.00120234 | 2.08396 | 0.226 | 1 | +| DEFAULT_d3304_00004 | RUNNING | | 4 | 16 | 32 | 0.016474 | | | | +| DEFAULT_d3304_00005 | RUNNING | | 4 | 128 | 64 | 0.00757252 | | | | +| DEFAULT_d3304_00006 | RUNNING | | 2 | 64 | 256 | 0.00177236 | | | | +| DEFAULT_d3304_00007 | RUNNING | 172.17.0.2:1494 | 8 | 8 | 8 | 0.000155891 | 2.30388 | 0.1011 | 1 | +| DEFAULT_d3304_00008 | RUNNING | | 2 | 16 | 64 | 0.0310199 | | | | +| DEFAULT_d3304_00009 | RUNNING | | 4 | 4 | 32 | 0.0175239 | | | | ++---------------------+----------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ + +Result for DEFAULT_d3304_00001: + accuracy: 0.1017 + date: 2021-01-05_20-23-51 + done: true + experiment_id: 26ac228b4b454584869f8490742cf253 + experiment_tag: 1_batch_size=8,l1=16,l2=32,lr=0.077467 + hostname: 1a844a452371 + iterations_since_restore: 1 + loss: 2.321864831352234 + node_ip: 172.17.0.2 + pid: 1575 + should_checkpoint: true + time_since_restore: 42.09821367263794 + time_this_iter_s: 42.09821367263794 + time_total_s: 42.09821367263794 + timestamp: 1609878231 + timesteps_since_restore: 0 + training_iteration: 1 + trial_id: d3304_00001 + +[2m[36m(pid=1588)[0m [2, 2000] loss: 1.916 +[2m[36m(pid=1585)[0m [1, 8000] loss: 0.576 +[2m[36m(pid=1505)[0m [1, 8000] loss: 0.584 +[2m[36m(pid=1565)[0m [1, 8000] loss: 0.422 +[2m[36m(pid=1504)[0m [1, 8000] loss: 0.433 +[2m[36m(pid=1572)[0m [1, 8000] loss: 0.578 +[2m[36m(pid=1568)[0m [1, 8000] loss: 0.580 +Result for DEFAULT_d3304_00003: + accuracy: 0.3762 + date: 2021-01-05_20-24-00 + done: false + experiment_id: d4b00469893d498ea65a729df202882a + experiment_tag: 3_batch_size=16,l1=32,l2=4,lr=0.0012023 + hostname: 1a844a452371 + iterations_since_restore: 2 + loss: 1.7041921138763427 + node_ip: 172.17.0.2 + pid: 1588 + should_checkpoint: true + time_since_restore: 50.74612545967102 + time_this_iter_s: 23.576955556869507 + time_total_s: 50.74612545967102 + timestamp: 1609878240 + timesteps_since_restore: 0 + training_iteration: 2 + trial_id: d3304_00003 + +== Status == +Memory usage on this node: 8.0/240.1 GiB +Using AsyncHyperBand: num_stopped=2 +Bracket: Iter 8.000: None | Iter 4.000: None | Iter 2.000: -1.7041921138763427 | Iter 1.000: -2.3038805620193483 +Resources requested: 16/32 CPUs, 0/2 GPUs, 0.0/157.71 GiB heap, 0.0/49.37 GiB objects +Result logdir: /var/lib/jenkins/ray_results/DEFAULT_2021-01-05_20-23-08 +Number of trials: 10/10 (8 RUNNING, 2 TERMINATED) ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ +| Trial name | status | loc | batch_size | l1 | l2 | lr | loss | accuracy | training_iteration | +|---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------| +| DEFAULT_d3304_00000 | RUNNING | | 2 | 4 | 16 | 0.000111924 | | | | +| DEFAULT_d3304_00002 | RUNNING | | 4 | 8 | 128 | 0.00436986 | | | | +| DEFAULT_d3304_00003 | RUNNING | 172.17.0.2:1588 | 16 | 32 | 4 | 0.00120234 | 1.70419 | 0.3762 | 2 | +| DEFAULT_d3304_00004 | RUNNING | | 4 | 16 | 32 | 0.016474 | | | | +| DEFAULT_d3304_00005 | RUNNING | | 4 | 128 | 64 | 0.00757252 | | | | +| DEFAULT_d3304_00006 | RUNNING | | 2 | 64 | 256 | 0.00177236 | | | | +| DEFAULT_d3304_00008 | RUNNING | | 2 | 16 | 64 | 0.0310199 | | | | +| DEFAULT_d3304_00009 | RUNNING | | 4 | 4 | 32 | 0.0175239 | | | | +| DEFAULT_d3304_00001 | TERMINATED | | 8 | 16 | 32 | 0.077467 | 2.32186 | 0.1017 | 1 | +| DEFAULT_d3304_00007 | TERMINATED | | 8 | 8 | 8 | 0.000155891 | 2.30388 | 0.1011 | 1 | ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ + +[2m[36m(pid=1567)[0m [1, 8000] loss: 0.458 +[2m[36m(pid=1585)[0m [1, 10000] loss: 0.461 +[2m[36m(pid=1505)[0m [1, 10000] loss: 0.467 +[2m[36m(pid=1565)[0m [1, 10000] loss: 0.329 +[2m[36m(pid=1504)[0m [1, 10000] loss: 0.344 +[2m[36m(pid=1572)[0m [1, 10000] loss: 0.463 +[2m[36m(pid=1568)[0m [1, 10000] loss: 0.464 +[2m[36m(pid=1567)[0m [1, 10000] loss: 0.360 +[2m[36m(pid=1588)[0m [3, 2000] loss: 1.663 +Result for DEFAULT_d3304_00002: + accuracy: 0.3791 + date: 2021-01-05_20-24-18 + done: false + experiment_id: eaf4d25c9a0e46219afb226ed323095b + experiment_tag: 2_batch_size=4,l1=8,l2=128,lr=0.0043699 + hostname: 1a844a452371 + iterations_since_restore: 1 + loss: 1.6690538251161575 + node_ip: 172.17.0.2 + pid: 1504 + should_checkpoint: true + time_since_restore: 68.1856791973114 + time_this_iter_s: 68.1856791973114 + time_total_s: 68.1856791973114 + timestamp: 1609878258 + timesteps_since_restore: 0 + training_iteration: 1 + trial_id: d3304_00002 + +== Status == +Memory usage on this node: 8.0/240.1 GiB +Using AsyncHyperBand: num_stopped=2 +Bracket: Iter 8.000: None | Iter 4.000: None | Iter 2.000: -1.7041921138763427 | Iter 1.000: -2.193919415283203 +Resources requested: 16/32 CPUs, 0/2 GPUs, 0.0/157.71 GiB heap, 0.0/49.37 GiB objects +Result logdir: /var/lib/jenkins/ray_results/DEFAULT_2021-01-05_20-23-08 +Number of trials: 10/10 (8 RUNNING, 2 TERMINATED) ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ +| Trial name | status | loc | batch_size | l1 | l2 | lr | loss | accuracy | training_iteration | +|---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------| +| DEFAULT_d3304_00000 | RUNNING | | 2 | 4 | 16 | 0.000111924 | | | | +| DEFAULT_d3304_00002 | RUNNING | 172.17.0.2:1504 | 4 | 8 | 128 | 0.00436986 | 1.66905 | 0.3791 | 1 | +| DEFAULT_d3304_00003 | RUNNING | 172.17.0.2:1588 | 16 | 32 | 4 | 0.00120234 | 1.70419 | 0.3762 | 2 | +| DEFAULT_d3304_00004 | RUNNING | | 4 | 16 | 32 | 0.016474 | | | | +| DEFAULT_d3304_00005 | RUNNING | | 4 | 128 | 64 | 0.00757252 | | | | +| DEFAULT_d3304_00006 | RUNNING | | 2 | 64 | 256 | 0.00177236 | | | | +| DEFAULT_d3304_00008 | RUNNING | | 2 | 16 | 64 | 0.0310199 | | | | +| DEFAULT_d3304_00009 | RUNNING | | 4 | 4 | 32 | 0.0175239 | | | | +| DEFAULT_d3304_00001 | TERMINATED | | 8 | 16 | 32 | 0.077467 | 2.32186 | 0.1017 | 1 | +| DEFAULT_d3304_00007 | TERMINATED | | 8 | 8 | 8 | 0.000155891 | 2.30388 | 0.1011 | 1 | ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ + +[2m[36m(pid=1585)[0m [1, 12000] loss: 0.384 +[2m[36m(pid=1505)[0m [1, 12000] loss: 0.390 +Result for DEFAULT_d3304_00009: + accuracy: 0.101 + date: 2021-01-05_20-24-19 + done: true + experiment_id: 471eb6134c2a45509b005af46861c602 + experiment_tag: 9_batch_size=4,l1=4,l2=32,lr=0.017524 + hostname: 1a844a452371 + iterations_since_restore: 1 + loss: 2.310983589553833 + node_ip: 172.17.0.2 + pid: 1572 + should_checkpoint: true + time_since_restore: 69.29919123649597 + time_this_iter_s: 69.29919123649597 + time_total_s: 69.29919123649597 + timestamp: 1609878259 + timesteps_since_restore: 0 + training_iteration: 1 + trial_id: d3304_00009 + +Result for DEFAULT_d3304_00004: + accuracy: 0.102 + date: 2021-01-05_20-24-19 + done: true + experiment_id: bd1f438c1fdd4a9ba98074d1cfd573fe + experiment_tag: 4_batch_size=4,l1=16,l2=32,lr=0.016474 + hostname: 1a844a452371 + iterations_since_restore: 1 + loss: 2.313420217037201 + node_ip: 172.17.0.2 + pid: 1568 + should_checkpoint: true + time_since_restore: 69.48366618156433 + time_this_iter_s: 69.48366618156433 + time_total_s: 69.48366618156433 + timestamp: 1609878259 + timesteps_since_restore: 0 + training_iteration: 1 + trial_id: d3304_00004 + +[2m[36m(pid=1565)[0m [1, 12000] loss: 0.267 +Result for DEFAULT_d3304_00005: + accuracy: 0.3301 + date: 2021-01-05_20-24-22 + done: false + experiment_id: 738b3d315db548a7956646b2c07f1b0c + experiment_tag: 5_batch_size=4,l1=128,l2=64,lr=0.0075725 + hostname: 1a844a452371 + iterations_since_restore: 1 + loss: 1.8058318739891053 + node_ip: 172.17.0.2 + pid: 1567 + should_checkpoint: true + time_since_restore: 72.0806794166565 + time_this_iter_s: 72.0806794166565 + time_total_s: 72.0806794166565 + timestamp: 1609878262 + timesteps_since_restore: 0 + training_iteration: 1 + trial_id: d3304_00005 + +Result for DEFAULT_d3304_00003: + accuracy: 0.4242 + date: 2021-01-05_20-24-23 + done: false + experiment_id: d4b00469893d498ea65a729df202882a + experiment_tag: 3_batch_size=16,l1=32,l2=4,lr=0.0012023 + hostname: 1a844a452371 + iterations_since_restore: 3 + loss: 1.5498835063934326 + node_ip: 172.17.0.2 + pid: 1588 + should_checkpoint: true + time_since_restore: 73.29849410057068 + time_this_iter_s: 22.552368640899658 + time_total_s: 73.29849410057068 + timestamp: 1609878263 + timesteps_since_restore: 0 + training_iteration: 3 + trial_id: d3304_00003 + +== Status == +Memory usage on this node: 6.9/240.1 GiB +Using AsyncHyperBand: num_stopped=4 +Bracket: Iter 8.000: None | Iter 4.000: None | Iter 2.000: -1.7041921138763427 | Iter 1.000: -2.3038805620193483 +Resources requested: 12/32 CPUs, 0/2 GPUs, 0.0/157.71 GiB heap, 0.0/49.37 GiB objects +Result logdir: /var/lib/jenkins/ray_results/DEFAULT_2021-01-05_20-23-08 +Number of trials: 10/10 (6 RUNNING, 4 TERMINATED) ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ +| Trial name | status | loc | batch_size | l1 | l2 | lr | loss | accuracy | training_iteration | +|---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------| +| DEFAULT_d3304_00000 | RUNNING | | 2 | 4 | 16 | 0.000111924 | | | | +| DEFAULT_d3304_00002 | RUNNING | 172.17.0.2:1504 | 4 | 8 | 128 | 0.00436986 | 1.66905 | 0.3791 | 1 | +| DEFAULT_d3304_00003 | RUNNING | 172.17.0.2:1588 | 16 | 32 | 4 | 0.00120234 | 1.54988 | 0.4242 | 3 | +| DEFAULT_d3304_00005 | RUNNING | 172.17.0.2:1567 | 4 | 128 | 64 | 0.00757252 | 1.80583 | 0.3301 | 1 | +| DEFAULT_d3304_00006 | RUNNING | | 2 | 64 | 256 | 0.00177236 | | | | +| DEFAULT_d3304_00008 | RUNNING | | 2 | 16 | 64 | 0.0310199 | | | | +| DEFAULT_d3304_00001 | TERMINATED | | 8 | 16 | 32 | 0.077467 | 2.32186 | 0.1017 | 1 | +| DEFAULT_d3304_00004 | TERMINATED | | 4 | 16 | 32 | 0.016474 | 2.31342 | 0.102 | 1 | +| DEFAULT_d3304_00007 | TERMINATED | | 8 | 8 | 8 | 0.000155891 | 2.30388 | 0.1011 | 1 | +| DEFAULT_d3304_00009 | TERMINATED | | 4 | 4 | 32 | 0.0175239 | 2.31098 | 0.101 | 1 | ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ + +[2m[36m(pid=1585)[0m [1, 14000] loss: 0.329 +[2m[36m(pid=1504)[0m [2, 2000] loss: 1.708 +[2m[36m(pid=1565)[0m [1, 14000] loss: 0.225 +[2m[36m(pid=1505)[0m [1, 14000] loss: 0.334 +[2m[36m(pid=1567)[0m [2, 2000] loss: 1.803 +[2m[36m(pid=1585)[0m [1, 16000] loss: 0.288 +[2m[36m(pid=1588)[0m [4, 2000] loss: 1.541 +[2m[36m(pid=1504)[0m [2, 4000] loss: 0.840 +[2m[36m(pid=1565)[0m [1, 16000] loss: 0.198 +[2m[36m(pid=1505)[0m [1, 16000] loss: 0.292 +[2m[36m(pid=1567)[0m [2, 4000] loss: 0.912 +Result for DEFAULT_d3304_00003: + accuracy: 0.4494 + date: 2021-01-05_20-24-44 + done: false + experiment_id: d4b00469893d498ea65a729df202882a + experiment_tag: 3_batch_size=16,l1=32,l2=4,lr=0.0012023 + hostname: 1a844a452371 + iterations_since_restore: 4 + loss: 1.4720179980278014 + node_ip: 172.17.0.2 + pid: 1588 + should_checkpoint: true + time_since_restore: 94.81268787384033 + time_this_iter_s: 21.514193773269653 + time_total_s: 94.81268787384033 + timestamp: 1609878284 + timesteps_since_restore: 0 + training_iteration: 4 + trial_id: d3304_00003 + +== Status == +Memory usage on this node: 6.9/240.1 GiB +Using AsyncHyperBand: num_stopped=4 +Bracket: Iter 8.000: None | Iter 4.000: -1.4720179980278014 | Iter 2.000: -1.7041921138763427 | Iter 1.000: -2.3038805620193483 +Resources requested: 12/32 CPUs, 0/2 GPUs, 0.0/157.71 GiB heap, 0.0/49.37 GiB objects +Result logdir: /var/lib/jenkins/ray_results/DEFAULT_2021-01-05_20-23-08 +Number of trials: 10/10 (6 RUNNING, 4 TERMINATED) ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ +| Trial name | status | loc | batch_size | l1 | l2 | lr | loss | accuracy | training_iteration | +|---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------| +| DEFAULT_d3304_00000 | RUNNING | | 2 | 4 | 16 | 0.000111924 | | | | +| DEFAULT_d3304_00002 | RUNNING | 172.17.0.2:1504 | 4 | 8 | 128 | 0.00436986 | 1.66905 | 0.3791 | 1 | +| DEFAULT_d3304_00003 | RUNNING | 172.17.0.2:1588 | 16 | 32 | 4 | 0.00120234 | 1.47202 | 0.4494 | 4 | +| DEFAULT_d3304_00005 | RUNNING | 172.17.0.2:1567 | 4 | 128 | 64 | 0.00757252 | 1.80583 | 0.3301 | 1 | +| DEFAULT_d3304_00006 | RUNNING | | 2 | 64 | 256 | 0.00177236 | | | | +| DEFAULT_d3304_00008 | RUNNING | | 2 | 16 | 64 | 0.0310199 | | | | +| DEFAULT_d3304_00001 | TERMINATED | | 8 | 16 | 32 | 0.077467 | 2.32186 | 0.1017 | 1 | +| DEFAULT_d3304_00004 | TERMINATED | | 4 | 16 | 32 | 0.016474 | 2.31342 | 0.102 | 1 | +| DEFAULT_d3304_00007 | TERMINATED | | 8 | 8 | 8 | 0.000155891 | 2.30388 | 0.1011 | 1 | +| DEFAULT_d3304_00009 | TERMINATED | | 4 | 4 | 32 | 0.0175239 | 2.31098 | 0.101 | 1 | ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ + +[2m[36m(pid=1585)[0m [1, 18000] loss: 0.256 +[2m[36m(pid=1565)[0m [1, 18000] loss: 0.173 +[2m[36m(pid=1504)[0m [2, 6000] loss: 0.572 +[2m[36m(pid=1505)[0m [1, 18000] loss: 0.259 +[2m[36m(pid=1567)[0m [2, 6000] loss: 0.611 +[2m[36m(pid=1585)[0m [1, 20000] loss: 0.230 +[2m[36m(pid=1565)[0m [1, 20000] loss: 0.156 +[2m[36m(pid=1505)[0m [1, 20000] loss: 0.234 +[2m[36m(pid=1504)[0m [2, 8000] loss: 0.417 +[2m[36m(pid=1588)[0m [5, 2000] loss: 1.452 +[2m[36m(pid=1567)[0m [2, 8000] loss: 0.461 +Result for DEFAULT_d3304_00003: + accuracy: 0.4839 + date: 2021-01-05_20-25-06 + done: false + experiment_id: d4b00469893d498ea65a729df202882a + experiment_tag: 3_batch_size=16,l1=32,l2=4,lr=0.0012023 + hostname: 1a844a452371 + iterations_since_restore: 5 + loss: 1.4083827662467956 + node_ip: 172.17.0.2 + pid: 1588 + should_checkpoint: true + time_since_restore: 116.5817449092865 + time_this_iter_s: 21.769057035446167 + time_total_s: 116.5817449092865 + timestamp: 1609878306 + timesteps_since_restore: 0 + training_iteration: 5 + trial_id: d3304_00003 + +== Status == +Memory usage on this node: 6.9/240.1 GiB +Using AsyncHyperBand: num_stopped=4 +Bracket: Iter 8.000: None | Iter 4.000: -1.4720179980278014 | Iter 2.000: -1.7041921138763427 | Iter 1.000: -2.3038805620193483 +Resources requested: 12/32 CPUs, 0/2 GPUs, 0.0/157.71 GiB heap, 0.0/49.37 GiB objects +Result logdir: /var/lib/jenkins/ray_results/DEFAULT_2021-01-05_20-23-08 +Number of trials: 10/10 (6 RUNNING, 4 TERMINATED) ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ +| Trial name | status | loc | batch_size | l1 | l2 | lr | loss | accuracy | training_iteration | +|---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------| +| DEFAULT_d3304_00000 | RUNNING | | 2 | 4 | 16 | 0.000111924 | | | | +| DEFAULT_d3304_00002 | RUNNING | 172.17.0.2:1504 | 4 | 8 | 128 | 0.00436986 | 1.66905 | 0.3791 | 1 | +| DEFAULT_d3304_00003 | RUNNING | 172.17.0.2:1588 | 16 | 32 | 4 | 0.00120234 | 1.40838 | 0.4839 | 5 | +| DEFAULT_d3304_00005 | RUNNING | 172.17.0.2:1567 | 4 | 128 | 64 | 0.00757252 | 1.80583 | 0.3301 | 1 | +| DEFAULT_d3304_00006 | RUNNING | | 2 | 64 | 256 | 0.00177236 | | | | +| DEFAULT_d3304_00008 | RUNNING | | 2 | 16 | 64 | 0.0310199 | | | | +| DEFAULT_d3304_00001 | TERMINATED | | 8 | 16 | 32 | 0.077467 | 2.32186 | 0.1017 | 1 | +| DEFAULT_d3304_00004 | TERMINATED | | 4 | 16 | 32 | 0.016474 | 2.31342 | 0.102 | 1 | +| DEFAULT_d3304_00007 | TERMINATED | | 8 | 8 | 8 | 0.000155891 | 2.30388 | 0.1011 | 1 | +| DEFAULT_d3304_00009 | TERMINATED | | 4 | 4 | 32 | 0.0175239 | 2.31098 | 0.101 | 1 | ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ + +[2m[36m(pid=1504)[0m [2, 10000] loss: 0.339 +Result for DEFAULT_d3304_00000: + accuracy: 0.1104 + date: 2021-01-05_20-25-10 + done: false + experiment_id: 454624d453954d46b33a1eb496e7ec53 + experiment_tag: 0_batch_size=2,l1=4,l2=16,lr=0.00011192 + hostname: 1a844a452371 + iterations_since_restore: 1 + loss: 2.2988875378131866 + node_ip: 172.17.0.2 + pid: 1585 + should_checkpoint: true + time_since_restore: 120.59520411491394 + time_this_iter_s: 120.59520411491394 + time_total_s: 120.59520411491394 + timestamp: 1609878310 + timesteps_since_restore: 0 + training_iteration: 1 + trial_id: d3304_00000 + +Result for DEFAULT_d3304_00008: + accuracy: 0.0983 + date: 2021-01-05_20-25-11 + done: true + experiment_id: 381603b190bc47a9b794321f7692695f + experiment_tag: 8_batch_size=2,l1=16,l2=64,lr=0.03102 + hostname: 1a844a452371 + iterations_since_restore: 1 + loss: 2.336980807876587 + node_ip: 172.17.0.2 + pid: 1505 + should_checkpoint: true + time_since_restore: 121.36707901954651 + time_this_iter_s: 121.36707901954651 + time_total_s: 121.36707901954651 + timestamp: 1609878311 + timesteps_since_restore: 0 + training_iteration: 1 + trial_id: d3304_00008 + +Result for DEFAULT_d3304_00006: + accuracy: 0.4586 + date: 2021-01-05_20-25-11 + done: false + experiment_id: d8bae0fc87134e6398fd0341279c1a1a + experiment_tag: 6_batch_size=2,l1=64,l2=256,lr=0.0017724 + hostname: 1a844a452371 + iterations_since_restore: 1 + loss: 1.5124113649010658 + node_ip: 172.17.0.2 + pid: 1565 + should_checkpoint: true + time_since_restore: 121.536208152771 + time_this_iter_s: 121.536208152771 + time_total_s: 121.536208152771 + timestamp: 1609878311 + timesteps_since_restore: 0 + training_iteration: 1 + trial_id: d3304_00006 + +== Status == +Memory usage on this node: 6.6/240.1 GiB +Using AsyncHyperBand: num_stopped=5 +Bracket: Iter 8.000: None | Iter 4.000: -1.4720179980278014 | Iter 2.000: -1.7041921138763427 | Iter 1.000: -2.301384049916267 +Resources requested: 10/32 CPUs, 0/2 GPUs, 0.0/157.71 GiB heap, 0.0/49.37 GiB objects +Result logdir: /var/lib/jenkins/ray_results/DEFAULT_2021-01-05_20-23-08 +Number of trials: 10/10 (5 RUNNING, 5 TERMINATED) ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ +| Trial name | status | loc | batch_size | l1 | l2 | lr | loss | accuracy | training_iteration | +|---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------| +| DEFAULT_d3304_00000 | RUNNING | 172.17.0.2:1585 | 2 | 4 | 16 | 0.000111924 | 2.29889 | 0.1104 | 1 | +| DEFAULT_d3304_00002 | RUNNING | 172.17.0.2:1504 | 4 | 8 | 128 | 0.00436986 | 1.66905 | 0.3791 | 1 | +| DEFAULT_d3304_00003 | RUNNING | 172.17.0.2:1588 | 16 | 32 | 4 | 0.00120234 | 1.40838 | 0.4839 | 5 | +| DEFAULT_d3304_00005 | RUNNING | 172.17.0.2:1567 | 4 | 128 | 64 | 0.00757252 | 1.80583 | 0.3301 | 1 | +| DEFAULT_d3304_00006 | RUNNING | 172.17.0.2:1565 | 2 | 64 | 256 | 0.00177236 | 1.51241 | 0.4586 | 1 | +| DEFAULT_d3304_00001 | TERMINATED | | 8 | 16 | 32 | 0.077467 | 2.32186 | 0.1017 | 1 | +| DEFAULT_d3304_00004 | TERMINATED | | 4 | 16 | 32 | 0.016474 | 2.31342 | 0.102 | 1 | +| DEFAULT_d3304_00007 | TERMINATED | | 8 | 8 | 8 | 0.000155891 | 2.30388 | 0.1011 | 1 | +| DEFAULT_d3304_00008 | TERMINATED | | 2 | 16 | 64 | 0.0310199 | 2.33698 | 0.0983 | 1 | +| DEFAULT_d3304_00009 | TERMINATED | | 4 | 4 | 32 | 0.0175239 | 2.31098 | 0.101 | 1 | ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ + +Result for DEFAULT_d3304_00002: + accuracy: 0.4078 + date: 2021-01-05_20-25-16 + done: false + experiment_id: eaf4d25c9a0e46219afb226ed323095b + experiment_tag: 2_batch_size=4,l1=8,l2=128,lr=0.0043699 + hostname: 1a844a452371 + iterations_since_restore: 2 + loss: 1.6191314194440842 + node_ip: 172.17.0.2 + pid: 1504 + should_checkpoint: true + time_since_restore: 126.61185264587402 + time_this_iter_s: 58.42617344856262 + time_total_s: 126.61185264587402 + timestamp: 1609878316 + timesteps_since_restore: 0 + training_iteration: 2 + trial_id: d3304_00002 + +[2m[36m(pid=1567)[0m [2, 10000] loss: 0.371 +[2m[36m(pid=1585)[0m [2, 2000] loss: 2.298 +[2m[36m(pid=1565)[0m [2, 2000] loss: 1.466 +[2m[36m(pid=1588)[0m [6, 2000] loss: 1.383 +Result for DEFAULT_d3304_00005: + accuracy: 0.3647 + date: 2021-01-05_20-25-24 + done: true + experiment_id: 738b3d315db548a7956646b2c07f1b0c + experiment_tag: 5_batch_size=4,l1=128,l2=64,lr=0.0075725 + hostname: 1a844a452371 + iterations_since_restore: 2 + loss: 1.7739140236496926 + node_ip: 172.17.0.2 + pid: 1567 + should_checkpoint: true + time_since_restore: 134.1462869644165 + time_this_iter_s: 62.06560754776001 + time_total_s: 134.1462869644165 + timestamp: 1609878324 + timesteps_since_restore: 0 + training_iteration: 2 + trial_id: d3304_00005 + +== Status == +Memory usage on this node: 6.3/240.1 GiB +Using AsyncHyperBand: num_stopped=6 +Bracket: Iter 8.000: None | Iter 4.000: -1.4720179980278014 | Iter 2.000: -1.7041921138763427 | Iter 1.000: -2.301384049916267 +Resources requested: 10/32 CPUs, 0/2 GPUs, 0.0/157.71 GiB heap, 0.0/49.37 GiB objects +Result logdir: /var/lib/jenkins/ray_results/DEFAULT_2021-01-05_20-23-08 +Number of trials: 10/10 (5 RUNNING, 5 TERMINATED) ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ +| Trial name | status | loc | batch_size | l1 | l2 | lr | loss | accuracy | training_iteration | +|---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------| +| DEFAULT_d3304_00000 | RUNNING | 172.17.0.2:1585 | 2 | 4 | 16 | 0.000111924 | 2.29889 | 0.1104 | 1 | +| DEFAULT_d3304_00002 | RUNNING | 172.17.0.2:1504 | 4 | 8 | 128 | 0.00436986 | 1.61913 | 0.4078 | 2 | +| DEFAULT_d3304_00003 | RUNNING | 172.17.0.2:1588 | 16 | 32 | 4 | 0.00120234 | 1.40838 | 0.4839 | 5 | +| DEFAULT_d3304_00005 | RUNNING | 172.17.0.2:1567 | 4 | 128 | 64 | 0.00757252 | 1.77391 | 0.3647 | 2 | +| DEFAULT_d3304_00006 | RUNNING | 172.17.0.2:1565 | 2 | 64 | 256 | 0.00177236 | 1.51241 | 0.4586 | 1 | +| DEFAULT_d3304_00001 | TERMINATED | | 8 | 16 | 32 | 0.077467 | 2.32186 | 0.1017 | 1 | +| DEFAULT_d3304_00004 | TERMINATED | | 4 | 16 | 32 | 0.016474 | 2.31342 | 0.102 | 1 | +| DEFAULT_d3304_00007 | TERMINATED | | 8 | 8 | 8 | 0.000155891 | 2.30388 | 0.1011 | 1 | +| DEFAULT_d3304_00008 | TERMINATED | | 2 | 16 | 64 | 0.0310199 | 2.33698 | 0.0983 | 1 | +| DEFAULT_d3304_00009 | TERMINATED | | 4 | 4 | 32 | 0.0175239 | 2.31098 | 0.101 | 1 | ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ + +[2m[36m(pid=1504)[0m [3, 2000] loss: 1.656 +Result for DEFAULT_d3304_00003: + accuracy: 0.5061 + date: 2021-01-05_20-25-27 + done: false + experiment_id: d4b00469893d498ea65a729df202882a + experiment_tag: 3_batch_size=16,l1=32,l2=4,lr=0.0012023 + hostname: 1a844a452371 + iterations_since_restore: 6 + loss: 1.3623717227935792 + node_ip: 172.17.0.2 + pid: 1588 + should_checkpoint: true + time_since_restore: 137.95851016044617 + time_this_iter_s: 21.376765251159668 + time_total_s: 137.95851016044617 + timestamp: 1609878327 + timesteps_since_restore: 0 + training_iteration: 6 + trial_id: d3304_00003 + +[2m[36m(pid=1585)[0m [2, 4000] loss: 1.147 +[2m[36m(pid=1565)[0m [2, 4000] loss: 0.749 +[2m[36m(pid=1504)[0m [3, 4000] loss: 0.838 +[2m[36m(pid=1585)[0m [2, 6000] loss: 0.760 +[2m[36m(pid=1565)[0m [2, 6000] loss: 0.498 +[2m[36m(pid=1588)[0m [7, 2000] loss: 1.326 +[2m[36m(pid=1504)[0m [3, 6000] loss: 0.560 +[2m[36m(pid=1585)[0m [2, 8000] loss: 0.561 +Result for DEFAULT_d3304_00003: + accuracy: 0.5209 + date: 2021-01-05_20-25-48 + done: false + experiment_id: d4b00469893d498ea65a729df202882a + experiment_tag: 3_batch_size=16,l1=32,l2=4,lr=0.0012023 + hostname: 1a844a452371 + iterations_since_restore: 7 + loss: 1.316757419013977 + node_ip: 172.17.0.2 + pid: 1588 + should_checkpoint: true + time_since_restore: 158.4953932762146 + time_this_iter_s: 20.536883115768433 + time_total_s: 158.4953932762146 + timestamp: 1609878348 + timesteps_since_restore: 0 + training_iteration: 7 + trial_id: d3304_00003 + +== Status == +Memory usage on this node: 5.8/240.1 GiB +Using AsyncHyperBand: num_stopped=6 +Bracket: Iter 8.000: None | Iter 4.000: -1.4720179980278014 | Iter 2.000: -1.7041921138763427 | Iter 1.000: -2.301384049916267 +Resources requested: 8/32 CPUs, 0/2 GPUs, 0.0/157.71 GiB heap, 0.0/49.37 GiB objects +Result logdir: /var/lib/jenkins/ray_results/DEFAULT_2021-01-05_20-23-08 +Number of trials: 10/10 (4 RUNNING, 6 TERMINATED) ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ +| Trial name | status | loc | batch_size | l1 | l2 | lr | loss | accuracy | training_iteration | +|---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------| +| DEFAULT_d3304_00000 | RUNNING | 172.17.0.2:1585 | 2 | 4 | 16 | 0.000111924 | 2.29889 | 0.1104 | 1 | +| DEFAULT_d3304_00002 | RUNNING | 172.17.0.2:1504 | 4 | 8 | 128 | 0.00436986 | 1.61913 | 0.4078 | 2 | +| DEFAULT_d3304_00003 | RUNNING | 172.17.0.2:1588 | 16 | 32 | 4 | 0.00120234 | 1.31676 | 0.5209 | 7 | +| DEFAULT_d3304_00006 | RUNNING | 172.17.0.2:1565 | 2 | 64 | 256 | 0.00177236 | 1.51241 | 0.4586 | 1 | +| DEFAULT_d3304_00001 | TERMINATED | | 8 | 16 | 32 | 0.077467 | 2.32186 | 0.1017 | 1 | +| DEFAULT_d3304_00004 | TERMINATED | | 4 | 16 | 32 | 0.016474 | 2.31342 | 0.102 | 1 | +| DEFAULT_d3304_00005 | TERMINATED | | 4 | 128 | 64 | 0.00757252 | 1.77391 | 0.3647 | 2 | +| DEFAULT_d3304_00007 | TERMINATED | | 8 | 8 | 8 | 0.000155891 | 2.30388 | 0.1011 | 1 | +| DEFAULT_d3304_00008 | TERMINATED | | 2 | 16 | 64 | 0.0310199 | 2.33698 | 0.0983 | 1 | +| DEFAULT_d3304_00009 | TERMINATED | | 4 | 4 | 32 | 0.0175239 | 2.31098 | 0.101 | 1 | ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ + +[2m[36m(pid=1565)[0m [2, 8000] loss: 0.372 +[2m[36m(pid=1504)[0m [3, 8000] loss: 0.416 +[2m[36m(pid=1585)[0m [2, 10000] loss: 0.434 +[2m[36m(pid=1565)[0m [2, 10000] loss: 0.292 +[2m[36m(pid=1588)[0m [8, 2000] loss: 1.278 +[2m[36m(pid=1504)[0m [3, 10000] loss: 0.333 +[2m[36m(pid=1585)[0m [2, 12000] loss: 0.347 +[2m[36m(pid=1565)[0m [2, 12000] loss: 0.245 +Result for DEFAULT_d3304_00003: + accuracy: 0.5406 + date: 2021-01-05_20-26-08 + done: false + experiment_id: d4b00469893d498ea65a729df202882a + experiment_tag: 3_batch_size=16,l1=32,l2=4,lr=0.0012023 + hostname: 1a844a452371 + iterations_since_restore: 8 + loss: 1.267511115884781 + node_ip: 172.17.0.2 + pid: 1588 + should_checkpoint: true + time_since_restore: 179.13841199874878 + time_this_iter_s: 20.64301872253418 + time_total_s: 179.13841199874878 + timestamp: 1609878368 + timesteps_since_restore: 0 + training_iteration: 8 + trial_id: d3304_00003 + +== Status == +Memory usage on this node: 5.8/240.1 GiB +Using AsyncHyperBand: num_stopped=6 +Bracket: Iter 8.000: -1.267511115884781 | Iter 4.000: -1.4720179980278014 | Iter 2.000: -1.7041921138763427 | Iter 1.000: -2.301384049916267 +Resources requested: 8/32 CPUs, 0/2 GPUs, 0.0/157.71 GiB heap, 0.0/49.37 GiB objects +Result logdir: /var/lib/jenkins/ray_results/DEFAULT_2021-01-05_20-23-08 +Number of trials: 10/10 (4 RUNNING, 6 TERMINATED) ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ +| Trial name | status | loc | batch_size | l1 | l2 | lr | loss | accuracy | training_iteration | +|---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------| +| DEFAULT_d3304_00000 | RUNNING | 172.17.0.2:1585 | 2 | 4 | 16 | 0.000111924 | 2.29889 | 0.1104 | 1 | +| DEFAULT_d3304_00002 | RUNNING | 172.17.0.2:1504 | 4 | 8 | 128 | 0.00436986 | 1.61913 | 0.4078 | 2 | +| DEFAULT_d3304_00003 | RUNNING | 172.17.0.2:1588 | 16 | 32 | 4 | 0.00120234 | 1.26751 | 0.5406 | 8 | +| DEFAULT_d3304_00006 | RUNNING | 172.17.0.2:1565 | 2 | 64 | 256 | 0.00177236 | 1.51241 | 0.4586 | 1 | +| DEFAULT_d3304_00001 | TERMINATED | | 8 | 16 | 32 | 0.077467 | 2.32186 | 0.1017 | 1 | +| DEFAULT_d3304_00004 | TERMINATED | | 4 | 16 | 32 | 0.016474 | 2.31342 | 0.102 | 1 | +| DEFAULT_d3304_00005 | TERMINATED | | 4 | 128 | 64 | 0.00757252 | 1.77391 | 0.3647 | 2 | +| DEFAULT_d3304_00007 | TERMINATED | | 8 | 8 | 8 | 0.000155891 | 2.30388 | 0.1011 | 1 | +| DEFAULT_d3304_00008 | TERMINATED | | 2 | 16 | 64 | 0.0310199 | 2.33698 | 0.0983 | 1 | +| DEFAULT_d3304_00009 | TERMINATED | | 4 | 4 | 32 | 0.0175239 | 2.31098 | 0.101 | 1 | ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ + +Result for DEFAULT_d3304_00002: + accuracy: 0.3997 + date: 2021-01-05_20-26-11 + done: false + experiment_id: eaf4d25c9a0e46219afb226ed323095b + experiment_tag: 2_batch_size=4,l1=8,l2=128,lr=0.0043699 + hostname: 1a844a452371 + iterations_since_restore: 3 + loss: 1.7084122330278158 + node_ip: 172.17.0.2 + pid: 1504 + should_checkpoint: true + time_since_restore: 182.02509140968323 + time_this_iter_s: 55.413238763809204 + time_total_s: 182.02509140968323 + timestamp: 1609878371 + timesteps_since_restore: 0 + training_iteration: 3 + trial_id: d3304_00002 + +[2m[36m(pid=1585)[0m [2, 14000] loss: 0.290 +[2m[36m(pid=1565)[0m [2, 14000] loss: 0.213 +[2m[36m(pid=1504)[0m [4, 2000] loss: 1.653 +[2m[36m(pid=1588)[0m [9, 2000] loss: 1.245 +[2m[36m(pid=1585)[0m [2, 16000] loss: 0.244 +[2m[36m(pid=1565)[0m [2, 16000] loss: 0.186 +Result for DEFAULT_d3304_00003: + accuracy: 0.5409 + date: 2021-01-05_20-26-29 + done: false + experiment_id: d4b00469893d498ea65a729df202882a + experiment_tag: 3_batch_size=16,l1=32,l2=4,lr=0.0012023 + hostname: 1a844a452371 + iterations_since_restore: 9 + loss: 1.2721123942375183 + node_ip: 172.17.0.2 + pid: 1588 + should_checkpoint: true + time_since_restore: 199.56540870666504 + time_this_iter_s: 20.42699670791626 + time_total_s: 199.56540870666504 + timestamp: 1609878389 + timesteps_since_restore: 0 + training_iteration: 9 + trial_id: d3304_00003 + +== Status == +Memory usage on this node: 5.8/240.1 GiB +Using AsyncHyperBand: num_stopped=6 +Bracket: Iter 8.000: -1.267511115884781 | Iter 4.000: -1.4720179980278014 | Iter 2.000: -1.7041921138763427 | Iter 1.000: -2.301384049916267 +Resources requested: 8/32 CPUs, 0/2 GPUs, 0.0/157.71 GiB heap, 0.0/49.37 GiB objects +Result logdir: /var/lib/jenkins/ray_results/DEFAULT_2021-01-05_20-23-08 +Number of trials: 10/10 (4 RUNNING, 6 TERMINATED) ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ +| Trial name | status | loc | batch_size | l1 | l2 | lr | loss | accuracy | training_iteration | +|---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------| +| DEFAULT_d3304_00000 | RUNNING | 172.17.0.2:1585 | 2 | 4 | 16 | 0.000111924 | 2.29889 | 0.1104 | 1 | +| DEFAULT_d3304_00002 | RUNNING | 172.17.0.2:1504 | 4 | 8 | 128 | 0.00436986 | 1.70841 | 0.3997 | 3 | +| DEFAULT_d3304_00003 | RUNNING | 172.17.0.2:1588 | 16 | 32 | 4 | 0.00120234 | 1.27211 | 0.5409 | 9 | +| DEFAULT_d3304_00006 | RUNNING | 172.17.0.2:1565 | 2 | 64 | 256 | 0.00177236 | 1.51241 | 0.4586 | 1 | +| DEFAULT_d3304_00001 | TERMINATED | | 8 | 16 | 32 | 0.077467 | 2.32186 | 0.1017 | 1 | +| DEFAULT_d3304_00004 | TERMINATED | | 4 | 16 | 32 | 0.016474 | 2.31342 | 0.102 | 1 | +| DEFAULT_d3304_00005 | TERMINATED | | 4 | 128 | 64 | 0.00757252 | 1.77391 | 0.3647 | 2 | +| DEFAULT_d3304_00007 | TERMINATED | | 8 | 8 | 8 | 0.000155891 | 2.30388 | 0.1011 | 1 | +| DEFAULT_d3304_00008 | TERMINATED | | 2 | 16 | 64 | 0.0310199 | 2.33698 | 0.0983 | 1 | +| DEFAULT_d3304_00009 | TERMINATED | | 4 | 4 | 32 | 0.0175239 | 2.31098 | 0.101 | 1 | ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ + +[2m[36m(pid=1504)[0m [4, 4000] loss: 0.842 +[2m[36m(pid=1585)[0m [2, 18000] loss: 0.214 +[2m[36m(pid=1565)[0m [2, 18000] loss: 0.159 +[2m[36m(pid=1504)[0m [4, 6000] loss: 0.561 +[2m[36m(pid=1585)[0m [2, 20000] loss: 0.191 +[2m[36m(pid=1588)[0m [10, 2000] loss: 1.210 +[2m[36m(pid=1565)[0m [2, 20000] loss: 0.143 +Result for DEFAULT_d3304_00003: + accuracy: 0.5619 + date: 2021-01-05_20-26-50 + done: true + experiment_id: d4b00469893d498ea65a729df202882a + experiment_tag: 3_batch_size=16,l1=32,l2=4,lr=0.0012023 + hostname: 1a844a452371 + iterations_since_restore: 10 + loss: 1.2222298237800597 + node_ip: 172.17.0.2 + pid: 1588 + should_checkpoint: true + time_since_restore: 220.31984639167786 + time_this_iter_s: 20.754437685012817 + time_total_s: 220.31984639167786 + timestamp: 1609878410 + timesteps_since_restore: 0 + training_iteration: 10 + trial_id: d3304_00003 + +== Status == +Memory usage on this node: 5.8/240.1 GiB +Using AsyncHyperBand: num_stopped=7 +Bracket: Iter 8.000: -1.267511115884781 | Iter 4.000: -1.4720179980278014 | Iter 2.000: -1.7041921138763427 | Iter 1.000: -2.301384049916267 +Resources requested: 8/32 CPUs, 0/2 GPUs, 0.0/157.71 GiB heap, 0.0/49.37 GiB objects +Result logdir: /var/lib/jenkins/ray_results/DEFAULT_2021-01-05_20-23-08 +Number of trials: 10/10 (4 RUNNING, 6 TERMINATED) ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ +| Trial name | status | loc | batch_size | l1 | l2 | lr | loss | accuracy | training_iteration | +|---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------| +| DEFAULT_d3304_00000 | RUNNING | 172.17.0.2:1585 | 2 | 4 | 16 | 0.000111924 | 2.29889 | 0.1104 | 1 | +| DEFAULT_d3304_00002 | RUNNING | 172.17.0.2:1504 | 4 | 8 | 128 | 0.00436986 | 1.70841 | 0.3997 | 3 | +| DEFAULT_d3304_00003 | RUNNING | 172.17.0.2:1588 | 16 | 32 | 4 | 0.00120234 | 1.22223 | 0.5619 | 10 | +| DEFAULT_d3304_00006 | RUNNING | 172.17.0.2:1565 | 2 | 64 | 256 | 0.00177236 | 1.51241 | 0.4586 | 1 | +| DEFAULT_d3304_00001 | TERMINATED | | 8 | 16 | 32 | 0.077467 | 2.32186 | 0.1017 | 1 | +| DEFAULT_d3304_00004 | TERMINATED | | 4 | 16 | 32 | 0.016474 | 2.31342 | 0.102 | 1 | +| DEFAULT_d3304_00005 | TERMINATED | | 4 | 128 | 64 | 0.00757252 | 1.77391 | 0.3647 | 2 | +| DEFAULT_d3304_00007 | TERMINATED | | 8 | 8 | 8 | 0.000155891 | 2.30388 | 0.1011 | 1 | +| DEFAULT_d3304_00008 | TERMINATED | | 2 | 16 | 64 | 0.0310199 | 2.33698 | 0.0983 | 1 | +| DEFAULT_d3304_00009 | TERMINATED | | 4 | 4 | 32 | 0.0175239 | 2.31098 | 0.101 | 1 | ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ + +[2m[36m(pid=1504)[0m [4, 8000] loss: 0.422 +Result for DEFAULT_d3304_00000: + accuracy: 0.2724 + date: 2021-01-05_20-26-55 + done: true + experiment_id: 454624d453954d46b33a1eb496e7ec53 + experiment_tag: 0_batch_size=2,l1=4,l2=16,lr=0.00011192 + hostname: 1a844a452371 + iterations_since_restore: 2 + loss: 1.8605026947617531 + node_ip: 172.17.0.2 + pid: 1585 + should_checkpoint: true + time_since_restore: 225.84529209136963 + time_this_iter_s: 105.25008797645569 + time_total_s: 225.84529209136963 + timestamp: 1609878415 + timesteps_since_restore: 0 + training_iteration: 2 + trial_id: d3304_00000 + +== Status == +Memory usage on this node: 5.3/240.1 GiB +Using AsyncHyperBand: num_stopped=8 +Bracket: Iter 8.000: -1.267511115884781 | Iter 4.000: -1.4720179980278014 | Iter 2.000: -1.7390530687630177 | Iter 1.000: -2.301384049916267 +Resources requested: 6/32 CPUs, 0/2 GPUs, 0.0/157.71 GiB heap, 0.0/49.37 GiB objects +Result logdir: /var/lib/jenkins/ray_results/DEFAULT_2021-01-05_20-23-08 +Number of trials: 10/10 (3 RUNNING, 7 TERMINATED) ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ +| Trial name | status | loc | batch_size | l1 | l2 | lr | loss | accuracy | training_iteration | +|---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------| +| DEFAULT_d3304_00000 | RUNNING | 172.17.0.2:1585 | 2 | 4 | 16 | 0.000111924 | 1.8605 | 0.2724 | 2 | +| DEFAULT_d3304_00002 | RUNNING | 172.17.0.2:1504 | 4 | 8 | 128 | 0.00436986 | 1.70841 | 0.3997 | 3 | +| DEFAULT_d3304_00006 | RUNNING | 172.17.0.2:1565 | 2 | 64 | 256 | 0.00177236 | 1.51241 | 0.4586 | 1 | +| DEFAULT_d3304_00001 | TERMINATED | | 8 | 16 | 32 | 0.077467 | 2.32186 | 0.1017 | 1 | +| DEFAULT_d3304_00003 | TERMINATED | | 16 | 32 | 4 | 0.00120234 | 1.22223 | 0.5619 | 10 | +| DEFAULT_d3304_00004 | TERMINATED | | 4 | 16 | 32 | 0.016474 | 2.31342 | 0.102 | 1 | +| DEFAULT_d3304_00005 | TERMINATED | | 4 | 128 | 64 | 0.00757252 | 1.77391 | 0.3647 | 2 | +| DEFAULT_d3304_00007 | TERMINATED | | 8 | 8 | 8 | 0.000155891 | 2.30388 | 0.1011 | 1 | +| DEFAULT_d3304_00008 | TERMINATED | | 2 | 16 | 64 | 0.0310199 | 2.33698 | 0.0983 | 1 | +| DEFAULT_d3304_00009 | TERMINATED | | 4 | 4 | 32 | 0.0175239 | 2.31098 | 0.101 | 1 | ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ + +Result for DEFAULT_d3304_00006: + accuracy: 0.5007 + date: 2021-01-05_20-26-57 + done: false + experiment_id: d8bae0fc87134e6398fd0341279c1a1a + experiment_tag: 6_batch_size=2,l1=64,l2=256,lr=0.0017724 + hostname: 1a844a452371 + iterations_since_restore: 2 + loss: 1.3979384284215048 + node_ip: 172.17.0.2 + pid: 1565 + should_checkpoint: true + time_since_restore: 227.80454421043396 + time_this_iter_s: 106.26833605766296 + time_total_s: 227.80454421043396 + timestamp: 1609878417 + timesteps_since_restore: 0 + training_iteration: 2 + trial_id: d3304_00006 + +[2m[36m(pid=1504)[0m [4, 10000] loss: 0.335 +Result for DEFAULT_d3304_00002: + accuracy: 0.3849 + date: 2021-01-05_20-27-06 + done: true + experiment_id: eaf4d25c9a0e46219afb226ed323095b + experiment_tag: 2_batch_size=4,l1=8,l2=128,lr=0.0043699 + hostname: 1a844a452371 + iterations_since_restore: 4 + loss: 1.720731588792801 + node_ip: 172.17.0.2 + pid: 1504 + should_checkpoint: true + time_since_restore: 236.71593952178955 + time_this_iter_s: 54.69084811210632 + time_total_s: 236.71593952178955 + timestamp: 1609878426 + timesteps_since_restore: 0 + training_iteration: 4 + trial_id: d3304_00002 + +== Status == +Memory usage on this node: 4.7/240.1 GiB +Using AsyncHyperBand: num_stopped=9 +Bracket: Iter 8.000: -1.267511115884781 | Iter 4.000: -1.5963747934103012 | Iter 2.000: -1.7041921138763427 | Iter 1.000: -2.301384049916267 +Resources requested: 4/32 CPUs, 0/2 GPUs, 0.0/157.71 GiB heap, 0.0/49.37 GiB objects +Result logdir: /var/lib/jenkins/ray_results/DEFAULT_2021-01-05_20-23-08 +Number of trials: 10/10 (2 RUNNING, 8 TERMINATED) ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ +| Trial name | status | loc | batch_size | l1 | l2 | lr | loss | accuracy | training_iteration | +|---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------| +| DEFAULT_d3304_00002 | RUNNING | 172.17.0.2:1504 | 4 | 8 | 128 | 0.00436986 | 1.72073 | 0.3849 | 4 | +| DEFAULT_d3304_00006 | RUNNING | 172.17.0.2:1565 | 2 | 64 | 256 | 0.00177236 | 1.39794 | 0.5007 | 2 | +| DEFAULT_d3304_00000 | TERMINATED | | 2 | 4 | 16 | 0.000111924 | 1.8605 | 0.2724 | 2 | +| DEFAULT_d3304_00001 | TERMINATED | | 8 | 16 | 32 | 0.077467 | 2.32186 | 0.1017 | 1 | +| DEFAULT_d3304_00003 | TERMINATED | | 16 | 32 | 4 | 0.00120234 | 1.22223 | 0.5619 | 10 | +| DEFAULT_d3304_00004 | TERMINATED | | 4 | 16 | 32 | 0.016474 | 2.31342 | 0.102 | 1 | +| DEFAULT_d3304_00005 | TERMINATED | | 4 | 128 | 64 | 0.00757252 | 1.77391 | 0.3647 | 2 | +| DEFAULT_d3304_00007 | TERMINATED | | 8 | 8 | 8 | 0.000155891 | 2.30388 | 0.1011 | 1 | +| DEFAULT_d3304_00008 | TERMINATED | | 2 | 16 | 64 | 0.0310199 | 2.33698 | 0.0983 | 1 | +| DEFAULT_d3304_00009 | TERMINATED | | 4 | 4 | 32 | 0.0175239 | 2.31098 | 0.101 | 1 | ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ + +[2m[36m(pid=1565)[0m [3, 2000] loss: 1.373 +[2m[36m(pid=1565)[0m [3, 4000] loss: 0.696 +[2m[36m(pid=1565)[0m [3, 6000] loss: 0.466 +[2m[36m(pid=1565)[0m [3, 8000] loss: 0.357 +[2m[36m(pid=1565)[0m [3, 10000] loss: 0.283 +[2m[36m(pid=1565)[0m [3, 12000] loss: 0.241 +[2m[36m(pid=1565)[0m [3, 14000] loss: 0.203 +[2m[36m(pid=1565)[0m [3, 16000] loss: 0.178 +[2m[36m(pid=1565)[0m [3, 18000] loss: 0.160 +[2m[36m(pid=1565)[0m [3, 20000] loss: 0.142 +Result for DEFAULT_d3304_00006: + accuracy: 0.5095 + date: 2021-01-05_20-28-36 + done: false + experiment_id: d8bae0fc87134e6398fd0341279c1a1a + experiment_tag: 6_batch_size=2,l1=64,l2=256,lr=0.0017724 + hostname: 1a844a452371 + iterations_since_restore: 3 + loss: 1.4272501501079649 + node_ip: 172.17.0.2 + pid: 1565 + should_checkpoint: true + time_since_restore: 326.1525847911835 + time_this_iter_s: 98.34804058074951 + time_total_s: 326.1525847911835 + timestamp: 1609878516 + timesteps_since_restore: 0 + training_iteration: 3 + trial_id: d3304_00006 + +== Status == +Memory usage on this node: 4.2/240.1 GiB +Using AsyncHyperBand: num_stopped=9 +Bracket: Iter 8.000: -1.267511115884781 | Iter 4.000: -1.5963747934103012 | Iter 2.000: -1.7041921138763427 | Iter 1.000: -2.301384049916267 +Resources requested: 2/32 CPUs, 0/2 GPUs, 0.0/157.71 GiB heap, 0.0/49.37 GiB objects +Result logdir: /var/lib/jenkins/ray_results/DEFAULT_2021-01-05_20-23-08 +Number of trials: 10/10 (1 RUNNING, 9 TERMINATED) ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ +| Trial name | status | loc | batch_size | l1 | l2 | lr | loss | accuracy | training_iteration | +|---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------| +| DEFAULT_d3304_00006 | RUNNING | 172.17.0.2:1565 | 2 | 64 | 256 | 0.00177236 | 1.42725 | 0.5095 | 3 | +| DEFAULT_d3304_00000 | TERMINATED | | 2 | 4 | 16 | 0.000111924 | 1.8605 | 0.2724 | 2 | +| DEFAULT_d3304_00001 | TERMINATED | | 8 | 16 | 32 | 0.077467 | 2.32186 | 0.1017 | 1 | +| DEFAULT_d3304_00002 | TERMINATED | | 4 | 8 | 128 | 0.00436986 | 1.72073 | 0.3849 | 4 | +| DEFAULT_d3304_00003 | TERMINATED | | 16 | 32 | 4 | 0.00120234 | 1.22223 | 0.5619 | 10 | +| DEFAULT_d3304_00004 | TERMINATED | | 4 | 16 | 32 | 0.016474 | 2.31342 | 0.102 | 1 | +| DEFAULT_d3304_00005 | TERMINATED | | 4 | 128 | 64 | 0.00757252 | 1.77391 | 0.3647 | 2 | +| DEFAULT_d3304_00007 | TERMINATED | | 8 | 8 | 8 | 0.000155891 | 2.30388 | 0.1011 | 1 | +| DEFAULT_d3304_00008 | TERMINATED | | 2 | 16 | 64 | 0.0310199 | 2.33698 | 0.0983 | 1 | +| DEFAULT_d3304_00009 | TERMINATED | | 4 | 4 | 32 | 0.0175239 | 2.31098 | 0.101 | 1 | ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ + +[2m[36m(pid=1565)[0m [4, 2000] loss: 1.320 +[2m[36m(pid=1565)[0m [4, 4000] loss: 0.701 +[2m[36m(pid=1565)[0m [4, 6000] loss: 0.454 +[2m[36m(pid=1565)[0m [4, 8000] loss: 0.345 +[2m[36m(pid=1565)[0m [4, 10000] loss: 0.276 +[2m[36m(pid=1565)[0m [4, 12000] loss: 0.234 +[2m[36m(pid=1565)[0m [4, 14000] loss: 0.199 +[2m[36m(pid=1565)[0m [4, 16000] loss: 0.170 +[2m[36m(pid=1565)[0m [4, 18000] loss: 0.151 +[2m[36m(pid=1565)[0m [4, 20000] loss: 0.144 +Result for DEFAULT_d3304_00006: + accuracy: 0.4749 + date: 2021-01-05_20-30-15 + done: false + experiment_id: d8bae0fc87134e6398fd0341279c1a1a + experiment_tag: 6_batch_size=2,l1=64,l2=256,lr=0.0017724 + hostname: 1a844a452371 + iterations_since_restore: 4 + loss: 1.4950430885698218 + node_ip: 172.17.0.2 + pid: 1565 + should_checkpoint: true + time_since_restore: 425.3827154636383 + time_this_iter_s: 99.23013067245483 + time_total_s: 425.3827154636383 + timestamp: 1609878615 + timesteps_since_restore: 0 + training_iteration: 4 + trial_id: d3304_00006 + +== Status == +Memory usage on this node: 4.1/240.1 GiB +Using AsyncHyperBand: num_stopped=9 +Bracket: Iter 8.000: -1.267511115884781 | Iter 4.000: -1.4950430885698218 | Iter 2.000: -1.7041921138763427 | Iter 1.000: -2.301384049916267 +Resources requested: 2/32 CPUs, 0/2 GPUs, 0.0/157.71 GiB heap, 0.0/49.37 GiB objects +Result logdir: /var/lib/jenkins/ray_results/DEFAULT_2021-01-05_20-23-08 +Number of trials: 10/10 (1 RUNNING, 9 TERMINATED) ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ +| Trial name | status | loc | batch_size | l1 | l2 | lr | loss | accuracy | training_iteration | +|---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------| +| DEFAULT_d3304_00006 | RUNNING | 172.17.0.2:1565 | 2 | 64 | 256 | 0.00177236 | 1.49504 | 0.4749 | 4 | +| DEFAULT_d3304_00000 | TERMINATED | | 2 | 4 | 16 | 0.000111924 | 1.8605 | 0.2724 | 2 | +| DEFAULT_d3304_00001 | TERMINATED | | 8 | 16 | 32 | 0.077467 | 2.32186 | 0.1017 | 1 | +| DEFAULT_d3304_00002 | TERMINATED | | 4 | 8 | 128 | 0.00436986 | 1.72073 | 0.3849 | 4 | +| DEFAULT_d3304_00003 | TERMINATED | | 16 | 32 | 4 | 0.00120234 | 1.22223 | 0.5619 | 10 | +| DEFAULT_d3304_00004 | TERMINATED | | 4 | 16 | 32 | 0.016474 | 2.31342 | 0.102 | 1 | +| DEFAULT_d3304_00005 | TERMINATED | | 4 | 128 | 64 | 0.00757252 | 1.77391 | 0.3647 | 2 | +| DEFAULT_d3304_00007 | TERMINATED | | 8 | 8 | 8 | 0.000155891 | 2.30388 | 0.1011 | 1 | +| DEFAULT_d3304_00008 | TERMINATED | | 2 | 16 | 64 | 0.0310199 | 2.33698 | 0.0983 | 1 | +| DEFAULT_d3304_00009 | TERMINATED | | 4 | 4 | 32 | 0.0175239 | 2.31098 | 0.101 | 1 | ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ + +[2m[36m(pid=1565)[0m [5, 2000] loss: 1.314 +[2m[36m(pid=1565)[0m [5, 4000] loss: 0.663 +[2m[36m(pid=1565)[0m [5, 6000] loss: 0.453 +[2m[36m(pid=1565)[0m [5, 8000] loss: 0.341 +[2m[36m(pid=1565)[0m [5, 10000] loss: 0.278 +[2m[36m(pid=1565)[0m [5, 12000] loss: 0.235 +[2m[36m(pid=1565)[0m [5, 14000] loss: 0.197 +[2m[36m(pid=1565)[0m [5, 16000] loss: 0.173 +[2m[36m(pid=1565)[0m [5, 18000] loss: 0.155 +[2m[36m(pid=1565)[0m [5, 20000] loss: 0.137 +Result for DEFAULT_d3304_00006: + accuracy: 0.531 + date: 2021-01-05_20-31-56 + done: false + experiment_id: d8bae0fc87134e6398fd0341279c1a1a + experiment_tag: 6_batch_size=2,l1=64,l2=256,lr=0.0017724 + hostname: 1a844a452371 + iterations_since_restore: 5 + loss: 1.373500657767952 + node_ip: 172.17.0.2 + pid: 1565 + should_checkpoint: true + time_since_restore: 526.6667892932892 + time_this_iter_s: 101.28407382965088 + time_total_s: 526.6667892932892 + timestamp: 1609878716 + timesteps_since_restore: 0 + training_iteration: 5 + trial_id: d3304_00006 + +== Status == +Memory usage on this node: 4.1/240.1 GiB +Using AsyncHyperBand: num_stopped=9 +Bracket: Iter 8.000: -1.267511115884781 | Iter 4.000: -1.4950430885698218 | Iter 2.000: -1.7041921138763427 | Iter 1.000: -2.301384049916267 +Resources requested: 2/32 CPUs, 0/2 GPUs, 0.0/157.71 GiB heap, 0.0/49.37 GiB objects +Result logdir: /var/lib/jenkins/ray_results/DEFAULT_2021-01-05_20-23-08 +Number of trials: 10/10 (1 RUNNING, 9 TERMINATED) ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ +| Trial name | status | loc | batch_size | l1 | l2 | lr | loss | accuracy | training_iteration | +|---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------| +| DEFAULT_d3304_00006 | RUNNING | 172.17.0.2:1565 | 2 | 64 | 256 | 0.00177236 | 1.3735 | 0.531 | 5 | +| DEFAULT_d3304_00000 | TERMINATED | | 2 | 4 | 16 | 0.000111924 | 1.8605 | 0.2724 | 2 | +| DEFAULT_d3304_00001 | TERMINATED | | 8 | 16 | 32 | 0.077467 | 2.32186 | 0.1017 | 1 | +| DEFAULT_d3304_00002 | TERMINATED | | 4 | 8 | 128 | 0.00436986 | 1.72073 | 0.3849 | 4 | +| DEFAULT_d3304_00003 | TERMINATED | | 16 | 32 | 4 | 0.00120234 | 1.22223 | 0.5619 | 10 | +| DEFAULT_d3304_00004 | TERMINATED | | 4 | 16 | 32 | 0.016474 | 2.31342 | 0.102 | 1 | +| DEFAULT_d3304_00005 | TERMINATED | | 4 | 128 | 64 | 0.00757252 | 1.77391 | 0.3647 | 2 | +| DEFAULT_d3304_00007 | TERMINATED | | 8 | 8 | 8 | 0.000155891 | 2.30388 | 0.1011 | 1 | +| DEFAULT_d3304_00008 | TERMINATED | | 2 | 16 | 64 | 0.0310199 | 2.33698 | 0.0983 | 1 | +| DEFAULT_d3304_00009 | TERMINATED | | 4 | 4 | 32 | 0.0175239 | 2.31098 | 0.101 | 1 | ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ + +[2m[36m(pid=1565)[0m [6, 2000] loss: 1.325 +[2m[36m(pid=1565)[0m [6, 4000] loss: 0.668 +[2m[36m(pid=1565)[0m [6, 6000] loss: 0.457 +[2m[36m(pid=1565)[0m [6, 8000] loss: 0.338 +[2m[36m(pid=1565)[0m [6, 10000] loss: 0.283 +[2m[36m(pid=1565)[0m [6, 12000] loss: 0.232 +[2m[36m(pid=1565)[0m [6, 14000] loss: 0.198 +[2m[36m(pid=1565)[0m [6, 16000] loss: 0.175 +[2m[36m(pid=1565)[0m [6, 18000] loss: 0.149 +[2m[36m(pid=1565)[0m [6, 20000] loss: 0.140 +Result for DEFAULT_d3304_00006: + accuracy: 0.4852 + date: 2021-01-05_20-33-55 + done: false + experiment_id: d8bae0fc87134e6398fd0341279c1a1a + experiment_tag: 6_batch_size=2,l1=64,l2=256,lr=0.0017724 + hostname: 1a844a452371 + iterations_since_restore: 6 + loss: 1.5015573524537555 + node_ip: 172.17.0.2 + pid: 1565 + should_checkpoint: true + time_since_restore: 645.3050956726074 + time_this_iter_s: 118.63830637931824 + time_total_s: 645.3050956726074 + timestamp: 1609878835 + timesteps_since_restore: 0 + training_iteration: 6 + trial_id: d3304_00006 + +== Status == +Memory usage on this node: 4.1/240.1 GiB +Using AsyncHyperBand: num_stopped=9 +Bracket: Iter 8.000: -1.267511115884781 | Iter 4.000: -1.4950430885698218 | Iter 2.000: -1.7041921138763427 | Iter 1.000: -2.301384049916267 +Resources requested: 2/32 CPUs, 0/2 GPUs, 0.0/157.71 GiB heap, 0.0/49.37 GiB objects +Result logdir: /var/lib/jenkins/ray_results/DEFAULT_2021-01-05_20-23-08 +Number of trials: 10/10 (1 RUNNING, 9 TERMINATED) ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ +| Trial name | status | loc | batch_size | l1 | l2 | lr | loss | accuracy | training_iteration | +|---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------| +| DEFAULT_d3304_00006 | RUNNING | 172.17.0.2:1565 | 2 | 64 | 256 | 0.00177236 | 1.50156 | 0.4852 | 6 | +| DEFAULT_d3304_00000 | TERMINATED | | 2 | 4 | 16 | 0.000111924 | 1.8605 | 0.2724 | 2 | +| DEFAULT_d3304_00001 | TERMINATED | | 8 | 16 | 32 | 0.077467 | 2.32186 | 0.1017 | 1 | +| DEFAULT_d3304_00002 | TERMINATED | | 4 | 8 | 128 | 0.00436986 | 1.72073 | 0.3849 | 4 | +| DEFAULT_d3304_00003 | TERMINATED | | 16 | 32 | 4 | 0.00120234 | 1.22223 | 0.5619 | 10 | +| DEFAULT_d3304_00004 | TERMINATED | | 4 | 16 | 32 | 0.016474 | 2.31342 | 0.102 | 1 | +| DEFAULT_d3304_00005 | TERMINATED | | 4 | 128 | 64 | 0.00757252 | 1.77391 | 0.3647 | 2 | +| DEFAULT_d3304_00007 | TERMINATED | | 8 | 8 | 8 | 0.000155891 | 2.30388 | 0.1011 | 1 | +| DEFAULT_d3304_00008 | TERMINATED | | 2 | 16 | 64 | 0.0310199 | 2.33698 | 0.0983 | 1 | +| DEFAULT_d3304_00009 | TERMINATED | | 4 | 4 | 32 | 0.0175239 | 2.31098 | 0.101 | 1 | ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ + +[2m[36m(pid=1565)[0m [7, 2000] loss: 1.295 +[2m[36m(pid=1565)[0m [7, 4000] loss: 0.662 +[2m[36m(pid=1565)[0m [7, 6000] loss: 0.452 +[2m[36m(pid=1565)[0m [7, 8000] loss: 0.339 +[2m[36m(pid=1565)[0m [7, 10000] loss: 0.270 +[2m[36m(pid=1565)[0m [7, 12000] loss: 0.235 +[2m[36m(pid=1565)[0m [7, 14000] loss: 0.193 +[2m[36m(pid=1565)[0m [7, 16000] loss: 0.169 +[2m[36m(pid=1565)[0m [7, 18000] loss: 0.154 +[2m[36m(pid=1565)[0m [7, 20000] loss: 0.137 +Result for DEFAULT_d3304_00006: + accuracy: 0.4696 + date: 2021-01-05_20-35-52 + done: false + experiment_id: d8bae0fc87134e6398fd0341279c1a1a + experiment_tag: 6_batch_size=2,l1=64,l2=256,lr=0.0017724 + hostname: 1a844a452371 + iterations_since_restore: 7 + loss: 1.5851255111492393 + node_ip: 172.17.0.2 + pid: 1565 + should_checkpoint: true + time_since_restore: 762.1866834163666 + time_this_iter_s: 116.88158774375916 + time_total_s: 762.1866834163666 + timestamp: 1609878952 + timesteps_since_restore: 0 + training_iteration: 7 + trial_id: d3304_00006 + +== Status == +Memory usage on this node: 4.1/240.1 GiB +Using AsyncHyperBand: num_stopped=9 +Bracket: Iter 8.000: -1.267511115884781 | Iter 4.000: -1.4950430885698218 | Iter 2.000: -1.7041921138763427 | Iter 1.000: -2.301384049916267 +Resources requested: 2/32 CPUs, 0/2 GPUs, 0.0/157.71 GiB heap, 0.0/49.37 GiB objects +Result logdir: /var/lib/jenkins/ray_results/DEFAULT_2021-01-05_20-23-08 +Number of trials: 10/10 (1 RUNNING, 9 TERMINATED) ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ +| Trial name | status | loc | batch_size | l1 | l2 | lr | loss | accuracy | training_iteration | +|---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------| +| DEFAULT_d3304_00006 | RUNNING | 172.17.0.2:1565 | 2 | 64 | 256 | 0.00177236 | 1.58513 | 0.4696 | 7 | +| DEFAULT_d3304_00000 | TERMINATED | | 2 | 4 | 16 | 0.000111924 | 1.8605 | 0.2724 | 2 | +| DEFAULT_d3304_00001 | TERMINATED | | 8 | 16 | 32 | 0.077467 | 2.32186 | 0.1017 | 1 | +| DEFAULT_d3304_00002 | TERMINATED | | 4 | 8 | 128 | 0.00436986 | 1.72073 | 0.3849 | 4 | +| DEFAULT_d3304_00003 | TERMINATED | | 16 | 32 | 4 | 0.00120234 | 1.22223 | 0.5619 | 10 | +| DEFAULT_d3304_00004 | TERMINATED | | 4 | 16 | 32 | 0.016474 | 2.31342 | 0.102 | 1 | +| DEFAULT_d3304_00005 | TERMINATED | | 4 | 128 | 64 | 0.00757252 | 1.77391 | 0.3647 | 2 | +| DEFAULT_d3304_00007 | TERMINATED | | 8 | 8 | 8 | 0.000155891 | 2.30388 | 0.1011 | 1 | +| DEFAULT_d3304_00008 | TERMINATED | | 2 | 16 | 64 | 0.0310199 | 2.33698 | 0.0983 | 1 | +| DEFAULT_d3304_00009 | TERMINATED | | 4 | 4 | 32 | 0.0175239 | 2.31098 | 0.101 | 1 | ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ + +[2m[36m(pid=1565)[0m [8, 2000] loss: 1.341 +[2m[36m(pid=1565)[0m [8, 4000] loss: 0.667 +[2m[36m(pid=1565)[0m [8, 6000] loss: 0.445 +[2m[36m(pid=1565)[0m [8, 8000] loss: 0.336 +[2m[36m(pid=1565)[0m [8, 10000] loss: 0.271 +[2m[36m(pid=1565)[0m [8, 12000] loss: 0.228 +[2m[36m(pid=1565)[0m [8, 14000] loss: 0.196 +[2m[36m(pid=1565)[0m [8, 16000] loss: 0.175 +[2m[36m(pid=1565)[0m [8, 18000] loss: 0.155 +[2m[36m(pid=1565)[0m [8, 20000] loss: 0.135 +Result for DEFAULT_d3304_00006: + accuracy: 0.467 + date: 2021-01-05_20-37-32 + done: true + experiment_id: d8bae0fc87134e6398fd0341279c1a1a + experiment_tag: 6_batch_size=2,l1=64,l2=256,lr=0.0017724 + hostname: 1a844a452371 + iterations_since_restore: 8 + loss: 1.6539037554110967 + node_ip: 172.17.0.2 + pid: 1565 + should_checkpoint: true + time_since_restore: 862.3724186420441 + time_this_iter_s: 100.18573522567749 + time_total_s: 862.3724186420441 + timestamp: 1609879052 + timesteps_since_restore: 0 + training_iteration: 8 + trial_id: d3304_00006 + +== Status == +Memory usage on this node: 4.1/240.1 GiB +Using AsyncHyperBand: num_stopped=10 +Bracket: Iter 8.000: -1.4607074356479388 | Iter 4.000: -1.4950430885698218 | Iter 2.000: -1.7041921138763427 | Iter 1.000: -2.301384049916267 +Resources requested: 2/32 CPUs, 0/2 GPUs, 0.0/157.71 GiB heap, 0.0/49.37 GiB objects +Result logdir: /var/lib/jenkins/ray_results/DEFAULT_2021-01-05_20-23-08 +Number of trials: 10/10 (1 RUNNING, 9 TERMINATED) ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ +| Trial name | status | loc | batch_size | l1 | l2 | lr | loss | accuracy | training_iteration | +|---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------| +| DEFAULT_d3304_00006 | RUNNING | 172.17.0.2:1565 | 2 | 64 | 256 | 0.00177236 | 1.6539 | 0.467 | 8 | +| DEFAULT_d3304_00000 | TERMINATED | | 2 | 4 | 16 | 0.000111924 | 1.8605 | 0.2724 | 2 | +| DEFAULT_d3304_00001 | TERMINATED | | 8 | 16 | 32 | 0.077467 | 2.32186 | 0.1017 | 1 | +| DEFAULT_d3304_00002 | TERMINATED | | 4 | 8 | 128 | 0.00436986 | 1.72073 | 0.3849 | 4 | +| DEFAULT_d3304_00003 | TERMINATED | | 16 | 32 | 4 | 0.00120234 | 1.22223 | 0.5619 | 10 | +| DEFAULT_d3304_00004 | TERMINATED | | 4 | 16 | 32 | 0.016474 | 2.31342 | 0.102 | 1 | +| DEFAULT_d3304_00005 | TERMINATED | | 4 | 128 | 64 | 0.00757252 | 1.77391 | 0.3647 | 2 | +| DEFAULT_d3304_00007 | TERMINATED | | 8 | 8 | 8 | 0.000155891 | 2.30388 | 0.1011 | 1 | +| DEFAULT_d3304_00008 | TERMINATED | | 2 | 16 | 64 | 0.0310199 | 2.33698 | 0.0983 | 1 | +| DEFAULT_d3304_00009 | TERMINATED | | 4 | 4 | 32 | 0.0175239 | 2.31098 | 0.101 | 1 | ++---------------------+------------+-----------------+--------------+------+------+-------------+---------+------------+----------------------+ + +== Status == +Memory usage on this node: 4.0/240.1 GiB +Using AsyncHyperBand: num_stopped=10 +Bracket: Iter 8.000: -1.4607074356479388 | Iter 4.000: -1.4950430885698218 | Iter 2.000: -1.7041921138763427 | Iter 1.000: -2.301384049916267 +Resources requested: 0/32 CPUs, 0/2 GPUs, 0.0/157.71 GiB heap, 0.0/49.37 GiB objects +Result logdir: /var/lib/jenkins/ray_results/DEFAULT_2021-01-05_20-23-08 +Number of trials: 10/10 (10 TERMINATED) ++---------------------+------------+-------+--------------+------+------+-------------+---------+------------+----------------------+ +| Trial name | status | loc | batch_size | l1 | l2 | lr | loss | accuracy | training_iteration | +|---------------------+------------+-------+--------------+------+------+-------------+---------+------------+----------------------| +| DEFAULT_d3304_00000 | TERMINATED | | 2 | 4 | 16 | 0.000111924 | 1.8605 | 0.2724 | 2 | +| DEFAULT_d3304_00001 | TERMINATED | | 8 | 16 | 32 | 0.077467 | 2.32186 | 0.1017 | 1 | +| DEFAULT_d3304_00002 | TERMINATED | | 4 | 8 | 128 | 0.00436986 | 1.72073 | 0.3849 | 4 | +| DEFAULT_d3304_00003 | TERMINATED | | 16 | 32 | 4 | 0.00120234 | 1.22223 | 0.5619 | 10 | +| DEFAULT_d3304_00004 | TERMINATED | | 4 | 16 | 32 | 0.016474 | 2.31342 | 0.102 | 1 | +| DEFAULT_d3304_00005 | TERMINATED | | 4 | 128 | 64 | 0.00757252 | 1.77391 | 0.3647 | 2 | +| DEFAULT_d3304_00006 | TERMINATED | | 2 | 64 | 256 | 0.00177236 | 1.6539 | 0.467 | 8 | +| DEFAULT_d3304_00007 | TERMINATED | | 8 | 8 | 8 | 0.000155891 | 2.30388 | 0.1011 | 1 | +| DEFAULT_d3304_00008 | TERMINATED | | 2 | 16 | 64 | 0.0310199 | 2.33698 | 0.0983 | 1 | +| DEFAULT_d3304_00009 | TERMINATED | | 4 | 4 | 32 | 0.0175239 | 2.31098 | 0.101 | 1 | ++---------------------+------------+-------+--------------+------+------+-------------+---------+------------+----------------------+ + +Best trial config: {'l1': 32, 'l2': 4, 'lr': 0.0012023396319256663, 'batch_size': 16} +Best trial final validation loss: 1.2222298237800597 +Best trial final validation accuracy: 0.5619 +Files already downloaded and verified +Files already downloaded and verified +Best trial test set accuracy: 0.5537 + +``` + +如果运行代码,则示例输出如下所示: + +为了避免浪费资源,大多数审判​​已提早停止。 效果最好的试验的验证准确率约为 58%,可以在测试仪上进行确认。 + +就是这样了! 您现在可以调整 PyTorch 模型的参数。 + +**脚本的总运行时间**:(14 分钟 43.400 秒) + +[下载 Python 源码:`hyperparameter_tuning_tutorial.py`](../_downloads/95074cd7ce8c3e57a92e7a9c49182e6a/hyperparameter_tuning_tutorial.py) + +[下载 Jupyter 笔记本:`hyperparameter_tuning_tutorial.ipynb`](../_downloads/c24b93738bc036c1b66d0387555bf69a/hyperparameter_tuning_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/54.md b/pytorch/官方教程/54.md new file mode 100644 index 00000000..e158b5e8 --- /dev/null +++ b/pytorch/官方教程/54.md @@ -0,0 +1,781 @@ +# 模型剪裁教程 + +> 原文: + +**作者**: [Michela Paganini](https://github.com/mickypaganini) + +最新的深度学习技术依赖于难以部署的过度参数化模型。 相反,已知生物神经网络使用有效的稀疏连通性。 为了减少内存,电池和硬件消耗,同时又不牺牲精度,在设备上部署轻量级模型并通过私有设备上计算来确保私密性,确定通过减少模型中的参数数量来压缩模型的最佳技术很重要。 在研究方面,剪裁用于研究参数过度配置和参数不足网络在学习动态方面的差异,以研究幸运的稀疏子网络的作用([“彩票”](https://arxiv.org/abs/1803.03635)),以及初始化,作为破坏性的神经结构搜索技术等等。 + +在本教程中,您将学习如何使用`torch.nn.utils.prune`稀疏神经网络,以及如何扩展它以实现自己的自定义剪裁技术。 + +## 要求 + +`"torch>=1.4.0a0+8e8a5e0"` + +```py +import torch +from torch import nn +import torch.nn.utils.prune as prune +import torch.nn.functional as F + +``` + +## 创建模型 + +在本教程中,我们使用 LeCun 等人,1998 年的 [LeNet](http://yann.lecun.com/exdb/publis/pdf/lecun-98.pdf) 架构。 + +```py +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + +class LeNet(nn.Module): + def __init__(self): + super(LeNet, self).__init__() + # 1 input image channel, 6 output channels, 3x3 square conv kernel + self.conv1 = nn.Conv2d(1, 6, 3) + self.conv2 = nn.Conv2d(6, 16, 3) + self.fc1 = nn.Linear(16 * 5 * 5, 120) # 5x5 image dimension + self.fc2 = nn.Linear(120, 84) + self.fc3 = nn.Linear(84, 10) + + def forward(self, x): + x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2)) + x = F.max_pool2d(F.relu(self.conv2(x)), 2) + x = x.view(-1, int(x.nelement() / x.shape[0])) + x = F.relu(self.fc1(x)) + x = F.relu(self.fc2(x)) + x = self.fc3(x) + return x + +model = LeNet().to(device=device) + +``` + +## 检查模块 + +让我们检查一下 LeNet 模型中的(未剪裁)`conv1`层。 现在它将包含两个参数`weight`和`bias`,并且没有缓冲区。 + +```py +module = model.conv1 +print(list(module.named_parameters())) + +``` + +出: + +```py +[('weight', Parameter containing: +tensor([[[[ 0.1552, 0.0102, -0.1944], + [ 0.0263, 0.1374, -0.3139], + [ 0.2838, 0.1943, 0.0948]]], + + [[[-0.0296, -0.2514, 0.1300], + [ 0.0756, -0.3155, -0.2900], + [-0.1840, 0.1143, -0.0120]]], + + [[[-0.2383, -0.3022, 0.2295], + [-0.0050, 0.2485, -0.3230], + [-0.1317, -0.0054, 0.2659]]], + + [[[-0.0932, 0.1316, 0.0670], + [ 0.0572, -0.1845, 0.0870], + [ 0.1372, 0.1080, 0.0324]]], + + [[[ 0.0908, -0.3280, 0.0365], + [-0.3108, 0.2317, -0.2271], + [ 0.1171, 0.2113, -0.2259]]], + + [[[ 0.0407, 0.0512, 0.0954], + [-0.0437, 0.0302, -0.1317], + [ 0.2573, 0.0626, 0.0883]]]], device='cuda:0', requires_grad=True)), ('bias', Parameter containing: +tensor([-0.1803, 0.1331, -0.3267, 0.3173, -0.0349, 0.1828], device='cuda:0', + requires_grad=True))] + +``` + +```py +print(list(module.named_buffers())) + +``` + +出: + +```py +[] + +``` + +## 剪裁模块 + +要剪裁模块(在此示例中,为 LeNet 架构的`conv1`层),请首先从`torch.nn.utils.prune`中可用的那些技术中选择一种剪裁技术(或[通过子类化`BasePruningMethod`实现您自己的东西](#extending-torch-nn-utils-pruning-with-custom-pruning-functions))。 然后,指定模块和该模块中要剪裁的参数的名称。 最后,使用所选剪裁技术所需的适当关键字参数,指定剪裁参数。 + +在此示例中,我们将在`conv1`层中名为`weight`的参数中随机剪裁 30% 的连接。 模块作为第一个参数传递给函数; `name`使用其字符串标识符在该模块中标识参数; `amount`表示与剪裁的连接百分比(如果是介于 0 和 1 之间的浮点数),或表示与剪裁的连接的绝对数量(如果它是非负整数)。 + +```py +prune.random_unstructured(module, name="weight", amount=0.3) + +``` + +剪裁是通过从参数中删除`weight`并将其替换为名为`weight_orig`的新参数(即,将`"_orig"`附加到初始参数`name`)来进行的。 `weight_orig`存储未剪裁的张量版本。 `bias`未剪裁,因此它将保持完整。 + +```py +print(list(module.named_parameters())) + +``` + +出: + +```py +[('bias', Parameter containing: +tensor([-0.1803, 0.1331, -0.3267, 0.3173, -0.0349, 0.1828], device='cuda:0', + requires_grad=True)), ('weight_orig', Parameter containing: +tensor([[[[ 0.1552, 0.0102, -0.1944], + [ 0.0263, 0.1374, -0.3139], + [ 0.2838, 0.1943, 0.0948]]], + + [[[-0.0296, -0.2514, 0.1300], + [ 0.0756, -0.3155, -0.2900], + [-0.1840, 0.1143, -0.0120]]], + + [[[-0.2383, -0.3022, 0.2295], + [-0.0050, 0.2485, -0.3230], + [-0.1317, -0.0054, 0.2659]]], + + [[[-0.0932, 0.1316, 0.0670], + [ 0.0572, -0.1845, 0.0870], + [ 0.1372, 0.1080, 0.0324]]], + + [[[ 0.0908, -0.3280, 0.0365], + [-0.3108, 0.2317, -0.2271], + [ 0.1171, 0.2113, -0.2259]]], + + [[[ 0.0407, 0.0512, 0.0954], + [-0.0437, 0.0302, -0.1317], + [ 0.2573, 0.0626, 0.0883]]]], device='cuda:0', requires_grad=True))] + +``` + +通过以上选择的剪裁技术生成的剪裁掩码将保存为名为`weight_mask`的模块缓冲区(即,将`"_mask"`附加到初始参数`name`)。 + +```py +print(list(module.named_buffers())) + +``` + +出: + +```py +[('weight_mask', tensor([[[[1., 1., 0.], + [0., 0., 1.], + [1., 0., 1.]]], + + [[[1., 1., 1.], + [1., 1., 1.], + [1., 1., 1.]]], + + [[[1., 1., 0.], + [1., 0., 0.], + [1., 0., 1.]]], + + [[[1., 1., 1.], + [1., 0., 1.], + [1., 1., 1.]]], + + [[[1., 1., 1.], + [0., 0., 1.], + [1., 1., 1.]]], + + [[[1., 0., 0.], + [1., 0., 1.], + [1., 0., 0.]]]], device='cuda:0'))] + +``` + +为了使正向传播不更改即可工作,需要存在`weight`属性。 在`torch.nn.utils.prune`中实现的剪裁技术计算权重的剪裁版本(通过将掩码与原始参数组合)并将它们存储在属性`weight`中。 注意,这不再是`module`的参数,现在只是一个属性。 + +```py +print(module.weight) + +``` + +出: + +```py +tensor([[[[ 0.1552, 0.0102, -0.0000], + [ 0.0000, 0.0000, -0.3139], + [ 0.2838, 0.0000, 0.0948]]], + + [[[-0.0296, -0.2514, 0.1300], + [ 0.0756, -0.3155, -0.2900], + [-0.1840, 0.1143, -0.0120]]], + + [[[-0.2383, -0.3022, 0.0000], + [-0.0050, 0.0000, -0.0000], + [-0.1317, -0.0000, 0.2659]]], + + [[[-0.0932, 0.1316, 0.0670], + [ 0.0572, -0.0000, 0.0870], + [ 0.1372, 0.1080, 0.0324]]], + + [[[ 0.0908, -0.3280, 0.0365], + [-0.0000, 0.0000, -0.2271], + [ 0.1171, 0.2113, -0.2259]]], + + [[[ 0.0407, 0.0000, 0.0000], + [-0.0437, 0.0000, -0.1317], + [ 0.2573, 0.0000, 0.0000]]]], device='cuda:0', + grad_fn=) + +``` + +最后,使用 PyTorch 的`forward_pre_hooks`在每次向前传递之前应用剪裁。 具体来说,当剪裁`module`时(如我们在此处所做的那样),它将为与之关联的每个参数获取`forward_pre_hook`进行剪裁。 在这种情况下,由于到目前为止我们只剪裁了名称为`weight`的原始参数,因此只会出现一个钩子。 + +```py +print(module._forward_pre_hooks) + +``` + +出: + +```py +OrderedDict([(0, )]) + +``` + +为了完整起见,我们现在也可以剪裁`bias`,以查看`module`的参数,缓冲区,挂钩和属性如何变化。 仅出于尝试另一种剪裁技术的目的,在此我们按 L1 范数剪裁偏差中的 3 个最小条目,如`l1_unstructured`剪裁函数中所实现的。 + +```py +prune.l1_unstructured(module, name="bias", amount=3) + +``` + +现在,我们希望命名参数同时包含`weight_orig`(从前)和`bias_orig`。 缓冲区将包括`weight_mask`和`bias_mask`。 两个张量的剪裁后的版本将作为模块属性存在,并且该模块现在将具有两个`forward_pre_hooks`。 + +```py +print(list(module.named_parameters())) + +``` + +出: + +```py +[('weight_orig', Parameter containing: +tensor([[[[ 0.1552, 0.0102, -0.1944], + [ 0.0263, 0.1374, -0.3139], + [ 0.2838, 0.1943, 0.0948]]], + + [[[-0.0296, -0.2514, 0.1300], + [ 0.0756, -0.3155, -0.2900], + [-0.1840, 0.1143, -0.0120]]], + + [[[-0.2383, -0.3022, 0.2295], + [-0.0050, 0.2485, -0.3230], + [-0.1317, -0.0054, 0.2659]]], + + [[[-0.0932, 0.1316, 0.0670], + [ 0.0572, -0.1845, 0.0870], + [ 0.1372, 0.1080, 0.0324]]], + + [[[ 0.0908, -0.3280, 0.0365], + [-0.3108, 0.2317, -0.2271], + [ 0.1171, 0.2113, -0.2259]]], + + [[[ 0.0407, 0.0512, 0.0954], + [-0.0437, 0.0302, -0.1317], + [ 0.2573, 0.0626, 0.0883]]]], device='cuda:0', requires_grad=True)), ('bias_orig', Parameter containing: +tensor([-0.1803, 0.1331, -0.3267, 0.3173, -0.0349, 0.1828], device='cuda:0', + requires_grad=True))] + +``` + +```py +print(list(module.named_buffers())) + +``` + +出: + +```py +[('weight_mask', tensor([[[[1., 1., 0.], + [0., 0., 1.], + [1., 0., 1.]]], + + [[[1., 1., 1.], + [1., 1., 1.], + [1., 1., 1.]]], + + [[[1., 1., 0.], + [1., 0., 0.], + [1., 0., 1.]]], + + [[[1., 1., 1.], + [1., 0., 1.], + [1., 1., 1.]]], + + [[[1., 1., 1.], + [0., 0., 1.], + [1., 1., 1.]]], + + [[[1., 0., 0.], + [1., 0., 1.], + [1., 0., 0.]]]], device='cuda:0')), ('bias_mask', tensor([0., 0., 1., 1., 0., 1.], device='cuda:0'))] + +``` + +```py +print(module.bias) + +``` + +出: + +```py +tensor([-0.0000, 0.0000, -0.3267, 0.3173, -0.0000, 0.1828], device='cuda:0', + grad_fn=) + +``` + +```py +print(module._forward_pre_hooks) + +``` + +出: + +```py +OrderedDict([(0, ), (1, )]) + +``` + +## 迭代式剪裁 + +一个模块中的同一参数可以被多次剪裁,各种剪裁调用的效果等于连接应用的各种蒙版的组合。 `PruningContainer`的`compute_mask`方法可处理新遮罩与旧遮罩的组合。 + +例如,假设我们现在想进一步剪裁`module.weight`,这一次是使用沿着张量的第 0 轴的结构化剪裁(第 0 轴对应于卷积层的输出通道,并且对于`conv1`具有 6 维) ,基于渠道的 L2 规范。 这可以通过`ln_structured`和`n=2`和`dim=0`函数来实现。 + +```py +prune.ln_structured(module, name="weight", amount=0.5, n=2, dim=0) + +# As we can verify, this will zero out all the connections corresponding to +# 50% (3 out of 6) of the channels, while preserving the action of the +# previous mask. +print(module.weight) + +``` + +出: + +```py +tensor([[[[ 0.0000, 0.0000, -0.0000], + [ 0.0000, 0.0000, -0.0000], + [ 0.0000, 0.0000, 0.0000]]], + + [[[-0.0296, -0.2514, 0.1300], + [ 0.0756, -0.3155, -0.2900], + [-0.1840, 0.1143, -0.0120]]], + + [[[-0.2383, -0.3022, 0.0000], + [-0.0050, 0.0000, -0.0000], + [-0.1317, -0.0000, 0.2659]]], + + [[[-0.0000, 0.0000, 0.0000], + [ 0.0000, -0.0000, 0.0000], + [ 0.0000, 0.0000, 0.0000]]], + + [[[ 0.0908, -0.3280, 0.0365], + [-0.0000, 0.0000, -0.2271], + [ 0.1171, 0.2113, -0.2259]]], + + [[[ 0.0000, 0.0000, 0.0000], + [-0.0000, 0.0000, -0.0000], + [ 0.0000, 0.0000, 0.0000]]]], device='cuda:0', + grad_fn=) + +``` + +现在,对应的钩子将为`torch.nn.utils.prune.PruningContainer`类型,并将存储应用于`weight`参数的剪裁历史。 + +```py +for hook in module._forward_pre_hooks.values(): + if hook._tensor_name == "weight": # select out the correct hook + break + +print(list(hook)) # pruning history in the container + +``` + +出: + +```py +[, ] + +``` + +## 序列化剪裁的模型 + +所有相关的张量,包括掩码缓冲区和用于计算剪裁的张量的原始参数,都存储在模型的`state_dict`中,因此可以根据需要轻松地序列化和保存。 + +```py +print(model.state_dict().keys()) + +``` + +出: + +```py +odict_keys(['conv1.weight_orig', 'conv1.bias_orig', 'conv1.weight_mask', 'conv1.bias_mask', 'conv2.weight', 'conv2.bias', 'fc1.weight', 'fc1.bias', 'fc2.weight', 'fc2.bias', 'fc3.weight', 'fc3.bias']) + +``` + +## 删除剪裁重新参数化 + +要使剪裁永久化,请删除`weight_orig`和`weight_mask`的重新参数化,然后删除`forward_pre_hook`,我们可以使用`torch.nn.utils.prune`的`remove`函数。 请注意,这不会撤消剪裁,好像从未发生过。 而是通过将参数`weight`重新分配给模型参数(剪裁后的版本)来使其永久不变。 + +删除重新参数化之前: + +```py +print(list(module.named_parameters())) + +``` + +出: + +```py +[('weight_orig', Parameter containing: +tensor([[[[ 0.1552, 0.0102, -0.1944], + [ 0.0263, 0.1374, -0.3139], + [ 0.2838, 0.1943, 0.0948]]], + + [[[-0.0296, -0.2514, 0.1300], + [ 0.0756, -0.3155, -0.2900], + [-0.1840, 0.1143, -0.0120]]], + + [[[-0.2383, -0.3022, 0.2295], + [-0.0050, 0.2485, -0.3230], + [-0.1317, -0.0054, 0.2659]]], + + [[[-0.0932, 0.1316, 0.0670], + [ 0.0572, -0.1845, 0.0870], + [ 0.1372, 0.1080, 0.0324]]], + + [[[ 0.0908, -0.3280, 0.0365], + [-0.3108, 0.2317, -0.2271], + [ 0.1171, 0.2113, -0.2259]]], + + [[[ 0.0407, 0.0512, 0.0954], + [-0.0437, 0.0302, -0.1317], + [ 0.2573, 0.0626, 0.0883]]]], device='cuda:0', requires_grad=True)), ('bias_orig', Parameter containing: +tensor([-0.1803, 0.1331, -0.3267, 0.3173, -0.0349, 0.1828], device='cuda:0', + requires_grad=True))] + +``` + +```py +print(list(module.named_buffers())) + +``` + +出: + +```py +[('weight_mask', tensor([[[[0., 0., 0.], + [0., 0., 0.], + [0., 0., 0.]]], + + [[[1., 1., 1.], + [1., 1., 1.], + [1., 1., 1.]]], + + [[[1., 1., 0.], + [1., 0., 0.], + [1., 0., 1.]]], + + [[[0., 0., 0.], + [0., 0., 0.], + [0., 0., 0.]]], + + [[[1., 1., 1.], + [0., 0., 1.], + [1., 1., 1.]]], + + [[[0., 0., 0.], + [0., 0., 0.], + [0., 0., 0.]]]], device='cuda:0')), ('bias_mask', tensor([0., 0., 1., 1., 0., 1.], device='cuda:0'))] + +``` + +```py +print(module.weight) + +``` + +出: + +```py +tensor([[[[ 0.0000, 0.0000, -0.0000], + [ 0.0000, 0.0000, -0.0000], + [ 0.0000, 0.0000, 0.0000]]], + + [[[-0.0296, -0.2514, 0.1300], + [ 0.0756, -0.3155, -0.2900], + [-0.1840, 0.1143, -0.0120]]], + + [[[-0.2383, -0.3022, 0.0000], + [-0.0050, 0.0000, -0.0000], + [-0.1317, -0.0000, 0.2659]]], + + [[[-0.0000, 0.0000, 0.0000], + [ 0.0000, -0.0000, 0.0000], + [ 0.0000, 0.0000, 0.0000]]], + + [[[ 0.0908, -0.3280, 0.0365], + [-0.0000, 0.0000, -0.2271], + [ 0.1171, 0.2113, -0.2259]]], + + [[[ 0.0000, 0.0000, 0.0000], + [-0.0000, 0.0000, -0.0000], + [ 0.0000, 0.0000, 0.0000]]]], device='cuda:0', + grad_fn=) + +``` + +删除重新参数化后: + +```py +prune.remove(module, 'weight') +print(list(module.named_parameters())) + +``` + +出: + +```py +[('bias_orig', Parameter containing: +tensor([-0.1803, 0.1331, -0.3267, 0.3173, -0.0349, 0.1828], device='cuda:0', + requires_grad=True)), ('weight', Parameter containing: +tensor([[[[ 0.0000, 0.0000, -0.0000], + [ 0.0000, 0.0000, -0.0000], + [ 0.0000, 0.0000, 0.0000]]], + + [[[-0.0296, -0.2514, 0.1300], + [ 0.0756, -0.3155, -0.2900], + [-0.1840, 0.1143, -0.0120]]], + + [[[-0.2383, -0.3022, 0.0000], + [-0.0050, 0.0000, -0.0000], + [-0.1317, -0.0000, 0.2659]]], + + [[[-0.0000, 0.0000, 0.0000], + [ 0.0000, -0.0000, 0.0000], + [ 0.0000, 0.0000, 0.0000]]], + + [[[ 0.0908, -0.3280, 0.0365], + [-0.0000, 0.0000, -0.2271], + [ 0.1171, 0.2113, -0.2259]]], + + [[[ 0.0000, 0.0000, 0.0000], + [-0.0000, 0.0000, -0.0000], + [ 0.0000, 0.0000, 0.0000]]]], device='cuda:0', requires_grad=True))] + +``` + +```py +print(list(module.named_buffers())) + +``` + +出: + +```py +[('bias_mask', tensor([0., 0., 1., 1., 0., 1.], device='cuda:0'))] + +``` + +## 剪裁模型中的多个参数 + +通过指定所需的剪裁技术和参数,我们可以轻松地剪裁网络中的多个张量,也许根据它们的类型,如在本示例中将看到的那样。 + +```py +new_model = LeNet() +for name, module in new_model.named_modules(): + # prune 20% of connections in all 2D-conv layers + if isinstance(module, torch.nn.Conv2d): + prune.l1_unstructured(module, name='weight', amount=0.2) + # prune 40% of connections in all linear layers + elif isinstance(module, torch.nn.Linear): + prune.l1_unstructured(module, name='weight', amount=0.4) + +print(dict(new_model.named_buffers()).keys()) # to verify that all masks exist + +``` + +出: + +```py +dict_keys(['conv1.weight_mask', 'conv2.weight_mask', 'fc1.weight_mask', 'fc2.weight_mask', 'fc3.weight_mask']) + +``` + +## 全局剪裁 + +到目前为止,我们仅查看了通常称为“局部”剪裁的情况,即通过比较每个条目的统计信息(权重,激活度,梯度等)来逐个剪裁模型中的张量的做法。 到该张量中的其他条目。 但是,一种通用且可能更强大的技术是通过删除(例如)删除整个模型中最低的 20% 的连接,而不是删除每一层中最低的 20% 的连接来一次剪裁模型。 这很可能导致每个层的剪裁百分比不同。 让我们看看如何使用`torch.nn.utils.prune`中的`global_unstructured`进行操作。 + +```py +model = LeNet() + +parameters_to_prune = ( + (model.conv1, 'weight'), + (model.conv2, 'weight'), + (model.fc1, 'weight'), + (model.fc2, 'weight'), + (model.fc3, 'weight'), +) + +prune.global_unstructured( + parameters_to_prune, + pruning_method=prune.L1Unstructured, + amount=0.2, +) + +``` + +现在,我们可以检查每个剪裁参数中引起的稀疏性,该稀疏性将不等于每层中的 20%。 但是,全局稀疏度将(大约)为 20%。 + +```py +print( + "Sparsity in conv1.weight: {:.2f}%".format( + 100\. * float(torch.sum(model.conv1.weight == 0)) + / float(model.conv1.weight.nelement()) + ) +) +print( + "Sparsity in conv2.weight: {:.2f}%".format( + 100\. * float(torch.sum(model.conv2.weight == 0)) + / float(model.conv2.weight.nelement()) + ) +) +print( + "Sparsity in fc1.weight: {:.2f}%".format( + 100\. * float(torch.sum(model.fc1.weight == 0)) + / float(model.fc1.weight.nelement()) + ) +) +print( + "Sparsity in fc2.weight: {:.2f}%".format( + 100\. * float(torch.sum(model.fc2.weight == 0)) + / float(model.fc2.weight.nelement()) + ) +) +print( + "Sparsity in fc3.weight: {:.2f}%".format( + 100\. * float(torch.sum(model.fc3.weight == 0)) + / float(model.fc3.weight.nelement()) + ) +) +print( + "Global sparsity: {:.2f}%".format( + 100\. * float( + torch.sum(model.conv1.weight == 0) + + torch.sum(model.conv2.weight == 0) + + torch.sum(model.fc1.weight == 0) + + torch.sum(model.fc2.weight == 0) + + torch.sum(model.fc3.weight == 0) + ) + / float( + model.conv1.weight.nelement() + + model.conv2.weight.nelement() + + model.fc1.weight.nelement() + + model.fc2.weight.nelement() + + model.fc3.weight.nelement() + ) + ) +) + +``` + +出: + +```py +Sparsity in conv1.weight: 3.70% +Sparsity in conv2.weight: 8.10% +Sparsity in fc1.weight: 22.05% +Sparsity in fc2.weight: 12.29% +Sparsity in fc3.weight: 8.45% +Global sparsity: 20.00% + +``` + +## 使用自定义剪裁函数扩展`torch.nn.utils.prune` + +要实现自己的剪裁函数,可以通过继承`BasePruningMethod`基类的子类来扩展`nn.utils.prune`模块,这与所有其他剪裁方法一样。 基类为您实现以下方法:`__call__`,`apply_mask`,`apply`,`prune`和`remove`。 除了一些特殊情况外,您无需为新的剪裁技术重新实现这些方法。 但是,您将必须实现`__init__`(构造器)和`compute_mask`(有关如何根据剪裁技术的逻辑为给定张量计算掩码的说明)。 另外,您将必须指定此技术实现的剪裁类型(支持的选项为`global`,`structured`和`unstructured`)。 需要确定在迭代应用剪裁的情况下如何组合蒙版。 换句话说,当剪裁预剪裁的参数时,当前的剪裁技术应作用于参数的未剪裁部分。 指定`PRUNING_TYPE`将使`PruningContainer`(处理剪裁掩码的迭代应用)正确识别要剪裁的参数。 + +例如,假设您要实现一种剪裁技术,以剪裁张量中的所有其他条目(或者-如果先前已剪裁过张量,则剪裁张量的其余未剪裁部分)。 这将是`PRUNING_TYPE='unstructured'`,因为它作用于层中的单个连接,而不作用于整个单元/通道(`'structured'`),或作用于不同的参数(`'global'`)。 + +```py +class FooBarPruningMethod(prune.BasePruningMethod): + """Prune every other entry in a tensor + """ + PRUNING_TYPE = 'unstructured' + + def compute_mask(self, t, default_mask): + mask = default_mask.clone() + mask.view(-1)[::2] = 0 + return mask + +``` + +现在,要将其应用于`nn.Module`中的参数,还应该提供一个简单的函数来实例化该方法并将其应用。 + +```py +def foobar_unstructured(module, name): + """Prunes tensor corresponding to parameter called `name` in `module` + by removing every other entry in the tensors. + Modifies module in place (and also return the modified module) + by: + 1) adding a named buffer called `name+'_mask'` corresponding to the + binary mask applied to the parameter `name` by the pruning method. + The parameter `name` is replaced by its pruned version, while the + original (unpruned) parameter is stored in a new parameter named + `name+'_orig'`. + + Args: + module (nn.Module): module containing the tensor to prune + name (string): parameter name within `module` on which pruning + will act. + + Returns: + module (nn.Module): modified (i.e. pruned) version of the input + module + + Examples: + >>> m = nn.Linear(3, 4) + >>> foobar_unstructured(m, name='bias') + """ + FooBarPruningMethod.apply(module, name) + return module + +``` + +试试吧! + +```py +model = LeNet() +foobar_unstructured(model.fc3, name='bias') + +print(model.fc3.bias_mask) + +``` + +出: + +```py +tensor([0., 1., 0., 1., 0., 1., 0., 1., 0., 1.]) + +``` + +**脚本的总运行时间**:(0 分钟 0.135 秒) + +[下载 Python 源码:`pruning_tutorial.py`](../_downloads/8eb4a30bf66c6a1a0d1faba246c07bb3/pruning_tutorial.py) + +[下载 Jupyter 笔记本:`pruning_tutorial.ipynb`](../_downloads/f40ae04715cdb214ecba048c12f8dddf/pruning_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/55.md b/pytorch/官方教程/55.md new file mode 100644 index 00000000..ad495c50 --- /dev/null +++ b/pytorch/官方教程/55.md @@ -0,0 +1,398 @@ +# LSTM 单词语言模型上的动态量化(beta) + +> 原文: + +**作者**: [James Reed](https://github.com/jamesr66a) + +**编辑**:[Seth Weidman](https://github.com/SethHWeidman/) + +## 简介 + +量化涉及将模型的权重和激活从`float`转换为`int`,这可以导致模型尺寸更小,推断速度更快,而对准确率的影响很小。 + +在本教程中,我们将最简单的量化形式-[动态量化](https://pytorch.org/docs/stable/quantization.html#torch.quantization.quantize_dynamic)应用于基于 LSTM 的下一个单词预测模型,紧紧遵循 PyTorch 示例中的[单词语言模型](https://github.com/pytorch/examples/tree/master/word_language_model) 。 + +```py +# imports +import os +from io import open +import time + +import torch +import torch.nn as nn +import torch.nn.functional as F + +``` + +## 1.定义模型 + +在这里,我们根据词语言模型示例中的[模型](https://github.com/pytorch/examples/blob/master/word_language_model/model.py)定义 LSTM 模型架构。 + +```py +class LSTMModel(nn.Module): + """Container module with an encoder, a recurrent module, and a decoder.""" + + def __init__(self, ntoken, ninp, nhid, nlayers, dropout=0.5): + super(LSTMModel, self).__init__() + self.drop = nn.Dropout(dropout) + self.encoder = nn.Embedding(ntoken, ninp) + self.rnn = nn.LSTM(ninp, nhid, nlayers, dropout=dropout) + self.decoder = nn.Linear(nhid, ntoken) + + self.init_weights() + + self.nhid = nhid + self.nlayers = nlayers + + def init_weights(self): + initrange = 0.1 + self.encoder.weight.data.uniform_(-initrange, initrange) + self.decoder.bias.data.zero_() + self.decoder.weight.data.uniform_(-initrange, initrange) + + def forward(self, input, hidden): + emb = self.drop(self.encoder(input)) + output, hidden = self.rnn(emb, hidden) + output = self.drop(output) + decoded = self.decoder(output) + return decoded, hidden + + def init_hidden(self, bsz): + weight = next(self.parameters()) + return (weight.new_zeros(self.nlayers, bsz, self.nhid), + weight.new_zeros(self.nlayers, bsz, self.nhid)) + +``` + +## 2.加载文本数据 + +接下来,我们再次根据单词模型示例对[预处理](https://github.com/pytorch/examples/blob/master/word_language_model/data.py),将 [Wikitext-2 数据集](https://www.google.com/search?q=wikitext+2+data)加载到语料库中。 + +```py +class Dictionary(object): + def __init__(self): + self.word2idx = {} + self.idx2word = [] + + def add_word(self, word): + if word not in self.word2idx: + self.idx2word.append(word) + self.word2idx[word] = len(self.idx2word) - 1 + return self.word2idx[word] + + def __len__(self): + return len(self.idx2word) + +class Corpus(object): + def __init__(self, path): + self.dictionary = Dictionary() + self.train = self.tokenize(os.path.join(path, 'train.txt')) + self.valid = self.tokenize(os.path.join(path, 'valid.txt')) + self.test = self.tokenize(os.path.join(path, 'test.txt')) + + def tokenize(self, path): + """Tokenizes a text file.""" + assert os.path.exists(path) + # Add words to the dictionary + with open(path, 'r', encoding="utf8") as f: + for line in f: + words = line.split() + [''] + for word in words: + self.dictionary.add_word(word) + + # Tokenize file content + with open(path, 'r', encoding="utf8") as f: + idss = [] + for line in f: + words = line.split() + [''] + ids = [] + for word in words: + ids.append(self.dictionary.word2idx[word]) + idss.append(torch.tensor(ids).type(torch.int64)) + ids = torch.cat(idss) + + return ids + +model_data_filepath = 'data/' + +corpus = Corpus(model_data_filepath + 'wikitext-2') + +``` + +## 3.加载预先训练的模型 + +这是一本有关动态量化的教程,这是在训练模型后应用的一种量化技术。 因此,我们将简单地将一些预训练的权重加载到此模型架构中; 这些权重是通过使用单词语言模型示例中的默认设置训练五个周期而获得的。 + +```py +ntokens = len(corpus.dictionary) + +model = LSTMModel( + ntoken = ntokens, + ninp = 512, + nhid = 256, + nlayers = 5, +) + +model.load_state_dict( + torch.load( + model_data_filepath + 'word_language_model_quantize.pth', + map_location=torch.device('cpu') + ) + ) + +model.eval() +print(model) + +``` + +出: + +```py +LSTMModel( + (drop): Dropout(p=0.5, inplace=False) + (encoder): Embedding(33278, 512) + (rnn): LSTM(512, 256, num_layers=5, dropout=0.5) + (decoder): Linear(in_features=256, out_features=33278, bias=True) +) + +``` + +现在,我们生成一些文本以确保预先训练的模型能够正常工作-与以前类似,我们在此处遵循 + +```py +input_ = torch.randint(ntokens, (1, 1), dtype=torch.long) +hidden = model.init_hidden(1) +temperature = 1.0 +num_words = 1000 + +with open(model_data_filepath + 'out.txt', 'w') as outf: + with torch.no_grad(): # no tracking history + for i in range(num_words): + output, hidden = model(input_, hidden) + word_weights = output.squeeze().div(temperature).exp().cpu() + word_idx = torch.multinomial(word_weights, 1)[0] + input_.fill_(word_idx) + + word = corpus.dictionary.idx2word[word_idx] + + outf.write(str(word.encode('utf-8')) + ('\n' if i % 20 == 19 else ' ')) + + if i % 100 == 0: + print('| Generated {}/{} words'.format(i, 1000)) + +with open(model_data_filepath + 'out.txt', 'r') as outf: + all_output = outf.read() + print(all_output) + +``` + +出: + +```py +| Generated 0/1000 words +| Generated 100/1000 words +| Generated 200/1000 words +| Generated 300/1000 words +| Generated 400/1000 words +| Generated 500/1000 words +| Generated 600/1000 words +| Generated 700/1000 words +| Generated 800/1000 words +| Generated 900/1000 words +b'broadcaster' b'good' b',' b'which' b'provided' b'for' b'a' b'vignettes' b'socially' b'and' b'the' b'FIA' b"'s" b'ad' b'.' b'The' b'state' b'into' b'this' b'position' +b'is' b'in' b'account' b'of' b'a' b'wide' b'Domonia' b'' b',' b'fallen' b'to' b'for' b'the' b'types' b'of' b'' b'developers' b'being' b'entertaining' b'.' +b'' b'The' b'Claus' b'II' b'(' b'The' b'Book' b'of' b'Karnataka' b',' b'2' b'/' b'10' b')' b'was' b'released' b'by' b'British' b'@-@' b'Irish' +b'ruler' b'arriving' b'on' b'the' b'winter' b'of' b'its' b'championship' b'orbit' b'.' b'In' b'early' b'spring' b'roles' b'dismay' b'when' b'he' b'replaced' b'by' b'a' +b'religious' b'park' b',' b'when' b'it' b'features' b'flowers' b'they' b'do' b'populist' b'.' b'temperatures' b'attempted' b'to' b'have' b'trouble' b'met' b',' b'' b',' +b'and' b'karaoke' b'leads' b'to' b'some' b'return' b'up' b'as' b'or' b'seated' b'.' b'The' b'remainder' b'of' b'w' b'voltage' b'contains' b'Allah' b'in' b'the' +b'series' b'to' b'infiltrate' b'disappeared' b'.' b'Though' b'it' b'comes' b'into' b'his' b'Shinnok' b"'s" b'history' b',' b'they' b'may' b'sometimes' b'7' b'@-@' b'April' +b',' b'roughly' b'7' b'%' b'of' b'50' b'mph' b'(' b'4' b'@.@' b'8' b'in' b')' b'while' b'males' b'have' b'put' b'except' b'far' b'as' +b'alkaline' b'@-@' b'up' b'.' b'' b'Electrical' b'medical' b'rings' b'were' b'always' b'published' b'.' b'' b'Based' b'on' b'2' b'November' b',' b'Idaho' b'can' +b'be' b'estimated' b'cooking' b'and' b'' b',' b'while' b'no' b',' b'thin' b'drugs' b'was' b'poor' b'to' b'each' b'area' b'.' b'It' b'has' b'not' +b'campaigned' b'those' b'of' b'the' b'most' b'potent' b'population' b'of' b'leaves' b'in' b'all' b'condition' b',' b'because' b'they' b'were' b'forced' b'to' b'die' b'in' +b'bhandara' b'' b'that' b'culture' b'.' b'Almost' b'a' b'prose' b'plan' b',' b'there' b'have' b'been' b'only' b'clear' b',' b'it' b'occurs' b'.' b'' +b'The' b'kakapo' b'was' b'interpreted' b'on' b'1998' b'from' b'1955' b'and' b'played' b'in' b'' b',' b'Western' b'Asia' b'on' b'0' b'August' b'1966' b',' +b'with' b'an' b'additional' b'population' b'that' b'Samuel' b'solemnly' b',' b'Chapman' b'sponsored' b'after' b'a' b'few' b'years' b'.' b'In' b'1990' b',' b'prominent' b'areas' +b'believe' b'that' b'as' b'being' b'an' b'rural' b'planet' b',' b'they' b'is' b'neglected' b'as' b'to' b'be' b'changed' b'.' b'Congress' b'This' b'well' b'"' +b'was' b'run' b'by' b'' b',' b'Waldemar' b'Greenwood' b'.' b'170' b'have' b'just' b'in' b'place' b',' b'he' b'overruled' b'.' b'The' b'1966' b'race' +b'is' b'a' b'embodies' b'state' b'of' b'Viking' b'or' b'most' b'generation' b',' b'not' b'in' b'the' b'codes' b'of' b'all' b'other' b'alignment' b'musical' b'politicians' +b'.' b'No' b'system' b'have' b'participated' b'on' b'3' b'to' b'9' b'%' b'of' b'any' b'urine' b',' b'with' b'both' b'drawings' b'and' b'significantly' b'towards' +b'his' b'deteriorating' b'and' b'poverty' b'.' b'As' b'a' b'rust' b',' b'contains' b'other' b'compositions' b'that' b'must' b'be' b'beneficial' b'by' b'overnight' b'or' b'fluid' +b',' b'u' b'organizations' b'can' b'seek' b'mild' b'late' b'down' b'on' b'a' b'broadside' b'and' b'leads' b'to' b'its' b'cycle' b'.' b'For' b'example' b',' +b'1137' b',' b'snowmelt' b'and' b'' b'\xe2\x80\x94' b'a' b'variety' b'of' b'dealt' b';' b'Species' b'(' b'with' b'a' b'reduction' b'of' b'prohibitions' b')' b',' +b'' b'exploration' b',' b'' b'an' b'fuel' b'eye' b'of' b'purple' b'trees' b',' b'was' b'shown' b'west' b'.' b'chased' b'Jack' b'of' b'claws' b',' +b'his' b'vertex' b'states' b'that' b'they' b',' b'in' b'1922' b',' b'was' b'killed' b'.' b'' b'There' b'have' b'been' b'official' b'concerns' b'of' b'Boat' +b'Kerry' b'including' b'L\xc3\xaa' b'\xe3\x80\x89' b'and' b'' b'A' b'Forest' b',' b'"' b'' b',' b'because' b'' b',' b'and' b'sometimes' b'encounters' b'like' b'I' +b"'ve" b'been' b'' b'.' b'"' b'' b'Hunter' b'pathway' b'writes' b'it' b'entering' b'the' b'second' b'.' b'The' b'kakapo' b'is' b'gems' b'used' b'after' +b'died' b'from' b'two' b'games' b'in' b'six' b'' b',' b'her' b'feature' b'and' b'called' b'"' b'mercenaries' b'"' b',' b'which' b'supported' b'by' b'the' +b'Selective' b'Race' b'.' b'"' b'' b'Bono' b'Dutch' b'struggles' b'to' b'the' b'species' b'' b',' b'especially' b'crusaders' b'I' b'lives' b'process' b',' b'but' +b'Constantin' b'approximate' b'and' b'character' b'or' b'so' b'.' b'There' b'have' b'numerous' b'pale' b'dioceses' b'as' b'a' b'resistant' b';' b'the' b'Inn' b'Comic' b'@-@' +b'white' b'individuals' b',' b'its' b'flat' b',' b'' b'and' b'correct' b',' b'in' b'which' b'they' b'felt' b'.' b'In' b'the' b'arms' b',' b'the' +b'original' b'occasion' b'about' b'Spanish' b'sites' b'all' b'(' b'millionaire' b'lay' b';' b'or' b'160' b'@-@' b'mosquitoes' b')' b'v' b'' b'(' b'c' b')' +b'.' b'The' b'bird' b'is' b'extremely' b'paved' b',' b'and' b'they' b'are' b'claimed' b'to' b'wedding' b'the' b'' b'of' b'Excellence' b',' b'and' b'an' +b'extinct' b'composite' b',' b'cute' b'outside' b'' b'.' b'This' b'may' b'be' b'seen' b'by' b'the' b'Seer' b'that' b'Tempest' b'"' b'comes' b'"' b'over' +b'a' b'bright' b'judicial' b'guitar' b',' b'which' b'describes' b',' b'and' b'tend' b'to' b'be' b'seen' b'.' b'' b'' b'=' b'=' b'Conservation' b'for' +b'contraception' b'=' b'=' b'' b'' b'Grieco' b'Island' b'is' b'a' b'eventually' b'scale' b'word' b'to' b'a' b'tropical' b'storm' b',' b'based' b'in' b'a' +b'pre' b'\xe2\x80\x93' b'9' b'lead' b',' b'a' b'forces' b'after' b'a' b'additional' b',' b'grey' b'substance' b',' b'Metro' b',' b'background' b',' b'and' b'cooperate' +b'with' b'its' b'overly' b'overview' b',' b'so' b'the' b'heaviest' b'route' b',' b'and' b'\xc2\xb3' b'.' b'portion' b'may' b'occur' b'this' b'other' b'up' b'an' +b'' b'break' b',' b'then' b'or' b'deep' b'distinct' b'or' b'female' b'offspring' b',' b'but' b'even' b'understand' b'.' b'Following' b'God' b'(' b'no' b'nervous' +b'image' b'from' b'complaints' b')' b',' b'the' b'player' b'represents' b'three' b'or' b'over' b'9' b'\xc2\xb0' b'large' b'(' b'five' b'weeks' b'of' b'many' b'cats' +b')' b',' b'as' b'it' b'targets' b'for' b'the' b'second' b'female' b'together' b'.' b'159' b',' b'it' b'also' b'spend' b'bold' b'markets' b'and' b'its' +b'players' b'powers' b',' b'dubbed' b'those' b'of' b'lengths' b'.' b'Most' b'are' b'arrow' b'could' b'be' b'noticed' b'involving' b'they' b'fall' b'.' b'On' b'FAU' +b"'s" b'only' b'lifetime' b'she' b'treated' b'or' b'their' b'apparent' b'soaring' b'proposition' b'has' b'5th' b'of' b'those' b'eye' b',' b'but' b'knows' b'in' b'a' +b'' b'Network' b';' b'which' b'of' b'that' b'reality' b'or' b'artificial' b'when' b'struggling' b'Bungie' b'is' b'successful' b'.' b'The' b'' b'sound' b'of' b'frontier' +b'ahead' b'for' b'damage' b'came' b'on' b',' b'so' b'the' b'first' b'series' b'funded' b'by' b'its' b'bowls' b',' b'a' b'chant' b'.' b'They' b'may' +b'be' b'used' b'Pongsak' b'or' b'occasionally' b'protected' b'them' b'.' b'Fingal' b'cylindrical' b'conspired' b'on' b'a' b'variety' b'of' b'prey' b',' b'' b',' b'Zach' +b',' b'and' b'young' b'possessing' b'Westland' b'valleys' b'.' b'Otherwise' b',' b'I' b'do' b'at' b'them' b'in' b'first' b'@-@' b'season' b'woodland' b',' b'where' +b'they' b'weighed' b'them' b'to' b'correct' b'a' b'list' b'of' b'other' b'birds' b'.' b'Another' b'theme' b'where' b'or' b',' b'it' b'is' b'a' b'appropriate' +b'source' b',' b'this' b'competed' b'in' b'integral' b'Waiouru' b'alone' b',' b'the' b'pathways' b'under' b'Aravind' b',' b'and' b'others' b',' b'instead' b'of' b'westward' +b',' b'as' b'they' b'are' b'quarters' b'and' b'caused' b'in' b'males' b'.' b'Once' b'selective' b'centered' b',' b'they' b'threats' b'were' b'Zuniceratops' b'.' b'Although' +b'the' b'most' b'spots' b'replication' b'became' b'a' b'fragile' b'pointer' b'(' b'a' b'pair' b'of' b'' b')' b',' b'strongly' b'"' b'mammals' b'"' b',' +b'which' b'give' b'Powderfinger' b'to' b'persecution' b'.' b'Other' b'conifers' b'but' b'even' b'only' b'swallow' b'so' b'every' b'symbols' b'of' b'Manders' b',' b'in' b'massive' + +``` + +它不是 GPT-2,但看起来该模型已开始学习语言结构! + +我们几乎准备好演示动态量化。 我们只需要定义一些辅助函数: + +```py +bptt = 25 +criterion = nn.CrossEntropyLoss() +eval_batch_size = 1 + +# create test data set +def batchify(data, bsz): + # Work out how cleanly we can divide the dataset into bsz parts. + nbatch = data.size(0) // bsz + # Trim off any extra elements that wouldn't cleanly fit (remainders). + data = data.narrow(0, 0, nbatch * bsz) + # Evenly divide the data across the bsz batches. + return data.view(bsz, -1).t().contiguous() + +test_data = batchify(corpus.test, eval_batch_size) + +# Evaluation functions +def get_batch(source, i): + seq_len = min(bptt, len(source) - 1 - i) + data = source[i:i+seq_len] + target = source[i+1:i+1+seq_len].reshape(-1) + return data, target + +def repackage_hidden(h): + """Wraps hidden states in new Tensors, to detach them from their history.""" + + if isinstance(h, torch.Tensor): + return h.detach() + else: + return tuple(repackage_hidden(v) for v in h) + +def evaluate(model_, data_source): + # Turn on evaluation mode which disables dropout. + model_.eval() + total_loss = 0. + hidden = model_.init_hidden(eval_batch_size) + with torch.no_grad(): + for i in range(0, data_source.size(0) - 1, bptt): + data, targets = get_batch(data_source, i) + output, hidden = model_(data, hidden) + hidden = repackage_hidden(hidden) + output_flat = output.view(-1, ntokens) + total_loss += len(data) * criterion(output_flat, targets).item() + return total_loss / (len(data_source) - 1) + +``` + +## 4.测试动态量化 + +最后,我们可以在模型上调用`torch.quantization.quantize_dynamic`! 特别, + +* 我们指定我们希望对模型中的`nn.LSTM`和`nn.Linear`模块进行量化 +* 我们指定希望将权重转换为`int8`值 + +```py +import torch.quantization + +quantized_model = torch.quantization.quantize_dynamic( + model, {nn.LSTM, nn.Linear}, dtype=torch.qint8 +) +print(quantized_model) + +``` + +出: + +```py +LSTMModel( + (drop): Dropout(p=0.5, inplace=False) + (encoder): Embedding(33278, 512) + (rnn): DynamicQuantizedLSTM(512, 256, num_layers=5, dropout=0.5) + (decoder): DynamicQuantizedLinear(in_features=256, out_features=33278, dtype=torch.qint8, qscheme=torch.per_tensor_affine) +) + +``` + +该模型看起来相同; 这对我们有什么好处? 首先,我们看到模型尺寸显着减小: + +```py +def print_size_of_model(model): + torch.save(model.state_dict(), "temp.p") + print('Size (MB):', os.path.getsize("temp.p")/1e6) + os.remove('temp.p') + +print_size_of_model(model) +print_size_of_model(quantized_model) + +``` + +出: + +```py +Size (MB): 113.945726 +Size (MB): 79.739984 + +``` + +其次,我们看到了更快的推理时间,而评估损失没有差异: + +注意:由于量化模型运行单线程,因此用于单线程比较的线程数为 1。 + +```py +torch.set_num_threads(1) + +def time_model_evaluation(model, test_data): + s = time.time() + loss = evaluate(model, test_data) + elapsed = time.time() - s + print('''loss: {0:.3f}\nelapsed time (seconds): {1:.1f}'''.format(loss, elapsed)) + +time_model_evaluation(model, test_data) +time_model_evaluation(quantized_model, test_data) + +``` + +出: + +```py +loss: 5.167 +elapsed time (seconds): 251.3 +loss: 5.168 +elapsed time (seconds): 166.3 + +``` + +在没有量化的情况下在 MacBook Pro 上本地运行此操作,推理大约需要 200 秒,而量化则只需大约 100 秒。 + +## 总结 + +动态量化可能是减小模型大小的简单方法,而对精度的影响有限。 + +谢谢阅读! 与往常一样,我们欢迎您提供反馈,因此,如果有任何问题,[请在这里创建一个 ISSUE](https://github.com/pytorch/pytorch/issues)。 + +**脚本的总运行时间**:(7 分钟 3.126 秒) + +[下载 Python 源码:`dynamic_quantization_tutorial.py`](../_downloads/3fa656e39c210acc81b96b164a3da032/dynamic_quantization_tutorial.py) + +[下载 Jupyter 笔记本:`dynamic_quantization_tutorial.ipynb`](../_downloads/9387e74b1a614d9ed5642654e06b1728/dynamic_quantization_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/56.md b/pytorch/官方教程/56.md new file mode 100644 index 00000000..9d12bb92 --- /dev/null +++ b/pytorch/官方教程/56.md @@ -0,0 +1,444 @@ +# BERT 上的动态量化(Beta) + +> 原文: + +小费 + +为了充分利用本教程,我们建议使用此 [Colab 版本](https://colab.research.google.com/github/pytorch/tutorials/blob/gh-pages/_downloads/dynamic_quantization_bert_tutorial.ipynb)。 这将使您可以尝试以下信息。 + +**作者**:[Jianyu Huang](https://github.com/jianyuh) + +**审核**: [Raghuraman Krishnamoorthi](https://github.com/raghuramank100) + +**编辑**:[Jessica Lin](https://github.com/jlin27) + +## 简介 + +在本教程中,我们将动态量化应用在 BERT 模型上,紧跟 [HuggingFace 转换器示例](https://github.com/huggingface/transformers)中的 BERT 模型。 通过这一循序渐进的旅程,我们将演示如何将著名的 BERT 等最新模型转换为动态量化模型。 + +* BERT,或者说转换器的双向嵌入表示,是一种预训练语言表示的新方法,它可以在许多常见的自然语言处理(NLP)任务(例如问题解答,文本分类, 和别的。 [可以在此处找到](https://arxiv.org/pdf/1810.04805.pdf)。 +* PyTorch 中的动态量化支持将浮点模型转换为具有静态`int8`或`float16`数据类型的权重和动态量化激活的量化模型。 当权重量化为`int8`时,激活(每批)动态量化为`int8`。 在 PyTorch 中,我们有[`torch.quantization.quantize_dynamic` API](https://pytorch.org/docs/stable/quantization.html#torch.quantization.quantize_dynamic),该 API 用仅动态权重的量化版本替换了指定的模块,并输出了量化模型。 +* 我们在[通用语言理解评估基准(GLUE)](https://gluebenchmark.com/)中演示了 [Microsoft Research Paraphrase 语料库(MRPC)任务](https://www.microsoft.com/en-us/download/details.aspx?id=52398)的准确率和推理表现结果。 MRPC(Dolan 和 Brockett,2005 年)是从在线新闻源中自动提取的句子对的语料库,带有人工标注,说明句子中的句子在语义上是否等效。 由于类别不平衡(正向为 68%,负向为 32%),我们遵循常规做法并报告 [F1 得分](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.f1_score.html)。 MRPC 是用于语言对分类的常见 NLP 任务,如下所示。 + +![../_img/bert.png](img/b43b70d8a6eef9ea4f75867b5e83b483.png) + +## 1.设置 + +### 1.1 安装 PyTorch 和 HuggingFace 转换器 + +要开始本教程,首先请遵循 [PyTorch](https://github.com/pytorch/pytorch/#installation) 和 [HuggingFace Github 仓库](https://github.com/huggingface/transformers#installation)中的安装说明。 此外,我们还将安装 [scikit-learn](https://github.com/scikit-learn/scikit-learn) 包,因为我们将重复使用其内置的 F1 分数计算助手函数。 + +```py +pip install sklearn +pip install transformers + +``` + +由于我们将使用 PyTorch 的 Beta 版部分,因此建议安装最新版本的 Torch 和`tochvision`。[ 您可以在此处找到有关本地安装的最新说明](https://pytorch.org/get-started/locally/)。 例如,要在 Mac 上安装: + +```py +yes y | pip uninstall torch tochvision +yes y | pip install --pre torch -f https://download.pytorch.org/whl/nightly/cu101/torch_nightly.html + +``` + +### 1.2 导入必要的模块 + +在这一步中,我们将导入本教程所需的 Python 模块。 + +```py +from __future__ import absolute_import, division, print_function + +import logging +import numpy as np +import os +import random +import sys +import time +import torch + +from argparse import Namespace +from torch.utils.data import (DataLoader, RandomSampler, SequentialSampler, + TensorDataset) +from tqdm import tqdm +from transformers import (BertConfig, BertForSequenceClassification, BertTokenizer,) +from transformers import glue_compute_metrics as compute_metrics +from transformers import glue_output_modes as output_modes +from transformers import glue_processors as processors +from transformers import glue_convert_examples_to_features as convert_examples_to_features + +# Setup logging +logger = logging.getLogger(__name__) +logging.basicConfig(format = '%(asctime)s - %(levelname)s - %(name)s - %(message)s', + datefmt = '%m/%d/%Y %H:%M:%S', + level = logging.WARN) + +logging.getLogger("transformers.modeling_utils").setLevel( + logging.WARN) # Reduce logging + +print(torch.__version__) + +``` + +我们设置线程数以比较 FP32 和 INT8 性能之间的单线程性能。 在本教程的最后,用户可以通过使用右侧并行后端构建 PyTorch 来设置其他线程数量。 + +```py +torch.set_num_threads(1) +print(torch.__config__.parallel_info()) + +``` + +### 1.3 了解辅助函数 + +助手函数内置在转换器库中。 我们主要使用以下辅助函数:一个用于将文本示例转换为特征向量的函数; 另一个用于测量预测结果的 F1 分数。 + +[`gum_convert_examples_to_features`](https://github.com/huggingface/transformers/blob/master/transformers/data/processors/glue.py)函数将文本转换为输入特征: + +* 标记输入序列; +* 在开头插入`[CLS]`; +* 在第一句和第二句之间并在最后插入`[SEP]`; +* 生成标记类型 ID,以指示标记是属于第一序列还是第二序列。 + +[`gum_compute_metrics`](https://github.com/huggingface/transformers/blob/master/transformers/data/processors/glue.py)函数的计算指标为 [F1 得分](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.f1_score.html),可以将其解释为精度和召回率的加权平均值,其中 F1 得分最佳值为 1,最差值为 0。精度和召回率对 F1 得分的相对贡献相等。 + +* F1 分数的公式为: + +![](img/tex56-1.gif) + +### 1.4 下载数据集 + +在运行 MRPC 任务之前,我们通过运行[此脚本](https://gist.github.com/W4ngatang/60c2bdb54d156a41194446737ce03e2e)并下载 [GLUE 数据](https://gluebenchmark.com/tasks)并将其解压缩到目录`glue_data`中。 + +```py +python download_glue_data.py --data_dir='glue_data' --tasks='MRPC' + +``` + +## 2.微调 BERT 模型 + +BERT 的精神是预训练语言表示形式,然后以最小的任务相关参数微调各种任务上的深层双向表示形式,并获得最新的结果。 在本教程中,我们将专注于对预训练的 BERT 模型进行微调,以对 MRPC 任务上的语义等效句子对进行分类。 + +要为 MRPC 任务微调预训练的 BERT 模型(HuggingFace 转换器中的`bert-base-uncased`模型),可以按照[示例](https://github.com/huggingface/transformers/tree/master/examples#mrpc)中的命令进行操作: + +```py +export GLUE_DIR=./glue_data +export TASK_NAME=MRPC +export OUT_DIR=./$TASK_NAME/ +python ./run_glue.py \ + --model_type bert \ + --model_name_or_path bert-base-uncased \ + --task_name $TASK_NAME \ + --do_train \ + --do_eval \ + --do_lower_case \ + --data_dir $GLUE_DIR/$TASK_NAME \ + --max_seq_length 128 \ + --per_gpu_eval_batch_size=8 \ + --per_gpu_train_batch_size=8 \ + --learning_rate 2e-5 \ + --num_train_epochs 3.0 \ + --save_steps 100000 \ + --output_dir $OUT_DIR + +``` + +[我们在此处为 MRPC 任务提供了经过微调的 BERT 模型](https://download.pytorch.org/tutorial/MRPC.zip)。 为了节省时间,您可以将模型文件(约 400 MB)直接下载到本地文件夹`$OUT_DIR`中。 + +### 2.1 设置全局配置 + +在这里,我们设置了用于在动态量化之前和之后评估微调 BERT 模型的全局配置。 + +```py +configs = Namespace() + +# The output directory for the fine-tuned model, $OUT_DIR. +configs.output_dir = "./MRPC/" + +# The data directory for the MRPC task in the GLUE benchmark, $GLUE_DIR/$TASK_NAME. +configs.data_dir = "./glue_data/MRPC" + +# The model name or path for the pre-trained model. +configs.model_name_or_path = "bert-base-uncased" +# The maximum length of an input sequence +configs.max_seq_length = 128 + +# Prepare GLUE task. +configs.task_name = "MRPC".lower() +configs.processor = processors[configs.task_name]() +configs.output_mode = output_modes[configs.task_name] +configs.label_list = configs.processor.get_labels() +configs.model_type = "bert".lower() +configs.do_lower_case = True + +# Set the device, batch size, topology, and caching flags. +configs.device = "cpu" +configs.per_gpu_eval_batch_size = 8 +configs.n_gpu = 0 +configs.local_rank = -1 +configs.overwrite_cache = False + +# Set random seed for reproducibility. +def set_seed(seed): + random.seed(seed) + np.random.seed(seed) + torch.manual_seed(seed) +set_seed(42) + +``` + +### 2.2 加载经过微调的 BERT 模型 + +我们从`configs.output_dir`加载标记器和经过微调的 BERT 序列分类器模型(FP32)。 + +```py +tokenizer = BertTokenizer.from_pretrained( + configs.output_dir, do_lower_case=configs.do_lower_case) + +model = BertForSequenceClassification.from_pretrained(configs.output_dir) +model.to(configs.device) + +``` + +### 2.3 定义分词和评估函数 + +我们重用了 [Huggingface](https://github.com/huggingface/transformers/blob/master/examples/run_glue.py) 中的分词和评估函数。 + +```py +# coding=utf-8 +# Copyright 2018 The Google AI Language Team Authors and The HuggingFace Inc. team. +# Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +def evaluate(args, model, tokenizer, prefix=""): + # Loop to handle MNLI double evaluation (matched, mis-matched) + eval_task_names = ("mnli", "mnli-mm") if args.task_name == "mnli" else (args.task_name,) + eval_outputs_dirs = (args.output_dir, args.output_dir + '-MM') if args.task_name == "mnli" else (args.output_dir,) + + results = {} + for eval_task, eval_output_dir in zip(eval_task_names, eval_outputs_dirs): + eval_dataset = load_and_cache_examples(args, eval_task, tokenizer, evaluate=True) + + if not os.path.exists(eval_output_dir) and args.local_rank in [-1, 0]: + os.makedirs(eval_output_dir) + + args.eval_batch_size = args.per_gpu_eval_batch_size * max(1, args.n_gpu) + # Note that DistributedSampler samples randomly + eval_sampler = SequentialSampler(eval_dataset) if args.local_rank == -1 else DistributedSampler(eval_dataset) + eval_dataloader = DataLoader(eval_dataset, sampler=eval_sampler, batch_size=args.eval_batch_size) + + # multi-gpu eval + if args.n_gpu > 1: + model = torch.nn.DataParallel(model) + + # Eval! + logger.info("***** Running evaluation {} *****".format(prefix)) + logger.info(" Num examples = %d", len(eval_dataset)) + logger.info(" Batch size = %d", args.eval_batch_size) + eval_loss = 0.0 + nb_eval_steps = 0 + preds = None + out_label_ids = None + for batch in tqdm(eval_dataloader, desc="Evaluating"): + model.eval() + batch = tuple(t.to(args.device) for t in batch) + + with torch.no_grad(): + inputs = {'input_ids': batch[0], + 'attention_mask': batch[1], + 'labels': batch[3]} + if args.model_type != 'distilbert': + inputs['token_type_ids'] = batch[2] if args.model_type in ['bert', 'xlnet'] else None # XLM, DistilBERT and RoBERTa don't use segment_ids + outputs = model(**inputs) + tmp_eval_loss, logits = outputs[:2] + + eval_loss += tmp_eval_loss.mean().item() + nb_eval_steps += 1 + if preds is None: + preds = logits.detach().cpu().numpy() + out_label_ids = inputs['labels'].detach().cpu().numpy() + else: + preds = np.append(preds, logits.detach().cpu().numpy(), axis=0) + out_label_ids = np.append(out_label_ids, inputs['labels'].detach().cpu().numpy(), axis=0) + + eval_loss = eval_loss / nb_eval_steps + if args.output_mode == "classification": + preds = np.argmax(preds, axis=1) + elif args.output_mode == "regression": + preds = np.squeeze(preds) + result = compute_metrics(eval_task, preds, out_label_ids) + results.update(result) + + output_eval_file = os.path.join(eval_output_dir, prefix, "eval_results.txt") + with open(output_eval_file, "w") as writer: + logger.info("***** Eval results {} *****".format(prefix)) + for key in sorted(result.keys()): + logger.info(" %s = %s", key, str(result[key])) + writer.write("%s = %s\n" % (key, str(result[key]))) + + return results + +def load_and_cache_examples(args, task, tokenizer, evaluate=False): + if args.local_rank not in [-1, 0] and not evaluate: + torch.distributed.barrier() # Make sure only the first process in distributed training process the dataset, and the others will use the cache + + processor = processors[task]() + output_mode = output_modes[task] + # Load data features from cache or dataset file + cached_features_file = os.path.join(args.data_dir, 'cached_{}_{}_{}_{}'.format( + 'dev' if evaluate else 'train', + list(filter(None, args.model_name_or_path.split('/'))).pop(), + str(args.max_seq_length), + str(task))) + if os.path.exists(cached_features_file) and not args.overwrite_cache: + logger.info("Loading features from cached file %s", cached_features_file) + features = torch.load(cached_features_file) + else: + logger.info("Creating features from dataset file at %s", args.data_dir) + label_list = processor.get_labels() + if task in ['mnli', 'mnli-mm'] and args.model_type in ['roberta']: + # HACK(label indices are swapped in RoBERTa pretrained model) + label_list[1], label_list[2] = label_list[2], label_list[1] + examples = processor.get_dev_examples(args.data_dir) if evaluate else processor.get_train_examples(args.data_dir) + features = convert_examples_to_features(examples, + tokenizer, + label_list=label_list, + max_length=args.max_seq_length, + output_mode=output_mode, + pad_on_left=bool(args.model_type in ['xlnet']), # pad on the left for xlnet + pad_token=tokenizer.convert_tokens_to_ids([tokenizer.pad_token])[0], + pad_token_segment_id=4 if args.model_type in ['xlnet'] else 0, + ) + if args.local_rank in [-1, 0]: + logger.info("Saving features into cached file %s", cached_features_file) + torch.save(features, cached_features_file) + + if args.local_rank == 0 and not evaluate: + torch.distributed.barrier() # Make sure only the first process in distributed training process the dataset, and the others will use the cache + + # Convert to Tensors and build dataset + all_input_ids = torch.tensor([f.input_ids for f in features], dtype=torch.long) + all_attention_mask = torch.tensor([f.attention_mask for f in features], dtype=torch.long) + all_token_type_ids = torch.tensor([f.token_type_ids for f in features], dtype=torch.long) + if output_mode == "classification": + all_labels = torch.tensor([f.label for f in features], dtype=torch.long) + elif output_mode == "regression": + all_labels = torch.tensor([f.label for f in features], dtype=torch.float) + + dataset = TensorDataset(all_input_ids, all_attention_mask, all_token_type_ids, all_labels) + return dataset + +``` + +## 3.应用动态量化 + +我们在模型上调用`torch.quantization.quantize_dynamic`,将动态量化应用于 HuggingFace BERT 模型。 特别, + +* 我们指定要对模型中的`torch.nn.Linear`模块进行量化; +* 我们指定希望将权重转换为量化的`int8`值。 + +```py +quantized_model = torch.quantization.quantize_dynamic( + model, {torch.nn.Linear}, dtype=torch.qint8 +) +print(quantized_model) + +``` + +### 3.1 检查模型大小 + +首先,检查模型尺寸。 我们可以观察到模型大小的显着减小(FP32 总大小:438 MB; INT8 总大小:181 MB): + +```py +def print_size_of_model(model): + torch.save(model.state_dict(), "temp.p") + print('Size (MB):', os.path.getsize("temp.p")/1e6) + os.remove('temp.p') + +print_size_of_model(model) +print_size_of_model(quantized_model) + +``` + +本教程中使用的 BERT 模型(`bert-base-uncased`)的词汇量`V`为 30522。在嵌入量为 768 的情况下,单词嵌入表的总大小为`~4 (Bytes/FP32) * 30522 * 768 = 90 MB` 。 因此,借助量化,非嵌入表部分的模型大小从 350 MB(FP32 模型)减少到 90 MB(INT8 模型)。 + +### 3.2 评估推理准确率和时间 + +接下来,我们比较一下动态量化后原始 FP32 模型和 INT8 模型之间的推断时间以及评估精度。 + +```py +def time_model_evaluation(model, configs, tokenizer): + eval_start_time = time.time() + result = evaluate(configs, model, tokenizer, prefix="") + eval_end_time = time.time() + eval_duration_time = eval_end_time - eval_start_time + print(result) + print("Evaluate total time (seconds): {0:.1f}".format(eval_duration_time)) + +# Evaluate the original FP32 BERT model +time_model_evaluation(model, configs, tokenizer) + +# Evaluate the INT8 BERT model after the dynamic quantization +time_model_evaluation(quantized_model, configs, tokenizer) + +``` + +在 MacBook Pro 上本地运行此程序,无需进行量化,推理(对于 MRPC 数据集中的所有 408 个示例)大约需要 160 秒,而进行量化则只需大约 90 秒。 我们总结了在 Macbook Pro 上运行量化 BERT 模型推断的结果,如下所示: + +```py +| Prec | F1 score | Model Size | 1 thread | 4 threads | +| FP32 | 0.9019 | 438 MB | 160 sec | 85 sec | +| INT8 | 0.902 | 181 MB | 90 sec | 46 sec | + +``` + +在 MRPC 任务的微调 BERT 模型上应用训练后动态量化后,我们的 F1 分数准确率为 0.6%。 作为比较,在[最新论文](https://arxiv.org/pdf/1910.06188.pdf)(表 1)中,通过应用训练后动态量化,可以达到 0.8788;通过应用量化感知训练,可以达到 0.8956。 主要区别在于我们在 PyTorch 中支持非对称量化,而该论文仅支持对称量化。 + +请注意,在本教程中,为了进行单线程比较,我们将线程数设置为 1。 我们还为这些量化的 INT8 运算符支持运算内并行化。 用户现在可以通过`torch.set_num_threads(N)`设置多线程(`N`是内部运算并行线程的数量)。 启用帧内并行支持的一项初步要求是使用正确的[后端](https://pytorch.org/docs/stable/notes/cpu_threading_torchscript_inference.html#build-options)(例如 OpenMP,Native 或 TBB)构建 PyTorch。 您可以使用`torch.__config__.parallel_info()`检查并行化设置。 在使用 PyTorch 和本机后端进行并行化的同一台 MacBook Pro 上,我们可以花大约 46 秒的时间来处理 MRPC 数据集的评估。 + +### 3.3 序列化量化模型 + +跟踪模型后,我们可以使用`torch.jit.save`序列化并保存量化模型,以备将来使用。 + +```py +input_ids = ids_tensor([8, 128], 2) +token_type_ids = ids_tensor([8, 128], 2) +attention_mask = ids_tensor([8, 128], vocab_size=2) +dummy_input = (input_ids, attention_mask, token_type_ids) +traced_model = torch.jit.trace(quantized_model, dummy_input) +torch.jit.save(traced_model, "bert_traced_eager_quant.pt") + +``` + +要加载量化模型,我们可以使用`torch.jit.load` + +```py +loaded_quantized_model = torch.jit.load("bert_traced_eager_quant.pt") + +``` + +## 总结 + +在本教程中,我们演示了如何演示如何将 BERT 等著名的最新 NLP 模型转换为动态量化模型。 动态量化可以减小模型的大小,而对准确率的影响有限。 + +谢谢阅读! 与往常一样,我们欢迎您提供反馈,因此,如果有任何问题,[请在这里创建一个 ISSUE](https://github.com/pytorch/pytorch/issues)。 + +## 参考文献 + +```py +[1] J.Devlin, M. Chang, K. Lee and K. Toutanova, BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (2018). + +[2] HuggingFace Transformers. + +[3] O. Zafrir, G. Boudoukh, P. Izsak, and M. Wasserblat (2019). Q8BERT: Quantized 8bit BERT. +``` \ No newline at end of file diff --git a/pytorch/官方教程/57.md b/pytorch/官方教程/57.md new file mode 100644 index 00000000..4f3cd2bb --- /dev/null +++ b/pytorch/官方教程/57.md @@ -0,0 +1,813 @@ +# PyTorch 中使用 Eager 模式的静态量化(beta) + +> 原文: + +**作者**: [Raghuraman Krishnamoorthi](https://github.com/raghuramank100) + +**编辑**:[Seth Weidman](https://github.com/SethHWeidman/) + +本教程说明了如何进行训练后的静态量化,并说明了两种更先进的技术-每通道量化和量化感知训练-可以进一步提高模型的准确率。 请注意,目前仅支持 CPU 量化,因此在本教程中我们将不使用 GPU/CUDA。 + +在本教程结束时,您将看到 PyTorch 中的量化如何导致模型大小显着减小同时提高速度。 此外,[您将在此处看到如何轻松应用显示的一些高级量化技术](https://arxiv.org/abs/1806.08342),以使您的量化模型受到的准确率影响要小得多。 + +警告:我们使用了许多其他 PyTorch 仓库中的样板代码,例如,定义了`MobileNetV2`模型架构,定义了数据加载器等等。 我们当然鼓励您阅读它; 但是如果要使用量化功能,请随时跳到“ 4。 训练后静态量化”部分。 + +我们将从进行必要的导入开始: + +```py +import numpy as np +import torch +import torch.nn as nn +import torchvision +from torch.utils.data import DataLoader +from torchvision import datasets +import torchvision.transforms as transforms +import os +import time +import sys +import torch.quantization + +# # Setup warnings +import warnings +warnings.filterwarnings( + action='ignore', + category=DeprecationWarning, + module=r'.*' +) +warnings.filterwarnings( + action='default', + module=r'torch.quantization' +) + +# Specify random seed for repeatable results +torch.manual_seed(191009) + +``` + +## 1.模型架构 + +我们首先定义 MobileNetV2 模型架构,并进行了一些值得注意的修改以实现量化: + +* 用`nn.quantized.FloatFunctional`代替添加 +* 在网络的开头和结尾处插入`QuantStub`和`DeQuantStub`。 +* 用 ReLU 替换 ReLU6 + +注意:此代码取自[此处](https://github.com/pytorch/vision/blob/master/torchvision/models/mobilenet.py)。 + +```py +from torch.quantization import QuantStub, DeQuantStub + +def _make_divisible(v, divisor, min_value=None): + """ + This function is taken from the original tf repo. + It ensures that all layers have a channel number that is divisible by 8 + It can be seen here: + https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet/mobilenet.py + :param v: + :param divisor: + :param min_value: + :return: + """ + if min_value is None: + min_value = divisor + new_v = max(min_value, int(v + divisor / 2) // divisor * divisor) + # Make sure that round down does not go down by more than 10%. + if new_v < 0.9 * v: + new_v += divisor + return new_v + +class ConvBNReLU(nn.Sequential): + def __init__(self, in_planes, out_planes, kernel_size=3, stride=1, groups=1): + padding = (kernel_size - 1) // 2 + super(ConvBNReLU, self).__init__( + nn.Conv2d(in_planes, out_planes, kernel_size, stride, padding, groups=groups, bias=False), + nn.BatchNorm2d(out_planes, momentum=0.1), + # Replace with ReLU + nn.ReLU(inplace=False) + ) + +class InvertedResidual(nn.Module): + def __init__(self, inp, oup, stride, expand_ratio): + super(InvertedResidual, self).__init__() + self.stride = stride + assert stride in [1, 2] + + hidden_dim = int(round(inp * expand_ratio)) + self.use_res_connect = self.stride == 1 and inp == oup + + layers = [] + if expand_ratio != 1: + # pw + layers.append(ConvBNReLU(inp, hidden_dim, kernel_size=1)) + layers.extend([ + # dw + ConvBNReLU(hidden_dim, hidden_dim, stride=stride, groups=hidden_dim), + # pw-linear + nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False), + nn.BatchNorm2d(oup, momentum=0.1), + ]) + self.conv = nn.Sequential(*layers) + # Replace torch.add with floatfunctional + self.skip_add = nn.quantized.FloatFunctional() + + def forward(self, x): + if self.use_res_connect: + return self.skip_add.add(x, self.conv(x)) + else: + return self.conv(x) + +class MobileNetV2(nn.Module): + def __init__(self, num_classes=1000, width_mult=1.0, inverted_residual_setting=None, round_nearest=8): + """ + MobileNet V2 main class + + Args: + num_classes (int): Number of classes + width_mult (float): Width multiplier - adjusts number of channels in each layer by this amount + inverted_residual_setting: Network structure + round_nearest (int): Round the number of channels in each layer to be a multiple of this number + Set to 1 to turn off rounding + """ + super(MobileNetV2, self).__init__() + block = InvertedResidual + input_channel = 32 + last_channel = 1280 + + if inverted_residual_setting is None: + inverted_residual_setting = [ + # t, c, n, s + [1, 16, 1, 1], + [6, 24, 2, 2], + [6, 32, 3, 2], + [6, 64, 4, 2], + [6, 96, 3, 1], + [6, 160, 3, 2], + [6, 320, 1, 1], + ] + + # only check the first element, assuming user knows t,c,n,s are required + if len(inverted_residual_setting) == 0 or len(inverted_residual_setting[0]) != 4: + raise ValueError("inverted_residual_setting should be non-empty " + "or a 4-element list, got {}".format(inverted_residual_setting)) + + # building first layer + input_channel = _make_divisible(input_channel * width_mult, round_nearest) + self.last_channel = _make_divisible(last_channel * max(1.0, width_mult), round_nearest) + features = [ConvBNReLU(3, input_channel, stride=2)] + # building inverted residual blocks + for t, c, n, s in inverted_residual_setting: + output_channel = _make_divisible(c * width_mult, round_nearest) + for i in range(n): + stride = s if i == 0 else 1 + features.append(block(input_channel, output_channel, stride, expand_ratio=t)) + input_channel = output_channel + # building last several layers + features.append(ConvBNReLU(input_channel, self.last_channel, kernel_size=1)) + # make it nn.Sequential + self.features = nn.Sequential(*features) + self.quant = QuantStub() + self.dequant = DeQuantStub() + # building classifier + self.classifier = nn.Sequential( + nn.Dropout(0.2), + nn.Linear(self.last_channel, num_classes), + ) + + # weight initialization + for m in self.modules(): + if isinstance(m, nn.Conv2d): + nn.init.kaiming_normal_(m.weight, mode='fan_out') + if m.bias is not None: + nn.init.zeros_(m.bias) + elif isinstance(m, nn.BatchNorm2d): + nn.init.ones_(m.weight) + nn.init.zeros_(m.bias) + elif isinstance(m, nn.Linear): + nn.init.normal_(m.weight, 0, 0.01) + nn.init.zeros_(m.bias) + + def forward(self, x): + + x = self.quant(x) + + x = self.features(x) + x = x.mean([2, 3]) + x = self.classifier(x) + x = self.dequant(x) + return x + + # Fuse Conv+BN and Conv+BN+Relu modules prior to quantization + # This operation does not change the numerics + def fuse_model(self): + for m in self.modules(): + if type(m) == ConvBNReLU: + torch.quantization.fuse_modules(m, ['0', '1', '2'], inplace=True) + if type(m) == InvertedResidual: + for idx in range(len(m.conv)): + if type(m.conv[idx]) == nn.Conv2d: + torch.quantization.fuse_modules(m.conv, [str(idx), str(idx + 1)], inplace=True) + +``` + +## 2.辅助函数 + +接下来,我们定义一些助手函数以帮助模型评估。 这些主要来自[这里](https://github.com/pytorch/examples/blob/master/imagenet/main.py)。 + +```py +class AverageMeter(object): + """Computes and stores the average and current value""" + def __init__(self, name, fmt=':f'): + self.name = name + self.fmt = fmt + self.reset() + + def reset(self): + self.val = 0 + self.avg = 0 + self.sum = 0 + self.count = 0 + + def update(self, val, n=1): + self.val = val + self.sum += val * n + self.count += n + self.avg = self.sum / self.count + + def __str__(self): + fmtstr = '{name} {val' + self.fmt + '} ({avg' + self.fmt + '})' + return fmtstr.format(**self.__dict__) + +def accuracy(output, target, topk=(1,)): + """Computes the accuracy over the k top predictions for the specified values of k""" + with torch.no_grad(): + maxk = max(topk) + batch_size = target.size(0) + + _, pred = output.topk(maxk, 1, True, True) + pred = pred.t() + correct = pred.eq(target.view(1, -1).expand_as(pred)) + + res = [] + for k in topk: + correct_k = correct[:k].reshape(-1).float().sum(0, keepdim=True) + res.append(correct_k.mul_(100.0 / batch_size)) + return res + +def evaluate(model, criterion, data_loader, neval_batches): + model.eval() + top1 = AverageMeter('Acc@1', ':6.2f') + top5 = AverageMeter('Acc@5', ':6.2f') + cnt = 0 + with torch.no_grad(): + for image, target in data_loader: + output = model(image) + loss = criterion(output, target) + cnt += 1 + acc1, acc5 = accuracy(output, target, topk=(1, 5)) + print('.', end = '') + top1.update(acc1[0], image.size(0)) + top5.update(acc5[0], image.size(0)) + if cnt >= neval_batches: + return top1, top5 + + return top1, top5 + +def load_model(model_file): + model = MobileNetV2() + state_dict = torch.load(model_file) + model.load_state_dict(state_dict) + model.to('cpu') + return model + +def print_size_of_model(model): + torch.save(model.state_dict(), "temp.p") + print('Size (MB):', os.path.getsize("temp.p")/1e6) + os.remove('temp.p') + +``` + +## 3.定义数据集和数据加载器 + +作为最后的主要设置步骤,我们为训练和测试集定义了数据加载器。 + +### ImageNet 数据 + +我们为本教程创建的特定数据集仅包含来自 ImageNet 数据的 1000 张图像,每个类别都有一张(此数据集的大小刚好超过 250 MB,可以相对轻松地下载)。 此自定义数据集的 URL 为: + +```py +https://s3.amazonaws.com/pytorch-tutorial-assets/imagenet_1k.zip + +``` + +要使用 Python 在本地下载此数据,可以使用: + +```py +import requests + +url = 'https://s3.amazonaws.com/pytorch-tutorial-assets/imagenet_1k.zip` +filename = '~/Downloads/imagenet_1k_data.zip' + +r = requests.get(url) + +with open(filename, 'wb') as f: + f.write(r.content) + +``` + +为了运行本教程,我们下载了这些数据,并使用 [Makefile](https://github.com/pytorch/tutorials/blob/master/Makefile) 中的这些行将其移到正确的位置。 + +另一方面,要使用整个 ImageNet 数据集运行本教程中的代码,[可以在此之后使用`torchvision`下载数据](https://pytorch.org/docs/stable/torchvision/datasets.html#imagenet)。 例如,要下载训练集并对其进行一些标准转换,可以使用: + +```py +import torchvision +import torchvision.transforms as transforms + +imagenet_dataset = torchvision.datasets.ImageNet( + '~/.data/imagenet', + split='train', + download=True, + transforms.Compose([ + transforms.RandomResizedCrop(224), + transforms.RandomHorizontalFlip(), + transforms.ToTensor(), + transforms.Normalize(mean=[0.485, 0.456, 0.406], + std=[0.229, 0.224, 0.225]), + ]) + +``` + +下载完数据后,我们在下面显示了一些函数,这些函数定义了将用于读取此数据的数据加载器。 这些函数主要来自[此处](https://github.com/pytorch/vision/blob/master/references/detection/train.py)。 + +```py +def prepare_data_loaders(data_path): + + traindir = os.path.join(data_path, 'train') + valdir = os.path.join(data_path, 'val') + normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], + std=[0.229, 0.224, 0.225]) + + dataset = torchvision.datasets.ImageFolder( + traindir, + transforms.Compose([ + transforms.RandomResizedCrop(224), + transforms.RandomHorizontalFlip(), + transforms.ToTensor(), + normalize, + ])) + + dataset_test = torchvision.datasets.ImageFolder( + valdir, + transforms.Compose([ + transforms.Resize(256), + transforms.CenterCrop(224), + transforms.ToTensor(), + normalize, + ])) + + train_sampler = torch.utils.data.RandomSampler(dataset) + test_sampler = torch.utils.data.SequentialSampler(dataset_test) + + data_loader = torch.utils.data.DataLoader( + dataset, batch_size=train_batch_size, + sampler=train_sampler) + + data_loader_test = torch.utils.data.DataLoader( + dataset_test, batch_size=eval_batch_size, + sampler=test_sampler) + + return data_loader, data_loader_test + +``` + +接下来,我们将加载经过预先​​训练的 MobileNetV2 模型。 [我们在这里提供用于从`torchvision`中下载数据的 URL](https://github.com/pytorch/vision/blob/master/torchvision/models/mobilenet.py#L9)。 + +```py +data_path = 'data/imagenet_1k' +saved_model_dir = 'data/' +float_model_file = 'mobilenet_pretrained_float.pth' +scripted_float_model_file = 'mobilenet_quantization_scripted.pth' +scripted_quantized_model_file = 'mobilenet_quantization_scripted_quantized.pth' + +train_batch_size = 30 +eval_batch_size = 30 + +data_loader, data_loader_test = prepare_data_loaders(data_path) +criterion = nn.CrossEntropyLoss() +float_model = load_model(saved_model_dir + float_model_file).to('cpu') + +``` + +接下来,我们将“融合模块”; 通过节省内存访问量,这可以使模型更快,同时还可以提高数值精度。 尽管这可以用于任何模型,但在量化模型中尤为常见。 + +```py +print('\n Inverted Residual Block: Before fusion \n\n', float_model.features[1].conv) +float_model.eval() + +# Fuses modules +float_model.fuse_model() + +# Note fusion of Conv+BN+Relu and Conv+Relu +print('\n Inverted Residual Block: After fusion\n\n',float_model.features[1].conv) + +``` + +出: + +```py +Inverted Residual Block: Before fusion + + Sequential( + (0): ConvBNReLU( + (0): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=32, bias=False) + (1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) + (2): ReLU() + ) + (1): Conv2d(32, 16, kernel_size=(1, 1), stride=(1, 1), bias=False) + (2): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) +) + + Inverted Residual Block: After fusion + + Sequential( + (0): ConvBNReLU( + (0): ConvReLU2d( + (0): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=32) + (1): ReLU() + ) + (1): Identity() + (2): Identity() + ) + (1): Conv2d(32, 16, kernel_size=(1, 1), stride=(1, 1)) + (2): Identity() +) + +``` + +最后,为了获得“基准”精度,让我们看看带有融合模块的未量化模型的精度 + +```py +num_eval_batches = 10 + +print("Size of baseline model") +print_size_of_model(float_model) + +top1, top5 = evaluate(float_model, criterion, data_loader_test, neval_batches=num_eval_batches) +print('Evaluation accuracy on %d images, %2.2f'%(num_eval_batches * eval_batch_size, top1.avg)) +torch.jit.save(torch.jit.script(float_model), saved_model_dir + scripted_float_model_file) + +``` + +出: + +```py +Size of baseline model +Size (MB): 13.999657 +..........Evaluation accuracy on 300 images, 77.67 + +``` + +我们看到 300 张图像的准确率达到 78%,这是 ImageNet 的坚实基础,特别是考虑到我们的模型只有 14.0 MB。 + +这将是我们比较的基准。 接下来,让我们尝试不同的量化方法 + +## 4.训练后的静态量化 + +训练后的静态量化不仅涉及像动态量化中那样将权重从`float`转换为`int`,而且还执行额外的步骤,即首先通过网络馈送一批数据并计算不同激活的结果分布(具体来说,这通过在记录此数据的不同点插入观察者模块来完成)。 然后使用这些分布来确定在推理时如何具体量化不同的激活(一种简单的技术是将整个激活范围简单地划分为 256 个级别,但我们也支持更复杂的方法)。 重要的是,此附加步骤使我们能够在操作之间传递量化值,而不是在每次操作之间将这些值转换为浮点数,然后再转换为整数,从而显着提高了速度。 + +```py +num_calibration_batches = 10 + +myModel = load_model(saved_model_dir + float_model_file).to('cpu') +myModel.eval() + +# Fuse Conv, bn and relu +myModel.fuse_model() + +# Specify quantization configuration +# Start with simple min/max range estimation and per-tensor quantization of weights +myModel.qconfig = torch.quantization.default_qconfig +print(myModel.qconfig) +torch.quantization.prepare(myModel, inplace=True) + +# Calibrate first +print('Post Training Quantization Prepare: Inserting Observers') +print('\n Inverted Residual Block:After observer insertion \n\n', myModel.features[1].conv) + +# Calibrate with the training set +evaluate(myModel, criterion, data_loader, neval_batches=num_calibration_batches) +print('Post Training Quantization: Calibration done') + +# Convert to quantized model +torch.quantization.convert(myModel, inplace=True) +print('Post Training Quantization: Convert done') +print('\n Inverted Residual Block: After fusion and quantization, note fused modules: \n\n',myModel.features[1].conv) + +print("Size of model after quantization") +print_size_of_model(myModel) + +top1, top5 = evaluate(myModel, criterion, data_loader_test, neval_batches=num_eval_batches) +print('Evaluation accuracy on %d images, %2.2f'%(num_eval_batches * eval_batch_size, top1.avg)) + +``` + +出: + +```py +QConfig(activation=functools.partial(, reduce_range=True), weight=functools.partial(, dtype=torch.qint8, qscheme=torch.per_tensor_symmetric)) +Post Training Quantization Prepare: Inserting Observers + + Inverted Residual Block:After observer insertion + + Sequential( + (0): ConvBNReLU( + (0): ConvReLU2d( + (0): Conv2d( + 32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=32 + (activation_post_process): MinMaxObserver(min_val=inf, max_val=-inf) + ) + (1): ReLU( + (activation_post_process): MinMaxObserver(min_val=inf, max_val=-inf) + ) + ) + (1): Identity() + (2): Identity() + ) + (1): Conv2d( + 32, 16, kernel_size=(1, 1), stride=(1, 1) + (activation_post_process): MinMaxObserver(min_val=inf, max_val=-inf) + ) + (2): Identity() +) +..........Post Training Quantization: Calibration done +Post Training Quantization: Convert done + + Inverted Residual Block: After fusion and quantization, note fused modules: + + Sequential( + (0): ConvBNReLU( + (0): QuantizedConvReLU2d(32, 32, kernel_size=(3, 3), stride=(1, 1), scale=0.1516050398349762, zero_point=0, padding=(1, 1), groups=32) + (1): Identity() + (2): Identity() + ) + (1): QuantizedConv2d(32, 16, kernel_size=(1, 1), stride=(1, 1), scale=0.17719413340091705, zero_point=63) + (2): Identity() +) +Size of model after quantization +Size (MB): 3.631847 +..........Evaluation accuracy on 300 images, 66.67 + +``` + +对于这个量化模型,我们发现在这 300 张相同的图像上,准确率仅低至约 62%。 不过,我们确实将模型的大小减小到了 3.6 MB 以下,几乎减少了 4 倍。 + +此外,我们可以通过使用不同的量化配置来显着提高准确率。 我们使用推荐的配置对 x86 架构进行量化,重复相同的练习。 此配置执行以下操作: + +* 量化每个通道的权重 +* 使用直方图观察器,该直方图观察器收集激活的直方图,然后以最佳方式选择量化参数。 + +```py +per_channel_quantized_model = load_model(saved_model_dir + float_model_file) +per_channel_quantized_model.eval() +per_channel_quantized_model.fuse_model() +per_channel_quantized_model.qconfig = torch.quantization.get_default_qconfig('fbgemm') +print(per_channel_quantized_model.qconfig) + +torch.quantization.prepare(per_channel_quantized_model, inplace=True) +evaluate(per_channel_quantized_model,criterion, data_loader, num_calibration_batches) +torch.quantization.convert(per_channel_quantized_model, inplace=True) +top1, top5 = evaluate(per_channel_quantized_model, criterion, data_loader_test, neval_batches=num_eval_batches) +print('Evaluation accuracy on %d images, %2.2f'%(num_eval_batches * eval_batch_size, top1.avg)) +torch.jit.save(torch.jit.script(per_channel_quantized_model), saved_model_dir + scripted_quantized_model_file) + +``` + +出: + +```py +QConfig(activation=functools.partial(, reduce_range=True), weight=functools.partial(, dtype=torch.qint8, qscheme=torch.per_channel_symmetric)) +....................Evaluation accuracy on 300 images, 74.67 + +``` + +仅更改这种量化配置方法,就可以将准确率提高到 76% 以上! 尽管如此,这仍比上述 78% 的基准差 1-2%。 因此,让我们尝试量化意识的训练。 + +## 5.量化感知的训练 + +量化感知的训练(QAT)是通常导致最高准确率的量化方法。 使用 QAT,在训练的正向和反向过程中,所有权重和激活都被“伪量化”:即,浮点值四舍五入以模拟`int8`值,但所有计算仍使用浮点数完成。 因此,在训练过程中进行所有权重调整,同时“意识到”该模型将最终被量化的事实。 因此,在量化之后,此方法通常会比动态量化或训练后静态量化产生更高的精度。 + +实际执行 QAT 的总体工作流程与之前非常相似: + +* 我们可以使用与以前相同的模型:量化感知的训练不需要额外的准备。 +* 我们需要使用`qconfig`来指定要在权重和激活之后插入哪种伪量化,而不是指定观察者 + +我们首先定义一个训练函数: + +```py +def train_one_epoch(model, criterion, optimizer, data_loader, device, ntrain_batches): + model.train() + top1 = AverageMeter('Acc@1', ':6.2f') + top5 = AverageMeter('Acc@5', ':6.2f') + avgloss = AverageMeter('Loss', '1.5f') + + cnt = 0 + for image, target in data_loader: + start_time = time.time() + print('.', end = '') + cnt += 1 + image, target = image.to(device), target.to(device) + output = model(image) + loss = criterion(output, target) + optimizer.zero_grad() + loss.backward() + optimizer.step() + acc1, acc5 = accuracy(output, target, topk=(1, 5)) + top1.update(acc1[0], image.size(0)) + top5.update(acc5[0], image.size(0)) + avgloss.update(loss, image.size(0)) + if cnt >= ntrain_batches: + print('Loss', avgloss.avg) + + print('Training: * Acc@1 {top1.avg:.3f} Acc@5 {top5.avg:.3f}' + .format(top1=top1, top5=top5)) + return + + print('Full imagenet train set: * Acc@1 {top1.global_avg:.3f} Acc@5 {top5.global_avg:.3f}' + .format(top1=top1, top5=top5)) + return + +``` + +我们像以前一样融合模块 + +```py +qat_model = load_model(saved_model_dir + float_model_file) +qat_model.fuse_model() + +optimizer = torch.optim.SGD(qat_model.parameters(), lr = 0.0001) +qat_model.qconfig = torch.quantization.get_default_qat_qconfig('fbgemm') + +``` + +最后,`prepare_qat`执行“伪量化”,为量化感知训练准备模型 + +```py +torch.quantization.prepare_qat(qat_model, inplace=True) +print('Inverted Residual Block: After preparation for QAT, note fake-quantization modules \n',qat_model.features[1].conv) + +``` + +出: + +```py +Inverted Residual Block: After preparation for QAT, note fake-quantization modules + Sequential( + (0): ConvBNReLU( + (0): ConvBnReLU2d( + 32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=32, bias=False + (bn): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) + (weight_fake_quant): FakeQuantize( + fake_quant_enabled=tensor([1], dtype=torch.uint8), observer_enabled=tensor([1], dtype=torch.uint8), quant_min=-128, quant_max=127, dtype=torch.qint8, qscheme=torch.per_channel_symmetric, ch_axis=0, scale=tensor([1.]), zero_point=tensor([0]) + (activation_post_process): MovingAveragePerChannelMinMaxObserver(min_val=tensor([]), max_val=tensor([])) + ) + (activation_post_process): FakeQuantize( + fake_quant_enabled=tensor([1], dtype=torch.uint8), observer_enabled=tensor([1], dtype=torch.uint8), quant_min=0, quant_max=255, dtype=torch.quint8, qscheme=torch.per_tensor_affine, ch_axis=-1, scale=tensor([1.]), zero_point=tensor([0]) + (activation_post_process): MovingAverageMinMaxObserver(min_val=inf, max_val=-inf) + ) + ) + (1): Identity() + (2): Identity() + ) + (1): ConvBn2d( + 32, 16, kernel_size=(1, 1), stride=(1, 1), bias=False + (bn): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) + (weight_fake_quant): FakeQuantize( + fake_quant_enabled=tensor([1], dtype=torch.uint8), observer_enabled=tensor([1], dtype=torch.uint8), quant_min=-128, quant_max=127, dtype=torch.qint8, qscheme=torch.per_channel_symmetric, ch_axis=0, scale=tensor([1.]), zero_point=tensor([0]) + (activation_post_process): MovingAveragePerChannelMinMaxObserver(min_val=tensor([]), max_val=tensor([])) + ) + (activation_post_process): FakeQuantize( + fake_quant_enabled=tensor([1], dtype=torch.uint8), observer_enabled=tensor([1], dtype=torch.uint8), quant_min=0, quant_max=255, dtype=torch.quint8, qscheme=torch.per_tensor_affine, ch_axis=-1, scale=tensor([1.]), zero_point=tensor([0]) + (activation_post_process): MovingAverageMinMaxObserver(min_val=inf, max_val=-inf) + ) + ) + (2): Identity() +) + +``` + +高精度训练量化模型需要在推断时对数字进行精确建模。 因此,对于量化感知的训练,我们通过以下方式修改训练循环: + +* 在训练快要结束时切换批量规范以使用运行均值和方差,以更好地匹配推理数字。 +* 我们还冻结了量化器参数(比例和零点),并对权重进行了微调。 + +```py +num_train_batches = 20 + +# Train and check accuracy after each epoch +for nepoch in range(8): + train_one_epoch(qat_model, criterion, optimizer, data_loader, torch.device('cpu'), num_train_batches) + if nepoch > 3: + # Freeze quantizer parameters + qat_model.apply(torch.quantization.disable_observer) + if nepoch > 2: + # Freeze batch norm mean and variance estimates + qat_model.apply(torch.nn.intrinsic.qat.freeze_bn_stats) + + # Check the accuracy after each epoch + quantized_model = torch.quantization.convert(qat_model.eval(), inplace=False) + quantized_model.eval() + top1, top5 = evaluate(quantized_model,criterion, data_loader_test, neval_batches=num_eval_batches) + print('Epoch %d :Evaluation accuracy on %d images, %2.2f'%(nepoch, num_eval_batches * eval_batch_size, top1.avg)) + +``` + +出: + +```py +....................Loss tensor(2.0747, grad_fn=) +Training: * Acc@1 56.167 Acc@5 77.333 +..........Epoch 0 :Evaluation accuracy on 300 images, 77.67 +....................Loss tensor(2.0358, grad_fn=) +Training: * Acc@1 54.833 Acc@5 78.500 +..........Epoch 1 :Evaluation accuracy on 300 images, 77.00 +....................Loss tensor(2.0417, grad_fn=) +Training: * Acc@1 54.667 Acc@5 77.333 +..........Epoch 2 :Evaluation accuracy on 300 images, 74.67 +....................Loss tensor(1.9055, grad_fn=) +Training: * Acc@1 56.833 Acc@5 78.667 +..........Epoch 3 :Evaluation accuracy on 300 images, 76.33 +....................Loss tensor(1.9055, grad_fn=) +Training: * Acc@1 58.167 Acc@5 80.000 +..........Epoch 4 :Evaluation accuracy on 300 images, 77.00 +....................Loss tensor(1.7821, grad_fn=) +Training: * Acc@1 60.500 Acc@5 82.833 +..........Epoch 5 :Evaluation accuracy on 300 images, 76.33 +....................Loss tensor(1.8145, grad_fn=) +Training: * Acc@1 58.833 Acc@5 82.333 +..........Epoch 6 :Evaluation accuracy on 300 images, 74.33 +....................Loss tensor(1.6930, grad_fn=) +Training: * Acc@1 63.000 Acc@5 81.333 +..........Epoch 7 :Evaluation accuracy on 300 images, 75.67 + +``` + +在这里,我们只对少数几个周期执行量化感知训练。 尽管如此,量化感知的训练在整个 imagenet 数据集上的准确率仍超过 71%,接近浮点精度 71.9%。 + +有关量化感知的训练的更多信息: + +* QAT 是训练后量化技术的超集,可以进行更多调试。 例如,我们可以分析模型的准确率是否受到权重或激活量化的限制。 +* 由于我们使用伪量化来对实际量化算术的数值建模,因此我们还可以在浮点中模拟量化模型的准确率。 +* 我们也可以轻松地模拟训练后量化。 + +### 来自量化的加速 + +最后,让我们确认一下我们上面提到的内容:量化模型实际上执行推理的速度更快吗? 让我们测试一下: + +```py +def run_benchmark(model_file, img_loader): + elapsed = 0 + model = torch.jit.load(model_file) + model.eval() + num_batches = 5 + # Run the scripted model on a few batches of images + for i, (images, target) in enumerate(img_loader): + if i < num_batches: + start = time.time() + output = model(images) + end = time.time() + elapsed = elapsed + (end-start) + else: + break + num_images = images.size()[0] * num_batches + + print('Elapsed time: %3.0f ms' % (elapsed/num_images*1000)) + return elapsed + +run_benchmark(saved_model_dir + scripted_float_model_file, data_loader_test) + +run_benchmark(saved_model_dir + scripted_quantized_model_file, data_loader_test) + +``` + +出: + +```py +Elapsed time: 7 ms +Elapsed time: 4 ms + +``` + +在 MacBook Pro 上本地运行此程序,常规模型的运行时间为 61 毫秒,而量化模型的运行时间仅为 20 毫秒,这说明了量化模型与浮点模型相比,典型的 2-4 倍加速。 + +## 总结 + +在本教程中,我们展示了两种量化方法-训练后静态量化和量化感知训练-描述它们在“幕后”进行的操作以及如何在 PyTorch 中使用它们。 + +谢谢阅读! 与往常一样,我们欢迎您提供反馈,因此,如果有任何问题,[请在这里创建一个 ISSUE](https://github.com/pytorch/pytorch/issues)。 + +**脚本的总运行时间**:(5 分钟 40.226 秒) + +[下载 Python 源码:`static_quantization_tutorial.py`](../_downloads/bd7ace4f5df8c6f747eadb10a7f737cd/static_quantization_tutorial.py) + +[下载 Jupyter 笔记本:`static_quantization_tutorial.ipynb`](../_downloads/03ac9a8e1176f5e39736885e8c439a82/static_quantization_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/58.md b/pytorch/官方教程/58.md new file mode 100644 index 00000000..ca6788e6 --- /dev/null +++ b/pytorch/官方教程/58.md @@ -0,0 +1,431 @@ +# 计算机视觉的量化迁移学习教程(beta) + +> 原文: + +小费 + +为了充分利用本教程,我们建议使用此 [Colab 版本](https://colab.research.google.com/github/pytorch/tutorials/blob/gh-pages/_downloads/quantized_transfer_learning_tutorial.ipynb)。 这将使您可以尝试以下信息。 + +**作者**: [Zafar Takhirov](https://github.com/z-a-f) + +**由**审核: [Raghuraman Krishnamoorthi](https://github.com/raghuramank100) + +**编辑**:[Jessica Lin](https://github.com/jlin27) + +本教程以 [Sasank Chilamkurthy](https://pytorch.org/tutorials/beginner/transfer_learning_tutorial.html) 编写的原始 [PyTorch 迁移学习](https://pytorch.org/tutorials/beginner/transfer_learning_tutorial.html)教程为基础。 + +迁移学习是指利用预训练的模型应用于不同数据集的技术。 使用迁移学习的主要方法有两种: + +1. **作为固定特征提取器的 ConvNet**:在这里,您[“冻结”](https://arxiv.org/abs/1706.04983)网络中所有参数的权重,除了最后几层(又称“头部”,通常是全连接层)。 将这些最后一层替换为使用随机权重初始化的新层,并且仅训练这些层。 +2. **ConvNet 的微调**:使用随机训练的网络初始化模型,而不是随机初始化,然后像往常一样使用不同的数据集进行训练。 通常,如果输出数量不同,则在网络中也会更换头部(或头部的一部分)。 这种方法通常将学习率设置为较小的值。 这样做是因为已经对网络进行了训练,并且只需进行较小的更改即可将其“微调”到新的数据集。 + +您还可以结合以上两种方法:首先,可以冻结特征提取器,并训练头部。 之后,您可以解冻特征提取器(或其一部分),将学习率设置为较小的值,然后继续进行训练。 + +在本部分中,您将使用第一种方法-使用量化模型提取特征。 + +## 第 0 部分,先决条件 + +在深入学习迁移学习之前,让我们回顾一下“先决条件”,例如安装和数据加载/可视化。 + +```py +# Imports +import copy +import matplotlib.pyplot as plt +import numpy as np +import os +import time + +plt.ion() + +``` + +### 安装每夜构建 + +因为您将使用 PyTorch 的 Beta 部分,所以建议安装最新版本的`torch`和`torchvision`。 [您可以在这里找到有关本地安装的最新说明](https://pytorch.org/get-started/locally/)。 例如,要在没有 GPU 支持的情况下进行安装: + +```py +pip install numpy +pip install --pre torch torchvision -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html +# For CUDA support use https://download.pytorch.org/whl/nightly/cu101/torch_nightly.html + +``` + +### 加载数据 + +注意 + +本部分与原始的迁移学习教程相同。 + +我们将使用`torchvision`和`torch.utils.data`包加载数据。 + +您今天要解决的问题是从图像中对**蚂蚁**和**蜜蜂**进行分类。 该数据集包含约 120 张针对蚂蚁和蜜蜂的训练图像。 每个类别有 75 个验证图像。 可以认为这是一个很小的数据集。 但是,由于我们正在使用迁移学习,因此我们应该能够很好地进行概括。 + +*此数据集是 imagenet 的很小子集。* + +注意 + +从[此处](https://download.pytorch.org/tutorial/hymenoptera_data.zip)下载数据,并将其提取到`data`目录。 + +```py +import torch +from torchvision import transforms, datasets + +# Data augmentation and normalization for training +# Just normalization for validation +data_transforms = { + 'train': transforms.Compose([ + transforms.Resize(224), + transforms.RandomCrop(224), + transforms.RandomHorizontalFlip(), + transforms.ToTensor(), + transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) + ]), + 'val': transforms.Compose([ + transforms.Resize(224), + transforms.CenterCrop(224), + transforms.ToTensor(), + transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) + ]), +} + +data_dir = 'data/hymenoptera_data' +image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x), + data_transforms[x]) + for x in ['train', 'val']} +dataloaders = {x: torch.utils.data.DataLoader(image_datasets[x], batch_size=16, + shuffle=True, num_workers=8) + for x in ['train', 'val']} +dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val']} +class_names = image_datasets['train'].classes + +device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") + +``` + +### 可视化一些图像 + +让我们可视化一些训练图像,以了解数据扩充。 + +```py +import torchvision + +def imshow(inp, title=None, ax=None, figsize=(5, 5)): + """Imshow for Tensor.""" + inp = inp.numpy().transpose((1, 2, 0)) + mean = np.array([0.485, 0.456, 0.406]) + std = np.array([0.229, 0.224, 0.225]) + inp = std * inp + mean + inp = np.clip(inp, 0, 1) + if ax is None: + fig, ax = plt.subplots(1, figsize=figsize) + ax.imshow(inp) + ax.set_xticks([]) + ax.set_yticks([]) + if title is not None: + ax.set_title(title) + +# Get a batch of training data +inputs, classes = next(iter(dataloaders['train'])) + +# Make a grid from batch +out = torchvision.utils.make_grid(inputs, nrow=4) + +fig, ax = plt.subplots(1, figsize=(10, 10)) +imshow(out, title=[class_names[x] for x in classes], ax=ax) + +``` + +### 模型训练的支持函数 + +以下是模型训练的通用函数。 此函数也: + +* 安排学习率 +* 保存最佳模型 + +```py +def train_model(model, criterion, optimizer, scheduler, num_epochs=25, device='cpu'): + """ + Support function for model training. + + Args: + model: Model to be trained + criterion: Optimization criterion (loss) + optimizer: Optimizer to use for training + scheduler: Instance of ``torch.optim.lr_scheduler`` + num_epochs: Number of epochs + device: Device to run the training on. Must be 'cpu' or 'cuda' + """ + since = time.time() + + best_model_wts = copy.deepcopy(model.state_dict()) + best_acc = 0.0 + + for epoch in range(num_epochs): + print('Epoch {}/{}'.format(epoch, num_epochs - 1)) + print('-' * 10) + + # Each epoch has a training and validation phase + for phase in ['train', 'val']: + if phase == 'train': + model.train() # Set model to training mode + else: + model.eval() # Set model to evaluate mode + + running_loss = 0.0 + running_corrects = 0 + + # Iterate over data. + for inputs, labels in dataloaders[phase]: + inputs = inputs.to(device) + labels = labels.to(device) + + # zero the parameter gradients + optimizer.zero_grad() + + # forward + # track history if only in train + with torch.set_grad_enabled(phase == 'train'): + outputs = model(inputs) + _, preds = torch.max(outputs, 1) + loss = criterion(outputs, labels) + + # backward + optimize only if in training phase + if phase == 'train': + loss.backward() + optimizer.step() + + # statistics + running_loss += loss.item() * inputs.size(0) + running_corrects += torch.sum(preds == labels.data) + if phase == 'train': + scheduler.step() + + epoch_loss = running_loss / dataset_sizes[phase] + epoch_acc = running_corrects.double() / dataset_sizes[phase] + + print('{} Loss: {:.4f} Acc: {:.4f}'.format( + phase, epoch_loss, epoch_acc)) + + # deep copy the model + if phase == 'val' and epoch_acc > best_acc: + best_acc = epoch_acc + best_model_wts = copy.deepcopy(model.state_dict()) + + print() + + time_elapsed = time.time() - since + print('Training complete in {:.0f}m {:.0f}s'.format( + time_elapsed // 60, time_elapsed % 60)) + print('Best val Acc: {:4f}'.format(best_acc)) + + # load best model weights + model.load_state_dict(best_model_wts) + return model + +``` + +### 可视化模型预测的支持函数 + +通用函数,显示一些图像的预测 + +```py +def visualize_model(model, rows=3, cols=3): + was_training = model.training + model.eval() + current_row = current_col = 0 + fig, ax = plt.subplots(rows, cols, figsize=(cols*2, rows*2)) + + with torch.no_grad(): + for idx, (imgs, lbls) in enumerate(dataloaders['val']): + imgs = imgs.cpu() + lbls = lbls.cpu() + + outputs = model(imgs) + _, preds = torch.max(outputs, 1) + + for jdx in range(imgs.size()[0]): + imshow(imgs.data[jdx], ax=ax[current_row, current_col]) + ax[current_row, current_col].axis('off') + ax[current_row, current_col].set_title('predicted: {}'.format(class_names[preds[jdx]])) + + current_col += 1 + if current_col >= cols: + current_row += 1 + current_col = 0 + if current_row >= rows: + model.train(mode=was_training) + return + model.train(mode=was_training) + +``` + +## 第 1 部分,基于量化特征提取器训练自定义分类器 + +在本节中,您将使用“冻结”量化特征提取器,并在其顶部训练自定义分类器头。 与浮点模型不同,您无需为量化模型设置`require_grad = False`,因为它没有可训练的参数。 请参阅[文档](https://pytorch.org/docs/stable/quantization.html)了解更多详细信息。 + +加载预训练的模型:在本练习中,您将使用 [ResNet-18](https://pytorch.org/hub/pytorch_vision_resnet/) 。 + +```py +import torchvision.models.quantization as models + +# You will need the number of filters in the `fc` for future use. +# Here the size of each output sample is set to 2. +# Alternatively, it can be generalized to nn.Linear(num_ftrs, len(class_names)). +model_fe = models.resnet18(pretrained=True, progress=True, quantize=True) +num_ftrs = model_fe.fc.in_features + +``` + +此时,您需要修改预训练模型。 该模型在开始和结束时都有量化/去量化块。 但是,由于只使用特征提取器,因此反量化层必须在线性层(头部)之前移动。 最简单的方法是将模型包装在`nn.Sequential`模块中。 + +第一步是在 ResNet 模型中隔离特征提取器。 尽管在本示例中,您被责成使用`fc`以外的所有层作为特征提取器,但实际上,您可以根据需要选择任意数量的零件。 如果您也想替换一些卷积层,这将很有用。 + +注意 + +将特征提取器与量化模型的其余部分分开时,必须手动将量化器/去量化器放置在要保持量化的部分的开头和结尾。 + +下面的函数创建一个带有自定义头部的模型。 + +```py +from torch import nn + +def create_combined_model(model_fe): + # Step 1\. Isolate the feature extractor. + model_fe_features = nn.Sequential( + model_fe.quant, # Quantize the input + model_fe.conv1, + model_fe.bn1, + model_fe.relu, + model_fe.maxpool, + model_fe.layer1, + model_fe.layer2, + model_fe.layer3, + model_fe.layer4, + model_fe.avgpool, + model_fe.dequant, # Dequantize the output + ) + + # Step 2\. Create a new "head" + new_head = nn.Sequential( + nn.Dropout(p=0.5), + nn.Linear(num_ftrs, 2), + ) + + # Step 3\. Combine, and don't forget the quant stubs. + new_model = nn.Sequential( + model_fe_features, + nn.Flatten(1), + new_head, + ) + return new_model + +``` + +警告 + +当前,量化模型只能在 CPU 上运行。 但是,可以将模型的未量化部分发送到 GPU。 + +```py +import torch.optim as optim +new_model = create_combined_model(model_fe) +new_model = new_model.to('cpu') + +criterion = nn.CrossEntropyLoss() + +# Note that we are only training the head. +optimizer_ft = optim.SGD(new_model.parameters(), lr=0.01, momentum=0.9) + +# Decay LR by a factor of 0.1 every 7 epochs +exp_lr_scheduler = optim.lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1) + +``` + +### 训练和评估 + +此步骤在 CPU 上大约需要 15-25 分钟。 由于量化模型只能在 CPU 上运行,因此您不能在 GPU 上运行训练。 + +```py +new_model = train_model(new_model, criterion, optimizer_ft, exp_lr_scheduler, + num_epochs=25, device='cpu') + +visualize_model(new_model) +plt.tight_layout() + +``` + +## 第 2 部分,微调量化模型 + +在这一部分中,我们将微调用于迁移学习的特征提取器,并对特征提取器进行量化。 请注意,在第 1 部分和第 2 部分中,特征提取器都是量化的。 不同之处在于,在第 1 部分中,我们使用了预训练的量化模型。 在这一部分中,我们将在对感兴趣的数据集进行微调之后创建一个量化的特征提取器,因此这是一种在具有量化优势的同时通过迁移学习获得更好的准确率的方法。 请注意,在我们的特定示例中,训练集非常小(120 张图像),因此微调整个模型的好处并不明显。 但是,此处显示的过程将提高使用较大数据集进行传递学习的准确率。 + +预训练特征提取器必须是可量化的。 为确保其可量化,请执行以下步骤: + +> 1. 使用 `torch.quantization.fuse_modules` 熔断 `(Conv, BN, ReLU)` , `(Conv, BN)` 和 `(Conv, ReLU)` 。 +> 2. 将特征提取器与自定义头部连接。 这需要对特征提取器的输出进行反量化。 +> 3. 在特征提取器中的适当位置插入伪量化模块,以模拟训练期间的量化。 + +对于步骤(1),我们使用`torchvision/models/quantization`中的模型,这些模型具有成员方法`fuse_model`。 此函数将所有`conv`,`bn`和`relu`模块融合在一起。 对于自定义模型,这需要使用模块列表调用`torch.quantization.fuse_modules` API 进行手动融合。 + +步骤(2)由上一节中使用的`create_combined_model`函数执行。 + +步骤(3)通过使用`torch.quantization.prepare_qat`来实现,它会插入伪量化模块。 + +在步骤(4)中,您可以开始“微调”模型,然后将其转换为完全量化的版本(步骤 5)。 + +要将微调模型转换为量化模型,可以调用`torch.quantization.convert`函数(在我们的情况下,仅对特征提取器进行量化)。 + +注意 + +由于随机初始化,您的结果可能与本教程中显示的结果不同。 + +```py +# notice quantize=False model = models.resnet18(pretrained=True, progress=True, quantize=False) num_ftrs = model.fc.in_features + +# Step 1 model.train() model.fuse_model() # Step 2 model_ft = create_combined_model(model) model_ft[0].qconfig = torch.quantization.default_qat_qconfig # Use default QAT configuration # Step 3 model_ft = torch.quantization.prepare_qat(model_ft, inplace=True) +``` + +### 微调模型 + +在当前教程中,整个模型都经过了微调。 通常,这将导致更高的精度。 但是,由于此处使用的训练集很小,最终导致我们过度适应了训练集。 + +步骤 4.微调模型 + +```py +for param in model_ft.parameters(): + param.requires_grad = True + +model_ft.to(device) # We can fine-tune on GPU if available + +criterion = nn.CrossEntropyLoss() + +# Note that we are training everything, so the learning rate is lower +# Notice the smaller learning rate +optimizer_ft = optim.SGD(model_ft.parameters(), lr=1e-3, momentum=0.9, weight_decay=0.1) + +# Decay LR by a factor of 0.3 every several epochs +exp_lr_scheduler = optim.lr_scheduler.StepLR(optimizer_ft, step_size=5, gamma=0.3) + +model_ft_tuned = train_model(model_ft, criterion, optimizer_ft, exp_lr_scheduler, + num_epochs=25, device=device) + +``` + +步骤 5.转换为量化模型 + +```py +from torch.quantization import convert +model_ft_tuned.cpu() + +model_quantized_and_trained = convert(model_ft_tuned, inplace=False) + +``` + +让我们看看量化模型在几张图像上的表现 + +```py +visualize_model(model_quantized_and_trained) + +plt.ioff() +plt.tight_layout() +plt.show() + +``` \ No newline at end of file diff --git a/pytorch/官方教程/59.md b/pytorch/官方教程/59.md new file mode 100644 index 00000000..4ad24ab9 --- /dev/null +++ b/pytorch/官方教程/59.md @@ -0,0 +1 @@ +# 并行和分布式训练 \ No newline at end of file diff --git a/pytorch/官方教程/60.md b/pytorch/官方教程/60.md new file mode 100644 index 00000000..52bda72d --- /dev/null +++ b/pytorch/官方教程/60.md @@ -0,0 +1,73 @@ +# PyTorch 分布式概述 + +> 原文: + +**作者**:[Shen Li](https://mrshenli.github.io/) + +这是`torch.distributed`包的概述页面。 由于在不同位置添加了越来越多的文档,示例和教程,因此不清楚要针对特定​​问题咨询哪个文档或教程,或者阅读这些内容的最佳顺序是什么。 该页面的目的是通过将文档分类为不同的主题并简要描述每个主题来解决此问题。 如果这是您第一次使用 PyTorch 构建分布式训练应用,建议使用本文档导航至最适合您的用例的技术。 + +## 简介 + +从 PyTorch v1.6.0 开始,`torch.distributed`中的功能可以分为三个主要组件: + +* [分布式数据并行训练](https://pytorch.org/docs/master/generated/torch.nn.parallel.DistributedDataParallel.html)(DDP)是一种广泛采用的单程序多数据训练范例。 使用 DDP,可以在每个流程上复制模型,并且每个模型副本都将获得一组不同的输入数据样本。 DDP 负责梯度通信,以保持模型副本同步,并使其与梯度计算重叠,以加快训练速度。 +* [基于 RPC 的分布式训练](https://pytorch.org/docs/master/rpc.html)(RPC)开发来支持无法适应数据并行训练的常规训练结构,例如分布式管道并行性,参数服务器范式以及 DDP 与其他训练范式的组合。 它有助于管理远程对象的生命周期,并将自动微分引擎扩展到机器范围之外。 +* [集体通信](https://pytorch.org/docs/stable/distributed.html)(c10d)库支持跨组内的进程发送张量。 它提供了集体通信 API(例如[`all_reduce`](https://pytorch.org/docs/stable/distributed.html#torch.distributed.all_reduce)和[`all_gather`](https://pytorch.org/docs/stable/distributed.html#torch.distributed.all_gather))和 P2P 通信 API(例如[`send`](https://pytorch.org/docs/stable/distributed.html#torch.distributed.send)和 [`isend`](https://pytorch.org/docs/stable/distributed.html#torch.distributed.isend))。 从 v1.6.0 开始,DDP 和 RPC([ProcessGroup 后端](https://pytorch.org/docs/master/rpc.html#process-group-backend))建立在 c10d 上,其中前者使用集体通信,而后者使用 P2P 通信。 通常,开发人员无需直接使用此原始通信 API,因为上述 DDP 和 RPC 功能可以满足许多分布式训练方案的需求。 但是,在某些情况下,此 API 仍然很有帮助。 一个示例是分布式参数平均,其中应用希望在反向传播之后计算所有模型参数的平均值,而不是使用 DDP 来传递梯度。 这可以使通信与计算脱钩,并允许对通信内容进行更细粒度的控制,但另一方面,它也放弃了 DDP 提供的性能优化。 [用 PyTorch 编写分布式应用](https://pytorch.org/tutorials/intermediate/dist_tuto.html)显示了使用 c10d 通信 API 的示例。 + +现有的大多数文档都是为 DDP 或 RPC 编写的,本页面的其余部分将详细介绍这两个组件的材料。 + +## 数据并行训练 + +PyTorch 为数据并行训练提供了几种选择。 对于从简单到复杂以及从原型到生产逐渐增长的应用,共同的发展轨迹将是: + +1. 如果数据和模型可以放在一个 GPU 中,并且不关心训练速度,请使用单设备训练。 +2. 如果服务器上有多个 GPU,请使用单机多 GPU [`DataParallel`](https://pytorch.org/docs/master/generated/torch.nn.DataParallel.html),并且您希望以最少的代码更改来加快训练速度。 +3. 如果您想进一步加快训练速度并愿意编写更多代码来设置它,请使用单机多 GPU [`DistributedDataParallel`](https://pytorch.org/docs/master/generated/torch.nn.parallel.DistributedDataParallel.html)。 +4. 如果应用需要跨计算机边界扩展,请使用多计算机[`DistributedDataParallel`](https://pytorch.org/docs/master/generated/torch.nn.parallel.DistributedDataParallel.html)和[启动脚本](https://github.com/pytorch/examples/blob/master/distributed/ddp/README.md)。 +5. 如果预计会出现错误(例如,OOM),或者在训练过程中资源可以动态加入和离开,请使用[扭弹性](https://pytorch.org/elastic)启动分布式训练。 + +注意 + +数据并行训练还可以与[自动混合精度(AMP)](https://pytorch.org/docs/master/notes/amp_examples.html#working-with-multiple-gpus)一起使用。 + +### `torch.nn.DataParallel` + +[`DataParallel`](https://pytorch.org/docs/master/generated/torch.nn.DataParallel.html)包以最低的编码障碍实现了单机多 GPU 并行处理。 它只需要一行更改应用代码。 教程[可选:数据并行](https://pytorch.org/tutorials/beginner/blitz/data_parallel_tutorial.html)显示了一个示例。 需要注意的是,尽管`DataParallel`非常易于使用,但通常无法提供最佳性能。 这是因为`DataParallel`的实现会在每个正向传播中复制该模型,并且其单进程多线程并行性自然会遭受 GIL 争用。 为了获得更好的性能,请考虑使用[`DistributedDataParallel`](https://pytorch.org/docs/master/generated/torch.nn.parallel.DistributedDataParallel.html)。 + +### `torch.nn.parallel.DistributedDataParallel` + +与[`DataParallel`](https://pytorch.org/docs/master/generated/torch.nn.DataParallel.html)相比,[`DistributedDataParallel`](https://pytorch.org/docs/master/generated/torch.nn.parallel.DistributedDataParallel.html)还需要设置一个步骤,即调用[`init_process_group`](https://pytorch.org/docs/stable/distributed.html#torch.distributed.init_process_group)。 DDP 使用多进程并行性,因此在模型副本之间没有 GIL 争用。 此外,该模型是在 DDP 构建时而不是在每个正向传播时广播的,这也有助于加快训练速度。 DDP 附带了几种性能优化技术。 有关更深入的说明,请参阅此 [DDP 论文](https://arxiv.org/abs/2006.15704)(VLDB'20)。 + +DDP 材料如下: + +1. [DDP 注解](https://pytorch.org/docs/stable/notes/ddp.html)提供了一个入门示例,并简要介绍了其设计和实现。 如果这是您第一次使用 DDP,请从本文档开始。 +2. [分布式数据并行入门](../intermediate/ddp_tutorial.html)解释了 DDP 训练的一些常见问题,包括不平衡的工作量,检查点和多设备模型。 请注意,DDP 可以轻松与[单机模型并行最佳实践](../intermediate/model_parallel_tutorial.html)教程中描述的单机多设备模型并行性结合。 +3. [启动和配置分布式数据并行应用](https://github.com/pytorch/examples/blob/master/distributed/ddp/README.md)文档显示了如何使用 DDP 启动脚本。 +4. [使用 Amazon AWS 的 PyTorch 分布式训练器](aws_distributed_training_tutorial.html)演示了如何在 AWS 上使用 DDP。 + +### TorchElastic + +随着应用复杂性和规模的增长,故障恢复成为当务之急。 有时,使用 DDP 时不可避免地会遇到 OOM 之类的错误,但是 DDP 本身无法从这些错误中恢复,基本的`try-except`块也无法工作。 这是因为 DDP 要求所有进程以紧密同步的方式运行,并且在不同进程中启动的所有`AllReduce`通信都必须匹配。 如果组中的某个进程抛出 OOM 异常,则很可能导致不同步(`AllReduce`操作不匹配),从而导致崩溃或挂起。 如果您期望在训练过程中发生故障,或者资源可能会动态离开并加入,请使用 [Torrlastic](https://pytorch.org/elastic) 启动分布式数据并行训练。 + +## 通用分布式训练 + +许多训练范式不适合数据并行性,例如参数服务器范式,分布式管道并行性,具有多个观察者或智能体的强化学习应用等。 [`torch.distributed.rpc`](https://pytorch.org/docs/master/rpc.html)旨在支持一般的分布式训练方案 。 + +[`torch.distributed.rpc`](https://pytorch.org/docs/master/rpc.html)包具有四个主要支柱: + +* [RPC](https://pytorch.org/docs/master/rpc.html#rpc) 支持在远程工作器上运行给定函数 +* [RRef](https://pytorch.org/docs/master/rpc.html#rref) 帮助管理远程对象的生存期。 引用计数协议在 [RRef 注解](https://pytorch.org/docs/master/rpc/rref.html#remote-reference-protocol)中提供。 +* [分布式自动微分](https://pytorch.org/docs/master/rpc.html#distributed-autograd-framework)将自动微分引擎扩展到机器范围之外。 有关更多详细信息,请参考[分布式 Autograd 设计](https://pytorch.org/docs/master/rpc/distributed_autograd.html#distributed-autograd-design)。 +* [分布式优化器](https://pytorch.org/docs/master/rpc.html#module-torch.distributed.optim),它使用分布式 Autograd 引擎计算的梯度自动与所有参与的工作器联系以更新参数。 + +RPC 教程如下: + +1. [分布式 RPC 框架入门](../intermediate/rpc_tutorial.html)教程首先使用一个简单的强化学习(RL)示例来演示 RPC 和 RRef。 然后,它对 RNN 示例应用了基本的分布式模型并行性,以展示如何使用分布式 Autograd 和分布式优化器。 +2. [使用分布式 RPC 框架实现参数服务器](../intermediate/rpc_param_server_tutorial.html)教程借鉴了 [HogWild 的训练精神](https://people.eecs.berkeley.edu/~brecht/papers/hogwildTR.pdf),并将其应用于异步参数服务器(PS)训练应用。 +3. 使用 RPC 的[分布式管道并行化](../intermediate/dist_pipeline_parallel_tutorial.html)教程将单机管道并行示例(在[单机模型并行最佳实践](../intermediate/model_parallel_tutorial.html)中介绍)扩展到了分布式环境,并展示了如何使用 RPC 来实现它 。 +4. [使用异步执行实现批量 RPC](../intermediate/rpc_async_execution.html) 教程演示了如何使用[`@rpc.functions.async_execution`](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.functions.async_execution)装饰器实现 RPC 批量。这可以帮助加速推理和训练。 它使用了以上教程 1 和 2 中采用的类似 RL 和 PS 示例。 +5. [将分布式`DataParallel`与分布式 RPC 框架结合](../advanced/rpc_ddp_tutorial.html)教程演示了如何将 DDP 与 RPC 结合使用分布式数据并行性和分布式模型并行性来训练模型。 + +## PyTorch 分布式开发人员 + +如果您想为 PyTorch 分布式做出贡献,请参阅我们的[开发人员指南](https://github.com/pytorch/pytorch/blob/master/torch/distributed/CONTRIBUTING.md)。 \ No newline at end of file diff --git a/pytorch/官方教程/61.md b/pytorch/官方教程/61.md new file mode 100644 index 00000000..b00c8b5c --- /dev/null +++ b/pytorch/官方教程/61.md @@ -0,0 +1,263 @@ +# 单机模型并行最佳实践 + +> 原文: + +**作者**:[Shen Li](https://mrshenli.github.io/) + +模型并行在分布式训练技术中被广泛使用。 先前的帖子已经解释了如何使用[`DataParallel`](https://pytorch.org/tutorials/beginner/blitz/data_parallel_tutorial.html)在多个 GPU 上训练神经网络; 此功能将相同的模型复制到所有 GPU,其中每个 GPU 消耗输入数据的不同分区。 尽管它可以极大地加快训练过程,但不适用于模型太大而无法容纳单个 GPU 的某些用例。 这篇文章展示了如何通过使用**模型并行**解决该问题,与`DataParallel`相比,该模型将单个模型拆分到不同的 GPU 上,而不是在每个 GPU 上复制整个模型(具体来说, 假设模型`m`包含 10 层:使用`DataParallel`时,每个 GPU 都具有这 10 层中的每一个的副本,而当在两个 GPU 上并行使用模型时,每个 GPU 可以承载 5 层。 + +模型并行化的高级思想是将模型的不同子网放置在不同的设备上,并相应地实现`forward`方法以在设备之间移动中间输出。 由于模型的一部分仅在任何单个设备上运行,因此一组设备可以共同为更大的模型服务。 在本文中,我们将不会尝试构建庞大的模型并将其压缩到有限数量的 GPU 中。 取而代之的是,本文着重展示并行模型的思想。 读者可以将这些想法应用到实际应用中。 + +注意 + +对于模型跨越多个服务器的分布式模型并行训练,请参考[分布式 RPC 框架入门](rpc_tutorial.html),以获取示例和详细信息。 + +## 基本用法 + +让我们从包含两个线性层的玩具模型开始。 要在两个 GPU 上运行该模型,只需将每个线性层放置在不同的 GPU 上,然后移动输入和中间输出以匹配层设备。 + +```py +import torch +import torch.nn as nn +import torch.optim as optim + +class ToyModel(nn.Module): + def __init__(self): + super(ToyModel, self).__init__() + self.net1 = torch.nn.Linear(10, 10).to('cuda:0') + self.relu = torch.nn.ReLU() + self.net2 = torch.nn.Linear(10, 5).to('cuda:1') + + def forward(self, x): + x = self.relu(self.net1(x.to('cuda:0'))) + return self.net2(x.to('cuda:1')) + +``` + +请注意,除了五个`to(device)`调用将线性层和张量放置在适当的设备上之外,上述`ToyModel`看起来非常类似于在单个 GPU 上实现它的方式。 那是模型中唯一需要更改的地方。 `backward()`和`torch.optim`将自动处理梯度,就像模型在一个 GPU 上一样。 调用损失函数时,只需确保标签与输出位于同一设备上。 + +```py +model = ToyModel() +loss_fn = nn.MSELoss() +optimizer = optim.SGD(model.parameters(), lr=0.001) + +optimizer.zero_grad() +outputs = model(torch.randn(20, 10)) +labels = torch.randn(20, 5).to('cuda:1') +loss_fn(outputs, labels).backward() +optimizer.step() + +``` + +## 将模型并行应用于现有模块 + +只需进行几行更改,就可以在多个 GPU 上运行现有的单 GPU 模块。 以下代码显示了如何将`torchvision.models.resnet50()`分解为两个 GPU。 这个想法是继承现有的`ResNet`模块,并在构建过程中将层拆分为两个 GPU。 然后,通过相应地移动中间输出,覆盖`forward`方法来缝合两个子网。 + +```py +from torchvision.models.resnet import ResNet, Bottleneck + +num_classes = 1000 + +class ModelParallelResNet50(ResNet): + def __init__(self, *args, **kwargs): + super(ModelParallelResNet50, self).__init__( + Bottleneck, [3, 4, 6, 3], num_classes=num_classes, *args, **kwargs) + + self.seq1 = nn.Sequential( + self.conv1, + self.bn1, + self.relu, + self.maxpool, + + self.layer1, + self.layer2 + ).to('cuda:0') + + self.seq2 = nn.Sequential( + self.layer3, + self.layer4, + self.avgpool, + ).to('cuda:1') + + self.fc.to('cuda:1') + + def forward(self, x): + x = self.seq2(self.seq1(x).to('cuda:1')) + return self.fc(x.view(x.size(0), -1)) + +``` + +对于模型太大而无法放入单个 GPU 的情况,上述实现解决了该问题。 但是,您可能已经注意到,如果模型合适,它将比在单个 GPU 上运行它要慢。 这是因为在任何时间点,两个 GPU 中只有一个在工作,而另一个在那儿什么也没做。 由于中间输出需要在`layer2`和`layer3`之间从`cuda:0`复制到`cuda:1`,因此性能进一步恶化。 + +让我们进行实验以更定量地了解执行时间。 在此实验中,我们通过运行随机输入和标签来训练`ModelParallelResNet50`和现有的`torchvision.models.resnet50()`。 训练后,模型将不会产生任何有用的预测,但是我们可以对执行时间有一个合理的了解。 + +```py +import torchvision.models as models + +num_batches = 3 +batch_size = 120 +image_w = 128 +image_h = 128 + +def train(model): + model.train(True) + loss_fn = nn.MSELoss() + optimizer = optim.SGD(model.parameters(), lr=0.001) + + one_hot_indices = torch.LongTensor(batch_size) \ + .random_(0, num_classes) \ + .view(batch_size, 1) + + for _ in range(num_batches): + # generate random inputs and labels + inputs = torch.randn(batch_size, 3, image_w, image_h) + labels = torch.zeros(batch_size, num_classes) \ + .scatter_(1, one_hot_indices, 1) + + # run forward pass + optimizer.zero_grad() + outputs = model(inputs.to('cuda:0')) + + # run backward pass + labels = labels.to(outputs.device) + loss_fn(outputs, labels).backward() + optimizer.step() + +``` + +上面的`train(model)`方法使用`nn.MSELoss`作为损失函数,并使用`optim.SGD`作为优化器。 它模拟了对`128 X 128`图像的训练,这些图像分为 3 批,每批包含 120 张图像。 然后,我们使用`timeit`来运行`train(model)`方法 10 次,并绘制带有标准差的执行时间。 + +```py +import matplotlib.pyplot as plt +plt.switch_backend('Agg') +import numpy as np +import timeit + +num_repeat = 10 + +stmt = "train(model)" + +setup = "model = ModelParallelResNet50()" +# globals arg is only available in Python 3\. In Python 2, use the following +# import __builtin__ +# __builtin__.__dict__.update(locals()) +mp_run_times = timeit.repeat( + stmt, setup, number=1, repeat=num_repeat, globals=globals()) +mp_mean, mp_std = np.mean(mp_run_times), np.std(mp_run_times) + +setup = "import torchvision.models as models;" + \ + "model = models.resnet50(num_classes=num_classes).to('cuda:0')" +rn_run_times = timeit.repeat( + stmt, setup, number=1, repeat=num_repeat, globals=globals()) +rn_mean, rn_std = np.mean(rn_run_times), np.std(rn_run_times) + +def plot(means, stds, labels, fig_name): + fig, ax = plt.subplots() + ax.bar(np.arange(len(means)), means, yerr=stds, + align='center', alpha=0.5, ecolor='red', capsize=10, width=0.6) + ax.set_ylabel('ResNet50 Execution Time (Second)') + ax.set_xticks(np.arange(len(means))) + ax.set_xticklabels(labels) + ax.yaxis.grid(True) + plt.tight_layout() + plt.savefig(fig_name) + plt.close(fig) + +plot([mp_mean, rn_mean], + [mp_std, rn_std], + ['Model Parallel', 'Single GPU'], + 'mp_vs_rn.png') + +``` + +![](img/7f2d776cf49fcf3fd44fd84a238a3cc6.png) + +结果表明,模型并行实现的执行时间比现有的单 GPU 实现长`4.02/3.75-1=7%`。 因此,我们可以得出结论,在 GPU 之间来回复制张量大约有 7% 的开销。 有待改进的地方,因为我们知道两个 GPU 之一在整个执行过程中处于空闲状态。 一种选择是将每个批量进一步划分为拆分流水线,以便当一个拆分到达第二子网时,可以将下一个拆分馈入第一子网。 这样,两个连续的拆分可以在两个 GPU 上同时运行。 + +## 通过流水线输入加快速度 + +在以下实验中,我们将每个 120 图像批量进一步分为 20 图像分割。 当 PyTorch 异步启动 CUDA 操作时,该实现无需生成多个线程即可实现并发。 + +```py +class PipelineParallelResNet50(ModelParallelResNet50): + def __init__(self, split_size=20, *args, **kwargs): + super(PipelineParallelResNet50, self).__init__(*args, **kwargs) + self.split_size = split_size + + def forward(self, x): + splits = iter(x.split(self.split_size, dim=0)) + s_next = next(splits) + s_prev = self.seq1(s_next).to('cuda:1') + ret = [] + + for s_next in splits: + # A. s_prev runs on cuda:1 + s_prev = self.seq2(s_prev) + ret.append(self.fc(s_prev.view(s_prev.size(0), -1))) + + # B. s_next runs on cuda:0, which can run concurrently with A + s_prev = self.seq1(s_next).to('cuda:1') + + s_prev = self.seq2(s_prev) + ret.append(self.fc(s_prev.view(s_prev.size(0), -1))) + + return torch.cat(ret) + +setup = "model = PipelineParallelResNet50()" +pp_run_times = timeit.repeat( + stmt, setup, number=1, repeat=num_repeat, globals=globals()) +pp_mean, pp_std = np.mean(pp_run_times), np.std(pp_run_times) + +plot([mp_mean, rn_mean, pp_mean], + [mp_std, rn_std, pp_std], + ['Model Parallel', 'Single GPU', 'Pipelining Model Parallel'], + 'mp_vs_rn_vs_pp.png') + +``` + +请注意,设备到设备的张量复制操作在源设备和目标设备上的当前流上同步。 如果创建多个流,则必须确保复制操作正确同步。 在完成复制操作之前写入源张量或读取/写入目标张量可能导致不确定的行为。 上面的实现仅在源设备和目标设备上都使用默认流,因此不必强制执行其他同步。 + +![](img/48d2e67f025b05eeb9259e249566add3.png) + +实验结果表明,对并行 ResNet50 进行建模的流水线输入可大致加快`3.75/2.51-1=49%`的速度,加快训练过程。 距离理想的 100% 加速仍然相去甚远。 由于我们在管道并行实现中引入了新参数`split_sizes`,因此尚不清楚新参数如何影响整体训练时间。 直观地讲,使用较小的`split_size`会导致许多小的 CUDA 内核启动,而使用较大的`split_size`会导致在第一次和最后一次拆分期间出现较长的空闲时间。 两者都不是最优的。 对于此特定实验,可能会有最佳的`split_size`配置。 让我们尝试通过使用几个不同的`split_size`值进行实验来找到它。 + +```py +means = [] +stds = [] +split_sizes = [1, 3, 5, 8, 10, 12, 20, 40, 60] + +for split_size in split_sizes: + setup = "model = PipelineParallelResNet50(split_size=%d)" % split_size + pp_run_times = timeit.repeat( + stmt, setup, number=1, repeat=num_repeat, globals=globals()) + means.append(np.mean(pp_run_times)) + stds.append(np.std(pp_run_times)) + +fig, ax = plt.subplots() +ax.plot(split_sizes, means) +ax.errorbar(split_sizes, means, yerr=stds, ecolor='red', fmt='ro') +ax.set_ylabel('ResNet50 Execution Time (Second)') +ax.set_xlabel('Pipeline Split Size') +ax.set_xticks(split_sizes) +ax.yaxis.grid(True) +plt.tight_layout() +plt.savefig("split_size_tradeoff.png") +plt.close(fig) + +``` + +![](img/9d53a7aba4b9016ea39aa794905ee059.png) + +结果表明,将`split_size`设置为 12 可获得最快的训练速度,从而导致`3.75/2.43-1=54%`加速。 仍有机会进一步加快训练过程。 例如,对`cuda:0`的所有操作都放在其默认流上。 这意味着下一个拆分的计算不能与上一个拆分的复制操作重叠。 但是,由于上一个和下一个分割是不同的张量,因此将一个计算与另一个副本重叠是没有问题的。 实现需要在两个 GPU 上使用多个流,并且不同的子网结构需要不同的流管理策略。 由于没有通用的多流解决方案适用于所有模型并行用例,因此在本教程中将不再讨论。 + +**注意**: + +这篇文章显示了几个性能指标。 当您在自己的计算机上运行相同的代码时,您可能会看到不同的数字,因为结果取决于底层的硬件和软件。 为了使您的环境获得最佳性能,一种正确的方法是首先生成曲线以找出最佳分割尺寸,然后将该分割尺寸用于管道输入。 + +**脚本的总运行时间**:(6 分钟 20.515 秒) + +[下载 Python 源码:`model_parallel_tutorial.py`](../_downloads/d961a67e594a77a630ec636c89f84bb8/model_parallel_tutorial.py) + +[下载 Jupyter 笔记本:`model_parallel_tutorial.ipynb`](../_downloads/b882009cab92c6a1d9121b1f8c4108c4/model_parallel_tutorial.ipynb) + +[由 Sphinx 画廊](https://sphinx-gallery.readthedocs.io)生成的画廊 \ No newline at end of file diff --git a/pytorch/官方教程/62.md b/pytorch/官方教程/62.md new file mode 100644 index 00000000..021492ce --- /dev/null +++ b/pytorch/官方教程/62.md @@ -0,0 +1,224 @@ +# 分布式数据并行入门 + +> 原文: + +**作者**:[Shen Li](https://mrshenli.github.io/) + +**编辑**:[Joe Zhu](https://github.com/gunandrose4u) + +先决条件: + +* [PyTorch 分布式概述](../beginner/dist_overview.html) +* [`DistributedDataParallel` API 文档](https://pytorch.org/docs/master/generated/torch.nn.parallel.DistributedDataParallel.html) +* [`DistributedDataParallel`注意事项](https://pytorch.org/docs/master/notes/ddp.html) + +[`DistributedDataParallel`](https://pytorch.org/docs/stable/nn.html#torch.nn.parallel.DistributedDataParallel)(DDP)在模块级别实现可在多台计算机上运行的数据并行性。 使用 DDP 的应用应产生多个进程,并为每个进程创建一个 DDP 实例。 DDP 在[`torch.distributed`](https://pytorch.org/tutorials/intermediate/dist_tuto.html)包中使用集体通信来同步梯度和缓冲区。 更具体地说,DDP 为`model.parameters()`给定的每个参数注册一个 Autograd 挂钩,当在后向传递中计算相应的梯度时,挂钩将触发。 然后,DDP 使用该信号触发跨进程的梯度同步。 有关更多详细信息,请参考 [DDP 设计说明](https://pytorch.org/docs/master/notes/ddp.html)。 + +推荐的使用 DDP 的方法是为每个模型副本生成一个进程,其中一个模型副本可以跨越多个设备。 DDP 进程可以放在同一台计算机上,也可以在多台计算机上,但是 GPU 设备不能在多个进程之间共享。 本教程从一个基本的 DDP 用例开始,然后演示了更高级的用例,包括检查点模型以及将 DDP 与模型并行结合。 + +注意 + +本教程中的代码在 8-GPU 服务器上运行,但可以轻松地推广到其他环境。 + +## `DataParallel`和`DistributedDataParallel`之间的比较 + +在深入探讨之前,让我们澄清一下为什么尽管增加了复杂性,但还是考虑使用`DistributedDataParallel`而不是`DataParallel`: + +* 首先,`DataParallel`是单进程,多线程,并且只能在单台机器上运行,而`DistributedDataParallel`是多进程,并且适用于单机和多机训练。 即使在单台机器上,`DataParallel`通常也比`DistributedDataParallel`慢,这是因为跨线程的 GIL 争用,每次迭代复制的模型以及分散输入和收集输出所带来的额外开销。 +* 回顾[先前的教程](https://pytorch.org/tutorials/intermediate/model_parallel_tutorial.html),如果模型太大而无法容纳在单个 GPU 上,则必须使用**模型并行**将其拆分到多个 GPU 中。 `DistributedDataParallel`与**模型并行**一起使用; `DataParallel`目前没有。 当 DDP 与模型并行组合时,每个 DDP 进程将并行使用模型,而所有进程共同将并行使用数据。 +* 如果您的模型需要跨越多台机器,或者您的用例不适合数据并行性范式,请参阅 [RPC API](https://pytorch.org/docs/stable/rpc.html) ,以获得更多通用的分布式训练支持。 + +## 基本用例 + +要创建 DDP 模块,请首先正确设置过程组。 更多细节可以在[用 PyTorch 编写分布式应用](https://pytorch.org/tutorials/intermediate/dist_tuto.html)中找到。 + +```py +import os +import sys +import tempfile +import torch +import torch.distributed as dist +import torch.nn as nn +import torch.optim as optim +import torch.multiprocessing as mp + +from torch.nn.parallel import DistributedDataParallel as DDP + +def setup(rank, world_size): + if sys.platform == 'win32': + # Distributed package only covers collective communications with Gloo + # backend and FileStore on Windows platform. Set init_method parameter + # in init_process_group to a local file. + # Example init_method="file:///f:/libtmp/some_file" + init_method="file:///{your local file path}" + + # initialize the process group + dist.init_process_group( + "gloo", + init_method=init_method, + rank=rank, + world_size=world_size + ) + else: + os.environ['MASTER_ADDR'] = 'localhost' + os.environ['MASTER_PORT'] = '12355' + + # initialize the process group + dist.init_process_group("gloo", rank=rank, world_size=world_size) + +def cleanup(): + dist.destroy_process_group() + +``` + +现在,让我们创建一个玩具模块,将其与 DDP 封装在一起,并提供一些虚拟输入数据。 请注意,由于 DDP 会将模型状态从等级 0 进程广播到 DDP 构造器中的所有其他进程,因此您不必担心不同的 DDP 进程从不同的模型参数初始值开始。 + +```py +class ToyModel(nn.Module): + def __init__(self): + super(ToyModel, self).__init__() + self.net1 = nn.Linear(10, 10) + self.relu = nn.ReLU() + self.net2 = nn.Linear(10, 5) + + def forward(self, x): + return self.net2(self.relu(self.net1(x))) + +def demo_basic(rank, world_size): + print(f"Running basic DDP example on rank {rank}.") + setup(rank, world_size) + + # create model and move it to GPU with id rank + model = ToyModel().to(rank) + ddp_model = DDP(model, device_ids=[rank]) + + loss_fn = nn.MSELoss() + optimizer = optim.SGD(ddp_model.parameters(), lr=0.001) + + optimizer.zero_grad() + outputs = ddp_model(torch.randn(20, 10)) + labels = torch.randn(20, 5).to(rank) + loss_fn(outputs, labels).backward() + optimizer.step() + + cleanup() + +def run_demo(demo_fn, world_size): + mp.spawn(demo_fn, + args=(world_size,), + nprocs=world_size, + join=True) + +``` + +如您所见,DDP 包装了较低级别的分布式通信详细信息,并提供了干净的 API,就好像它是本地模型一样。 梯度同步通信发生在反向传递过程中,并且与反向计算重叠。 当`backward()`返回时,`param.grad`已经包含同步梯度张量。 对于基本用例,DDP 仅需要几个 LoC 即可设置流程组。 在将 DDP 应用到更高级的用例时,需要注意一些警告。 + +## 带偏差的处理速度 + +在 DDP 中,构造器,正向传播和反向传递都是分布式同步点。 预期不同的进程将启动相同数量的同步,并以相同的顺序到达这些同步点,并在大致相同的时间进入每个同步点。 否则,快速流程可能会提早到达,并在等待流浪者时超时。 因此,用户负责平衡流程之间的工作负载分配。 有时,由于例如网络延迟,资源争夺,不可预测的工作量峰值,不可避免地会出现处理速度偏差。 为了避免在这种情况下超时,请在调用[`init_process_group`](https://pytorch.org/docs/stable/distributed.html#torch.distributed.init_process_group)时传递足够大的`timeout`值。 + +## 保存和加载检查点 + +在训练过程中通常使用`torch.save`和`torch.load`来检查点模块并从检查点中恢复。 有关更多详细信息,请参见[保存和加载模型](https://pytorch.org/tutorials/beginner/saving_loading_models.html)。 使用 DDP 时,一种优化方法是仅在一个进程中保存模型,然后将其加载到所有进程中,从而减少写开销。 这是正确的,因为所有过程都从相同的参数开始,并且梯度在反向传播中同步,因此优化程序应将参数设置为相同的值。 如果使用此优化,请确保在保存完成之前不要启动所有进程。 此外,在加载模块时,您需要提供适当的`map_location`参数,以防止进程进入其他设备。 如果缺少`map_location`,则`torch.load`将首先将模块加载到 CPU,然后将每个参数复制到保存位置,这将导致同一台机器上的所有进程使用相同的设备集。 有关更高级的故障恢复和弹性支持,请参考[这里](https://pytorch.org/elastic)。 + +```py +def demo_checkpoint(rank, world_size): + print(f"Running DDP checkpoint example on rank {rank}.") + setup(rank, world_size) + + model = ToyModel().to(rank) + ddp_model = DDP(model, device_ids=[rank]) + + loss_fn = nn.MSELoss() + optimizer = optim.SGD(ddp_model.parameters(), lr=0.001) + + CHECKPOINT_PATH = tempfile.gettempdir() + "/model.checkpoint" + if rank == 0: + # All processes should see same parameters as they all start from same + # random parameters and gradients are synchronized in backward passes. + # Therefore, saving it in one process is sufficient. + torch.save(ddp_model.state_dict(), CHECKPOINT_PATH) + + # Use a barrier() to make sure that process 1 loads the model after process + # 0 saves it. + dist.barrier() + # configure map_location properly + map_location = {'cuda:%d' % 0: 'cuda:%d' % rank} + ddp_model.load_state_dict( + torch.load(CHECKPOINT_PATH, map_location=map_location)) + + optimizer.zero_grad() + outputs = ddp_model(torch.randn(20, 10)) + labels = torch.randn(20, 5).to(rank) + loss_fn = nn.MSELoss() + loss_fn(outputs, labels).backward() + optimizer.step() + + # Not necessary to use a dist.barrier() to guard the file deletion below + # as the AllReduce ops in the backward pass of DDP already served as + # a synchronization. + + if rank == 0: + os.remove(CHECKPOINT_PATH) + + cleanup() + +``` + +## 将 DDP 与模型并行性结合起来 + +DDP 还可以与多 GPU 模型一起使用。 当训练具有大量数据的大型模型时,DDP 包装多 GPU 模型特别有用。 + +```py +class ToyMpModel(nn.Module): + def __init__(self, dev0, dev1): + super(ToyMpModel, self).__init__() + self.dev0 = dev0 + self.dev1 = dev1 + self.net1 = torch.nn.Linear(10, 10).to(dev0) + self.relu = torch.nn.ReLU() + self.net2 = torch.nn.Linear(10, 5).to(dev1) + + def forward(self, x): + x = x.to(self.dev0) + x = self.relu(self.net1(x)) + x = x.to(self.dev1) + return self.net2(x) + +``` + +将多 GPU 模型传递给 DDP 时,不得设置`device_ids`和`output_device`。 输入和输出数据将通过应用或模型`forward()`方法放置在适当的设备中。 + +```py +def demo_model_parallel(rank, world_size): + print(f"Running DDP with model parallel example on rank {rank}.") + setup(rank, world_size) + + # setup mp_model and devices for this process + dev0 = rank * 2 + dev1 = rank * 2 + 1 + mp_model = ToyMpModel(dev0, dev1) + ddp_mp_model = DDP(mp_model) + + loss_fn = nn.MSELoss() + optimizer = optim.SGD(ddp_mp_model.parameters(), lr=0.001) + + optimizer.zero_grad() + # outputs will be on dev1 + outputs = ddp_mp_model(torch.randn(20, 10)) + labels = torch.randn(20, 5).to(dev1) + loss_fn(outputs, labels).backward() + optimizer.step() + + cleanup() + +if __name__ == "__main__": + n_gpus = torch.cuda.device_count() + if n_gpus < 8: + print(f"Requires at least 8 GPUs to run, but got {n_gpus}.") + else: + run_demo(demo_basic, 8) + run_demo(demo_checkpoint, 8) + run_demo(demo_model_parallel, 4) + +``` \ No newline at end of file diff --git a/pytorch/官方教程/63.md b/pytorch/官方教程/63.md new file mode 100644 index 00000000..9f4cfc09 --- /dev/null +++ b/pytorch/官方教程/63.md @@ -0,0 +1,385 @@ +# 用 PyTorch 编写分布式应用 + +> 原文: + +**作者**:[SébArnold](https://seba1511.com) + +先决条件: + +* [PyTorch 分布式概述](../beginner/dist_overview.html) + +在这个简短的教程中,我们将介绍 PyTorch 的分布式包。 我们将了解如何设置分布式设置,如何使用不同的交流策略以及如何查看包的一些内部内容。 + +## 设置 + +PyTorch 中包含的分布式包(即`torch.distributed`)使研究人员和从业人员可以轻松地并行化他们在跨进程和机器集群的计算。 为此,它利用了传递消息的语义,从而允许每个进程将数据传递给任何其他进程。 与多处理包相反,进程可以使用不同的通信后端,而不仅限于在同一台计算机上执行。 + +为了开始,我们需要同时运行多个进程的能力。 如果您有权访问计算群集,则应咨询本地系统管理员或使用您喜欢的协调工具。 (例如 [pdsh](https://linux.die.net/man/1/pdsh),[clustershell](https://cea-hpc.github.io/clustershell/) 或[其他](https://slurm.schedmd.com/))。出于本教程的目的,我们将使用以下模板使用一台计算机并分叉多个进程。 + +```py +"""run.py:""" +#!/usr/bin/env python +import os +import torch +import torch.distributed as dist +from torch.multiprocessing import Process + +def run(rank, size): + """ Distributed function to be implemented later. """ + pass + +def init_process(rank, size, fn, backend='gloo'): + """ Initialize the distributed environment. """ + os.environ['MASTER_ADDR'] = '127.0.0.1' + os.environ['MASTER_PORT'] = '29500' + dist.init_process_group(backend, rank=rank, world_size=size) + fn(rank, size) + +if __name__ == "__main__": + size = 2 + processes = [] + for rank in range(size): + p = Process(target=init_process, args=(rank, size, run)) + p.start() + processes.append(p) + + for p in processes: + p.join() + +``` + +上面的脚本产生了两个进程,每个进程将设置分布式环境,初始化进程组(`dist.init_process_group`),最后执行给定的`run`函数。 + +让我们看一下`init_process`函数。 它确保每个进程都可以使用相同的 IP 地址和端口通过主机进行协调。 请注意,我们使用了`gloo`后端,但其他后端也可用。 (请参阅[第 5.1 节](#communication-backends)),我们将在本教程的结尾部分介绍`dist.init_process_group`中发生的魔术,但实际上,它允许进程通过共享位置相互进行通信。 + +## 点对点通信 + +![Send and Recv](img/f29264b289639882a61fb5c3447b1ecc.png) + +发送和接收 + +数据从一个进程到另一个进程的传输称为点对点通信。 这些是通过`send`和`recv`函数或其*直接*对应部分`isend`和`irecv`实现的。 + +```py +"""Blocking point-to-point communication.""" + +def run(rank, size): + tensor = torch.zeros(1) + if rank == 0: + tensor += 1 + # Send the tensor to process 1 + dist.send(tensor=tensor, dst=1) + else: + # Receive tensor from process 0 + dist.recv(tensor=tensor, src=0) + print('Rank ', rank, ' has data ', tensor[0]) + +``` + +在上面的示例中,两个进程都从零张量开始,然后进程 0 递增张量并将其发送到进程 1,以便它们都以 1.0 结尾。 请注意,进程 1 需要分配内存以存储它将接收的数据。 + +另请注意,`send`/`recv`被**阻塞**:两个过程都停止,直到通信完成。 另一方面,即时消息是**非阻塞**; 脚本继续执行,方法返回`Work`对象,我们可以选择`wait()`作为对象。 + +```py +"""Non-blocking point-to-point communication.""" + +def run(rank, size): + tensor = torch.zeros(1) + req = None + if rank == 0: + tensor += 1 + # Send the tensor to process 1 + req = dist.isend(tensor=tensor, dst=1) + print('Rank 0 started sending') + else: + # Receive tensor from process 0 + req = dist.irecv(tensor=tensor, src=0) + print('Rank 1 started receiving') + req.wait() + print('Rank ', rank, ' has data ', tensor[0]) + +``` + +使用立即数时,我们必须谨慎使用已发送和已接收张量。 由于我们不知道何时将数据传递给其他进程,因此在`req.wait()`完成之前,我们既不应该修改发送的张量也不应该访问接收的张量。 换一种说法, + +* 在`dist.isend()`之后写入`tensor`将导致不确定的行为。 +* 在`dist.irecv()`之后从`tensor`读取将导致不确定的行为。 + +但是,在执行了`req.wait()`之后,我们可以保证已进行通信,并且`tensor[0]`中存储的值为 1.0。 + +当我们希望对流程的通信进行精细控制时,点对点通信非常有用。 它们可用于实现精美的算法,例如[百度的 DeepSpeech](https://github.com/baidu-research/baidu-allreduce) 或 [Facebook 的大规模实验](https://research.fb.com/publications/imagenet1kin1h/)中使用的算法。(请参阅 [4.1 节](#our-own-ring-allreduce)) + +## 集合通信 + +| | | +| --- | --- | +| ![Scatter](img/3aa3584628cb0526c8b0e9d02b15d876.png) | 分散 | +| ![Gather](img/7e8670a3b7cdc7848394514ef1da090a.png) | 收集 | +| ![Reduce](img/1c451df4406aea85e640d1ae7df6df31.png) | 归约 | +| ![All-Reduce](img/0ef9693f0008d5a75aa5ac2b542b83ac.png) | 全部归约 | +| ![Broadcast](img/525847c9d4b48933cb231204a2d13e0e.png) | 广播 | +| ![All-Gather](img/4a48977cd9545f897942a4a4ef1175ac.png) | 全部收集 | + +与点对点通信相反,集合允许跨**组**中所有进程的通信模式。 小组是我们所有过程的子集。 要创建组,我们可以将等级列表传递给`dist.new_group(group)`。 默认情况下,集合在所有进程(也称为**世界**)上执行。 例如,为了获得所有过程中所有张量的总和,我们可以使用`dist.all_reduce(tensor, op, group)`集合。 + +```py +""" All-Reduce example.""" +def run(rank, size): + """ Simple point-to-point communication. """ + group = dist.new_group([0, 1]) + tensor = torch.ones(1) + dist.all_reduce(tensor, op=dist.reduce_op.SUM, group=group) + print('Rank ', rank, ' has data ', tensor[0]) + +``` + +由于我们需要组中所有张量的总和,因此我们将`dist.reduce_op.SUM`用作化简运算符。 一般而言,任何可交换的数学运算都可以用作运算符。 PyTorch 开箱即用,带有 4 个这样的运算符,它们都在元素级运行: + +* `dist.reduce_op.SUM`, +* `dist.reduce_op.PRODUCT`, +* `dist.reduce_op.MAX`, +* `dist.reduce_op.MIN`。 + +除了`dist.all_reduce(tensor, op, group)`之外,PyTorch 中目前共有 6 个集合体。 + +* `dist.broadcast(tensor, src, group)`:将`tensor`从`src`复制到所有其他进程。 +* `dist.reduce(tensor, dst, op, group)`:将`op`应用于所有`tensor`,并将结果存储在`dst`中。 +* `dist.all_reduce(tensor, op, group)`:与`reduce`相同,但是结果存储在所有进程中。 +* `dist.scatter(tensor, src, scatter_list, group)`:将第`i`个张量`scatter_list[i]`复制到第`i`个过程。 +* `dist.gather(tensor, dst, gather_list, group)`:从`dst`中的所有进程复制`tensor`。 +* `dist.all_gather(tensor_list, tensor, group)`:将所有进程中的`tensor`从所有进程复制到`tensor_list`。 +* `dist.barrier(group)`:阻止组中的所有进程,直到每个进程都进入此函数。 + +## 分布式训练 + +**注意**:[您可以在此 GitHub 存储库中找到本节的示例脚本](https://github.com/seba-1511/dist_tuto.pth/)。 + +现在我们了解了分布式模块的工作原理,让我们用它编写一些有用的东西。 我们的目标是复制[`DistributedDataParallel`](https://pytorch.org/docs/stable/nn.html#torch.nn.parallel.DistributedDataParallel)的功能。 当然,这将是一个教学示例,在现实世界中,您应该使用上面链接的经过官方测试,优化的最佳版本。 + +很简单,我们想要实现随机梯度下降的分布式版本。 我们的脚本将允许所有进程在其数据批量上计算其模型的梯度,然后平均其梯度。 为了在更改进程数时确保相似的收敛结果,我们首先必须对数据集进行分区。 (您也可以使用[`tnt.dataset.SplitDataset`](https://github.com/pytorch/tnt/blob/master/torchnet/dataset/splitdataset.py#L4)代替下面的代码段。) + +```py +""" Dataset partitioning helper """ +class Partition(object): + + def __init__(self, data, index): + self.data = data + self.index = index + + def __len__(self): + return len(self.index) + + def __getitem__(self, index): + data_idx = self.index[index] + return self.data[data_idx] + +class DataPartitioner(object): + + def __init__(self, data, sizes=[0.7, 0.2, 0.1], seed=1234): + self.data = data + self.partitions = [] + rng = Random() + rng.seed(seed) + data_len = len(data) + indexes = [x for x in range(0, data_len)] + rng.shuffle(indexes) + + for frac in sizes: + part_len = int(frac * data_len) + self.partitions.append(indexes[0:part_len]) + indexes = indexes[part_len:] + + def use(self, partition): + return Partition(self.data, self.partitions[partition]) + +``` + +使用上面的代码片段,我们现在可以使用以下几行简单地对任何数据集进行分区: + +```py +""" Partitioning MNIST """ +def partition_dataset(): + dataset = datasets.MNIST('./data', train=True, download=True, + transform=transforms.Compose([ + transforms.ToTensor(), + transforms.Normalize((0.1307,), (0.3081,)) + ])) + size = dist.get_world_size() + bsz = 128 / float(size) + partition_sizes = [1.0 / size for _ in range(size)] + partition = DataPartitioner(dataset, partition_sizes) + partition = partition.use(dist.get_rank()) + train_set = torch.utils.data.DataLoader(partition, + batch_size=bsz, + shuffle=True) + return train_set, bsz + +``` + +假设我们有 2 个副本,则每个进程的`train_set`为`60000/2 = 30000`个样本。 我们还将批量大小除以副本数,以使*整个*批量大小保持为 128。 + +现在,我们可以编写我们通常的前向后优化训练代码,并添加一个函数调用来平均模型的梯度。 (以下内容主要是受 [PyTorch MNIST 官方示例](https://github.com/pytorch/examples/blob/master/mnist/main.py)的启发)。 + +```py +""" Distributed Synchronous SGD Example """ +def run(rank, size): + torch.manual_seed(1234) + train_set, bsz = partition_dataset() + model = Net() + optimizer = optim.SGD(model.parameters(), + lr=0.01, momentum=0.5) + + num_batches = ceil(len(train_set.dataset) / float(bsz)) + for epoch in range(10): + epoch_loss = 0.0 + for data, target in train_set: + optimizer.zero_grad() + output = model(data) + loss = F.nll_loss(output, target) + epoch_loss += loss.item() + loss.backward() + average_gradients(model) + optimizer.step() + print('Rank ', dist.get_rank(), ', epoch ', + epoch, ': ', epoch_loss / num_batches) + +``` + +仍然需要执行`average_gradients(model)`函数,该函数只需要一个模型并在整个世界上平均其梯度即可。 + +```py +""" Gradient averaging. """ +def average_gradients(model): + size = float(dist.get_world_size()) + for param in model.parameters(): + dist.all_reduce(param.grad.data, op=dist.reduce_op.SUM) + param.grad.data /= size + +``` + +等等! 我们成功实现了分布式同步 SGD,并且可以在大型计算机集群上训练任何模型。 + +**注意**:虽然从技术上来说最后一句话是是正确的,但要实现同步 SGD 的生产级实现,还需要[更多技巧](https://seba-1511.github.io/dist_blog)。 同样,[请使用经过测试和优化的东西](https://pytorch.org/docs/stable/nn.html#torch.nn.parallel.DistributedDataParallel)。 + +### 我们自己的 Ring-Allreduce + +另一个挑战是,假设我们想实现 DeepSpeech 的高效环网减少。 使用点对点集合很容易实现。 + +```py +""" Implementation of a ring-reduce with addition. """ +def allreduce(send, recv): + rank = dist.get_rank() + size = dist.get_world_size() + send_buff = send.clone() + recv_buff = send.clone() + accum = send.clone() + + left = ((rank - 1) + size) % size + right = (rank + 1) % size + + for i in range(size - 1): + if i % 2 == 0: + # Send send_buff + send_req = dist.isend(send_buff, right) + dist.recv(recv_buff, left) + accum[:] += recv_buff[:] + else: + # Send recv_buff + send_req = dist.isend(recv_buff, right) + dist.recv(send_buff, left) + accum[:] += send_buff[:] + send_req.wait() + recv[:] = accum[:] + +``` + +在上面的脚本中,`allreduce(send, recv)`函数的签名与 PyTorch 中的签名略有不同。 它需要一个`recv`张量,并将所有`send`张量的总和存储在其中。 作为练习留给读者,我们的版本与 DeepSpeech 中的版本之间仍然有一个区别:它们的实现将梯度张量划分为*块*,以便最佳地利用通信带宽。 (提示:[`torch.chunk`](https://pytorch.org/docs/stable/torch.html#torch.chunk)) + +## 高级主题 + +现在,我们准备发现`torch.distributed`的一些更高级的功能。 由于涉及的内容很多,本节分为两个小节: + +1. 通讯后端:我们在这里学习如何使用 MPI 和 Gloo 进行 GPU-GPU 通讯。 +2. 初始化方法:我们了解如何在`dist.init_process_group()`中最佳设置初始协调阶段。 + +### 通信后端 + +`torch.distributed`最优雅的方面之一是它具有抽象能力,并且可以在不同的后端之上构建。 如前所述,目前在 PyTorch 中实现了三个后端:Glo,NCCL 和 MPI。 它们各自具有不同的规格和权衡,具体取决于所需的用例。 可以在此处找到支持功能的比较表。 + +**Gloo 后端** + +到目前为止,我们已经广泛使用 [Gloo 后端](https://github.com/facebookincubator/gloo)。 它作为开发平台非常方便,因为它已包含在预编译的 PyTorch 二进制文件中,并且可在 Linux(自 0.2 开始)和 macOS(自 1.3 开始)上运行。 它支持 CPU 上的所有点对点和集合操作,以及 GPU 上的所有集合操作。 CUDA 张量的集体运算的实现未像 NCCL 后端提供的那样优化。 + +如您所知,如果在 GPU 上放置`model`,我们的分布式 SGD 示例将无法正常工作。 为了使用多个 GPU,让我们还进行以下修改: + +1. 使用`device = torch.device("cuda:{}".format(rank))` +2. `model = Net() => model = Net().to(device)` +3. 使用`data, target = data.to(device), target.to(device)` + +经过上述修改,我们的模型现在可以在两个 GPU 上训练,您可以使用`watch nvidia-smi`监视其使用情况。 + +**MPI 后端** + +消息传递接口(MPI)是来自高性能计算领域的标准化工具。 它允许进行点对点和集体通信,并且是`torch.distributed` API 的主要灵感。 存在几种针对不同目的而优化的 MPI 实现(例如 [Open-MPI](https://www.open-mpi.org/),[MVAPICH2](http://mvapich.cse.ohio-state.edu/),[Intel MPI](https://software.intel.com/en-us/intel-mpi-library))。 使用 MPI 后端的优势在于 MPI 在大型计算机群集上的广泛可用性-和高水平的优化。 [一些](https://developer.nvidia.com/mvapich)[最近的](https://developer.nvidia.com/ibm-spectrum-mpi)[实现](https://www.open-mpi.org/)也能够利用 CUDA IPC 和 GPU Direct 技术,以避免通过 CPU 进行内存复制。 + +不幸的是,PyTorch 的二进制文件不能包含 MPI 实现,我们将不得不手动对其进行重新编译。 幸运的是,鉴于编译后,PyTorch 会单独查看以查找可用的 MPI 实现,因此此过程相当简单。 [以下步骤通过从源安装 PyTorch 来安装 MPI 后端](https://github.com/pytorch/pytorch#from-source)。 + +1. 创建并激活 Anaconda 环境,按照[指南](https://github.com/pytorch/pytorch#from-source)的要求安装所有先决条件,但是**尚未**运行。 +2. 选择并安装您喜欢的 MPI 实现。 请注意,启用支持 CUDA 的 MPI 可能需要一些其他步骤。 在我们的情况下,我们将坚持不支持 GPU 的 Open-MPI:`conda install -c conda-forge openmpi` +3. 现在,转到克隆的 PyTorch 存储库并执行`python setup.py install`。 + +为了测试我们新安装的后端,需要进行一些修改。 + +1. 将`if __name__ == '__main__':`下的内容替换为`init_process(0, 0, run, backend='mpi')`。 +2. 运行`mpirun -n 4 python myscript.py`。 + +这些更改的原因是,MPI 需要在生成进程之前创建自己的环境。 MPI 还将生成自己的进程,并执行[初始化方法](#initialization-methods)中描述的握手,使`init_process_group`的`rank`和`size`参数多余。 实际上,这非常强大,因为您可以将其他参数传递给`mpirun`,以便为每个进程定制计算资源。 (诸如每个进程的内核数,将计算机手动分配给特定级别之类的东西,以及[其它](https://www.open-mpi.org/faq/?category=running#mpirun-hostfile)。)这样做,您应该获得与其他通信后端相同的熟悉输出。 + +**NCCL 后端** + +[NCCL 后端](https://github.com/nvidia/nccl)提供了针对 CUDA 张量的集体运算的优化实现。 如果仅对集体操作使用 CUDA 张量,请考虑使用此后端以获得最佳性能。 NCCL 后端包含在具有 CUDA 支持的预构建二进制文件中。 + +### 初始化方法 + +为了完成本教程,我们来谈谈我们调用的第一个函数:`dist.init_process_group(backend, init_method)`。 特别是,我们将介绍负责每个过程之间初始协调步骤的不同初始化方法。 这些方法使您可以定义协调方式。 根据您的硬件设置,这些方法之一自然应该比其他方法更合适。 除了以下各节之外,您还应该查看[官方文档](https://pytorch.org/docs/stable/distributed.html#initialization)。 + +**环境变量** + +在本教程中,我们一直在使用环境变量初始化方法。 通过在所有机器上设置以下四个环境变量,所有进程将能够正确连接到主服务器,获取有关其他进程的信息,最后与它们握手。 + +* `MASTER_PORT`:计算机上的空闲端口,它将托管等级为 0 的进程。 +* `MASTER_ADDR`:将以等级 0 托管进程的计算机的 IP 地址。 +* `WORLD_SIZE`:进程总数,以便主机知道要等待多少个工作器。 +* `RANK`:每个进程的等级,因此他们将知道它是否是工作器的主人。 + +**共享文件系统** + +共享文件系统要求所有进程都有权访问共享文件系统,并将通过共享文件进行协调。 这意味着每个进程都将打开文件,写入文件信息,然后等到每个人都打开文件。 之后,所有必需的信息将可用于所有过程。 为了避免争用情况,文件系统必须通过[`fcntl`](http://man7.org/linux/man-pages/man2/fcntl.2.html)支持锁定。 + +```py +dist.init_process_group( + init_method='file:///mnt/nfs/sharedfile', + rank=args.rank, + world_size=4) + +``` + +**TCP** + +通过提供等级 0 和可访问的端口号的进程的 IP 地址,可以实现通过 TCP 进行初始化。 在这里,所有工作器都可以连接到等级为 0 的流程,并交换有关如何相互联系的信息。 + +```py +dist.init_process_group( + init_method='tcp://10.1.1.20:23456', + rank=args.rank, + world_size=4) + +``` + +
+ +**致谢** + +
+ +我要感谢 PyTorch 开发人员在实现,文档和测试方面做得如此出色。 当代码不清楚时,我总是可以依靠[文档](https://pytorch.org/docs/stable/distributed.html)或[测试](https://github.com/pytorch/pytorch/blob/master/test/test_distributed.py)来找到答案。 我尤其要感谢 Soumith Chintala,Adam Paszke 和 Natalia Gimelshein 提供的有见地的评论并回答了有关初稿的问题。 \ No newline at end of file diff --git a/pytorch/官方教程/64.md b/pytorch/官方教程/64.md new file mode 100644 index 00000000..8a53aba3 --- /dev/null +++ b/pytorch/官方教程/64.md @@ -0,0 +1,467 @@ +# 分布式 RPC 框架入门 + +> 原文: + +**作者**:[Shen Li](https://mrshenli.github.io/) + +先决条件: + +* [PyTorch 分布式概述](../beginner/dist_overview.html) +* [RPC API 文档](https://pytorch.org/docs/master/rpc.html) + +本教程使用两个简单的示例来演示如何使用[`torch.distributed.rpc`](https://pytorch.org/docs/master/rpc.html)包构建分布式训练,该包首先在 PyTorch v1.4 中作为原型功能引入。 这两个示例的源代码可以在 [PyTorch 示例](https://github.com/pytorch/examples)中找到。 + +先前的教程[分布式数据并行入门](ddp_tutorial.html)和[使用 PyTorch](dist_tuto.html) 编写分布式应用,描述了[`DistributedDataParallel`](https://pytorch.org/docs/stable/_modules/torch/nn/parallel/distributed.html),该模型支持特定的训练范例,该模型可在多个进程之间复制,每个进程都处理输入数据的拆分。 有时,您可能会遇到需要不同训练范例的场景。 例如: + +1. 在强化学习中,从环境中获取训练数据可能相对昂贵,而模型本身可能很小。 在这种情况下,产生多个并行运行的观察者并共享一个智能体可能会很有用。 在这种情况下,智能体将在本地负责训练,但是应用仍将需要库在观察者和训练者之间发送和接收数据。 +2. 您的模型可能太大,无法容纳在一台计算机上的 GPU 中,因此需要一个库来帮助将模型拆分到多台计算机上。 或者,您可能正在实现[参数服务器](https://www.cs.cmu.edu/~muli/file/parameter_server_osdi14.pdf)训练框架,其中模型参数和训练器位于不同的机器上。 + +[`torch.distributed.rpc`](https://pytorch.org/docs/master/rpc.html)包可以帮助解决上述情况。 在情况 1 中, [RPC](https://pytorch.org/docs/master/rpc.html#rpc) 和 [RRef](https://pytorch.org/docs/master/rpc.html#rref) 允许将数据从一个工作程序发送到另一个工作程序,同时轻松引用远程数据对象。 在情况 2 中,[分布式 Autograd](https://pytorch.org/docs/master/rpc.html#distributed-autograd-framework) 和[分布式优化器](https://pytorch.org/docs/master/rpc.html#module-torch.distributed.optim)使执行反向传递和优化器步骤就像本地训练一样。 在接下来的两节中,我们将使用强化学习示例和语言模型示例来演示[`torch.distributed.rpc`](https://pytorch.org/docs/master/rpc.html)的 API。 请注意,本教程并非旨在构建最准确或最有效的模型来解决给定的问题,相反,此处的主要目标是演示如何使用[`torch.distributed.rpc`](https://pytorch.org/docs/master/rpc.html)包来构建分布式训练应用。 + +## 使用 RPC 和 RRef 的分布式强化学习 + +本节介绍了使用 RPC 建立玩具分布式强化学习模型以解决 [OpenAI Gym](https://gym.openai.com) 中的 CartPole-v1 的步骤。 策略代码主要是从现有的单线程[示例](https://github.com/pytorch/examples/blob/master/reinforcement_learning)中借用的,如下所示。 我们将跳过`Policy`设计的详细信息,并将重点介绍 RPC 的用法。 + +```py +import torch.nn as nn +import torch.nn.functional as F + +class Policy(nn.Module): + + def __init__(self): + super(Policy, self).__init__() + self.affine1 = nn.Linear(4, 128) + self.dropout = nn.Dropout(p=0.6) + self.affine2 = nn.Linear(128, 2) + + self.saved_log_probs = [] + self.rewards = [] + + def forward(self, x): + x = self.affine1(x) + x = self.dropout(x) + x = F.relu(x) + action_scores = self.affine2(x) + return F.softmax(action_scores, dim=1) + +``` + +首先,让我们准备一个助手,以在`RRef`的所有者工作程序上远程运行函数。 您将在本教程的示例中的多个地方发现该函数。 理想情况下,`torch.distributed.rpc`包应立即提供这些助手函数。 例如,如果应用可以直接调用`RRef.some_func(*arg)`,然后将其转换为`RRef`所有者的 RPC,将会更容易。 在[`pytorch/pytorch#31743`](https://github.com/pytorch/pytorch/issues/31743)中跟踪了此 API 的进度。 + +```py +from torch.distributed.rpc import rpc_sync + +def _call_method(method, rref, *args, **kwargs): + return method(rref.local_value(), *args, **kwargs) + +def _remote_method(method, rref, *args, **kwargs): + args = [method, rref] + list(args) + return rpc_sync(rref.owner(), _call_method, args=args, kwargs=kwargs) + +# to call a function on an rref, we could do the following +# _remote_method(some_func, rref, *args) + +``` + +我们准备介绍观察员。 在此示例中,每个观察者创建自己的环境,并等待智能体的命令来运行剧集。 在每个剧集中,一个观察者最多循环`n_steps`个迭代,并且在每个迭代中,它使用 RPC 将其环境状态传递给智能体并取回操作。 然后,它将该操作应用于其环境,并从环境中获取奖励和下一个状态。 之后,观察者使用另一个 RPC 向智能体报告奖励。 同样,请注意,这显然不是最有效的观察者实现。 例如,一个简单的优化可能是将当前状态和最后的报酬打包到一个 RPC 中,以减少通信开销。 但是,目标是演示 RPC API,而不是为 CartPole 构建最佳的求解器。 因此,在此示例中,让逻辑保持简单,并明确两个步骤。 + +```py +import argparse +import gym +import torch.distributed.rpc as rpc + +parser = argparse.ArgumentParser( + description="RPC Reinforcement Learning Example", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, +) + +parser.add_argument('--world_size', default=2, help='Number of workers') +parser.add_argument('--log_interval', default=1, help='Log every log_interval episodes') +parser.add_argument('--gamma', default=0.1, help='how much to value future rewards') +parser.add_argument('--seed', default=1, help='random seed for reproducibility') +args = parser.parse_args() + +class Observer: + + def __init__(self): + self.id = rpc.get_worker_info().id + self.env = gym.make('CartPole-v1') + self.env.seed(args.seed) + + def run_episode(self, agent_rref, n_steps): + state, ep_reward = self.env.reset(), 0 + for step in range(n_steps): + # send the state to the agent to get an action + action = _remote_method(Agent.select_action, agent_rref, self.id, state) + + # apply the action to the environment, and get the reward + state, reward, done, _ = self.env.step(action) + + # report the reward to the agent for training purpose + _remote_method(Agent.report_reward, agent_rref, self.id, reward) + + if done: + break + +``` + +agent 的代码稍微复杂一点,我们将其分成多个部分。 在此示例中,智能体既充当训练者又充当主角色,以便它向多个分布式观察者发送命令以运行剧集,并且还记录本地的所有动作和奖励,这些动作和奖赏将在每个剧集之后的训练阶段使用。 下面的代码显示了`Agent`构造器,其中大多数行都在初始化各种组件。 最后的循环在其他工作器上远程初始化观察者,并在本地将`RRefs`保留给这些观察者。 智能体稍后将使用那些观察者`RRefs`发送命令。 应用无需担心`RRefs`的寿命。 每个`RRef`的所有者维护一个引用计数图以跟踪其生命周期,并保证只要该`RRef`的任何活动用户都不会删除远程数据对象。 有关详细信息,请参考`RRef` [设计文档](https://pytorch.org/docs/master/notes/rref.html)。 + +```py +import gym +import numpy as np + +import torch +import torch.distributed.rpc as rpc +import torch.optim as optim +from torch.distributed.rpc import RRef, rpc_async, remote +from torch.distributions import Categorical + +class Agent: + def __init__(self, world_size): + self.ob_rrefs = [] + self.agent_rref = RRef(self) + self.rewards = {} + self.saved_log_probs = {} + self.policy = Policy() + self.optimizer = optim.Adam(self.policy.parameters(), lr=1e-2) + self.eps = np.finfo(np.float32).eps.item() + self.running_reward = 0 + self.reward_threshold = gym.make('CartPole-v1').spec.reward_threshold + for ob_rank in range(1, world_size): + ob_info = rpc.get_worker_info(OBSERVER_NAME.format(ob_rank)) + self.ob_rrefs.append(remote(ob_info, Observer)) + self.rewards[ob_info.id] = [] + self.saved_log_probs[ob_info.id] = [] + +``` + +接下来,智能体向观察者公开两个 API,以供他们选择动作和报告奖励。 这些函数仅在智能体上本地运行,但是将由观察者通过 RPC 触发。 + +```py +class Agent: + ... + def select_action(self, ob_id, state): + state = torch.from_numpy(state).float().unsqueeze(0) + probs = self.policy(state) + m = Categorical(probs) + action = m.sample() + self.saved_log_probs[ob_id].append(m.log_prob(action)) + return action.item() + + def report_reward(self, ob_id, reward): + self.rewards[ob_id].append(reward) + +``` + +让我们在智能体上添加`run_episode`函数,该函数告诉所有观察者执行片段。 在此函数中,它首先创建一个列表,以从异步 RPC 收集期货,然后在所有观察者`RRefs`上循环以生成异步 RPC。 在这些 RPC 中,智能体还将自身的`RRef`传递给观察者,以便观察者也可以在智能体上调用函数。 如上所示,每个观察者都将 RPC 返回给智能体,它们是嵌套的 RPC。 在每个剧集之后,`saved_log_probs`和`rewards`将包含记录的动作概率和奖励。 + +```py +class Agent: + ... + def run_episode(self, n_steps=0): + futs = [] + for ob_rref in self.ob_rrefs: + # make async RPC to kick off an episode on all observers + futs.append( + rpc_async( + ob_rref.owner(), + _call_method, + args=(Observer.run_episode, ob_rref, self.agent_rref, n_steps) + ) + ) + + # wait until all obervers have finished this episode + for fut in futs: + fut.wait() + +``` + +最后,在一集之后,智能体需要训练模型,该模型在下面的`finish_episode`函数中实现。 此函数中没有 RPC,并且大多数是从单线程[示例](https://github.com/pytorch/examples/blob/master/reinforcement_learning)中借用的。 因此,我们跳过描述其内容。 + +```py +class Agent: + ... + def finish_episode(self): + # joins probs and rewards from different observers into lists + R, probs, rewards = 0, [], [] + for ob_id in self.rewards: + probs.extend(self.saved_log_probs[ob_id]) + rewards.extend(self.rewards[ob_id]) + + # use the minimum observer reward to calculate the running reward + min_reward = min([sum(self.rewards[ob_id]) for ob_id in self.rewards]) + self.running_reward = 0.05 * min_reward + (1 - 0.05) * self.running_reward + + # clear saved probs and rewards + for ob_id in self.rewards: + self.rewards[ob_id] = [] + self.saved_log_probs[ob_id] = [] + + policy_loss, returns = [], [] + for r in rewards[::-1]: + R = r + args.gamma * R + returns.insert(0, R) + returns = torch.tensor(returns) + returns = (returns - returns.mean()) / (returns.std() + self.eps) + for log_prob, R in zip(probs, returns): + policy_loss.append(-log_prob * R) + self.optimizer.zero_grad() + policy_loss = torch.cat(policy_loss).sum() + policy_loss.backward() + self.optimizer.step() + return min_reward + +``` + +使用`Policy`,`Observer`和`Agent`类,我们准备启动多个过程来执行分布式训练。 在此示例中,所有进程都运行相同的`run_worker`函数,并且它们使用等级来区分其角色。 等级 0 始终是智能体,其他所有等级都是观察者。 智能体通过重复调用`run_episode`和`finish_episode`作为主设备,直到运行的奖励超过环境指定的奖励阈值为止。 所有观察者都被动地等待来自智能体的命令。 该代码由[`rpc.init_rpc`](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.init_rpc)和[`rpc.shutdown`](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.shutdown)包装,它们分别初始化和终止 RPC 实例。 [API 页面](https://pytorch.org/docs/master/rpc.html)中提供了更多详细信息。 + +```py +import os +from itertools import count + +import torch.multiprocessing as mp + +AGENT_NAME = "agent" +OBSERVER_NAME="obs" +TOTAL_EPISODE_STEP = 100 + +def run_worker(rank, world_size): + os.environ['MASTER_ADDR'] = 'localhost' + os.environ['MASTER_PORT'] = '29500' + if rank == 0: + # rank0 is the agent + rpc.init_rpc(AGENT_NAME, rank=rank, world_size=world_size) + + agent = Agent(world_size) + for i_episode in count(1): + n_steps = int(TOTAL_EPISODE_STEP / (args.world_size - 1)) + agent.run_episode(n_steps=n_steps) + last_reward = agent.finish_episode() + + if i_episode % args.log_interval == 0: + print('Episode {}\tLast reward: {:.2f}\tAverage reward: {:.2f}'.format( + i_episode, last_reward, agent.running_reward)) + + if agent.running_reward > agent.reward_threshold: + print("Solved! Running reward is now {}!".format(agent.running_reward)) + break + else: + # other ranks are the observer + rpc.init_rpc(OBSERVER_NAME.format(rank), rank=rank, world_size=world_size) + # observers passively waiting for instructions from the agent + + # block until all rpcs finish, and shutdown the RPC instance + rpc.shutdown() + +mp.spawn( + run_worker, + args=(args.world_size, ), + nprocs=args.world_size, + join=True +) + +``` + +以下是使用`world_size = 2`进行训练时的一些示例输出。 + +```py +Episode 10 Last reward: 26.00 Average reward: 10.01 +Episode 20 Last reward: 16.00 Average reward: 11.27 +Episode 30 Last reward: 49.00 Average reward: 18.62 +Episode 40 Last reward: 45.00 Average reward: 26.09 +Episode 50 Last reward: 44.00 Average reward: 30.03 +Episode 60 Last reward: 111.00 Average reward: 42.23 +Episode 70 Last reward: 131.00 Average reward: 70.11 +Episode 80 Last reward: 87.00 Average reward: 76.51 +Episode 90 Last reward: 86.00 Average reward: 95.93 +Episode 100 Last reward: 13.00 Average reward: 123.93 +Episode 110 Last reward: 33.00 Average reward: 91.39 +Episode 120 Last reward: 73.00 Average reward: 76.38 +Episode 130 Last reward: 137.00 Average reward: 88.08 +Episode 140 Last reward: 89.00 Average reward: 104.96 +Episode 150 Last reward: 97.00 Average reward: 98.74 +Episode 160 Last reward: 150.00 Average reward: 100.87 +Episode 170 Last reward: 126.00 Average reward: 104.38 +Episode 180 Last reward: 500.00 Average reward: 213.74 +Episode 190 Last reward: 322.00 Average reward: 300.22 +Episode 200 Last reward: 165.00 Average reward: 272.71 +Episode 210 Last reward: 168.00 Average reward: 233.11 +Episode 220 Last reward: 184.00 Average reward: 195.02 +Episode 230 Last reward: 284.00 Average reward: 208.32 +Episode 240 Last reward: 395.00 Average reward: 247.37 +Episode 250 Last reward: 500.00 Average reward: 335.42 +Episode 260 Last reward: 500.00 Average reward: 386.30 +Episode 270 Last reward: 500.00 Average reward: 405.29 +Episode 280 Last reward: 500.00 Average reward: 443.29 +Episode 290 Last reward: 500.00 Average reward: 464.65 +Solved! Running reward is now 475.3163778435275! + +``` + +在此示例中,我们展示了如何使用 RPC 作为通信工具来跨工作器传递数据,以及如何使用 RRef 引用远程对象。 的确,您可以直接在`ProcessGroup` `send`和`recv` API 之上构建整个结构,也可以使用其他通信/ RPC 库。 但是,通过使用`torch.distributed.rpc`,您可以在后台获得本机支持并不断优化性能。 + +接下来,我们将展示如何将 RPC 和 RRef 与分布式 Autograd 和分布式优化器结合起来执行分布式模型并行训练。 + +## 使用分布式 Autograd 和分布式优化器的分布式 RNN + +在本节中,我们将使用 RNN 模型来展示如何使用 RPC API 构建分布式模型并行训练。 示例 RNN 模型非常小,可以轻松地放入单个 GPU 中,但是我们仍将其层划分为两个不同的工作器来演示这一想法。 开发人员可以应用类似的技术在多个设备和机器上分布更大的模型。 + +RNN 模型设计是从 PyTorch [示例](https://github.com/pytorch/examples/tree/master/word_language_model)存储库中的词语言模型中借用的,该存储库包含三个主要组件,一个嵌入表,一个`LSTM`层和一个解码器。 下面的代码将嵌入表和解码器包装到子模块中,以便它们的构造器可以传递给 RPC API。 在`EmbeddingTable`子模块中,我们有意将`Embedding`层放在 GPU 上以涵盖用例。 在 v1.4 中,RPC 始终在目标工作线程上创建 CPU 张量参数或返回值。 如果函数使用 GPU 张量,则需要将其显式移动到适当的设备。 + +```py +class EmbeddingTable(nn.Module): + r""" + Encoding layers of the RNNModel + """ + def __init__(self, ntoken, ninp, dropout): + super(EmbeddingTable, self).__init__() + self.drop = nn.Dropout(dropout) + self.encoder = nn.Embedding(ntoken, ninp).cuda() + self.encoder.weight.data.uniform_(-0.1, 0.1) + + def forward(self, input): + return self.drop(self.encoder(input.cuda()).cpu() + +class Decoder(nn.Module): + def __init__(self, ntoken, nhid, dropout): + super(Decoder, self).__init__() + self.drop = nn.Dropout(dropout) + self.decoder = nn.Linear(nhid, ntoken) + self.decoder.bias.data.zero_() + self.decoder.weight.data.uniform_(-0.1, 0.1) + + def forward(self, output): + return self.decoder(self.drop(output)) + +``` + +使用上述子模块,我们现在可以使用 RPC 将它们组合在一起以创建 RNN 模型。 在下面的代码中,`ps`代表参数服务器,该服务器托管嵌入表和解码器的参数。 构造器使用[远程](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.remote) API 在参数服务器上创建`EmbeddingTable`对象和`Decoder`对象,并在本地创建`LSTM`子模块。 在前进过程中,训练器使用`EmbeddingTable` `RRef`查找远程子模块,然后使用 RPC 将输入数据传递到`EmbeddingTable`,并获取查找结果。 然后,它通过本地`LSTM`层运行嵌入,最后使用另一个 RPC 将输出发送到`Decoder`子模块。 通常,要实现分布式模型并行训练,开发人员可以将模型分为多个子模块,调用 RPC 远程创建子模块实例,并在必要时使用`RRef`查找它们。 正如您在下面的代码中看到的那样,它看起来与单机模型并行训练非常相似。 主要区别是用 RPC 函数替换了`Tensor.to(device)`。 + +```py +class RNNModel(nn.Module): + def __init__(self, ps, ntoken, ninp, nhid, nlayers, dropout=0.5): + super(RNNModel, self).__init__() + + # setup embedding table remotely + self.emb_table_rref = rpc.remote(ps, EmbeddingTable, args=(ntoken, ninp, dropout)) + # setup LSTM locally + self.rnn = nn.LSTM(ninp, nhid, nlayers, dropout=dropout) + # setup decoder remotely + self.decoder_rref = rpc.remote(ps, Decoder, args=(ntoken, nhid, dropout)) + + def forward(self, input, hidden): + # pass input to the remote embedding table and fetch emb tensor back + emb = _remote_method(EmbeddingTable.forward, self.emb_table_rref, input) + output, hidden = self.rnn(emb, hidden) + # pass output to the rremote decoder and get the decoded output back + decoded = _remote_method(Decoder.forward, self.decoder_rref, output) + return decoded, hidden + +``` + +在介绍分布式优化器之前,让我们添加一个辅助函数来生成模型参数的 RRef 列表,该列表将由分布式优化器使用。 在本地训练中,应用可以调用`Module.parameters()`来获取对所有参数张量的引用,并将其传递给本地优化器以进行后续更新。 但是,由于某些参数存在于远程计算机上,因此同一 API 在分布式训练方案中不起作用。 因此,分布式优化器不采用参数`Tensors`的列表,而是采用`RRefs`的列表,每个模型参数一个`RRef`用于本地和远程模型参数。 辅助函数非常简单,只需调用`Module.parameters()`并在每个参数上创建一个本地`RRef`。 + +```py +def _parameter_rrefs(module): + param_rrefs = [] + for param in module.parameters(): + param_rrefs.append(RRef(param)) + return param_rrefs + +``` + +然后,由于`RNNModel`包含三个子模块,因此我们需要调用`_parameter_rrefs` 3 次,并将其包装到另一个辅助函数中。 + +```py +class RNNModel(nn.Module): + ... + def parameter_rrefs(self): + remote_params = [] + # get RRefs of embedding table + remote_params.extend(_remote_method(_parameter_rrefs, self.emb_table_rref)) + # create RRefs for local parameters + remote_params.extend(_parameter_rrefs(self.rnn)) + # get RRefs of decoder + remote_params.extend(_remote_method(_parameter_rrefs, self.decoder_rref)) + return remote_params + +``` + +现在,我们准备实现训练循环。 初始化模型参数后,我们创建`RNNModel`和`DistributedOptimizer`。 分布式优化器将采用参数`RRefs`的列表,查找所有不同的所有者工作器,并在每个所有者工作器上创建给定的本地优化器(即,在这种情况下,您也可以使用其他本地优化器`SGD`) 使用给定的参数(即`lr=0.05`)。 + +在训练循环中,它首先创建一个分布式 Autograd 上下文,这将帮助分布式 Autograd 引擎查找梯度和涉及的 RPC 发送/接收函数。 分布式 Autograd 引擎的设计详细信息可以在其[设计说明](https://pytorch.org/docs/master/notes/distributed_autograd.html)中找到。 然后,它像本地模型一样开始正向传播,并运行分布式后向传递。 对于后向分布,您只需要指定一个根列表,在这种情况下,就是损失`Tensor`。 分布式 Autograd 引擎将自动遍历分布式图并正确编写梯度。 接下来,它在分布式优化器上运行`step`函数,该函数将与所有涉及的本地优化器联系以更新模型参数。 与本地训练相比,一个较小的差异是您不需要运行`zero_grad()`,因为每个 Autograd 上下文都有专用的空间来存储梯度,并且在每次迭代创建上下文时,来自不同迭代的那些梯度不会累积到同一组`Tensors`。 + +```py +def run_trainer(): + batch = 5 + ntoken = 10 + ninp = 2 + + nhid = 3 + nindices = 3 + nlayers = 4 + hidden = ( + torch.randn(nlayers, nindices, nhid), + torch.randn(nlayers, nindices, nhid) + ) + + model = rnn.RNNModel('ps', ntoken, ninp, nhid, nlayers) + + # setup distributed optimizer + opt = DistributedOptimizer( + optim.SGD, + model.parameter_rrefs(), + lr=0.05, + ) + + criterion = torch.nn.CrossEntropyLoss() + + def get_next_batch(): + for _ in range(5): + data = torch.LongTensor(batch, nindices) % ntoken + target = torch.LongTensor(batch, ntoken) % nindices + yield data, target + + # train for 10 iterations + for epoch in range(10): + for data, target in get_next_batch(): + # create distributed autograd context + with dist_autograd.context() as context_id: + hidden[0].detach_() + hidden[1].detach_() + output, hidden = model(data, hidden) + loss = criterion(output, target) + # run distributed backward pass + dist_autograd.backward(context_id, [loss]) + # run distributed optimizer + opt.step(context_id) + # not necessary to zero grads since they are + # accumulated into the distributed autograd context + # which is reset every iteration. + print("Training epoch {}".format(epoch)) + +``` + +最后,让我们添加一些粘合代码以启动参数服务器和训练器流程。 + +```py +def run_worker(rank, world_size): + os.environ['MASTER_ADDR'] = 'localhost' + os.environ['MASTER_PORT'] = '29500' + if rank == 1: + rpc.init_rpc("trainer", rank=rank, world_size=world_size) + _run_trainer() + else: + rpc.init_rpc("ps", rank=rank, world_size=world_size) + # parameter server do nothing + pass + + # block until all rpcs finish + rpc.shutdown() + +if __name__=="__main__": + world_size = 2 + mp.spawn(run_worker, args=(world_size, ), nprocs=world_size, join=True) + +``` \ No newline at end of file diff --git a/pytorch/官方教程/65.md b/pytorch/官方教程/65.md new file mode 100644 index 00000000..901fb97b --- /dev/null +++ b/pytorch/官方教程/65.md @@ -0,0 +1,412 @@ +# 使用分布式 RPC 框架实现参数服务器 + +> 原文: + +**作者**: [Rohan Varma](https://github.com/rohan-varma) + +先决条件: + +* [PyTorch 分布式概述](../beginner/dist_overview.html) +* [RPC API 文档](https://pytorch.org/docs/master/rpc.html) + +本教程介绍了一个简单的示例,该示例使用 PyTorch 的[分布式 RPC 框架](https://pytorch.org/docs/stable/rpc.html)实现参数服务器。 参数服务器框架是一种范例,其中一组服务器存储参数(例如大型嵌入表),并且多个训练人员查询参数服务器以检索最新参数。 这些训练器可以在本地运行训练循环,并偶尔与参数服务器同步以获得最新参数。 有关参数服务器方法的更多信息,请查阅[本文](https://www.cs.cmu.edu/~muli/file/parameter_server_osdi14.pdf)。 + +使用分布式 RPC 框架,我们将构建一个示例,其中多个训练器使用 RPC 与同一个参数服务器进行通信,并使用 [RRef](https://pytorch.org/docs/stable/rpc.html#torch.distributed.rpc.RRef) 访问远程参数服务器实例上的状态。 每位训练器将通过使用分布式 Autograd 跨多个节点拼接 Autograd 图,以分布式方式启动其专用的反向传递。 + +**注意**:本教程介绍了分布式 RPC 框架的用法,该方法可用于将模型拆分到多台计算机上,或用于实现参数服务器训练策略,在该策略中,网络训练器可以获取托管在另一台计算机上的参数。 相反,如果您要跨多个 GPU 复制模型,请参阅[分布式数据并行教程](https://pytorch.org/tutorials/intermediate/ddp_tutorial.html)。 还有另一个 [RPC 教程](https://pytorch.org/tutorials/intermediate/rpc_tutorial.html),涵盖了强化学习和 RNN 用例。 + +让我们从熟悉的地方开始:导入我们所需的模块并定义一个简单的 ConvNet,它将在 MNIST 数据集上进行训练。 以下网络是从[`pytorch/examples`仓库](https://github.com/pytorch/examples/tree/master/mnist)中定义的网络中广泛采用的。 + +```py +import argparse +import os +import time +from threading import Lock + +import torch +import torch.distributed.autograd as dist_autograd +import torch.distributed.rpc as rpc +import torch.multiprocessing as mp +import torch.nn as nn +import torch.nn.functional as F +from torch import optim +from torch.distributed.optim import DistributedOptimizer +from torchvision import datasets, transforms + +# --------- MNIST Network to train, from pytorch/examples ----- + +class Net(nn.Module): + def __init__(self, num_gpus=0): + super(Net, self).__init__() + print(f"Using {num_gpus} GPUs to train") + self.num_gpus = num_gpus + device = torch.device( + "cuda:0" if torch.cuda.is_available() and self.num_gpus > 0 else "cpu") + print(f"Putting first 2 convs on {str(device)}") + # Put conv layers on the first cuda device, or CPU if no cuda device + self.conv1 = nn.Conv2d(1, 32, 3, 1).to(device) + self.conv2 = nn.Conv2d(32, 64, 3, 1).to(device) + # Put rest of the network on the 2nd cuda device, if there is one + if "cuda" in str(device) and num_gpus > 1: + device = torch.device("cuda:1") + + print(f"Putting rest of layers on {str(device)}") + self.dropout1 = nn.Dropout2d(0.25).to(device) + self.dropout2 = nn.Dropout2d(0.5).to(device) + self.fc1 = nn.Linear(9216, 128).to(device) + self.fc2 = nn.Linear(128, 10).to(device) + + def forward(self, x): + x = self.conv1(x) + x = F.relu(x) + x = self.conv2(x) + x = F.max_pool2d(x, 2) + + x = self.dropout1(x) + x = torch.flatten(x, 1) + # Move tensor to next device if necessary + next_device = next(self.fc1.parameters()).device + x = x.to(next_device) + + x = self.fc1(x) + x = F.relu(x) + x = self.dropout2(x) + x = self.fc2(x) + output = F.log_softmax(x, dim=1) + return output + +``` + +接下来,让我们定义一些辅助函数,这些函数将对其余脚本有用。 下面使用[`rpc_sync`](https://pytorch.org/docs/stable/rpc.html#torch.distributed.rpc.rpc_sync)和 [RRef](https://pytorch.org/docs/stable/rpc.html#torch.distributed.rpc.RRef) 来定义一个函数,该函数在远程节点上的对象上调用给定方法。 下面,通过`rref`参数指定了对远程对象的句柄,并在其拥有的节点`rref.owner()`上运行它。 在调用者节点上,我们通过使用`rpc_sync`同步运行此命令,这意味着我们将阻塞直到收到响应。 + +```py +# --------- Helper Methods -------------------- + +# On the local node, call a method with first arg as the value held by the +# RRef. Other args are passed in as arguments to the function called. +# Useful for calling instance methods. method could be any matching function, including +# class methods. +def call_method(method, rref, *args, **kwargs): + return method(rref.local_value(), *args, **kwargs) + +# Given an RRef, return the result of calling the passed in method on the value +# held by the RRef. This call is done on the remote node that owns +# the RRef and passes along the given argument. +# Example: If the value held by the RRef is of type Foo, then +# remote_method(Foo.bar, rref, arg1, arg2) is equivalent to calling +# .bar(arg1, arg2) on the remote node and getting the result +# back. + +def remote_method(method, rref, *args, **kwargs): + args = [method, rref] + list(args) + return rpc.rpc_sync(rref.owner(), call_method, args=args, kwargs=kwargs) + +``` + +现在,我们准备定义参数服务器。 我们将子类化`nn.Module`,并将句柄保存到上面定义的网络中。 我们还将保存一个输入设备,该输入设备将是在调用模型之前将输入传输到的设备。 + +```py +# --------- Parameter Server -------------------- +class ParameterServer(nn.Module): + def __init__(self, num_gpus=0): + super().__init__() + model = Net(num_gpus=num_gpus) + self.model = model + self.input_device = torch.device( + "cuda:0" if torch.cuda.is_available() and num_gpus > 0 else "cpu") + +``` + +接下来,我们将定义前进通道。 请注意,无论模型输出的设备如何,我们都会将输出移至 CPU,因为分布式 RPC 框架当前仅支持通过 RPC 发送 CPU 张量。 由于有可能在调用者/被调用者上使用不同的设备(CPU/GPU),因此我们有意禁用通过 RPC 发送 CUDA 张量,但在将来的版本中可能会支持此功能。 + +```py +class ParameterServer(nn.Module): +... + def forward(self, inp): + inp = inp.to(self.input_device) + out = self.model(inp) + # This output is forwarded over RPC, which as of 1.5.0 only accepts CPU tensors. + # Tensors must be moved in and out of GPU memory due to this. + out = out.to("cpu") + return out + +``` + +接下来,我们将定义一些其他函数,可用于训练和验证。 第一个`get_dist_gradients`将采用分布式 Autograd 上下文 ID,并调用`dist_autograd.get_gradients` API,以检索由分布式 Autograd 计算的梯度。 可以在[分布式 Autograd 文档](https://pytorch.org/docs/stable/rpc.html#distributed-autograd-framework)中找到更多信息。 请注意,由于该框架当前仅支持通过 RPC 发送张量,因此我们还会迭代生成的字典并将每个张量转换为 CPU 张量。 接下来,`get_param_rrefs`将迭代我们的模型参数,并将它们包装为(本地)[RRef](https://pytorch.org/docs/stable/rpc.html#torch.distributed.rpc.RRef)。 训练者节点将通过 RPC 调用此方法,并将返回要优化的参数列表。 这是[分布式优化器](https://pytorch.org/docs/stable/rpc.html#module-torch.distributed.optim)的输入,它需要所有必须优化的参数作为`RRef`的列表。 + +```py +# Use dist autograd to retrieve gradients accumulated for this model. +# Primarily used for verification. +def get_dist_gradients(self, cid): + grads = dist_autograd.get_gradients(cid) + # This output is forwarded over RPC, which as of 1.5.0 only accepts CPU tensors. + # Tensors must be moved in and out of GPU memory due to this. + cpu_grads = {} + for k, v in grads.items(): + k_cpu, v_cpu = k.to("cpu"), v.to("cpu") + cpu_grads[k_cpu] = v_cpu + return cpu_grads + +# Wrap local parameters in a RRef. Needed for building the +# DistributedOptimizer which optimizes paramters remotely. +def get_param_rrefs(self): + param_rrefs = [rpc.RRef(param) for param in self.model.parameters()] + return param_rrefs + +``` + +最后,我们将创建用于初始化参数服务器的方法。 请注意,所有过程中只有一个参数服务器实例,并且所有训练器都将与同一参数服务器对话并更新相同的存储模型。 如`run_parameter_server`所示,服务器本身不采取任何独立的操作; 它等待来自训练者的请求(尚未定义),并通过运行所请求的函数对其作出响应。 + +```py +# The global parameter server instance. +param_server = None +# A lock to ensure we only have one parameter server. +global_lock = Lock() + +def get_parameter_server(num_gpus=0): + """ + Returns a singleton parameter server to all trainer processes + """ + global param_server + # Ensure that we get only one handle to the ParameterServer. + with global_lock: + if not param_server: + # construct it once + param_server = ParameterServer(num_gpus=num_gpus) + return param_server + +def run_parameter_server(rank, world_size): + # The parameter server just acts as a host for the model and responds to + # requests from trainers. + # rpc.shutdown() will wait for all workers to complete by default, which + # in this case means that the parameter server will wait for all trainers + # to complete, and then exit. + print("PS master initializing RPC") + rpc.init_rpc(name="parameter_server", rank=rank, world_size=world_size) + print("RPC initialized! Running parameter server...") + rpc.shutdown() + print("RPC shutdown on parameter server.") + +``` + +请注意,以上`rpc.shutdown()`不会立即关闭参数服务器。 相反,它将等待所有工作器(在这种情况下为训练人员)也呼唤`rpc.shutdown()`。 这样可以保证参数服务器在所有训练人员(尚未定义)完成训练过程之前不会脱机。 + +接下来,我们将定义`TrainerNet`类。 这也将是`nn.Module`的子类,并且我们的`__init__`方法将使用`rpc.remote` API 获取对我们的参数服务器的 RRef 或远程引用。 请注意,此处我们没有将参数服务器复制到本地进程,而是可以将`self.param_server_rref`视为指向驻留在单独进程中的参数服务器的分布式共享指针。 + +```py +# --------- Trainers -------------------- + +# nn.Module corresponding to the network trained by this trainer. The +# forward() method simply invokes the network on the given parameter +# server. +class TrainerNet(nn.Module): + def __init__(self, num_gpus=0): + super().__init__() + self.num_gpus = num_gpus + self.param_server_rref = rpc.remote( + "parameter_server", get_parameter_server, args=(num_gpus,)) + +``` + +接下来,我们将定义一个名为`get_global_param_rrefs`的方法。 为了激发对这种方法的需求,值得阅读[`DistributedOptimizer`](https://pytorch.org/docs/stable/rpc.html#module-torch.distributed.optim)上的文档,尤其是 API 签名。 必须向优化器传递与要优化的远程参数相对应的`RRef`列表,因此在这里我们获得了必要的`RRef`。 由于给定`TrainerNet`与之交互的唯一远程工作器是`ParameterServer`,因此我们只需在`ParameterServer`上调用`remote_method`。 我们使用在`ParameterServer`类中定义的`get_param_rrefs`方法。 此方法将`RRef`的列表返回到需要优化的参数。 请注意,在这种情况下,我们的`TrainerNet`没有定义自己的参数; 如果确实如此,我们还需要将每个参数都包装在`RRef`中,并将其包含在`DistributedOptimizer`的输入中。 + +```py +class TrainerNet(nn.Module): +... + def get_global_param_rrefs(self): + remote_params = remote_method( + ParameterServer.get_param_rrefs, + self.param_server_rref) + return remote_params + +``` + +现在,我们准备定义`forward`方法,该方法将调用(同步)RPC 以运行`ParameterServer`上定义的网络的正向传播。 请注意,我们将`self.param_server_rref`(它是`ParameterServer`的远程句柄)传递给 RPC 调用。 该调用将向运行`ParameterServer`的节点发送 RPC,调用`forward`传递,然后返回与模型输出相对应的`Tensor`。 + +```py +class TrainerNet(nn.Module): +... + def forward(self, x): + model_output = remote_method( + ParameterServer.forward, self.param_server_rref, x) + return model_output + +``` + +完全定义好训练器之后,现在该编写我们的神经网络训练循环,该循环将创建我们的网络和优化器,通过网络运行一些输入并计算损失。 训练循环看起来很像本地训练计划,但由于我们的网络在机器之间分布,因此进行了一些修改。 + +下面,我们初始化`TrainerNet`并构建一个`DistributedOptimizer`。 请注意,如上所述,我们必须传入要优化的所有全局参数(跨参与分布式训练的所有节点)。 另外,我们传入要使用的本地优化器,在这种情况下为 SGD。 请注意,我们可以像创建本地优化器一样配置基础优化器算法-`optimizer.SGD`的所有参数都将正确转发。 例如,我们传入一个自定义学习率,它将用作所有本地优化器的学习率。 + +```py +def run_training_loop(rank, num_gpus, train_loader, test_loader): + # Runs the typical nueral network forward + backward + optimizer step, but + # in a distributed fashion. + net = TrainerNet(num_gpus=num_gpus) + # Build DistributedOptimizer. + param_rrefs = net.get_global_param_rrefs() + opt = DistributedOptimizer(optim.SGD, param_rrefs, lr=0.03) + +``` + +接下来,我们定义我们的主要训练循环。 我们遍历了 PyTorch 的[`DataLoader`](https://pytorch.org/docs/stable/data.html)提供的可迭代项。 在编写典型的前向/后向/优化器循环之前,我们首先将逻辑包装在[分布式 Autograd 上下文](https://pytorch.org/docs/stable/rpc.html#torch.distributed.autograd.context)中。 请注意,这需要记录在模型的正向传播中调用的 RPC,以便可以构造一个适当的图,其中包括在后向传递中所有参与的分布式工作器。 分布式 Autograd 上下文返回`context_id`,它用作用于累积和优化与特定迭代对应的梯度的标识符。 + +与调用典型的`loss.backward()`会启动此本地工作程序的反向传播相反,我们调用`dist_autograd.backward()`并传递我们的`context_id`和`loss`,这是我们希望反向传播从它开始的根。 另外,我们将此`context_id`传递到优化程序调用中,该调用程序必须能够在所有节点上查找由该特定反向传播计算出的相应梯度。 + +```py +def run_training_loop(rank, num_gpus, train_loader, test_loader): +... + for i, (data, target) in enumerate(train_loader): + with dist_autograd.context() as cid: + model_output = net(data) + target = target.to(model_output.device) + loss = F.nll_loss(model_output, target) + if i % 5 == 0: + print(f"Rank {rank} training batch {i} loss {loss.item()}") + dist_autograd.backward(cid, [loss]) + # Ensure that dist autograd ran successfully and gradients were + # returned. + assert remote_method( + ParameterServer.get_dist_gradients, + net.param_server_rref, + cid) != {} + opt.step(cid) + + print("Training complete!") + print("Getting accuracy....") + get_accuracy(test_loader, net) + +``` + +与传统的本地模型非常相似,下面的内容只是简单地计算了我们训练后模型的准确率。 但是,请注意,我们在上面传递给此函数的`net`是`TrainerNet`的实例,因此,正向传播以透明方式调用 RPC。 + +```py +def get_accuracy(test_loader, model): + model.eval() + correct_sum = 0 + # Use GPU to evaluate if possible + device = torch.device("cuda:0" if model.num_gpus > 0 + and torch.cuda.is_available() else "cpu") + with torch.no_grad(): + for i, (data, target) in enumerate(test_loader): + out = model(data, -1) + pred = out.argmax(dim=1, keepdim=True) + pred, target = pred.to(device), target.to(device) + correct = pred.eq(target.view_as(pred)).sum().item() + correct_sum += correct + + print(f"Accuracy {correct_sum / len(test_loader.dataset)}") + +``` + +接下来,类似于我们将`run_parameter_server`定义为负责初始化 RPC 的`ParameterServer`的主循环的方式,让我们为训练者定义一个类似的循环。 所不同的是,我们的训练器必须执行上面定义的训练循环: + +```py +# Main loop for trainers. +def run_worker(rank, world_size, num_gpus, train_loader, test_loader): + print(f"Worker rank {rank} initializing RPC") + rpc.init_rpc( + name=f"trainer_{rank}", + rank=rank, + world_size=world_size) + + print(f"Worker {rank} done initializing RPC") + + run_training_loop(rank, num_gpus, train_loader, test_loader) + rpc.shutdown() + +``` + +请注意,类似于`run_parameter_server`,`rpc.shutdown()`默认情况下将等待该节点退出之前,所有训练器和`ParameterServer`的所有工作器都调用`rpc.shutdown()`。 这样可确保节点正常终止,并且没有一个节点脱机,而另一个节点则期望其联机。 + +现在,我们已经完成了特定于训练器和参数服务器的代码,剩下的就是添加代码以启动训练器和参数服务器。 首先,我们必须接受适用于我们的参数服务器和训练器的各种参数。 `world_size`对应于将参加训练的节点总数,并且是所有训练器和参数服务器的总和。 我们还必须为每个单独的进程传递唯一的`rank`,从 0(将在其中运行单个参数服务器的地方)到`world_size - 1`。 `master_addr`和`master_port`是可用于标识等级 0 进程在何处运行的参数,并且各个节点将使用它们来相互发现。 要在本地测试此示例,只需将`localhost`和相同的`master_port`传递给所有产生的实例。 请注意,出于演示目的,此示例仅支持 0-2 个 GPU,尽管可以扩展该模式以使用其他 GPU。 + +```py +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description="Parameter-Server RPC based training") + parser.add_argument( + "--world_size", + type=int, + default=4, + help="""Total number of participating processes. Should be the sum of + master node and all training nodes.""") + parser.add_argument( + "rank", + type=int, + default=None, + help="Global rank of this process. Pass in 0 for master.") + parser.add_argument( + "num_gpus", + type=int, + default=0, + help="""Number of GPUs to use for training, Currently supports between 0 + and 2 GPUs. Note that this argument will be passed to the parameter servers.""") + parser.add_argument( + "--master_addr", + type=str, + default="localhost", + help="""Address of master, will default to localhost if not provided. + Master must be able to accept network traffic on the address + port.""") + parser.add_argument( + "--master_port", + type=str, + default="29500", + help="""Port that master is listening on, will default to 29500 if not + provided. Master must be able to accept network traffic on the host and port.""") + + args = parser.parse_args() + assert args.rank is not None, "must provide rank argument." + assert args.num_gpus <= 3, f"Only 0-2 GPUs currently supported (got {args.num_gpus})." + os.environ['MASTER_ADDR'] = args.master_addr + os.environ["MASTER_PORT"] = args.master_port + +``` + +现在,我们将根据命令行参数创建一个与参数服务器或训练器相对应的过程。 如果传入的等级为 0,我们将创建一个`ParameterServer`,否则,将创建一个`TrainerNet`。 请注意,我们正在使用`torch.multiprocessing`启动与我们要执行的函数相对应的子进程,并使用`p.join()`从主线程等待该进程完成。 在初始化训练器的情况下,我们还使用 PyTorch 的[数据加载器](https://pytorch.org/docs/stable/data.html)来指定 MNIST 数据集上的训练和测试数据加载器。 + +```py +processes = [] +world_size = args.world_size +if args.rank == 0: + p = mp.Process(target=run_parameter_server, args=(0, world_size)) + p.start() + processes.append(p) +else: + # Get data to train on + train_loader = torch.utils.data.DataLoader( + datasets.MNIST('../data', train=True, download=True, + transform=transforms.Compose([ + transforms.ToTensor(), + transforms.Normalize((0.1307,), (0.3081,)) + ])), + batch_size=32, shuffle=True,) + test_loader = torch.utils.data.DataLoader( + datasets.MNIST( + '../data', + train=False, + transform=transforms.Compose([ + transforms.ToTensor(), + transforms.Normalize((0.1307,), (0.3081,)) + ])), + batch_size=32, + shuffle=True, + ) + # start training worker on this node + p = mp.Process( + target=run_worker, + args=( + args.rank, + world_size, args.num_gpus, + train_loader, + test_loader)) + p.start() + processes.append(p) + +for p in processes: + p.join() + +``` + +要在本地运行示例,请在单独的终端窗口中为服务器和要生成的每个工作程序运行以下命令工作程序:`python rpc_parameter_server.py --world_size=WORLD_SIZE --rank=RANK`。 例如,对于世界大小为 2 的主节点,命令为`python rpc_parameter_server.py --world_size=2 --rank=0`。 然后可以在单独的窗口中使用命令`python rpc_parameter_server.py --world_size=2 --rank=1`启动训练器,这将开始使用一台服务器和一台训练器进行训练。 请注意,本教程假定使用 0 到 2 个 GPU 进行训练,并且可以通过将`--num_gpus=N`传递到训练脚本中来配置此参数。 + +您可以传入命令行参数`--master_addr=ADDRESS`和`--master_port=PORT`来指示主工作器正在监听的地址和端口,例如,以测试在其他机器上运行训练者和主节点的功能。 \ No newline at end of file diff --git a/pytorch/官方教程/66.md b/pytorch/官方教程/66.md new file mode 100644 index 00000000..e397964f --- /dev/null +++ b/pytorch/官方教程/66.md @@ -0,0 +1,292 @@ +# 使用 RPC 的分布式管道并行化 + +> 原文: + +**作者**:[Shen Li](https://mrshenli.github.io/) + +先决条件: + +* [PyTorch 分布式概述](../beginner/dist_overview.html) +* [单机模型并行最佳实践](https://pytorch.org/tutorials/intermediate/model_parallel_tutorial.html) +* [分布式 RPC 框架](https://pytorch.org/tutorials/intermediate/rpc_tutorial.html)入门 +* RRef 辅助函数: [`RRef.rpc_sync()`](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.RRef.rpc_sync), [`RRef.rpc_async()`](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.RRef.rpc_async)和 [`RRef.remote()`](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.RRef.remote) + +本教程使用 Resnet50 模型来演示如何使用[`torch.distributed.rpc`](https://pytorch.org/docs/master/rpc.html) API 实现分布式管道并行性。 可以将其视为[单机模型并行最佳实践](model_parallel_tutorial.html)中讨论的多 GPU 管道并行性的分布式对应物。 + +注意 + +本教程需要 PyTorch v1.6.0 或更高版本。 + +注意 + +本教程的完整源代码可以在[`pytorch/examples`](https://github.com/pytorch/examples/tree/master/distributed/rpc/pipeline)中找到。 + +## 基础知识 + +上一教程[分布式 RPC 框架入门](rpc_tutorial.html)显示了如何使用[`torch.distributed.rpc`](https://pytorch.org/docs/master/rpc.html)为 RNN 模型实现分布式模型并行性。 该教程使用一个 GPU 来托管`EmbeddingTable`,并且提供的代码可以正常工作。 但是,如果模型驻留在多个 GPU 上,则将需要一些额外的步骤来增加所有 GPU 的摊销利用率。 管道并行性是在这种情况下可以提供帮助的一种范例。 + +在本教程中,我们使用`ResNet50`作为示例模型,[单机模型并行最佳实践](model_parallel_tutorial.html)教程也使用了该模型。 类似地,`ResNet50`模型被分为两个碎片,输入批量被划分为多个拆分,并以流水线方式馈入两个模型碎片。 区别在于,本教程将调用异步 RPC,而不是使用 CUDA 流来并行执行。 因此,本教程中介绍的解决方案也可以跨计算机边界使用。 本教程的其余部分分四个步骤介绍了实现。 + +## 第 1 步:对 ResNet50 模型进行分片 + +这是在两个模型分片中实现`ResNet50`的准备步骤。 以下代码是从`torchvision`中的 [ResNet 实现](https://github.com/pytorch/vision/blob/7c077f6a986f05383bcb86b535aedb5a63dd5c4b/torchvision/models/resnet.py#L124)中借用的。 `ResNetBase`模块包含两个 ResNet 碎片的通用构件和属性。 + +```py +import threading + +import torch +import torch.nn as nn + +from torchvision.models.resnet import Bottleneck + +num_classes = 1000 + +def conv1x1(in_planes, out_planes, stride=1): + return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False) + +class ResNetBase(nn.Module): + def __init__(self, block, inplanes, num_classes=1000, + groups=1, width_per_group=64, norm_layer=None): + super(ResNetBase, self).__init__() + + self._lock = threading.Lock() + self._block = block + self._norm_layer = nn.BatchNorm2d + self.inplanes = inplanes + self.dilation = 1 + self.groups = groups + self.base_width = width_per_group + + def _make_layer(self, planes, blocks, stride=1): + norm_layer = self._norm_layer + downsample = None + previous_dilation = self.dilation + if stride != 1 or self.inplanes != planes * self._block.expansion: + downsample = nn.Sequential( + conv1x1(self.inplanes, planes * self._block.expansion, stride), + norm_layer(planes * self._block.expansion), + ) + + layers = [] + layers.append(self._block(self.inplanes, planes, stride, downsample, self.groups, + self.base_width, previous_dilation, norm_layer)) + self.inplanes = planes * self._block.expansion + for _ in range(1, blocks): + layers.append(self._block(self.inplanes, planes, groups=self.groups, + base_width=self.base_width, dilation=self.dilation, + norm_layer=norm_layer)) + + return nn.Sequential(*layers) + + def parameter_rrefs(self): + return [RRef(p) for p in self.parameters()] + +``` + +现在,我们准备定义两个模型碎片。 对于构造器,我们只需将所有 ResNet50 层分为两部分,然后将每个部分移至提供的设备中。 两个分片的`forward`函数获取输入数据的`RRef`,在本地获取数据,然后将其移至所需的设备。 将所有层应用于输入后,它将输出移至 CPU 并返回。 这是因为当调用方和被调用方中的设备数量不匹配时,RPC API 要求张量驻留在 CPU 上,以避免无效的设备错误。 + +```py +class ResNetShard1(ResNetBase): + def __init__(self, device, *args, **kwargs): + super(ResNetShard1, self).__init__( + Bottleneck, 64, num_classes=num_classes, *args, **kwargs) + + self.device = device + self.seq = nn.Sequential( + nn.Conv2d(3, self.inplanes, kernel_size=7, stride=2, padding=3, bias=False), + self._norm_layer(self.inplanes), + nn.ReLU(inplace=True), + nn.MaxPool2d(kernel_size=3, stride=2, padding=1), + self._make_layer(64, 3), + self._make_layer(128, 4, stride=2) + ).to(self.device) + + for m in self.modules(): + if isinstance(m, nn.Conv2d): + nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu') + elif isinstance(m, nn.BatchNorm2d): + nn.init.constant_(m.weight, 1) + nn.init.constant_(m.bias, 0) + + def forward(self, x_rref): + x = x_rref.to_here().to(self.device) + with self._lock: + out = self.seq(x) + return out.cpu() + +class ResNetShard2(ResNetBase): + def __init__(self, device, *args, **kwargs): + super(ResNetShard2, self).__init__( + Bottleneck, 512, num_classes=num_classes, *args, **kwargs) + + self.device = device + self.seq = nn.Sequential( + self._make_layer(256, 6, stride=2), + self._make_layer(512, 3, stride=2), + nn.AdaptiveAvgPool2d((1, 1)), + ).to(self.device) + + self.fc = nn.Linear(512 * self._block.expansion, num_classes).to(self.device) + + def forward(self, x_rref): + x = x_rref.to_here().to(self.device) + with self._lock: + out = self.fc(torch.flatten(self.seq(x), 1)) + return out.cpu() + +``` + +## 第 2 步:将 ResNet50 模型片段拼接到一个模块中 + +然后,我们创建一个`DistResNet50`模块来组装两个分片并实现流水线并行逻辑。 在构造器中,我们使用两个`rpc.remote`调用分别将两个分片放在两个不同的 RPC 工作器上,并保持`RRef`到两个模型部分,以便可以在正向传播中引用它们。 `forward`函数将输入批量分为多个微批量,并将这些微批量以流水线方式馈送到两个模型部件。 它首先使用`rpc.remote`调用将第一个分片应用于微批量,然后将返回的中间输出`RRef`转发到第二个模型分片。 之后,它将收集所有微输出的`Future`,并在循环后等待所有它们。 请注意,`remote()`和`rpc_async()`都立即返回并异步运行。 因此,整个循环是非阻塞的,并将同时启动多个 RPC。 中间输出`y_rref`保留了两个模型零件上一个微批量的执行顺序。 微批量的执行顺序无关紧要。 最后,正向函数将所有微批量的输出连接到一个单一的输出张量中并返回。 `parameter_rrefs`函数是简化分布式优化器构造的助手,将在以后使用。 + +```py +class DistResNet50(nn.Module): + def __init__(self, num_split, workers, *args, **kwargs): + super(DistResNet50, self).__init__() + + self.num_split = num_split + + # Put the first part of the ResNet50 on workers[0] + self.p1_rref = rpc.remote( + workers[0], + ResNetShard1, + args = ("cuda:0",) + args, + kwargs = kwargs + ) + + # Put the second part of the ResNet50 on workers[1] + self.p2_rref = rpc.remote( + workers[1], + ResNetShard2, + args = ("cuda:1",) + args, + kwargs = kwargs + ) + + def forward(self, xs): + out_futures = [] + for x in iter(xs.split(self.split_size, dim=0)): + x_rref = RRef(x) + y_rref = self.p1_rref.remote().forward(x_rref) + z_fut = self.p2_rref.rpc_async().forward(y_rref) + out_futures.append(z_fut) + + return torch.cat(torch.futures.wait_all(out_futures)) + + def parameter_rrefs(self): + remote_params = [] + remote_params.extend(self.p1_rref.remote().parameter_rrefs().to_here()) + remote_params.extend(self.p2_rref.remote().parameter_rrefs().to_here()) + return remote_params + +``` + +## 步骤 3:定义训练循环 + +定义模型后,让我们实现训练循环。 我们使用专门的“主”工作器来准备随机输入和标签,并控制分布式反向传递和分布式优化器步骤。 它首先创建`DistResNet50`模块的实例。 它指定每个批量的微批数量,并提供两个 RPC 工作程序的名称(即`worker1`和`worker2`)。 然后,它定义损失函数,并使用`parameter_rrefs()`帮助器创建`DistributedOptimizer`以获取参数`RRefs`的列表。 然后,主训练循环与常规本地训练非常相似,除了它使用`dist_autograd`向后启动并为反向和优化器`step()`提供`context_id`之外。 + +```py +import torch.distributed.autograd as dist_autograd +import torch.optim as optim +from torch.distributed.optim import DistributedOptimizer + +num_batches = 3 +batch_size = 120 +image_w = 128 +image_h = 128 + +def run_master(num_split): + # put the two model parts on worker1 and worker2 respectively + model = DistResNet50(num_split, ["worker1", "worker2"]) + loss_fn = nn.MSELoss() + opt = DistributedOptimizer( + optim.SGD, + model.parameter_rrefs(), + lr=0.05, + ) + + one_hot_indices = torch.LongTensor(batch_size) \ + .random_(0, num_classes) \ + .view(batch_size, 1) + + for i in range(num_batches): + print(f"Processing batch {i}") + # generate random inputs and labels + inputs = torch.randn(batch_size, 3, image_w, image_h) + labels = torch.zeros(batch_size, num_classes) \ + .scatter_(1, one_hot_indices, 1) + + with dist_autograd.context() as context_id: + outputs = model(inputs) + dist_autograd.backward(context_id, [loss_fn(outputs, labels)]) + opt.step(context_id) + +``` + +## 第 4 步:启动 RPC 进程 + +最后,下面的代码显示了所有进程的目标函数。 主要逻辑在`run_master`中定义。 工作器被动地等待主服务器发出的命令,因此只需运行`init_rpc`和`shutdown`即可,其中默认情况下`shutdown`会阻塞,直到所有 RPC 参与者都完成。 + +```py +import os +import time + +import torch.multiprocessing as mp + +def run_worker(rank, world_size, num_split): + os.environ['MASTER_ADDR'] = 'localhost' + os.environ['MASTER_PORT'] = '29500' + options = rpc.TensorPipeRpcBackendOptions(num_worker_threads=128) + + if rank == 0: + rpc.init_rpc( + "master", + rank=rank, + world_size=world_size, + rpc_backend_options=options + ) + run_master(num_split) + else: + rpc.init_rpc( + f"worker{rank}", + rank=rank, + world_size=world_size, + rpc_backend_options=options + ) + pass + + # block until all rpcs finish + rpc.shutdown() + +if __name__=="__main__": + world_size = 3 + for num_split in [1, 2, 4, 8]: + tik = time.time() + mp.spawn(run_worker, args=(world_size, num_split), nprocs=world_size, join=True) + tok = time.time() + print(f"number of splits = {num_split}, execution time = {tok - tik}") + +``` + +下面的输出显示通过增加每批中的拆分数量而获得的加速。 + +```py +$ python main.py +Processing batch 0 +Processing batch 1 +Processing batch 2 +number of splits = 1, execution time = 16.45062756538391 +Processing batch 0 +Processing batch 1 +Processing batch 2 +number of splits = 2, execution time = 12.329529762268066 +Processing batch 0 +Processing batch 1 +Processing batch 2 +number of splits = 4, execution time = 10.164430618286133 +Processing batch 0 +Processing batch 1 +Processing batch 2 +number of splits = 8, execution time = 9.076049566268921 + +``` \ No newline at end of file diff --git a/pytorch/官方教程/67.md b/pytorch/官方教程/67.md new file mode 100644 index 00000000..60d01b71 --- /dev/null +++ b/pytorch/官方教程/67.md @@ -0,0 +1,393 @@ +# 使用异步执行实现批量 RPC 处理 + +> 原文: + +**作者**:[Shen Li](https://mrshenli.github.io/) + +先决条件: + +* [PyTorch 分布式概述](../beginner/dist_overview.html) +* [分布式 RPC 框架](rpc_tutorial.html)入门 +* [使用分布式 RPC 框架](rpc_param_server_tutorial.html)实现参数服务器 +* [RPC 异步执行装饰器](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.functions.async_execution) + +本教程演示了如何使用[`@rpc.functions.async_execution`](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.functions.async_execution)装饰器来构建批量 RPC 应用,该装饰器通过减少阻止的 RPC 线程数和合并被调用方上的 CUDA 操作来帮助加快训练速度。 这使用 TorchServer 的相同想法进行[批量推断](https://pytorch.org/serve/batch_inference_with_ts.html)。 + +注意 + +本教程需要 PyTorch v1.6.0 或更高版本。 + +## 基础知识 + +先前的教程显示了使用[`torch.distributed.rpc`](https://pytorch.org/docs/stable/rpc.html)构建分布式训练应用的步骤,但并未详细说明在处理 RPC 请求时被调用方发生的情况。 从 PyTorch v1.5 开始,每个 RPC 请求都会在被调用方上阻塞一个线程,以在该请求中执行该函数,直到该函数返回为止。 这适用于许多用例,但有一个警告。 如果用户函数例如通过嵌套 RPC 调用在 IO 上阻塞,或者例如在等待其他 RPC 请求解除阻塞的信号时阻塞,则被调用方上的 RPC 线程将必须空闲,直到 IO 完成或发生信令事件为止。 结果,RPC 被调用者可能使用了不必要的更多线程。 造成此问题的原因是 RPC 将用户函数视为黑盒,并且几乎不了解该函数会发生什么。 为了允许用户函数产生和释放 RPC 线程,需要向 RPC 系统提供更多提示。 + +从 v1.6.0 开始,PyTorch 通过引入两个新概念来解决此问题: + +* [`torch.futures.Future`](https://pytorch.org/docs/master/futures.html) 类型封装了异步执行,还支持安装回调函数。 +* 一个[`@rpc.functions.async_execution`](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.functions.async_execution)装饰器,允许应用告诉被调用方目标函数将返回将来的函数,并且在执行期间可以暂停并产生多次。 + +使用这两个工具,应用代码可以将用户函数分解为多个较小的函数,将它们作为`Future`对象上的回调链接在一起,然后返回包含最终结果的`Future`。 在被调用方,当获取`Future`对象时,它还将安装后续的 RPC 响应准备和通讯作为回调,这将在最终结果准备好时触发。 这样,被调用者不再需要阻塞一个线程并等待直到最终返回值准备就绪。 有关简单示例,请参考[`@rpc.functions.async_execution`](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.functions.async_execution) 的 API 文档。 + +除了减少被调用方上的空闲线程数之外,这些工具还有助于使批量 RPC 处理更容易,更快捷。 本教程的以下两节演示了如何使用[`@rpc.functions.async_execution`](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.functions.async_execution)装饰器来构建分布式批更新参数服务器和批量强化学习应用。 + +## 批量更新参数服务器 + +考虑具有一个参数服务器(PS)和多个训练器的同步参数服务器训练应用。 在此应用中,PS 保留参数并等待所有训练器报告坡度。 在每次迭代中,它都会等到收到所有训练者的梯度后,再一次更新所有参数。 下面的代码显示 PS 类的实现。 `update_and_fetch_model`方法是用`@rpc.functions.async_execution`装饰的,将由训练器调用。 每次调用都会返回一个`Future`对象,该对象将填充有更新的模型。 大多数训练器发起的调用仅将梯度累积到`.grad`字段,立即返回,并在 PS 上产生 RPC 线程。 最后到达的训练器将触发优化器步骤,并消耗所有先前报告的梯度。 然后,它使用更新的模型设置`future_model`,该模型又通过`Future`对象通知其他训练器的所有先前请求,并将更新后的模型发送给所有训练器。 + +```py +import threading +import torchvision +import torch +import torch.distributed.rpc as rpc +from torch import optim + +num_classes, batch_update_size = 30, 5 + +class BatchUpdateParameterServer(object): + def __init__(self, batch_update_size=batch_update_size): + self.model = torchvision.models.resnet50(num_classes=num_classes) + self.lock = threading.Lock() + self.future_model = torch.futures.Future() + self.batch_update_size = batch_update_size + self.curr_update_size = 0 + self.optimizer = optim.SGD(self.model.parameters(), lr=0.001, momentum=0.9) + for p in self.model.parameters(): + p.grad = torch.zeros_like(p) + + def get_model(self): + return self.model + + @staticmethod + @rpc.functions.async_execution + def update_and_fetch_model(ps_rref, grads): + # Using the RRef to retrieve the local PS instance + self = ps_rref.local_value() + with self.lock: + self.curr_update_size += 1 + # accumulate gradients into .grad field + for p, g in zip(self.model.parameters(), grads): + p.grad += g + + # Save the current future_model and return it to make sure the + # returned Future object holds the correct model even if another + # thread modifies future_model before this thread returns. + fut = self.future_model + + if self.curr_update_size >= self.batch_update_size: + # update the model + for p in self.model.parameters(): + p.grad /= self.batch_update_size + self.curr_update_size = 0 + self.optimizer.step() + self.optimizer.zero_grad() + # by settiing the result on the Future object, all previous + # requests expecting this updated model will be notified and + # the their responses will be sent accordingly. + fut.set_result(self.model) + self.future_model = torch.futures.Future() + + return fut + +``` + +对于训练器,它们都使用来自 PS 的相同参数集进行初始化。 在每次迭代中,每位训练器首先进行前进和后退操作,以局部生成梯度。 然后,每个训练器都使用 RPC 向 PS 报告其梯度,并通过同一 RPC 请求的返回值取回更新的参数。 在训练器的实现中,目标函数是否标记有`@rpc.functions.async_execution`都没有关系。 训练器只需使用`rpc_sync`调用`update_and_fetch_model`,这会阻塞训练器,直到返回更新的模型。 + +```py +batch_size, image_w, image_h = 20, 64, 64 + +class Trainer(object): + def __init__(self, ps_rref): + self.ps_rref, self.loss_fn = ps_rref, torch.nn.MSELoss() + self.one_hot_indices = torch.LongTensor(batch_size) \ + .random_(0, num_classes) \ + .view(batch_size, 1) + + def get_next_batch(self): + for _ in range(6): + inputs = torch.randn(batch_size, 3, image_w, image_h) + labels = torch.zeros(batch_size, num_classes) \ + .scatter_(1, self.one_hot_indices, 1) + yield inputs.cuda(), labels.cuda() + + def train(self): + name = rpc.get_worker_info().name + # get initial model parameters + m = self.ps_rref.rpc_sync().get_model().cuda() + # start training + for inputs, labels in self.get_next_batch(): + self.loss_fn(m(inputs), labels).backward() + m = rpc.rpc_sync( + self.ps_rref.owner(), + BatchUpdateParameterServer.update_and_fetch_model, + args=(self.ps_rref, [p.grad for p in m.cpu().parameters()]), + ).cuda() + +``` + +在本教程中,我们将跳过启动多个进程的代码,有关完整实现,请参考[示例](https://github.com/pytorch/examples/tree/master/distributed/rpc)回购。 请注意,可以在没有[`@rpc.functions.async_execution`](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.functions.async_execution)装饰器的情况下实现批量。 但是,这将需要在 PS 上阻塞更多的 RPC 线程,或者使用另一轮 RPC 来获取更新的模型,后者将增加代码的复杂性和通信开销。 + +本节使用一个简单的参数服务器训练示例来说明如何使用[`@rpc.functions.async_execution`](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.functions.async_execution)装饰器实现批量 RPC 应用。 在下一节中,我们将使用批量重新实现上一[分布式 RPC 框架](https://pytorch.org/tutorials/intermediate/rpc_tutorial.html)入门指南中的强化学习示例,并演示其对训练速度的影响。 + +## 批量 CartPole 求解器 + +本节以 [OpenAI Gym](https://gym.openai.com/) 中的 CartPole-v1 为例,说明批量 RPC 的性能影响。 请注意,我们的目标是演示[`@rpc.functions.async_execution`](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.functions.async_execution)的用法,而不是构建最佳的 CartPole 求解器或解决大多数不同的 RL 问题,我们使用非常简单的策略和奖励计算策略,并将重点放在多观察者单智能体的批量 RPC 实现。 我们使用与前面的教程类似的`Policy`模型,如下所示。 与上一教程相比,不同之处在于其构造器使用了一个附加的`batch`参数来控制`F.softmax`的`dim`参数,因为进行批量时,`forward`函数中的`x`参数包含来自多个观察者的状态,因此尺寸需要适当更改。 其他所有内容保持不变。 + +```py +import argparse +import torch.nn as nn +import torch.nn.functional as F + +parser = argparse.ArgumentParser(description='PyTorch RPC Batch RL example') +parser.add_argument('--gamma', type=float, default=1.0, metavar='G', + help='discount factor (default: 1.0)') +parser.add_argument('--seed', type=int, default=543, metavar='N', + help='random seed (default: 543)') +parser.add_argument('--num-episode', type=int, default=10, metavar='E', + help='number of episodes (default: 10)') +args = parser.parse_args() + +torch.manual_seed(args.seed) + +class Policy(nn.Module): + def __init__(self, batch=True): + super(Policy, self).__init__() + self.affine1 = nn.Linear(4, 128) + self.dropout = nn.Dropout(p=0.6) + self.affine2 = nn.Linear(128, 2) + self.dim = 2 if batch else 1 + + def forward(self, x): + x = self.affine1(x) + x = self.dropout(x) + x = F.relu(x) + action_scores = self.affine2(x) + return F.softmax(action_scores, dim=self.dim) + +``` + +`Observer`的构造器也会相应地进行调整。 它还带有`batch`参数,该参数控制用于选择动作的`Agent`函数。 在批量模式下,它将调用`Agent`上的`select_action_batch`函数,该函数将很快出现,并且该函数将以[`@rpc.functions.async_execution`](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.functions.async_execution)装饰。 + +```py +import gym +import torch.distributed.rpc as rpc + +class Observer: + def __init__(self, batch=True): + self.id = rpc.get_worker_info().id - 1 + self.env = gym.make('CartPole-v1') + self.env.seed(args.seed) + self.select_action = Agent.select_action_batch if batch else Agent.select_action + +``` + +与之前的教程[分布式 RPC 框架入门](https://pytorch.org/tutorials/intermediate/rpc_tutorial.html)相比,观察者的行为略有不同。 它不会在环境停止时退出,而是始终在每个剧集中运行`n_steps`迭代。 当环境返回时,观察者只需重置环境并重新开始。 通过这种设计,智能体将从每个观察者那里收到固定数量的状态,因此可以将它们打包成固定大小的张量。 在每个步骤中,`Observer`使用 RPC 将其状态发送到`Agent`,并通过返回值获取操作。 在每个剧集的结尾,它将所有步骤的奖励返还给`Agent`。 注意,`Agent`将使用 RPC 调用此`run_episode`函数。 因此,此函数中的`rpc_sync`调用将是嵌套的 RPC 调用。 我们也可以将此函数标记为`@rpc.functions.async_execution`,以避免阻塞`Observer`上的一个线程。 但是,由于瓶颈是`Agent`而不是`Observer`,因此可以在`Observer`进程中阻塞一个线程。 + +```py +import torch + +class Observer: + ... + + def run_episode(self, agent_rref, n_steps): + state, ep_reward = self.env.reset(), NUM_STEPS + rewards = torch.zeros(n_steps) + start_step = 0 + for step in range(n_steps): + state = torch.from_numpy(state).float().unsqueeze(0) + # send the state to the agent to get an action + action = rpc.rpc_sync( + agent_rref.owner(), + self.select_action, + args=(agent_rref, self.id, state) + ) + + # apply the action to the environment, and get the reward + state, reward, done, _ = self.env.step(action) + rewards[step] = reward + + if done or step + 1 >= n_steps: + curr_rewards = rewards[start_step:(step + 1)] + R = 0 + for i in range(curr_rewards.numel() -1, -1, -1): + R = curr_rewards[i] + args.gamma * R + curr_rewards[i] = R + state = self.env.reset() + if start_step == 0: + ep_reward = min(ep_reward, step - start_step + 1) + start_step = step + 1 + + return [rewards, ep_reward] + +``` + +`Agent`的构造器还采用`batch`参数,该参数控制如何对动作概率进行批量。 在批量模式下,`saved_log_probs`包含一张张量列表,其中每个张量包含一个步骤中所有观察者的动作抢夺。 如果不进行批量,则`saved_log_probs`是字典,其中的键是观察者 ID,值是该观察者的动作概率列表。 + +```py +import threading +from torch.distributed.rpc import RRef + +class Agent: + def __init__(self, world_size, batch=True): + self.ob_rrefs = [] + self.agent_rref = RRef(self) + self.rewards = {} + self.policy = Policy(batch).cuda() + self.optimizer = optim.Adam(self.policy.parameters(), lr=1e-2) + self.running_reward = 0 + + for ob_rank in range(1, world_size): + ob_info = rpc.get_worker_info(OBSERVER_NAME.format(ob_rank)) + self.ob_rrefs.append(rpc.remote(ob_info, Observer, args=(batch,))) + self.rewards[ob_info.id] = [] + + self.states = torch.zeros(len(self.ob_rrefs), 1, 4) + self.batch = batch + self.saved_log_probs = [] if batch else {k:[] for k in range(len(self.ob_rrefs))} + self.future_actions = torch.futures.Future() + self.lock = threading.Lock() + self.pending_states = len(self.ob_rrefs) + +``` + +非批量`select_acion`只需运行状态抛出策略,保存动作概率,然后立即将动作返回给观察者。 + +```py +from torch.distributions import Categorical + +class Agent: + ... + + @staticmethod + def select_action(agent_rref, ob_id, state): + self = agent_rref.local_value() + probs = self.policy(state.cuda()) + m = Categorical(probs) + action = m.sample() + self.saved_log_probs[ob_id].append(m.log_prob(action)) + return action.item() + +``` + +使用批量时,状态以观察者 id 为行 ID 存储在 2D 张量`self.states`中。 然后,它通过将回调函数安装到批量生成的`self.future_actions` `Future`对象上来链接`Future`,该对象将使用使用该观察者 ID 索引的特定行进行填充。 最后到达的观察者一口气通过策略运行所有批量状态,并相应地设置`self.future_actions`。 发生这种情况时,将触发安装在`self.future_actions`上的所有回调函数,并使用它们的返回值来填充链接的`Future`对象,该对象进而通知`Agent`为所有先前的 RPC 请求准备和传达来自其他观察者的响应。 + +```py +class Agent: + ... + + @staticmethod + @rpc.functions.async_execution + def select_action_batch(agent_rref, ob_id, state): + self = agent_rref.local_value() + self.states[ob_id].copy_(state) + future_action = self.future_actions.then( + lambda future_actions: future_actions.wait()[ob_id].item() + ) + + with self.lock: + self.pending_states -= 1 + if self.pending_states == 0: + self.pending_states = len(self.ob_rrefs) + probs = self.policy(self.states.cuda()) + m = Categorical(probs) + actions = m.sample() + self.saved_log_probs.append(m.log_prob(actions).t()[0]) + future_actions = self.future_actions + self.future_actions = torch.futures.Future() + future_actions.set_result(actions.cpu()) + return future_action + +``` + +现在,让我们定义如何将不同的 RPC 函数结合在一起。 `Agent`控制每个剧集的执行。 它首先使用`rpc_async`在所有观察者上开始该剧集,并阻止将由观察者奖励填充的返还期货。 请注意,以下代码使用 RRef 帮助器`ob_rref.rpc_async()`在具有提供的参数的`ob_rref` RRef 的所有者上启动`run_episode`函数。 然后将保存的动作概率和返回的观察者奖励转换为期望的数据格式,并开始训练步骤。 最后,它将重置所有状态并返回当前剧集的奖励。 此函数是运行一集的入口。 + +```py +class Agent: + ... + + def run_episode(self, n_steps=0): + futs = [] + for ob_rref in self.ob_rrefs: + # make async RPC to kick off an episode on all observers + futs.append(ob_rref.rpc_async().run_episode(self.agent_rref, n_steps)) + + # wait until all obervers have finished this episode + rets = torch.futures.wait_all(futs) + rewards = torch.stack([ret[0] for ret in rets]).cuda().t() + ep_rewards = sum([ret[1] for ret in rets]) / len(rets) + + # stack saved probs into one tensor + if self.batch: + probs = torch.stack(self.saved_log_probs) + else: + probs = [torch.stack(self.saved_log_probs[i]) for i in range(len(rets))] + probs = torch.stack(probs) + + policy_loss = -probs * rewards / len(rets) + policy_loss.sum().backward() + self.optimizer.step() + self.optimizer.zero_grad() + + # reset variables + self.saved_log_probs = [] if self.batch else {k:[] for k in range(len(self.ob_rrefs))} + self.states = torch.zeros(len(self.ob_rrefs), 1, 4) + + # calculate running rewards + self.running_reward = 0.5 * ep_rewards + 0.5 * self.running_reward + return ep_rewards, self.running_reward + +``` + +其余代码是正常的进程启动和日志记录,与其他 RPC 教程类似。 在本教程中,所有观察者都被动地等待来自智能体的命令。 有关完整的实现,请参考[示例](https://github.com/pytorch/examples/tree/master/distributed/rpc)回购。 + +```py +def run_worker(rank, world_size, n_episode, batch, print_log=True): + os.environ['MASTER_ADDR'] = 'localhost' + os.environ['MASTER_PORT'] = '29500' + if rank == 0: + # rank0 is the agent + rpc.init_rpc(AGENT_NAME, rank=rank, world_size=world_size) + + agent = Agent(world_size, batch) + for i_episode in range(n_episode): + last_reward, running_reward = agent.run_episode(n_steps=NUM_STEPS) + + if print_log: + print('Episode {}\tLast reward: {:.2f}\tAverage reward: {:.2f}'.format( + i_episode, last_reward, running_reward)) + else: + # other ranks are the observer + rpc.init_rpc(OBSERVER_NAME.format(rank), rank=rank, world_size=world_size) + # observers passively waiting for instructions from agents + rpc.shutdown() + +def main(): + for world_size in range(2, 12): + delays = [] + for batch in [True, False]: + tik = time.time() + mp.spawn( + run_worker, + args=(world_size, args.num_episode, batch), + nprocs=world_size, + join=True + ) + tok = time.time() + delays.append(tok - tik) + + print(f"{world_size}, {delays[0]}, {delays[1]}") + +if __name__ == '__main__': + main() + +``` + +批量 RPC 有助于将操作推断合并为较少的 CUDA 操作,从而减少了摊销的开销。 上面的`main`函数使用不同数量的观察者(从 1 到 10)在批量和无批量模式下运行相同的代码。下图使用默认参数值绘制了不同世界大小的执行时间。 结果证实了我们的期望,即批量有助于加快训练速度。 + +![](img/f5504c7ed93640f2bed4d2a606c015ba.png) + +## 了解更多 + +* [批量更新参数服务器的源代码](https://github.com/pytorch/examples/blob/master/distributed/rpc/batch/parameter_server.py) +* [批量 CartPole 求解器](https://github.com/pytorch/examples/blob/master/distributed/rpc/batch/reinforce.py) +* [分布式 Autograd](https://pytorch.org/docs/master/rpc.html#distributed-autograd-framework) +* [分布式管道并行性](dist_pipeline_parallel_tutorial.html) \ No newline at end of file diff --git a/pytorch/官方教程/68.md b/pytorch/官方教程/68.md new file mode 100644 index 00000000..5cadd0cc --- /dev/null +++ b/pytorch/官方教程/68.md @@ -0,0 +1,234 @@ +# 将分布式`DataParallel`与分布式 RPC 框架相结合 + +> 原文: + +**作者**: [Pritam Damania](https://github.com/pritamdamania87) + +本教程使用一个简单的示例演示如何将[`DistributedDataParallel`](https://pytorch.org/docs/stable/nn.html#torch.nn.parallel.DistributedDataParallel)(DDP)与[分布式 RPC 框架](https://pytorch.org/docs/master/rpc.html)结合使用,以将分布式数据并行性与分布式模型并行性结合在一起,以训练简单模型。 该示例的源代码可以在中找到[。](https://github.com/pytorch/examples/tree/master/distributed/rpc/ddp_rpc) + +先前的教程[分布式数据并行入门](https://pytorch.org/tutorials/intermediate/ddp_tutorial.html)和[分布式 RPC 框架入门](https://pytorch.org/tutorials/intermediate/rpc_tutorial.html)分别描述了如何执行分布式数据并行训练和分布式模型并行训练。 虽然,有几种训练范例,您可能想将这两种技术结合起来。 例如: + +1. 如果我们的模型具有稀疏部分(较大的嵌入表)和密集部分(FC 层),则可能需要将嵌入表放在参数服务器上,并使用[`DistributedDataParallel`](https://pytorch.org/docs/stable/nn.html#torch.nn.parallel.DistributedDataParallel)。 [分布式 RPC 框架](https://pytorch.org/docs/master/rpc.html)可用于在参数服务器上执行嵌入查找。 +2. 如 [PipeDream](https://arxiv.org/abs/1806.03377) 论文中所述,启用混合并行性。 我们可以使用[分布式 RPC 框架](https://pytorch.org/docs/master/rpc.html)在多个工作程序之间流水线化模型的各个阶段,并使用[`DistributedDataParallel`](https://pytorch.org/docs/stable/nn.html#torch.nn.parallel.DistributedDataParallel)复制每个阶段(如果需要)。 + +在本教程中,我们将介绍上述情况 1。 我们的设置中共有 4 个工作器,如下所示: + +1. 1 个主机,负责在参数服务器上创建嵌入表(`nn.EmbeddingBag`)。 主人还会在两个教练上驱动训练循环。 +2. 1 参数服务器,它基本上将嵌入表保存在内存中,并响应来自主服务器和训练器的 RPC。 +3. 2 个训练器,用于存储 FC 层(线性线性),并使用[`DistributedDataParallel`](https://pytorch.org/docs/stable/nn.html#torch.nn.parallel.DistributedDataParallel)在它们之间进行复制。 训练人员还负责执行前进,后退和优化器步骤。 + +整个训练过程执行如下: + +1. 主服务器在参数服务器上创建一个嵌入表,并为其保留一个 [RRef](https://pytorch.org/docs/master/rpc.html#rref)。 +2. 然后,主持人开始在训练器上进行训练循环,并将嵌入表 RRef 传递给训练器。 +3. 训练器创建一个`HybridModel`,该`HybridModel`首先使用主机提供的嵌入表 RRef 执行嵌入查找,然后执行包装在 DDP 中的 FC 层。 +4. 训练者执行模型的正向传播,并使用[分布式 Autograd](https://pytorch.org/docs/master/rpc.html#distributed-autograd-framework) 使用损失执行反向传递。 +5. 作为向后遍历的一部分,将首先计算 FC 层的梯度,并通过 DDP 中的`allreduce`将其同步到所有训练器。 +6. 接下来,分布式 Autograd 将梯度传播到参数服务器,在该服务器中更新嵌入表的梯度。 +7. 最后,[分布式优化器](https://pytorch.org/docs/master/rpc.html#module-torch.distributed.optim)用于更新所有参数。 + +注意 + +如果您将 DDP 和 RPC 结合使用,则应始终使用[分布式 Autograd](https://pytorch.org/docs/master/rpc.html#distributed-autograd-framework) 进行反向传播。 + +现在,让我们详细介绍每个部分。 首先,我们需要先设置所有工作器,然后才能进行任何训练。 我们创建 4 个过程,使等级 0 和 1 是我们的训练器,等级 2 是主控制器,等级 3 是参数服务器。 + +我们使用 TCP init_method 在所有 4 个工作器上初始化 RPC 框架。 RPC 初始化完成后,主服务器使用[`rpc.remote`](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.remote)在参数服务器上创建[`EmbeddingBag`](https://pytorch.org/docs/master/generated/torch.nn.EmbeddingBag.html)。 然后,主控制器通过使用[`rpc_async`](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.rpc_async)在每个教练上调用`_run_trainer`,循环遍历每个教练并开始训练循环。 最后,主人在退出之前等待所有训练结束。 + +训练器首先使用[`init_process_group`](https://pytorch.org/docs/stable/distributed.html#torch.distributed.init_process_group)为`world_size = 2`的 DDP 初始化`ProcessGroup`(对于两个训练器)。 接下来,他们使用 TCP `init_method`初始化 RPC 框架。 请注意,RPC 初始化和`ProcessGroup`初始化中的端口不同。 这是为了避免两个框架的初始化之间的端口冲突。 初始化完成后,训练器只需等待主服务器的`_run_trainer` RPC。 + +参数服务器只是初始化 RPC 框架,并等待来自训练者和主服务器的 RPC。 + +```py +def run_worker(rank, world_size): + r""" + A wrapper function that initializes RPC, calls the function, and shuts down + RPC. + """ + os.environ['MASTER_ADDR'] = 'localhost' + os.environ['MASTER_PORT'] = '29500' + + rpc_backend_options = TensorPipeRpcBackendOptions() + rpc_backend_options.init_method='tcp://localhost:29501' + + # Rank 2 is master, 3 is ps and 0 and 1 are trainers. + if rank == 2: + rpc.init_rpc( + "master", + rank=rank, + world_size=world_size, + rpc_backend_options=rpc_backend_options) + + # Build the embedding table on the ps. + emb_rref = rpc.remote( + "ps", + torch.nn.EmbeddingBag, + args=(NUM_EMBEDDINGS, EMBEDDING_DIM), + kwargs={"mode": "sum"}) + + # Run the training loop on trainers. + futs = [] + for trainer_rank in [0, 1]: + trainer_name = "trainer{}".format(trainer_rank) + fut = rpc.rpc_async( + trainer_name, _run_trainer, args=(emb_rref, rank)) + futs.append(fut) + + # Wait for all training to finish. + for fut in futs: + fut.wait() + elif rank <= 1: + # Initialize process group for Distributed DataParallel on trainers. + dist.init_process_group( + backend="gloo", rank=rank, world_size=2) + + # Initialize RPC. + trainer_name = "trainer{}".format(rank) + rpc.init_rpc( + trainer_name, + rank=rank, + world_size=world_size, + rpc_backend_options=rpc_backend_options) + + # Trainer just waits for RPCs from master. + else: + rpc.init_rpc( + "ps", + rank=rank, + world_size=world_size, + rpc_backend_options=rpc_backend_options) + # parameter server do nothing + pass + + # block until all rpcs finish + rpc.shutdown() + +if __name__=="__main__": + # 2 trainers, 1 parameter server, 1 master. + world_size = 4 + mp.spawn(run_worker, args=(world_size, ), nprocs=world_size, join=True) + +``` + +在讨论训练器的详细信息之前,让我们介绍一下训练器使用的`HybridModel`。 如下所述,使用对参数服务器上嵌入表(`emb_rref`)的 RRef 和用于 DDP 的`device`初始化`HybridModel`。 模型的初始化在 DDP 中包装了[`nn.Linear`](https://pytorch.org/docs/master/generated/torch.nn.Linear.html)层,以在所有训练器之间复制和同步该层。 + +该模型的前进方法非常简单。 它使用 [RRef 帮助程序](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.RRef.rpc_sync)在参数服务器上执行嵌入查找,并将其输出传递到 FC 层。 + +```py +class HybridModel(torch.nn.Module): + r""" + The model consists of a sparse part and a dense part. The dense part is an + nn.Linear module that is replicated across all trainers using + DistributedDataParallel. The sparse part is an nn.EmbeddingBag that is + stored on the parameter server. + + The model holds a Remote Reference to the embedding table on the parameter + server. + """ + + def __init__(self, emb_rref, device): + super(HybridModel, self).__init__() + self.emb_rref = emb_rref + self.fc = DDP(torch.nn.Linear(16, 8).cuda(device), device_ids=[device]) + self.device = device + + def forward(self, indices, offsets): + emb_lookup = self.emb_rref.rpc_sync().forward(indices, offsets) + return self.fc(emb_lookup.cuda(self.device)) + +``` + +接下来,让我们看看训练器上的设置。 训练者首先使用对参数服务器上嵌入表的 RRef 及其自身等级创建上述`HybridModel`。 + +现在,我们需要检索要使用[`DistributedOptimizer`](https://pytorch.org/docs/master/rpc.html#module-torch.distributed.optim)优化的所有参数的 RRef 列表。 为了从参数服务器中检索嵌入表的参数,我们定义了一个简单的辅助函数`_retrieve_embedding_parameters`,该函数基本上遍历了嵌入表的所有参数并返回 RRef 的列表。 训练器通过 RPC 在参数服务器上调用此方法,以接收所需参数的 RRef 列表。 由于`DistributedOptimizer`始终将需要优化的参数的 RRef 列表,因此我们甚至需要为 FC 层的本地参数创建 RRef。 这是通过遍历`model.parameters()`,为每个参数创建 RRef 并将其附加到列表来完成的。 请注意,`model.parameters()`仅返回本地参数,不包含`emb_rref`。 + +最后,我们使用所有 RRef 创建我们的`DistributedOptimizer`,并定义`CrossEntropyLoss`函数。 + +```py +def _retrieve_embedding_parameters(emb_rref): + param_rrefs = [] + for param in emb_rref.local_value().parameters(): + param_rrefs.append(RRef(param)) + return param_rrefs + +def _run_trainer(emb_rref, rank): + r""" + Each trainer runs a forward pass which involves an embedding lookup on the + parameter server and running nn.Linear locally. During the backward pass, + DDP is responsible for aggregating the gradients for the dense part + (nn.Linear) and distributed autograd ensures gradients updates are + propagated to the parameter server. + """ + + # Setup the model. + model = HybridModel(emb_rref, rank) + + # Retrieve all model parameters as rrefs for DistributedOptimizer. + + # Retrieve parameters for embedding table. + model_parameter_rrefs = rpc.rpc_sync( + "ps", _retrieve_embedding_parameters, args=(emb_rref,)) + + # model.parameters() only includes local parameters. + for param in model.parameters(): + model_parameter_rrefs.append(RRef(param)) + + # Setup distributed optimizer + opt = DistributedOptimizer( + optim.SGD, + model_parameter_rrefs, + lr=0.05, + ) + + criterion = torch.nn.CrossEntropyLoss() + +``` + +现在,我们准备介绍在每个训练器上运行的主要训练循环。 `get_next_batch`只是一个辅助函数,用于生成随机输入和训练目标。 我们针对多个周期和每个批量运行训练循环: + +1. 为分布式 Autograd 设置[分布式 Autograd 上下文](https://pytorch.org/docs/master/rpc.html#torch.distributed.autograd.context)。 +2. 运行模型的正向传播并检索其输出。 +3. 使用损失函数,根据我们的输出和目标计算损失。 +4. 使用分布式 Autograd 使用损失执行分布式反向传递。 +5. 最后,运行“分布式优化器”步骤以优化所有参数。 + +```py + def get_next_batch(rank): + for _ in range(10): + num_indices = random.randint(20, 50) + indices = torch.LongTensor(num_indices).random_(0, NUM_EMBEDDINGS) + + # Generate offsets. + offsets = [] + start = 0 + batch_size = 0 + while start < num_indices: + offsets.append(start) + start += random.randint(1, 10) + batch_size += 1 + + offsets_tensor = torch.LongTensor(offsets) + target = torch.LongTensor(batch_size).random_(8).cuda(rank) + yield indices, offsets_tensor, target + + # Train for 100 epochs + for epoch in range(100): + # create distributed autograd context + for indices, offsets, target in get_next_batch(rank): + with dist_autograd.context() as context_id: + output = model(indices, offsets) + loss = criterion(output, target) + + # Run distributed backward pass + dist_autograd.backward(context_id, [loss]) + + # Tun distributed optimizer + opt.step(context_id) + + # Not necessary to zero grads as each iteration creates a different + # distributed autograd context which hosts different grads + print("Training done for epoch {}".format(epoch)) + +``` + +[整个示例的源代码可以在这里找到](https://github.com/pytorch/examples/tree/master/distributed/rpc/ddp_rpc)。 \ No newline at end of file diff --git a/pytorch/官方教程/README.md b/pytorch/官方教程/README.md new file mode 100644 index 00000000..cd349818 --- /dev/null +++ b/pytorch/官方教程/README.md @@ -0,0 +1,35 @@ +# PyTorch 中文官方教程 1.7 + +> 原文:[WELCOME TO PYTORCH TUTORIALS](https://pytorch.org/tutorials/) +> +> 协议:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/) +> +> 自豪地采用[谷歌翻译](https://translate.google.cn/) +> +> 不要担心自己的形象,只关心如何实现目标。——《原则》,生活原则 2.3.c + +* [在线阅读](https://dl.apachecn.org) +* [ApacheCN 面试求职交流群 724187166](https://jq.qq.com/?_wv=1027&k=54ujcL3) +* [ApacheCN 学习资源](http://www.apachecn.org/) + +## 贡献指南 + +本项目需要校对,欢迎大家提交 Pull Request。 + +> 请您勇敢地去翻译和改进翻译。虽然我们追求卓越,但我们并不要求您做到十全十美,因此请不要担心因为翻译上犯错——在大部分情况下,我们的服务器已经记录所有的翻译,因此您不必担心会因为您的失误遭到无法挽回的破坏。(改编自维基百科) + +## 联系方式 + +### 负责人 + +* [飞龙](https://github.com/wizardforcel): 562826179 + +### 其他 + +* 在我们的 [apachecn/apachecn-tf-zh](https://github.com/apachecn/apachecn-tf-zh) github 上提 issue. +* 发邮件到 Email: `apachecn@163.com`. +* 在我们的 [组织学习交流群](http://www.apachecn.org/organization/348.html) 中联系群主/管理员即可. + +## 赞助我们 + +![](http://data.apachecn.org/img/about/donate.jpg) diff --git a/pytorch/官方教程/SUMMARY.md b/pytorch/官方教程/SUMMARY.md new file mode 100644 index 00000000..03b5cf62 --- /dev/null +++ b/pytorch/官方教程/SUMMARY.md @@ -0,0 +1,71 @@ +# Summary + ++ [PyTorch 中文官方教程 1.7](README.md) ++ [学习 PyTorch](01.md) + + [PyTorch 深度学习:60 分钟的突击](02.md) + + [张量](03.md) + + [`torch.autograd`的简要介绍](04.md) + + [神经网络](05.md) + + [训练分类器](06.md) + + [通过示例学习 PyTorch](07.md) + + [热身:NumPy](08.md) + + [PyTorch:张量](09.md) + + [PyTorch:张量和 Autograd](10.md) + + [PyTorch:定义新的 Autograd 函数](11.md) + + [PyTorch:`nn`](12.md) + + [PyTorch:`optim`](13.md) + + [PyTorch:自定义`nn`模块](14.md) + + [PyTorch:控制流 + 权重共享](15.md) + + [`torch.nn`到底是什么?](16.md) + + [使用 TensorBoard 可视化模型,数据和训练](17.md) ++ [图片/视频](18.md) + + [`torchvision`对象检测微调教程](19.md) + + [计算机视觉的迁移学习教程](20.md) + + [对抗示例生成](21.md) + + [DCGAN 教程](22.md) ++ [音频](23.md) + + [音频 I/O 和`torchaudio`的预处理](24.md) + + [使用`torchaudio`的语音命令识别](25.md) ++ [文本](26.md) + + [使用`nn.Transformer`和`torchtext`的序列到序列建模](27.md) + + [从零开始的 NLP:使用字符级 RNN 分类名称](28.md) + + [从零开始的 NLP:使用字符级 RNN 生成名称](29.md) + + [从零开始的 NLP:使用序列到序列网络和注意力的翻译](30.md) + + [使用`torchtext`的文本分类](31.md) + + [`torchtext`语言翻译](32.md) ++ [强化学习](33.md) + + [强化学习(DQN)教程](34.md) + + [训练玩马里奥的 RL 智能体](35.md) ++ [在生产中部署 PyTorch 模型](36.md) + + [通过使用 Flask 的 REST API 在 Python 中部署 PyTorch](37.md) + + [TorchScript 简介](38.md) + + [在 C++ 中加载 TorchScript 模型](39.md) + + [将模型从 PyTorch 导出到 ONNX 并使用 ONNX 运行时运行它(可选)](40.md) ++ [前端 API](41.md) + + [PyTorch 中的命名张量简介(原型)](42.md) + + [PyTorch 中通道在最后的内存格式(beta)](43.md) + + [使用 PyTorch C++ 前端](44.md) + + [自定义 C++ 和 CUDA 扩展](45.md) + + [使用自定义 C++ 运算符扩展 TorchScript](46.md) + + [使用自定义 C++ 类扩展 TorchScript](47.md) + + [TorchScript 中的动态并行性](48.md) + + [C++ 前端中的 Autograd](49.md) + + [在 C++ 中注册调度运算符](50.md) ++ [模型优化](51.md) + + [分析您的 PyTorch 模块](52.md) + + [使用 Ray Tune 的超参数调整](53.md) + + [模型剪裁教程](54.md) + + [LSTM 单词语言模型上的动态量化(beta)](55.md) + + [BERT 上的动态量化(Beta)](56.md) + + [PyTorch 中使用 Eager 模式的静态量化(beta)](57.md) + + [计算机视觉的量化迁移学习教程(beta)](58.md) ++ [并行和分布式训练](59.md) + + [PyTorch 分布式概述](60.md) + + [单机模型并行最佳实践](61.md) + + [分布式数据并行入门](62.md) + + [用 PyTorch 编写分布式应用](63.md) + + [分布式 RPC 框架入门](64.md) + + [使用分布式 RPC 框架实现参数服务器](65.md) + + [使用 RPC 的分布式管道并行化](66.md) + + [使用异步执行实现批量 RPC 处理](67.md) + + [将分布式`DataParallel`与分布式 RPC 框架相结合](68.md) diff --git a/pytorch/官方教程/book.json b/pytorch/官方教程/book.json new file mode 100644 index 00000000..2d99e483 --- /dev/null +++ b/pytorch/官方教程/book.json @@ -0,0 +1,176 @@ +{ + "title" : "Pytorch 中文文档", + "author" : "ApacheCN", + "description" : "Pytorch 中文文档: 教程和文档", + "language" : "zh-hans", + "plugins": [ + "github", + "github-buttons", + "-sharing", + "insert-logo", + "sharing-plus", + "back-to-top-button", + "code", + "copy-code-button", + "katex", + "pageview-count", + "edit-link", + "emphasize", + "alerts", + "auto-scroll-table", + "popup", + "hide-element", + "page-toc-button", + "tbfed-pagefooter", + "sitemap", + "advanced-emoji", + "expandable-chapters", + "splitter", + "search-pro" + ], + "pluginsConfig": { + "github": { + "url": "https://github.com/apachecn/pytorch-doc-zh" + }, + "github-buttons": { + "buttons": [ + { + "user": "apachecn", + "repo": "pytorch-doc-zh", + "type": "star", + "count": true, + "size": "small" + } + ] + }, + "insert-logo": { + "url": "http://data.apachecn.org/img/logo.jpg", + "style": "background: none; max-height: 150px; min-height: 150px" + }, + "hide-element": { + "elements": [".gitbook-link"] + }, + "edit-link": { + "base": "https://github.com/apachecn/pytorch-doc-zh/blob/master/docs/1.7", + "label": "编辑本页" + }, + "sharing": { + "qzone": true, + "weibo": true, + "twitter": false, + "facebook": false, + "google": false, + "qq": false, + "line": false, + "whatsapp": false, + "douban": false, + "all": [ + "qq", "douban", "facebook", "google", "linkedin", "twitter", "weibo", "whatsapp" + ] + }, + "page-toc-button": { + "maxTocDepth": 4, + "minTocSize": 4 + }, + "tbfed-pagefooter": { + "copyright":"Copyright © ibooker.org.cn 2019", + "modify_label": "该文件修订时间: ", + "modify_format": "YYYY-MM-DD HH:mm:ss" + }, + "sitemap": { + "hostname": "http://pytorch.apachecn.org" + } + }, + "my_links" : { + "sidebar" : { + "Home" : "https://www.baidu.com" + } + }, + "my_plugins": [ + "donate", + "todo", + "-lunr", + "-search", + "expandable-chapters-small", + "chapter-fold", + "expandable-chapters", + "expandable-chapters-small", + "back-to-top-button", + "ga", + "baidu", + "sitemap", + "tbfed-pagefooter", + "advanced-emoji", + "sectionx", + "page-treeview", + "simple-page-toc", + "ancre-navigation", + "theme-apachecn@git+https://github.com/apachecn/theme-apachecn#HEAD", + "pagefooter-apachecn@git+https://github.com/apachecn/gitbook-plugin-pagefooter-apachecn#HEAD" + ], + "my_pluginsConfig": { + "github-buttons": { + "buttons": [ + { + "user": "apachecn", + "repo": "pytorch-doc-zh", + "type": "star", + "count": true, + "size": "small" + }, + { + "user": "apachecn", + "width": "160", + "type": "follow", + "count": true, + "size": "small" + } + ] + }, + "ignores": ["node_modules"], + "simple-page-toc": { + "maxDepth": 3, + "skipFirstH1": true + }, + "page-toc-button": { + "maxTocDepth": 2, + "minTocSize": 2 + }, + "page-treeview": { + "copyright": "Copyright © aleen42", + "minHeaderCount": "2", + "minHeaderDeep": "2" + }, + "donate": { + "wechat": "微信收款的二维码URL", + "alipay": "支付宝收款的二维码URL", + "title": "", + "button": "赏", + "alipayText": "支付宝打赏", + "wechatText": "微信打赏" + }, + "page-copyright": { + "description": "modified at", + "signature": "你的签名", + "wisdom": "Designer, Frontend Developer & overall web enthusiast", + "format": "YYYY-MM-dd hh:mm:ss", + "copyright": "Copyright © 你的名字", + "timeColor": "#666", + "copyrightColor": "#666", + "utcOffset": "8", + "style": "normal", + "noPowered": false + }, + "ga": { + "token": "UA-102475051-10" + }, + "baidu": { + "token": "75439e2cbd22bdd813226000e9dcc12f" + }, + "pagefooter-apachecn": { + "copyright":"Copyright © ibooker.org.cn 2019", + "modify_label": "该文件修订时间: ", + "modify_format": "YYYY-MM-DD HH:mm:ss" + } + } +} diff --git a/pytorch/官方教程/img/029a9d26725997aae97e9e3f6f10067f.png b/pytorch/官方教程/img/029a9d26725997aae97e9e3f6f10067f.png new file mode 100644 index 0000000000000000000000000000000000000000..f6edf4ad4d57d7351122f566a59316d5012defb5 GIT binary patch literal 15068 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 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/049e79b05a41598709a2aeef166e4a2a.png b/pytorch/官方教程/img/049e79b05a41598709a2aeef166e4a2a.png new file mode 100644 index 0000000000000000000000000000000000000000..0adfff1ed74f42d7b77cb2c87b9ce68dbe135e54 GIT binary patch literal 47233 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�NOE@rIrTY`P)u3A4Y>a4pu{+Se7{LL~0Xn>a^LW8X43P;J0bV=r+W7ZIrB z`HCM_Zzj8G>+|34Qd3(COX7@c92rq9n#-*EA3a2~c%38sJt4uc;fS`jKc-SoCJd_W zCR$o2#ERK1@m&5fiT5-fy6_lro%cDs#K#$|G3ZyXq4+a7b4NVZpy@&OE(m|NZ(#n; zw%A@=F@EOf=jIw>T>XpKV&!L?gEd2HQj?2=ha`_{(r?$zOzJfyL#+r&PinGHF2jXs zULLdE|0pUld=G7{Xq||hX*>GE7d+wKjIsHF!#cpTGh9!qLzk@A4cjak%8G_v?ro3$ zq|AqJ!XLnkwu7H}NWml^T;5cVCbTbibzmMVJ0aQ3vd(j$4-)y*VCP~!4VfD6tjRhB zGu5A8>ks5Mfs2zzi2wn7q>VCp&DWiPR+O3$0nCmL`po8K;(^P6mc)5cL-3a-43PAJ z!yZu6-W>#kht;gf_Kt6%Wcd5AFTGEx{JJK2`?QoBj!2mE27Bsp1W71|SDzdT8SX|_ zrb7FtjZi%4->|3d6*$_5wP##|)<}J=gk<~br4MRlNr*Ly?@zoY2zn}2-2nfIdnB{d z7A<^tVhAmnwIlSY>8~67SGq{P`@4%Jc?7e)DCKQ4aNpif?CImH2Vy10*M*yFVkOT? z1lT6jBwAv;^aZfbN0nCHANxIt9d#`nUUFlm3DdH#Gj2^i4ifRdd*h6cc|bSzNRJS4 ze#80_IWr8R^^!Ve`lsm*KGWFaY}euXo@I{$_jH$ruw7*{kqI?t{`f}#35`jW7c*K( zWRO#)n*{=_X^YHgjC*?HAD#S&0$#|v_v*>&5H&W=-XG`sDk(oumpQTcC^H4r$(%h! zl+ZfOqIwFer!9yPGk%h!e(?YzO+uti+xDJdRI|=YB=Hb0m=(tSjv4%z(9g%C-yf8= z+Xm8bd#C0Pr18%s>o5{T^J&GKPkE-s9<*{8BEtI%;=KtfRW;$k@m5FpE-u z?{zk|@L6bOu=3*SPsc`@`2(|;2gL@tOmAd&QCxfv5}uvLSa-%mO1`%~B;*#4RdjY< zDYee}wPK4Nk%Rd25aWTWH78})Ip=@Wx!?#w)b&Tr%VX(nHj>Y1>tcl*pme~CSGbP} z=>*+4~32!>Z-RJt~SAL5{K;UGrXC zqtw1wc!7$sIJcz8h4y+f?P6upQdFnlKyTfVFh+6R}W^5%@`{SgLM*a;}Ugj(3+_NMLig1?wis^oFrP;z!S~ zmZ;%)PZw$p$E>NoYWt#j*WiaQX414M$umCLH&K!$B`}^dm$1zvIx64nam~}nez{PX z_xVmNd|EFb5$b4i=r=tFIt!5jI*Zq`n3 z6ydj$A8d7!U0>Lm_LeHDc^&1jRBS6)-4mwY?bF`dEV$m2mLTCkpr#Gq5YOS6kG&MOLfp(8kbzsbk6k#+X^+|dq< literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/04ee335faf821b337dba0c4d7ccb0b67.png b/pytorch/官方教程/img/04ee335faf821b337dba0c4d7ccb0b67.png new file mode 100644 index 0000000000000000000000000000000000000000..81f76fc6e521861068b18eb353dbd60622f2cf90 GIT binary patch literal 3397 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 R{{13=rRh17*GBHt{{bR?AnyPG literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/04fb3a8ed8e63cf7cffb5f29224decca.png b/pytorch/官方教程/img/04fb3a8ed8e63cf7cffb5f29224decca.png new file mode 100644 index 0000000000000000000000000000000000000000..6810d2f2e558e0dfa9f40ff2c9e5056c35f73591 GIT binary patch literal 80358 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�x!4oX+v7cv|i??R^LhBBe+^3nT>MDCJj5 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

iHxS& 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 bmqD*sQw2sX2&J!Iy*zT#%2Ktk&msQ@0&}u! literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/063cdb1f0b70bc4c83494b9819c6a3f5.png b/pytorch/官方教程/img/063cdb1f0b70bc4c83494b9819c6a3f5.png new file mode 100644 index 0000000000000000000000000000000000000000..8bdf3614f408b23773e14626f7192d53c7d76ad4 GIT binary patch literal 7098 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 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/0a7a97c39d6dfc0e08d2701eb7a49231.png b/pytorch/官方教程/img/0a7a97c39d6dfc0e08d2701eb7a49231.png new file mode 100644 index 0000000000000000000000000000000000000000..646fd547b9588b5c9f9990f9c4b223b9c232d437 GIT binary patch literal 1483 zcmZ{kX*|>k7{|wLW|$ergt3$VAfepRQU+t(XA_f;i|EM=ks^RS~?d!PY>r9|*9nupSzlozT`-pE^a(a?=>- zX*#ds$ZvbP;WO!TrHB|5TZc$&;EUC3E=BZndO-Mra1iH@MT*OP+xX8N3%<6G_lWj; zt3;hP-KNZup2f{T?~>L48FXbRn*Fl#!TZ^J@dGtJtdyrTB)|mb9RK&@QDAzUCY?bI zML~q<0%-cjWIDYdy5#p@n-F2rj=sNb5{c?b_Z&`Yopmj2IlXXZI#3wVESGBm8xLO*?6xT z)wrUuvFbP?%S(UKP+e>q3w*$&LH(p?bF?n*d0uj3sU0p|nVc&$S!<~Q!D#YT>;i2# zEeOU+4)F$;qnwxqJj?Co$x)G>zV~5re2ZT$uD9Teg9F%U zfw&9o&qTCe5nYk?)WlT|{V~O+<{O)8Wej%JBh!pUljdS1tGM&W+&3BsiBBbSkNL@X zcH)#Gm+V`@?K3@28mm<>G43RrPQS57h}9vKpq=+K{f73MCKnI8G~&N%q4_CFX)5 zC&#}Hvm0fG{c)q7=2TrPGyjXHt`3X}m%lvhzjA2M%sRz89lO zC$=6DMg`T*4|MS6ToCp~(q1zpZSh*S*pUN}%y5z!Fwh zu)4d1W+S>xp22yK!D1fi34~3v=4H~Qi@ftsy5h=JZ3Gmezdi#aXJSm0HsRgK4k8NU z98~OMs(A*8noc*CiY(pAC#Xl3qsk$75$8fd;v;p5xO(g9Q!xQKn25#<9CbDFZAX;P z?95?5l}wfBi@0qNjBVHO8%&qz-S~+j%%}Ds_FGED9%cD}qPvM2Z@Eq}dL+vVn|DMX zd%m(?ra09|A;DhmpHT-M?&gn#iHG@5?!xF2lP+|rl+M}K8(-g*-*URNAL#t530pc) z7(utu%T@#bxE0n~b+hb+TG-$_F{Lay2=5aINK2_nrO1Qe#+WeiMQ{w6D&7wAKUtQ@-K58 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/0c7a402331744a44f5e17575b1607904.png b/pytorch/官方教程/img/0c7a402331744a44f5e17575b1607904.png new file mode 100644 index 0000000000000000000000000000000000000000..85b99b476019af59ec78e78af59c791153ed2816 GIT binary patch literal 1611 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 bdLD<~@~J+(#W-{5r~!t$Xq{@LL)3o&qZ*t! literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/1af46e992c93618e7ba22e311f063d1b.png b/pytorch/官方教程/img/1af46e992c93618e7ba22e311f063d1b.png new file mode 100644 index 0000000000000000000000000000000000000000..79b719581da1ce0a0f9d9aa68117d87f35b4930f GIT binary patch literal 5611 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

?~(t`STK(YLasmsYsE0JxCO+86K0J}b9Hh@bud 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 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/20ef8681366b44461cf49d1ab98ab8f2.png b/pytorch/官方教程/img/20ef8681366b44461cf49d1ab98ab8f2.png new file mode 100644 index 0000000000000000000000000000000000000000..540ccf723eaabb4162df64032776ef9f903d8396 GIT binary patch literal 4284 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 IF!hM}ADC2M?*IS* literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/28a4f1426695fb55f1f6bc86278f6547.png b/pytorch/官方教程/img/28a4f1426695fb55f1f6bc86278f6547.png new file mode 100644 index 0000000000000000000000000000000000000000..774b810979113eb2fe3d112286f1876e5ff35c00 GIT binary patch literal 5235 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 So-L^W00002+nxz<7FjlZlDRp+kr0>FF65 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 Y(BIN?LW~adXs};&G%smnsgoc54~*<&2LJ#7 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/6b495cb0cd4336a2469d9f07696faa3e.png b/pytorch/官方教程/img/6b495cb0cd4336a2469d9f07696faa3e.png new file mode 100644 index 0000000000000000000000000000000000000000..694a9196eb1eea8a7d11ac9d20cb454e36ae1d6e GIT binary patch literal 23000 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 Dv--5# literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/77e0660b596f377125122a2409288181.png b/pytorch/官方教程/img/77e0660b596f377125122a2409288181.png new file mode 100644 index 0000000000000000000000000000000000000000..273aee8f36e024bf2243f0d9612b642637851fef GIT binary patch literal 1431 zcmYLJYfzGD6sFD0RJ76zbe&q)%cPbHJ6TX^WuKyiqEuefYmP2TS(v3J zx=NZtlGk0qTV|M~Xk+^d?iC60`)e5vzvHp>twex2g zue?>JGewf9#3sj}6XKMJ>3y3%C8VK58M?>B24qN49lr|oTN&(^;u#Mh0O*kG34;3X_yZxHkqUL~l*3rXW`5 zCe0i^f4m~!(G#wK8FzTLQ)2wA;i~Z6dwka~{UMFhB;IR=OSAApf|DE&7uC|Gcs}o= zQqW6zw3Kpbf(45@TG;BPdYC0!2%F3lru18GKFh;3!^NVg>qw7oCTdueEvxVDOmlxa z`0zk?F)-f0DxjL8U0Gbg@y!z(Y0>ts^9U1tes@)?7bpI%HrPGIFTa^v&9rHle!+@K zy0BZHpXqUsH`E;94dCTc4Xgz(-VTd1c8n&t836b#vsl$sr|dxSHRB12D{RI0A_1fk zsE(=>4vF=4NYy?v`?V#-Sf7Fzs}8PR+;;g&3szD(Lb4#itmDZ{(RG>D=Zs>!|NgcI zgAa_k4?92|(KCtlX|5+a5jJ+?J7^=&^Br`8l6?v#BhbJ{AHP4NNhMT}6;lmbkHBUi)_#<-w4TVIh9< zqt1vtw3RY*gt7#rKkB_dSC;3-Ejw0%I%V#@w@Z!wn^B|HG#n0O!PSFtpKjwVt5sx$ zEOs3oGvFo@zp}{h0%rLFW;)_xbby* zHYA>-zjJDW-%On&;HDWVa|?~(HzoG!uW_3MF!TyZN>?&xcJ(v?e~-hmGsf)`3SBxfT|&M;PM z9xJhqM+k$QaoU{f^o$%A@bjNWBpjl%ke2wYlcU7+6{7oAMe)fh{?xx9^AE&QWq?h5 zAgiK4zb0^#c>Y`Mv@Wz~u*CLl{5-3!41-|g=vMNFuv**vA@8+8AnBJ2GakD`ziFk; zgr@$4C`Y3rX9TMCv^|}D1o+-?1D`H;s$q?RbIq}M$6P`vfLRI?-dc#3%&caK815&@ z?ckx>h?}?Yv&2AWB$p}5#-oKn*wrTSbs0Efv1=(P(+rtcUvM0J70c+W3(Njd8UcbN z)WYVsnJ1h~FI)RXI25jj9Te_Vv%w4!B&5U+P(loJ^MehV< g??DspQKVdk1XSiG;{48MfR`46IfC;N9E!^N547RU?*IS* literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/7a28f697e6bab9f3d9b1e8da4a5a5249.png b/pytorch/官方教程/img/7a28f697e6bab9f3d9b1e8da4a5a5249.png new file mode 100644 index 0000000000000000000000000000000000000000..9f4bf2b1bed874738be0827e0857707879a544c4 GIT binary patch literal 20640 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%0D#8;eqx`S1O1hbit z8P}HDNb7cnYj1iU-1C6-gG33%<}UF9+Kgc9(?v*tENaBEV5u{C!(Yu4jiohDmdZM2`qK%B4+;<|*EIZS=FO zXZi$U?GOjtO(FzR3?t9cUV1Z3!D7ayr zhE?ciw|))(7jn~;em<7uvq=45y*cs)*B7ZZG+1z0{ay>O7v-~80 z5^CI^`(@*j(U&b0exSX1JzS)%&baq&T{a#S1Aix5pWkdPAIx+`Pv|O#x<_DDGC>`B z((?GE;QUKEe@u$tSJw0KMOEqs*T0-j!jRi}%FgVu(t5W-d7)&%fbVPsS0j(k;gGAi z(1bOrb7zXYVH=w8>(?qhskFF~s=(zWCe8njJf=^{BvF<;73+-@;M84i|fU0KVei%?mpH~ zZP*cGlCw@0f(W|)KRLa40UN=to4)@Z#rvdoYozjUYeNMb*{%+3*BA(_)Z`W?1-2Se z>GFQT^QFmK$5yxI_%*+Oye|WPOIZ275)Lr85d8nLGoe|I`u2%#F-!Y=(hq>-`qmha zZ?bW4^h~D0DnsvH)vx*Lf#)E*J+YhVi3+kXrQWmF$xt$$@f?k&K<>I_q9aXrevyxr zJE-SrD-!|QgI8nuCK~O{7{WgF;zmNHV7mK{qk!vb;mT>n7>T2%=_cB%gkp}hR+Ow4 zQx&Qb3+A_SIVkwd@otR{2nVfNS!p@D`fClw)&g$t}p3K?}oU} z08HwI#t<$U+)2z_I1X;OdmL!^d;m5Qoa<`;j&`g3G0SVq^!l86!RtonFY|`2vJuf# zCOy~4UZ%45240!g^_RO8T3k9)(-1(pzw6fC(-uBAf?bcl? z`L}R?lPWH!{Vr5`(L8blHxl-IyY z9`4j(|AKQYLSHaiQ{rFxpFW^n4|aG!p5`V7+-?B_mI1F{0lR!Fh@b2*}aPT&{&GV!d<7-W4KU>GPX}%eD z=7WP$8CW8i<3u^np^^sIh}ZslcdVD^`00!lQ9mMQPO4KPa%1~@h#owx3iN%)e|05l z=0oG97e2Mup4pZ;w6k!ukE}{uFSDlz zII&&HGg4nrOywr0*|?A11Qe*8ho=Mcq(oknBQ%c5BqK<2JpS45u28oO105}wgT?kH z9{9c~WLQ5?&9Q*))>lWUpsvc4=2DRUL-kAUioDYvNf~AR;wS1pBLjQ|y39uHj-nuM z*y`{C$znkfxxobca}O$g#<2=F^@8As9FZUo!&Kl@aHVZSvI0hUpG?v@LbrrT&-}Jp z>i=QuXG;lFpzL1%ATZAfSA8e)%{SCl9W{_Ta2bz&)eln@juJYK9AJiR002@IFpk> zk3=fKzdw1cyeaE5u7PvIqc6my6DRxkB|ArB7D#@1VI^+uS4;A3!zsiLzozx4LRyeF z((ByH|4NGJHkJn{2|O1_yUxi?SIS0|tnu%kC!8)_76s6NoDKF26+y>K6UMv9v6I&j zXy}vVV{+oRTy9@s_7Alf7AtsgysyZ6V71gR>NrQ8TB7io!RS1X{X>2PR{LqcN>Op~ zU22v`Xjvn9x^`eD=+I`r(+z2+1v94TKYaiYj=UG?LuckSuJ;No^iGGi6x1_{*o$8T;)b? zIyus#kLL7@t^4myo>fhUy$>ugrX&=nF8u;`$Q>o0ln(y|+F&v8J zbeL*U9qVy}CrnR2Re+;x2`NxxfXZ3Ct0>YER_L$*b rm$?)yg@rQI(5n1TbpxO4hddwt-P%=J9^E>xZUCBUx~k>MwqgGdPS%)Z literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/7e8670a3b7cdc7848394514ef1da090a.png b/pytorch/官方教程/img/7e8670a3b7cdc7848394514ef1da090a.png new file mode 100644 index 0000000000000000000000000000000000000000..3a199f398c31fc83539f71a7134fd4390b9f0d23 GIT binary patch literal 6114 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 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/7f2d776cf49fcf3fd44fd84a238a3cc6.png b/pytorch/官方教程/img/7f2d776cf49fcf3fd44fd84a238a3cc6.png new file mode 100644 index 0000000000000000000000000000000000000000..785c6f6ad6689691c6765a2a07655522c69d651e GIT binary patch literal 3102 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 XkgqG)j9)B200000NkvXXu0mjf4#O3u literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/8130c72979511b4b2daddcb2d909388a.png b/pytorch/官方教程/img/8130c72979511b4b2daddcb2d909388a.png new file mode 100644 index 0000000000000000000000000000000000000000..1e90f6053d37499823c39aaf9b6d1874b3dc6d6a GIT binary patch literal 1679 zcmchX`#aMM0LFK;teMNxRYXNDxs6Z=^JHX-3Db~C7$KK@CCR0d+c8;_nL`v)hp^;Y zn4EHJQ`W`|b1T!1+i7kw=5)><(fiB$Jns*m_x*Ev^#@|8=mKN08^*-y}gnu9gRaC#gal!aRaY~*E}V) zaj9p&=$Rg#k?B1xSrZrY#zIHEt_E3dB{GZ-+Au`yT!U9#KS%sRNtPCZ4w0hnOnyyt zIv{TpZ!{A)32Af45g5l;5R`myZN6JJeF~@vk&vZNuQ3Tgmu*+4MEGgvXbt-;=td3S zf3}K<*txElULIyf8X6YAk+)Y7nco*{#lq1E>V~`-)8j7wi;3cSjWcC(ype{W-Ij<*`pRMkN93f%`Wk|F_X);hcc6S0{wihsG+ENv$U-rAS*92K6ngh zcSBWJ4CF%qlvblSE1HNtAPnzPsTp@wN;`MHxebCI6J20D>Oqpubx+$~ zo5Gi(BBznS(#d@tX|zmqTJTJY?->=t+yos6swuEJT-4b`vf^bhG|-8ba>?yv9Ti(X zIBd53MZRM+EjLQ1YqR7aKKi-Zb-~#UYr~NxX=KY4_`6jByJZn#;KmaWFE5*b|BxOsCQf{o3T(xmfJc~uA ztW+&6(24GI*%p^vG(#I74oZmGOEnbspYu_{Ojm0@ZOxiiT)2`D^PO&7_ol^g1gMM9 z1w$I5x&<}BP7?!&dmZ1ZFL|Alr_z@pi64zf!@;^(A25k0+<|CIN->V|eEqS-7H9Xd z8|Gt2fcN+bj3s?7m=R=YwpZ8_%U&PXo921eT)RT$s@l-&zFmxcaCjkB@kf&*-MnzM z^P72rTbJ-_ElK}|R@DChuq^I{(P`}dBQQhqLe$#>3we+51 zh~41Yoqq6Pp_)1@D%}^qlH-G7EVs_%Q0Jw@2R^&7!pCjn``d{RO1&0sz5U_Gyc&}^w#vWY cYTvdCTqQ=LoB!20+N14iZ2j*23u|=kkN^Mx literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/85974d98be6202902f21ce274418953f.png b/pytorch/官方教程/img/85974d98be6202902f21ce274418953f.png new file mode 100644 index 0000000000000000000000000000000000000000..5bf9e630be39fb74b9d0eff8624cbcc33eb21cef GIT binary patch literal 17987 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 z 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 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/87aa5017f5f0ba9a29d66e74ac6b3d1a.png b/pytorch/官方教程/img/87aa5017f5f0ba9a29d66e74ac6b3d1a.png new file mode 100644 index 0000000000000000000000000000000000000000..81f76fc6e521861068b18eb353dbd60622f2cf90 GIT binary patch literal 3397 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 R{{13=rRh17*GBHt{{bR?AnyPG literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/8879aed8539537d699fb0d155b55b403.png b/pytorch/官方教程/img/8879aed8539537d699fb0d155b55b403.png new file mode 100644 index 0000000000000000000000000000000000000000..1171591d42396928a3b4413296cd9f65f4f24eb0 GIT binary patch literal 10092 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 VNxacS{-@8OX{zd~G%DFd{~v9N*zN!T literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/89adff7333b116436cf785388029ba1a.png b/pytorch/官方教程/img/89adff7333b116436cf785388029ba1a.png new file mode 100644 index 0000000000000000000000000000000000000000..88f2c9d03762c3a9095af7781cb9b1b364fcea2d GIT binary patch literal 5970 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 K>zyX?_WuKK0hWmX literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/8b09d6361316e495383ceedf9b8407ea.png b/pytorch/官方教程/img/8b09d6361316e495383ceedf9b8407ea.png new file mode 100644 index 0000000000000000000000000000000000000000..69fed39fc4d52d3c9af8929216dcc181cc3a7138 GIT binary patch literal 55030 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 bFy{XOU!lE{UQKRP00000NkvXXu0mjfWq0UO literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/8ec7228e178647ed9c25273de4b9a270.png b/pytorch/官方教程/img/8ec7228e178647ed9c25273de4b9a270.png new file mode 100644 index 0000000000000000000000000000000000000000..7262a25da16f20d1f1f523ec4b88659bf903a9bd GIT binary patch literal 5509 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 b_kxo9t`K%N$9Vs7RiLMBs8yz6^W;AOaH74% literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/8f596b99dbb3c262b61db267d5db2d63.png b/pytorch/官方教程/img/8f596b99dbb3c262b61db267d5db2d63.png new file mode 100644 index 0000000000000000000000000000000000000000..e8ba21d389342338ae5f733265e9db124acfac4b GIT binary patch literal 70390 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

o2n{js5f+V$8aGLF75scST^$ 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±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 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/9ae42af4b6629f7493bc1bc150af6355.png b/pytorch/官方教程/img/9ae42af4b6629f7493bc1bc150af6355.png new file mode 100644 index 0000000000000000000000000000000000000000..17dc7a87324d4b311b17ddf472c10e75316636e7 GIT binary patch literal 4781 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 Y(BIN?LW~adXs};&G%smnsgoc54~*<&2LJ#7 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/9b7e299515676cf41cd2c0fd6ab1295d.png b/pytorch/官方教程/img/9b7e299515676cf41cd2c0fd6ab1295d.png new file mode 100644 index 0000000000000000000000000000000000000000..7d56120cf9bc3517947a4bca40f58887a8b1bfcb GIT binary patch literal 1582 zcmV+}2GRM6P)Z#6abG-0Fuf72nYxX2?+`c3JVJh3=9kn4Gj(s4i66x`Ef31000HK zNkl6F^Vvh#)5ev36t$6}V_5&c*|5O>0CJ7hYF`n)b zkZQuk{-|<=1oO8^k!@n+WSy)H)}Nmrd#~S*#s2&7DD(K5Sk?aY%&J1CpC{{^v-F!R zEZ@v*izQ!5hOw}`nwftLWfTjida}(JHofW_E&Hmknnv{7EO(r&l*9B?wgcJ}vrNwBlhFjKHyiyIEYBkz6YdogzD_Qro zJ1+ris)9P4;TqZ&i;s2evc}_-hEQ-dwHL5pdyQ5Jt+?D})n0y0$7!t_E*Dw4mtKA; zU%xPs9|8F~RyeV0 zF)B#VA^R^v%cqsm~vb}ykDtklglvPv5? zy~Q$Z&=h+Gb*xJY7Nhz6VmbXP^7%!ID8J0(ThsZlXq;d6{;o4Odg>eSk3*2JXS)>T@t8A}e zKtVIGW`?%Apk1eZ*90u*S6AA>j4TWF!`cOw#=6|tXVDP9fMv~P#l0%7R$*h^0CPGV$IYt{bbdB z`8y^x)>-P|ar6CAvV3N-q^ychw#+J`SxzC-qv8a0GD@RyXRxi(@`XjBS(8FWDtM>* zS|V0)XTmKLvPOjrP*6_f6g&0JII3!1V@Ts!T5;ex6-L8x4cg6FEwxx+v3FRgkWr3R zaa^0R^b)IxW=#s2$uD3`ONb#P%>s+WvqpuC^UKXOzs-#t=X9(|A%iR-P*8(XF78Z; z9_*P#<5{8CLza_OzlExZH?_rYmR3P zwlG5ptnzr)r25ImvYA+yjI5k~p~eSQO2_doJ)7_KnaB1!kb_uDw?Q$_+M+wa$RVudn^r~+V68Lg5de%Ybl;4{J8Q4QhSHF;KQy97kGtkOA>~3v9CL z&oO62)o^dtq6}z{)jOZiq$jI?Vrg&I+%LZvPOJqP&|YrH<~ACRK!pz~etcMS8IU(i z-N(|wp{Qv*} literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/9d53a7aba4b9016ea39aa794905ee059.png b/pytorch/官方教程/img/9d53a7aba4b9016ea39aa794905ee059.png new file mode 100644 index 0000000000000000000000000000000000000000..68716bcde327099fbc91ce742a21dacfc5cbce45 GIT binary patch literal 4175 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 OdRbfAvmcmypZ*_{7zc#_ literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/a2eafa804c5b1d5c8564675a255507b2.png b/pytorch/官方教程/img/a2eafa804c5b1d5c8564675a255507b2.png new file mode 100644 index 0000000000000000000000000000000000000000..33339e494ab7dc44cce3a3d4c9244da51036d29d GIT binary patch literal 5903 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 R{{13=rRh17*GBHt{{bR?AnyPG literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/aaf8c905effc5044cb9691420e5261fa.png b/pytorch/官方教程/img/aaf8c905effc5044cb9691420e5261fa.png new file mode 100644 index 0000000000000000000000000000000000000000..eb3c503f589b21eb07f4c7f7b623a5033d6d4fe0 GIT binary patch literal 11945 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 D(5WZP literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/30f766e7717c0e45a583a4f58ebc322a.png b/pytorch/官方教程/img/30f766e7717c0e45a583a4f58ebc322a.png new file mode 100644 index 0000000000000000000000000000000000000000..85e0f8162f1b9183153e22735c13130d2cd07364 GIT binary patch literal 4650 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 O00002nY%a!eB5V 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 R{{13=rRh17*GBHt{{bR?AnyPG literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/342d5d0add3b5754dae73ff222bbc543.png b/pytorch/官方教程/img/342d5d0add3b5754dae73ff222bbc543.png new file mode 100644 index 0000000000000000000000000000000000000000..781c0939b6826b87f9165b5e019bb507118db84f GIT binary patch literal 62523 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 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/35d54d0c48ca1c52d56850a202a2c160.png b/pytorch/官方教程/img/35d54d0c48ca1c52d56850a202a2c160.png new file mode 100644 index 0000000000000000000000000000000000000000..2196aa5f0fa2e729be03baaddd4d2cc5476c9c8a GIT binary patch literal 10685 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 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/3aa3584628cb0526c8b0e9d02b15d876.png b/pytorch/官方教程/img/3aa3584628cb0526c8b0e9d02b15d876.png new file mode 100644 index 0000000000000000000000000000000000000000..0a47c4b38afa2bd6dd986207d65415cb83775ea7 GIT binary patch literal 6315 zcmZ{J2T&70w{8j$dX(Oaib(H8njJ)X4?T1+p$O6uf%S0U^;M_j)BU=%oe#a0wV%+@qwVq@tptrlzK$p`oRv zrK6*xr>BQPp+cjmF#v!~Ui0w-PcXnn*-`RdYHdNg_3gdjSS(WDtjp_`W7*aRb@2f#}+rVLHz>jeoFYSZkv(aL* zGjsB@E*wu&ugAaNVXJv>X;5_FZ?Q%MX8JQhC##^YIjz^H!tkx;d(g}Bs{Qturj;Uk z}8T znQC7=m_&n$vqB4WOZR`%4r;MMFQJ1nZmCXzh=G6$b2q2xwWoD8fPmX5=#p>=85@5P z52}nlJIeKzc_jE^gSKf6n*oWDUS$Og0Z3+>_J#{M762#Rv8MvoV<23DhZd_2p7$p^ zGif$Ww>v+lK@E_H6tK?GPFDQFHbXQ3NJ%(ue3SCHH=KO@&chE*!bF(O1S_;+S$_JB_+j-77ojydPx_k@Tm0zqjHW6;OYG{ED+qg&zdBKW~M;nu(5YesW zw|?y}aD@9<7Kqhs(im+(68J)iD>N1GBk+W?Yd5!?4K)Bh6WX3gypK+^zn+TfBDm8l z`VwLw%H^<#yHn*xRM;Y5*2kYkA85i8x&#(Z-KK}sn#%i#Q-D*n& zt9>$*)~x!2Vg%$W5M^pa0g(VU5S$Xl51@emH~zyT)xo;o{oTLG5mpi(r>rFLfruqQ zH7A9q@-2QH0fsT_~wo7ntfB_(sQL>Kz@0?y# z!ffz4IY5uWi?KNq5+n8yiYlgpeTZ?)<;qD)xC6;{EUBej)S$pJUTw?Cl{|$-tAc&p z4e&-S1CbG+$0WHD=-9uKqTlf_*Q|=1Xp|Z%aHG9+c?_V!js+F$&rj^PGc6maz*y;N zu}0))EKdxu=Oz>jvS}ZL>dCT|y&_pq#nXR@B9%i6Z)g^}*jIhGumBZzY#QexInjjv zxZp1mKr#jvU!Rt!{tOjCu>*$qdwNe{7}{}WY>do@@>Q1+yF-Pzv9W8LZ^}W(WY{D! zQST+Dl@<&|m3SKK@ZWTA?*1yU^Pm;*n;NSWM@6p?cv;G#!$A)FB$kDhGrnn3QV09Z zQve|7dnKWN(d^ZM3d}P6NQ;LsUkOrK&uoDKnJ7G44$BiywY_yz4BG$Gj8pR4*El|1>bLS>@B~-xeCCN`T#Q+W=ZD zfEFl8hP?)O^k4j{i3ObL0Dg-Q;znQdkQhwmp6(NlL*Ln%pzA(gJ_`fLYaV8DNQNeN z-f8}0&JxOwn2(W6g?Bza?}NP^F6t4qe)CGP`bAl_#?g$XCW#)MsWDl68tzKUDV67W zM9PsN94%=9I%>xb=i(bHAss$qpKZ#q-u4q{q2=C*SId_^!=Ez+2)|zB$SOftD2Hlw zmt(yC<>fq_e@!|&-u?B?N5?@{uMz$saEG}ovGz{_`OE-=dPY)+0f+l{hZ)d9;BE>A z(cHJ|Gt6}?-sf1sN)zGoS%qVUeMF~098JjSz z-kdVZZ|-4?j=}_l%eRie`a5Wn<1Z#;)s%IY>y`S>BPIUIls39IFC5nBGJZCe6wb*a zT^m`4-iL>r7rk!ik(m>q)YFd(;WW39$RR*81{(PtFwBiFBr2v_uG?j`@AsPf*>v(h zI+l0A(J_x~vc)yjHMf}jm{xe}-a0Yzo+`xCH{Sz={A=qxgszTmnR5%lm>8-a%`-dl z*{&>Sa_rMn3>Um~S(u#->54xUUm5N^p4WZl8SLN#{$ulyUiIyE&f)?6ll3-#O*++x zs<7ghbFfaEJp+2qf>zP3E(;f`4x^RzdAfRuN54UZdPinjr{bSChf}zvBdUBaC*-mN z;G5*DhFV=gwU%R>PS-*e38}eBcm^lSP&J57AEb;K+py%TOtB!eS3fQ98a?8wb|v zp>EJZ$!>ki+0$}7u5ToDyi#}F9zpj@PQ5_P{g!Rt)?=p`r<<~3^`#E((^S?71;&Vj zz0FDMHKtF>6yCC82PI`CtfN^C^n z!w#0k5ZRC}G<%5hVR0lfw&*j*!McoM+ZhrOPO3XTd^C>0spAc!|8dk4mfP%QDLJu? z8g4VSt~?C7e7jDbc%R_b?TZJ;pF&Q99IG0hUMBP8i>n6j)dW?Q@@fBQ4BPv;rTVkz zNcoJ-)m0Yz;oR(LapR*!o9Q1ro8||!F;@$Vcl~MM0V=Ynl7{2=4PCVm%gP^x$IW8G6DK^pAVMA&`O3Gk?qVnTJC`*G977=%J(P{WulEY=Mf3%T&@;= z8nUH6lHG$29m+25k|?8h=o+|=?cRGhO~mI9BGQjyxzeGIT3ye>!8r)V&r)v^|z!z)_*Su+2L z)bKNL;|ks^*L$2a5ke;)rug}$6Bs$=eTv1TF=VP=w2hTJ%v8KEj?Hf$IS*7kQ9qv9 z6X=)gseUiE%%?pK{fK~$lAmtR*A;I3z5DVjO4Pa*bJA8+F%W55aG4Ad*O?uKS z*=f@0QaClDz)FIof#F@dpcJ+x5OlP zcC%3WmQW#Fs8F)3=<}$+57VaYIPwmt1dVaGl7;}8lhf~S$HHY!OjX-^{N+t@E+TWM zejTYJU1mEfChzW>v%XZ1VBRy~{FJgi4<d-hmn-7=%B%K@`gkfU*_E&S zX9K#7PO|E}#W@sN5o(m&$5AJ@Id;pL@GfGZ)WZD*c}J0#pmofRuEjH<*93UZ2$E2cO8 zy36K<+5G3}BK)c@vbCbIh(q+bbukr0%R)JTegV$Es>e_<_)@8!E2EWt*11(YW^GEbKcx)o)oX1#zy86=j>(cra>d8J9mmUr?FQy zH0l3!yM4POt5#jcl{+>_zFxbS=Xy{Dp7uNbECiF*(7wvmU&OQVxQ^OLZ?Dyv56Zey zz>hY!^j22mY$hWpfCHNp^Xz3P3ZSem`4;IH*sbp@yNZ6gwCw#iuKGebuvPemlbriS zzLMmADw))iOj%$_!2cJdWT4<~eAjZ!H7ZN9e+x*d!DVmBZTC4v4oj0u?#gZ;i@$2n zgFW~K;-G)>ITw*M4`0ZC{-)^k!1(H+-RL1c4U8JdI-tnr$fqGj#F1qaQd&I7L;hq{ zbb~Q+FmkWaZy8Ehn`>mDdx<7M8I}{etOHOsUBepSSdqs|35K0Sh`_t&)i|83?_s^G zpNJ6OLmP%E1H?35xr0NrFB4^v<20ma@y)J~?CKGeZLQ`Q#qsw>6`P?sHPrbNc@qoZ zUJ^9J1G}Q0Wd?|vAA2r+jWl(1Wz}O;R;)QV#Bp)bMkA1vPkMcddV|xO$SR?jb={+e zOKBv;g1l-6MD9OYz7F(g2xPBLZ*gJ3#zj9O_ma=51G5Nb982SZe{1b2DaYTku-$k9 zhUGf)L1M_p+BIOROM2y3&ndWlJC~PQdflZWHk92fGkFj9!8fy~eF^+H zaaKBr7QTg(?peCz?J+jv(!fMgfwTXW8y~4E>M2bdk zaGCl%rG~0SKd7ns(?nToz*?WZ1LU_5KaY{s3uXRzFa2l9cvrY)u;4A!2~tT~f*Z+y zzkSExF44$t>EJHE6&jCXdJ|F<$-|4}2M8ixvSJ(@m$@hT5PKtr1pyKigIH2x)e6ed66SR<#wL>`?OifrDLBb-B%0WJ z^pXjaD9|rNtN{!1(sjL^R#J@V7YQu%ey)YRvZ>AiX#38ixiEO@7mH7buW(+#Lqo{v zlUSzYH|r$G1!62btEPY6w_4(+Pp&$1A%3BcenWxTs8rcpBr*J{QQx}F3KLSJC zvZ8Th#3!l0znV;i_b8cn!39&h=%}s&@M0V0iviu#rzQm;uR}g7V^esZoBPXOO32si z!h+l^5Oqq$(()%AH6Sm2De3FP#%JM%O*QRb?n-h_#2g~%2u9@9X6p?RnMvg!hs?vm zC__+)+kRpNt_#G}ld`~2W^Or-52F)b^xEgAXa!XIeNWKI`G(On9g)>i``(Myd&Z{d zSpRW$*u)^qv1ca<$zlo!{)O^!*{RJhr%g8i555xMEvIb?5snkX!>Qc{hy7xl+D;X=Wze zi*X)x!7B-sfNUmA=Z5h#u=EGhH_8J@YYf^o>W~M5TIu0StApeu#OIs3#p@?{`P4tNlql-@aA>uN_KRcd=gG_3L- z2}tXDZzJ2D%%|Hz-^5g~8Z;vEf}Xz&Jc#RUl>%kj)FH!jVccGJN+Wk(VV53yP%KNa z)Nl~(Lr-I+{E7fq)*rI`0;V}%V}`4x7&fi;SAcb?d0F$Dt^V#L=RglF%+V4!AtZ)e zR}LNuMETd7{!k*08p<8sjwx)CUW#suw$BG$4O{}~BYt=9Z7ZWygz7S(_7MMO6`nA5 zg;fNR1QbuST_jql`7DmY0{>R@ilK9Y#bYcWh_4Pz2Vv|Am@HW~wJE@V#kv0pe*bT% zJir!(bV^`!VQ(*Ja5^XP9{+G#K>0%&+-m!~i-4JBYK)WZ3j7GOlQVDdHk7l^W}Q|n zMic7iX;SAK8Kah;w{qk>?>vg0I~`-*%^PcG%;IUKB&bS0m*Gm|fV5s(n$XDHlx<@N z<=}hpcVPh&#c#u=x0(t;$df{i@!hg_gZ4G(`ZGWNO$oc(5$zV6(hocAEWO+L>mIEq zR2$NdKi?Hwg@1kWG<_o~jvXN}-@wRSKKI80g8n~wAHFZ>Y(CgB-TQOGGj3iosdIRm zbC(h3h>y}ZJ0qCA|NI|onR3}b&Br5godIvqpPjA~?WFXYwKen8=Ip(CX?_yiF2hkNn>FAKVRXOIGYNRan4R%lHur!2ITAw>Nhs!1NF9v|X9! zp=y1+UkQIPqo<|=E;Mxpz8XW=&-l#TenTuaH*{^{;i^qEiLPLkj7ps2snE(I) literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/3fae03d85aed3a2237fd4b2f7fb7b480.png b/pytorch/官方教程/img/3fae03d85aed3a2237fd4b2f7fb7b480.png new file mode 100644 index 0000000000000000000000000000000000000000..5b7b315ae47d5cf69dd1bcb5c2365ec0aaea7a33 GIT binary patch literal 1192 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 ZC3VF&_;ex)^B?X%QBl-XsCjP{^?z&Z)SdtU literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/45cf97ab2bd8f85e41c99cd60c565619.png b/pytorch/官方教程/img/45cf97ab2bd8f85e41c99cd60c565619.png new file mode 100644 index 0000000000000000000000000000000000000000..aa8917f8e492362c1e23691af0ee25d691a51b9b GIT binary patch literal 7257 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 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/462373919a0dfe17cd816fa0d8af140c.png b/pytorch/官方教程/img/462373919a0dfe17cd816fa0d8af140c.png new file mode 100644 index 0000000000000000000000000000000000000000..0e6c0308d4146ad6e38194fe8bff2ad2d2b4dbab GIT binary patch literal 1440 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 BTdx2B literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/4a48977cd9545f897942a4a4ef1175ac.png b/pytorch/官方教程/img/4a48977cd9545f897942a4a4ef1175ac.png new file mode 100644 index 0000000000000000000000000000000000000000..4765ededc13bf10552b61f79aa598d4b437880ae GIT binary patch literal 14081 zcma*ObyQT}8~;mpgQQYQ$Iu-LNP|cXJ)n}(Ak9z;(t>mf3eqVZhY%2klm=nw?jdGi zfXnB8?_Kx5-@5DB>pW}i^jOv#7KmJfkCRFuA+~Df!%?Dfmw-z z{ZPZ*N+$5&g!HrxU*6x}v zAtfaxBO@axC#Rxz-@w3-h|^GcVd%GTXsP9utx1g=Rxgokw9Giq2%vA>Z&YGMfc94QyRW4?>6f8v?gcIyt?# zpW*Jxcc(KnfWhx$SmN*;llL=$)0@Lrmy?Ku*}(_3Q!0;SeOJ>`{ik(<5!!2nc0*kd0M)YRy>70< zIw#pLEZbLEV*f-d_zb&Uviv@#j-h!aX5k0@ie}&Ke46=Ab$#udFC+R$&%OKJF&U15 zh$X$7dJIhFK;qnMH5OOtOvwkIJwuj+EN(==N6)yhC*T9C|EL;b_ zHvqDOu3b1nIMH{z7mI07kS54U4cNgKe13K9q6gUUz|+oSN02vDNYVvZzWMaAmhequ z8iWlqpB1Q_23+)@e4u*P8H8v2di=R0yvr30}+!(Mb3Z zgKq4APDMf?CaA__Ma5%X5YY2pt=csF6VrQGRPn`4{3OT>+rjykJKgPM91EyMU4t4o zl|5z9c6nDWSDif{7QN@%q0tpJP~~62MU=O$67K@Zl(N6Scg%qgLo)@y)!Y+|H0kGK zsEd>S@+XIFVnd)Aw;KPO*E>yw&{}A|M0TtX>NfH`>pe+Vbs*CZd&q51U|}Wwys|_)9O;cL!Y``#xFsrXaaIMeHeF7%s*}jrrNyDUC#v!L zO^(o?B1yHgi~x#NHwE5j)OMZADX=3+-!S4vpQ{=yM&*|O=e8>8b_{djet3~h^xA3H z3|M=KlC+vTxwBtw#TwcJmhUUtwF;7M=>FXDP_e}S%V%#fUcdUu-S1h4mMDNrAagI# zm;YO`1A|Xi`8_|7u*5sS<{0J{T-)@rhA9MT9{;Q1;9{_bm=uZo7H#t4&IyS1sYJp4=@khL;apntZ(x~Y* zj#}adSiFf@{+xu}ATdHJ!yl2+95DY1N1i5G=hKi_(Ir%U@*qvbj{RVLYC=ETEDrVh zs%8g$i+nGR{M4bba@9)-5Y@at9jdZCVG5&O$-4C>4fK0^{W3k|^9vmhG;>|;G3HyN zHM)YwGc}JsdJU){0(FL^B~AmML!!U0Bm1}&ZG?1z9lowv#>ry|uCcCT1*)Y^PGDtI z<9bQW6?ywnnL3aSITY&tIvW0-SNAJacvQg&46M;$p0+V>-%E$XEBlEa0|T!vr9TBe z1vUyd2#hTO>(KRht=v-ETWD2OP-I-l3bK!OUQO^^Ym`0o^i(=VLKh`ZGbn(6{OO4Q^Pgnk}43*K+l);r$q|R-@5^7c@mbbifzegp0Xq1lw%SY!Nw&_+m z24wX4ssB3&<*(`ATBbeY*iuM?yChXt)gFJd5V;}uIXb}hx%TV>CGRswkS3)L&=~RK zU8-$?-)5ap)`UV$>_6i?vRv)>QqxonKbWJyw44k}c8~u25b8tku{>6+7p4u{Izglk z6l5r%hS2J&+C8XGJj=BCyz2k7Ihbm#*Ep$*HUO8*uETXlMst+}t|6jIoY`AeC9&UL>my|}mOgR489*mUGDS)RrAm?Z zpku7p$DXc>V)3cORM)LY(#nqB@DBbvMR`F#D3+$wzOI47!lbi8U`NxhcsKQdq%Y&G zf2vFNnH_#uiK0~nvkT@t91?=QJ63+*o3KS^N|~0|f5vGkM%~fEMeJ zz2x|}d{hEL^osXZERVOxaOY&Mt=`qWG#&`;mfzdEa8nT}J2lP-iFyMImUlG*n$@34 zFUuVBTi?2B@k#Bza`ob);JwO$9!v8*wy0#OeVfQIC1TcfR{8pVErTMy)Kcr#Dm}9I zcChgx7GE`z!s}Y#hN;Lg;Rtf*xc{R>CAOryHSsC*syP9;r@4S#N`C9RHM{P!GM6$a zg?pHWB&mkL5THgZVZnSwQ2`FQnz_Df%2wlW*!Gxt714(ofLBm`+|6dAUNx3mR>=BRN-K>I$kO4}2KNNec1oD+Ord&iU{8mtlyoyRzgfoEi)DG09xlqMOk zP8wZjLYjWv44kzwr;9Fzu{L!=KWZxs^Sb>LwLLe-+u?s2lem;$FHlKQ&?>vO4Uu@> zX0F&eDphQq14WGgSTHkqe@ig34;NLAz808CEZn&no4Inc=3BWYFwMvffnju1w+d^Q z!pY^B-c_Abdff5}y0@&+*^c|!lGsyQ7=sT^+`EoH2&b;69n%U-)cn^hwJE0%&)$mK z?;=>ip|gte{{nIBCeFv z%6_E|VDc0Gc!Ud{l<3~d#q&CcKHjFTk*I2h0@HWS-DK$r$Pe;08rjRJc^7k;h4n1D+**`mM<_jFrFDy|8IFIF#0LtCU>brTc%ak zye3IGz=fD6JKd}8Oo~a(;{$&ow@pX&wpCE?sx>urrYPpslq51)UU zbnyF7hmQQd`{RizE*R=3?h>^!f9U-|w8L@W>)N75Kpi>&@h(7?sgVN4>4=v$>bm%u zrm5S~kDA2XeF5ncAlrPZn+|bH$$ZNo$^1j~Dbh;n%q~7^M2MJ*8q|Ecr9&*0L(1~g z*Ji7ZYuL>WIlNV0jHn>Q%jQ}xTon@;=0qK2i9mZJaogjLC`^2Geh!1`&~H-wZ-rcp zI|=xyYnq&CxZ|jUG#G$oblvN3i(+vsryRLrz@KyCcUR3VEtE`{VQlu~jL)Q=pTD6< z(N~GbEEw1BD&CDoWZNn*M`w-TI==HDiHs&=gl(T>65^@0I}zZ&XUkw!?4jTq0Wq^D zWW7-Kr)`wN?A3ld;P!D@EQ;RxV{;}flU%eZ#Ws?v}s-6H{Kqu2H6Ob`+M-HNR=vNtSIY-S&pNS4EYoadx-B4C?5Spl` z)4j@uxa9?G{@PJcr;atKIcY4>x15B@Oom$HCE(_?DdJ{x<*rCRP95YTdhRNlHnk>A zZK9lc!xHdVdR7((nzo7)k@o(ba<$DHj?p)P1ObWfh9 zbI3?>Qq8Gkh$Kn|*PfUlbuqWfv`qcl544`FG}ZV^UkmyC6j|-i*!yxW|G-J7vPAQZ= z$8132rCa4*{5>G`pDX4}rU^9B#BODcE}IlDXUsbcGP-54sULDf7N}Vy`edSfBXTg; ztAF!Ed|zm}K^n4FRl$Vze6!v(F*RK8#|4%#IJDw`W3KB;uisV}2D>ilZ_|GtENvLVI+gCe869YcD}3`(Cf$lp9NYTLjK;-MK> zpoA*tQPzr8nvf9F(skotg8xbJ9b!=CXpl&xrZM~;`SB(aG}Oe0j!983+N~S9%#CK& zrg1N_DiRZ!$W(!r^NW5C(>&*J+{j%8Z>Z>Ne0t-TMBlZ=o_on;UsPqsea6E5WZqUy#Ksn$zSz5&9 za$0rGB%C3ARbU=`&-u)EWEB$1up2d72p04F#1m*y3$BCU{684Gxdk3}=i7P@TJ_)W zUSXbnoRe~34ND1j^q91Th7CT5GGlE}Vi+0Pv4)q=&$Dv>A~0&R(ipyB>0K64l&#DB z23hl!1Uhg>hSg(Of2$Gv)?)cb zD4{gek|C=|nXc)$r3Hk;iT^amtfDU-t_G8+>haX>Z0Ed_( zi@hb1S(v_u7QZc}CcCHehhL6O6B2j#^{*(p@rTinpJT7(_ekv%mNLTy#znCGaAR~h zVza$g=(f}*nDN?K(yFnvg=dFcaQk#&6px)tSe5qldD$rrv7xe+F}oG&Vlrg=7_P_f+rcPux*=TsS$=EkR$WOvNSZ6cgk6ntF%PsGf%fzWG~JuxANA41jtm;R7EI{-Sob}Zzf(sFC59a!-CRzErNEsto=8FpEX~!j}L!_ zmhr5vjEpagWPd$JBd2$E921kl?@EvFK<+J4H~9 zZ`ufuRlpp&F)-^1p08_Xk7EUP%*nEDKB%&}lqOw!T+hm1@upFAxAzsX9)b}Z3QFoN ziN>8GX%u?DN5-%5#T_k6d(nIKL=&5RHN?}L!7h+oY7V#_BZl+Nl7+cIij&7MYPCteuuhyZwFo1RqTYX@6&*mH8?;*2Jv zq!Rgj{d&wEP8F927NszBmL0Q1^(TQ*hk>R`j%gi|qET%L$PSe}`wAsJUD>Q^?$)f> zMT-C7bK9afM+lc-jU@+ePr^BHsvp_j|l2PpoQTA8++K>NR~UD>DEQ9C%b((9S?a$N5y7`n0A z)V}&;LYV0C7F2}cXl}D|#K))W*cz3~81;{JjE<*xJ8_y&@gameR)Bw0d3K;k~&p z2X%3Bc9>Wp;gF8d*vFI4YsPew5(|&0+EOA>4KzaZz{DuGb3n2GmZtUnLSz-9eDPaP z#{p*p4t0!8BbRjTQRC-CR{OhB(l!hKBHB{R_v`$~=~Ab{l|hVtg_tx1ab+k9QWr81 z^-;_6;&;4oi5D<2e_C$*2u?iXB61NXgBP<;eIuoh{A%J`N-7wyckyl~`YIJ^6<=({S- z#RbkR$`jsv5eR;j858|P>*P1pZqdn0TP5_~rAEKw?ZS>TG8MNX`pxqj_^cS??*tBa zyVnL5gM80)MSyFUnul%PKV;VQjE~4629*g&8$Xp9g%AA@FW>h`o8a%z}hIE9HiIgQ8k6}vf! z)nuhO6-4XrKbNCu3^Qp5N1NIalmSOK7D!tj@#S-V&z)>W(tkO;pZ~l{DPXWp+Lo-D z(;6gbe&gb;i>|vN6ey&BRpaI?RwFH}NGNiz@8)brn?$W#f`JocP%k0F2Zhbqrhat) zT2ZZ41ydZ%|K5cn_d3qBi?B+1S(`X!I@d8>v!k!u4jOi2Xg^4%kPy4xQpM)en+c1_ zC%wwqFdAnSAHjKk;cHMWAp?SXVJ>pA4gc6#G%VB>9`>WS;LQ%yJsG?;v@GU%{XL*z z!v8dzPH;v;-82h%4yQ#h>3&gOb#=|2W&XROcOqMUqVL~6tk)qSBMOb4=9{9x?d~+< z&?G-+AM2T!%XEg2C(`VDIW@``{?c{vwnI~ugG<@YDh95cAsE^CyRUiRMYnCM^&9`1 zatJ@}9hW_bT+!^9;BvN-+~79N6vDsfs@)o9s|~9eE7IvY<}9amc|l__5JL;&N;aWx z=qI|GNxj&%FA>?chB}{N{C~~Ha1K&QJMti)9K(4TGpYj+-{0(8jhx%T-wI-MUVns0 z%O>|p3x8}kQH#@sq3fTT! zy)IjivXq=-dM5Mnrg+?g$gt(n^@%@6%*|IHoNcF$aa}+ND9Yw)JTHEn(Nb+_2YY5$ zH<;rXoS&CN2=nn$*sqGHZUYkLt?g0H-2LqeV__m<=`q>v23YX`;|tnOFMOE{|Cs_T z-A;ah`m>WuX|krZS-5G~7D14B@jL{4@Tdiwi@@No$qID(_7Kh2%PDcLWW6^-HDK9- znO@y*IQGu|V*oyE!I0^Z-yq$lFV29I4hK;<5ACw(n!eB`ZYzyV z+epz>Fn5f$4p~7*SNIDY;<|SR%!C?H8i90fh=%{{cOw_Wm8GDU&?5U%i%h=Pk1|wh zerU{OZpdC0-N01M0^c|7{b>lAwv9xr_~z}^={8dtg`d`%A6cG^ioPmnX+`VJ;StZ7 z>j)VRfe-ZaaDh6DhT|n&5^H{rF1*KVKN%gpTxutR9JTRCtjs(zSNV~+2j33#m3Ydl zHLD7|HN2lt@W3eroT#Be32(|}4}KtE)%~D%_(the{L;bA0pYMG6PYyXCEt>_jr-P< zR;-HNBuD=R^@EVSSSDTWus`^uWKDbwmc?|1%f?_&P&X*+_7-L){Df880 z9woEV5AQPG`4HQBr?t|*oKNY?+`IJ1Vx4}_{4lXBMLlAf{${>aQ8PU551sa*hz7f5 zhUSx#$TMNnK00v}rY3j=Z#m^BmbCoYqLf~TKszkfMB3c`xZ$az&$MCsKp}U7w%gzkp+se9G2SCg!rQ$1oj66*FUW!|&Gr@QEL0^Blu%7TsD*I+Y zVwnc@#2rtte*Iow{2eyc4c2x`?*G{$yy^HU^sCp_tcA)KeU5RUmfCT!Ka*Mez}B%k z6D}RUxff`92CHixgcobgTSDW{Mg)Ec%RWj@6=fKz;K#4`^XbYFh$Kz7?Hq&`ChYM8 zswmo`n7;>~;tz8)w1lb(hOw+_Chxu%ynWj~2!A8$ZI2S4Paf1;sTLs*77wQ^e_v-- zC|(~*SNtoNsr;0(XUjIS>g>G;hj|%&Bln{0SKe}gfMiw7vE~qY_3ZLb3Gus}AqWv= zFiPA+MDHJY|HrLgk)qv)r6RN9M1GvpcF~P*-?k3In}^3=LrEiPcwfKnDm2wWr!l?w zR`-cx>DfwVXA`?(I9$(wDV;%PsCpOIxKwa9&Gl3?)Z=(LiC`<-$ARJ`!ly8llS+BP zb%A6_2YR8y<3IDp-151ZL0{(Y3&jF1$C3r+ZzhJ%0#;a9)SN^v1?RnigO-3d&Mw2jm~D?h~THCk7hH6BOEhR3q?otMy^R8~zCX0>0$ zCR_{J(xIjuRT_e^=$OmY{vnHJB6*cCb}OyAn)W<{e?W17Mutj=-3~jz7+uoVm?@Rw zayvAt!bEQEU-qb`c(Xaql`l}BrEa4gInAv?Js6%8U|Q8GYGb#0nQYv}n1$!tnrcJZ zy*M%`~{jmOKvPu^=ySy~4#EsPsd#qPYG zq$*w4Cf>|8@W$#C`As;Y%JxCjtZ8^$9-2xE_Qm=vI7R)I)Sl=kHAjwW7r0nMtv*<7 zseH0^%8fKbWQ{JxkaKc30lpV_QKHn5k9zYt=>%J~iH_kG|GH~v) z{r;nDCC_k;4nto)#u%6Wr+xQviIOkA-+o<>Jet>ENO6MCEQ*M=Z{2IW_(8gcBobHAAhw}AX;HFsu!N}Fu&n&m; zL~u-m9hO^37$=)9a9*af)JYQHoRydDh)!v@MtI&{fTOuHHiY$K0O_y&aMi@T?S5;<9|;f0;T zOG$h;jI7p~5Lnahr?VVvIS+|F5r7);L$W@=rq%f!vAqa93q-6*TSFqRBS6ZI&)ITA z`tTfygbc3f|84yhL|HAjo|!wi6;1!w_Z=oVzu1u}U9YEl^xvv8K7}5GAzQw7b#u>0 zC=^=bLqOPPo@j$LNnO4<6<(4baj!-hTYIX%M5@aV;=_FTBlgZozZM>rTlBFCmQKDZ zpH@wV6M}jCTQ)#XR>3vR88Bl%HJNw55uySIaBhC>XoTU|@sBdo-`pHj{4SA41VDS= zr)aKUu=1%egJbPSRz-sG&W5XHdz+?8jO@CDODpMgITUy!9Mu|Koe9B+w?bk`FRjO` z4VW0pa5@{;XOh*5N$5lXg3oALM^6uDP5ek8psBzLwZh$}F}vzFeNT_v&#^Gkkye zSI*$&*vs=;*p|$H6 zXVjK%VqF*`x+l{$Wz!iqJkutD2CbVQPHBEtue_PYAkzhU>(TG}NXyFQE4ELuwFyh; zsj_ib{kqdr9pT}RjINml*l69*=);V0{x;GbZP=>tUGMPIr=Q_j4M{onMV@6{u8|7C zP+~RvfaEMvsSh{@*mjV(1Y&ZI?%~3T;i8~V*I^nL>%U~tw6vfn=R4#4#V(WAIW&|9=1u8b^>>f%8**~#G-NPes!1_X=6l7S!+uBYrTDj;V=RUt*5#ii77;VVjAP0#y$(XVNH{msCFqB%0a)C9spB8Tir0JMr7 z!Wy*q2aPHr#)P+)#T)jyGyBE}Zbl=t1oHU0O&y98LU5%Gq&^f^$?a+TLFpt%4^tIm z(nhcQM0y`Y{JQuZ-e1A~`jkV`2Jvb2k=AvrImF0O8uxUr$XxM84sWMbhF@uIzCDR z{*M+nnr(6&rJcJjkyM`@s&i<%c*>;?0u;525WGIgd1C`29EEDs_KJPCV4$-LH`? zTY%v?J>`CgLs|55#4QcYs#ej2`7GPy<1D4N&jXBy%G;${zY&0r6LPITWw#7J7ytGED6dI{` z_Ew%0Af(ZO=&F0|3tB5jm2yeD>*_xe#+U5Uf08PppmJ^|)kvXg@v(`ykKzMu^(qw( z`(Nht|9tI7$~&JFU@Q^9mzW2unYE>E3KW1x?qn-hya+9dCS$NMey!kt#0y-$*@wdA zQ}r@S-*H%Y_iGh7|6i3bw**m%^>49^GArq>#gD^3KQJ%wtqyq(4oaEJHZ z$DIm5{-qQH#}{CFlg?*J{AQPtZMo?uT!3M@AsViHnVP7Hjg9Q!0uz|Muzsqb3e3vn z1YVw1Qx1?J`;yUw#2J$yDiG^R|9P7&f8n}sVujw|v=JKG6ZZ8gH`qH4$}>9tF#<&N znPwW*QM@L$OGoU)(og|e?t2cM-C^2a^+3Cd8?PYcRVIY5JDPrX(|vI7J~ojrb?@(+ zf~pAYr&EDBbEP)d1s`iQC9m@w>W=E$Rc+wg)WIKDLvTksxMlrkO3NYa=~SmRlox?W zE7Hi0NS;H427ePb+Z{}s!&YR`yM=DeQ|CpB$DJ$USG5#xot9`1U$O~JI^hyUDWRsGJJWfpCf=`8@-FT#fSX6;3InoDDR#pn26-yX%ODKI_8cOMl7LzYi=$kQgtWPYo=8 z{UcWh2!q7DyFp5EwQ8iLV-*NP=}8bDy!m05)3_(HbZ_UN78dq;0AHx=B+(+)S5rqH zcZ4%poAO=H&3(Sk_?yvhqe8p^x@%9e8>ac_kS%GH4DUB-RCv*g`rC40u<%Ov@6S6r z!h%ugG;2A4X>>g5`wjT5AQqic!jZqy`ks^isqDYB??0vY@n=AiH-&%xuAu{^Qow$! zUj6bOXzWQ3pWfr!RlS(=&_($lM?KWFe9(IT=UqI=R1a3vOjbyfHbC;q4;QGN^H>It z&Ls}zBfLFzI+)Gz_M0AOJcYt`kGSH$6+xdG7@G@(6tkl=Znlb`C|iu03oB4aam!8^ zd)jp><5k@&@hrva-H>_@R?qp;l`6-pzkO#iN?-OVLl)Ij_y1}w{xBR#6C*kwqR~4IwY6`$UjgD#B9Xv{yox?iX0j1 zS$j;BU@c@QIFMXf=G;79GgMPU+-KsHHFRnzbNAW(Gx$e zRA8aULoBwJ6eBx4dXE1;;-%O67SR#=b}I)ST!uq@w21kh_@~D2#NUKKr`JHX<9H5m zwYClPIZ{ka+=%}J=#{R*%N@0>5fY#>1{E-pnT%@6)wkX;_|I>V)W%&d}-_d}bM42JL=Qjv~s-SpFsLi|i>vRz1mS zn3nC_CVPYy_U451H~C&!t^Gkmw@tOI$vpTWt49=!6VcW~tuckpjc1#jR@2PAE9JE-r}gFC3s`*Q)bdxV^vVZRO| zn~{T$LkdL?rqGLI+->!rv^%7gRTkvtcT{KP;FMw5XvyF;EThCt+x z=Y;jZ&{h1)Gh!yRM~e;aiAxmeU9-yUr4$$u*u)MGE`key;=4X(1OHgQ!GJlmnY>3& z&s{DlQk==ZCI%B)O`#iucWECzm*gQqD>W8U6J?!4(Ze$=WmaV4s5+x|M}?IyHE^2u znF0Kb0Sr69>Ye_F3;f}l==vhAG&-4o_Y}&72nmo&=}2 zyxW6=LYML-Ow9QK@2(67^0h0fOc@R-xJi!CfPaKXo?T!Tk!o06Lkv|hzJ-ER6Cn$o>zWbtcHVzWQh>5T<_e3tK5hz^ zIIe?=+mW2xRrG^K2~N69p!s*5w#9chd>eR?`r+rBiZ<48^*6T6CjD-qom!!JT5VBo z*~1fn3$)!G0n!xe{i(8Y#lR(3ng@ybdKRE0b#MFZZlDi4$JGB7JHU}Z3h;{FjeMyq zUpX(AcpE;lV+e3Vhr^YZ(FZwktJ} znox~z;B1H%CtJb5nIqy0UD;+=IR6vfQVngC5wbl{9r6;|8`X5LzSg_@AFeNa zg`*UQE*pD`ZuMCT{7FPTTL^3){Hfl2qII(=6Y{Po~<6g=i&b>BQJiD?Q|a4ef24}$EnGy9D?~%{lvG; z?!O^AbGv}uSW4GW_+JZO;~p{-Erk_+>+>(}MS* zWr7x6gJthymJRnb2SDH9zOuJ5v1HoV{mGD)yXigO?_%qS(GMZ|&h0zr56JeDT^_|O ze9n`b0bQU_axHuQN6r<|CP`6m=Mq-#?fz) zedk4Vk#Ex$`#O$<_P$mFh`AH3fa~?VAp3kjC!tV&Jy!ED|Gl5&8xgax0%1G8n>|tX z>5$Ty#OJr2pY2%5PzfH?l~CmeWOYXk^d^H9eZ;!~4rQ3WHp-k3&8o!%elt2Op)vou zskbHjLHS9nf;7cY*^E8E-G(Y)3UW$_9AO&nsGBMv zr>pDFx;j@u9`J58O~y!g2B=`bu4e#DGirH(%!b%oroO7MpCbm+H7`)*6WC$YX*tq*jjGEAl}-r4pZJ@0l?m;X94 znAamY8SX}4t#+xLi3%Q78`^)JMLy2}bi0CG(dH_B+83(Gm-kP8YuKE! zY<8_>E4>Czan~}{#@sF&6gTe%!*kMsxg+>Vh<)!HGdrX}RAaBrm#ShO{@mJrB90j=+SF(VG0*+%^`me+wq{gzPnT` z&cE1@r9!`gx`?3uIj?bZ9Enylkeeqob~(j@!zPK4>g%p8$rX1OWYNG1)wLCe#5sD) z9%qnHO#-@Mv^py^^DEqs@uAaP=#A)IA3<%%O)ZS9mtr9F_IkKKsQ~P`IAt!oiZ0N? z{R1A)cY9~wJ<_d}%{eo{Zg?2dD7-plH#4!4f^Kx`CqkeC)c?9C5J{*Q>Hkue7iv#gl6L$n)zS+nV<8q^Th;&DIqx)SF j!_9Za>vjHwdrSfw!WjlU-lKZ(*JS%?2$9Q9&M literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/4b79dddf1ff54b9384754144d8246d9b.png b/pytorch/官方教程/img/4b79dddf1ff54b9384754144d8246d9b.png new file mode 100644 index 0000000000000000000000000000000000000000..c7ee20ee8515c6998f06c799707ef48eb01ed6b8 GIT binary patch literal 35130 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 XrYRgLJt@DV00000NkvXXu0mjf?@y?# literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/4d4a02b1af752dcb28b536a50d0f9ee4.png b/pytorch/官方教程/img/4d4a02b1af752dcb28b536a50d0f9ee4.png new file mode 100644 index 0000000000000000000000000000000000000000..aa1ddb9edc2caec2bf8208aa13551762320ea504 GIT binary patch literal 136 zcmeAS@N?(olHy`uVBq!ia0y~yU}|7sV0^&H3>4v)_gfC6*aCb)T>t<7&&bGVC9`85 zP{h{L#WAGf*4u-Oyg=Te1>gO1`OFspnS{ZE^9<7;Ffe+bk@f;9_H^}gS?83{1ORC( B8%qEH literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/5015200eb4481feb8a71a658b384ec39.png b/pytorch/官方教程/img/5015200eb4481feb8a71a658b384ec39.png new file mode 100644 index 0000000000000000000000000000000000000000..aa1ddb9edc2caec2bf8208aa13551762320ea504 GIT binary patch literal 136 zcmeAS@N?(olHy`uVBq!ia0y~yU}|7sV0^&H3>4v)_gfC6*aCb)T>t<7&&bGVC9`85 zP{h{L#WAGf*4u-Oyg=Te1>gO1`OFspnS{ZE^9<7;Ffe+bk@f;9_H^}gS?83{1ORC( B8%qEH literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/525847c9d4b48933cb231204a2d13e0e.png b/pytorch/官方教程/img/525847c9d4b48933cb231204a2d13e0e.png new file mode 100644 index 0000000000000000000000000000000000000000..bf1f10fc30c88a7c6296285df16eccc80fe044f0 GIT binary patch literal 5867 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 CcA?e) literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/592fae78143370fffc1d0c7957706384.png b/pytorch/官方教程/img/592fae78143370fffc1d0c7957706384.png new file mode 100644 index 0000000000000000000000000000000000000000..7533691c8a96346ecffc9333b0e21a8c82bcfe49 GIT binary patch literal 2307 zcmZ8jdpOgL7vEUy$}ASSZIWxblyYa-L}6(1d*6sjN|8$#DKWzr#YB-yLQ#uclH4lS zN(!yql9^Q)=2oP_etx~Z|NNfkbIy65^WS+s=W{+M+1cp;3cei<0)bHWc0^YY2n=jS z1VnVRlemnzuvzq+9VjHBP`F&Ga*)Y${?u0A*t`u3&(6=g>a!IJg~DJkI2?{ZAdpBT z3Wbu8kdTy=G}<2T2?9aW?1@&C$Pa=7$Dk53^b400A-&*`3RX-!%e>^(k~!I6S;ikm zlK?7(mmM3sR(3ZdkDDr1_SFQM+$@~jvj0b(-wmYP9^WeDx&=GTi$8!me)(+f^Md`! z85&=QPu^KfZ9J%!)Hggoeicaa&zqja@mEXw99}-UtN*^&rM~5^O3&@nCV}P1H|5*h zLrU4@gOgIFS-FDDlr*1=1Azq=qF7ss^r5}MNYi^*j=1HPnP(k$3=d)Aif>9VgT z0yw%#DNByoX-o8D!0U!{^)v$d|%@LqN}mtERT zkM$fN=H%eBdv6yyf`1)W@~5ILi1`92^3z$YT5u{NLh@p1V4bj0~p&%FpqUl+v&jG!j{r(j&1_AmT0Z9Em zD`Z*8tlH4dgsG-`4(@oa?}MQo04m3+3e$#)0iMQl=6-@r^5x+}m9fEzjhOQWzKhZk zUzAKFpi`h*GvJjS#K$5cs3OhOQs#?R>D8TZV8VnrNHZ!7M}J|3S=(?v#u&JNXq$`G z#F!eMu?NK^<~R5lh_|5LzO@;ma?>EsmEYw+ctPH@*J$kImRa@t@MuPGLf}Q}xw6CQ zoKN4H+;$Jxc%N)rZo#HLNkQ4_Fo~dJ&gs?a?G!6}PqTR(GF%wp7nv&7R zg7OY|<vJfdfTXLwiJ2I(5= zzi&pWE*a0yCv1!r)L7h0Pz`kZ1*0!VNgF(x1= z9XrC-Y@t?d$ZHZJ*B@uktkexfuj?uSpkqDxP)4_gZoUp@-=c)bLxh4|A(lu3k00`t zeHDgFq*6N4(O}LAiYt2Vr+(3ELffWI`M&Y8mM%O$(4#H z)b_vLaPmc4n!ZXXdThgO?>njzOx=~3qa)-T<1|sUEy}(J=+qvA=#SjLqATCMLY_iB zOy6R?o73e=60QE2E$EnkXlPpz(m|}&KV7jFU6RHADm(DA>Pm2w7SZu@>q)AyGNfSb zS4maA99?6p1+?3LtYkIH&-%yrXKkU+?U=8g38k(-w02JM9MQ|Tb?uTDyxSOm%I!rU z8tU_d#u1CdJ$;@Si_5x99A{IC2rM#CUwrCVcoqESVcA}Dk zzUFoHvL)u{_{QA$-v(-BnMW}Zz;wT2|D#h54B2eeXv)Wo$jH}vV7=|C{Lc~>`n74Q zEYm$eh&^ktYv83yoG$KiNAu326hk(O zMTU?^&W>?|!-Q*JMaWENRW7hWH%;T(FML~FVN7aTt%k;0>J+T~6uoY=3fc()C!O?I zZQs(dw|>W+Hrw<ltokgd) zF0Ls+54M`#i;R(g+~F2b%q$Uf=LILNn}ye$7<5`cgpP}GctZHN2O^jkIU#&g{AYSR zI)i|W%o^qUa+5TknH9jmQ0LjV^l%|JX{zZfUkmyS`5J8=W^}?5B#kxku+?bMNt~)k zh5V=X6xH2mfYb#HmqsA zs)!(tH;QAagCpn6BW7^LzHxNG4{aWCzNH%j5CYKtPu0>Rt5V!72<3VAqbZBgTA0J6&f`#lui@AucVG^?T} zQX}`9T$RpdV){I_d8==fo!iiwnnpdVM;Y;Tkq9gQpz~`e@n&Mtaa8-TrK8Pu*-z@~ z*X%*#1tsgJgIL1z*L(U(!g&J^zQL}$!y)fA%2C!l&{5~ SuHXD>K=vdj;sa}M`hNj6haXM= literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/5ad82e2b23a82287af2caa2fe4b316b3.png b/pytorch/官方教程/img/5ad82e2b23a82287af2caa2fe4b316b3.png new file mode 100644 index 0000000000000000000000000000000000000000..6f4c03dc3509e8c6b64075754dc276e303fb9ce9 GIT binary patch literal 4664 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 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/5c33a15f9b0da3f9377dc63f70bb58a7.png b/pytorch/官方教程/img/5c33a15f9b0da3f9377dc63f70bb58a7.png new file mode 100644 index 0000000000000000000000000000000000000000..906bb3c0112d5f1293ce35c0a18f07e45dc8a400 GIT binary patch literal 2636 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 GvHt*Lp$W18 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/611c2725bdfb89e258da9a99fca53433.png b/pytorch/官方教程/img/611c2725bdfb89e258da9a99fca53433.png new file mode 100644 index 0000000000000000000000000000000000000000..7662dbd4d0a9e770587305af02dd0fc235a161d5 GIT binary patch literal 38085 zcmb5V^;cWZ_dN_0cc*xP;u_p36nFRHTAUy+ytqS=BE<@{(Be*ly9F&24G<(ypoF3+ z1o`s*Jb%IS(_QP{HS5lqnIn7eGs*h8YDD;S_-JToL>lVKhG=LnI?>S3lQCaBzp4DT zHuC%s($_XtnVE)k)fMH(2Ob<8Sm|m#Jv}i{P*ti6;Ns%q;o;%q;}Z}N5E2p+5fKp+ z6O)jTShH{nprPgJYbYxk|F?eHtMztcVp)vO;5u->Am(e+_X__m6rwogMUKOu+pElTvNcO1!WB?wN_G} zL=95>!q>@$ejgKgs^%)Uu@H_*JC&N;p=N2pus{ao)(`Sh0}7Xz{lz6EWyLf8$n)1( z2t^-2J9&8QPWk!EQd2=RYFkBPBX zlB(QV#aN$qWu*(@_6!(rI0Pm%m$04LcIMO1onAh&+#Z(&DT#iwbvbmsmqeeq3i>c- ztJbczBx2$Nt7%_2z?yzA?#t~GM3;yfe)5h93zM0@hU+$K$Knk=!^jy z_TBd^Wzv-9#h1>fc-QIm*2^`iUislp3MS*dzoL(W%LQ9H{dEezTdU_>5!Fv&+<{L5 z)8EP(wUrcKeh znvU{0CTViiS3x_(t=11zFnX}=EVZtLZfG8Pmuu^*o7@>7EHCWKFcol;4|yX=0t;n( zqR9j?PSrazs- zWTNN(VBUx(;T&TN{g(m{f=(G!nLp+9rg%Qf2}pP<=k=azFVn9ZeLMBA8k#^>9e zBd*`qbgE9jSE95!WDoQ>DAL=K!=p_*leNyO4;9J#lE8xB5CnrI%QfJ?3TH=SdQq|= z&c4ZDp-Rfb89Sp%`_d8-W?I}w)|8Brw?WN-i(MfLRMnNeB;@0fR1ZXLy%+sew#){p zw1{FEt7A9@rva=#jQq9s84UpWZ7G5lRLMacdGf9C@xG^eFQJo&Hq7Wf@BKgvcqJtQl-4*Tl za7GOIe5j8ynaSe=(ZKb*bnAoCL0?*z;EUj$>E=l%B?4yYm1@#=-~*f58aOpX|@y4e1qprP4Ml+Wb3Vo-4=*xD#TCP%{%Vz$zRfEmiTxUs@X$hV~ zc#WSo4KlzUirxP%L*T_-nWQvE#VgNApNyi(&`*1hPqIMZ92BSSg4(wokexbUz028} z)}jzy1QcGX7TeL!hyxxZ*pU(!e*DNunNTvP>#{9bLS${6TNhD2haMyE{Z^bk?h5>K za?pSGC-j~1cN@*k{AdCOd7F=lRZrZ_@y;$xtyvstf~c~Qy#o4>1JybEhGk3DL(bp3 z#lz9#rC=_}$|+dQP#JY%zwnRl zM%-9H$S1_$H@)HUxOqWmgw}VIe``;{pAzgnf{WIs=}IY<$Bp7$=dXi-fBy?8g8?ty z2tX;31A~N*H%`P3vRP?X} z>^0!L7JbQI7LI}JJm|hh!(ORRpQdsn0YKX~&jzN_sZ!hr(TP`c>5~cU5nu#|;xQ%0 zUD=H>5k^Twcn8SDrI?ES;h*l+9Zxhs>4>58(w5zSCK2sF3@fj!P(Yj4O8IT46S)Y`9?KXK@A}PV7D}U!jQ^ou zUzBR+BhP-;C6wb=`B`HX7QuX2O<-j6@g#!MXYDY-+Nr`7cZKbDB5z30&_e;UFa#qa z6l57E?2XuUN-&-XKEJRoSnX$Ilxj`$Z^;PH7fiY^$VEmBNMF|I*Dhau6Vl; zuG=dGGBQ9%QK@K}=Q%}Lg7lhxM#b?T2>nO>V!H@ebGf8|AYYq$h%|5#-Z5DxMiP#&I<93U+wCUd37p^D=@SJGV^LVWfWIg5XkBhqjl}m6+^#1ia;GlFh zC`Iw_&zpB0Fb>E`0RaK#%4w`w=iMiFBb2PP9}6RiT}Rd#XvuMmCsHfgqdaCS8PE?H z;(g!x%U&l*v{HdsqQgMTswp|Wj6%q@rA>B_eFTmVGsPpe9lwg}i1i&?aC5N67DNla5cjcvCN7{xW5kdw=2Wa2f+7J51H%_j#j>OhIPTBznHU zZ9YKB^UfK+pP-E%dhZzJqyA{*A=VKq}*hg)_C zI?&~esGEnEl=j5$iuj^9fAQTPzBq^pvrm#yN8AO3zntoO7Q6_wrDyN!2sN3l@(4!g zdZuk<0itH#|8+_jm2WCT=Dr~s)T}D`A8+v9m3vJ;)Vs$7p7m_<% z7(x7%6*#^IviNcz=!VVG_S|Q;q|Tn~&-s0Ok%21elK`r0n*w-HeFq;3?A$DJAfMSK zI1RiER9=bjnGImr>Kj*9^Js@Rxgu6kP=i>Oo`Zl^HVUsbs+5q&fV>=BOTjx82uot1S{D=$5kU+{FyL%Gv}N1?9& z%d@JyTW|@-TDL_#dDgiSw((Jd^0ecCSeAOJzigp{v8+=dka4UGRc zh-LpVC0}6kHxD4VV8>{1+CT#7oF-`zvNAL1v?Bp=$P_JvYhTp0yr6k@C5GRK(-iPr zIl?>Ko5>SP+;yo!4Qtju)^Lx3s^&9V$vlLeXK8@u8Xmrwww;l;u*!Cjki0SPzau=r z_)=9~B8!QB<)Sj_Kk_@52wdQ_yhP$<`hVz(gnx`PGX1ve-v#bt@%7P8WhO>iM^rCd zTz>CU~JGKa(Kw+)C zhxkB!?!L9#sC7Rhj0wEK=|2tUcm=y6zQG2L-uVnzi(wikB7QV^l%W`o`wGC|;1+{3 zk29g++t}$q{wlk00K5h(I9@jdvH6KrVi#^j#RIZPP6%~~c$+cJ9=(ANc4%-czM2W$ z2m80vQliqE!Vk1)DFfr_wnw!w@?Vk|2U>V-_as`F*18o|2r=io3YzcqOhR4tk>BKl zW!^8OJM75K--LMgEw}4<_YjM-b=+q}3ea#X{d${8Zv@0?5REy%<; zj~2#t_(2NF>DioIOC;w5@TVHmB{>&~PQ<}DpZ?y_>urT$<`2Jwx8QXapaPEjK7tqc zy&Kk!`>d%p%^doUGB3xMT02a>uS)XZN12_pYmFX9cw9yLg>3L$U@UZ~Nf+Qgb? z)1oaxzZz@WIgnVxXxLTCdWj!@A|I?^=gVgHEy=&^@Xnm(<&Xv>0x1Zb;ZnnG4bUCx`yH+a8z>A7qp_X`pWinuU3edg{y@DN(Oh(^ckNlLvlIgwSj zz#GJ412rn6&19I~3~`nOt-qXFbHk8edAq5_4Wg~VVjWJ+7eP)gZECz}H+9+?Tb2cd zg@=qTrb~t;HFmZacK|v&sF2f}B%4~MpfPkSYfVcLwuQ^RxN1R%xG(jI%OFnm6`u_Z zR=By>sr*?%{97B*)yuR*Kq%kj;bSLq;%!?G7x{u{*>mYqZHSD2fYOs0MYgI^)fcXC zS{+!OugRUf4#dLcVz^P#hf4fSkLB|?dJy_D{870-s>sbapHRN2jOcU0cV45NC;SCt zJx{QvpBeYO=5hi(&d>A?@7J1yh_l1P?V{V~YQXsTkx(a%3uH2#goq2OWNVs)7nO=z zLQ;KVWP;`M4vVz6|L$p|ky$_*e!W`>auTv?5)O*tbgOC|X1C+jau<8Z?4o{9rCC}{Q+@O9!&-<4z8-9f|ulLD5hZ|0+*;k}w_iV3Szt7yUW;I3_ig@8zH4%#upr_%nV-u)aKrMQm+pu+;NODj57z4SgXVTviQi&of!^yLF1<;~ufG_j zEIy_T>WEpL6VKSbva-79Q1%V==S%9NlE;jfGy_vcDsWkEP_rJytevzwCvm)5xG1_N zhMr?dZCQ%u9}b_)5mf~%$VP+pDiP1Xr85l?dJy)aO6HG$8+c>&d(CzN5)`xo{kc;roFPO z&aAp`j1F^#K^Z1!m2f1(j&!k+*H^)|Y5Sp4$|5XcXXd)H5cT>P(Z(Ba87x5tVK!-> zI1`N85B{o@VfRHKMEfK~9goMjaDt~}>SsNYlwT+NpR9yp&fqtL5zEIi5hp8&{}M>s zuB^ZOqn!$Hs7))dE90fG`RC-zlDHFy8!P5}c<6|6koL##=}sihqMAm}9+C4MbLH!Q8>bd3gd_lwgoZM%(FLGH|@Z?@GCHLO5rt^Gpf5Iq=8{hKEnCi=J!%PkKsFSqVR!bN}Kt@ z5|)+k`exUz)g_q?x4Y{u(pgRW0Jx-H`^Lf40PTGKg$nz`6V(z15dJh=a_X1l)sRbv ztM}Az;lT7D!__$c|FpKNTAOx1iG8G_$M#Tq6hw3@t%Hr#8*TrlocyhhPu6| zllscMu{-zJ{sL)x$q7JmFKw33^^#r4hT`uvY;RBe5U*^rf(hgDlSpNYom!z=TXDRF z214=_)Y0`f)^ADq-~OfoP{0~RjgU1wy}qF)DB*LlOudj}rC2`g9y)`VZ&mrOk?{>X!RXTM=s{1Cr zV=0fjL4|lj(`?!|*6Xw#Ctsv^x_+e+?44Z>KU6Ko8<~BX?%DaHUSf`_pS}@fHAm|W z)l;*l-I!_6a?SHO1fzxYQ1h2bxj*VXoE!p>c+YUCv^(o?-iOQ2Dm6`F=xeyg-dPZe zrAtCM6(IyE!A5-n*VVBJC~-CLyG~mVPX~IhT$SvuCNud~Xfe^RibERWEIPb?Z7Xr% zS^=ib;$jnC&tG28wzDSi27vSqTzX#w-|bDi$~~Nn3wP#YmCAkU5^U7>`Y8OB8RFt~ zi)a6O9GXy!&j0YUHH+WA(lEj z0mIy6y_pJ_!CL6Q#^@#!L>oOYvfTe+uEqUIg42Oqg~rQdL1oJW5BINt{e(Q~dS4O5 zhUM29rfC&hn44<>~J78?U$Q08~)xN!hYgHoZ%*LEkHn5h;WvCfAFnP6_4GsM8SL=I{sz9u)54 zohuRK{cn?RSZ~XLxYwi#3&d@{#y<$1uE%Ph+dj%+&W-mp_G{H^Vj;NWLxY5kSLevwK z9_M)_Qo|AawMCZ#xY6|Wm6UQ(Opc#+4vNk%>c@f?tKka3R%%!3FEf{-$A}uGPmM=}QU|J;R#&MVqxuU~a@&R- zeVdZ7JQ5Y-d7NGI!bp{P&3tuJGQ(RFfxD4q2wT{}1=}zFe9l@v2%oBpupOZ@kzlfa zLVt?6!kY^0M34FVKu7VMoh9_2U)>dw{U&FrGfAF9GO{Gj(h=cwn>-l76KG55J#iQs zqhE1Ak#U&I$JcbA>q2;TPVu0meIMW`Z0>T$AKCIqkNJ_)6=3_Q`q+Ju8TpUxD}6G< z4=;X&m3gCV2Of|4q{`0nYHlRt8R z{XOYg;u&BnHNAU}?ItxX{Z}ymg^SNT*p`vGic1u#doLHeYFElwJW;6FcjbaP+m^^> ziXSKkU+!QKECT({?v9l7VRE@055Q19Xh_tENipG05oCExH&d-MV~eL&B7Q&iujQ-Y zpS6pRnSXc1|Bb<&AkY>Vo*27uo0(OJPBT@k47qjWK3!rqEoU#kK$nX3 zh`udwc?cH+KiX1OLE7ofso~N4GG|2My7q6JpBCDR|K9ri%-jRNZ*9~Ei{O%ugM#;9 zm!p*&09@#y0rK1QsBWp#FWS2wjVLI$GW_%BPj0H-LEzHj?#kCvic+9y(No=uPt> z@VI=Wir>n)G32hOwFjW^)|cCU$z!c4bY?e3ECQwA@MqM^eAev*Eb&^(DP&OU#1viF zY{Z<{Ccnk5;CDmz7T?}$^Gu3colUy@o(`uj8Wjazc#V;v*Rg$*f$Jt~J>q3+h@IK* z^XUkt=R+=_HFDbgS6KUZ3YbPWwQ4SOGb6mKWh(8POq62({g`HeTtYsA2HE2qH3FjP zEVS{=$Ju8FTG_*f-0*`ZTRQml9R78ng?5oov(wAbikrplw6JCOrgFFFb59 zuQhdwJ<#Y^q~=u2;C5HdXZ31cucJX|b5=z6ngY26`y?~l} z1O#L!+(!cKCuW|3{_S+#?|LR$lO!&R(-01^U^x)!5Q$df$*L6`9h%wjFj}nKB!-Cf zh+7LInh$)QO_m=HNLTf{igvO4$|1`gx^)%L{7jxTI0h%97bH?}l1DjloOhY_9}%i1 z-GWDAa{{&Q-CC+r=sZ*rNza1Ly47;*9!yIj?xoYH)I|3-~SgErKx6rszcU0U7) zyzoLTE{f$e0a@XcmmOwWU)!t`nf*jZNa=CiB9V-GrF@ke*;x-b^l`t!?x1aAP%$5wrv z^neZ@vJ15+4=B(nytyhzckWYP!ueeea6YG&pO4E2?+X^B(HD-$0Tu4zxLvrV zkZM=E;=ur9)jU1KLS4{ge_7xGY&8L_*v$o&rW$jJSZit@sTJrTDOfUB|Iq3?mu&nqSP?7`ic}Mm(aIp(b4X$}NwAmYEEM_`p|FOkF)oV>MVqiPMO#Lb* zd#=atZ{xwq(R}>D2m3W)Ba&vc3GJdhIOye9BG`Rv!3waqB9B4k zsH(?Iu85J|67UAUmCkgDcSyfI+gYJU-NuZLmZM$HPM3*Cb-Q0!gul^U)})^8t6{rQ z>ys3Q3*@hYblB9m2$tUC^|dL_Rhl*O8#>iD?g^Ew37Z>JF-*-9bSlHoiz?IY$u2J! zKUmDtwn+y?n}i(Y)EG>{Gq|6QpK!NXFPv-Z>2Y3q4F6V6Uw~INXf2QULW+Cber)2u z%3A%`Kzd~mKK{*CsJGe(vM z+G?ee2BQTdATMfOn=`uysv?&GSw)8`%T|A7p)=?g&xtQz{rKo8;KGS(ZB^c`4E^TmZfOM;=fW~|H9z>oLV!_WO!a=; zS|o{0%J;lbl3#f{h{jMQ)*`ZIW%CFYD?;vi9yfAuHgxzF=dB213cBzQ~831se5zE zy5(BtBadY?O1be_hdn3?Eh4F3-yR7Sd({d06P1j}>#z*dg<|Aqli>)gV`B=;4O8lC z(&WWB(xy%D$beRrE;~mS?&N26+v{6XIw>q|cI%o|Snq$NuyALWf_uKz-iodKux4>e z425hIpp=gh+TtwR)|=BlNimyw@@u)mv=XY?5?_OTc<#Lg(l>SEoe0TUd)X~%O9){J zpQ9wvRw!eYOe6#1p)lnyVuNd@T-qXiM*h>;a*W~1zl({s@YmoKU1ab3cE$sFf(8Eu z3r_Nep6cN=aGh>is<@`uYb(gc{13Bh1;;PH=D%>;xVS#ex(MF@9e+PJ620xx9~+BY z8!KJY@dZmx(%7LfY7V(Ubv|X>f$z%&i$I{jO*|*k@6bbXcEVhXS6MA#qcF-5Wl?>3>8A10E;ivmML$R6u^I137;%0UZlUHa(da(ES6}+V|H?NKCPaR$51M4H_^${Lb0)=h@4qR4J5#e`mq}S({vSE)a z5wJ%v7L-2(VFcXFN8oQp4Zm844nuj~`{(T6I(qAFnrddgwC=>L`lb~@7`=h5G*so^ zR+rAKdRnji@in0UmSedoQC0QdrgsT;GW=PRK8iHLgQ1dvk4zYdf!iX2iSf{HUHh5z95b?kqL|~nz z{sGb~c%=;r0{D$*`F(L<{bCsZlnkbWIdGN8&wVWUgl=GAbTiT_S%_Gl)lELq5n=b> z4>1B#Sa}n~e|MKWkY;x!5tvixa*Pb?!B~Fc&r}*Qaa{;`Sq7t$yU6jGIdmZvjR{z= z*!qLRxeG>b={3yyxC z{}gP}a6f(^4Eo(ivWyfGtW2@M_tn`D5E0BW_*0&%5+~u;G-e~OiiwpgNs9a3_{gLy z!mE&`G3VFJT|aj3XE_?P2eGFlqPYGqNq$@5cgqa+!i>+f92DpG`4Mp$in0;)b8Ij{ z*Zkuq0iwzwa$oMZTj7M7Jn5Emz(r zk*@Stx$$uEU|8bABT=JX6Ct+mxDLQ8@=14gI}(%%*874Gn7&9!TzhwUiE~o>xhUH3 z-?rM}_0!|oUuP>-tGAfO)b6Ar`DcSy)1#kW5xn5jZzA`64-A%7#}E5Vag8CzA_QoN zzO9wg%Z(ivxHyuJlzY8sA9dSzc_f%sGN8X-~Ja%bNL$;@Mk?}6h2M_ z7(f+tmy?MvwOnutBOCbphg2ZSYYPL`%aKk87Z>c)EihG?L8@*5Jquo{?^9R}XSAdo zPqQ7#(GSbj7UfSrIVcUN5?htA5El-zUzLOvA(_6;2bzyQXq}A?bul!hI(QnM>-x6RJO2(Z0qcoFth$t{adpuJGTO>H)UiKv zfm8C>ag1Me;NR|j5QA8Gn3B;1@)V%5!z;%J!|kF&dG?jfg#|9#cN4z_ z<0<}j+O%wt)AoMEC_tUw8wfu2aawY4#M|`76s87nW)WNCdr;&bwivSYIUm*V6shr<);mMM^@dHrH>qX#jfsR6cPN-j8 zpl{egHdR6f!@z^J2*`T~_9%Xqn{=}Tsz%Pg*~ z`-<1JG;-~|E(>}`1-#2`2g{YtI0#$bgHo}wK8hx^d|zyktiMpy#G(B93F0ffQy79L z_)R*#zI|o#Lbcbi-k+)iV5=E60vU`-)SUG4js4HAfyI~I!Z{=F#VqhGi9mtY`Ny4K zq5KQ0&0%N~k{s9x=Dal?V!g`SwyRYf<5pJbvKmDLi#aBvxRa994P{oXW8!p*4`a~^ zOZ38^naQAoQo+X;Fmy!7W!Y%8eeiFVGL(5^cdDBdGo3uiK6nF>_}nNk!a8=dC?a4P zM4?N!66MK~3jt0ZVl(hxQj;(Xz)nxt=nvW6kpqn|f<<|Xl-?Gv)U=4FOA*mpv$jYQ z8MjrVBwq@1&ZFQTQf$_`;HSC^dJ5797oQPZ;MC~3l3Y$sRXO0Cf(^_JJ2-q&9yz;y z(fYlc?NrS++gxvZyvXs+<8`JueVkRh{`E3)EEolK8*6vonHC1%!EUBi%+TR#Og_%O zb7#j1ny=c>$T9Aa8{gk<2rM=VKd2HZhEjegEf1&%(IrNG{zhW0`J_7f)SJVU- z;u~B&J0P<+UrHrBGoSb1(S!KG6dSn>@@=*sICDnqeMhyp-FgRdZ{2PPGXr_6x+>4+ zN055!p7!2D{0cbRafLF<5On-ZZ|zw?=bO@6&hctBI# zaM5<}o3Y{PUY*S-qRNuXO+5!_!l45y&g9B>juYmLl2IwV3Gdo| zT8!%2EQC##?AkLI9W($%Z_~?b`7_TC%oK+BjFxFx6*E0d?1LBb;Fhpk$2v#@bQ+n?H(cp$F;_rx6nYFWIV zeLPDIS(nRt2FjGwYdSEP2;p@;D~8CMIRI@`#YVus ztHAOII!Y3{39MJ&%qMFL?x@}J<~5_%g(De;DE%@{ExDbv8`%nr{7US~m}Fjvm9cU2 zD>@$x<>?%WqJ4Y)n}aP~GhPL6_?uFKS?H~0?=GPy7Gi9BO^eEli*i%&?m+&0AH6IL zauSKcgB?h~X4rzU_*?-zNSA<KFz@W9OUA{U5}FIQZhUE!;nvX^bJ3TUwH?yyml;`CjZEuN z+o)pp+k!m2R3`K#yC;;F$c?!uqrJ7+VV52r&T4XxG5GQF?ie__lB8sM{JN?7zIJPT zr+m^zv3YU-Kk|QJH^WEfOyOAN1~quYHcou^8bC;}5wf}fE_250lN@}h#%xPev?xP) zdG=kuB%6)!Q_z;i2%9LuG6s)-KbxbZ6q#@mmL)2hbx8NsyoNWL?KGwiP@vk&!A$`wa z;VpPR$akgUl>Y}QOAV*N>^`AmU&6WwO-k1Y6pezaK!SP%dIkFOCKw|K8`B%z7XW0@ z6zlx(iS=7m2b$T48XIp~#*&MUO6YmO4#@^*Bt-AOLZZ-Xio$M_J3@W>7P4}OEkks}R^uBaaq@Y}rD~jDW7Hu=6@BK_Wd?cFJlk9laWAY~_ zRs1j2FB7?}UwBf~FIcRnfp)FRYzy4R0-tDAwqxgOKGTnW*CR;ed+^MOu&Z6yZvMva~CzqnR?^RQi#0zuI3l+JcUGL(ZE2HS5*MD(ksgfK}ioF$!Fl zIefOHuyBZt*?Q8@j5Cvaxo?1TF=r(n(2(e2qlKP3;_zlJ-Hi3i)0c(jt^g#$4_P zi{K&P^L;aV==o)nzhutqfzyeHLP5lmX`r_VEX5wdJCgm|qT02hh&|1q>e^@S0bsF}8vh54W1bBkj14IYWx#8r+}BWMO%5 zJwpM9)epV`DRL!Mfaa1)XJHUJPnMtbHuJCCSMF^@oA^G=h8p7*cRp(_PI=9}MJD{j z9~Y{h+b#|F{@Vl)~Ck+2_x z-mF(B;f>@3dVeg184iCUjbI1T@ObIW$;xaoxPAfl&*O(8WLYlTOll;v{wi_v3rC zLwXJ)7};EcJ`8_e&tZY~2vTZ~t0KukB(k5G1^?~#+=f1JdRpx4yGaG5#}*XQ6Hn_n z@wM%o+Qu*7kHV&C*Fi3V2Om-fOGH2~HCzv-78xEYe695i-RnQk-m)hDt)Sua92(cm zJ)!ylMm$8Gy@~*qg()jc9kKUH-V3s2I2lDc!?Kz_Gwm${*p}rn+!rx3r zpbNO|TvIuE1lajFo=J0-y8b`(OoYU97UHm!C^Eei{@a4QOpd&zyHN8#oQ??MaZfDnPX7Hg_6@X@h{-~EFWjFs?<$uDn4q(^akYWeS!Y~9X|joB(;kK^(x?4-_zd545Bj+gm`*WVld&-Dcf1LAI;O#3xu?)Z!`O-eW(y&6k!`8~sG3q-wj46z< zvC3>R9gU>F^rxQxCqthwhRr3j2kDK+UsmIuxkV$m2KL(72HF48Vo_DO)S!E})L|)j4dKcCBpqwVXrZW3Sswi?dEME?L1y#pinn3Py?u zT6rWWx!}1q6CH6_^iNs9t*BYAEd2~8n7Hux7v$>16J_SZ*y;xxvz8Bv6?off19GDU z`4jQxGEeAkd~RWFqc8XY<&qRuWhSpnF2M7^5+B92b~Fy>^I|zwZME^IY?of0fU9vY zeZjir-3QO?APP{o$V;E|+hgaR?cqzc2cgra95u=f62YfVjNr@Kvl{-eRtC6V4->y5 z7vpriQ*pqwT$VJGVjs<=h#TMj@8i!4P~32NO(w%Mj^z3iDY+NfNdu!PniUBhiYM)b zi4r1ak<$sm2<`T3tPsT22_jrzfN0iCkk@ydh9vTQAqpc@sm^A3VDtXC9>dA77Z4TFkt1>I`!5#k60Gikgi{lV->Pojp3L%q%K8Eg&Fo<|BD^e zoUi+-A07ek*3BCInxBTJA@Iw0+ zmx1$-_d0EyzDA+=lpkg$Jvzq%YNi5A-Jxv90Ve3yZ?_3*HtAY4;2SG>{Y$N*qZt>_ zxkT6gva?1TQzk6tMnjtUtY|Y{ix_t$xw0%+k!Ss44g|3O znM$zs_PTnUeg_c5wNC#Auqu8pBVBTO!c8wJDyZNgnhkpa_=iL1vWR)LA(F%?;C#+#9HyPyQV%ocUbJ*-@A2$`b}?M{IcQz z6o5azPF9gsO3&IYVX>SIxdW(&mUWxa?EO^g?bi=1(e*E}lo@T(`7z3kQKw|P{(3CF zKO}9leCVj7E9~W)9Kk6-Ozn7Cc5iytuTwPyzQ!LI&QLnV@pj}9e>6H(-f=o;DkD`H!faiHZB%8fNDMg74nDt&M~onIU@tartCzU>G>SVjeL zj;7Ap;(Z!^wwHh%t_DD6%bp^CrHVkT`tCaBKE2e;M?JWC^oV!L?f~d#D(hKn!&;)2 z{AKGoxua9bFSgtZ-dCn;Ck-iwhkmB~ZoJolmB4lwFRqbSC@HCF)~VNYIhk2HLshU* z286fbEOuUlyCe16!ml2jt}jH(P>u?(ePnv>&)v$jr0@qGgof|IIm7IWvTh35^`@AJ zI2$d0$ep=v99me>;s=tsxN?IZO5d^=km{3@uiHlaQ@Vzf^Q(VqF7SluG@EYN@|?fO zc-ZKcT>|lzp(qA=+2$gQ+tMnYj-AiW7la9vOS;OhR=q+d$~(0GR&;2Sc74!1E1WFl z(o^e@B0_Rg>vB>?rH?4jsA@1|0YByRYNVwqa=)(cGu$t!X=uQ;=0qGRTZXa^{1*`q z{D;}td7lu1m>sP5TX((wDa$>#X&D)AU8=RvlC3N*MB^y#tEH2W|Q8SF^q5%VgRTAIVcCqTXdUGy{c*?eNlAWMKKrL01 za^%1;God#F(0sh2#|JvMdA&!%EGga|<;bP*7_Bt9&|50kFZJ+p=J|}|87KWqS}>iI zr^%{M%>#Zoseof5Idh?9irYYOdr=N7 z)rA&msyuq7@{Qpf4@dE5l~flC5KNt#^<1{KlLV%&*)Xmf_!)b=`~3mx^YRCz{Nib6wsN*Er&dn zG}-(O47`artIoGx7Fx4Fz- z^j^GE;@A|OHykr`1;nfp?T_v!v}{U)9=r>b5h#+s;6}6tddZ#bKbX2 zHFWnefZ#*-CAeR`6r~Ddwd5!xI6GFg8rJ8S+nhk4l4+g5#DcJ6L5UA(RF^$EhSD-^qTHr-F$KpZK{5hIa_bcT@!dRvYV@; zB-uGeez)5piCs2f({J&_JFV{(@pa*e4piq-IiH^zOU7C8tb;%$ldv$oh1ThS5E66~ z!w<1xk~7>~F611PY#44F`>#3sc{tgGFVjut<$rt|Ih=T5MO%M3S~ae+x0+=Ft>aI% zT{zSwab>+L!^mHx@XyD~TmuDW`~JqaKhCOVek<|tJ$V)@2yXO=Ze~2AzWBqoQ%CBv z2xLHNc9M;{)sf5k!OdZ~$Cv&iJ-gNdK2lF)U#q-{Y4(sEA`p#AVw&wOQl3${s&SDT zysF%9_0wo6+w(jia z<^61eADq(mjAr;<`t5yEpg&)>&}bl~M}h^1eGE`%V0-wxvedCbZg{8cy7aS))xU=r z3{1xlaB=_)S=gWr#H#V7bE!!fa3yB)$6N?Ga1u^#=CwGT-f-wt?Cikhk==D-Tn(AT z1`XHPX4j>^)2pI*(&Gt2>?Le^_Z7YbpfewcPLF%5?VW^(|nI+aEO;%RG(?Co6+lJEDTns89 zh-9vHQA^#s5O67^%`}XTO5M5I831_@1F z$c88^Uy{p&$QK6jU7n@rh(t3ii7Wsej#Hk&2y9`Qg(?NL?$7j`v=m-yx-T%k^3{V> zv^iw&5>k5G(x7!V>HI$cvp`J0NjXqsjVbvECkh;wdx>gl2tyhtMC2C@I({sdtxO!a zEI#IMvc7RY_hWO4q2=i%G4ybF<-o0HA8X9L9yQS~ZkFd11INr9p&Wycl3lLs?+T%6 zg=m>aTRH0`a06zpFzE82U_rmY^qvxjLxK|Kx2bD%gi4cii7wFFpnhAe`WyvOXP|Fejfq=h_s}v$4}6F^QN@ja1ECm-BRP znXF7q|L8J%IiX%f3h zjG?v+q%FWjv`kL}>zQi^9Ae_+C?uDRn~e7KScj1yl9tK>Tynfxrq`6W)>t~Oi?SdG zT$k2k3j>WfrK&2E1Rua$A)G=l-0~aGEqmqy)z26H)dsjn&Ee>m_qhc*PB1s%MLvJ$ zb|^n`v<%f&;LZC>1gkS(S?CrqY_?DtacA zl;!G@9WKx%Z(9Ogn|0)L30$eVC1%oj(NDece(uA}eYDuYTLx4_yg*X4tR`^)`9DH- z)i?;9QhLI|85nI!l|_Q<|)*6oboKL=3OWGX2JR?)^TuiN4Se?&)RXSI%<{pcASX!L24JF^e!6 z`ned4Bj#dmE)?$?y_6q)G~ywXELsl_5fShU~AQBT9<6YO+l#Db26NE>`_;{I0nJUW zQc=7#;xoRudFmPm32Q$(a6_nL#1bqtDuL?+vJ5UxZ<4pIrzkLym5xI4yd}mpAXbwS ze#BfuE>;)NQU-Wk-ME0Nv`Tkf`@0kNT&)wmwa-O`Dw_HIT>ok_pu!2KU%j?$QzQ6T z$ZBqRZOgA8O2@7cr93eOP!t=d$w+9}WU{^n;1ZGqGD0Ont5h2GDKfY?cAr34oqTSM zlVOID#nr&ZrAzd+t?D}7tgreHz8Z7y0r#>5bbdeAzw+SXr#$;SpXKTNR|i)cHkLeQ zGfDzpC+Slm9Dq}}e;aT>wMXERzs1V!NFkkV=44h0R05g;XpCMos9wOC63kLtsCf!l zV>|n`w||W#d&BSh-Pe}IFQP;B@gjHgztHnP|5?T_<{Pg47Bhfc+(M z4>ONKx~-D+E1axT7rI5Tx1OPTFkS+QbJ4(En|=&jZJGOl3e%5! z&1qR^J)L~WA+?Jyru9)SRI&Yqo)Dfmyz_;l z+Z&S@=-#JqpXc5WZXM*)U*6|(*+EVOhSD(~7Y^EwBaW8Ck=r;(c!nx%a7LGsoG5~= z#RxN$mkm)=!o`{-MH_K2Y`4P{0VD6LXwx4uZh>w#>AA?rjyB$q^M|4`KxZ~ zIgUb6ye&{mCesW(6u4Y~+43gu-y)qMjs3YxhT}P+5!TN{l-VGnVd-@NFYL zuM^>ZF8Khc$a7~Zc;kNVb00^EJ4h66*HC_Ca4+{HpqK=Lmkl5%)(Flq1?y)U-S&`YuJ~2* z+~+>VsO-#Udv{bgUb}IyHxU+k%h(edVYD^DYBZwd1o3g;=a#`-%2HHnY@!N!LRf?H zl^V@6f)+xqI2{%T$5KsFL{9=uLBr=r;B!mKz7#j>jXRZ%XTb3I<{TtxUq3f16bu!)75Pa=sy_g87I0lr&g1I^Dve$m31c!{IA4*4_3-t`jUt^6G zFp8llRg$KKpB0HaJ`oaYe zl@#Qj?{f!muWzTn7^sV8`Sk6~<>UwlaiJj;P$UD^G zxQnlSE`0c=d2UVSSWOLu%N!|VZh1A7E-`@<_Cx7Bx2$Yg3(POam{yKs`f40!V*LBvlC7;A2-$N2>w zcejiBW>odcd2T&2iAv`NBdzG?s$f-H)-gxSC>#T3_PI)u`%Hp7Eka%oF?-xw7Y^J| z*KsFIJNuB*OtHhH`q#DM9Y&S*DX4#-#nly zbTBGPI}szaV@9h(ja*yC>11OtgOi|*5R@{d=&R60Fw?|cWeYw#k;wr4AhNZBA}7=` zj6(L5sjTa|0?fVKz;<&3TlS3ucTx&<%s1Z8eFV5$sf#@K(xaN+mJWOEfXa*~p_+Ebj3$0LY~R70?!gb z7Q3tLwV<@bY3UPW1_4uY13H3J=F6!4TZoJTvRH{s;(*{xqxgWJfMPy~m zMpINwcGgl1Jo1NR)DmMe2$gHA6|4TGs@0Xfl3?yUS!F=+P4Ws>kmIr>20_9%*IRxJ zxFJ#Z+l^dzBU+w?Yp2oQ1YCjhBC3SCE>6#cazv=b&gaU|4W(m-D&e_hY}pIcnkcMF z!kI88iMhnM1ddh3sSVjz!>OdYH-UJ7Nx<#FkS*~kt5eT=@5Uz*Lu@lpt zY{+E1ah{7yQBBz#VoZt$S&_0HyEAP)xa4*F$IS{Ao)TenJ79k0JlBvJr3_QgiDk(M z2k6&|7#uo}2t_pF)Fd?y++1C z3$-Bvw@$SZ6ga`@`e>O_p~Q{Zu)ejJq?W;rD3tP|oi?>*f26oxER%yJ1hjb^+1ji^ zij*y@dL9VuhQ%vS%M+G2%a4bFn~)0`;9tV$g1?8DgQLKR_k*I@Cb%c=^KXKi^R)hP zV{cWcUb~1f!l6Bherq8KT%1PsV>XlkMVtz;jFH0HJu?^R8Z`YN0BB>KEkWI^Rc(

RK(;6GVl;#_Y}{(*6gd}{nZl~SP` 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 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/ae800707f2489607d51d67499071db16.png b/pytorch/官方教程/img/ae800707f2489607d51d67499071db16.png new file mode 100644 index 0000000000000000000000000000000000000000..39e12d44f0578a953034c02653a3b877bfa8d8c8 GIT binary patch literal 30944 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%0Ar1(W!!(@4yRS>m?p=~MTPb{hP@cDb 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 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/b1ba956974f3e844b0b0cea490cc1148.png b/pytorch/官方教程/img/b1ba956974f3e844b0b0cea490cc1148.png new file mode 100644 index 0000000000000000000000000000000000000000..01e2c0bd440d3132101937042d4824ee672bf902 GIT binary patch literal 4232 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 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/b3f0b96ed8ba751fee4a5fc7ca878eb1.png b/pytorch/官方教程/img/b3f0b96ed8ba751fee4a5fc7ca878eb1.png new file mode 100644 index 0000000000000000000000000000000000000000..81f76fc6e521861068b18eb353dbd60622f2cf90 GIT binary patch literal 3397 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 R{{13=rRh17*GBHt{{bR?AnyPG literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/b43b70d8a6eef9ea4f75867b5e83b483.png b/pytorch/官方教程/img/b43b70d8a6eef9ea4f75867b5e83b483.png new file mode 100644 index 0000000000000000000000000000000000000000..ba13d24c952f5df0743437f30a87d8670320010e GIT binary patch literal 29291 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 j@%n!j1q+B3t&v1oJ-t5)(P6 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/be538c850b645a41a7a77ff388954e14.png b/pytorch/官方教程/img/be538c850b645a41a7a77ff388954e14.png new file mode 100644 index 0000000000000000000000000000000000000000..c63a206df35047f5efeeb04819730797ba48371e GIT binary patch literal 18441 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 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/be60e8e1f4baa0de87cf9d37c5325525.png b/pytorch/官方教程/img/be60e8e1f4baa0de87cf9d37c5325525.png new file mode 100644 index 0000000000000000000000000000000000000000..850895dbc1e988242cbbc8bd3454060de3141e00 GIT binary patch literal 4216 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 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/beccc5ac5df1571304e11d6b12772a99.png b/pytorch/官方教程/img/beccc5ac5df1571304e11d6b12772a99.png new file mode 100644 index 0000000000000000000000000000000000000000..bd8898abafff4e5a3104d193a5d728f48bbe9b8e GIT binary patch literal 5625 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 R{{13=rRh17*GBHt{{bR?AnyPG literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/c0f8a413c1f6dd23bb137d8adff1adda.png b/pytorch/官方教程/img/c0f8a413c1f6dd23bb137d8adff1adda.png new file mode 100644 index 0000000000000000000000000000000000000000..13d8444f7ea6678fde237c95498f578dd6b0a05d GIT binary patch literal 122782 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 PF@&>&t9{imX3Bp6_;ImW literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/c9d3ddd13da5858e2cb03b53753ece3c.png b/pytorch/官方教程/img/c9d3ddd13da5858e2cb03b53753ece3c.png new file mode 100644 index 0000000000000000000000000000000000000000..32c29744ba83bd3e085974a2a2921229c8ad41d1 GIT binary patch literal 3677 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 YbhkFf*;317|4-zxv_P9z|LuAIe>ATl!~g&Q literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/cc57a36a43d450df4bfc1d1d1b1ce274.png b/pytorch/官方教程/img/cc57a36a43d450df4bfc1d1d1b1ce274.png new file mode 100644 index 0000000000000000000000000000000000000000..56432ac74751d82412b99f434ceacb94cbee1d90 GIT binary patch literal 4468 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 NXsYU|lwP+E{ST$b8Lj{T literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/d0d82c063f83a0ba4bb8df4dcec57138.png b/pytorch/官方教程/img/d0d82c063f83a0ba4bb8df4dcec57138.png new file mode 100644 index 0000000000000000000000000000000000000000..c6265aa55de7bc427362db979167e9cc95191cd6 GIT binary patch literal 2002 zcmchY`#%#31I9<>z7>v3hr}t@%5`&3N>~iJhjHXC4!JCsT;5Ko+zvv_J-38%XB@N> zqq)vy#x|`nwpmkdq1oyEBi{G<<@tP`AHL7?+w;u9&Pq)9oG<_Y5QAD`a zC%#iZ6Abq~{-Q zQ86(wAP@)wfyM*`Y5)KMIMl-2Ic}LncptrNEroeNFo=W&c_f~{FkI;Fyw8BZ_Cxz> zD2#jJbcV0gS2jD5g!ZksR0TV<&QBdkV3s~Z87Hq7#G~?m?)d+yHx)ydS1hAUu9^8c z8rmgJ#jTUV942K)&+$3dl)vY%MxrwwE{e%YGhRawIXBUm&$;KI@RJ-Y5;kGns1 z9euT!d|b0s9B>!Q4ISzxL-Tyb`jhF>WbEzCfbPFWMBv7A0il$ZgHg%D1UJc%l$Jd+ zL-m1^On~&V`Lb~VJ}t}v*&c~24QuNx`C^{A4pSSyc6l$`K^!@dWgJ5; z=~P{0Cc!gCU5{4>zSxxJk0g&v)kc?eYr*mB1fD_I?IhMDq95+t++}yX#r1dDTHH(a zDO_$`mQl;sdA(?f+>V~(VP@^3!9pG?B!W%K{_#C7ay%Q{sE%l0t z-5tEkk@9?n84ZDX+2mA3xJoG0dP$FsWBtV86^J_Us_sYU55{;*ibI4^f&it&g_Dy^0^oFcWSAFH2WSUK}MONQTLD` zD7C-6Da5D)ge+!BwyX9yB0mnHvHHd7zhq~XJLC0VXM2L*=v^*)TX;FjZm8D88Ch5$ z7%X*7pOGHRk^b7O0gSL z|2cTbrj6GMMfNQ6Y@+oVckI8nvS!GId%sX3ctQ zUi`-F*+TO0l3)llF4{E0F{+urW@*$d@KvPbzbyv=XI*z=FRCLQD%B7vj3D-5k83-`c&hk#|Pz&|~2IQ=Q zVjLLG9Yt3Z_+F3WCxbkjCNEOrJEIx^ZeA`_%g}dR;v?`c9b*5}Sv692f8mV;LkWF_fb+LzD{? zE4SVKSY^B6@CQ4eCOIWVwB}~>s21n0WFX_t%BEm2 z6(S47Kr_cl!&BQ0Vb^4m6Q1)R@IFm6#EIX+k8qt-g@hG)89*}?FunI90sQA0rilko zc8u?vEpD~SpyX^&8#(IQFE4S=b4qt1td#mA)fL&zZb-)>mgjWtvQ$GCnV#p7;gV)w4c$ySv-=$cNmOMnuMIfRTOkCSCIBl+Y*? zEmVafYL;E6J-4=xrQWoe#7tMeZvjiYT*6PobAjtlt1fXrX7Z=rF<@wkc73y+v{%n2 z)^?~I(n2o>)Dqw}>EN+~9Ltz_xP$TEj<$j26SM5`UNc&VR_1KABx$v)ZpRCn`&NN* zF?rzRjakj26K9K*QuInIg!3d>m);~Bs-bRZhX)1V#5+#Mfv>@%--DFc{k&PZz`D)- zaGMd$XqF?luc&QF>QflFPgaG~5T0mYB!F13PTi@M3pQ|Bq2M5o9vQ)Rp7TI*f%bf= z$W7q3+UtIFye=IW-Hy9 r#u2r3G;i7qxBk4-|NF1{KD2KZ!P&?g)OeTh-!|wiJB!vEzd!yLg6y9> literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/d148a5bd51a3278e9698bba522cbc34a.png b/pytorch/官方教程/img/d148a5bd51a3278e9698bba522cbc34a.png new file mode 100644 index 0000000000000000000000000000000000000000..a94ef69caf186bbe08c23c9166854b5585edee12 GIT binary patch literal 11320 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 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/d15de2be2b754f9a4f46418764232b5e.png b/pytorch/官方教程/img/d15de2be2b754f9a4f46418764232b5e.png new file mode 100644 index 0000000000000000000000000000000000000000..71ba971e67711312cf30dd842568846c7233c7b9 GIT binary patch literal 40274 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

SOauFTB9#aMW9J^r$&_Pn72!<}Kcgn#hXB(##s5 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 DE|OYF literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/d5ab1f07cb4a9d9200c2a2d3b238340d.png b/pytorch/官方教程/img/d5ab1f07cb4a9d9200c2a2d3b238340d.png new file mode 100644 index 0000000000000000000000000000000000000000..bdb9b5ac7f41d2fd560d56da91e041b43c549ef5 GIT binary patch literal 157215 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℞8J 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%0Dq5me~c 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 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/e21cb5ec883a2e5dceeff4064add3acd.png b/pytorch/官方教程/img/e21cb5ec883a2e5dceeff4064add3acd.png new file mode 100644 index 0000000000000000000000000000000000000000..c127daced41a0521eb2148367fb01d93abc83454 GIT binary patch literal 8365 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 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/ea0bddb69dfbd67215b823007544ab8f.png b/pytorch/官方教程/img/ea0bddb69dfbd67215b823007544ab8f.png new file mode 100644 index 0000000000000000000000000000000000000000..81f76fc6e521861068b18eb353dbd60622f2cf90 GIT binary patch literal 3397 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 R{{13=rRh17*GBHt{{bR?AnyPG literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/ebec7787362bc53fe2289e5740da5756.png b/pytorch/官方教程/img/ebec7787362bc53fe2289e5740da5756.png new file mode 100644 index 0000000000000000000000000000000000000000..5f3dbdfa9076492f6d070011a14a22901149f26e GIT binary patch literal 18697 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 O5x~)oh;O+RlKdZWkUH4_ literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/efb29904552d032a076d8512d4e60b95.png b/pytorch/官方教程/img/efb29904552d032a076d8512d4e60b95.png new file mode 100644 index 0000000000000000000000000000000000000000..37ababe81786bf23c6c0ddc355e77ffdf3d8bc0a GIT binary patch literal 73798 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⩔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 Z$mFt9%2LZZQJa5cyxfnwHM^Y2{wML1)vo{m literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/f4990a0920dff7e4647a23cfc1639a8a.png b/pytorch/官方教程/img/f4990a0920dff7e4647a23cfc1639a8a.png new file mode 100644 index 0000000000000000000000000000000000000000..f370a9a140a079b4f8d085e17f07887c69bc35cb GIT binary patch literal 42628 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 LBc^%AXK(xm<0v{q literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/f5504c7ed93640f2bed4d2a606c015ba.png b/pytorch/官方教程/img/f5504c7ed93640f2bed4d2a606c015ba.png new file mode 100644 index 0000000000000000000000000000000000000000..c61237b17316d9ae2c7ec4bae57f81faa9339052 GIT binary patch literal 4081 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 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/fed25c69a6015a90b6e9406e4ac6e01c.png b/pytorch/官方教程/img/fed25c69a6015a90b6e9406e4ac6e01c.png new file mode 100644 index 0000000000000000000000000000000000000000..01a02cb462ab1c2df2cb175b0e90b4513eb360ac GIT binary patch literal 19024 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 Hu0mjfmf;pk literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/ffad28c33f8a48d06521421f1aa441ed.png b/pytorch/官方教程/img/ffad28c33f8a48d06521421f1aa441ed.png new file mode 100644 index 0000000000000000000000000000000000000000..81f76fc6e521861068b18eb353dbd60622f2cf90 GIT binary patch literal 3397 zcmai%`9Bj5;KsMvW`=D>t{gLSlcS4VoBOIHNpnjgg~*&O8@XvDN77|sjy~oNk+IyA zeEa_XeZ9UvJg@ijdj5guc@k~Une)TN;Q#=D-_pXw4gdhs{z(+f^)HDI zdTaF$8n!m}rhgZj8y0>a9v*)GIkUeqIJq$1xUji@um^*|czAf=a5yh7FCQNtKR-VL zfj}aW7uP1s006!ZmL>%Iu<_;mzMz>Vbezjc1Cgo6%D<4dAGdU6du}o;VtF;X%fz^u zb@_{14{nP7rQQk=&F5f=7&H+Z|$eO=wR6{bZ^!N_+0KX@WOeIk5fx%%tf zsHU7}yhC}g$FK{Rh@3}LPYetJUh=Q#j1niSz5x{>*h8)3iXo-nX0t<4Y6f1UDO=?t zEo&7fwK=}Hn9hxm(SEpbV@@PCa}aM5FKm9hEJ*(NXkKQjXe(1qI1Vym%EZvSkJlvj zJC&s<6S+1&SX&P0EXg}o4oVTMN?vQfBnowF?fnYQy~`@LwAqa0k{MqVxa-gK9CQ#Y zzmla&9Z;L~E7zw4miXU3F{x5_l)z(MT+hDX$EsrS!aT-qrHS7kOMPzQjrH-Bc}T`< zTc5s#N%v&j$NlyauRbL+ZG1UeV74Z|K%NQoz%KeY8$<#a#Yf zrg@(NWGuu(PP6AH12i8^O8maF{!@bfGS8J}63T5M-=LF%+hA#SmR+VbgoapYy}By_ zvwV*6PObR?NnE!NeQP?{;}Pfn9A`_*wNb;*?3Wh=Y(Y9brXK4;FQl6$Uv#Nf3#h-3 zslm16Q}wPLRY6r5zd6ei^pLecX>=sf(=R1YWQnO(eTVII%fZ4gkT4g>k-4qcJbBQp ztvo!9;WBVz=3rPWrlLm99HqK|Aasv()-sM}w)Flshlg@%R)3E(dJ48X}{E)+VR z=Cilw1_~lS(dvno@E%))n@|WO_SlOycf7$njAs5b#1>f8gpb>+(V(x8SEIB0NT)o= zd~dfp2oc8xa=>*zm~66%<5~w_HtAbq8Yr52hJXcHL(|e7%Qf=afXW%tFW)+=H`ic4 zp4w}K!2X#FWI(u^EWSNj=uh}h;x}i38ng4V#>AI7KIh|L8Cd-MqHp`OmK0Zzwtt!M zH%Tu;S z6OTx8pEq7n9xWB=6^9_P&gC_>7j<0);?I{A=7=$Y;nKn|Z?i8dtV4p0?6GG{SkiKJ z7lEKSv&vX$Y^P=(V$9sKlN8IaFw{IEHZZKZL&;7c-RC;yVbNtA%t&BGtIrqyfOIEC z^&XNBrxsWs9L%Ft(4CE?Hrha*=urv|6xd2Lr*wj~xVFnhb*j|w=|I9WENEc8WbOXF zKD#eOUN}}FhK6itRRp=d5ALx1D+q$L-YR3wZM2_ESZ6Zfj9}DLe~lynQd(QhImZ57 z^ZhfXz>!vMCE-0Z%6)(pJzLRS!woc$0&c6?6Xc2m*veyuQdjEvLYx!*5aM;2U*m;g z?beB$SVfDtCaU2g52OhpaT$t$h4vQIp(JE1Xe%Y(opfDntK*$_K|qPZ{aC}#{JBM} zeM|Pw0ZdRB3t*mECEKTxwKbs<1~;!aflb|~q9_p59 zdKM@1YV*x&SHOZn^8+I6-o#%dc1QZ|(Yki6B26z2OSaSNhEkVOQB*^%(Cl`*Lc&;< zV>*6=%rtNbb5b^9urpK)xS23Cf$888hB|27J=yi?v+si^j!%Gc4Xb>1Bjn%DjGZ%G zHmR_`fR3tN74i%HnntSwoqKn;=aq%*6J~&z$kX(5+xev>b^Q#Skd482!=Afaae5~o z-yFXyJ!qJX9^8u1^dMU%n^S0A4z>KQRv-P$X}P_`6tt0`)Ro)Z9g}enuVt0kGy3Mo z+2ytHCWB8hDezQip5oGq=7Qx^2N38fE;2EWqFyEEuyTm?Gvgf9jR{P8d37?(51r{Ti zq3&T!MpE&v&U|QkuJvN~O53Gs&2%YIizt^|pv^_moW;2w0CG}e2XTRz?73rJ~%8&{of(TEd|2TQ;+j=GWcElaX zfYKu^B`Ktx+)FffQkxV*INlq&xY6<5Gh4c;FHfzvbw+RU?b@Fh!dJhdwSftPsw)jl zh=NVwNM42F_)rfyS6_%uRI3vHZd&C+yu_Z1IEBzwYRin8vD?@1P2l{sB@;;rpP*I<@yI>wIsvqH^kzLe> z{h=0;aAdFGAO@wpyJ6k`vVG>wRs9J4NNxuG(cx;>6uWy(^leOsp~IAe@R^>f1zCr* zj-ibj$y$S(3Wj=(m4#ut+q_1qg5l>OZdqN6`J{0KzA&ryt-=JmK*jHo|DWJX^P+8KxJ$LE-|@*S?bCQY)|*nwZLC2AUKioJ9Cw41wWa1 zK(WJhAFng*xX5#?!Bh#Y^kb`1CUD@4BIs0dLcWNkx^2>|JFWa83QK!G408({Rfa76 z!9WnWL+MdSH)Fw=2O&_6)$IHRSz$3(Uv=IO|C=4tJB7IEXd0~$VoSrV7A82MD3`zp z^sg_JUa&CEyk0>md)rYar9AHsprCX3Rf{ld0$FGBrWm>#fl85+^8Y=dr+iyPmd7D| zTUYNvKDhC`DZWh@7VCa9a}9IjvNlLb5S)OQG>Ar4QBJ)95(QE&tq$j(J=Sd&9*yy9 zNt*57Cy)4;YCsn{ID8Ud-SO%=5K)0&fF5pEdW5yHQ&f7P)QBQ9rQk5)fOA7qbIedk zWBq7%2gU8^pHOat1b$yN}k)t zvbiOe+jO2gxn}($#CUO5oOw^l#%0gxd`K2cJN=HV13M9Z&UrWjJ;k5R98AMMFMZ#G z0!H@hMt$JQ8#mtKz`-O<Q=+UDP* zzki}EJ>y3V&jR06POJUemO!m&hKR`0e2{ag|JHFm6vI7f1vp#MwSuPiTQak}IGa)` z9E?ES25DI?QL+d$E^N1c3VCKi@pj%PAE>RaWtbDTrUu7%=W|{ucs`BSF`HDl@merv z*$QR+_34=F*d!ON=>A1it1T>cL_yUA%b~6!xlG5A$t2tCxXmiaFY$w2h8719T{iuZK_ILg{v`*F2$|)SF3s4 zww_1{iLmW}yBekfKc4uZ7r0p0DN78MG*PU_j4u5!ZImL--Jlyk)ZPwFx0>jbD^n*h z9PVD7ySd+_sGP)sGKg9RZ}xJxPKYO~C7aJK_HZckLn9@_)ux`^C<1 R{{13=rRh17*GBHt{{bR?AnyPG literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/tex21-1.gif b/pytorch/官方教程/img/tex21-1.gif new file mode 100644 index 0000000000000000000000000000000000000000..7d658baa7af9a4aa578e700191bde4e8c5279542 GIT binary patch literal 2306 zcmV+d3H|m*Nk%w1VQ2yq0J8u9|Ns9000640s)&e)+}zxln3!f}X729py1Kd$5D<2D zc2rbUL_|a)A|lMp%rY`EA^8LW00000EC2ui0B8ae000F35XecZy*TU5yZ>M)j$~<` zD0&QO>#}YvtMGiSHds%4UJ{D{A>?2PeaNIzsc0CMxdocq|@v z5Y2?*F!@ph1%+9ut<-Y|cF7SKArcx04P7&WgolO`4+4aVCIbi=e;j#-7?S{SmPw9} zkrE043Ie31rEVSz3>1(RaR3CXP?~QAISf4^1+pOns1^jDn<&A<6M8e=ur6?LfYjg$RRuVhc_1uc zWLxWzKs(VdV8Mh98wHSf@i)hn=-MS}vesy>RtT`Kv%4*UJSCSI|p= zbph9WkAY@$J8*8Jym{c|-Fe8^va*|RXpA*<+pxl)=LTzVGnMdeQjF{?uLSk3+XlXK=}T?D-xE0AMh%fCPC2xeOMrPRN;XMWr>5hbxyx;Ap-zHx zaV~9tvVkLy=R>;^Ko7GgQ2Rs(P7p2c0JQ6XJCc7ZkLaIh480_!Q*FC_lOsO)W(_cS zLctPjO5^HGLK#kaN+Sh)fx@RteD&c!Uc>SjRJ4Tvnmg1i{pmE7G9?KJz+5&kF>mo| z8{JdNT!aUXwVf(mzZjLhR3;Qw^`U_ksE8R1n1Q$1M;LFzAjUSBssBK5BQ2M6ao z35ZaG65yZ-K_LYZW@bHntEE0Q`p`Mu1}*>i8TAEg-{H zlu7`D_=MH0HZqiT5@iOMNDv#j0r7FFTowQ&%Kk^oQg*9^o>Y=5BT2>!;E5KuCd8<_MQ4Tcu*aS*lbjB6p8$ z8xK6`&Hm`|mF2s@zw}TK98R)d(S*e`7g)_%n)7P1vD!1aS-)G6!d+d$0Or|B50NY5ZW`pjsrl+BiphjUKgthK)i61O=H?2TL?f!Rd6Y*7Ds}b;-i!k3?B>d!PA-kl!#^!>O~f3PpM{t97wxb ziHrvWqi#}ZQq4`B(BZkWCC3d2=xR?d0#q{~RY_~TS~Hqz3%ZgN26nx`Q_B;PXKwUZ zYt1Vx4ru~(1t@82v!{hHa8|B@BCdNy${gNWRz*lO2;vA#@*n}FdL6a`$THoR`T+#; z)YL<_O2-1olaz`WB^DXv#Q-eCl{tWg6o4UEJ-D)=IvD_e0x%0_>VbyQIAs)Y5aw?c z{$n9Fkf9F_7zI6L0}^Oe7Xiz4KyyJ+mjUSIw#jutbge}&>dvLO#>?(@J=ERrA~&~a z1jc*mNn5KJ4?F@HuO6@?#8F^{6|&JU+x&>%082Mr?d5@i$xE;SVwV)!&FzDkn_J#; zOTF-YE_=DcoLo#e!r8(wGXC3w+XiD4L~R&N>jK|r5g4}(Ixu%R4B!|um@@;+pa9c& zHO6#z4d-$2>$;gZ4;4rjp{S@Ws^p5Wys!k0eAMZ1pp1Vg3xpz zg@Voip+CUqO)OdlbS8wMq3~!AG};4rSw(LxjpjGl8MKI-Nu-?uvR)>76EpPdsdz|v_`n^nKvb_l@J1#M$H26p=P2h2?Zaznx08VK|T?u-?=xMDNu cR=2+Q&2MY0jo<(7H#fKta40ZrCJ_JtJ2>^z)&Kwi literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/tex22-1.gif b/pytorch/官方教程/img/tex22-1.gif new file mode 100644 index 0000000000000000000000000000000000000000..f1e35c3ca3540d6ce8244a73aa6655392912a90d GIT binary patch literal 2339 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 AbpQYW literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/tex27-1.gif b/pytorch/官方教程/img/tex27-1.gif new file mode 100644 index 0000000000000000000000000000000000000000..5da456a281e48870b71bb3b315e921b0a45986d4 GIT binary patch literal 18636 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 E7d$fVl>h($ literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/tex34-1.gif b/pytorch/官方教程/img/tex34-1.gif new file mode 100644 index 0000000000000000000000000000000000000000..70b73c449901695fb396e70c25dd164de82bcd2a GIT binary patch literal 875 zcmV-x1C;znNk%w1VZZDxlSokCY!u6P3Hm8#3DAxE+ z1|u|h&HgABmbZj#mZ;fxkmH~zn8hLrN^OLM3|bZk0TO$Ce^70LV+s`u0wWAUg)EyO z1dtU80SR-I6qbfU0s{f9t^_|7uoe%s50?|OQ?&-B01N{J0uKYY3OUDo2@3(k2L%TR zwGMT>zEuHmSq;7y3X2ztR~WJvwznZU2MM^j5(SqU(IE|qkP4sx;1>lB{{H~GaTsI( z4we8=3XoD@%E1Z*0Xii3B;n9N2?b9z9Jir?K@0u`_Fbq~0T4bA3m`ejqYnTn00NW< zys#?H08$(QAd;d$h^Pq=UrJ~|Fi(Il5RnGB(o@1upad8^$ax`RM@<%LR#0%0+=nU? z90=SAK!Fb#AQG^I*&qOcK@%EK9WrbmM2-$6G@a0lFRr^4>Q*>ZX9GmI6d3f~pf+pU zx1K;ntsr-T!H*sgkj(n6+!O&~+1VBOtAT)392e`m0vKj!0i*>i!0dsdg$8I1Zw}nq z18iJRDd^%Of%FDlcHkn{>7gIM=QDLeg6$FmX?cb9wOcxeyYz$AF#;H{qWOyq21xY_ zv3!8?55Y6m(KX=9s1O72PGC@8_LQJuEdB*WYkCP)!D0~o#T|eEhyw{)2u${YW(h#@ zfLJ2rM}a2%Vc`H(vmh`4C7}3+!Db6&XMq8TF~Gn9fJ{&e7!MTi00T()kx2j!l=w=D zE`>x*0zxv7fCD^|Qsa#|^4AtA6A{n@2tDmk3>GT1_+pF`$f>)1HXj5L5Yf)$+@ zh6(~P36rJ>LLh(`O;~*}X9#H4kmmVyf8+VJ9623G14KD8*&j;IwFKtP=ze2ORu4}`iXpQzTF=Baeqs%r{@ z=&3ln06PUt BUe5pk literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/tex34-2.gif b/pytorch/官方教程/img/tex34-2.gif new file mode 100644 index 0000000000000000000000000000000000000000..a02bcdef9c45e1821d8a45fb11189b1651cdfab5 GIT binary patch literal 925 zcmV;O17iF~Nk%w1Vcq}}0J8u9|Ns90008dp?udwpn3$MmW@bc0MBLom5D*Y{c6PeD zx~i(G%*@OpA|g~&R5CI$A^8LW00000EC2ui0Nwx-000F35XecZwPM`Or|w`Vj$~P7 zV8fUf+Nsh<$=EOuLm^DXgEWoDq2ge51O=mVNy^-EJ4x>s98QXzMSyt)X(z~2(n2sq z0SClxAvh=$)|rB9SrF)Wdik7Qx8HFwa~%a^Oap@)g%oxbjT8w67LgtT1ZNWuc@>(Q zESO7_6`}wGmY|&-2!Tqe9IKobt_o^(TM|VHppTva2@Aa?1c^$tpa5UEzL>ll43b>U z7tfQxkk$YQcNPo*D-1~m!~h1Yc?wv;BEwwT)7}8!0OAzoAPM6}_8s^Z=oSBb-Lka< z5da(&5L_U@kbt=gHWn~orErr1d_VLl>= z5_DoC;pYaSDU3=$Dx$y;4P+@4b#!#wg{QXy(2&~|W>a4eR_v5e=89DcweYYp1^`Zn zj#oi8Mma$*(Y_U8P6`ZQa0QSDfE}Koc@$^QiB$>^5C9tm1pyvXVDL9<00gdk+C?y~ zf#(uC5*P|f^}&OxnOQOb$vU?L*s>+iwqP5#30?C(*KTmzxm-}bv)Pq9e1m|w)JJkS z5L^1wn|L00_bP0>I|~iUV?du-eFIj=)h0<6aW{c+3NXz(YZmT|9>+X-FOki32zY zk);R&xc0^ZyfARz1PT-YCpedYI367~kPspWV{(EV*kE>H~@yMD3s-2e5{KYNw)(uo?*r zC|W^yvtCeZ3AYLxDg~_~t11u=O^iuku#A+TL$1LLP$&S*I!hh28x#u@w--zc)nEf4 zpy~#Qt~vq%l2N;fwjP*ULb@b)djY-cw0n@gd0bn9zwQQ10>F3>j0SZSL;wIgIwox_ literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/tex34-3.gif b/pytorch/官方教程/img/tex34-3.gif new file mode 100644 index 0000000000000000000000000000000000000000..c138c933d1f70116232ab371f8586727e92c1a79 GIT binary patch literal 1076 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 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/tex35-1.gif b/pytorch/官方教程/img/tex35-1.gif new file mode 100644 index 0000000000000000000000000000000000000000..69fb2c0d365bdddbcd2029a44d365f97020aee3f GIT binary patch literal 690 zcmV;j0!{r#Nk%w1VU++A0J8u9|Ns9000640st^zmR8&-Uc6K5nB4%c0+}zxVh=}g) z?wFXEy1KeDGBQL&M9j?0A^8LW00000EC2ui0F?j}000F35XecZy*TU5yVpwcaUvxQ zL{S)qdbHFU9Io?>coil~awwEgZU`U{F^U6)fS4GR5&FF_Rx0~QK$rxXLJlbLP>w-yeTn+#SI4Nw>ae-)T>rv;!F z0*_a}6|)u#+6%%L2?+uZ-Pm`|76Vgyl^q8J?(guv76!`}2hr9S25WEyx)l!K5KuG$ zp9BW$FksTOgxswF=_nW|mX87gf)fffxX~(Gy%he}S`~1Z&0xWQg=(2Qn6M&+2N=N^ z2#`fXt_cH70Wi?20YwYS0L46Ya~?7eoh-2#p=!i{017CR%EK49G1zwFaToCxzOp2<}3HpMe0ImRo5UvIMknnB7VF0ih$Zq77 zx3j1w$X^2!KBcXtIm~ YqtSuf1j{w?V~{&8aG*tq2onJSJJgT}NB{r; literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/tex35-2.gif b/pytorch/官方教程/img/tex35-2.gif new file mode 100644 index 0000000000000000000000000000000000000000..97787edcd229761a4a534908ad5adcc4f4c5f2a4 GIT binary patch literal 1611 zcmV-R2DJG{Nk%w1VVMCI0J8u9|Ns90004-Hh^nfp%*@Q(+}uP&M3|VER8&+lGBS2{ zb`TH{y1KgV?(Sx0W+EaYA^8LW00000EC2ui0GR<6000F35XecvBQ@*IyZ>M)j-=KI z-cXb{*LkGYfJAaFF0B7}!%YdA8}Nft0zz!Z;%Lg5fo zzyZhDVfaDcBqh^H>A@-64YjlfSV0a~cY}ln22T9qhf(0C`yhj6{qW7z02c zz`$q$+`OA`K-`LW+pZPaH-L;oB=$JqE3xs6K4AVA7mBQ~z}kd@3L6r)ewVhD zse@`kh6c|@G7LGQqz07BVhmd8K>^PXMl-ymAV9zX0-7QkY5G(b1EU2LG_0fbK!Ybt zydHQ#puvCv2vSmoI)T9e2htAE*`Q$JyZ}-M*~~C@Y=OKR)*jreOpAsDv#_+IP$1`< zs{*wi-HCKT5H0}f>cKk!uo1#8`u+_e*v|&S1}Y&?w_yf?*RWv=&5#-svH=CmDA-aU z!IM!3q!IARCBdr!iviT$hm1feb~VCrc#vF%-BSh!*V~aUdo!_yZ9D0!?7t1O}CI zfPVm7IDr6LEVz$QEffS+2LYHz!2|Jm5RWbyfzTT;31HwEUyH#&5+mYKzyNw1G?vmn zgw05TgYrb!!F+nS!2l$cl(+$kyS(U4jHZF$p^Y5KLmU7LOoqdjU7ALQQg+2Nff`zT zV!$V0Uc})CIDI6+jx2cq8VLjtm|Fm(h|p#Q58#;01Pa`V3V#w*14^AMJTWE*>aCUl zdlejX00Aq0~l7SnTtHKN&#p&{z@pU7S&~@j-fg5YNeNaHM8Z3vj|zjHpKRLtOvO& zdz!8r{(^0!>tRWOvI3~q z!feD6P{|7kA~4MZH6)bTD`H2-3;=Eyj0q%5O1RAy449Y*0ugPUw7$tT3n8bU2H?;D z2@KQ}Mg$&-tv8I6eYU&)vO>}E-fj6^0N^AYJ-7x1w8MY{XA$6lSC66o)ap+>u7Oqt z6Lzo!cF&nRgs!XZRaUrN_0+2VIdIW#Of;Sd@e~r&PFg=F(%kbHGin9Nk!)XP4!}K1 z7EuHlD~u?SfV%ey(h-dM)gsM9m<&cSL*|(XRT4ujPl|wy>G9S`-a?54AyEKc5Q$sH zD1u92VNj>chTj|!%+3&_22IRO2Z5M5dwCIzY4p`F|F{BUCi9!%B;6e>g@9SifP&#X zWhpIrmP9HC6-$^1?JBX(PnjZ>>CC4-_sP#>rm>#@4X8i|N>CgOZ-@m=s6rRY&~SFe Jm*I>606QB=u}c5| literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/tex35-3.gif b/pytorch/官方教程/img/tex35-3.gif new file mode 100644 index 0000000000000000000000000000000000000000..ef40453d23b2c4a5e68f4f9cc0bbed5c6096f1a1 GIT binary patch literal 1044 zcmV+v1nc`pNk%w1VGjWl0J8u9|Ns9000640s+gFVc6N5$+}uP&L?R+0h=_>p?(Q-& zGE`Jly1Kd$5D;c&X3WgYA^8LW00000EC2ui01p8Z000F35XecZy*TU5yZ>M)0tqsn zXsVf)Fc5_*t1dj>XrS->9#4yjps^qj4hN$nNjU}_O2Y$J85WO8!jjNDJfqV~!eMy< z3I?j0V@9vv8$y5}sN3zq34#Iq0S;sm0xS~-c@hZ?0&fd`fI@^4h7^g5Edvw<2NMBs zo)em!pB@P+2?2){2w@Tm6A74z0hVWc6ale94QsHkv!J$|xq`bGu7xb8qaCau2Fabv z8w0^7a()zng1G{vf&tzD4A>6=*k=LFGu=Yq6XO)+=LP8)bh6&`(i$!zr}@$LVW4IT zRhec6{DcFrgi?h8#VGxvvasQ+hY@|zs=y!*f@A&w25b^|A&rQS6GW06SS`b#0S?YF zG*=-NfQ%IsXuGh$WTuI5bZY2nf!@Xn#gG^wpupxz1d%={HPUqD1%ex(AS#yY)K07u zMqU7Vp+Qst0%&?7Yr(9Av@%5j2oUVRuni0v`00nj$O*b(?`p`qSMUh113~@~@SvFk zwE%1uP)vaV(p+N$A07Gm>@mPU@*RW&5CXM=YKo6@&I9R}Y zfr6&JxgZ^;0BQw#fdsUCKzRaz+!6-d7S@4*Y}tk-Jl7z7Y_5bA4kXCyd?$woPE%MP zL0-H04d~w>#=P*g%mwb8CJ>u5JrJMHHU6hYRT&Uf0aFxgwo51^n5KsS1TauSgaSC= zjd9ThF(CsLhJ(N$q*dmh1`HaU>K5yDssqTiy%(ZQU&EyV1RJPJyAzl z7~rA-6Y=Op!G{Qhm_v3F5IMmEMgs7F0}9-glmrU|lVy{b)N>C2QbhMhFJ4-*B?C87 z(1-{lZHc8VcFi@#mtlr9W|woC$p@M?Zg7Af)^QOce*P&CVrLo9Q;h%$U~^`g>|NI5 zqKzIIl^fy=u*Z{Pb@G5o3xtu;WD`&R^euW0ZP&f<`kid(}=5I-kGbx1uzg_ zsnYN}@WLH6`~ofFVN!6#4j+OqB>}$y@EQ+G*)IkOxROf&`T`K|Dv}`L>=_Qw;=lkg zn3TZGE)T$$G%tst^UMX*Ji*O5%N$F*Kc8Gwx-u}$TAw_?$6bdl Owg{e$4F@(6002AS;IU=^ literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/tex35-4.gif b/pytorch/官方教程/img/tex35-4.gif new file mode 100644 index 0000000000000000000000000000000000000000..745fadf29565083746ed369d50c577496dcef81b GIT binary patch literal 525 zcmV+o0`mPwNk%w1VRZl#0J8u9|Ns9000640s+gFVc6N5$+}uP&L?R+0h=_>p?(Q-& zGE`Jly1Kd$5D;c&X3WgYA^8LW00000EC2ui0CfNp000F35J(^fDKqQMyZ_);U14cj zKw+3{>u#v}&gn4)bgpNGE#W(p0U=2MgR}>2SUe&<#)PEce6lLD=(K9pAQY2kRE1O%29H*k91Z~r z2A`mzpoKgElw2SUGmR4j4ilq+MF6`P0U%`Xhrs{@_W->AlBbyj3j`IAEWyD545w3{{oJMR=-ap_OvZ;b Pw{Je3QT!gRAp!t9tKG?d literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/tex4-1.gif b/pytorch/官方教程/img/tex4-1.gif new file mode 100644 index 0000000000000000000000000000000000000000..2bf1400f3361e5ed080d76230e6351bfe5b08e78 GIT binary patch literal 441 zcmV;q0Y?5uNk%w1VPpUl0J8u9|Ns90008dp?udwpn3$MmW@bc0MBLom5D*Y{c6PeD zx~i(G%*@OpA|g~&R5CI$A^8LW00000EC2ui0Av6Z000F35XecZy*O*R)GERzY73DR zW2&x*+`y;8_y4NiifjAh=QhVfh*f z6wNRra1k`X31cN51|$fR08LboON$o{KN1RG77J`)bP@;-Byt1|b!8O;KUN5M7Hflb z00IG;7z#86SyBiJ6$+{VFbRo=0bq3lLlj913|3<%bq4_p3j+%PzyZiN4Sp2`u@nUk z($mzZ76b(-6b70Ox1L%En6!C&6%CHyVg_7*F4o{S6R8%U#TE)x>JkRGne(kgC@?^< zpg~ap^K_!{&q4!jVFXQZCIFa~HTxuhnt%vHv`=SAeth&ut)#pP!0y#xgHgf&BLO`f zkmSM~1vd;d5jg270T%%XXtenB;08iZG!=Zqkifx`2Ue`qN-)5IN;JY46d*vZj)DZk jR-_Z4GNV~_Zva3%%eGE~1`lkuovUL&Bf5B1L;wIgI~bjE literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/tex4-2.gif b/pytorch/官方教程/img/tex4-2.gif new file mode 100644 index 0000000000000000000000000000000000000000..d5884b93a5770986f187afe888bee1fe25918fc9 GIT binary patch literal 535 zcmV+y0_gomNk%w1VM+ie0J8u9|Ns90008dp?z+0Vn3$N%%*?8)s#H`|h=_=Gc6JaD z5N2j(L_|a~GBVuU+#(_(A^8LW00000EC2ui07?KS000F35J(^fDKqQMyZ_)e7y@7% zn}8q$vXo&g&jBVONk%X*;3&PBa5yn!3W`aBu~`zIP)Q*m82~p1YIOT4um~fqg20*D zxabK1Rb3<#T5KSg-Xb*t=7Y&u#OquQITHc_Mga&N4{U&2g##H`6owoF0S=8^mO%## z5@Q?>o|!`i1PPuFe@HM3C@KgTuB1Z_i2w&V3`P_WX9B)t0BeJ^GX)J2I}!^k33LDn z2Q3YlKE^}|#WHLHyp03R2i76L&>#;bqm2g15)b4b2WK-64-L1C3f~Ls9_<*tji|s{_R#Lx$`KfRY3_)))vo;O^m;H52@l zSSBGChmAOM>fEUl&?y2y#RvnS0HMn|2$HF?Hsz>>k0M2q9B`%qq^38R7Ckg|0O z1$Z6mp~3~O6TGY-8_vMR1q9Az7*XN`+DtVnlDr$`8-P1}Nns7l#S73dgt@?MqwofT zi}4b706Zbj1eG;gO77s5kV%@j_HLH&C{i3ypSF&kOL0Oc2}`B?S)D=Ekt=`WAka#C Z!!FXkGK3x5dqXoEblSd+TO2?H06R42$Z7xp literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/tex4-3.gif b/pytorch/官方教程/img/tex4-3.gif new file mode 100644 index 0000000000000000000000000000000000000000..4724a31c497d7c375df5685102f5283efcefdfc1 GIT binary patch literal 517 zcmV+g0{Z<&Nk%w1VNn1l0J8u9|Ns90008dp?z+0Vn3$N%%*?8)s#H`|h=_=Gc6JaD z5N2j(L_|a~GBVuU+#(_(A^8LW00000EC2ui08s!Z000F35J(^fDKqQMyZ>Ma42A$0 z$0i^Mfh?vd&-4^v5|U&D69W##uSP6p44Hyrl3;9_#;9~s2uKFPjlnwYiV7_PiK`%R zsyMHDLr7g0%LG>&7_Qe!O~CnZau#!UcMUre0s%+?2ptb@f@_BZM^=YO8v_9jk9U|u z2MZEq91ozIYYu@*F$*ax2pFuUf((`d4{5dqW&mx4vUdwC33dPp2QCeoK)*x|2bo50 z0+!4iIt#Q(fi({%rPWW$hr7IfMGp@Ri{Kl#6AKR$2kS)$3Xbdq|?sBL0(prJ#DzM`PQK|q1BECC0RJK*bIfRD2vLy8<3Qq2GcC{wB=$B*Sd8)-65 zA;9v`ge|`qK71Il28jt~9K@3_PiB__3kE1PP-^G^f*mScFbYC}$Wj9mAoM`O1d0jH zpi!N2V}cGU+r}1Am`6enwRft>qX)ML7@A}J0jx`;&4dAP3L-+NkS~a~HvCk)NX#$? zLK!L%?YP%*)Bu%nhT2=!GS@m8K1r}CL9^!$sFGk5I`{O4Y!uv0a0=D6hhRGFWZi08 HLj(Xj*)6}8 literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/tex4-4.gif b/pytorch/官方教程/img/tex4-4.gif new file mode 100644 index 0000000000000000000000000000000000000000..2193427d84497939345e81c767267734a931eaef GIT binary patch literal 439 zcmV;o0Z9HwNk%w1VL1RQ0J8u9|Ns90007L)%tS;)+}zx{y1Eb$5QvC~R8&-$n3$@n zs_yRYGBPrDc6MfFW+EaYA^8LW00000EC2ui0673E000F35XdP;AQP-}(s4^Bj$~Bqf_D0>9+!A~6U@f`C9tm2eaa6`+A69gEdkP=de# z9y^kw8}_j#h=U{`Cq2yVnsZ{9E&>W91x$G~1cXt1Pa+Qvg*Ay*I|Tp^I2#93mXAJK z3k(eaLJJQ9PYDR2oHYdwSON|SG7ShG3>W~otB+<2fx8n03{y%EA&$VgnNm~_4-9q5 zbHqsp26)l{%-Mz8*_LJD;;JRy++o`R>g(+7?(50s=T!2*;Ns&a_47Xgl>A8+&HwlthUgFC~T)pHR506Tn=t(*V= literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/tex4-5.gif b/pytorch/官方教程/img/tex4-5.gif new file mode 100644 index 0000000000000000000000000000000000000000..665d0d4cfd78e2ccd8bb5bccf7f1aacbf8752b78 GIT binary patch literal 13131 zcmcJ01yodRxUPzXq;w1+APAD8(w%~IH==ZhNQ0nsOGk!ypVjgPVxg3jaK zJ)S@E(h`~;#(PU+wxD?^v(pWwOl8Gy@(PPzq3+L9qHHTxWZyxp1ITq^Wgb`eZ(C%8 zUn|Nkbwz;9Oiwn^+jGffzd|s+d%o<)`Qr5?+wK7mf@ zWqsasU4pqMu z5U6#HXjqe~#~lqJAdT}v{J7-)u?%r5+Xb93n69*+5~Eyasi$t&)5u*lE&%c5J$#q# z1+dt-7;k#z0>vp#U_6SPV|AaU48co2Si*$R9LX|QNUx<^pq26$K7o8c9ofZ4@gL6Q z)oNa&Z6Ltm4z06=$8FesyWSsqP`fyYwdCt*`nJPoNn?x5Y)V4U$LON=xR1Cin*6n0 z_;K$LIwDkE5^sF&)1tmjd)X-KClHe-QeH}!O~I?!e8ZbpO~hnOMjJE>aI>deQIFDPk_N$%5w19-y8J;Nz!SnxE*rc3%`86Ub_hBO>5 z7_>vZ03qjggL0~$Z7FeHNLmn#i?Y)rSkPP-1HX^t_(1x$Td=zt`?tW?{=TmeF5Eq? z6EWDuCJ&cK{?tTXR||UW3Os*f3P{u2Q07INgvC%`;%hbj?M~!`WQVma>sD`xzoD$M zs3qf<&Y0GBi|uxKEe0*q7|DapRS{6(F_SJ}7ZaTF5F5_fSGmfZDZa*XevCmU)fkt? ziBCX3wybpx_FG0YVRVOF40D^yxV^1OV~eYL`sAcro}`B+(k~6`RG~cSJEZoNecoT8 zw$6DBodpiNjxs5)K7lAg59T3>TMAZJ&vo7WW4F|ceKem*@(7O#E%TWtfc5fn98t@E zs^JRSK(}-C7chUjpPp7iw$4vJetTkaKu6a+7Dum>iNihx9`jw0d}jt>6YI|Y?vboS zVn&cf-?_4GXw>>dj+UYPCgxe10~1>7yW!&OwbymDHZdEnjw)S0xl&oe#)c;XH;W@m zk6SgkO_WYjWhnr8s|DgkyX>R$YDwE3J!rv#J~qbgiDyM0ZoPUk*SXW4Yl6raXF*A@BTr}-xG(_)i**WUjlgMF|3507biA5YBr3#kogU27jQW% z>Y9}r-lBx@?vbG_4E76%eJz#Gob3GfLi%Vtge`mZmU?@U+w&rn0w-wd*e7VtrTN{@ z%;NLmdy&3x52zG575kWGj+1?-8;__xOM8t+89;ciU8lhZC*eheTrk2Kd!H3~%dbTi` zs%AJR#t}iiN_)!gMf_wSD;m?l>Yq}PGHc@ambA2`O^?B^v={`CmQb>SO_d~N$NB}Q z2TYLFzelY70x_a3Zj$|cJu*j=ljf2o%AuAT9twKj7Xm>QJWC)oZWq5A% z#zj7VBB-U&igz2lmS-InXC=qnNU!6Frks?`4FtR;i)pWGwR-H6^}d&`5hqx{TT|`PHoC+H!S?$vHqzHPJ4PNVnD9>v zO5Of3Ll&?r-5wzILm1(J|90R+r+IznXKOunidBEx}7!|e>D4I4iy%jlLwW-^< z+1Guo!;RrXt1(VlWw6P)Jgh(rip!gfalACk{Rj*0>j;C`4}3l?_1=oo-VWe7$}%8F z8J_yN0y>B5^1f%J=xa5#05cHzU7Nai)epEaQ<1XV0`g-B{k1qH z^;tA*l^W$NzEZ&T8KYkp+ak(FcYoHIQ@rsOOQ!D%;MWn;8Kc(^rG@?aVZUoH+GA=4 zIdiAzZ0UX7KxqaN9H5>dCP|aVKbo}$v+u~(C3+qlP6FGWN_Ql@0tFZmp zk=A=)ZsE-lRJ^A$Z}vk*NXO$gm#H+6ZO`fUiCN{gTRtMPKgC=*Od`f-!Ou^OFZ^_3 zY>g$(Sl*%TYwS>IbCIAQZl&_C+@{%m^7CAh8Ub2JPnmIo2k8*_F2SOfT|dUiRI9vg ztITTufG9pd1>l|q>33K;Iv;#GBA``d72d_SFVGkhWgRM`yj4^i?DDRk?oG+DQ=jdN zX(GpGf6Ub^J5EIhT|qu?TwSWA%Au@^#J2VK^}v*|rTqgmLL~|})idN`MAXCs|6^r|L*9%q9PkY%bPxxZCrx zFj8pA4XMNQCQkjuT9|H`mtkZwyS23I8%5A=ZmFO0R%pM%U0`bvEQ{t6T-DtfpDPZr z(KZ~ff4*&4;+neetalnK{G-0Rrs_V`;@X(ob1hOr*Hcvf_uj_i@3M=tLZy9WuN(aeYfkn zYu5BQ&B8VfS+}iOGjXL*)ILMzKJwg^CUHUn<#Aq+vVU$_5Vy{njaz<0e^VaNrnAv4 zyX(2|D0<(!Ja-q@AeAMfIHIvWcUpYK<8y~KWfDZ;$kU+ZlJ_b%Or1AqP|huoXbozw z_;mov=InZu8x&COVQGlh;jz#yzHi@V9_lZbJv@WkAx;^PCKG^KVp8r)c3#1<&ICBU zL9>Yeh{=NuYaD;y_^!>imUXtv!@i^1wJhu7--yIuhI{<2YO9X}Bt=KXzq6Z6_6BEx z`bCoXxM0p)s!bxkP))+35g84VqUt*{o#@VNFT+llrAaW4$@L%rBL9*|8xhOJn!gl6 z3D4fdI(elz@Hiz$r#5hq74v*Y1V7iV**P81D5_iyxN8hi%@6? zCkEkOMuG$SV3xL+@EFPl-Vztcs3#_tKcq1^x4@oAf6{cP2p85Sn6vMZcEP0wT_D6+xGgK!hy+yZVDvD z5raPdGIy41c|H>AF`DQ0Y9p{L zCj?8=we{ZqvJBS)eToTU#eM~9n53`Cl`Hg5gL!TYh6d0{d;d{6|D@<)SR@A>3IK^pd&|loFO}Ig?q$OQ`c!P9jJR3g8K7D~t+L zk=QNq*q5a}jmRP9$CFCLa`B?DN2IgUtqYq_b=1k=Oc{KKoo$bcq|+l*l`#hQg5ft6 z7^vVyEo1#=I4Nk*wZ9nJHx(SV>W9;+fyGw#kUI5r6-0gdlbdZhpr5N%Sev z(d|@C3Kn7*p!YRA;KCyy`oC#AHNrtFvhu?Sp4{hQq5fDj+A|g5{(#BrTSL=i@-k zns6!3vCj*vsBVtVCx1wqanph6=-pU&rbmvg zei%-fQduV`e<7B`fGcqGDXxEtD9#EIh;ZRit#Gi_LY0mz!G0IVjy~id=XGeQT&UGe zYY*LZ7JSOFs(#fQkTXLr#pQ;|@;NY{pV3o{(lyBF1Mk}{p;J5se+_~kSg0Mx1p-G8 zCGd$b=ySj~mQmESSRQt@|3%$(?l_>kp_G7YVmG1sZuSaPAR}5 zxI$KcNi)tq*psXIP4>QwI%cNBFgU9f|9BP{1a5`t?_0uEOgyL7`em%0v6 z@^HN6@<&F&-!n!-3{J5Kf3(-1f4M!*xa2tVg5{8!W*gQHF=LPRRDP`^K1#AYU=Epr z57xKE_^OjcfyFOG7@3w#rzB)*rXex$IK5uQB4qaG@=}mr(qDY_T^uJec^Qv0JI{u) z+76BEx=m?HP+CBufyYrA$zTx~OEp z=UmH^wsNG?60QDDE0kmlPg7KSqtGmLv%;rxAVUSnL{P$A&+}GOkFnMDQ#pOiL21l) zWaXn?B<#g0d!IwOD4$YxODlyTTaQa9C7q{aYnQT8TX=KTU9GFoZkGN8DM$E^+`jP= z(JSKh7OqIp%nzc8U4&yrqj`oc7N;b~bTO9OhmfMV3 ze&0R^ji9dsTIQ^pW9gVI^nb_fr?R$UJMW}FkovJO4?6?Bwz|3g_|ojW?Y#2+{O zLagL{8NQI)i%OcBGhY$VZBF23qdu7JE&h$6lyTC4g=Mfifoi~32VJ~IqJ z*@H4mc?v|TUGAqGWzI<>wt>??YEKF+cg`aHkzL*iYO1UZOTm-ygKhSW!K>Fmh^%_$hp=jv2U}7?QIQU)Bt#;-$qTU#6=mBMUFRId@dhc9F^@-wOS30m78V z{8z-4a@+~@4b`xv)|_M|cP#ItL$1pfVaSslZ|#U@1C1<`9;R<$o>wz4hmxx=Ue|g< zh=#w@)XNDC_C`yPuP%%m&yWW&S_Gw-6!kxDX+v|3{!eqv#MrKwG1FW0ovflGwG2ZB zM}C)H8A$UsM4$SFRXDde+xn@dK|o_oDo~*pCgJ=7dy(0Rl{L{* zwy}A@=~;y&|6PU1`6fkpmteTY=R>?!`;eCeV5An1K;(UQCfkd2)vKZ-I;#JEh)6`fgk z*=PEwV^vQdpwpkd`q&*v?q(v&oGR4 zdOO|!1kn;bntXLVHtlvDxbcNW?{9m=y~g-M2hNFkhSFyubI;#FWylZdbZ~Uhoj;uZ zu(^Ho9aYqzX59Y#K+b8P+3M@aqLMVVDSN+XtSLbTfe7wt;%(EHUsW(}@!hW8KjmNc zi=5wss0UIL%G&8ExrXI?$@1E-FZiI#psoH^t(eE)OYaD=bFt-;<@b&~UqT6S5|A=% z&S_!-(z_+ddCBKi$l7c45v?Ece7GrKpLP;~wZP5Nnfx~TF!9DrYxKFbzsX|0Yd0;U z|DDr}3q@C0&P{9>$vO#+-l)2)*eTJ>hFs@-$q^ApC_O4X7a@s`=U$5>>%dF!d?h+h z;b)WA^x;Y3k6cgyHXafjGr}r_>>gRb9NeXaHCrD-C;RtmiC@4IwN3Nu5|!w0@*~gI zSG)S(XSbyJgB6B1RWQgwVL0W2px1d3f=4zL=9lu1PGcUiF392Vh+hfS^0mZCn6?M` zX%6~kXiaaaQ0H)j8)Ucn#uRjMIDLZG1Q9?YKn*ar`yAI%S z@HZ)>K$^E?HM#n<8~eLmUv-4E89if?dxsY6rq4CrgJ?r!DD3^=Am6a+xQIW-myfao zojr&Fi)dFv2k2OconA18Q#+=C(S0#0i*A2-98~?ugq)ge*ynlcO8OaSlQcB9=s{3$ z1GF~Q-&iiW)<1a^sVgUceak6pExn=RoQR@iOC1E?*&aX~u6Yx~+G1`V*Ri+s0Q@e&J78fGky{`c- zN*8Bi?$Lb_t>Em2ciHI!?XwQ-XaM>Fwt1miD#rrDC^BE?Rp+K9Rc-$RQA-UDa0%w0 z&C*PwU}>!cb$rRSUx2gQ^mTFr7X$H^FcAw5mT)Ej?+cn+6IW~a}sTq8(W=G`(B5E4H&IISgfb4uhRTr!YEGk0G`NU5Bu z8oR3<);*0p%mgDND0TJ-gT~q!Wgj@efQ)RFJtsi@)^td?EDv$!E=ayh^5WHgfx%7t zHPM2p(MT}OtFv`F^P!6_L%&I~+uP|6@+aB39gH81VIVrs_3`s^+SDET%COipdO^p* zQ98Z(PiE&1{>JcN;uNp=&(J17VIf|Jy8|v#N#|F+E>b3@QT4`(7TF0Em{vp0BXVoB z1H(xT$0YY%Q$jz%vs{_{4wGRgL{UJJB@&iHOp`~vsGNgr>Asr-+)~G{+sP_Dj=WZDIT_Nw>!PoH`Lo5nS8_AEXPVq;j%zG-- zjrFj&({b-sN{`zDjkBZWFmy0ouNbK;t?f&%Lo)w^_J8td6AzDoZ{s(n*Fz>=)=#I2 zldq~Om90dk*3+jSI&Qu8(28pE8aBs~*|K1Xf=D3z+O9no zNtNTS>s0Y*=b3rUY+>~VRy!&UTFyStHL9X@8F{N_ySeT7ra=>GkUa*h`#?t<$S9f}+H%s-T{*7~ zU3Z|MLuC9<7Kd~4TWV=%pRt0^(ud$4RN`ra=}7!CzkIrdC^bz){OaddNFMI6{o9%V>cKwWqS?hg z(^>xp*=@SyxMiZTxG`UCDR(QO)=xkfry>E4)35CIgT@;7?4UDg<+i<^cx>1 zeNul@mq*Xf+PaAFHnRVnKS_7Ecqzzk?>CeC9iQ%fcR;FByO_q7pVqN*zJfB~+#u7x z5lg*tU)plGtjnYxjAiW%VvVjjuBBjE`_1~2$vL;PtxZBfaLmDy$^qE&#f3 zRXgfbe5#O)J3glk7m+9cO6IWD$bfGxIFB>p3A!qZ6i&ndK*v<{Fwe%qA* z9UNDi6q=msEm6OAhECiB=NI^NFN2F)1wtnm%XJE$2jUq2jnDOh?;1!Q(^IhQ7|(nv zO34Qb&4Jkuzs6~Ve9HQZ&UgkewofGOa|LU&>-R-S@s5onoPbT~s4p9fG(O&MYmQ~( z7U`5zDQIw|3SmFVyaRLahW-=G*(tDZhcyrAo0S z#_J9k(4XrkL6~0rkb`8LBLeFPA+5JZhYdDHhcB0MH0D7$I`P*+h_#;L^vHU z>OGQVVdNgJmwrlpWSRYRqLR%gWYpRIY@^UUZA^Sl*;^J|B$= zhoO_NOfAbUl~5q|DBH!{o8KJP5;x#2HDL}OPCfB-vgFeLR!f7LLQIQlGr7=*04ZFr zf{Ke@Q8^0{^KDjwOok47ez|1o`R=>hc;lLnnd_El`0_kw^Dp6Q+W{ z47Ml4(U=dcqrXV+kD+jM%;~WyX{)~ApX@rx1Lcj`DW~Rvb!gvrRm68&kArfXivCg+ zr3^jLlUs?SH)h1qAXmNen3anN;L*0z`y;xA>nq@&E!`X|CEjWs;Uq0I;FzD$iI{Qc zz)hDt&m9r4XZ_MC;SQrSZ}oV_?XHV(;%tCPz-t$GoBBa@Zokf?ptGe)1rw;uZnjI& zRBskFtJEh$C;T0b9OSqFUNr0MZvE>HR1!QVSq@YAJ%V+{;Kl0p=5*{zF~tOV4RXs- zliUB{^)+;6+2Fe4_CooF%$uzuyjQ%@1wc6lBg$7us7$zU6HZ=Fjn~mHM9dmg{DVAg zvwR!!`S&wbGR2)gKAoOp)-T@uniktk8H~`D|@hmghb7?w&h(b4-dCpz4zcRCf zE*rh@!TAw_ii}Yc)<2*59aKDY?UHt=XIU6aucn#Zajh}?7x8hAWvk(Eexc|!h7JBw zoay(WEPQ`q>YG94ipjOPd-tJ8A7SWfUIhFGfUfYNE^7D}QJgmYlmnSpGAE~y#{OTr zUNNQQVlMZ{Qs4FiW7EY49MPe`F{{IdWInZYXD-M8>AuH} z;sSrOt8~8B+K1(Z9;NYO)Okf(sr|#RY}dTRxoZhon;SKtz3fr97QqNPvpPtohBKq+@d&&r!e&N%Ukg)ee*8cA7CgvSw=DVc6;KD!v~1*3 z12}XI`05u5ZqiD`qjFPyq27Npr}L}^VC;LYye7mUoToL|K*C1#X767brlas27nQmx zcXzHohZ8NZ?T4D*VWZWhs9{La2c3Vm8a=B-=o@bX@DTq^k~G0H2gAYAA6qdYuzVK) z=izs3`P(3}Ud2txQnoq_`P?!68cLsgOO^C5& zgZuuo$N`*D13STgw$2l?t!g#glKJsY;hm z+Bem2*q3=58PXk`2h|78;xZ=QZoy0ZFWV2=5xDEiq1yRkbYqKcjjcwS>08>`qCVGU zEyg--D1rm*vK^5p+L`fzNyojJyoEtOKH}*^N2J;FnEG4&fWz_)!#Pa3Bv;XAT$kYh zk~r#oh`;2rBr)%_=y7O9jVICuD!UfDC3dl~($%5ED!-mtai!TjQ67y$nw}D-+_6X6 zdfF(U@Uks{HoIz{0Om~i^cHT77xnUjT`P@8^`+C-(abBzk#`b#ZuVi+K%`(K9UJVB z!S7NGZ%Wx*L=*JG^2qR~Sz_Dws_2<)Iv)VnE*&i=K!MWiKugh?kyEE(?7Mn3^<{UP z$~fF+<;n@>Qp>j3V(-ugUG9Qry;c(F9HBr1M}5WsD87Wle%a`}mi0mM>_mk=%it^p zGL8MF78lGsU4jL|v_^zVVp*W{n#qJK$Mq{ke~YQCEo>h^=^-f;`cucx(Sk}&ujL&{ zcOUPOlTCmyB59mQ>wseE_pts?+AvoGhNq!srvBxPR|1aa@9fqcIoh)MDe4bP0u%^B zfU3~PemPB&aC>?Z0IgMu46%}=EEuCSwbPqxz+#+?$*)b#dm5t{Qj=HpvQk;#gT7r# z`FJ=RlTLw4X4x%T!@lS!XYhUyr2PpWZQAwp_ryOy&|{%So%-tKUmolRnJnTzx;mI` z$YBZGo`-b4PFn`}Vla9!;)3{q#jE_TBGcbq;LhIyC0;iE^_Rb%*LVQ!9xFOPyT_9v z@}Tc5Lp{c#OTP0C>MR+Tqbg_7{tizN4dIy%8mq_g-b+DycDu!$MOK#9&Ki?$3ssq^ zFMLN2ay^;qrwD^~o}fJIi`SmuN3JX?l`XGL>RxDivn`Sym7mVh zHM!n+Tu3cDD=~ROU=GU!m$MV(jfRQOUu&mFh-ZlEKY(Kt1lH~6Hv?dK271>|RZlwH z_;2_L$gwV<38ha(hdfr~a~kGqyVm%t%u6=h;)?-UdZ(`Sx@o5e1xQK=<8WHf{M}aB zOn1FMTbB6@8SvOp`UiNL9&$B+|6W=&Fxkd@##B!o$z>L8N60J__>l|h`RZCE+va}o zX`Z1+&bCOVNljlz{A$l9+qV`|Ht>I`Cd!UcQC7jR$t=vPmf-Yb{pITcTkvSNQW$<} zA_1%=-%fyNRfT)!eblp8wGNG0pc)GPjX6le{8ve=R<^|@^MWkW{ z$t;drV1QCGH8yT_8PvH*$8|@uviUf3gD|QI@Lkf<&ZmtzoC&Z{aqGD6vQj6U!2!nI z9ck&uZH`9yAsi&@W5nC^6Ro@*^m6WrmHf|y@+#~jEl#4!U4(^O+7m zNZ^grSj=8DOC?V`8r$}*eisUz2)lTLlPzubW4bGsOIXb)B{#5A z1LIAwTyw}m^h%<|_w^)l?6b!^J;VV}#afXJh|L&MH-J)CS7IQqP=Vk4bGMiyhE*%K zOiGRFjfc>;ogkBd9imI-k>#`!v`mPb+-POG3vrDqF(ZN6yhJ$4ebq5PgC~RaV5*R= zfu^`1Im#5E=(M9P=!&iv6t)UI^H=VgBU+h6G~Boj=uLyLzB7o{Wv0EcbnO=_%OekR zpw?$Ca#)YYi2g1k(3VkARfyVJ=0CA87|gbA1Gh{Ig6 zUN%irw$EM5Lw4w^RgH6RIEU^ zr70ZQz82CJ-TB)214UxsCKYO$4{&3Adtw=RHD#p{*>yy2Vtt;k+KZ0~JAj6PgogoM z3EJ=j7cH%h2THyX< zXkEG;NiU<9zLN6(?0;`1wx4Kt>a@5RAL^ai^Q6y^DzV){AZ|SkM zOheD^?R62k#PD#}bEM3pz?aCDz>!kjV>h~yR^f6E;_q_I;h09amFxR23O$rCz5`$u z*Akcfdf11nCYzjMu`)uV$UKyuFhxV!=bgCJ={dB2j_vk4=EwTYh%dkW$*Vs$IU2O& z%cb=(BM0dDAa>i)JYH63MGIQH51_odF8zL5<}obaRu|eZ99>|optwaF=R30?3d1Sc zF)UV}6V}}y{sq>XzA>I(*b}gWq8m}G7@U_ie0JD(?>p{3S&P}Q?d!>~Y_$9H^&_2=$x{QRsr@|fc zetjj9{6(&5L}JN~+}Uq#%?~hr6GMA6l;=4nLxh_kPvm!nJ+v()bE*uGR&@sio9d{< zkZE2E#Pr&%;oNxeF#Xl8)!^(*S0X^{QgF+W$Bk@k>^c9U3c;!Tk%`$ z!mK$?j~&%cLfAx!$KGA{OQjRg{UWKCZcy$F&##h=7`rp3Q4sH|!EM8`c$^8bk2-Uk z{;4h7gHW}Ll&~XAw}BHuuJToqWYUaKs7pBry+9Eb5Sx7GY}O#YDtz(b2+@PZk#+ zgbYtdi~Yh|#vcHqwpRLgfiYh5*9)^c_NN(AvZwe3yow|UgKZ_fr(mIBMh;p&Iz5&w z+;=8ZY93}!G7@Eqaf*G@!LI?zfO%YfaTcqNW3>?Jvwg5bkzK{nzP0Mbf+^>)B)?|u z%0aezj?(kE4^D zFXe?)4lJO!v_1qt12qYRY{rpx3OSg_Q{5rX3aAESd`0x$8Aao#XbgdVU;;jc0lUdg zP|C5_9eMG77ibM58+FKgx}fP~)f`evor$aq2w0L~66)hVbz5Y0tcgBmzH45w8aY*6 z)^@wU5oAIuD|>B_E);o*-%sL6?v^4;RWSMIRcuEy(J&ry;}QdGYga(A^$luCz>6FI kKi|Cge}C`e9#ZUBf^)tFxsnXL0CP`XMp?Q-@?GHn0$+BoegFUf literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/tex4-6.gif b/pytorch/官方教程/img/tex4-6.gif new file mode 100644 index 0000000000000000000000000000000000000000..cca1906ef4b3890903f59713179df1349d743959 GIT binary patch literal 880 zcmV-$1CRViNk%w1VebGP0J8u9|Ns90004G&b|NAoW@ctGGBT>Fs_yRYy1KfUn3&w$ z+z=2DR8&;V%*=?0h(tt0A^8LW00000EC2ui0Pg@D000F35XecZy*TU5yZ>M)jwD$K z$@3)6P`+?1&vb292qLYLaR0!da5zj%77B@h$ZS#?27@DsKstj^Db-3-EUw_DYbW`J zZ)3otY)hTr9z(;VXfWWwLj4}{Wf%^46$gPEg+K^?9|;Bs4GRqphk`JSj*yZf4Fnkj za~1*voL77q2nh$HKLsHKMgR!`YM+!Zt`f1cBLX@W2eKFiOHK~G6A28-$^i!kuQmdc z91Ur1X0;{M$7|Oi2dovy3#b>&SKt~9!{{~L9S)@oj%(N@@DuV4^dssZ2x&~5O`9NK z7!5c6M%jT?upS8n3hyLnIKn`w4gyp$d647-f{Xq#0EuvrfQ1AF1PnS1LDD1ulqx|e z0Op~zdf&x4bjH>{!+0ai9 zq|vMpb*j{=6`a;n;K^!R3T&As9dJ`a6&u1PsGV??f{q3>A@$@rVJ19YDU0hBPH zmxFyrYPg0?yn}2HPU~DKYc|Mf?rU9e%;0 zVG-9}3Ru&gTxu0~j9*VTq_ID~(**u9(EjBC3X{Qrf)v>~5Yt2xjfG2HMHR?_9{qtp zp$+s2lA8qzfF^+hLaD);3}Ja-$s=UNb2e-f?ixH~=@bi%Di8;URwxJpomJ4%B%2uUR;%O9`b0`? z6$5|(b1-l~n309(>YRRdFa`p$ASLVS7^6fBAt=XI%hwt%S<4}|v1;qBiP?Tjfu3MQ G0029OnPQy) literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/tex4-7.gif b/pytorch/官方教程/img/tex4-7.gif new file mode 100644 index 0000000000000000000000000000000000000000..9815ee71e12d086d3c15244e7ddcbc475cbcdd8c GIT binary patch literal 16590 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�CWMWZtSn8Q%6hd*xkeB+V+;iqB) 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 b+kJ#@wxOqXN~_;}T24VmRk~c#EbRXQ9^Tsa literal 0 HcmV?d00001 diff --git a/pytorch/官方教程/img/tex56-1.gif b/pytorch/官方教程/img/tex56-1.gif new file mode 100644 index 0000000000000000000000000000000000000000..a28a3f617fafbadd1a224254b2f6876b502b3b72 GIT binary patch literal 1342 zcmV-E1;P49Nk%w1VQ~Qy0J8u9|Ns90004G&b|NAo5D*Y%W@bc0M3|VEs;a7ph={tn zy3EYX?(Xi~+}u=DR5CI$A^8LW00000EC2ui0C52m000F35XecZy*TT=S>j+Qj$~Ar9rrEaOjR2w;V-&4(rx~+F45${Wgs~Hun`gIuzcK^A1$HKoxXa7B6lE6+ zlgiAC2XfWU63`S00cR3~5}HH=fdB&E7{g)W)miL%+LWaf1>y$o?^)OH^R*Hj#Htc0 zUJwJkDiF}H@JtT{2M!c?gN8tZ0}q}=lo$+v0s;O9Ffma=2LYflUj8HqiH*wv1P-ua zXlSA0#f)?!7U=jfqVF{ z6NRnm^k!6!XQ=)RNw5#0RYd_1c%b9KBnsp(6mY<|uiv&98sw#LK+Two7m!U5d~U!S z#sCVa(IH_0G6Y9s@mbKel%Jpy3IzI;VnJLwh5;b109i6Rf|mbeF7zhBQAcit);uRc zaX3)DAA@pDnaSnZ&dW>PiU2(_U)nSeq$40a8LOd4|w-7 zzy{-3)d@d!JkapduTO-E$;H-yKrlWC;Qqu!Zt^V_UI5q>SV0o)J@B4=6W}+2egyF6 zA39fLg4bK_Tu6Zf9l^&!0Q1#1n1sElQDHb90w~}wd?={efeDhhL3J5G=t(0KT6l{9 z8HR^jauj$7zyaZ@hu3*8fOJQ6(ZpwCWid_(00IG+WRhcv4SP5vWgqi6Pot`!T)06<3i6D{V zsCjCtl?use1q#rrngiqs)+w(@{#9TS3#`ic>L;<*WbBZt-TL1Wi{jO2ABGb4-iXx_ zYit9^E}*QZa1{wy2BTI0sb7>{puihPQkU8#7sMqaeLGShScnYh=n0Vr5Hb;w1NVZf zqxu4HSew)uNU*_B$Q6jPo8TE2pG1vVV!#$tQ1GbR9;xsfd^AjD%Dvt=uE|2W>iv8wD zXATogjgHj~=!hi)feh8aZ47|S3e)&HwquB7|3Nj{SWlq!kX#qw^%G!YfFlM_=Y8eg zYo?vo+HI2=&MQ?1fNYNMKn6e;lOqriz~`SMO{@mp(R{B&*pOm5Zy`nW6G(+IQGn$O zv<`?FL(@*jO5EfglkYPJ52gdGuM|5Sux}#KHJ1<#Jn(C>K5pr5o=!A9s}pAY>#oaA zyX`M|?||~Wzw!L+G2IcgN5dE2J@W4_uR!yapkKe`*p#}D5$Mt!?*0G-f&oHw8-djW zY5|17;SwmZ|1q!x19X!EA4owE^lveuGfGDgSV0mLtb!Np;0qc61`dkwgc;aLH_k&s z38L_YB2Xa=O>i&v>28KNL`?+>SQ9g-ZhScm;+i-o#5xtRi2Bfn5s%13aYO(BJF`4Q A>Hq)$ literal 0 HcmV?d00001 diff --git a/pytorch/实战/1.ipynb b/pytorch/实战/1.ipynb new file mode 100644 index 00000000..4ff48f15 --- /dev/null +++ b/pytorch/实战/1.ipynb @@ -0,0 +1,213 @@ +{ + "metadata": { + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.0-final" + }, + "orig_nbformat": 2, + "kernelspec": { + "name": "python3", + "display_name": "Python 3.8.0 64-bit", + "metadata": { + "interpreter": { + "hash": "38740d3277777e2cd7c6c2cc9d8addf5118fdf3f82b1b39231fd12aeac8aee8b" + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 2, + "cells": [ + { + "source": [ + "# 3 Tensor" + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "torch.Size([3, 4]) torch.float32 cpu\ntensor([[1., 0., 1., 1.],\n [1., 0., 1., 1.],\n [1., 0., 1., 1.],\n [1., 0., 1., 1.]])\ntensor([[1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.],\n [1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.],\n [1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.],\n [1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.]])\ntensor([[[1., 0., 1., 1.]],\n\n [[1., 0., 1., 1.]],\n\n [[1., 0., 1., 1.]],\n\n [[1., 0., 1., 1.]]])\ntensor([[6., 5., 6., 6.],\n [6., 5., 6., 6.],\n [6., 5., 6., 6.],\n [6., 5., 6., 6.]])\n[[6. 5. 6. 6.]\n [6. 5. 6. 6.]\n [6. 5. 6. 6.]\n [6. 5. 6. 6.]]\n[[9. 8. 9. 9.]\n [9. 8. 9. 9.]\n [9. 8. 9. 9.]\n [9. 8. 9. 9.]]\n" + ] + } + ], + "source": [ + "import torch\n", + "import numpy as np \n", + "\n", + "# 张量初始化的方法\n", + "# 直接生成张量\n", + "data = [[1,2],[3,4]]\n", + "x_data = torch.tensor(data)\n", + "\n", + "# numpy数组转化\n", + "np_array = np.array(data)\n", + "x_np=torch.from_numpy(np_array)\n", + "\n", + "# 通过已有的张量生成新的张量\n", + "x_ones = torch.ones_like(x_data)\n", + "x_rand = torch.rand_like(x_data,dtype = torch.float)\n", + "\n", + "# 通过制定数组的维度生成张量\n", + "shape = (2,3)\n", + "rand_tensor = torch.rand(size=shape)\n", + "ones_tensor = torch.ones(shape)\n", + "zeros_tensor = torch.zeros(shape)\n", + "\n", + "# 张量的属性\n", + "tensor = torch.rand(3,4)\n", + "print(tensor.shape,tensor.dtype,tensor.device)\n", + "\n", + "# 张量运算\n", + "# 将tensor导入gpu内运行\n", + "if torch.cuda.is_available():\n", + " tensor = tensor.to('cuda')\n", + "# 张量的索引和切片-与numpy数组完全一致\n", + "tensor = torch.ones(4,4)\n", + "tensor[:,1]=0\n", + "print(tensor)\n", + "\n", + "# 张量的拼接_在某个内层已有的维度上延伸\n", + "t1 = torch.cat([tensor,tensor,tensor],dim=1)\n", + "print(t1)\n", + "\n", + "# 张量的拼接_创建一个新的维度,组装原来的tensor。在某个维度上组装原来的tensor。原来的tensor不会被破坏\n", + "t2 = torch.stack((tensor,),dim=1)\n", + "print(t2)\n", + "\n", + "# 张量的乘积和矩阵乘法\n", + "# 逐个元素相乘\n", + "tensor.mul(tensor)\n", + "tensor*tensor\n", + "# 矩阵乘法\n", + "tensor.matmul(tensor.T)\n", + "tensor @ tensor.T\n", + "\n", + "# 自赋值运算 _自赋值。否则返回运算后的值。\n", + "tensor.add_(5)\n", + "print(tensor)\n", + "\n", + "# tensor与numpy的相互转换。而且numpy与tensor公用同样的地址的值\n", + "np_array = tensor.numpy()\n", + "print(np_array)\n", + "tensor.add_(3)\n", + "print(np_array)" + ] + }, + { + "source": [ + "## 4 torch.autograd " + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [], + "source": [ + "# 正向传播和方向传播的用法\n", + "import torch,torchvision\n", + "model = torchvision.models.resnet18(pretrained=True)\n", + "\n", + "data = torch.rand(1,3,64,64)\n", + "labels = torch.rand(1,1000)\n", + "# print(data)\n", + "prediction = model(data)\n", + "# print(prediction.type)\n", + "loss = (prediction-labels).sum()\n", + "loss.backward()\n", + "optim = torch.optim.SGD(model.parameters(),lr=1e-2,momentum=0.9)\n", + "optim.step()" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "None\nNone\ntensor([36., 81.])\ntensor([-12., -8.])\ntensor([True, True])\ntensor([True, True])\n" + ] + } + ], + "source": [ + "# autograd实现微分\n", + "# tensor 能够通过autograd自动梯度。进行梯度下降分析。即记住运算过程。\n", + "# 每个张量都有自己的grad属性。用来存储本张量的梯度下降值。\n", + "import torch\n", + "\n", + "a = torch.tensor([2.,3.],requires_grad=True)\n", + "b = torch.tensor([6.,4.],requires_grad=True)\n", + "\n", + "\n", + "Q = 3*a**3 -b**2\n", + "\n", + "# 构建一个梯度运算的图(树)。\n", + "print(a.grad)\n", + "print(b.grad)\n", + "\n", + "# Q.sum().backward()\n", + "external_grad = torch.tensor([1.,1.])\n", + "Q.backward(gradient=external_grad)\n", + "\n", + "print(a.grad)\n", + "print(b.grad)\n", + "\n", + "print(9*a**2 == a.grad)\n", + "print(-2*b == b.grad)" + ] + }, + { + "source": [ + "> 计算图.自动维护一个计算图。输入节点为叶节点。输出节点为根节点。的树。" + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "source": [ + "## 5 神经网络" + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "import torch.nn as nn\n", + "import torch.nn.functional as f\n", + "\n", + "class Net(nn.Module):\n", + " def __init__(self):\n", + " self.conv1 = nn.Conv2d(1,6,3)\n", + " self.conv2 = nn.Conv2d(6,16,3)\n", + " self.fc1 = nn.Linear(16*6*6,120)\n", + " self" + ] + } + ] +} \ No newline at end of file diff --git a/工作日志/2021年3月19日-四月份计划.md b/工作日志/2021年3月19日-四月份计划.md index e62b4c2c..4687402c 100644 --- a/工作日志/2021年3月19日-四月份计划.md +++ b/工作日志/2021年3月19日-四月份计划.md @@ -3,53 +3,83 @@ > 复习计划暂时搁置。开始机器学习的计划(第二篇)五月份学弟就要毕业了,也就是在四月份一个月要把一下的东西全部搞出来。 > 当前工作的主要的三个方向 +> > 1. 机器学习算法实践。 > 2. 联邦学习文章复现。 > 3. 恶意软件数据处理。 -> * 静态数据处理 -> * 动态数据处理 +> +> - 静态数据处理 +> - 动态数据处理 ### 机器学习算法实践(四周) + > 尝试各种机器学习算法,主要使用主流的算法框架。寻找网络教程,完成这一块,还有很多书。机器学习算法,应该由浅入深。不能像之前那样想先学会所有的原理,自己手动实现这些原理,然后使用别人的框架实现这些过程,在别人的基础上进行改进。当前应该吧顺序颠倒过来。从使用开始,逐渐理解底层的东西,然后做出适当的修改。 +> > 1. ->使用算法框架或别人的代码解决问题 > 2. ->理解该代码的底层逻辑 > 3. ->理解机器学习算法的原理 > 4. ->改进算法符合自己的预期目标。 - - - 机器学习分类 - - [x] 机器学习实战算法原理+ numpy实现 + - [x] 《机器学习实战》(算法原理+numpy 实现) - sklearn - - [ ] 学习基础用法 - - [ ] 分类算法实现 + - [x] 学习基础用法 + - [x] 分类算法实现 - tensorflow - - [ ] 学习TensorFlow2.0基础 - - [ ] TensorFlow恶意软件机器学习分类 - - [ ] TensorFlow恶意软件神经网络分类 - - [ ] TensorFlow联邦学习实现 + - [ ] 学习 TensorFlow2.0 基础 + - [ ] TensorFlow 恶意软件机器学习分类 + - [ ] TensorFlow 恶意软件神经网络分类 + - [ ] TensorFlow 联邦学习实现 - pysft - fate ### 联邦学习文章复现(四周) + > 阅读当前最新的联邦学习文章。使用别人的代码复现联邦学习的过程。复习和复现 - [ ] DeepAMD - [ ] CIC ### 恶意软件数据处理(四周) + > 针对恶意软件使用机器学习算法。尝试单机或者使用联邦学习解决恶意软件中的问题。 - 恶意软件数据的处理 - [ ] 静态数据处理 - [ ] 动态数据处理 - ### 任务安排 -1. 每天sklearn一个机器学习小算法 +1. 每天 sklearn 一个机器学习小算法 2. 每天一个联邦学习框架 3. 每天一篇联邦学习的文章。 4. 每天数据集处理一小步。 -## 收获 \ No newline at end of file + +## 机器学习的目标 + + +### 机器学习原理与实践的教程 + +- [x] 吴恩达机器学习教程 +- [x] 吴恩达深度学习教程 +- [x] 机器学习实战 +- [ ] 深度学习实战 + +### 机器学习的技术栈 + +> 原理已经差不多。接下来应该是学习技术。进行实践 + +- 语言基础 + - [x] Python + - [x] numpy + - [x] scipy + - [x] pandas + - [x] matplotlib +- 机器学习基础 + - [x] sklearn +- 深度学习基础 + - [ ] TensorFlow + - [ ] tensorflow federated + +## 收获 diff --git a/工作日志/2021年3月22日-今日计划.md b/工作日志/2021年3月22日-今日计划.md index 689662fe..70f47081 100644 --- a/工作日志/2021年3月22日-今日计划.md +++ b/工作日志/2021年3月22日-今日计划.md @@ -1,3 +1,5 @@ +## 计划 + 1. 每天sklearn一个机器学习小算法 - [x] 支持向量机(学习原理、sklearn实践 - [ ] 、tensorflow malware) @@ -8,4 +10,36 @@ 3. 每天一篇联邦学习的文章。 - [ ] CIC动态数据处理和静态数据处理方式 4. 每天数据集处理一小步。 - - [ ] 实现动态数据处理 \ No newline at end of file + - [ ] 实现动态数据处理 + +## 收获 + +1. 对分类的所有方法包括原理和基本的原理实现numpy进行了总结。主要参考机器学习实践。主要包括以下六种分类方法。没有更多了。这里的机器学习算法,既包括模型,也包括模型的训练算法。 + 1. k近邻:基于邻居的机器学习算法:KNN + 2. 决策树:基于树和信息增益的机器学习算法:DT + 3. 朴素贝叶斯:基于贝叶斯定力的机器学习算法:NB + 4. 逻辑回归:基于回归的方式处理分类问题: + 5. 支持向量机:基于支持向量的机器学习算法: + 6. 集成方法:基于两种不同的集成方式。bagging和boosting。 +2. 对sklearn进行了学习。 + 1. 主要学习了sklearn的算法核心。这些算法不是单纯的以分类和回归两个类别来进行分类的。而是以算法的核心思想来进行分类的。比如基于邻居的既可以聚类也可以分类,基于树的可以分类也可以回归。即以算法的思想进行分包。而不是以算法处理的问题类别。包括neighbors/tree/naive_bayes/linear_model/svm/esemble六个机器学习核心。 + 1. neighbors在第二章基于邻居的方法中有说明sklearn.neighbors.KNNClassifier + 2. tree第四章前两节 sklearn.tree.DeceisionTreeClassifier + 3. naive_bayes第四章10节sklearn.naive_bayes.GaussianNB/MultinomialNB/BernoulliNB + 4. linear_model.logisticRegression第三章第7节sgdclassier第9节。sklearn.linear_model.logisticRegression + 5. svm第四章第5节sklearn.svm.SVC + 6. esemeble第四章34节只有randomforest。sklearn.esemble.RandomForestClassifier/AdaBoost + 2. 区分了随机梯度下降算法和以上方法的区别。以上方法都有其模型算法的核心。并非随机梯度下降。在linear_model.SGDClassifier中以logisticsRegression和SVM等算法为核心。进行梯度下降算法。梯度下降算法是一种模型训练算法,而非模型本身。默认是用SVM进行梯度下降,主要解决数据过大的问题。linear_model.SGDRegression主要是用SGD来处理回归问题。 + 3. 关于多分类问题的处理。主要包括两种方式onevsone和onevsall两种模式。sklearn.multiclass.OneVsRestClassifier/OneVsOneClassifier +3. 学习了模型预处理和评估的方法。主要包括以下两部分 + 1. sklearn中的Dataset加载和使用。sklear.datasets + 2. 数据的标准化和归一化(正则标准化和minmax标准化)sklearn.procession.minmax_scale/normalize + 3. 处理数据缺失值的方法sklearn.impute.kNNimpute... + 4. 构建词向量的方法。可以一键构建词向量。sklearn.feature_extraction.from_graph/from_text + 5. 数据降维的方法:PCA、SVD、因子分析法sklearn.decomposition.PCA/SVD + 6. 数据处理流的方法。sklearn.Pipeline.pipeline + 7. 模型评估的方法sklearn.metrics.roc/auc/f1_score + 8. 关于半监督的处理方式。主要包括标签传递算法等。sklearn.semi_supervised + 9. 模糊机器学习算法。让数据在数据周围进行微小的扰动。添加高斯模糊或者bayes模糊。sklearn.mixture + 10. 模型选择的方法。交叉验证sklearn.modelselection.kfold + 11. 特征选择的方法。sklearn.feature_selectiron.* diff --git a/机器学习/殷康龙/机器学习开发日志/3 两种生成随机布尔屏蔽.ipynb b/机器学习/殷康龙/机器学习开发日志/3 两种生成随机布尔屏蔽.ipynb index 5cad24e2..26b95bdb 100644 --- a/机器学习/殷康龙/机器学习开发日志/3 两种生成随机布尔屏蔽.ipynb +++ b/机器学习/殷康龙/机器学习开发日志/3 两种生成随机布尔屏蔽.ipynb @@ -10,17 +10,13 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.3-final" + "version": "3.8.0-final" }, "orig_nbformat": 2, "kernelspec": { "name": "python3", - "display_name": "Python 3.7.3 64-bit (conda)", - "metadata": { - "interpreter": { - "hash": "7b4b4feff2f24a0f0a34464dbe537a36fda679851528fb8735cb41fa49dffb2d" - } - } + "display_name": "Python 3", + "language": "python" } }, "nbformat": 4, @@ -52,6 +48,13 @@ "print(mask)" ] }, + { + "source": [ + "## 2 np.random.binomial" + ], + "cell_type": "markdown", + "metadata": {} + }, { "cell_type": "code", "execution_count": 5, @@ -69,6 +72,30 @@ "mask = np.random.binomial(n=1,p=0.3,size=[3,4]).astype(bool)\n", "print(mask)" ] + }, + { + "source": [ + "## 3 使用shuffle" + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "# 创建数据集\n", + "N =1000\n", + "holdout = 200\n", + "from sklearn.datasets import make_regression\n", + "X,y = make_regression(1000,shuffle=True)\n", + "\n", + "# 分割数据集的第二种方法。\n", + "X_h,y_h = X[:holdout],y[:holdout]\n", + "X_t,y_t = X[holdout:],y[holdout:]" + ] } ] } \ No newline at end of file diff --git a/机器学习/殷康龙/机器学习开发日志/4 sklearn中的sgd说明.ipynb b/机器学习/殷康龙/机器学习开发日志/4 sklearn中的sgd说明.ipynb new file mode 100644 index 00000000..dd031ece --- /dev/null +++ b/机器学习/殷康龙/机器学习开发日志/4 sklearn中的sgd说明.ipynb @@ -0,0 +1,120 @@ +{ + "metadata": { + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.0-final" + }, + "orig_nbformat": 2, + "kernelspec": { + "name": "python3", + "display_name": "Python 3.8.0 64-bit", + "metadata": { + "interpreter": { + "hash": "38740d3277777e2cd7c6c2cc9d8addf5118fdf3f82b1b39231fd12aeac8aee8b" + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 2, + "cells": [ + { + "source": [ + "# Scikit-learn——LogisticRegression与SGDClassifier\n", + "\n", + "## 1 sklearn.linear_model.logistic regression\n", + "\n", + "* 一般来说,逻辑回归用梯度下降算法来求解参数比较常见;所以这也导致一开始误以为LogisticRegression模型就是用梯度下降算法来实现的,当遇到SGDClassifier(Stochastic Gradient Descent)随机梯度下降分类器的时候,就有点蒙了。梯度下降明明是一个求解算法,怎么就和分类器扯上关系了。原来SGDClassifier是一系列采用了梯度下降来求解参数的算法的集合,例如(SVM, logistic regression)等;\n", + "\n", + "* 而sklearn中,LogisticRegression的实现方法是基于“liblinear”, “newton-cg”, “lbfgs” and “sag”这些库来实现的,当数据集特别大的时候,推荐使用SGDClassifier中的逻辑回归。下面简单介绍一下LogisticRegression的使用。\n", + "\n", + "```\n", + "lr=LogisticRegression() # 初始化模型\n", + "lr.fit(X_train,y_train) # 拟合\n", + "```" + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "source": [ + "## 2 sklearn.linear_model.SGDClassifier\n", + "\n", + "* SGDClassifier是一个用随机梯度下降算法训练的线性分类器的集合。默认情况下是一个线性(软间隔)支持向量机分类器。顺便说一句,有人可能会疑惑:大多数SVM的求解不都是用的SMO算法么?怎么这儿又跑来一个SGD算法。原因是因为,支持向量机的另一个解释就是最小化合页损失函数(详见李航统计学习方法P113)。因此,该损失函数同样可以通过梯度下降算法来求解参数。下面是SGDClassifier的基本使用方法:\n", + "\n", + "* 需要注意的是,梯度下降对数据的范围异常敏感,所有要先进行Feature scaling" + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "output_type": "error", + "ename": "SyntaxError", + "evalue": "unexpected EOF while parsing (, line 44)", + "traceback": [ + "\u001b[1;36m File \u001b[1;32m\"\"\u001b[1;36m, line \u001b[1;32m44\u001b[0m\n\u001b[1;33m print((classification_report(y_test,sgdc_pre,target_names=['Benign','Malignant']))\u001b[0m\n\u001b[1;37m ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m unexpected EOF while parsing\n" + ] + } + ], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "from sklearn.cross_validation import train_test_split\n", + "from sklearn.preprocessing import StandardScaler\n", + "from sklearn.linear_model import LogisticRegression\n", + "from sklearn.linear_model import SGDClassifier\n", + "from sklearn.metrics import classification_report\n", + "\n", + "column_name=['Sample code number','Clump Thickness','Uniformity of Cell Size',\n", + "'Uniformity of Cell Shape','Marginal Adhesion','Single Epithelial Cell Size',\n", + "'Bare Nuclei','Bland Chromatin','Normal Nucleoli','Mitoses','Class']\n", + "\n", + "data=pd.read_csv('./DataSets/breast-cancer-wisconsin.data',names=column_name) \n", + "# 读取数据集\n", + "\n", + "data=data.replace(to_replace='?',value=np.nan) \n", + "#将缺失值替换成NAN,(原始数据集缺失值用的是问号)\n", + "\n", + "data=data.dropna(how='any') \n", + "# 去掉所有包含缺失值的样本点\n", + "\n", + "X_train,X_test,y_train,y_test=train_test_split(data[column_name[1:10]],data[column_name[10]],test_size=0.25,random_state=33) \n", + "# 取前10列为X,第10列为y,并且分割;random_state参数的作用是为了保证每次运行程序时都以同样的方式进行分割\n", + "\n", + "#print y_train.value_counts() # 查看分割后的数据集\n", + "#print y_test.value_counts()\n", + "\n", + "ss=StandardScaler() \n", + "#feature scaling \n", + "X_train=ss.fit_transform(X_train)\n", + "X_test=ss.fit_transform(X_test)\n", + "\n", + "\n", + "\n", + "lr=LogisticRegression()\n", + "lr.fit(X_train,y_train)\n", + "lr_pre=lr.predict(X_test)\n", + "print(lr.score(X_test,y_test))\n", + "print(classification_report(y_test,lr_pre,target_names=['Benign','Malignant']))\n", + "sgdc=SGDClassifier(loss='log')\n", + "sgdc.fit(X_train,y_train)\n", + "sgdc_pre = sgdc.predict(X_test)\n", + "print(sgdc.score(X_test,y_test))\n", + "print((classification_report(y_test,sgdc_pre,target_names=['Benign','Malignant']))" + ] + } + ] +} \ No newline at end of file