{"id":443701,"date":"2024-12-28T03:03:53","date_gmt":"2024-12-28T03:03:53","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=443701"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=443701","title":{"rendered":"<span>\u041f\u0438\u0448\u0435\u043c \u0441\u0432\u043e\u0439 PyTorch \u043d\u0430 NumPy. \u0427\u0430\u0441\u0442\u044c 3. \u0421\u0442\u0440\u043e\u0438\u043c \u0433\u0440\u0430\u0444 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><strong>PyTorch<\/strong>\u00a0\u2014 \u044d\u0442\u043e \u043c\u043e\u0449\u043d\u044b\u0439 \u0438 \u0433\u0438\u0431\u043a\u0438\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f \u043c\u0430\u0448\u0438\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f, \u0448\u0438\u0440\u043e\u043a\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u0435\u0439\u0440\u043e\u043d\u043d\u044b\u0445 \u0441\u0435\u0442\u0435\u0439. \u041e\u043d \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u0435\u043d \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f, \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0433\u0440\u0430\u0444\u0430\u043c \u0438 \u0431\u043e\u0433\u0430\u0442\u043e\u0439 \u044d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0435\u0439. \u0414\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430, \u0447\u0430\u0441\u0442\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u043c\u0430\u0448\u0438\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f.<\/p>\n<p>\u041d\u043e \u0410\u043d\u0434\u0440\u0435\u0439 \u041a\u0430\u0440\u043f\u0430\u0442\u044b, \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0418\u0418, \u0441\u0447\u0438\u0442\u0430\u0435\u0442, \u0447\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u0441 \u043d\u0443\u043b\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043d\u044f\u0442\u044c \u0438\u0445 \u0441\u0443\u0442\u044c \u0438 \u0434\u0435\u0442\u0430\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u044b, \u0447\u0442\u043e \u0441\u043b\u043e\u0436\u043d\u043e \u043e\u0441\u043e\u0437\u043d\u0430\u0442\u044c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438. \u042d\u0442\u043e \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0440\u0430\u0437\u0432\u0438\u0442\u044c \u0438\u043d\u0442\u0443\u0438\u0446\u0438\u044e \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u0432. \u0410\u043d\u0434\u0440\u0435\u0439 \u043f\u043e\u0441\u0432\u044f\u0449\u0430\u0435\u0442 \u043c\u043d\u043e\u0433\u043e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0447\u0442\u043e\u0431\u044b \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u0442\u044c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u044b \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0435\u0439\u0440\u043e\u0441\u0435\u0442\u0435\u0439 \u0432 \u0441\u0432\u043e\u0438\u0445\u00a0<a href=\"https:\/\/karpathy.ai\/\" rel=\"noopener noreferrer nofollow\">\u0431\u043b\u043e\u0433\u0430\u0445<\/a>\u00a0\u0438 \u043d\u0430 \u0441\u0432\u043e\u0451\u043c\u00a0<a href=\"https:\/\/www.youtube.com\/@AndrejKarpathy\" rel=\"noopener noreferrer nofollow\">\u044e\u0442\u0443\u0431-\u043a\u0430\u043d\u0430\u043b\u0435<\/a>. \u041e\u043d \u0442\u0430\u043a\u0436\u0435 \u043d\u0435 \u0440\u0430\u0437 \u043f\u043e\u0434\u0447\u0435\u0440\u043a\u0438\u0432\u0430\u043b, \u0447\u0442\u043e \u043d\u0430 \u0435\u0433\u043e \u043a\u0443\u0440\u0441\u0435 \u0432\u00a0<a href=\"https:\/\/cs.stanford.edu\/people\/karpathy\/\" rel=\"noopener noreferrer nofollow\">C\u0442\u044d\u043d\u0444\u043e\u0440\u0434\u0435<\/a>\u00a0\u0435\u0441\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0438 \u043f\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0435 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u0435.<\/p>\n<p>\u042f \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u043f\u043e\u0441\u0432\u044f\u0442\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e \u044d\u0442\u043e\u0439 \u0438\u0434\u0435\u0438, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043c\u043d\u0435 \u0441\u0430\u043c\u043e\u043c\u0443 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u043a\u043e\u043f\u0430\u0442\u044c\u0441\u044f \u0432 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430\u0445 \u0433\u043b\u0443\u0431\u043e\u043a\u043e\u0433\u043e \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f. \u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435\u00a0<a href=\"https:\/\/habr.com\/ru\/articles\/869520\/\" rel=\"noopener noreferrer nofollow\">\u0432\u0442\u043e\u0440\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438<\/a><\/p>\n<p>\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b:<\/p>\n<ul>\n<li>\n<p>\u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c \u0430\u043d\u0430\u043b\u043e\u0433\u00a0<code>pytorch.tensor()<\/code><\/p>\n<\/li>\n<li>\n<p>\u043f\u0435\u0440\u0435\u0432\u0435\u0434\u0451\u043c \u0432\u0441\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043d\u0430 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0433\u0440\u0430\u0444<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u043e\u0432\u0435\u0434\u0451\u043c \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e\u0435\u0445\u0430\u043b\u0438!<\/p>\n<p><strong>Note!<\/strong><br \/>\u041f\u0435\u0440\u0435\u0434 \u043d\u0430\u0447\u0430\u043b\u043e\u043c \u0447\u0442\u0435\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u044c\u0438 \u044f \u043a\u0440\u0430\u0439\u043d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043a \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0432\u0438\u0434\u0435\u043e \u043f\u043e \u0442\u0435\u043c\u0435 <strong>\u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0433\u0440\u0430\u0444 <\/strong>\u0438 \u0447\u0442\u0435\u043d\u0438\u044e \u0441\u0442\u0430\u0442\u044c\u0438<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=dZIk8a1Dquc&amp;list=PLZu_eiiJs4b4hNw-YPz6I3sXY63K31ZYc&amp;index=29\" rel=\"noopener noreferrer nofollow\">\u043f\u0435\u0440\u0432\u043e\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=RbENpxoFA4A&amp;list=PLZu_eiiJs4b4hNw-YPz6I3sXY63K31ZYc&amp;index=30\" rel=\"noopener noreferrer nofollow\">\u0432\u0442\u043e\u0440\u043e\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=wG_nF1awSSY&amp;list=PLZu_eiiJs4b4hNw-YPz6I3sXY63K31ZYc&amp;index=52\" rel=\"noopener noreferrer nofollow\">\u0442\u0440\u0435\u0442\u044c\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=4wgXBr7fnQg&amp;list=PLZu_eiiJs4b4hNw-YPz6I3sXY63K31ZYc&amp;index=50\" rel=\"noopener noreferrer nofollow\">\u0447\u0435\u0442\u0432\u0435\u0440\u0442\u043e\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/sidsite.com\/posts\/autodiff\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u044f<\/a> <\/p>\n<\/li>\n<\/ul>\n<p>\u042f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0434\u0435\u0438 \u0438\u0437 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043a\u0430\u043a \u0431\u0430\u0437\u0443 \u0434\u043b\u044f \u0441\u0432\u043e\u0438\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0435\u0449\u0435 \u0440\u0430\u0437 \u0433\u043b\u044f\u043d\u0435\u043c \u043e\u0442\u0440\u044b\u0432\u043e\u043a \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u043a\u043e\u0434\u0430!<\/p>\n<pre><code class=\"python\">class SimpleConvNet(Module):     def __init__(self):         ...              def forward(self, x):         x = self.conv1(x)         x = self.relu(x)         x = self.maxpool1(x)         x = self.conv2(x)         x = self.relu(x)         x = self.maxpool2(x)         x = self.flatten(x)         x = self.linear1(x)         x = self.relu(x)         x = self.linear2(x)         return x <\/code><\/pre>\n<p>\u041f\u043e\u0434\u0443\u043c\u0430\u0439\u0442\u0435, \u043a\u0430\u043a\u0438\u0435 \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u043b\u0443\u0447\u0430\u0438 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0438\u0437 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u044f?<\/p>\n<p>\u042f \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438\u0434\u0435\u0439:<\/p>\n<ol>\n<li>\n<p>\u0427\u0442\u043e \u0435\u0441\u043b\u0438 \u043c\u044b \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0432\u043d\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u043d\u0430\u043c\u0438 \u0441\u043b\u043e\u0451\u0432? \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"python\">class SimpleConvNet(Module):     def __init__(self):         ...              def forward(self, x):         x = self.conv1(x)         x = self.relu(x)         x = self.maxpool1(x)         x = self.conv2(x)         x = self.relu(x)         x = x * 2          x = self.maxpool2(x)         x = x ** 2         x = self.flatten(x)         x = self.linear1(x)         x = self.relu(x)         x = x + 1         x = self.linear2(x)         return x <\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0432\u0433\u043b\u044f\u0434\u0438\u0442\u0435\u0441\u044c \u0432 \u043c\u0435\u0442\u043e\u0434 <code>.backward()<\/code> \u043a\u043b\u0430\u0441\u0441\u0430 <code>CrossEntropyLoss<\/code>, \u0442\u043e \u043f\u043e\u0439\u043c\u0435\u0442\u0435, \u0447\u0442\u043e \u043c\u044b \u043d\u0435 \u0443\u043c\u0435\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0441\u043b\u0443\u0447\u0430\u0438 \u043a\u043e\u0433\u0434\u0430 \u043d\u0430\u0448\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u0432\u043d\u0435 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 <code>Linear<\/code>, <code>Conv2d<\/code>, <code>BatchNorm2d<\/code> \u0438 \u0442.\u0434. \u0415\u0441\u043b\u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043d\u044b\u0439 \u0441\u043f\u0443\u0441\u043a, \u0442\u043e \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0442\u0430\u043a, \u043a\u0430\u043a \u0431\u0443\u0434\u0442\u043e \u044d\u0442\u0438\u0445 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0445 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439 <strong>\u043d\u0435<\/strong> \u0431\u044b\u043b\u043e, \u0447\u0442\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e \u043d\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u0442 \u043d\u0438 \u043a \u0447\u0435\u043c\u0443 \u0445\u043e\u0440\u043e\u0448\u0435\u043c\u0443. \u0410 \u0435\u0441\u043b\u0438 \u043c\u044b \u0435\u0449\u0435 \u043a\u0430\u043a\u0438\u043c-\u0442\u043e \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u0435\u043d\u044f\u043b\u0438 \u0440\u0430\u0437\u043c\u0435\u0440 \u043d\u0430\u0448\u0438\u0445 \u043c\u0430\u0442\u0440\u0438\u0446, \u0442\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0432\u043e\u043e\u0431\u0449\u0435 \u0443\u043f\u0430\u0434\u0451\u0442 \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439.<\/p>\n<ol start=\"2\">\n<li>\n<p>\u0412\u0441\u043f\u043e\u043c\u043d\u0438\u0442\u0435, \u043a\u0430\u043a \u043c\u044b \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043b\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043e\u0432? \u041c\u044b \u0438\u0445 \u0441\u0447\u0438\u0442\u0430\u043b\u0438 \u043d\u0430 \u0431\u0443\u043c\u0430\u0433\u0435, \u0430 \u043f\u043e\u0442\u043e\u043c \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u043b\u0438 \u0432 \u043a\u043e\u0434\u0435. \u0422\u0430\u043a \u0431\u044b\u043b\u043e \u0441 \u043b\u0438\u043d\u0435\u0439\u043d\u044b\u043c\u0438 \u0441\u043b\u043e\u044f\u043c\u0438, \u0441\u0432\u0451\u0440\u0442\u043e\u0447\u043d\u044b\u043c\u0438 \u0441\u043b\u043e\u044f\u043c\u0438, \u0441\u043b\u043e\u044f\u043c\u0438 \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \u041d\u043e \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u044b \u0437\u0430\u0445\u043e\u0442\u0438\u043c \u0447\u0442\u043e-\u0442\u043e \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u043e\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c, \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e <strong>\u0443\u0442\u043e\u043d\u0438\u043c<\/strong> \u0432 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0445 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f\u0445 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043e\u0432! \u0412\u043e\u0442, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u044f \u0441\u0447\u0438\u0442\u0430\u043b \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044b \u0434\u043b\u044f <code>RNN<\/code>.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/60b\/a6d\/ede\/60ba6dedea1577de392b2f5028f46971.png\" width=\"960\" height=\"1280\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/60b\/a6d\/ede\/60ba6dedea1577de392b2f5028f46971.png\"\/><\/figure>\n<p>\u0418 \u044d\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0430\u043c\u0430\u044f \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0435\u043a\u0443\u0440\u0440\u0435\u043d\u0442\u043d\u044b\u0445 \u0441\u043b\u043e\u0435\u0432, \u0434\u043b\u044f LSTM \u0438 GRU &#8212; \u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 <strong>\u0435\u0449\u0451<\/strong> \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u044f \u0441\u043e\u043c\u043d\u0435\u0432\u0430\u044e\u0441\u044c \u0447\u0442\u043e-\u0442\u043e \u0432\u043e\u043e\u0431\u0449\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u0432\u044b\u043f\u0438\u0441\u0430\u0442\u044c \u0444\u043e\u0440\u043c\u0443\u043b\u044b. \u0410 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0447\u0435\u0442\u0441\u044f! \u0417\u043d\u0430\u0447\u0438\u0442 \u043d\u0430\u0434\u043e \u0447\u0442\u043e-\u0442\u043e \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u0442\u044c!<\/p>\n<\/li>\n<li>\n<p> \u041d\u0435\u0442 \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u0438! \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0434\u0443\u043c\u0430\u0442\u044c \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442!<\/p>\n<p>\u041d\u0430\u043c \u0445\u043e\u0447\u0435\u0442\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0441\u0430\u043c\u0430 \u0441\u0447\u0438\u0442\u0430\u043b\u0430 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044b! \u0422\u043e\u0447\u043d\u043e \u0442\u0430\u043a\u0436\u0435, \u043a\u0430\u043a \u043c\u044b \u0432\u043e\u0437\u043b\u043e\u0436\u0438\u043b\u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043e\u0432 \u043d\u0430 \u043c\u0435\u0442\u043e\u0434 <code>.backward()<\/code> \u0432 \u0441\u043b\u043e\u044f\u0445, \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0430 <code>.backward()<\/code> &#8212; \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0432\u043e\u0437\u043b\u043e\u0436\u0438\u0442\u044c \u0432\u043e\u043e\u0431\u0449\u0435 \u0432\u0441\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f!<\/p>\n<\/li>\n<\/ol>\n<p>\u0412\u0441\u0435 \u043d\u0430\u0448\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0440\u0435\u0448\u0438\u0442\u044c \u0433\u0440\u0430\u0444 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439!<\/p>\n<p><strong>Computational Graph<\/strong><\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0432\u0441\u0435 \u043d\u0430\u0448\u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0432 \u0432\u0438\u0434\u0435 \u0433\u0440\u0430\u0444\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440!<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1d9\/b48\/c7a\/1d9b48c7a3e38a37fa7cebcd468e1e7f.png\" width=\"688\" height=\"550\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/1d9\/b48\/c7a\/1d9b48c7a3e38a37fa7cebcd468e1e7f.png\"\/><\/figure>\n<p>\u0412 \u0443\u0437\u043b\u0430\u0445 \u0431\u0443\u0434\u0443\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043b\u0438\u0431\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438. \u0423\u0437\u0435\u043b \u0432 \u0441\u0438\u043d\u0435\u043c \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0438\u043a\u0435 \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0441\u0435\u0431\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e, \u0447\u0442\u043e \u0431\u044b\u043b\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f &#171;\u0441\u043b\u043e\u0436\u0435\u043d\u0438\u0435&#187;, \u0434\u0432\u0443\u0445 \u0447\u0438\u0441\u0435\u043b <code>a<\/code> \u0438 <code>b<\/code>, \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 &#8212; \u0447\u0438\u0441\u043b\u043e <code>c<\/code>.<br \/>\u0423\u0437\u0435\u043b \u0432 \u043a\u0440\u0430\u0441\u043d\u043e\u043c \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0438\u043a\u0435 \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0441\u0435\u0431\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e, \u0447\u0442\u043e \u0431\u044b\u043b\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f &#171;\u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0435&#187;, \u0434\u0432\u0443\u0445 \u0447\u0438\u0441\u0435\u043b <code>b<\/code> \u0438 <code>c<\/code>, \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 &#8212; \u0447\u0438\u0441\u043b\u043e <code>f<\/code>.<br \/>\u041f\u043e\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0435 \u0442\u0430\u043a\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/73d\/19e\/76e\/73d19e76e740135ee6c0b7b35100eb4d.png\" width=\"1251\" height=\"523\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/73d\/19e\/76e\/73d19e76e740135ee6c0b7b35100eb4d.png\"\/><\/figure>\n<p>\u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u043a\u0440\u0430\u0441\u0438\u0432\u0443\u044e \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e <a href=\"https:\/\/en.wikipedia.org\/wiki\/Chain_rule\" rel=\"noopener noreferrer nofollow\">chain rule<\/a>!<\/p>\n<p>\u041a\u043b\u044e\u0447\u0435\u0432\u0430\u044f \u0438\u0434\u0435\u044f \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043b\u0435 \u043a\u0430\u0436\u0434\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043d\u043e \u0438 \u0441\u0440\u0430\u0437\u0443 \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0435.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/575\/6d3\/713\/5756d371372ea6f9463d46a4955a9abf.png\" width=\"745\" height=\"358\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/575\/6d3\/713\/5756d371372ea6f9463d46a4955a9abf.png\"\/><\/figure>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>c<\/code> = <code>a<\/code> + <code>b<\/code>. \u0422\u043e\u0433\u0434\u0430 \u0432 <code>c<\/code> \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u0430\u043c\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>c<\/code>, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0435 \u043e\u0442 <code>a<\/code> \u0438 <code>b<\/code>, \u0442\u043e \u0435\u0441\u0442\u044c (<code>c<\/code>, <code>1<\/code>, <code>1<\/code>)<br \/>\u0414\u043b\u044f <code>c = a * b<\/code> \u0431\u0443\u0434\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c (<code>c<\/code>, <code>b<\/code>, <code>a<\/code>), \u0434\u043b\u044f <code>c = a \/ b<\/code>, \u0431\u0443\u0434\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c (<code>c<\/code>, <code>1 \/ b<\/code>, <code>-a \/ b^2<\/code>) &#8212; \u043b\u043e\u0433\u0438\u043a\u0430 \u044f \u043d\u0430\u0434\u0435\u044e\u0441\u044c \u0441\u0442\u0430\u043b\u0430 \u043f\u043e\u043d\u044f\u0442\u043d\u0430.<br \/>\u041a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0432\u0441\u0435 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0438 \u0438\u0445 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0435, \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u043b\u044e\u0431\u044b\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0438 \u0431\u0440\u0430\u0442\u044c \u043b\u044e\u0431\u044b\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0435 \u043e\u0442 \u043d\u0438\u0445, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043c\u044b \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u0441\u0447\u0438\u0442\u0430\u0435\u043c \u0441\u0432\u043e\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442 &#8212; \u0430 \u044d\u0442\u043e \u0437\u0430\u0434\u0430\u0447\u0430 \u0441\u0438\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0449\u0435, \u0447\u0435\u043c \u0431\u0440\u0430\u0442\u044c \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442 \u043e\u0442 \u0438\u0442\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f. \u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0437 \u0436\u0438\u0437\u043d\u0438. \u0412\u044b \u0447\u0438\u0442\u0430\u0435\u0442\u0435 \u043c\u043d\u043e\u0433\u043e \u043a\u043d\u0438\u0433 \u0440\u0430\u0437\u043d\u044b\u0445 \u0436\u0430\u043d\u0440\u043e\u0432. \u041d\u043e \u0432\u044b \u0442\u0430\u043a\u0436\u0435 \u0445\u043e\u0442\u0438\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u043a\u0430\u0436\u0434\u044b\u0439 \u0436\u0430\u043d\u0440 \u043b\u0435\u0436\u0430\u043b \u0432 \u0441\u0432\u043e\u0435\u0439 \u043f\u043e\u043b\u043a\u0435. \u0427\u0442\u043e \u043f\u0440\u043e\u0449\u0435 &#8212; \u043f\u043e\u0441\u043b\u0435 \u043f\u0440\u043e\u0447\u0442\u0435\u043d\u0438\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043a\u043d\u0438\u0433\u0438 \u043a\u043b\u0430\u0441\u0442\u044c \u0432 \u043d\u0443\u0436\u043d\u0443\u044e \u043f\u043e\u043b\u043a\u0443 \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u0431\u0438\u0440\u0430\u0442\u044c \u0446\u0435\u043b\u0443\u044e \u0441\u0442\u043e\u043f\u043a\u0443 \u043d\u0430\u043a\u043e\u043f\u0438\u0432\u0448\u0438\u0445\u0441\u044f \u043a\u043d\u0438\u0433? \u0422\u0430\u043a\u0436\u0435 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0438 \u0437\u0434\u0435\u0441\u044c<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b07\/271\/53a\/b0727153aa0cb91fc4f316bd54775a73.png\" width=\"633\" height=\"124\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b07\/271\/53a\/b0727153aa0cb91fc4f316bd54775a73.png\"\/><\/figure>\n<p>\u041f\u0440\u043e\u0449\u0435 \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u0443\u044e \u0432\u0441\u0435\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438\u043b\u0438 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u0442 <code>x1\/x2<\/code>, \u043f\u043e\u0442\u043e\u043c \u043e\u0442 <code>sin(x)<\/code>, \u043f\u043e\u0442\u043e\u043c <code>exp(x2)<\/code> \u0438 \u0432 \u043a\u043e\u043d\u0446\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u043c\u043d\u043e\u0436\u0438\u0442\u044c \u0438\u0445 \u043f\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u0443 chain rule?<\/p>\n<p>\u0417\u0430\u0433\u043b\u044f\u043d\u0435\u043c <a href=\"https:\/\/sidsite.com\/posts\/autodiff\/#:~:text=A%20variable%20(or,the%20child%20variable.\" rel=\"noopener noreferrer nofollow\">\u0441\u044e\u0434\u0430<\/a><\/p>\n<p>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f (\u0438\u043b\u0438 \u0443\u0437\u0435\u043b) \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0434\u0432\u0435 \u0447\u0430\u0441\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<ul>\n<li>\n<p><strong>value<\/strong> \u2014 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439.<\/p>\n<\/li>\n<li>\n<p><strong>local_gradients<\/strong> \u2014 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u00ab\u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0435\u00bb.<\/p>\n<\/li>\n<\/ul>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>get_gradients<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 <code>local_gradients<\/code> \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0433\u043e \u043e\u0431\u0445\u043e\u0434\u0430 \u0433\u0440\u0430\u0444\u0430, \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u044f \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044b. (<em>\u0422. \u0435. <\/em><code>local_gradients<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0435\u0441\u0442\u044c \u0441\u0432\u043e\u0438 <code>local_gradients<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0435\u0441\u0442\u044c \u0441\u0432\u043e\u0438 <code>local_gradients<\/code>, \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435.)<\/p>\n<p>\u0413\u0440\u0430\u0434\u0438\u0435\u043d\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442\u0441\u044f \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043f\u0440\u0430\u0432\u0438\u043b:<\/p>\n<ol>\n<li>\n<p>\u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0443\u0442\u0438 \u043e\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043a \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0443\u043c\u043d\u043e\u0436\u044c\u0442\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0440\u0451\u0431\u0435\u0440 \u043f\u0443\u0442\u0438 (\u0447\u0442\u043e \u0434\u0430\u0451\u0442 <code>path_value<\/code>).<\/p>\n<\/li>\n<li>\n<p>\u0421\u043b\u043e\u0436\u0438\u0442\u0435 \u0432\u0441\u0435 <code>path_value<\/code> \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0443\u0442\u0438.<\/p>\n<\/li>\n<\/ol>\n<p>\u2026 \u042d\u0442\u043e \u0434\u0430\u0451\u0442 \u0447\u0430\u0441\u0442\u043d\u0443\u044e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u0443\u044e \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0441\u043a\u0435\u043b\u0435\u0442 \u0431\u0443\u0434\u0443\u0449\u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430!<\/p>\n<pre><code class=\"python\">class Tensor:     def __init__(self, value, local_gradients=None):         self.value = value         self.local_gradients = local_gradients <\/code><\/pre>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e \u0441\u043b\u043e\u0436\u0435\u043d\u0438\u044f!<\/p>\n<pre><code class=\"python\">class Tensor:     def __init__(self, value, local_gradients=None):         self.value = value         self.local_gradients = local_gradients              def __add__(self, other):         value = self.value + other.value         local_gradients = ((self, 1), (other, 1))         return Tensor(value, local_gradients) <\/code><\/pre>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0443<\/p>\n<pre><code class=\"python\">a = Tensor(5) b = Tensor(10) c = a + b c, c.value, c.local_gradients &gt;&gt;&gt; (&lt;__main__.Tensor at 0x7d85aad85810&gt;,  15,  ((&lt;__main__.Tensor at 0x7d85aad87160&gt;, 1),   (&lt;__main__.Tensor at 0x7d85aad85660&gt;, 1))) <\/code><\/pre>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0435! \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043c\u0435\u0442\u043e\u0434 <code>.backward()<\/code><\/p>\n<pre><code class=\"python\">from collections import defaultdict      class Tensor:     def backward(self):     # \u0441\u043b\u043e\u0432\u0430\u0440\u044c \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445         gradients = defaultdict(lambda: 0)         # \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043e\u0432 \u0443 \u0434\u0435\u0442\u0435\u0439, \u043f\u043e\u0442\u043e\u043c \u0443 \u0438\u0445 \u0434\u0435\u0442\u0435\u0439 \u0438 \u0442.\u0434.         def compute_gradients(obj, path_value):             if obj.local_gradients: # \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0438 \u0443\u0437\u0435\u043b \u043b\u0438\u0441\u0442\u043e\u043c (leaf)             # \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0440\u0435\u0431\u0435\u043d\u043a\u0430 \u0438 \u0435\u0433\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u0441\u0447\u0438\u0442\u0430\u043d\u043d\u044b\u0439 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442                 for child, local_grad_value in obj.local_gradients:                 # \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c chain rule \u0438 \u0443\u043c\u043d\u043e\u0436\u0430\u0435\u043c \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u043d\u044b\u0439 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442 \u043d\u0430 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442 child                     path_value_to_child = path_value * local_grad_value                     # \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044b \u043e\u0442 \u0440\u0430\u0437\u043d\u044b\u0445 \u043b\u0438\u0441\u0442\u044c\u0435\u0432                     gradients[child] += path_value_to_child                     # \u0441\u0447\u0438\u0442\u0430\u0435\u043c \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0434\u0435\u0442\u0435\u0439 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e child                     compute_gradients(child, path_value_to_child)                      compute_gradients(self, path_value=1)          return gradients <\/code><\/pre>\n<p>\u0421\u043c\u043e\u0442\u0440\u0438\u043c<\/p>\n<pre><code class=\"python\">a = Tensor(5) b = Tensor(10) c = a + b gradients = c.backward() gradients[a], gradients[b] &gt;&gt;&gt; (1, 1)<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u0438\u043c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u044f<\/p>\n<pre><code class=\"python\">def __mul__(self, other): value = self.value * other.value local_gradients = ((self, other.value), (other, self.value)) return Tensor(value, local_gradients) <\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u043e\u0439 \u043f\u043e \u043f\u0435\u0440\u0432\u043e\u043c\u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0443, \u0431\u0443\u0434\u0435\u0442 <strong>\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435<\/strong> \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u0438 \u043d\u0430\u043e\u0431\u043e\u0440\u043e\u0442!<\/p>\n<pre><code class=\"python\">a = Tensor(4) b = Tensor(3) c = a + b # = 4 + 3 = 7 d = a * c # = 4 * 7 = 28  gradients = d.backward()  print('d.value =', d.value) print(\"The partial derivative of d with respect to a =\", gradients[a]) &gt;&gt;&gt; d.value = 28 The partial derivative of d with respect to a = 11 <\/code><\/pre>\n<pre><code class=\"python\">print('gradients[b] =', gradients[b]) print('gradients[c] =', gradients[c]) &gt;&gt;&gt; gradients[b] = 4 gradients[c] = 4 <\/code><\/pre>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0435 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044b<\/p>\n<pre><code class=\"python\">print('dict(d.local_gradients)[a] =', dict(d.local_gradients)[a]) print('dict(d.local_gradients)[c] =', dict(d.local_gradients)[c]) print('dict(c.local_gradients)[a] =', dict(c.local_gradients)[a]) print('dict(c.local_gradients)[b] =', dict(c.local_gradients)[b]) &gt;&gt;&gt; dict(d.local_gradients)[a] = 7 dict(d.local_gradients)[c] = 4 dict(c.local_gradients)[a] = 1 dict(c.local_gradients)[b] = 1 <\/code><\/pre>\n<p>\u0412\u0441\u0451 \u0432\u0435\u0440\u043d\u043e, \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0435\u0440\u0435\u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043d\u0430 \u0431\u0443\u043c\u0430\u0433\u0435!<\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0449\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439!<\/p>\n<pre><code class=\"python\"># \u0432\u044b\u0447\u0438\u0442\u0430\u043d\u0438\u0435 def __sub__(self, other): value = self.value - other.value local_gradients = ((self, 1), (other, -1)) return Tensor(value, local_gradients)  # \u0443\u043d\u0430\u0440\u043d\u044b\u0439 \u043c\u0438\u043d\u0443\u0441 def __neg__(self):  value = -self.value local_gradients = ((self, -1),) return Tensor(value, local_gradients)  # \u0434\u0435\u043b\u0435\u043d\u0438\u0435 def __truediv__(self, other):  value = self.value \/ other.value local_gradients = ((self, 1 \/ other.value), (other, - self.value \/ (other.value**2))) return Tensor(value, local_gradients) <\/code><\/pre>\n<p>\u041f\u043e\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u0443\u044e \u043f\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438<\/p>\n<pre><code class=\"python\">def f(a, b):     return (a \/ b - a) * (b \/ a + a + b) * (a - b)  a = Tensor(230.3) b = Tensor(33.2) y = f(a, b)  gradients = y.backward()  print(\"The partial derivative of y with respect to a =\", gradients[a]) print(\"The partial derivative of y with respect to b =\", gradients[b]) &gt;&gt;&gt; The partial derivative of y with respect to a = -153284.83150602411 The partial derivative of y with respect to b = 3815.0389441500956 <\/code><\/pre>\n<p>\u041c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0435 \u043e\u0446\u0435\u043d\u043a\u0438, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c\u044b\u0445 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432.<\/p>\n<pre><code class=\"python\">delta = Tensor(1e-10) numerical_grad_a = (f(a + delta, b) - f(a, b)) \/ delta numerical_grad_b = (f(a, b + delta) - f(a, b)) \/ delta print(\"The numerical estimate for a =\", numerical_grad_a.value) print(\"The numerical estimate for b =\", numerical_grad_b.value) &gt;&gt;&gt; The numerical estimate for a = -153258.44287872314 The numerical estimate for b = 3837.0490074157715 <\/code><\/pre>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0449\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/p>\n<pre><code class=\"python\"># \u0432\u043e\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0432 \u0441\u0442\u0435\u043f\u0435\u043d\u044c def __pow__(self, power): value = self.value ** power local_gradients = ((self, power * (self.value**(power-1))),) return Tensor(value, local_gradients)  @classmethod def sin(cls, obj): value = np.sin(obj.value) local_gradients = ((obj, np.cos(obj.value)),) return Tensor(value, local_gradients)  @classmethod     def cos(cls, obj): value = np.cos(obj.value) local_gradients = ((obj, -np.sin(obj.value)),) return Tensor(value, local_gradients)  @classmethod def exp(cls, obj): value = np.exp(obj.value) local_gradients = ((obj, value),) return Tensor(value, local_gradients)  @classmethod def log(cls, a): value = np.log(a.value) local_gradients = ( ('log', a, lambda x: x * 1. \/ a.value), ) return Tensor(value, local_gradients) <\/code><\/pre>\n<p>\u0418 \u0435\u0449\u0451 \u0440\u0430\u0437 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c!<\/p>\n<pre><code class=\"python\">def f(a, b):     return ((a ** 2) \/ Tensor.sin(b) - a) * (b \/ a + Tensor.cos(a) + b) * (a - Tensor.exp(b))  a = Tensor(230.3) b = Tensor(33.2) y = f(a, b)  gradients = y.backward()  print(\"The partial derivative of y with respect to a =\", gradients[a]) print(\"The partial derivative of y with respect to b =\", gradients[b])  delta = Tensor(1e-10) numerical_grad_a = (f(a + delta, b) - f(a, b)) \/ delta numerical_grad_b = (f(a, b + delta) - f(a, b)) \/ delta print(\"The numerical estimate for a =\", numerical_grad_a.value) print(\"The numerical estimate for b =\", numerical_grad_b.value)  &gt;&gt;&gt; The partial derivative of y with respect to a = -1.5667411882581273e+19 The partial derivative of y with respect to b = -5.795077766989229e+20  The numerical estimate for a = -1.566703616e+19 The numerical estimate for b = -5.79518464e+20 <\/code><\/pre>\n<p><strong>\u041a\u0440\u0443\u0442\u043e!<\/strong> \u041c\u044b \u0441  \u0432\u0430\u043c\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b\u0438 \u043e\u0434\u043d\u0443 \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u0444\u0443\u043d\u0434\u0430\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0438\u0434\u0435\u0439 \u0432 \u043d\u0435\u0439\u0440\u043e\u043d\u043d\u044b\u0445 \u0441\u0435\u0442\u044f\u0445 &#8212; <strong>\u0433\u0440\u0430\u0444 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439<\/strong>. \u0414\u0430\u043b\u044c\u0448\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043e\u043f\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0430 \u043d\u0435\u0433\u043e, \u0432\u0441\u0451 \u0447\u0442\u043e \u043d\u0430\u043c \u043e\u0441\u0442\u0430\u043d\u0435\u0442\u0441\u044f \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u043c <code>Tensor<\/code> &#8212; \u044d\u0442\u043e \u043f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u0442\u044c \u0435\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044f \u043d\u043e\u0432\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b!<\/p>\n<p>\u041a\u0430\u043a \u0432\u044b \u043f\u043e\u043c\u043d\u0438\u0442\u0435, \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e <strong>\u0412\u0421\u0401<\/strong> \u0432 \u043d\u0435\u0439\u0440\u043e\u043d\u043a\u0430\u0445 &#8212; \u044d\u0442\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043c\u0430\u0442\u0440\u0438\u0446. \u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0435\u0451 \u0432 \u043d\u0430\u0448\u0435\u043c \u043d\u043e\u0432\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435. \u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0435 \u043c\u044b \u0443\u0436\u0435 \u0437\u043d\u0430\u0435\u043c! \u0415\u0441\u043b\u0438 <img decoding=\"async\" class=\"formula inline\" source=\"C = AB\" alt=\"C = AB\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/6\/66\/668\/668262ec6fc9765062d39f653a74efe3.svg\" width=\"auto\" height=\"auto\"\/>,<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"formula\" source=\"\\frac{dL}{dA} = \\frac{dL}{dC} \\cdot \\frac{dC}{dA}\" alt=\"\\frac{dL}{dA} = \\frac{dL}{dC} \\cdot \\frac{dC}{dA}\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/395\/4bc\/398\/3954bc3987a73d25ebed302e89fd106a.svg\" width=\"134\" height=\"43\"\/><\/p>\n<p>\u0414\u043b\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u043e\u0439 \u043f\u043e \u043c\u0430\u0442\u0440\u0438\u0446\u0435 <img decoding=\"async\" class=\"formula inline\" source=\"C\" alt=\"C\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/0\/0d\/0d6\/0d61f8370cad1d412f80b84d143e1257.svg\" width=\"auto\" height=\"auto\"\/> (\u0433\u0434\u0435 <img decoding=\"async\" class=\"formula inline\" source=\"C = AB\" alt=\"C = AB\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/6\/66\/668\/668262ec6fc9765062d39f653a74efe3.svg\" width=\"auto\" height=\"auto\"\/>):<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"formula\" source=\"\\frac{dC}{dA} = B^T\" alt=\"\\frac{dC}{dA} = B^T\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/074\/71b\/cd7\/07471bcd7e0f9c1edb8de0a30483dff1.svg\" width=\"84\" height=\"43\"\/><\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"formula\" source=\"\\frac{dL}{dA} = \\frac{dL}{dC} \\cdot B^T\" alt=\"\\frac{dL}{dA} = \\frac{dL}{dC} \\cdot B^T\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ab2\/a9c\/53e\/ab2a9c53e90fe4da11a085cb3a04c15f.svg\" width=\"129\" height=\"43\"\/><\/p>\n<p>\u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0434\u043b\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u043e\u0439 \u043f\u043e \u043c\u0430\u0442\u0440\u0438\u0446\u0435 <img decoding=\"async\" class=\"formula inline\" source=\"B\" alt=\"B\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/9\/9d\/9d5\/9d5ed678fe57bcca610140957afab571.svg\" width=\"auto\" height=\"auto\"\/>:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"formula\" source=\"\\frac{dL}{dB} = A^T \\cdot \\frac{dL}{dC}\" alt=\"\\frac{dL}{dB} = A^T \\cdot \\frac{dL}{dC}\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/485\/ec2\/92f\/485ec292fb7ad200850d18b11f1343f3.svg\" width=\"0\" height=\"0\"\/><\/p>\n<p>\u041d\u043e \u0435\u0441\u0442\u044c \u043e\u0434\u043d\u0430 \u0437\u0430\u0433\u0432\u043e\u0437\u0434\u043e\u0447\u043a\u0430! \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0435\u0449\u0451 \u0440\u0430\u0437 \u043d\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <code>.backward()<\/code><\/p>\n<pre><code class=\"python\">for child, local_grad_value in obj.local_gradients: path_value_to_child = path_value * local_grad_value gradients[child] += path_value_to_child compute_gradients(child, path_value_to_child)<\/code><\/pre>\n<p>\u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u043c\u044b \u0443\u043c\u043d\u043e\u0436\u0430\u0435\u043c <code>path_value<\/code> \u0438 <code>local_grad_value<\/code>, \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u0430\u0442\u0440\u0438\u0446 \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u043d\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 <code>*<\/code>, \u0430 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 <code>@<\/code>. \u041c\u043e\u0436\u043d\u043e \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u0441\u043b\u0443\u0447\u0430\u0439 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e, \u043d\u043e \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0443\u043c\u043d\u043e. \u041f\u043e\u043a\u0430\u0436\u0443 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435:<\/p>\n<pre><code class=\"python\">def __add__(self, other): value = self.value + other.value local_gradients = ((self, lambda x: x), (other, lambda x: x)) return Tensor(value, local_gradients=local_gradients)<\/code><\/pre>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 <code>local_gradients<\/code> &#8212; \u043d\u0435 \u0441\u0430\u043c\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u043e\u0439, \u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u0448\u0430\u0433\u0430 \u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0434\u043b\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0448\u0430\u0433\u0430. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 <code>x<\/code> \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0430\u043a\u0436\u0435 <code>x<\/code>, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u0430\u044f \u0440\u0430\u0432\u043d\u0430 <code>1<\/code>. \u0414\u043b\u044f \u0432\u044b\u0447\u0438\u0442\u0430\u043d\u0438\u044f<\/p>\n<pre><code class=\"python\">def __sub__(self, other): value = self.value + other.value local_gradients = ((self, lambda x: x), (other, lambda x: -x)) return Tensor(value, local_gradients=local_gradients) <\/code><\/pre>\n<p>\u0414\u043b\u044f \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0441\u043b\u0430\u0433\u0430\u0435\u043c\u043e\u0433\u043e \u043e\u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 <code>x<\/code> \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0430\u043a\u0436\u0435 <code>x<\/code>, \u0430 \u0434\u043b\u044f \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u043e\u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 <code>x<\/code> \u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 <code>-x<\/code>, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u0430\u044f \u0440\u0430\u0432\u043d\u0430 <code>-1<\/code>. \u0422\u0430\u043a\u0436\u0435 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438, \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0434\u043b\u044f \u043e\u0442\u043b\u0430\u0434\u043a\u0438!<\/p>\n<pre><code class=\"python\">def __add__(self, other): value = self.value + other.value local_gradients = (('add', self, lambda x: x), ('add', other, lambda x: x)) return Tensor(value, local_gradients=local_gradients) <\/code><\/pre>\n<p>\u0418\u0442\u0430\u043a, \u043c\u0430\u0442\u0440\u0438\u0447\u043d\u043e\u0435 \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0432 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u043c \u0438\u0442\u043e\u0433\u0435 \u0442\u0430\u043a!<\/p>\n<pre><code class=\"python\">def __matmul__(self, other): value = self.value @ other.value local_gradients = (('matmul', self, lambda x: x @ other.value.T), ('matmul', other, lambda x: self.value.T @ x)) return Tensor(value, local_gradients=local_gradients) <\/code><\/pre>\n<p>\u0418 \u043c\u0435\u0442\u043e\u0434 <code>.backward()<\/code> \u0442\u043e\u0436\u0435 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u0441\u044f \u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u043d\u0430\u0448\u0438\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439.<\/p>\n<pre><code class=\"python\">for operation, child, child_gradient_func in obj.local_gradients: # child_gradient_func \u043a\u0430\u043a \u0440\u0430\u0437 \u0442\u0430 \u0441\u0430\u043c\u0430\u044f lambda \u0444\u0443\u043d\u043a\u0446\u0438\u044f path_value_to_child = child_gradient_func(path_value) gradients[child] += path_value_to_child compute_gradients(child, path_value_to_child) <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0433\u043e\u0442\u043e\u0432\u044b \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u043a \u043d\u0435\u0439\u0440\u043e\u043d\u043d\u044b\u043c \u0441\u043b\u043e\u044f\u043c. \u041d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443!<br \/> \u0412\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u043a \u0441\u0430\u043c\u043e\u043c\u0443 \u043f\u0435\u0440\u0432\u043e\u043c\u0443 \u043f\u0440\u0438\u043c\u0435\u0440\u0443 \u0441 &#171;\u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u043c&#187; \u0441\u043e\u0431\u0430\u043a\u0438. \u0422\u0435\u043f\u0435\u0440\u044c \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0435 \u043e\u0431\u044a\u0435\u043a\u0442 <code>numpy.ndarray<\/code>, \u0430 \u043e\u0431\u044a\u0435\u043a\u0442 \u043d\u0430\u0448\u0435\u0433\u043e \u043d\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 <code>Tensor<\/code><\/p>\n<pre><code class=\"python\">input_x = np.array([[ 0.99197708, -0.77980023, -0.8391331 , -0.41970686,  0.72636492],        [ 0.85901409, -0.22374584, -1.95850625, -0.81685145,  0.96359871],        [-0.42707937, -0.50053309,  0.34049477,  0.62106931, -0.76039365],        [ 0.34206742,  2.15131285,  0.80851759,  0.28673013,  0.84706839],        [-1.70231094,  0.36473216,  0.33631525, -0.92515589, -2.57602677]]) target_x = [1.0, 0.0]  input_tensor = Tensor(input_x) target_tensor = Tensor(target_x) <\/code><\/pre>\n<p>\u041a\u043b\u0430\u0441\u0441 <code>Module<\/code> \u0438 <code>Linear<\/code>  \u043e\u0441\u0442\u0430\u0432\u0438\u043c \u0442\u0430\u043a\u0438\u043c\u0438 \u0436\u0435, \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u0435\u0441\u0430 \u043c\u043e\u0434\u0435\u043b\u0438 \u044d\u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043a\u043b\u0430\u0441\u0441\u0430<code>Tensor<\/code><\/p>\n<pre><code class=\"python\">class Module:     def __init__(self):         self._constructor_Parameter = ParameterObj()         global Parameter         Parameter = self._constructor_Parameter              def forward(self):         pass            def __call__(self, x):         return self.forward(x)            def parameters(self):         return self  class Linear:     def __init__(self, input_channels: int, output_channels: int, bias = True):         self.input_channels = input_channels         self.output_channels = output_channels         self.bias_flag = bias         self.backward_list = []         # \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043a\u043b\u0430\u0441\u0441\u0430 Tensor         self.weight = Tensor(np.random.uniform(- 0.5, 0.5, size=(self.input_channels, self.output_channels)))         self.bias = Tensor(np.random.uniform(- 0.5, 0.5, size=self.output_channels) * bias)         Parameter([self, self.weight, self.bias])              def __call__(self, x: Tensor):         self.x = Tensor(x)         result = x @ Parameter.calling[self][0] + Parameter.calling[self][1]         return result <\/code><\/pre>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043a\u043b\u0430\u0441\u0441\u0430 <code>Tensor<\/code>, \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0438 \u043e\u043d \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c \u044d\u0442\u043e\u0433\u043e \u0436\u0435 \u043a\u043b\u0430\u0441\u0441\u0430 \u0438\u043b\u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 (\u0447\u0438\u0441\u043b\u043e \u0438\u043b\u0438 <code>numpy.ndarray<\/code>) \u0438 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u044c \u0435\u0433\u043e \u0432 \u043e\u0431\u044a\u0435\u043a\u0442 <code>numpy.ndarray<\/code>.\u0422\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0444\u043e\u0440\u043c\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 <code>shape<\/code><\/p>\n<pre><code class=\"python\">class Tensor:     def __init__(self, value, local_gradients=None):         if isinstance(value, Tensor):             self.value = value.value             self.local_gradients = value.local_gradients         else:             self.value = np.array(value)             self.local_gradients = local_gradients         self.shape = self.value.shape <\/code><\/pre>\n<p>\u0421\u043e\u0431\u0435\u0440\u0451\u043c \u043c\u043e\u0434\u0435\u043b\u044c<\/p>\n<pre><code class=\"python\">class SimpleNet(Module):     def __init__(self):         super().__init__()         self.linear1 = Linear(input_channels=5, output_channels=10, bias=True)     def forward(self, x):         return self.linear1(x)  model = SimpleNet() model(input_tensor).shape &gt;&gt;&gt; (5, 10) <\/code><\/pre>\n<p>\u041e\u0442\u043b\u0438\u0447\u043d\u043e, \u043c\u043e\u0434\u0435\u043b\u044c \u0432\u044b\u0434\u0430\u0451\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f! \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0449\u0451 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434!<\/p>\n<p>\u041c\u0435\u0442\u043e\u0434 <code>reshape<\/code>, \u043e\u043d \u043d\u0430\u043c \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0447\u0430\u0441\u0442\u043e \u0431\u0443\u0434\u0435\u043c \u043c\u0435\u043d\u044f\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440\u044b \u043d\u0430\u0448\u0438\u0445 \u0442\u0435\u043d\u0437\u043e\u0440\u043e\u0432:<\/p>\n<pre><code class=\"python\">def reshape(self, *args): local_gradients = (('reshape', self, lambda x: x.reshape(self.shape)),) return Tensor(self.value.reshape(*args), local_gradients=local_gradients)<\/code><\/pre>\n<p>\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435:<br \/> \u0441\u0435\u0439\u0447\u0430\u0441 \u0432\u044b\u0432\u043e\u0434 \u043d\u0430\u0448\u0435\u0433\u043e \u0442\u0435\u043d\u0437\u043e\u0440\u044b \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a, \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043a\u0440\u0430\u0441\u0438\u0432\u043e \u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0432\u043d\u043e:<br \/> <code>&lt;__main__.Tensor at 0x7c2122fce0e0&gt;<\/code><br \/> \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u043c<\/p>\n<pre><code class=\"python\">def __repr__(self): return np.array_repr(self.value)<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c: <code>&gt;&gt;&gt; array(4)<\/code><br \/> \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0449\u0451 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434:<\/p>\n<pre><code class=\"python\"># \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0442\u0435\u043d\u0437\u043e\u0440 \u043d\u0443\u043b\u0435\u0439. \u0412 \u0446\u0435\u043b\u043e\u043c \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0435\u043d\u0437\u043e\u0440\u0430 @classmethod def zeros(cls, shape): return cls(np.zeros(shape))  # C\u043e\u0437\u0434\u0430\u0442\u044c \u0442\u0435\u043d\u0437\u043e\u0440 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f. \u041e\u0447\u0435\u043d\u044c \u0447\u0430\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0435\u0441\u043e\u0432 @classmethod def randn(cls, shape): return cls(np.random.normal(size=shape))  # \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0437\u043d\u0430\u043a \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 relu @classmethod def sign(cls, a): value = np.sign(a.value) return cls(value)  # \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043f\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438 5.0 \u0432 5 @classmethod def int_(cls, *args): return cls(np.int_(*args))  # \u0422\u043e\u0436\u0435 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0447\u0438\u0441\u0435\u043b @classmethod def arange(cls, *args): return cls(np.arange(*args))  # \u0421\u0443\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u043e\u0434\u043d\u0430 \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u0432\u0430\u0436\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439. \u041f\u043e\u0447\u0442\u0438 \u0432\u0435\u0437\u0434\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f @classmethod def sum(cls, array, axis=None, keepdims=False): if not keepdims: # \u041d\u0435 \u0445\u043e\u0442\u0438\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440\u043d\u043e\u0441\u0442\u044c if axis is not None: local_gradients = (('sum', array, lambda x: np.expand_dims(np.array(x), axis=axis) + np.zeros(array.shape)),) return Tensor(np.sum(array.value, axis=axis), local_gradients=local_gradients) else: local_gradients = (('sum', array, lambda x: x + np.zeros(array.shape)),) return Tensor(np.sum(array.value, axis=axis), local_gradients=local_gradients)  else: # \u0425\u043e\u0442\u0438\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440\u043d\u043e\u0441\u0442\u044c value = np.sum(array.value, axis=axis, keepdims=True) * np.ones_like(array.value) local_gradients = (('sum', array, lambda x: x),) return cls(value, local_gradients=local_gradients) # \u043a\u043e\u0434 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0442\u0430\u043d\u043d\u044b\u043c \u0438\u0437-\u0437\u0430 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0443\u0447\u0435\u0441\u0442\u044c \u0440\u0430\u0437\u043d\u0443\u044e \u0440\u0430\u0437\u043c\u0435\u0440\u043d\u043e\u0441\u0442\u044c \u043c\u0430\u0442\u0440\u0438\u0446 \u043f\u0440\u0438 \u0440\u0430\u0441\u0447\u0435\u0442\u0435 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043e\u0432  # \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0443\u0436\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0439 \u043d\u0430\u043c softmax @classmethod def softmax(cls, z, axis=-1,): return cls.exp(z) \/ cls.sum(cls.exp(z), axis=axis, keepdims=True)<\/code><\/pre>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c, \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u0432 \u043d\u0430\u0448\u0438 \u0441\u043b\u043e\u0438<\/p>\n<pre><code class=\"python\">class Flatten:     def __init__(self):          Parameter([self, []])     def __call__(self, x):         self.init_shape = x.shape         return x.reshape(self.init_shape[0], -1)  class ReLU:     def __init__(self):          pass     def __call__(self, x):         return x * (Tensor.sign(x) + 1) \/ 2<\/code><\/pre>\n<pre><code class=\"python\">class SimpleNet(Module):     def __init__(self):         super().__init__()         self.linear1 = Linear(input_channels=25, output_channels=10, bias=True)         self.linear2 = Linear(input_channels=10, output_channels=2, bias=True)         self.flatten = Flatten()         self.relu = ReLU()      def forward(self, x):         x_1 = self.flatten(x)         x_2 = self.linear1(x_1)         x_3 = self.relu(x_2)         x_4 = self.linear2(x_3)         return x_4 model = SimpleNet() model(input_tensor.reshape(1, -1)) &gt;&gt;&gt; array([[ 0.2440679 , -1.75806267]])<\/code><\/pre>\n<p>\u041a\u0440\u0443\u0442\u043e! \u0412\u0441\u0451 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043e\u0431\u0443\u0447\u0438\u0442\u044c! \u0414\u0430\u043b\u044c\u0448\u0435 \u0441\u0447\u0438\u0442\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>loss<\/code>-\u0444\u0443\u043d\u043a\u0446\u0438\u0438.<\/p>\n<pre><code class=\"python\">class CrossEntropyLoss:      def __init__(self):         self.predicted = None         self.true = None      def __call__(self, logits, true):         predicted = Tensor.exp(logits) \/ Tensor.sum(Tensor.exp(logits), axis=1).reshape(-1, 1) # softmax         self.true = true         # \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043b\u043e\u0441\u0441-\u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u0440\u044f\u043c\u043e \u043f\u043e \u0444\u043e\u0440\u043c\u0443\u043b\u0435         self.loss = Tensor.sum(self.true * Tensor.log(predicted + 1e-5), axis=1) * -1         return self<\/code><\/pre>\n<p>\u0417\u0430\u043c\u0435\u0442\u044c\u0442\u0435, \u044d\u0442\u0430 \u0442\u0430 \u0436\u0435 \u0441\u0430\u043c\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f, \u0447\u0442\u043e \u0438 \u0432 \u043f\u0440\u043e\u0448\u043b\u044b\u0445 \u0441\u0442\u0430\u0442\u044c\u044f\u0445, \u043d\u043e \u043c\u044b \u043f\u043e\u043c\u0435\u043d\u044f\u043b\u0438 <code>np<\/code> \u043d\u0430 <code>Tensor<\/code>.<\/p>\n<pre><code class=\"python\">loss = loss_fn(model(input_tensor.reshape(1, -1)), target_tensor)  loss.loss &gt;&gt;&gt; array([0.2581563])<\/code><\/pre>\n<p>\u0427\u0442\u043e \u0436, \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438 \u043c\u044b \u0443\u0436\u0435 \u0437\u043d\u0430\u0435\u043c, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u043c \u0432\u044b\u0437\u0432\u0430\u0442\u044c <code>.backward()<\/code> \u043f\u0440\u044f\u043c\u043e \u0441 \u0442\u0435\u043d\u0437\u043e\u0440\u0430 <code>loss.loss<\/code>, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0432\u0441\u0435 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044b (<s>\u0441\u043f\u043e\u0439\u043b\u0435\u0440: \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u043c, \u0443 \u043d\u0430\u0441 \u0432\u044b\u043b\u0435\u0442\u0438\u0442 \u043e\u0448\u0438\u0431\u043a\u0430<\/s>)! \u041d\u043e \u043e\u0442\u043a\u0440\u043e\u044e \u0434\u043b\u044f \u0432\u0430\u0441 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0441\u0435\u043a\u0440\u0435\u0442\u0438\u043a. \u0413\u0440\u0430\u0434\u0438\u0435\u043d\u0442 \u0434\u043b\u044f \u043a\u0440\u043e\u0441\u0441-\u044d\u043d\u0442\u0440\u043e\u043f\u0438\u0438 + <code>softmax<\/code> \u043c\u043e\u0436\u043d\u043e \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043d\u0435 \u0447\u0435\u0440\u0435\u0437 \u0433\u0440\u0430\u0444, \u0430 \u0447\u0435\u0440\u0435\u0437 \u0444\u043e\u0440\u043c\u0443\u043b\u0443. \u0412\u043e\u0442 \u0442\u0430\u043a \u0432\u043e\u0442! \u041c\u044b \u0443\u0431\u0435\u0433\u0430\u043b\u0438 \u043e\u0442 \u0444\u043e\u0440\u043c\u0443\u043b\u044c\u043d\u044b\u0445 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439, \u0430 \u0441\u0430\u043c\u0438 \u0436\u0435 \u0432\u0435\u0440\u043d\u0443\u043b\u0438\u0441\u044c \u043a \u043d\u0438\u043c. \u041d\u043e \u0437\u0434\u0435\u0441\u044c \u044d\u0442\u043e \u043e\u043f\u0440\u0430\u0432\u0434\u0430\u043d\u043e, \u0432\u0435\u0434\u044c \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u0442\u0435 \u043a\u0430\u043a\u0430\u044f \u0442\u0430\u043c \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u0430\u044f \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f, \u0430 \u0437\u043d\u0430\u0447\u0438\u0442 \u043c\u044b \u043c\u043e\u0436\u0435\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0442\u0440\u044e\u043a <\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7df\/188\/370\/7df18837093e3bb301622991485ce9a9.png\" width=\"105\" height=\"59\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/7df\/188\/370\/7df18837093e3bb301622991485ce9a9.png\"\/><\/figure>\n<p>\u0414\u043b\u044f \u043d\u0435\u0433\u043e \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <code>detach<\/code> &#8212; \u043e\u043d \u0432\u044b\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u0435\u0442 \u0442\u0435\u043d\u0437\u043e\u0440 \u0438\u0437 \u0433\u0440\u0430\u0444\u0430. \u0422\u043e \u0435\u0441\u0442\u044c \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043c\u0430\u0442\u0440\u0438\u0446\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439.<\/p>\n<pre><code class=\"python\">def detach(self): return Tensor(self.value)<\/code><\/pre>\n<pre><code class=\"python\">class CrossEntropyLoss:      def __call__(self, predicted, true):     ### \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432\u044b\u0445\u043e\u0434\u0430 \u043c\u043e\u0434\u0435\u043b\u0438         self.logits = Tensor(predicted, local_gradients=predicted.local_gradients)         ###         self.predicted = Tensor.softmax(predicted) # softmax         #number_of_classes = predicted.shape[1]         #self.true = Tensor.int_(Tensor.arange(0, number_of_classes) == true)         self.true = true         # \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043b\u043e\u0441\u0441-\u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u0440\u044f\u043c\u043e \u043f\u043e \u0444\u043e\u0440\u043c\u0443\u043b\u0435         self.loss = Tensor.sum(self.true * Tensor.log(self.predicted + 1e-5), axis=1) * -1         return self      def backward(self):     # \u041f\u043e\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442 \u043f\u043e \u0444\u043e\u0440\u043c\u0443\u043b\u0435         self.analytics = (self.predicted - self.true)         # \u0412\u044b\u0442\u0430\u0449\u0438\u043c \u0438\u0437 \u0433\u0440\u0430\u0444\u0430, \u0442\u043e \u0435\u0441\u0442\u044c \u043f\u043e \u0444\u0430\u043a\u0442\u0443 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438 \u0434\u043e\u043c\u043d\u043e\u0436\u0438\u043c \u043d\u0430 self.logits, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0441\u0451 \u0435\u0449\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0433\u0440\u0430\u0444\u0435.          self.analytics = self.analytics.detach() * self.logits         self.gradients = self.analytics.backward()<\/code><\/pre>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c \u043c\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>self.analytics<\/code> \u043f\u043e\u0434\u043c\u0435\u043d\u0438\u043b\u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u043e\u0439 \u0432\u043d\u0443\u0442\u0440\u0438 \u0433\u0440\u0430\u0444\u0430. \u0410 \u0434\u043e\u043c\u043d\u043e\u0436\u0438\u0432 <code>self.analytics<\/code> \u043d\u0430<code>self.logits<\/code>, \u043c\u044b \u0432\u0435\u0440\u043d\u0443\u043b\u0438\u0441\u044c \u0432 \u0433\u0440\u0430\u0444, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b\u043b \u0435\u0449\u0435 \u0434\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f <code>softmax<\/code> \u0438 \u043a\u0440\u043e\u0441\u0441-\u044d\u043d\u0442\u0440\u043e\u043f\u0438\u0438, \u0438 \u0443\u0436\u0435 \u043e\u0442\u0441\u044e\u0434\u0430 \u043c\u043e\u0436\u0435\u043c \u0447\u0435\u0441\u0442\u043d\u043e \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044b \u0432\u043d\u0443\u0442\u0440\u0438 \u0433\u0440\u0430\u0444\u0430!<\/p>\n<p>\u0415\u0449\u0451 \u0440\u0430\u0437: <code>self.logits.backward()<\/code> &#8212; \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0435\u0442 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0433\u0440\u0430\u0444\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043d\u0435\u0442 <code>softmax<\/code> + \u043a\u0440\u043e\u0441\u0441-\u044d\u043d\u0442\u0440\u043e\u043f\u0438\u0438, \u0430 <code>((self.predicted - self.true).detach() * self.logits).backward()<\/code> &#8212; \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0435\u0442 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0433\u0440\u0430\u0444\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043d\u0435\u0442 <code>softmax<\/code> + \u043a\u0440\u043e\u0441\u0441-\u044d\u043d\u0442\u0440\u043e\u043f\u0438\u0438, \u043d\u043e \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0435\u044f\u0432\u043d\u043e \u0443\u0447\u0442\u0451\u0442 \u0438\u0445 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u0430 \u0441\u0447\u0435\u0442 \u043c\u043d\u043e\u0436\u0438\u0442\u0435\u043b\u044f <code>(self.predicted - self.true).detach()<\/code><\/p>\n<p>\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c<\/p>\n<pre><code class=\"python\">loss.backward() loss.gradients[model.linear1.weight].shape, loss.gradients[model.linear1.bias].shape &gt;&gt;&gt; ((25, 10), (1, 10))<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043d\u043e\u0432\u0430 \u0440\u0443\u0447\u043a\u0430\u043c\u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043d\u044b\u0439 \u0441\u043f\u0443\u0441\u043a \u0438 \u043e\u0431\u0443\u0447\u0438\u043c \u043c\u043e\u0434\u0435\u043b\u044c!<\/p>\n<pre><code class=\"python\">model = SimpleNet() loss_fn = CrossEntropyLoss() lr = 0.01 for i in range(100):     output = model(input_tensor.reshape(1, -1))     loss = loss_fn(output, target_tensor)      loss.backward()     gradients = loss.gradients     for layer in [model.linear1, model.linear2]:         layer.weight.value = layer.weight.value - lr * gradients[layer.weight]         layer.bias.value = layer.bias.value - lr * gradients[layer.bias]      if i % 10 == 0:         print(loss.loss) &gt;&gt;&gt; array([1.29812516]) array([0.46082039]) array([0.21713806]) array([0.13151886]) array([0.0906402]) array([0.06659202]) array([0.05139489]) array([0.04118782]) array([0.03398361]) array([0.0286905])<\/code><\/pre>\n<p><strong>\u0423\u0440\u0430.<\/strong> \u041d\u0430\u0448\u0430 \u043c\u043e\u0434\u0435\u043b\u044c \u043e\u0431\u0443\u0447\u0430\u0435\u0442\u0441\u044f! \u0418\u0434\u0435\u043c \u0434\u0430\u043b\u044c\u0448\u0435 \u0438 \u0437\u0430\u043f\u0438\u0445\u043d\u0451\u043c \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043d\u044b\u0439 \u0441\u043f\u0443\u0441\u043a \u0432 \u0443\u0436\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0439 \u043d\u0430\u043c <code>SGD<\/code><\/p>\n<pre><code class=\"python\">class Tensor:     def __init__(self, value, local_gradients=None):         self.shape = self.value.shape         self.grad = 0          class CrossEntropyLoss     def backward(self):         self.analytics = (self.predicted - self.true)         self.analytics = self.analytics.detach() * self.logits         self.gradients = self.analytics.backward() global Parameter         for index, layer in enumerate(Parameter.layers[::-1]):             if type(layer).__name__ == 'Linear':                 layer.weight.grad += self.gradients[layer.weight] \/ self.loss.shape[0]                 layer.bias.grad += self.gradients[layer.bias] \/ self.loss.shape[0]                  class SGD:     def __init__(self, model, lr=2e-4):         self.model = model         self.lr = lr      def step(self):         for index, layer in enumerate(self.model._constructor_Parameter.layers[::-1]):             if type(layer).__name__  == 'Linear':                 layer.weight.value -= self.lr * layer.weight.grad                 layer.bias.value -= self.lr * layer.b.grad.mean(axis=0)<\/code><\/pre>\n<p>\u041d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u0441\u044e\u0434\u0430 <\/p>\n<pre><code class=\"python\">layer.weight.grad += self.gradients[layer.weight] \/ self.loss.shape[0] layer.bias.grad += self.gradients[layer.bias] \/ self.loss.shape[0]<\/code><\/pre>\n<p>\u042d\u0442\u043e \u0436\u0435 \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u0438\u0435 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043e\u0432! \u0410 \u0440\u0430\u0437\u0432\u0435 \u043e\u043d\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e? \u041d\u0435\u0442! \u0417\u043d\u0430\u0447\u0438\u0442 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u043d\u0443\u043b\u044f\u0442\u044c \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u043d\u044b\u0435 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044b \u0432 \u043a\u0430\u0436\u0434\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432\u0432\u0435\u0434\u0451\u043c \u043d\u043e\u0432\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 <code>.zero_grad()<\/code><\/p>\n<pre><code class=\"python\">class Module:     def zero_grad(self):         for index, layer in enumerate(self._constructor_Parameter.layers):             if type(layer).__name__ == 'Linear':                 layer.weight.grad = 0                 layer.bias.grad = 0<\/code><\/pre>\n<p>\u041e\u0431\u0443\u0447\u0430\u0435\u043c!<\/p>\n<pre><code class=\"python\">model = SimpleNet() loss_fn = CrossEntropyLoss() optim = SGD(model.parameters(), lr=1e-3) lr = 0.001 for i in range(100):     output = model(input_tensor.reshape(1, -1))     loss = loss_fn(output, target_tensor)      model.zero_grad()     loss.backward()     optim.step()      if i % 10 == 0:         print(loss.loss) &gt;&gt;&gt; array([0.51065697]) array([0.15970178]) array([0.01386941]) array([0.00090227]) array([4.67924761e-05]) array([-6.95378636e-06]) array([-9.88413122e-06]) array([-9.99684238e-06]) array([-9.99989122e-06]) array([-9.99994927e-06])<\/code><\/pre>\n<p>\u041a\u0440\u0443\u0442\u043e! \u041c\u044b \u043e\u0431\u0443\u0447\u0438\u043b\u0438 \u043d\u0430\u0448\u0443 \u043f\u0435\u0440\u0432\u0443\u044e \u043d\u0435\u0439\u0440\u043e\u043d\u043a\u0443 \u043d\u0430 \u0433\u0440\u0430\u0444\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439!<\/p>\n<p><strong>NOTE!<\/strong><\/p>\n<p>\u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u0431\u043b\u043e\u043a\u0435 \u044f \u0431\u0443\u0434\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0441\u0432\u0451\u0440\u0442\u043e\u0447\u043d\u043e\u0439 \u043d\u0435\u0439\u0440\u043e\u043d\u043a\u0438 \u043d\u0430 \u0433\u0440\u0430\u0444\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439. \u041f\u043e \u0438\u0442\u043e\u0433\u0443 \u043e\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043d\u043e <strong>\u043d\u0435 \u043e\u0431\u0443\u0447\u0430\u0435\u0442\u0441\u044f<\/strong>. \u041e\u0448\u0438\u0431\u043a\u0443 \u044f \u043d\u0435 \u0443\u0441\u043f\u0435\u043b \u043d\u0430\u0439\u0442\u0438, \u043d\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u043e\u0442\u043b\u0430\u0434\u0438\u0442\u044c \u043a\u043e\u0434 \u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e. \u042f \u0440\u0435\u0448\u0438\u043b \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u0443 \u0447\u0430\u0441\u0442\u044c, \u0442\u0430\u043a \u043a\u0430\u043a \u0445\u043e\u0442\u0435\u043b \u0434\u043e\u043d\u0435\u0441\u0442\u0438 \u0438\u043c\u0435\u043d\u043d\u043e <strong>\u0438\u0434\u0435\u0439\u043d\u0443\u044e \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0443\u044e<\/strong> \u043c\u043e\u0435\u0433\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430. \u0418 \u043f\u0443\u0441\u0442\u044c \u043e\u0431\u0443\u0447\u0438\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f, \u044f \u043d\u0430\u0434\u0435\u044e\u0441\u044c \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u0443 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044f \u043e\u0441\u0442\u0430\u043d\u0435\u0442\u0441\u044f!<\/p>\n<h2>Conv2d<\/h2>\n<p>\u041e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, <strong>NumPy<\/strong> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0441\u0432\u0435\u0440\u0442\u043a\u0443 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u0430\u0442\u0440\u0438\u0446. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <a href=\"https:\/\/numpy.org\/devdocs\/reference\/generated\/numpy.lib.stride_tricks.sliding_window_view.html#numpy-lib-stride-tricks-sliding-window-view\" rel=\"noopener noreferrer nofollow\">numpy.lib.stride_tricks.sliding_window_view<\/a><br \/>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>numpy.lib.stride_tricks.sliding_window_view<\/code> \u0432 NumPy \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432 \u0441 \u043e\u043a\u043d\u0430\u043c\u0438 \u0441\u043a\u043e\u043b\u044c\u0437\u044f\u0449\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445. \u042d\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0440\u044f\u0434\u043e\u0432, \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0441\u0432\u0451\u0440\u0442\u043e\u043a \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439, \u0433\u0434\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043f\u043e\u0434\u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0441\u043a\u043e\u043b\u044c\u0437\u044f\u0449\u0435\u043c \u043e\u043a\u043d\u0435. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043e\u043a\u043d\u043e \u0443 \u043d\u0430\u0441 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c\u043e \u0432 \u0432\u044b\u0442\u044f\u043d\u0443\u0442\u043e\u0433\u043e \u0432\u0435\u043a\u0442\u043e\u0440\u0430. <br \/>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438 <code>(2, 5, 5)<\/code> \u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u0430 <code>(2, 3, 3)<\/code> \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432 \u0432\u0438\u0434\u0435 <code>(3, 3, 2, 3, 3)<\/code>, \u0438 \u0434\u043b\u044f \u0440\u0430\u0441\u0447\u0435\u0442\u0430 \u0441\u0432\u0451\u0440\u0442\u043a\u0438 \u0434\u043b\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u0438 <code>(i, j)<\/code>, \u0432\u043e\u0437\u044c\u043c\u0451\u043c <code>[i][j]<\/code>, \u0432\u044b\u0442\u044f\u043d\u0435\u043c \u0432 \u0432\u0435\u043a\u0442\u043e\u0440, <code>[i][j].reshape(-1)<\/code> \u0438 \u0443\u043c\u043d\u043e\u0436\u0438\u043c \u043d\u0430 \u0432\u044b\u0442\u044f\u043d\u0443\u0442\u044b\u0439 \u0432\u0435\u043a\u0442\u043e\u0440 \u0444\u0438\u043b\u044c\u0442\u0440\u0430 <code>[i][j].reshape(-1) @ kernel.reshape(-1)<\/code><\/p>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c<\/p>\n<pre><code class=\"python\">image = np.array([[0, 50, 0, 29],         [0, 80, 31, 2],          [33, 90, 0, 75],         [0, 9, 0, 95]         ]) kernel = np.ones((3, 3))  v = sliding_window_view(image, (kernel.shape[0], kernel.shape[1]), axis=(-1, -2)) *not_used, a, b = v.shape v = v.reshape(*not_used, -1) kernel_s = kernel.reshape(-1) result = v @ kernel_s np.allclose(result, scipy.signal.fftconvolve(image, kernel, mode='valid')) &gt;&gt;&gt; True<\/code><\/pre>\n<p>\u041a\u0440\u0443\u0442\u043e! \u0423\u0441\u043b\u043e\u0436\u043d\u0438\u043c \u0437\u0430\u0434\u0430\u0447\u0443<\/p>\n<pre><code class=\"python\">image = np.random.randn(3, 7, 7) kernel = np.ones((3, 3, 3))  v = sliding_window_view(image, kernel.shape, axis=(-1, -2, -3)) *not_used, a, b, c= v.shape v = v.reshape(*not_used, -1) kernel_s = kernel.reshape(-1) result = v @ kernel_s np.allclose(result, scipy.signal.fftconvolve(image, kernel, mode='valid')) &gt;&gt;&gt; True<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c<\/p>\n<pre><code class=\"python\">image = np.random.randn(10, 3, 7, 7) kernel = np.ones((1, 3, 3, 3))  v = sliding_window_view(image, kernel.shape[1:], axis=(-1, -2, -3)) *not_used, a, b, c = v.shape v = v.reshape(*not_used, -1) kernel_s = kernel.reshape(-1) result = v @ kernel_s np.allclose(result, scipy.signal.fftconvolve(image, kernel, mode='valid')) &gt;&gt;&gt; True<\/code><\/pre>\n<p>\u0418 \u0437\u0430\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441 \u043d\u0430\u0448\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0438\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438<\/p>\n<pre><code class=\"python\">image = np.random.randn(11, 1, 4, 7, 7) kernel = np.random.randn(1, 5, 4, 3, 3)  i = image_.shape[-1] f = kernel_.shape[-1] padding = 0 step = 1 m = (i-f + 2*padding) \/\/ step +1 number_of_kernels = kernel_.shape[1] number_of_images = image_.shape[0] new_image = np.zeros((number_of_images, number_of_kernels, m, m)) for image_n in range(number_of_images):     for kernel_n in range(number_of_kernels):         for y in range(m):             for x in range(m):                 start_x = x * step                 end_x = start_x + f                 start_y = y * step                 end_y = start_y + f                 new_image[image_n][kernel_n][y][x] = np.sum(image_[image_n, 0, :, start_y:end_y, start_x:end_x] * kernel_[0, kernel_n])  kernel = kernel.squeeze(axis=0) image = image.squeeze(axis=1)  num_images, matrix_z, matrix_y, matrix_x = image.shape num_kernels, kernel_z, kernel_y, kernel_x = kernel.shape result_x, result_y = matrix_x - kernel_x + 1, matrix_y - kernel_y + 1 new_matrix = sliding_window_view(image, (1, kernel_z, kernel_y, kernel_x)) new_kernel = kernel.transpose(1, 2, 3, 0) result =  new_matrix.reshape(num_images, -1, kernel_z * kernel_y * kernel_x) @ new_kernel.reshape(-1, num_kernels) result = result.transpose(0, 2, 1) result = result.reshape(num_images, num_kernels, result_y, result_x)  np.allclose(result, new_image) &gt;&gt;&gt; True<\/code><\/pre>\n<p>\u041e\u0442\u043b\u0438\u0447\u043d\u043e! \u041c\u044b \u043d\u0430\u0443\u0447\u0438\u043b\u0438\u0441\u044c \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u044c \u0441\u0432\u0451\u0440\u0442\u043a\u0443 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0430\u0442\u0440\u0438\u0447\u043d\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u044f, \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u044d\u0442\u0443 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e \u0432 \u043d\u0430\u0448 \u043a\u043b\u0430\u0441\u0441 \u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0434\u043b\u044f \u043d\u0435\u0451 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u0443\u044e!<\/p>\n<pre><code class=\"python\">class Tensor:   @classmethod   def sliding_window_view(cls, matrix, kernel_z, kernel_y, kernel_x):     result = np.lib.stride_tricks.sliding_window_view(matrix.value, (1, kernel_z, kernel_y, kernel_x)).copy()     def multiply_by_locgrad(path_value):         temp = np.zeros(matrix.shape)         np.add.at(np.lib.stride_tricks.sliding_window_view(temp, (1, kernel_z, kernel_y, kernel_x), writeable=True), None, path_value)         return temp      local_gradients = (('slide', matrix, multiply_by_locgrad),)     return cls(result, local_gradients=local_gradients) <\/code><\/pre>\n<ul>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434 <code>np.add.at<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043c\u0430\u0441\u0441\u0438\u0432 <code>temp<\/code> \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 <code>path_value<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 &#171;\u043e\u043a\u043d\u0430\u043c\u0438&#187; \u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0435\u0449\u0451 \u043e\u0434\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 <code>sliding_window_view<\/code> \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c <code>writeable=True<\/code>, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u0430\u043a \u0432\u044b \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0433\u043b\u0438 \u0443\u0432\u0438\u0434\u0435\u0442\u044c, \u0447\u0442\u043e \u043c\u044b \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e <code>.transpose()<\/code>, \u043d\u043e \u043d\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0438 \u0435\u0451 \u0432 \u043a\u043b\u0430\u0441\u0441\u0435, \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u043c!<\/p>\n<pre><code class=\"python\">def transpose(self, *args): local_gradients = (('transpose', self, lambda x: x.transpose(*args)),) return Tensor(self.value.transpose(*args), local_gradients=local_gradients)<\/code><\/pre>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u043a\u043b\u0430\u0441\u0441 <code>Conv2d<\/code> \u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u043d\u043e\u0432\u044b\u0445 \u0437\u043d\u0430\u043d\u0438\u0439<\/p>\n<pre><code class=\"python\">class Conv2d:      def __init__(self, input_channels: int, output_channels: int, kernel_size: int, bias = True):         self.param = None         self.bias_flag = bias         self.input_channels = input_channels         self.kernel_size = (input_channels, kernel_size, kernel_size)         self.n_filters = output_channels          self.weight = Tensor.randn((self.n_filters, input_channels, kernel_size, kernel_size), )         self.bias = Tensor.randn((self.n_filters, 1, 1))         self.weight.value *= 1e-2 # \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u043c \u0434\u043b\u044f \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u0438         self.bias.value *= 1e-2          Parameter([self, self.weight, self.bias])      def __call__(self, x):         matrix = x         kernel = self.weight         num_images, matrix_z, matrix_y, matrix_x = matrix.shape         num_kernels, kernel_z, kernel_y, kernel_x = kernel.shape         result_x, result_y = matrix_x - kernel_x + 1, matrix_y - kernel_y + 1                  new_matrix = Tensor.sliding_window_view(matrix, kernel_z, kernel_y, kernel_x)                  tranposed_kernel = kernel.transpose(1, 2, 3, 0)              result = new_matrix.reshape(num_images, -1,  kernel_z * kernel_y * kernel_x) @ tranposed_kernel.reshape(-1, num_kernels)                  result = result.transpose(0, 2, 1)                  return result.reshape(num_images, num_kernels, result_y, result_x) + self.bias <\/code><\/pre>\n<p>\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u043b\u044f \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f \u043d\u0430 <code>MNIST<\/code>. \u041a\u043e\u0434 \u0434\u043b\u044f \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u043e\u0437\u044c\u043c\u0451\u043c \u0438\u0437 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<p>\u0410 \u0432\u043e\u0442 \u0442\u0430\u043a \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043e\u0432!<\/p>\n<pre><code class=\"python\">mul child shape: (64, 10) obj shape: (64, 10) mul child shape: (64, 10) obj shape: (64, 10) add child shape: (64, 10) obj shape: (64, 10) matmul child shape: (64, 50) obj shape: (64, 10) div child shape: (64, 50) obj shape: (64, 50) mul child shape: (64, 50) obj shape: (64, 50) add child shape: (64, 50) obj shape: (64, 50) matmul child shape: (64, 1296) obj shape: (64, 50) reshape child shape: (64, 4, 18, 18) obj shape: (64, 1296) div child shape: (64, 4, 18, 18) obj shape: (64, 4, 18, 18) mul child shape: (64, 4, 18, 18) obj shape: (64, 4, 18, 18) add child shape: (64, 4, 18, 18) obj shape: (64, 4, 18, 18) reshape child shape: (64, 4, 324) obj shape: (64, 4, 18, 18) transpose child shape: (64, 324, 4) obj shape: (64, 4, 324) matmul child shape: (64, 324, 36) obj shape: (64, 324, 4) reshape child shape: (64, 1, 18, 18, 1, 4, 3, 3) obj shape: (64, 324, 36) slide child shape: (64, 4, 20, 20) obj shape: (64, 1, 18, 18, 1, 4, 3, 3) div child shape: (64, 4, 20, 20) obj shape: (64, 4, 20, 20) mul child shape: (64, 4, 20, 20) obj shape: (64, 4, 20, 20) add child shape: (64, 4, 20, 20) obj shape: (64, 4, 20, 20) reshape child shape: (64, 4, 400) obj shape: (64, 4, 20, 20) transpose child shape: (64, 400, 4) obj shape: (64, 4, 400) matmul child shape: (64, 400, 36) obj shape: (64, 400, 4) reshape child shape: (64, 1, 20, 20, 1, 4, 3, 3) obj shape: (64, 400, 36) slide child shape: (64, 4, 22, 22) obj shape: (64, 1, 20, 20, 1, 4, 3, 3)<\/code><\/pre>\n<pre><code class=\"python\">class SimpleConvNet(Module):     def __init__(self):         super().__init__()         self.conv1 = Conv2d(input_channels = 1, output_channels = 5, kernel_size=5) #28 -&gt; 24         self.conv2 = Conv2d(input_channels = 5, output_channels = 10, kernel_size=5) #24 -&gt; 20         self.conv3 = Conv2d(input_channels = 10, output_channels = 20, kernel_size=5) #20 -&gt; 16         self.conv4 = Conv2d(input_channels = 20, output_channels = 20, kernel_size=5) #16 -&gt; 12         self.conv5 = Conv2d(input_channels = 20, output_channels = 20, kernel_size=5) #12 -&gt; 8         self.conv6 = Conv2d(input_channels = 20, output_channels = 10, kernel_size=5) #8 -&gt; 4                  self.flatten = Flatten()         self.linear1 = Linear(input_channels= 4 * 4 * 10, output_channels=20, bias=True)         self.linear2 = Linear(input_channels= 20, output_channels=10, bias=True)         self.relu = ReLU()      def forward(self, x):         x = self.conv1(x)         x = self.relu(x)         x = self.conv2(x)         x = self.relu(x)         x = self.conv3(x)         x = self.relu(x)         x = self.conv4(x)         x = self.relu(x)         x = self.conv5(x)         x = self.relu(x)         x = self.conv6(x)         x = self.relu(x)                  x = self.flatten(x)         x = self.linear1(x)         x = self.relu(x)         x = self.linear2(x)         return x  model = SimpleConvNet() loss_fn = CrossEntropyLoss() optim = SGD(model.parameters(), lr=1e-3) for i in range(5):     y_pred_list = []     y_true_list = []     for index, batch in enumerate(data_loader):         input_x, target = batch         input_x = input_x \/ 255         input_x = np.expand_dims(input_x, axis=1) # (64, 28, 28) -&gt; (64, 1, 28, 28)                  input_tensor = Tensor(input_x)         target_tensor = Tensor(target)                  output = model(input_tensor)         loss = loss_fn(output, target_tensor)          model.zero_grad()         loss.backward()         optim.step()                  print(loss.loss.value.mean())  &gt;&gt;&gt; 2.3434739196082752 2.3261346480555405 2.3450367034537822 2.328755621690293 2.290884864380055 2.3062695760361183 2.312287414927344 2.3049557593729144 2.2829010337160796<\/code><\/pre>\n<p><strong>\u041d\u0435<\/strong> \u043e\u0431\u0443\u0447\u0430\u0435\u0442\u0441\u044f<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/997\/9be\/1cd\/9979be1cd47e871262b1027e124bc048.png\" width=\"225\" height=\"225\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/997\/9be\/1cd\/9979be1cd47e871262b1027e124bc048.png\"\/><\/figure>\n<p>\u041d\u043e \u043d\u0430\u0434\u0435\u044e\u0441\u044c \u0432\u044b \u0445\u043e\u0442\u044f \u0431\u044b \u043f\u043e\u043d\u044f\u043b\u0438 \u0438\u0434\u0435\u044e!<\/p>\n<p>\u042f \u043e\u043f\u0443\u0441\u0442\u0438\u043b \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 <code>__hash__<\/code>, <code>__eq__<\/code> , \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u0430\u043c\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440\u0430, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043c\u0435\u0440\u043d\u043e\u0441\u0442\u0435\u0439 \u0442\u0435\u043d\u0437\u043e\u0440\u043e\u0432, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 <code>broadcasting<\/code> \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439. \u0412\u0441\u0435 \u043e\u043d\u0438 \u043d\u0435 \u043d\u0435\u0441\u0443\u0442 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0438\u0434\u0435\u0439\u043d\u043e\u0439 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0435\u0439, \u043d\u043e <strong>\u0431\u0435\u0437\u0443\u0441\u043b\u043e\u0432\u043d\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b<\/strong> \u0434\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0432\u0441\u0435\u0445 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432. \u042f \u043d\u0435 \u0441\u0442\u0430\u043b \u0437\u0430\u0446\u0438\u043a\u043b\u0438\u0432\u0430\u0442\u044c \u043d\u0430 \u044d\u0442\u043e\u043c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0438 \u043d\u0430\u0434\u0435\u044e\u0441\u044c \u0432\u044b \u043f\u043e\u0439\u043c\u0435\u0442\u0435 \u043c\u0435\u043d\u044f!<\/p>\n<h2>\u041a\u0423\u041b\u042c\u041c\u0418\u041d\u0410\u0426\u0418\u042f<\/h2>\n<p>\u0418\u0442\u0430\u043a, \u0432\u0441\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u043c \u0441\u0430\u043c\u044b\u0439 \u043f\u0435\u0440\u0432\u044b\u0439 \u0431\u043b\u043e\u043a \u043a\u043e\u0434\u0430 \u0438\u0437 <a href=\"https:\/\/habr.com\/ru\/articles\/869118\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0435\u0440\u0432\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438<\/a>!<\/p>\n<pre><code class=\"python\"># \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043d\u0430\u0431\u043e\u0440 \u0434\u0430\u043d\u043d\u044b\u0445 X = torch.randn(100, 3)  # 100 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u0441 3 \u043f\u0440\u0438\u0437\u043d\u0430\u043a\u0430\u043c\u0438 y = torch.randint(0, 2, (100,))  # 100 \u043c\u0435\u0442\u043e\u043a \u043a\u043b\u0430\u0441\u0441\u043e\u0432 (0 \u0438\u043b\u0438 1)  # \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u0443\u044e \u043d\u0435\u0439\u0440\u043e\u043d\u043d\u0443\u044e \u0441\u0435\u0442\u044c class SimpleNN(nn.Module):     def __init__(self):         super(SimpleNN, self).__init__()         self.fc1 = nn.Linear(3, 5)  # \u041f\u0435\u0440\u0432\u044b\u0439 \u0441\u043b\u043e\u0439: 3 \u0432\u0445\u043e\u0434\u0430, 5 \u0432\u044b\u0445\u043e\u0434\u043e\u0432         self.fc2 = nn.Linear(5, 2)  # \u0412\u0442\u043e\u0440\u043e\u0439 \u0441\u043b\u043e\u0439: 5 \u0432\u0445\u043e\u0434\u043e\u0432, 2 \u0432\u044b\u0445\u043e\u0434\u0430 (\u043a\u043b\u0430\u0441\u0441\u044b)         self.softmax = nn.Softmax(dim=1)  # \u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u0435\u0439 \u043a\u043b\u0430\u0441\u0441\u043e\u0432      def forward(self, x):         x = torch.relu(self.fc1(x))  # \u041f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u043c \u0430\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u044e ReLU         x = self.fc2(x)  # \u0412\u0442\u043e\u0440\u043e\u0439 \u0441\u043b\u043e\u0439         x = self.softmax(x)  # \u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u0432 \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u0438         return x  # \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043c\u043e\u0434\u0435\u043b\u044c model = SimpleNN()  # \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043f\u043e\u0442\u0435\u0440\u044c \u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440 criterion = nn.CrossEntropyLoss()  # \u041a\u0440\u043e\u0441\u0441-\u044d\u043d\u0442\u0440\u043e\u043f\u0438\u044f \u0434\u043b\u044f \u043c\u043d\u043e\u0433\u043e\u043a\u043b\u0430\u0441\u0441\u043e\u0432\u043e\u0439 \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 optimizer = optim.SGD(model.parameters(), lr=0.01)  # \u0421\u0442\u043e\u0445\u0430\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043d\u044b\u0439 \u0441\u043f\u0443\u0441\u043a  # \u041e\u0431\u0443\u0447\u0430\u0435\u043c \u043c\u043e\u0434\u0435\u043b\u044c num_epochs = 100 for epoch in range(num_epochs):     # \u041f\u0440\u044f\u043c\u043e\u0439 \u043f\u0440\u043e\u0445\u043e\u0434     outputs = model(X)          # \u0412\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0442\u0435\u0440\u044c     loss = criterion(outputs, y)          # \u041e\u0431\u0440\u0430\u0442\u043d\u044b\u0439 \u043f\u0440\u043e\u0445\u043e\u0434     optimizer.zero_grad()  # \u041e\u0431\u043d\u0443\u043b\u044f\u0435\u043c \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044b     loss.backward()  # \u0412\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044b     optimizer.step()  # \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043c\u043e\u0434\u0435\u043b\u0438<\/code><\/pre>\n<p>\u0421\u043c\u043e\u0442\u0440\u0438\u043c \u0438 \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u043c: <strong>\u041c\u044b \u0441 \u0432\u0430\u043c\u0438 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c \u0432 \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0442\u0440\u043e\u0447\u043a\u0435 \u044d\u0442\u043e\u0433\u043e \u043a\u043e\u0434\u0430. <\/strong>\u041a\u0430\u043a \u044f \u0438 <strong>\u043e\u0431\u0435\u0449\u0430\u043b<\/strong>, \u0441\u043e\u0431\u0440\u0430\u0432 \u0437\u043d\u0430\u043d\u0438\u044f \u044f \u043e\u0434\u043d\u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443, \u043c\u044b \u0437\u0430\u043c\u0435\u043d\u0438\u043c \u043d\u0430\u043a\u043e\u043d\u0435\u0446<\/p>\n<pre><code class=\"python\">import torch import torch.nn as nn<\/code><\/pre>\n<p>\u043d\u0430<\/p>\n<pre><code class=\"python\">import &lt;\u043d\u0430\u0448\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430&gt; import &lt;\u043d\u0430\u0448\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430&gt;.nn as nn<\/code><\/pre>\n<p>\u0410 \u0442\u0430\u043a \u044f \u043c\u043e\u0433\u0443 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u043e \u0441\u0432\u043e\u0435\u0439 <a href=\"https:\/\/github.com\/TimaGitHub\/pycandle-2\" rel=\"noopener noreferrer nofollow\">\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439<\/a><\/p>\n<pre><code class=\"python\">import candle import candle.nn as nn<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/617\/ac8\/170\/617ac81707cfc245d25cc072088342a2.png\" width=\"612\" height=\"445\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/617\/ac8\/170\/617ac81707cfc245d25cc072088342a2.png\"\/><\/figure>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043c\u043e\u0435\u0433\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430 \u043f\u043e\u0434\u043e\u0448\u043b\u0430 \u043a \u043a\u043e\u043d\u0446\u0443. \u042f \u043d\u0430\u0434\u0435\u044e\u0441\u044c, \u0447\u0442\u043e \u0441\u043c\u043e\u0433 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u043f\u043e\u044f\u0441\u043d\u0438\u0442\u044c \u0437\u0430 \u0440\u0430\u0431\u043e\u0442\u0443 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u0433\u043b\u0443\u0431\u043e\u043a\u043e\u0433\u043e \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f \u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 <strong>PyTorch<\/strong>! <strong>\u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0437\u0430 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435!<\/strong><\/p>\n<p>\u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u044f \u0445\u043e\u0447\u0443 \u0443\u0436\u0435 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0432\u0448\u0438\u0441\u044c <strong>\u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439<\/strong> \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0439 <strong>\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439<\/strong> \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043e\u0431\u0443\u0447\u0435\u043d\u043d\u044b\u0439 <strong>GPT2, <\/strong>\u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u043f\u043e\u043a\u0430\u0437\u0430\u0432, \u0447\u0442\u043e \u043c\u044b \u0432 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e\u0439 \u0441\u0442\u0435\u043f\u0435\u043d\u0438 \u043e\u0432\u043b\u0430\u0434\u0435\u043b\u0438 \u043c\u0430\u0441\u0442\u0435\u0440\u0441\u0442\u0432\u043e\u043c \u043c\u0430\u0448\u0438\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f!<\/p>\n<p><a href=\"https:\/\/github.com\/TimaGitHub\/pycandle\" rel=\"noopener noreferrer nofollow\">\u041f\u0435\u0440\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438<\/a><\/p>\n<p><a href=\"https:\/\/github.com\/TimaGitHub\/pycandle-2\" rel=\"noopener noreferrer nofollow\">\u0412\u0442\u043e\u0440\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438<\/a><\/p>\n<p><a href=\"https:\/\/github.com\/TimaGitHub\/smolGPT\" rel=\"noopener noreferrer nofollow\">GPT-2 \u043d\u0430 \u044d\u0442\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435<\/a><\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/870426\/\"> https:\/\/habr.com\/ru\/articles\/870426\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><strong>PyTorch<\/strong>\u00a0\u2014 \u044d\u0442\u043e \u043c\u043e\u0449\u043d\u044b\u0439 \u0438 \u0433\u0438\u0431\u043a\u0438\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f \u043c\u0430\u0448\u0438\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f, \u0448\u0438\u0440\u043e\u043a\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u0435\u0439\u0440\u043e\u043d\u043d\u044b\u0445 \u0441\u0435\u0442\u0435\u0439. \u041e\u043d \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u0435\u043d \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f, \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0433\u0440\u0430\u0444\u0430\u043c \u0438 \u0431\u043e\u0433\u0430\u0442\u043e\u0439 \u044d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0435\u0439. \u0414\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430, \u0447\u0430\u0441\u0442\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u043c\u0430\u0448\u0438\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f.<\/p>\n<p>\u041d\u043e \u0410\u043d\u0434\u0440\u0435\u0439 \u041a\u0430\u0440\u043f\u0430\u0442\u044b, \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0418\u0418, \u0441\u0447\u0438\u0442\u0430\u0435\u0442, \u0447\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u0441 \u043d\u0443\u043b\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043d\u044f\u0442\u044c \u0438\u0445 \u0441\u0443\u0442\u044c \u0438 \u0434\u0435\u0442\u0430\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u044b, \u0447\u0442\u043e \u0441\u043b\u043e\u0436\u043d\u043e \u043e\u0441\u043e\u0437\u043d\u0430\u0442\u044c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438. \u042d\u0442\u043e \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0440\u0430\u0437\u0432\u0438\u0442\u044c \u0438\u043d\u0442\u0443\u0438\u0446\u0438\u044e \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u0432. \u0410\u043d\u0434\u0440\u0435\u0439 \u043f\u043e\u0441\u0432\u044f\u0449\u0430\u0435\u0442 \u043c\u043d\u043e\u0433\u043e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0447\u0442\u043e\u0431\u044b \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u0442\u044c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u044b \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0435\u0439\u0440\u043e\u0441\u0435\u0442\u0435\u0439 \u0432 \u0441\u0432\u043e\u0438\u0445\u00a0<a href=\"https:\/\/karpathy.ai\/\" rel=\"noopener noreferrer nofollow\">\u0431\u043b\u043e\u0433\u0430\u0445<\/a>\u00a0\u0438 \u043d\u0430 \u0441\u0432\u043e\u0451\u043c\u00a0<a href=\"https:\/\/www.youtube.com\/@AndrejKarpathy\" rel=\"noopener noreferrer nofollow\">\u044e\u0442\u0443\u0431-\u043a\u0430\u043d\u0430\u043b\u0435<\/a>. \u041e\u043d \u0442\u0430\u043a\u0436\u0435 \u043d\u0435 \u0440\u0430\u0437 \u043f\u043e\u0434\u0447\u0435\u0440\u043a\u0438\u0432\u0430\u043b, \u0447\u0442\u043e \u043d\u0430 \u0435\u0433\u043e \u043a\u0443\u0440\u0441\u0435 \u0432\u00a0<a href=\"https:\/\/cs.stanford.edu\/people\/karpathy\/\" rel=\"noopener noreferrer nofollow\">C\u0442\u044d\u043d\u0444\u043e\u0440\u0434\u0435<\/a>\u00a0\u0435\u0441\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0438 \u043f\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0435 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u0435.<\/p>\n<p>\u042f \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u043f\u043e\u0441\u0432\u044f\u0442\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e \u044d\u0442\u043e\u0439 \u0438\u0434\u0435\u0438, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043c\u043d\u0435 \u0441\u0430\u043c\u043e\u043c\u0443 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u043a\u043e\u043f\u0430\u0442\u044c\u0441\u044f \u0432 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430\u0445 \u0433\u043b\u0443\u0431\u043e\u043a\u043e\u0433\u043e \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f. \u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435\u00a0<a href=\"https:\/\/habr.com\/ru\/articles\/869520\/\" rel=\"noopener noreferrer nofollow\">\u0432\u0442\u043e\u0440\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438<\/a><\/p>\n<p>\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b:<\/p>\n<ul>\n<li>\n<p>\u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c \u0430\u043d\u0430\u043b\u043e\u0433\u00a0<code>pytorch.tensor()<\/code><\/p>\n<\/li>\n<li>\n<p>\u043f\u0435\u0440\u0435\u0432\u0435\u0434\u0451\u043c \u0432\u0441\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043d\u0430 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0433\u0440\u0430\u0444<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u043e\u0432\u0435\u0434\u0451\u043c \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e\u0435\u0445\u0430\u043b\u0438!<\/p>\n<p><strong>Note!<\/strong><br \/>\u041f\u0435\u0440\u0435\u0434 \u043d\u0430\u0447\u0430\u043b\u043e\u043c \u0447\u0442\u0435\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u044c\u0438 \u044f \u043a\u0440\u0430\u0439\u043d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043a \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0432\u0438\u0434\u0435\u043e \u043f\u043e \u0442\u0435\u043c\u0435 <strong>\u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0433\u0440\u0430\u0444 <\/strong>\u0438 \u0447\u0442\u0435\u043d\u0438\u044e \u0441\u0442\u0430\u0442\u044c\u0438<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=dZIk8a1Dquc&amp;list=PLZu_eiiJs4b4hNw-YPz6I3sXY63K31ZYc&amp;index=29\" rel=\"noopener noreferrer nofollow\">\u043f\u0435\u0440\u0432\u043e\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=RbENpxoFA4A&amp;list=PLZu_eiiJs4b4hNw-YPz6I3sXY63K31ZYc&amp;index=30\" rel=\"noopener noreferrer nofollow\">\u0432\u0442\u043e\u0440\u043e\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=wG_nF1awSSY&amp;list=PLZu_eiiJs4b4hNw-YPz6I3sXY63K31ZYc&amp;index=52\" rel=\"noopener noreferrer nofollow\">\u0442\u0440\u0435\u0442\u044c\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=4wgXBr7fnQg&amp;list=PLZu_eiiJs4b4hNw-YPz6I3sXY63K31ZYc&amp;index=50\" rel=\"noopener noreferrer nofollow\">\u0447\u0435\u0442\u0432\u0435\u0440\u0442\u043e\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/sidsite.com\/posts\/autodiff\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u044f<\/a> <\/p>\n<\/li>\n<\/ul>\n<p>\u042f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0434\u0435\u0438 \u0438\u0437 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043a\u0430\u043a \u0431\u0430\u0437\u0443 \u0434\u043b\u044f \u0441\u0432\u043e\u0438\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0435\u0449\u0435 \u0440\u0430\u0437 \u0433\u043b\u044f\u043d\u0435\u043c \u043e\u0442\u0440\u044b\u0432\u043e\u043a \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u043a\u043e\u0434\u0430!<\/p>\n<pre><code class=\"python\">class SimpleConvNet(Module):     def __init__(self):         ...              def forward(self, x):         x = self.conv1(x)         x = self.relu(x)         x = self.maxpool1(x)         x = self.conv2(x)         x = self.relu(x)         x = self.maxpool2(x)         x = self.flatten(x)         x = self.linear1(x)         x = self.relu(x)         x = self.linear2(x)         return x <\/code><\/pre>\n<p>\u041f\u043e\u0434\u0443\u043c\u0430\u0439\u0442\u0435, \u043a\u0430\u043a\u0438\u0435 \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u043b\u0443\u0447\u0430\u0438 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0438\u0437 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u044f?<\/p>\n<p>\u042f \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438\u0434\u0435\u0439:<\/p>\n<ol>\n<li>\n<p>\u0427\u0442\u043e \u0435\u0441\u043b\u0438 \u043c\u044b \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0432\u043d\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u043d\u0430\u043c\u0438 \u0441\u043b\u043e\u0451\u0432? \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"python\">class SimpleConvNet(Module):     def __init__(self):         ...              def forward(self, x):         x = self.conv1(x)         x = self.relu(x)         x = self.maxpool1(x)         x = self.conv2(x)         x = self.relu(x)         x = x * 2          x = self.maxpool2(x)         x = x ** 2         x = self.flatten(x)         x = self.linear1(x)         x = self.relu(x)         x = x + 1         x = self.linear2(x)         return x <\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0432\u0433\u043b\u044f\u0434\u0438\u0442\u0435\u0441\u044c \u0432 \u043c\u0435\u0442\u043e\u0434 <code>.backward()<\/code> \u043a\u043b\u0430\u0441\u0441\u0430 <code>CrossEntropyLoss<\/code>, \u0442\u043e \u043f\u043e\u0439\u043c\u0435\u0442\u0435, \u0447\u0442\u043e \u043c\u044b \u043d\u0435 \u0443\u043c\u0435\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0441\u043b\u0443\u0447\u0430\u0438 \u043a\u043e\u0433\u0434\u0430 \u043d\u0430\u0448\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u0432\u043d\u0435 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 <code>Linear<\/code>, <code>Conv2d<\/code>, <code>BatchNorm2d<\/code> \u0438 \u0442.\u0434. \u0415\u0441\u043b\u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043d\u044b\u0439 \u0441\u043f\u0443\u0441\u043a, \u0442\u043e \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0442\u0430\u043a, \u043a\u0430\u043a \u0431\u0443\u0434\u0442\u043e \u044d\u0442\u0438\u0445 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0445 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439 <strong>\u043d\u0435<\/strong> \u0431\u044b\u043b\u043e, \u0447\u0442\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e \u043d\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u0442 \u043d\u0438 \u043a \u0447\u0435\u043c\u0443 \u0445\u043e\u0440\u043e\u0448\u0435\u043c\u0443. \u0410 \u0435\u0441\u043b\u0438 \u043c\u044b \u0435\u0449\u0435 \u043a\u0430\u043a\u0438\u043c-\u0442\u043e \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u0435\u043d\u044f\u043b\u0438 \u0440\u0430\u0437\u043c\u0435\u0440 \u043d\u0430\u0448\u0438\u0445 \u043c\u0430\u0442\u0440\u0438\u0446, \u0442\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0432\u043e\u043e\u0431\u0449\u0435 \u0443\u043f\u0430\u0434\u0451\u0442 \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439.<\/p>\n<ol start=\"2\">\n<li>\n<p>\u0412\u0441\u043f\u043e\u043c\u043d\u0438\u0442\u0435, \u043a\u0430\u043a \u043c\u044b \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043b\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043e\u0432? \u041c\u044b \u0438\u0445 \u0441\u0447\u0438\u0442\u0430\u043b\u0438 \u043d\u0430 \u0431\u0443\u043c\u0430\u0433\u0435, \u0430 \u043f\u043e\u0442\u043e\u043c \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u043b\u0438 \u0432 \u043a\u043e\u0434\u0435. \u0422\u0430\u043a \u0431\u044b\u043b\u043e \u0441 \u043b\u0438\u043d\u0435\u0439\u043d\u044b\u043c\u0438 \u0441\u043b\u043e\u044f\u043c\u0438, \u0441\u0432\u0451\u0440\u0442\u043e\u0447\u043d\u044b\u043c\u0438 \u0441\u043b\u043e\u044f\u043c\u0438, \u0441\u043b\u043e\u044f\u043c\u0438 \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \u041d\u043e \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u044b \u0437\u0430\u0445\u043e\u0442\u0438\u043c \u0447\u0442\u043e-\u0442\u043e \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u043e\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c, \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e <strong>\u0443\u0442\u043e\u043d\u0438\u043c<\/strong> \u0432 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0445 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f\u0445 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043e\u0432! \u0412\u043e\u0442, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u044f \u0441\u0447\u0438\u0442\u0430\u043b \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044b \u0434\u043b\u044f <code>RNN<\/code>.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0418 \u044d\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0430\u043c\u0430\u044f \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0435\u043a\u0443\u0440\u0440\u0435\u043d\u0442\u043d\u044b\u0445 \u0441\u043b\u043e\u0435\u0432, \u0434\u043b\u044f LSTM \u0438 GRU &#8212; \u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 <strong>\u0435\u0449\u0451<\/strong> \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u044f \u0441\u043e\u043c\u043d\u0435\u0432\u0430\u044e\u0441\u044c \u0447\u0442\u043e-\u0442\u043e \u0432\u043e\u043e\u0431\u0449\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u0432\u044b\u043f\u0438\u0441\u0430\u0442\u044c \u0444\u043e\u0440\u043c\u0443\u043b\u044b. \u0410 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0447\u0435\u0442\u0441\u044f! \u0417\u043d\u0430\u0447\u0438\u0442 \u043d\u0430\u0434\u043e \u0447\u0442\u043e-\u0442\u043e \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u0442\u044c!<\/p>\n<\/li>\n<li>\n<p> \u041d\u0435\u0442 \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u0438! \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0434\u0443\u043c\u0430\u0442\u044c \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442!<\/p>\n<p>\u041d\u0430\u043c \u0445\u043e\u0447\u0435\u0442\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0441\u0430\u043c\u0430 \u0441\u0447\u0438\u0442\u0430\u043b\u0430 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044b! \u0422\u043e\u0447\u043d\u043e \u0442\u0430\u043a\u0436\u0435, \u043a\u0430\u043a \u043c\u044b \u0432\u043e\u0437\u043b\u043e\u0436\u0438\u043b\u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043e\u0432 \u043d\u0430 \u043c\u0435\u0442\u043e\u0434 <code>.backward()<\/code> \u0432 \u0441\u043b\u043e\u044f\u0445, \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0430 <code>.backward()<\/code> &#8212; \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0432\u043e\u0437\u043b\u043e\u0436\u0438\u0442\u044c \u0432\u043e\u043e\u0431\u0449\u0435 \u0432\u0441\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f!<\/p>\n<\/li>\n<\/ol>\n<p>\u0412\u0441\u0435 \u043d\u0430\u0448\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0440\u0435\u0448\u0438\u0442\u044c \u0433\u0440\u0430\u0444 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439!<\/p>\n<p><strong>Computational Graph<\/strong><\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0432\u0441\u0435 \u043d\u0430\u0448\u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0432 \u0432\u0438\u0434\u0435 \u0433\u0440\u0430\u0444\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440!<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0412 \u0443\u0437\u043b\u0430\u0445 \u0431\u0443\u0434\u0443\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043b\u0438\u0431\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438. \u0423\u0437\u0435\u043b \u0432 \u0441\u0438\u043d\u0435\u043c \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0438\u043a\u0435 \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0441\u0435\u0431\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e, \u0447\u0442\u043e \u0431\u044b\u043b\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f &#171;\u0441\u043b\u043e\u0436\u0435\u043d\u0438\u0435&#187;, \u0434\u0432\u0443\u0445 \u0447\u0438\u0441\u0435\u043b <code>a<\/code> \u0438 <code>b<\/code>, \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 &#8212; \u0447\u0438\u0441\u043b\u043e <code>c<\/code>.<br \/>\u0423\u0437\u0435\u043b \u0432 \u043a\u0440\u0430\u0441\u043d\u043e\u043c \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0438\u043a\u0435 \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0441\u0435\u0431\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e, \u0447\u0442\u043e \u0431\u044b\u043b\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f &#171;\u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0435&#187;, \u0434\u0432\u0443\u0445 \u0447\u0438\u0441\u0435\u043b <code>b<\/code> \u0438 <code>c<\/code>, \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 &#8212; \u0447\u0438\u0441\u043b\u043e <code>f<\/code>.<br \/>\u041f\u043e\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0435 \u0442\u0430\u043a\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u043a\u0440\u0430\u0441\u0438\u0432\u0443\u044e \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e <a href=\"https:\/\/en.wikipedia.org\/wiki\/Chain_rule\" rel=\"noopener noreferrer nofollow\">chain rule<\/a>!<\/p>\n<p>\u041a\u043b\u044e\u0447\u0435\u0432\u0430\u044f \u0438\u0434\u0435\u044f \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043b\u0435 \u043a\u0430\u0436\u0434\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043d\u043e \u0438 \u0441\u0440\u0430\u0437\u0443 \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0435.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>c<\/code> = <code>a<\/code> + <code>b<\/code>. \u0422\u043e\u0433\u0434\u0430 \u0432 <code>c<\/code> \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u0430\u043c\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>c<\/code>, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0435 \u043e\u0442 <code>a<\/code> \u0438 <code>b<\/code>, \u0442\u043e \u0435\u0441\u0442\u044c (<code>c<\/code>, <code>1<\/code>, <code>1<\/code>)<br \/>\u0414\u043b\u044f <code>c = a * b<\/code> \u0431\u0443\u0434\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c (<code>c<\/code>, <code>b<\/code>, <code>a<\/code>), \u0434\u043b\u044f <code>c = a \/ b<\/code>, \u0431\u0443\u0434\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c (<code>c<\/code>, <code>1 \/ b<\/code>, <code>-a \/ b^2<\/code>) &#8212; \u043b\u043e\u0433\u0438\u043a\u0430 \u044f \u043d\u0430\u0434\u0435\u044e\u0441\u044c \u0441\u0442\u0430\u043b\u0430 \u043f\u043e\u043d\u044f\u0442\u043d\u0430.<br \/>\u041a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0432\u0441\u0435 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0438 \u0438\u0445 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0435, \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u043b\u044e\u0431\u044b\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0438 \u0431\u0440\u0430\u0442\u044c \u043b\u044e\u0431\u044b\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0435 \u043e\u0442 \u043d\u0438\u0445, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043c\u044b \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u0441\u0447\u0438\u0442\u0430\u0435\u043c \u0441\u0432\u043e\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442 &#8212; \u0430 \u044d\u0442\u043e \u0437\u0430\u0434\u0430\u0447\u0430 \u0441\u0438\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0449\u0435, \u0447\u0435\u043c \u0431\u0440\u0430\u0442\u044c \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442 \u043e\u0442 \u0438\u0442\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f. \u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0437 \u0436\u0438\u0437\u043d\u0438. \u0412\u044b \u0447\u0438\u0442\u0430\u0435\u0442\u0435 \u043c\u043d\u043e\u0433\u043e \u043a\u043d\u0438\u0433 \u0440\u0430\u0437\u043d\u044b\u0445 \u0436\u0430\u043d\u0440\u043e\u0432. \u041d\u043e \u0432\u044b \u0442\u0430\u043a\u0436\u0435 \u0445\u043e\u0442\u0438\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u043a\u0430\u0436\u0434\u044b\u0439 \u0436\u0430\u043d\u0440 \u043b\u0435\u0436\u0430\u043b \u0432 \u0441\u0432\u043e\u0435\u0439 \u043f\u043e\u043b\u043a\u0435. \u0427\u0442\u043e \u043f\u0440\u043e\u0449\u0435 &#8212; \u043f\u043e\u0441\u043b\u0435 \u043f\u0440\u043e\u0447\u0442\u0435\u043d\u0438\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043a\u043d\u0438\u0433\u0438 \u043a\u043b\u0430\u0441\u0442\u044c \u0432 \u043d\u0443\u0436\u043d\u0443\u044e \u043f\u043e\u043b\u043a\u0443 \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u0431\u0438\u0440\u0430\u0442\u044c \u0446\u0435\u043b\u0443\u044e \u0441\u0442\u043e\u043f\u043a\u0443 \u043d\u0430\u043a\u043e\u043f\u0438\u0432\u0448\u0438\u0445\u0441\u044f \u043a\u043d\u0438\u0433? \u0422\u0430\u043a\u0436\u0435 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0438 \u0437\u0434\u0435\u0441\u044c<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041f\u0440\u043e\u0449\u0435 \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u0443\u044e \u0432\u0441\u0435\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438\u043b\u0438 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u0442 <code>x1\/x2<\/code>, \u043f\u043e\u0442\u043e\u043c \u043e\u0442 <code>sin(x)<\/code>, \u043f\u043e\u0442\u043e\u043c <code>exp(x2)<\/code> \u0438 \u0432 \u043a\u043e\u043d\u0446\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u043c\u043d\u043e\u0436\u0438\u0442\u044c \u0438\u0445 \u043f\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u0443 chain rule?<\/p>\n<p>\u0417\u0430\u0433\u043b\u044f\u043d\u0435\u043c <a href=\"https:\/\/sidsite.com\/posts\/autodiff\/#:~:text=A%20variable%20(or,the%20child%20variable.\" rel=\"noopener noreferrer nofollow\">\u0441\u044e\u0434\u0430<\/a><\/p>\n<p>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f (\u0438\u043b\u0438 \u0443\u0437\u0435\u043b) \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0434\u0432\u0435 \u0447\u0430\u0441\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<ul>\n<li>\n<p><strong>value<\/strong> \u2014 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439.<\/p>\n<\/li>\n<li>\n<p><strong>local_gradients<\/strong> \u2014 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u00ab\u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0435\u00bb.<\/p>\n<\/li>\n<\/ul>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>get_gradients<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 <code>local_gradients<\/code> \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0433\u043e \u043e\u0431\u0445\u043e\u0434\u0430 \u0433\u0440\u0430\u0444\u0430, \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u044f \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044b. (<em>\u0422. \u0435. <\/em><code>local_gradients<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0435\u0441\u0442\u044c \u0441\u0432\u043e\u0438 <code>local_gradients<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0435\u0441\u0442\u044c \u0441\u0432\u043e\u0438 <code>local_gradients<\/code>, \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435.)<\/p>\n<p>\u0413\u0440\u0430\u0434\u0438\u0435\u043d\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442\u0441\u044f \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043f\u0440\u0430\u0432\u0438\u043b:<\/p>\n<ol>\n<li>\n<p>\u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0443\u0442\u0438 \u043e\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043a \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0443\u043c\u043d\u043e\u0436\u044c\u0442\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0440\u0451\u0431\u0435\u0440 \u043f\u0443\u0442\u0438 (\u0447\u0442\u043e \u0434\u0430\u0451\u0442 <code>path_value<\/code>).<\/p>\n<\/li>\n<li>\n<p>\u0421\u043b\u043e\u0436\u0438\u0442\u0435 \u0432\u0441\u0435 <code>path_value<\/code> \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0443\u0442\u0438.<\/p>\n<\/li>\n<\/ol>\n<p>\u2026 \u042d\u0442\u043e \u0434\u0430\u0451\u0442 \u0447\u0430\u0441\u0442\u043d\u0443\u044e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u0443\u044e \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0441\u043a\u0435\u043b\u0435\u0442 \u0431\u0443\u0434\u0443\u0449\u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430!<\/p>\n<pre><code class=\"python\">class Tensor:     def __init__(self, value, local_gradients=None):         self.value = value         self.local_gradients = local_gradients <\/code><\/pre>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e \u0441\u043b\u043e\u0436\u0435\u043d\u0438\u044f!<\/p>\n<pre><code class=\"python\">class Tensor:     def __init__(self, value, local_gradients=None):         self.value = value         self.local_gradients = local_gradients              def __add__(self, other):         value = self.value + other.value         local_gradients = ((self, 1), (other, 1))         return Tensor(value, local_gradients) <\/code><\/pre>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0443<\/p>\n<pre><code class=\"python\">a = Tensor(5) b = Tensor(10) c = a + b c, c.value, c.local_gradients &gt;&gt;&gt; (&lt;__main__.Tensor at 0x7d85aad85810&gt;,  15,  ((&lt;__main__.Tensor at 0x7d85aad87160&gt;, 1),   (&lt;__main__.Tensor at 0x7d85aad85660&gt;, 1))) <\/code><\/pre>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0435! \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043c\u0435\u0442\u043e\u0434 <code>.backward()<\/code><\/p>\n<pre><code class=\"python\">from collections import defaultdict      class Tensor:     def backward(self):     # \u0441\u043b\u043e\u0432\u0430\u0440\u044c \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445         gradients = defaultdict(lambda: 0)         # \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043e\u0432 \u0443 \u0434\u0435\u0442\u0435\u0439, \u043f\u043e\u0442\u043e\u043c \u0443 \u0438\u0445 \u0434\u0435\u0442\u0435\u0439 \u0438 \u0442.\u0434.         def compute_gradients(obj, path_value):             if obj.local_gradients: # \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0438 \u0443\u0437\u0435\u043b \u043b\u0438\u0441\u0442\u043e\u043c (leaf)             # \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0440\u0435\u0431\u0435\u043d\u043a\u0430 \u0438 \u0435\u0433\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u0441\u0447\u0438\u0442\u0430\u043d\u043d\u044b\u0439 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442                 for child, local_grad_value in obj.local_gradients:                 # \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c chain rule \u0438 \u0443\u043c\u043d\u043e\u0436\u0430\u0435\u043c \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u043d\u044b\u0439 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442 \u043d\u0430 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442 child                     path_value_to_child = path_value * local_grad_value                     # \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044b \u043e\u0442 \u0440\u0430\u0437\u043d\u044b\u0445 \u043b\u0438\u0441\u0442\u044c\u0435\u0432                     gradients[child] += path_value_to_child                     # \u0441\u0447\u0438\u0442\u0430\u0435\u043c \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0434\u0435\u0442\u0435\u0439 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e child                     compute_gradients(child, path_value_to_child)                      compute_gradients(self, path_value=1)          return gradients <\/code><\/pre>\n<p>\u0421\u043c\u043e\u0442\u0440\u0438\u043c<\/p>\n<pre><code class=\"python\">a = Tensor(5) b = Tensor(10) c = a + b gradients = c.backward() gradients[a], gradients[b] &gt;&gt;&gt; (1, 1)<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u0438\u043c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u044f<\/p>\n<pre><code class=\"python\">def __mul__(self, other): value = self.value * other.value local_gradients = ((self, other.value), (other, self.value)) return Tensor(value, local_gradients) <\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u043e\u0439 \u043f\u043e \u043f\u0435\u0440\u0432\u043e\u043c\u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0443, \u0431\u0443\u0434\u0435\u0442 <strong>\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435<\/strong> \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u0438 \u043d\u0430\u043e\u0431\u043e\u0440\u043e\u0442!<\/p>\n<pre><code class=\"python\">a = Tensor(4) b = Tensor(3) c = a + b # = 4 + 3 = 7 d = a * c # = 4 * 7 = 28  gradients = d.backward()  print('d.value =', d.value) print(\"The partial derivative of d with respect to a =\", gradients[a]) &gt;&gt;&gt; d.value = 28 The partial derivative of d with respect to a = 11 <\/code><\/pre>\n<pre><code class=\"python\">print('gradients[b] =', gradients[b]) print('gradients[c] =', gradients[c]) &gt;&gt;&gt; gradients[b] = 4 gradients[c] = 4 <\/code><\/pre>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0435 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044b<\/p>\n<pre><code class=\"python\">print('dict(d.local_gradients)[a] =', dict(d.local_gradients)[a]) print('dict(d.local_gradients)[c] =', dict(d.local_gradients)[c]) print('dict(c.local_gradients)[a] =', dict(c.local_gradients)[a]) print('dict(c.local_gradients)[b] =', dict(c.local_gradients)[b]) &gt;&gt;&gt; dict(d.local_gradients)[a] = 7 dict(d.local_gradients)[c] = 4 dict(c.local_gradients)[a] = 1 dict(c.local_gradients)[b] = 1 <\/code><\/pre>\n<p>\u0412\u0441\u0451 \u0432\u0435\u0440\u043d\u043e, \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0435\u0440\u0435\u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043d\u0430 \u0431\u0443\u043c\u0430\u0433\u0435!<\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0449\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439!<\/p>\n<pre><code class=\"python\"># \u0432\u044b\u0447\u0438\u0442\u0430\u043d\u0438\u0435 def __sub__(self, other): value = self.value - other.value local_gradients = ((self, 1), (other, -1)) return Tensor(value, local_gradients)  # \u0443\u043d\u0430\u0440\u043d\u044b\u0439 \u043c\u0438\u043d\u0443\u0441 def __neg__(self):  value = -self.value local_gradients = ((self, -1),) return Tensor(value, local_gradients)  # \u0434\u0435\u043b\u0435\u043d\u0438\u0435 def __truediv__(self, other):  value = self.value \/ other.value local_gradients = ((self, 1 \/ other.value), (other, - self.value \/ (other.value**2))) return Tensor(value, local_gradients) <\/code><\/pre>\n<p>\u041f\u043e\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u0443\u044e \u043f\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438<\/p>\n<pre><code class=\"python\">def f(a, b):    <\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-443701","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/443701","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=443701"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/443701\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=443701"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=443701"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=443701"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}