diff --git a/build/404.md b/build/404.md deleted file mode 100644 index 318d8ca58..000000000 --- a/build/404.md +++ /dev/null @@ -1,3 +0,0 @@ -# 404 - -![](img/404.jpg) diff --git a/build/Makefile b/build/Makefile deleted file mode 100644 index f2ace4966..000000000 --- a/build/Makefile +++ /dev/null @@ -1,231 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = _build - -# User-friendly check for sphinx-build -ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) - $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don\'t have Sphinx installed, grab it from http://sphinx-doc.org/) -endif - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . -# the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -all: html -.PHONY: help -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " applehelp to make an Apple Help Book" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " epub3 to make an epub3" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " texinfo to make Texinfo files" - @echo " info to make Texinfo files and run them through makeinfo" - @echo " gettext to make PO message catalogs" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " xml to make Docutils-native XML files" - @echo " pseudoxml to make pseudoxml-XML files for display purposes" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - @echo " coverage to run coverage check of the documentation (if enabled)" - @echo " dummy to check syntax errors of document sources" - -.PHONY: clean -clean: - rm -rf $(BUILDDIR)/* - -.PHONY: html -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -.PHONY: dirhtml -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -.PHONY: singlehtml -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -.PHONY: pickle -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -.PHONY: json -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -.PHONY: htmlhelp -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -.PHONY: qthelp -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/TheStraightDope.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/TheStraightDope.qhc" - -.PHONY: applehelp -applehelp: - $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp - @echo - @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." - @echo "N.B. You won't be able to view it unless you put it in" \ - "~/Library/Documentation/Help or install it in your application" \ - "bundle." - -.PHONY: devhelp -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/TheStraightDope" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/TheStraightDope" - @echo "# devhelp" - -.PHONY: epub -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -.PHONY: epub3 -epub3: - $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3 - @echo - @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3." - -.PHONY: latex -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -.PHONY: latexpdf -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -.PHONY: latexpdfja -latexpdfja: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through platex and dvipdfmx..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -.PHONY: text -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -.PHONY: man -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -.PHONY: texinfo -texinfo: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo - @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." - @echo "Run \`make' in that directory to run these through makeinfo" \ - "(use \`make info' here to do that automatically)." - -.PHONY: info -info: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo "Running Texinfo files through makeinfo..." - make -C $(BUILDDIR)/texinfo info - @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." - -.PHONY: gettext -gettext: - $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale - @echo - @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." - -.PHONY: changes -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -.PHONY: linkcheck -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -.PHONY: doctest -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." - -.PHONY: coverage -coverage: - $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage - @echo "Testing of coverage in the sources finished, look at the " \ - "results in $(BUILDDIR)/coverage/python.txt." - -.PHONY: xml -xml: - $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml - @echo - @echo "Build finished. The XML files are in $(BUILDDIR)/xml." - -.PHONY: pseudoxml -pseudoxml: - $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml - @echo - @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." - -.PHONY: dummy -dummy: - $(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy - @echo - @echo "Build finished. Dummy builder generates no files." diff --git a/build/_static/d2l-ai.png b/build/_static/d2l-ai.png deleted file mode 100644 index a2fa99c49..000000000 Binary files a/build/_static/d2l-ai.png and /dev/null differ diff --git a/build/_static/discuss.js b/build/_static/discuss.js deleted file mode 100644 index dd84f98df..000000000 --- a/build/_static/discuss.js +++ /dev/null @@ -1,31 +0,0 @@ -$(document).ready(function () { - var discuss_str = '参与讨论' - $('h2').each(function(){ - if ($(this).text().indexOf("扫码") != -1) { - var url = $(this).find('a').attr('href'); - var tokens = url.split('/'); - var topic_id = tokens[tokens.length-1]; - - $(this).html('

'.concat(discuss_str).concat('

')); - $(this).parent().append('
'); - - $('img').each(function(){ - if ($(this).attr('src').indexOf("qr_") != -1) { - $(this).hide(); - } - }); - - DiscourseEmbed = { discourseUrl: 'https://discuss.gluon.ai/', topicId: topic_id }; - (function() { - var d = document.createElement('script'); d.type = 'text/javascript'; - d.async = true; - d.src = DiscourseEmbed.discourseUrl + 'javascripts/embed.js'; - (document.getElementsByTagName('head')[0] || - document.getElementsByTagName('body')[0]).appendChild(d); - })(); - } - }); - - var replaced = $('body').html().replace(/扫码直达讨论区/g, discuss_str); - $('body').html(replaced); -}); diff --git a/build/_static/favicon.png b/build/_static/favicon.png deleted file mode 100644 index 34cec8cfb..000000000 Binary files a/build/_static/favicon.png and /dev/null differ diff --git a/build/_static/frontpage.css b/build/_static/frontpage.css deleted file mode 100644 index 720c98c40..000000000 --- a/build/_static/frontpage.css +++ /dev/null @@ -1,111 +0,0 @@ -h1, .side-doc-outline { - display: none; -} -.document .page-content { - width: 100%; -} - -h2, h3, h4 { - letter-spacing: 2px; -} -.mdl-grid { - align-items: center; - justify-content: center; - text-align: center; - padding: 150px 0 0 0; -} - -.endorsement h3 { - padding-top: 1.5em; - font-size: 1.4em; -} - -.endorsement p { - line-height: 2em; - /* text-align: right; */ -} - -.endorsement .author { - font-weight: 500; - font-size: 1.4em; - margin: 0; -} - -h2.toc { - padding: 150px 0 0 0; -} - -.header h2 { - font-size: 30px; - padding-bottom: 35px; -} - -.header p { - font-size: 24px; - letter-spacing: 2px; - line-height: 36px; - padding-bottom: 10px; -} - - -.header img { - max-width: 350px; -} - -.header .mdl-button { - margin: 0px 10px; - letter-spacing: 2px; - font-size: 16px; - margin: 1rem 1.5rem; - height: 40px; - width: 120px; -} - - -.author-item { - max-width: 300px; -} - -.author-item h3 { - padding-top: 25px; - padding-bottom: 10px; -} -.author-item img { - border-radius: 50%; - width: 120px; -} -.authors h4 { - width: 100%; -} - -.features .mdl-cell { - padding: 0 36px; -} -.features h2, .features-2 h2 { - padding-bottom: 24px; -} -.features-2 p { - padding: 0 200px; -} - - -@media (max-width: 1000px) { - .mdl-grid, h2.toc { - padding: 50px 0 0 0; - } - - .header img, .features-2 img { - max-width: 300px; - } - - .header .mdl-cell--1-col { - display: none; - } - .features img { - max-width: 350px; - } - - .features-2 p { - padding: 0 24px; - } -} diff --git a/build/_static/gluon.png b/build/_static/gluon.png deleted file mode 100644 index 4b5612978..000000000 Binary files a/build/_static/gluon.png and /dev/null differ diff --git a/build/_static/gluon_s2.png b/build/_static/gluon_s2.png deleted file mode 100644 index 08cd0fdbe..000000000 Binary files a/build/_static/gluon_s2.png and /dev/null differ diff --git a/build/_static/gluon_white.png b/build/_static/gluon_white.png deleted file mode 100644 index bb5f4099a..000000000 Binary files a/build/_static/gluon_white.png and /dev/null differ diff --git a/build/_static/google_analytics.js b/build/_static/google_analytics.js deleted file mode 100644 index 7529c8add..000000000 --- a/build/_static/google_analytics.js +++ /dev/null @@ -1,7 +0,0 @@ - (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ - (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), - m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) - })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); - - ga('create', 'UA-96378503-2', 'auto'); - ga('send', 'pageview'); diff --git a/build/_static/logo-with-text.png b/build/_static/logo-with-text.png deleted file mode 100644 index c56c7811e..000000000 Binary files a/build/_static/logo-with-text.png and /dev/null differ diff --git a/build/_static/zh-d2l-ai.png b/build/_static/zh-d2l-ai.png deleted file mode 100644 index fd6cd756b..000000000 Binary files a/build/_static/zh-d2l-ai.png and /dev/null differ diff --git a/build/aws4learn.md b/build/aws4learn.md deleted file mode 100644 index b9bf3963c..000000000 --- a/build/aws4learn.md +++ /dev/null @@ -1,41 +0,0 @@ -# 申请用于学习或教学《动手学深度学习》的免费计算资源 - -如果你是学习或教学《动手学深度学习》的在校学生或老师,可通过以下方式申请免费计算资源。AWS的工作人员将尽快审批每份申请。需要注意的是,工作人员不能保证每份申请都能够被批准:提供真实、准确、详细的信息将有助于申请获批。在计算资源上配置环境并运行本书内容的方法可参考:“[使用AWS运行代码](../chapter_appendix/aws.html)”(必读),以及“[获取和运行本书的代码](../chapter_prerequisite/install.html)”和“[使用Jupyter记事本](../chapter_appendix/jupyter.html)”(选读)。 - - -## 用于学习 - -在校学生或老师可申请用于本书学习的免费计算资源(即在校期间每年价值75~100美金的云计算资源)。 - -如果你有edu邮箱,申请链接如下: - -[https://www.awseducate.com/registration?lang=zh_CN#APP_TYPE](https://www.awseducate.com/registration?lang=zh_CN#APP_TYPE) - -如果你没有edu邮箱,请发邮件至 aws-educate-china@amazon.com 申请。请在邮件的标题和内容分别填写以下内容: - -标题:申请用于学习《动手学深度学习》的云计算资源 - -内容:请提供姓名、电子邮箱、手机号码、学校名称。学生需提供任一可验证本人身份的授课老师的姓名、手机号码和电子邮箱;老师需提供可验证本人身份的同专业任一其他授课老师的姓名、手机号码和电子邮箱。 - - -## 用于教学 - -计划使用《动手学深度学习》授课的在校老师可以为自己、助教和学生申请用于本书教学的免费计算资源。 - -请在申请链接中的“研究介绍”一项回答以下几个问题: - -1. 请提供课程主页(如有)、课程名称、教师人数、助教人数和学生人数。 -2. 请描述教学计划,如学生的背景情况、如何使用《动手学深度学习》教学、计算资源的使用要求、课程大纲等。 - -申请链接如下: - -[https://aws.amazon.com/cn/events/educate_cloud/research-credits/](https://aws.amazon.com/cn/events/educate_cloud/research-credits/) - - -### 加入《动手学深度学习》教学交流群 - -如果你对使用《动手学深度学习》教学有任何问题,欢迎加入微信群与作者、AWS工作人员以及其他老师交流。 - -由于群人数有限,仅限老师入群:请扫码添加AWS的邢进老师的微信申请入群。 - - diff --git a/build/conf.py b/build/conf.py deleted file mode 100644 index b57c1973b..000000000 --- a/build/conf.py +++ /dev/null @@ -1,411 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# The D2L documentation build configuration file, created by -# sphinx-quickstart on Tue Jul 18 10:40:45 2017. -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys -import os -from recommonmark.parser import CommonMarkParser -from recommonmark.transform import AutoStructify - -# Use footnote size for code block. -from sphinx.highlighting import PygmentsBridge -from pygments.formatters.latex import LatexFormatter - -class CustomLatexFormatter(LatexFormatter): - def __init__(self, **options): - super(CustomLatexFormatter, self).__init__(**options) - self.verboptions = r"formatcom=\footnotesize" - -PygmentsBridge.latex_formatter = CustomLatexFormatter - - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.doctest', - 'sphinx.ext.intersphinx', - 'sphinx.ext.todo', - 'sphinx.ext.mathjax', - 'sphinx.ext.ifconfig', - 'sphinx.ext.viewcode', - 'nbsphinx', - 'IPython.sphinxext.ipython_console_highlighting', -] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -source_parsers = {'.md': CommonMarkParser} - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# source_suffix = ['.rst', '.md'] -source_suffix = ['.rst', '.ipynb', '.md'] - -# The encoding of source files. -#source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = '《动手学深度学习》' -copyright = '2017--2019' -author = "Aston Zhang\\\\Mu Li\\\\Zachary C. Lipton\\\\Alexander J. Smola" - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '' -# The full version, including alpha/beta/rc tags. -release = '' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = 'zh_CN' - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This patterns also effect to html_static_path and html_extra_path -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '**.ipynb_checkpoints', - 'mx-theme'] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = True - - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# html_theme = 'sphinx_rtd_theme' - -html_theme_path = ['mx-theme'] -html_theme = 'mxtheme' -html_theme_options = { - 'primary_color': 'blue', - 'accent_color': 'deep_orange', - 'header_links' : [ - ('伯克利深度学习课程', 'https://courses.d2l.ai/berkeley-stat-157/index.html', True, 'fas fa-user-graduate'), - ('PDF', 'https://zh.d2l.ai/d2l-zh.pdf', True, 'fas fa-file-pdf'), - ('Jupyter 记事本文件', 'https://zh.d2l.ai/d2l-zh.zip', True, 'fas fa-download'), - ('讨论', 'https://discuss.gluon.ai/c/lecture?order=views', True, 'fab fa-discourse'), - ('GitHub', 'https://github.com/d2l-ai/d2l-zh', True, 'fab fa-github'), - ('English Version', 'https://d2l.ai', True, 'fas fa-external-link-alt'), - ], - 'show_footer': True -} - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - -# The name for this set of Sphinx documents. -# " v documentation" by default. -#html_title = 'The D2L v0.1' - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -html_logo = '_static/logo-with-text.png' - -# The name of an image file (relative to this directory) to use as a favicon of -# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -html_favicon = '_static/favicon.png' - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -#html_extra_path = [] - -# If not None, a 'Last updated on:' timestamp is inserted at every page -# bottom, using the given strftime format. -# The empty string is equivalent to '%b %d, %Y'. -#html_last_updated_fmt = None - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_domain_indices = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None - -# Language to be used for generating the HTML full-text search index. -# Sphinx supports the following languages: -# 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja' -# 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr', 'zh' -html_search_language = 'zh' - -# A dictionary with options for the search language support, empty by default. -# 'ja' uses this config value. -# 'zh' user can custom change `jieba` dictionary path. -import jieba -jieba_dict = os.path.join(os.path.dirname(jieba.__file__), 'dict.txt') -html_search_options = {'dict':jieba_dict} - -# The name of a javascript file (relative to the configuration directory) that -# implements a search results scorer. If empty, the default will be used. -#html_search_scorer = 'scorer.js' - -# Output file base name for HTML help builder. -htmlhelp_basename = 'D2Ldoc' - -# -- Options for LaTeX output --------------------------------------------- - - -latex_elements = { - # 'papersize' : 'a4paper', - 'utf8extra' : '', - 'inputenc' : '', - 'babel' : r'''\usepackage[english]{babel}''', - 'preamble' : r''' -\usepackage{ctex} -\setmainfont{Source Serif Pro} -\setsansfont{Source Sans Pro} -\setmonofont{Source Code Pro} -\setCJKmainfont[BoldFont=Source Han Serif SC SemiBold]{Source Han Serif SC} -\setCJKsansfont[BoldFont=Source Han Sans SC Medium]{Source Han Sans SC Normal} -\setCJKmonofont{Source Han Sans SC Normal} - - -\addto\captionsenglish{\renewcommand{\chaptername}{}} -\addto\captionsenglish{\renewcommand{\contentsname}{目录}} - -\usepackage[draft]{minted} -\fvset{breaklines=true, breakanywhere=true} -\setlength{\headheight}{13.6pt} - -\makeatletter - \fancypagestyle{normal}{ - \fancyhf{} - \fancyfoot[LE,RO]{{\py@HeaderFamily\thepage}} - \fancyfoot[LO]{{\py@HeaderFamily\nouppercase{\rightmark}}} - \fancyfoot[RE]{{\py@HeaderFamily\nouppercase{\leftmark}}} - \fancyhead[LE,RO]{{\py@HeaderFamily }} - } -\makeatother - -\CJKsetecglue{} -\usepackage{zhnumber} -''', -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', - -# Latex figure (float) alignment -#'figure_align': 'htbp', -'figure_align': 'H', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - (master_doc, 'd2l-zh.tex', '动手学深度学习', - author, 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = '_static/gluon.png' - -# latex_engine = 'xelatex' -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# If true, show page references after internal links. -#latex_show_pagerefs = False - -# If true, show URL addresses after external links. -#latex_show_urls = False - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -latex_domain_indices = False - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'd2l-zh', 'The D2L Documentation', - [author], 1) -] - -# If true, show URL addresses after external links. -#man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - (master_doc, 'd2l-zh', 'The D2L Documentation', - author, 'd2l-zh', 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -#texinfo_appendices = [] - -# If false, no module index is generated. -#texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False - - -# Example configuration for intersphinx: refer to the Python standard library. -# intersphinx_mapping = {'https://docs.python.org/': None} - - -# Figure X.y (1 level) -numfig = True -numfig_secnum_depth = 1 - - -intersphinx_mapping = { - # 'python': 'https://docs.python.org/3.5', - # 'matplotlib': 'https://matplotlib.org', - # 'numpy': ('http://docs.scipy.org/doc/numpy/', None), - # 'mxnet': ('http://mxnet.io', None) -} - -# notebooks will be executed by sphnix_plugin -nbsphinx_execute = 'never' - -# let the source file format to be xxx.ipynb instead of xxx.ipynb.txt -html_sourcelink_suffix = '' - -def image_caption(app, docname, source): - for i, src in enumerate(source): - out = '' - for l in src.split('\n'): - if '![' in l and 'img' in l: - # Sphinx does not allow very long caption with space, replace space - # with a special token - l = l.strip().replace(' ', 'Ⓐ') - out += l + '\n' - source[i] = out - -def setup(app): - app.add_transform(AutoStructify) - app.add_config_value('recommonmark_config', { - }, True) - app.add_javascript('google_analytics.js') - app.add_javascript('discuss.js') - app.connect('source-read', image_caption) diff --git a/build/env.yml b/build/env.yml deleted file mode 100644 index ac534050a..000000000 --- a/build/env.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: d2l-zh-build -dependencies: -- python=3.6 -- jupyter=1.0.0 -- sphinx=1.8.2 -- matplotlib=2.2.2 -- pandas=0.23.4 -- notebook=5.0.0 -- pip: - - nbsphinx==0.3.5 - - recommonmark==0.4.0 - - https://github.com/mli/notedown/tarball/master - - mxnet-cu101==1.5.0 - - d2lzh==1.0.0 - - jieba==0.39 - - beautifulsoup4==4.7.1 - - awscli - - urllib3>=1.25.4 diff --git a/build/frontpage.html b/build/frontpage.html deleted file mode 100644 index 45817040e..000000000 --- a/build/frontpage.html +++ /dev/null @@ -1,280 +0,0 @@ - - -
-
- -
-
-
-
-

《动手学深度学习》

-

面向中文读者的能运行、可讨论的深度学习教科书

-
-
- -
-
-

公告

-
- -
-
-
- -
-
-
- -

阿斯顿·张

-

亚马逊高级科学家,美国伊利诺伊大学香槟分校计算机科学博士。

-
-
-
-
- -

李沐

-

亚马逊首席(principal)科学家,美国卡内基梅隆大学计算机系博士。

-
-
-
-
- -

扎卡里 C. 立顿

-

亚马逊科学家,美国卡内基梅隆大学助理教授,加州大学圣迭戈分校计算机科学博士。

-
-
-
-
- -

亚历山大 J. 斯莫拉

-

亚马逊副总裁/杰出科学家,德国柏林工业大学计算机科学博士。

-
-
-

以及来自社区的 100+ 位贡献者

-

为本书贡献

- Star - Fork -
- -
- -
-

学术界推荐

-
-

“Dive into this book if you want to dive into deep learning!”

-

韩家炜

-

ACM 院士、IEEE 院士
美国伊利诺伊大学香槟分校计算机系 Michael Aiken Chair 教授 -

-
- -
-

“This is a highly welcome addition to the machine learning literature.”

-

Bernhard Schölkopf

-

ACM 院士、德国国家科学院院士
德国马克斯•普朗克研究所智能系统院院长

-
- -
-

“书中代码可谓‘所学即所用’。”

-

周志华

-

ACM 院士、IEEE 院士、AAAS 院士
南京大学计算机科学与技术系主任

-
- -
-

“这本书可以帮助深度学习实践者快速提升自己的能力。”

-

张潼

-

ASA 院士、IMS 院士
香港科技大学计算机系和数学系教授

-
- -
- -
-

工业界推荐

-
-

“一本优秀的深度学习教材,值得任何想了解深度学习何以引爆人工智能革命的人关注。” -

-

黄仁勋

-

NVIDIA创始人 & CEO

-
- -
-

“《动手学深度学习》是最适合工业界研发工程师学习的。我毫无保留地向广大的读者们强烈推荐。” -

-

余凯

-

地平线公司创始人 & CEO

-
- -
-

“强烈推荐这本书!我特别赞赏这种手脑一体的学习方式。”

-

漆远

-

蚂蚁金服副总裁、首席AI科学家

-
- -
-

“《动手学深度学习》是一本很容易让学习者上瘾的书。”

-

沈强

-

将门创投创始合伙人

-
-
-
-
-
-
-

每一小节都是可以运行的 Jupyter 记事本

-

你可以自由修改代码和超参数来获取及时反馈,从而积累深度学习的实战经验。

-
-
-
- -
-
- -
-

公式 + 图示 + 代码

-

我们不仅结合文字、公式和图示来阐明深度学习里常用的模型和算法,还提供代码来演示如何从零开始实现它们,并使用真实数据来提供一个交互式的学习体验。

- -
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

活跃社区支持

-

你可以通过每个章节最后的链接来同社区的数千名小伙伴一起讨论学习。

-
-
-
- -
-
-

本书(中英文版)被用作教材或参考书

-
如有遗漏,请邮件至d2lbook.en@gmail.com
-
- 北京大学
- 复旦大学
- 哈尔滨工业大学
- 清华大学
- 上海财经大学
- 上海交通大学
- 浙江大学
- 中国科学技术大学
- Carnegie Mellon University(美国)
- Emory University(美国)
- Gazi Üniversitesi(土耳其)
- Georgia Institute of Technology(美国)
- Habib University(巴基斯坦)
- Hasso-Plattner-Institut(德国)
- Hiroshima University(日本)
- Imperial College London(英国)
- Indian Institute of Technology Bombay(印度)
- Indian Institute of Technology Kanpur(印度)
- Indian Institute of Technology Kharagpur(印度)
- Indian Institute of Technology Mandi(印度)
- Indian Institute of Technology Ropar(印度)
- Institut Supérieur De L'electronique Et Du Numérique(法国)
- İstanbul Teknik Üniversitesi (土耳其)
- King Abdullah University of Science and Technology(沙特阿拉伯)
- Kyungpook National University(韩国)
- Massachusetts Institute of Technology(美国)
- McGill University(加拿大)
- National University of Singapore(新加坡)
- Nazarbayev University(哈萨克斯坦)
- Northeastern University(美国)
- Pontificia Universidad Católica de Chile(智利)
- Rutgers, The State University of New Jersey(美国)
- Sapienza Università di Roma(意大利)
- Stanford University(美国)
- Technische Universiteit Delft(荷兰)
- Texas A&M University(美国)
- Universidad Carlos III de Madrid(西班牙)
- Universidad Nacional de Colombia Sede Manizales(哥伦比亚)
- Universidade Federal de Minas Gerais(巴西)
- Università degli Studi di Brescia(意大利)
- Universität Heidelberg(德国)
- Universitatea de Vest din Timișoara(罗马尼亚)
- University of Arkansas(美国)
- University of California, Berkeley(美国)
- University of California, Los Angeles(美国)
- University of California, San Diego(美国)
- University of California, Santa Barbara(美国)
- University of Illinois at Urbana-Champaign(美国)
- University of Maryland(美国)
- University of Minnesota, Twin Cities(美国)
- University of New Hampshire(美国)
- University of North Carolina at Chapel Hill(美国)
- University of Pennsylvania(美国)
- University of Technology Sydney(澳大利亚)
- University of Washington(美国)
- University of Waterloo(加拿大)
- Universitat Politècnica de Catalunya(西班牙)
- Vietnamese-German University(越南) -
-
- -
-
-

英文版引用

-
-
- -
-      @book{zhang2020dive,
-          title={Dive into Deep Learning},
-          author={Aston Zhang and Zachary C. Lipton and Mu Li and Alexander J. Smola},
-          note={\url{http://www.d2l.ai}},
-          year={2020}
-      }
-	  
-
-
-
-
- -

目录

- - diff --git a/build/index.rst b/build/index.rst deleted file mode 100644 index f93e9db39..000000000 --- a/build/index.rst +++ /dev/null @@ -1,34 +0,0 @@ -《动手学深度学习》 -==================== - -.. raw:: html - :file: frontpage.html - - -.. toctree:: - :maxdepth: 1 - - chapter_preface/preface - - -.. toctree:: - :maxdepth: 1 - - chapter_how-to-use/how-to-use - - -.. toctree:: - :maxdepth: 2 - :numbered: - - chapter_introduction/deep-learning-intro - chapter_prerequisite/index - chapter_deep-learning-basics/index - chapter_deep-learning-computation/index - chapter_convolutional-neural-networks/index - chapter_recurrent-neural-networks/index - chapter_optimization/index - chapter_computational-performance/index - chapter_computer-vision/index - chapter_natural-language-processing/index - chapter_appendix/index diff --git a/build/mx-theme b/build/mx-theme deleted file mode 160000 index 38ae27e0f..000000000 --- a/build/mx-theme +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 38ae27e0f8406123b004631e765fc9daa9ce7656 diff --git a/build/utils b/build/utils deleted file mode 160000 index 5d794f99e..000000000 --- a/build/utils +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5d794f99e7592e827a5388b463a43c55fe80f715 diff --git a/chapter_attention-mechanisms/transformer.md b/chapter_attention-mechanisms/transformer.md index 5deea82f9..487200def 100644 --- a/chapter_attention-mechanisms/transformer.md +++ b/chapter_attention-mechanisms/transformer.md @@ -558,7 +558,7 @@ enc_attention_weights = d2l.reshape( enc_attention_weights.shape ``` -在编码器的自我注意中,查询和键来自相同的输入序列。由于填充令牌不具有意义,并且输入序列的指定有效长度,因此没有查询参与填充令牌的位置。在以下内容中,将逐行呈现两层多头注意力权重。每位负责人都根据查询、键和值的单独表示子空间独立出席。 +在编码器的自我注意中,查询和键来自相同的输入序列。由于填充令牌不具有意义,并且输入序列的指定有效长度,因此没有查询参与填充令牌的位置。在以下内容中,将按行呈现两层多头注意力权重。每位负责人都根据查询、键和值的单独表示子空间独立出席。 ```{.python .input} d2l.show_heatmaps( diff --git a/chapter_convolutional-modern/alexnet.md b/chapter_convolutional-modern/alexnet.md index 143a6c76d..f473fa26c 100644 --- a/chapter_convolutional-modern/alexnet.md +++ b/chapter_convolutional-modern/alexnet.md @@ -3,15 +3,15 @@ 在LeNet提出后,卷积神经网络在计算机视觉和机器学习领域中很有名气。但卷积神经网络并没有主导这些领域。这是因为虽然 LeNet 在小数据集上取得了很好的效果,但是在更大、更真实的数据集上训练卷积神经网络的性能和可行性还有待研究。事实上,在上世纪90年代初到2012年之间的大部分时间里,神经网络往往被其他机器学习方法超越,如支持向量机(support vector machines)。 -在计算机视觉中,直接将神经网络与其他机器学习方法进行比较也许不公平。这是因为,卷积神经网络的输入是由原始像素值或是经过简单预处理(例如居中、缩放)的像素值组成的。但在使用传统机器学习方法时,从业者永远不会将原始像素作为输入。在传统机器学习方法中,计算机视觉工作流是由经过人的手工精心设计的特征工作流组成的。对于这些传统方法,大部分的进展都来自于对特征有了更聪明的想法,并且学习到的算法往往归于事后的解释。 +在计算机视觉中,直接将神经网络与其他机器学习方法进行比较也许不公平。这是因为,卷积神经网络的输入是由原始像素值或是经过简单预处理(例如居中、缩放)的像素值组成的。但在使用传统机器学习方法时,从业者永远不会将原始像素作为输入。在传统机器学习方法中,计算机视觉流水线是由经过人的手工精心设计的特征流水线组成的。对于这些传统方法,大部分的进展都来自于对特征有了更聪明的想法,并且学习到的算法往往归于事后的解释。 虽然上世纪90年代就有了一些神经网络加速器,但仅靠它们还不足以开发出有大量参数的深层多通道多层卷积神经网络。此外,当时的数据集仍然相对较小。除了这些障碍,训练神经网络的一些关键技巧仍然缺失,包括启发式参数初始化、随机梯度下降的巧妙变体、非挤压激活函数和有效的正则化技术。 -因此,与训练*端到端*(从像素到分类结果)系统不同,经典机器学习的工作流看起来更像下面这样: +因此,与训练*端到端*(从像素到分类结果)系统不同,经典机器学习的流水线看起来更像下面这样: 1. 获取一个有趣的数据集。在早期,收集这些数据集需要昂贵的传感器(在当时最先进的图像也就100万像素)。 2. 根据光学、几何学、其他知识以及偶然的发现,手工对特征数据集进行预处理。 -3. 通过标准的特征提取算法(如SIFT(尺度不变特征变换) :cite:`Lowe.2004` 、SURF(加速鲁棒特征) :cite:`Bay.Tuytelaars.Van-Gool.2006` 或其他手动调整的工作流来输入数据。 +3. 通过标准的特征提取算法(如SIFT(尺度不变特征变换) :cite:`Lowe.2004` 、SURF(加速鲁棒特征) :cite:`Bay.Tuytelaars.Van-Gool.2006` 或其他手动调整的流水线来输入数据。 4. 将提取的特征放到最喜欢的分类器中(例如线性模型或其它核方法),以训练分类器。 如果你和机器学习研究人员交谈,你会发现他们相信机器学习既重要又美丽:优雅的理论去证明各种模型的性质。机器学习是一个正在蓬勃发展、严谨且非常有用的领域。然而,如果你和计算机视觉研究人员交谈,你会听到一个完全不同的故事。他们会告诉你图像识别的诡异事实————推动领域进步的是数据特征,而不是学习算法。计算机视觉研究人员相信,从对最终模型精度的影响来说,更大或更干净的数据集、或是稍微改进的特征提取,比任何学习算法带来的进步要大得多。 diff --git a/chapter_convolutional-modern/batch-norm.md b/chapter_convolutional-modern/batch-norm.md index 32fb07616..e47ac5062 100644 --- a/chapter_convolutional-modern/batch-norm.md +++ b/chapter_convolutional-modern/batch-norm.md @@ -72,7 +72,7 @@ $$\begin{aligned} \hat{\boldsymbol{\mu}}_\mathcal{B} &= \frac{1}{|\mathcal{B}|} ### 全连接层 通常,我们将批量归一化层置于全连接层中的仿射变换和激活函数之间。 -设全连接层的输入为 u ,权重参数和偏差参数分别为 $\mathbf{W}$ 和 $\mathbf{b}$ ,激活函数为 $\phi$ ,批量归一化的运算符为 $\mathrm{BN}$ 。 +设全连接层的输入为 u ,权重参数和偏置参数分别为 $\mathbf{W}$ 和 $\mathbf{b}$ ,激活函数为 $\phi$ ,批量归一化的运算符为 $\mathrm{BN}$ 。 那么,使用批量归一化的全连接层的输出的计算详情如下: $$\mathbf{h} = \phi(\mathrm{BN}(\mathbf{W}\mathbf{x} + \mathbf{b}) ).$$ @@ -500,7 +500,7 @@ Ali Rahimi 在接受 2017 年 NeurIPS 大会的“接受时间考验奖”(Tes ## 练习 -1. 在使用批量归一化之前,我们是否可以从全连接层或卷积层中删除偏差参数?为什么? +1. 在使用批量归一化之前,我们是否可以从全连接层或卷积层中删除偏置参数?为什么? 1. 比较LeNet在使用和不使用批量归一化情况下的学习率。 1. 绘制训练和测试准确度的提高。 1. 你的学习率有多高? diff --git a/chapter_convolutional-modern/index.md b/chapter_convolutional-modern/index.md index 5f205d559..965d80384 100644 --- a/chapter_convolutional-modern/index.md +++ b/chapter_convolutional-modern/index.md @@ -1,4 +1,4 @@ -# 深度卷积神经网络 +# 现代卷积神经网络 :label:`chap_modern_cnn` 上一章我们介绍了卷积神经网络的基本原理,本章我们将带你了解现代的卷积神经网络结构,许多现代卷积神经网络的研究都是建立在这一章的基础上的。 diff --git a/chapter_convolutional-modern/resnet.md b/chapter_convolutional-modern/resnet.md index e11b22ad0..ca2aa5a84 100644 --- a/chapter_convolutional-modern/resnet.md +++ b/chapter_convolutional-modern/resnet.md @@ -8,7 +8,7 @@ ## 函数类 首先,假设有一类特定的神经网络结构 $\mathcal{F}$,它包括学习速率和其他超参数设置。 -对于所有 $f \in \mathcal{F}$,存在一些参数集(例如权重和偏差),这些参数可以通过在合适的数据集上进行训练而获得。 +对于所有 $f \in \mathcal{F}$,存在一些参数集(例如权重和偏置),这些参数可以通过在合适的数据集上进行训练而获得。 现在假设 $f^*$ 是我们真正想要找到的函数,如果是 $f^* \in \mathcal{F}$,那我们可以轻而易举的训练得到它,但通常我们不会那么幸运。 相反,我们将尝试找到一个函数 $f^*_\mathcal{F}$,这是我们在 $\mathcal{F}$ 中的最佳选择。 例如,给定一个具有 $\mathbf{X}$ 特性和 $\mathbf{y}$ 标签的数据集,我们可以尝试通过解决以下优化问题来找到它: @@ -43,7 +43,7 @@ $$f^*_\mathcal{F} := \mathop{\mathrm{argmin}}_f L(\mathbf{X}, \mathbf{y}, f) \te 让我们聚焦于神经网络局部:如图 :numref:`fig_residual_block` 所示,假设我们的原始输入为 $x$ ,而希望学出的理想映射为 $f(\mathbf{x})$ (作为 :numref:`fig_residual_block` 上方激活函数的输入)。 :numref:`fig_residual_block` 左图虚线框中的部分需要直接拟合出该映射 $f(\mathbf{x})$ ,而右图虚线框中的部分则需要拟合出残差映射 $f(\mathbf{x}) - \mathbf{x}$ 。 残差映射在现实中往往更容易优化。 -以本节开头提到的恒等映射作为我们希望学出的理想映射 $f(\mathbf{x})$ ,我们只需将 :numref:`fig_residual_block` 中右图虚线框内上方的加权运算(如仿射)的权重和偏差参数设成 0,那么 $f(\mathbf{x})$ 即为恒等映射。 +以本节开头提到的恒等映射作为我们希望学出的理想映射 $f(\mathbf{x})$ ,我们只需将 :numref:`fig_residual_block` 中右图虚线框内上方的加权运算(如仿射)的权重和偏置参数设成 0,那么 $f(\mathbf{x})$ 即为恒等映射。 实际中,当理想映射 $f(\mathbf{x})$ 极接近于恒等映射时,残差映射也易于捕捉恒等映射的细微波动。 :numref:`fig_residual_block` 右图是 ResNet 的基础结构-- *残差块*(residual block)。 在残差块中,输入可通过跨层数据线路更快地向前传播。 diff --git a/chapter_convolutional-neural-networks/channels.md b/chapter_convolutional-neural-networks/channels.md index b740ce029..89389fb00 100644 --- a/chapter_convolutional-neural-networks/channels.md +++ b/chapter_convolutional-neural-networks/channels.md @@ -105,7 +105,7 @@ $1 \times 1$ 卷积,即 $k_h = k_w = 1$,看起来似乎没有多大意义。 这里输入和输出具有相同的高度和宽度,输出中的每个元素都是从输入图像中同一位置的元素的线性组合。 我们可以将 $1\times 1$ 卷积层看作是在每个像素位置应用的全连接层,以 $c_i$ 个输入值转换为 $c_o$ 个输出值。 因为这仍然是一个卷积层,所以跨像素的权重是一致的。 -同时,$1\times 1$ 卷积层需要的权重维度为 $c_o\times c_i$ ,再额外加上一个偏差。 +同时,$1\times 1$ 卷积层需要的权重维度为 $c_o\times c_i$ ,再额外加上一个偏置。 ![互相关计算使用了具有3个输入通道和2个输出通道的 $1\times 1$ 卷积核。其中,输入和输出具有相同的高度和宽度。](../img/conv-1x1.svg) diff --git a/chapter_convolutional-neural-networks/conv-layer.md b/chapter_convolutional-neural-networks/conv-layer.md index e44c6b416..6701653b0 100644 --- a/chapter_convolutional-neural-networks/conv-layer.md +++ b/chapter_convolutional-neural-networks/conv-layer.md @@ -14,7 +14,7 @@ :label:`fig_correlation` 在二维互相关运算中,卷积窗口从输入张量的左上角开始,从左到右、从上到下滑动。 -当卷积窗口滑动到新一个位置时,包含在该窗口中的部分张量与卷积核张量进行逐元素相乘,得到的张量再求和得到一个单一的标量值,由此我们得出了这一位置的输出张量值。 +当卷积窗口滑动到新一个位置时,包含在该窗口中的部分张量与卷积核张量进行按元素相乘,得到的张量再求和得到一个单一的标量值,由此我们得出了这一位置的输出张量值。 在如上例子中,输出张量的四个元素由二维互相关运算得到,这个输出高度为 $2$ 、宽度为 $2$ ,如下所示: $$ @@ -86,11 +86,11 @@ corr2d(X, K) ## 卷积层 -卷积层对输入和卷积核权重进行互相关运算,并在添加标量偏差之后产生输出。 -所以,卷积层中的两个被训练的参数是卷积核权重和标量偏差。 +卷积层对输入和卷积核权重进行互相关运算,并在添加标量偏置之后产生输出。 +所以,卷积层中的两个被训练的参数是卷积核权重和标量偏置。 就像我们之前随机初始化全连接层一样,在训练基于卷积层的模型时,我们也随机初始化卷积核权重 -基于上面定义的 `corr2d` 函数实现二维卷积层。在 `__init__` 构造函数中,将 `weight` 和 `bias` 声明为两个模型参数。前向传播函数调用 `corr2d` 函数并添加偏差。 +基于上面定义的 `corr2d` 函数实现二维卷积层。在 `__init__` 构造函数中,将 `weight` 和 `bias` 声明为两个模型参数。前向传播函数调用 `corr2d` 函数并添加偏置。 ```{.python .input} class Conv2D(nn.Block): @@ -185,7 +185,7 @@ corr2d(d2l.transpose(X), K) 如果我们只需寻找黑白边缘,那么以上 `[1, -1]` 的边缘检测器足以。然而,当有了更复杂数值的卷积核,或者连续的卷积层时,我们不可能手动设计过滤器。那么我们是否可以学习由 `X` 生成 `Y` 的卷积核呢? 现在让我们看看是否可以通过仅查看“输入-输出”对来了解由 `X` 生成 `Y` 的卷积核。 -我们先构造一个卷积层,并将其卷积核初始化为随机张量。接下来,在每次迭代中,我们比较 `Y` 与卷积层输出的平方误差,然后计算梯度来更新卷积核。为了简单起见,我们在此使用内置的二维卷积层,并忽略偏差。 +我们先构造一个卷积层,并将其卷积核初始化为随机张量。接下来,在每次迭代中,我们比较 `Y` 与卷积层输出的平方误差,然后计算梯度来更新卷积核。为了简单起见,我们在此使用内置的二维卷积层,并忽略偏置。 ```{.python .input} # 构造一个二维卷积层,它具有1个输出通道和形状为(1,2)的卷积核 @@ -305,7 +305,7 @@ d2l.reshape(conv2d.get_weights()[0], (1, 2)) ## 小结 -* 二维卷积层的核心计算是二维互相关运算。最简单的形式是,对二维输入数据和卷积核执行互相关操作,然后添加一个偏差。 +* 二维卷积层的核心计算是二维互相关运算。最简单的形式是,对二维输入数据和卷积核执行互相关操作,然后添加一个偏置。 * 我们可以设计一个卷积核来检测图像的边缘。 * 我们可以从数据中学习卷积核的参数。 * 学习卷积核时,无论用严格卷积运算或互相关运算,卷积层的输出不会受太大影响。 diff --git a/chapter_convolutional-neural-networks/why-conv.md b/chapter_convolutional-neural-networks/why-conv.md index 9e945258f..1ec796fd5 100644 --- a/chapter_convolutional-neural-networks/why-conv.md +++ b/chapter_convolutional-neural-networks/why-conv.md @@ -6,7 +6,7 @@ 有时我们缺乏足够的知识来指导更巧妙的模型结构设计,此时多层感知机可能是最好的选择。然而,对于高维感知数据,这种无结构网络可能会变得笨拙。 例如,在之前区分猫和狗的例子中。假设我们收集了一个照片数据集,每张照片具有百万级像素,这意味着多层感知机的每次输入都有一百万个维度。 -根据我们在:numref:`subsec_parameterization-cost-fc-layers`中对全连接层参数开销的讨论。即使将隐藏层维度降低到 $1000$ ,这个神经网络也将有 $10^6 \times 10^3 = 10^9$ 个参数。想要训练这个模型很难,需要有大量的GPU、分布式优化训练的经验和超乎常人的耐心。 +根据我们在 :numref:`subsec_parameterization-cost-fc-layers` 中对全连接层参数开销的讨论。即使将隐藏层维度降低到 $1000$ ,这个神经网络也将有 $10^6 \times 10^3 = 10^9$ 个参数。想要训练这个模型很难,需要有大量的GPU、分布式优化训练的经验和超乎常人的耐心。 细心的读者可能会反对这一论点,认为要求百万像素的分辨率可能不是必要的。 @@ -81,7 +81,7 @@ $$[\mathbf{H}]_{i, j} = u + \sum_{a = -\Delta}^{\Delta} \sum_{b = -\Delta}^{\Del 简而言之, :eqref:`eq_conv-layer` 是一个卷积层,而卷积神经网络是包含卷积层的一类特殊的神经网络。 在深度学习研究社区中, $\mathbf{V}$ 被称为 *卷积核* (convolution kernel) 或者 *滤波器* (filter),是可学习的权重。 当图像处理的局部区域很小时,卷积神经网络与多层感知机的训练差异可能是巨大的:以前,多层感知机可能需要数十亿个参数来表示,而现在卷积神经网络通常只需要几百个参数,而且不需要改变输入或隐藏表示的维数。 -以上所有的权重学习都依赖于归纳偏差,当这种偏差与实际情况相符时,我们就可以得到有效的模型,这些模型能很好地推广到不可见的数据中。 +以上所有的权重学习都依赖于归纳偏置,当这种偏置与实际情况相符时,我们就可以得到有效的模型,这些模型能很好地推广到不可见的数据中。 但如果这些假设与实际情况不符,比如当图像不满足平移不变时,我们的模型可能难以拟合。 diff --git a/chapter_deep-learning-computation/custom-layer.md b/chapter_deep-learning-computation/custom-layer.md index e16513791..cd4d5b5fa 100644 --- a/chapter_deep-learning-computation/custom-layer.md +++ b/chapter_deep-learning-computation/custom-layer.md @@ -105,7 +105,7 @@ tf.reduce_mean(Y) 既然我们知道了如何定义简单的层,那么让我们继续定义具有参数的层,这些参数可以通过训练进行调整。我们可以使用内置函数来创建参数,这些参数提供一些基本的管理功能。比如管理访问、初始化、共享、保存和加载模型参数。这样做的好处之一是,我们不需要为每个自定义层编写自定义序列化程序。 -现在,让我们实现自定义版本的全连接层。回想一下,该层需要两个参数,一个用于表示权重,另一个用于表示偏差项。在此实现中,我们使用ReLU作为激活函数。该层需要输入参数:`in_units`和`units`,分别表示输入和输出的数量。 +现在,让我们实现自定义版本的全连接层。回想一下,该层需要两个参数,一个用于表示权重,另一个用于表示偏置项。在此实现中,我们使用ReLU作为激活函数。该层需要输入参数:`in_units`和`units`,分别表示输入和输出的数量。 ```{.python .input} class MyDense(nn.Block): diff --git a/chapter_deep-learning-computation/model-construction.md b/chapter_deep-learning-computation/model-construction.md index 2afd2b3b6..5ff6674b6 100644 --- a/chapter_deep-learning-computation/model-construction.md +++ b/chapter_deep-learning-computation/model-construction.md @@ -1,7 +1,7 @@ # 层和块 :label:`sec_model_construction` -当我们第一次介绍神经网络时,我们关注的是具有单一输出的线性模型。在这里,整个模型只由一个神经元组成。注意,单个神经元(1)接受一些输入;(2)生成相应的标量输出;(3)具有一组相关参数,这些参数可以更新以优化某些感兴趣的目标函数。然后,当我们开始考虑具有多个输出的网络,我们就利用矢量化算法来描述整层神经元。像单个神经元一样,层(1)接受一组输入,(2)生成相应的输出,(3)由一组可调整参数描述。当我们使用softmax回归时,一个单层本身就是模型。然而,即使我们随后引入了多层感知机,我们仍然可以认为该模型保留了上面所说的基本结构。 +当我们第一次介绍神经网络时,我们关注的是具有单一输出的线性模型。在这里,整个模型只由一个神经元组成。注意,单个神经元(1)接受一些输入;(2)生成相应的标量输出;(3)具有一组相关 *参数*(parameters),这些参数可以更新以优化某些感兴趣的目标函数。然后,当我们开始考虑具有多个输出的网络,我们就利用矢量化算法来描述整层神经元。像单个神经元一样,层(1)接受一组输入,(2)生成相应的输出,(3)由一组可调整参数描述。当我们使用softmax回归时,一个单层本身就是模型。然而,即使我们随后引入了多层感知机,我们仍然可以认为该模型保留了上面所说的基本结构。 有趣的是,对于多层感知机而言,整个模型及其组成层都是这种结构。整个模型接受原始输入(特征),生成输出(预测),并包含一些参数(所有组成层的参数集合)。同样,每个单独的层接收输入(由前一层提供)生成输出(到下一层的输入),并且具有一组可调参数,这些参数根据从下一层反向传播的信号进行更新。 diff --git a/chapter_deep-learning-computation/parameters.md b/chapter_deep-learning-computation/parameters.md index 6471ee966..ef5f6e868 100644 --- a/chapter_deep-learning-computation/parameters.md +++ b/chapter_deep-learning-computation/parameters.md @@ -66,11 +66,11 @@ print(net[2].state_dict()) print(net.layers[2].weights) ``` -输出的结果告诉我们一些重要的事情。首先,这个全连接层包含两个参数,分别是该层的权重和偏差。两者都存储为单精度浮点数(float32)。注意,参数名称允许我们唯一地标识每个参数,即使在包含数百个层的网络中也是如此。 +输出的结果告诉我们一些重要的事情。首先,这个全连接层包含两个参数,分别是该层的权重和偏置。两者都存储为单精度浮点数(float32)。注意,参数名称允许我们唯一地标识每个参数,即使在包含数百个层的网络中也是如此。 ### 目标参数 -注意,每个参数都表示为参数(parameter)类的一个实例。要对参数执行任何操作,首先我们需要访问底层的数值。有几种方法可以做到这一点。有些比较简单,而另一些则比较通用。下面的代码从第二个神经网络层提取偏差,提取后返回的是一个参数类实例,并进一步访问该参数的值。 +注意,每个参数都表示为参数(parameter)类的一个实例。要对参数执行任何操作,首先我们需要访问底层的数值。有几种方法可以做到这一点。有些比较简单,而另一些则比较通用。下面的代码从第二个神经网络层提取偏置,提取后返回的是一个参数类实例,并进一步访问该参数的值。 ```{.python .input} print(type(net[1].bias)) @@ -224,7 +224,7 @@ print(rgnet) print(rgnet.summary()) ``` -因为层是分层嵌套的,所以我们也可以像通过嵌套列表索引一样访问它们。例如,我们下面访问第一个主要的块,其中第二个子块的第一层的偏差项。 +因为层是分层嵌套的,所以我们也可以像通过嵌套列表索引一样访问它们。例如,我们下面访问第一个主要的块,其中第二个子块的第一层的偏置项。 ```{.python .input} rgnet[0][1][0].bias.data() @@ -249,7 +249,7 @@ rgnet.layers[0].layers[1].layers[1].weights[1] :end_tab: :begin_tab:`pytorch` -默认情况下,PyTorch会根据一个范围均匀地初始化权重和偏差矩阵,这个范围是根据输入和输出维度计算出的。PyTorch的`nn.init`模块提供了多种预置初始化方法。 +默认情况下,PyTorch会根据一个范围均匀地初始化权重和偏置矩阵,这个范围是根据输入和输出维度计算出的。PyTorch的`nn.init`模块提供了多种预置初始化方法。 :end_tab: :begin_tab:`tensorflow` diff --git a/chapter_deep-learning-computation/read-write.md b/chapter_deep-learning-computation/read-write.md index 2c6a91fcd..25b094f3e 100644 --- a/chapter_deep-learning-computation/read-write.md +++ b/chapter_deep-learning-computation/read-write.md @@ -105,7 +105,7 @@ mydict2 ## 加载和保存模型参数 -保存单个权重向量(或其他张量)确实是有用的,但是如果我们想保存整个模型,并在以后加载它们。单独保存每个向量则会变得很麻烦。毕竟,我们可能有数百个参数散布在各处。因此,深度学习框架提供了内置函数来保存和加载整个网络。需要注意的一个重要细节是,这将保存模型的*参数*(parameters)而不是保存整个模型。例如,如果我们有一个3层多层感知机,我们需要单独指定结构。因为模型本身可以包含任意代码,所以模型本身难以序列化。因此,为了恢复模型,我们需要用代码生成结构,然后从磁盘加载参数。让我们从熟悉的多层感知机开始尝试一下。 +保存单个权重向量(或其他张量)确实是有用的,但是如果我们想保存整个模型,并在以后加载它们。单独保存每个向量则会变得很麻烦。毕竟,我们可能有数百个参数散布在各处。因此,深度学习框架提供了内置函数来保存和加载整个网络。需要注意的一个重要细节是,这将保存模型的参数而不是保存整个模型。例如,如果我们有一个3层多层感知机,我们需要单独指定结构。因为模型本身可以包含任意代码,所以模型本身难以序列化。因此,为了恢复模型,我们需要用代码生成结构,然后从磁盘加载参数。让我们从熟悉的多层感知机开始尝试一下。 ```{.python .input} class MLP(nn.Block): diff --git a/chapter_installation/index.md b/chapter_installation/index.md index 64409ff3b..b3bd4699d 100644 --- a/chapter_installation/index.md +++ b/chapter_installation/index.md @@ -1,21 +1,24 @@ # 安装 :label:`chap_installation` -我们需要设置一个环境来运行 Python,Jupyter Notebook,相关库以及运行本书所需的代码,以快速入门并获得动手学习经验。 +我们需要配置一个环境来运行 Python、Jupyter Notebook、相关库以及运行本书所需的代码,以快速入门并获得动手学习经验。 ## 安装 Miniconda -最简单的方法就是安装依赖 Python 3.x 的 [Miniconda](https://conda.io/en/latest/miniconda.html)。如果已安装 conda,则可以跳过以下步骤。从网站下载相应的 Miniconda sh 文件,然后使用 `sh -b` 从命令行执行安装。对于 macOS 用户: +最简单的方法就是安装依赖 Python 3.x 的 [Miniconda](https://conda.io/en/latest/miniconda.html)。如果已安装 conda,则可以跳过以下步骤。 +从网站下载相应的 Miniconda sh 文件,然后使用 `sh -b` 从命令行执行安装。 + +对于 macOS 用户: ```bash -# The file name is subject to changes +# 文件名可能会更改 sh Miniconda3-latest-MacOSX-x86_64.sh -b ``` 对于 Linux 用户: ```bash -# The file name is subject to changes +# 文件名可能会更改 sh Miniconda3-latest-Linux-x86_64.sh -b ``` @@ -25,7 +28,7 @@ sh Miniconda3-latest-Linux-x86_64.sh -b ~/miniconda3/bin/conda init ``` -现在关闭并重新打开当前的 shell。你应该能够创建一个新的环境,如下所示: +现在关闭并重新打开当前的 shell。你应该能用下面的命令创建一个新的环境: ```bash conda create --name d2l python=3.8 -y @@ -33,7 +36,7 @@ conda create --name d2l python=3.8 -y ## 下载 D2L Notebook -接下来,需要下载这本书的代码。你可以点击任何 HTML 页面顶部的 “Jupyter 笔记本文件” 选项卡下载,并解压代码。或者可以按照如下方式进行下载: +接下来,需要下载这本书的代码。你可以点击任何 HTML 页面顶部的 “Jupyter 记事本文件” 选项下载后解压代码。或者可以按照如下方式进行下载: ```bash mkdir d2l-zh && cd d2l-zh @@ -51,9 +54,9 @@ conda activate d2l ## 安装框架和 `d2l` 软件包 -在安装深度学习框架之前,请先检查你的计算机上是否有正确的 GPU(在标准笔记本电脑上为显示器提供电源的 GPU 不计入我们的目的)。如果要在 GPU 服务器上安装,请继续执行 :ref:`subsec_gpu` 以获取有关安装 GPU 支持版本的说明。 +在安装深度学习框架之前,请先检查你的计算机上是否有可用的 GPU(在笔记本电脑上为显示器提供输出的GPU不算)。如果要在 GPU 机器上安装,请继续在 :ref:`subsec_gpu` 获取有关安装GPU支持版本的说明。 -或者,你可以按照如下方法安装CPU版本。这将足够帮助你完成前几章,但你需要在运行更大的模型之前访问 GPU。 +或者,你可以按照如下方法安装CPU版本。这将足够帮助你完成前几章,但你需要在运行更大模型之前获取GPU。 :begin_tab:`mxnet` @@ -77,50 +80,50 @@ pip install tensorflow tensorflow-probability ``` :end_tab: -我们还安装了 `d2l` 软件包,它封装了本书中常用的函数和类。 +你还需要安装 `d2l` 软件包,它封装了本书中常用的函数和类。 ```bash # -U:将所有包升级到最新的可用版本 pip install -U d2l ``` -安装完成后,我们现在通过运行以下操作打开 Jupyter 笔记本: +安装完成后,我们通过运行以下命令打开 Jupyter 笔记本: ```bash jupyter notebook ``` -此时,你可以在 Web 浏览器中打开 (通常会自动打开)。然后我们可以运行这本书的每个部分的代码。在运行书籍代码或更新深度学习框架或 `d2l` 软件包之前,请始终执行 `conda activate d2l` 以激活运行时环境。要退出环境,请运行 `conda deactivate`。 +现在,你可以在 Web 浏览器中打开 (通常会自动打开)。然后我们可以运行这本书中每个部分的代码。在运行书籍代码、更新深度学习框架或 `d2l` 软件包之前,请始终执行 `conda activate d2l` 以激活运行时环境。要退出环境,请运行 `conda deactivate`。 ## GPU 支持 :label:`subsec_gpu` :begin_tab:`mxnet` -默认情况下,安装MXNet时不支持 GPU,以确保它在任何计算机(包括大多数笔记本电脑)上运行。本书的一部分要求或建议使用 GPU 运行。如果你的计算机具有 NVIDIA 显卡并且已安装 [CUDA](https://developer.nvidia.com/cuda-downloads),则应安装启用 GPU 的版本。如果你已经安装了仅 CPU 版本,则可能需要首先通过运行以下操作将其删除: +默认情况下,安装的MXNet不支持GPU。这可以确保它在任何计算机(包括大多数笔记本电脑)上运行。本书的部分内容建议或要求使用 GPU 运行。如果你的计算机带有 NVIDIA 显卡并且已安装 [CUDA](https://developer.nvidia.com/cuda-downloads),则应安装支持 GPU 的版本。如果你已经安装了仅支持 CPU 版本,则可能需要先通过运行以下命令将其删除: ```bash pip uninstall mxnet ``` -然后,我们需要找到你安装的 CUDA 版本。你可以通过 `nvcc --version` 或 `cat /usr/local/cuda/version.txt` 查看它。假定你已安装 CUDA 10.1,则可以使用以下命令进行安装: +然后,我们需要找到安装的 CUDA 版本。你可以通过 `nvcc --version` 或 `cat /usr/local/cuda/version.txt` 查看。假设你已安装 CUDA 10.1,则可以使用以下命令进行安装: ```bash -# For Windows users +# 对于 Windows 用户: pip install mxnet-cu101==1.7.0 -f https://dist.mxnet.io/python -# For Linux and macOS users +# 对于 Linux 和 macOS 用户: pip install mxnet-cu101==1.7.0 ``` -你可以根据你的 CUDA 版本更改最后一位数字,例如:CUDA 10.0 的 `cu100` 和 CUDA 9.0 的 `cu90`。 +你可以根据你的 CUDA 版本更改最后一位数字,例如:CUDA 10.0 是 `cu100`, CUDA 9.0 是 `cu90`。 :end_tab: :begin_tab:`pytorch,tensorflow` 默认情况下,深度学习框架安装了GPU支持。 -如果你的计算机有NVIDIA GPU,并且已经安装了[CUDA](https://developer.nvidia.com/cuda-downloads),那么你应该已经设置好了。 +如果你的计算机有NVIDIA GPU,并且已经安装了[CUDA](https://developer.nvidia.com/cuda-downloads),那么你应该已经配置好了。 :end_tab: ## 练习 @@ -128,13 +131,13 @@ pip install mxnet-cu101==1.7.0 1. 下载该书的代码并安装运行时环境。 :begin_tab:`mxnet` -[Discussions](https://discuss.d2l.ai/t/23) +[Discussions](https://discuss.d2l.ai/t/2082) :end_tab: :begin_tab:`pytorch` -[Discussions](https://discuss.d2l.ai/t/24) +[Discussions](https://discuss.d2l.ai/t/2083) :end_tab: :begin_tab:`tensorflow` -[Discussions](https://discuss.d2l.ai/t/436) +[Discussions](https://discuss.d2l.ai/t/2084) :end_tab: diff --git a/chapter_introduction/index.md b/chapter_introduction/index.md index 98dca4874..7e66f8942 100644 --- a/chapter_introduction/index.md +++ b/chapter_introduction/index.md @@ -752,4 +752,4 @@ Canny边缘检测器 :cite:`Canny.1987` 和SIFT特征提取器 :cite:`Lowe.2004` 1. 如果把人工智能的发展看作一场新的工业革命,那么算法和数据之间的关系是什么?它类似于蒸汽机和煤吗?根本区别是什么? 1. 你还可以在哪里应用端到端的训练方法,比如 :numref:`fig_ml_loop` 、物理、工程和计量经济学? -[Discussions](https://discuss.d2l.ai/t/22) +[Discussions](https://discuss.d2l.ai/t/2088) diff --git a/chapter_linear-networks/image-classification-dataset.md b/chapter_linear-networks/image-classification-dataset.md index 47c3ba474..a607ad63d 100644 --- a/chapter_linear-networks/image-classification-dataset.md +++ b/chapter_linear-networks/image-classification-dataset.md @@ -59,7 +59,7 @@ mnist_test = torchvision.datasets.FashionMNIST( mnist_train, mnist_test = tf.keras.datasets.fashion_mnist.load_data() ``` -Fashion-MNIST 由 10 个类别的图像组成,每个类别由训练数据集中的 6000 张图像和测试数据集中的 1000 张图像组成。*测试数据集*(test dataset)(或 *测试集*(test set))不会用于训练,只用于评估模型性能。训练集和测试集分别包含 60000 和 10000 张图像。 +Fashion-MNIST 由 10 个类别的图像组成,每个类别由训练数据集中的 6000 张图像和测试数据集中的 1000 张图像组成。*测试数据集*(test dataset)不会用于训练,只用于评估模型性能。训练集和测试集分别包含 60000 和 10000 张图像。 ```{.python .input} #@tab mxnet, pytorch @@ -269,7 +269,7 @@ for X, y in train_iter: 我们现在已经准备好在下面的章节中使用Fashion-MNIST数据集。 -## 总结 +## 小结 * Fashion-MNIST是一个服装分类数据集,由10个类别的图像组成。我们将在后续章节中使用此数据集来评估各种分类算法。 * 我们将高度$h$像素,宽度$w$像素图像的形状记为$h \times w$或($h$, $w$)。 @@ -277,7 +277,7 @@ for X, y in train_iter: ## 练习 -1. 将减少 `batch_size`(如减少到 1)是否会影响读取性能? +1. 减少 `batch_size`(如减少到 1)是否会影响读取性能? 1. 数据迭代器的性能非常重要。你认为当前的实现足够快吗?探索各种选择来改进它。 1. 查阅框架的在线API文档。还有哪些其他数据集可用? diff --git a/chapter_linear-networks/linear-regression-concise.md b/chapter_linear-networks/linear-regression-concise.md index d3ac099bd..abbc5fd97 100644 --- a/chapter_linear-networks/linear-regression-concise.md +++ b/chapter_linear-networks/linear-regression-concise.md @@ -86,7 +86,7 @@ next(iter(data_iter)) 当我们在 :numref:`sec_linear_scratch` 中实现线性回归时,我们明确定义了模型参数变量,并编写了计算的代码,这样通过基本的线性代数运算得到输出。但是,如果模型变得更加复杂,而且当你几乎每天都需要实现模型时,你会想简化这个过程。这种情况类似于从头开始编写自己的博客。做一两次是有益的、有启发性的,但如果每次你每需要一个博客就花一个月的时间重新发明轮子,那你将是一个糟糕的网页开发者。 -对于标准操作,我们可以使用框架的预定义好的层。这使我们只需关注使用哪些层来构造模型,而不必关注层的实现细节。我们首先定义一个模型变量`net`,它是一个 `Sequential` 类的实例。 `Sequential` 类为串联在一起的多个层定义了一个容器。当给定输入数据, `Sequential` 实例将数据传入到第一层,然后将第一层的输出作为第二层的输入,依此类推。在下面的例子中,我们的模型只包含一个层,因此实际上不需要`Sequential`。但是由于以后几乎所有的模型都是多层的,在这里使用`Sequential`会让你熟悉标准的工作流。 +对于标准操作,我们可以使用框架的预定义好的层。这使我们只需关注使用哪些层来构造模型,而不必关注层的实现细节。我们首先定义一个模型变量`net`,它是一个 `Sequential` 类的实例。 `Sequential` 类为串联在一起的多个层定义了一个容器。当给定输入数据, `Sequential` 实例将数据传入到第一层,然后将第一层的输出作为第二层的输入,依此类推。在下面的例子中,我们的模型只包含一个层,因此实际上不需要`Sequential`。但是由于以后几乎所有的模型都是多层的,在这里使用`Sequential`会让你熟悉标准的流水线。 回顾 :numref:`fig_single_neuron` 中的单层网络架构,这一单层被称为 *全连接层*(fully-connected layer),因为它的每一个输入都通过矩阵-向量乘法连接到它的每个输出。 @@ -129,12 +129,12 @@ net.add(tf.keras.layers.Dense(1)) ## 初始化模型参数 -在使用`net`之前,我们需要初始化模型参数。如在线性回归模型中的权重和偏差。 +在使用`net`之前,我们需要初始化模型参数。如在线性回归模型中的权重和偏置。 深度学习框架通常有预定义的方法来初始化参数。 -在这里,我们指定每个权重参数应该从均值为0,标准差为0.01的正态分布中随机采样,偏差参数将初始化为零。 +在这里,我们指定每个权重参数应该从均值为0、标准差为0.01的正态分布中随机采样,偏置参数将初始化为零。 :begin_tab:`mxnet` -我们从 MXNet 导入 `initializer` 模块。这个模块提供了各种模型参数初始化方法。Gluon将 `init` 作为访问 `initializer` 包的快捷方式。我们可以通过调用 `init.Normal(sigma=0.01)` 来指定初始化权重的方法。默认情况下,偏差参数初始化为零。 +我们从 MXNet 导入 `initializer` 模块。这个模块提供了各种模型参数初始化方法。Gluon将 `init` 作为访问 `initializer` 包的快捷方式。我们可以通过调用 `init.Normal(sigma=0.01)` 来指定初始化权重的方法。默认情况下,偏置参数初始化为零。 :end_tab: :begin_tab:`pytorch` @@ -290,7 +290,7 @@ for epoch in range(num_epochs): ``` 下面我们比较生成数据集的真实参数和通过有限数据训练获得的模型参数。 -要访问参数,我们首先从 `net` 访问所需的层,然后读取该层的权重和偏差。 +要访问参数,我们首先从 `net` 访问所需的层,然后读取该层的权重和偏置。 正如在从零开始实现中一样,我们估计得到的参数与生成数据的真实参数非常接近。 ```{.python .input} @@ -316,7 +316,7 @@ b = net.get_weights()[1] print('b的估计误差:', true_b - b) ``` -## 总结 +## 小结 :begin_tab:`mxnet` * 我们可以使用Gluon更简洁地实现模型。 diff --git a/chapter_linear-networks/linear-regression-scratch.md b/chapter_linear-networks/linear-regression-scratch.md index 340aa95e0..67a1b0cc1 100644 --- a/chapter_linear-networks/linear-regression-scratch.md +++ b/chapter_linear-networks/linear-regression-scratch.md @@ -3,7 +3,7 @@ 在了解线性回归的关键思想之后,我们可以开始通过代码来动手实现线性回归了。 在这一节中,我们将从零开始实现整个方法,包括数据流水线、模型、损失函数和小批量随机梯度下降优化器。 -虽然现代的深度学习框架几乎可以自动化的进行所有这些工作,但从零开始实现可以确保你真正知道自己在做什么。 +虽然现代的深度学习框架几乎可以自动化地进行所有这些工作,但从零开始实现可以确保你真正知道自己在做什么。 同时,了解更细致的工作原理将方便我们自定义模型、自定义层或自定义损失函数。 在这一节中,我们将只使用张量和自动求导。在之后的章节中,我们会充分利用深度学习框架的优势,介绍更简洁的实现方式。 @@ -144,7 +144,7 @@ for X, y in data_iter(batch_size, features, labels): ## 初始化模型参数 在我们开始用小批量随机梯度下降优化我们的模型参数之前,我们需要先有一些参数。 -在下面的代码中,我们通过从均值为0、标准差为0.01的正态分布中采样随机数来初始化权重,并将偏差初始化为0。 +在下面的代码中,我们通过从均值为0、标准差为0.01的正态分布中采样随机数来初始化权重,并将偏置初始化为0。 ```{.python .input} w = np.random.normal(0, 0.01, (2, 1)) @@ -173,7 +173,7 @@ b = tf.Variable(tf.zeros(1), trainable=True) ## 定义模型 接下来,我们必须定义模型,将模型的输入和参数同模型的输出关联起来。 -回想一下,要计算线性模型的输出,我们只需计算输入特征 $\mathbf{X}$ 和模型权重$\mathbf{w}$的矩阵-向量乘法后加上偏差$b$。注意,上面的$\mathbf{Xw}$ 是一个向量,而$b$是一个标量。回想一下 :numref:`subsec_broadcasting` 中描述的广播机制。当我们用一个向量加一个标量时,标量会被加到向量的每个分量上。 +回想一下,要计算线性模型的输出,我们只需计算输入特征 $\mathbf{X}$ 和模型权重$\mathbf{w}$的矩阵-向量乘法后加上偏置$b$。注意,上面的$\mathbf{Xw}$ 是一个向量,而$b$是一个标量。回想一下 :numref:`subsec_broadcasting` 中描述的广播机制。当我们用一个向量加一个标量时,标量会被加到向量的每个分量上。 ```{.python .input} #@tab all diff --git a/chapter_linear-networks/linear-regression.md b/chapter_linear-networks/linear-regression.md index 9311dffd2..a2728eee7 100644 --- a/chapter_linear-networks/linear-regression.md +++ b/chapter_linear-networks/linear-regression.md @@ -2,13 +2,13 @@ :label:`sec_linear_regression` *回归*(regression) 是指一类为一个或多个自变量与因变量之间关系建模的方法。在自然科学和社会科学领域,回归经常用来表示输入和输出之间的关系。 -在机器学习领域中的大多数任务通常都与*预测*(prediction)有关。 +在机器学习领域中的大多数任务通常都与*预测*(prediction)有关。 当我们想预测一个数值时,就会涉及到回归问题。常见的例子包括:预测价格(房屋、股票等)、预测住院时间(针对住院病人)、预测需求(零售销量)等。但不是所有的*预测*都是回归问题。在后面的章节中,我们将介绍分类问题。分类问题的目标是预测数据属于一组类别中的哪一个。 ## 线性回归的基本元素 -*线性回归* (Linear regression)在回归的各种标准工具中最简单而且最流行。它可以追溯到19世纪初。线性回归基于几个简单的假设:首先,假设自变量 $\mathbf{x}$ 和因变量 $y$ 之间的关系是线性的,即$y$可以表示为 $\mathbf{x}$ 中元素的加权和,这里通常允许包含观测值的一些噪声;其次,我们假设任何噪声都比较正常,如噪声遵循正态分布。 +*线性回归* (linear regression)在回归的各种标准工具中最简单而且最流行。它可以追溯到19世纪初。线性回归基于几个简单的假设:首先,假设自变量 $\mathbf{x}$ 和因变量 $y$ 之间的关系是线性的,即$y$可以表示为 $\mathbf{x}$ 中元素的加权和,这里通常允许包含观测值的一些噪声;其次,我们假设任何噪声都比较正常,如噪声遵循正态分布。 为了解释*线性回归*,我们举一个实际的例子:我们希望根据房屋的面积(平方英尺)和房龄(年)来估算房屋价格(美元)。为了开发一个能预测房价的模型,我们需要收集一个真实的数据集。这个数据集包括了房屋的销售价格、面积和房龄。在机器学习的术语中,该数据集称为 *训练数据集*(training data set)或*训练集* (training set),每行数据(在这个例子中是与一次房屋交易相对应的数据)称为*样本*(sample),也可以称为*数据点* (data point)或*数据样本*(data instance)。我们要试图预测的目标(在这个例子中是房屋价格)称为 *标签*(label)或 *目标*(target)。预测所依据的自变量(面积和房龄)称为 *特征*(features)或 *协变量*(covariates)。 @@ -22,10 +22,10 @@ $$\mathrm{price} = w_{\mathrm{area}} \cdot \mathrm{area} + w_{\mathrm{age}} \cdot \mathrm{age} + b.$$ :eqlabel:`eq_price-area` -:eqref:`eq_price-area` 中的$w_{\mathrm{area}}$ 和 $w_{\mathrm{age}}$ 称为 *权重*(weight),$b$ 称为 *偏差*(bias)(或称为*偏移量*(offset)、*截距*(intercept))。权重决定了每个特征对我们预测值的影响。偏差是指当所有特征都取值为0时,预测值应该为多少。即使现实中不会有任何房子的面积是0或房龄正好是0年,我们仍然需要偏差项。如果没有偏差项,我们模型的表达能力将受到限制。 -严格来说, :eqref:`eq_price-area` 是输入特征的一个*仿射变换*(affine transformation)。仿射变换的特点是通过加权和对特征进行*线性变换*(linear transformation),并通过偏差项来进行*平移*(translation)。 +:eqref:`eq_price-area` 中的$w_{\mathrm{area}}$ 和 $w_{\mathrm{age}}$ 称为 *权重*(weight),$b$ 称为 *偏置*(bias),或称为*偏移量*(offset)、*截距*(intercept)。权重决定了每个特征对我们预测值的影响。偏置是指当所有特征都取值为0时,预测值应该为多少。即使现实中不会有任何房子的面积是0或房龄正好是0年,我们仍然需要偏置项。如果没有偏置项,我们模型的表达能力将受到限制。 +严格来说, :eqref:`eq_price-area` 是输入特征的一个*仿射变换*(affine transformation)。仿射变换的特点是通过加权和对特征进行*线性变换*(linear transformation),并通过偏置项来进行*平移*(translation)。 -给定一个数据集,我们的目标是寻找模型的权重 $\mathbf{w}$ 和偏差 $b$,使得根据模型做出的预测大体符合数据里的真实价格。输出的预测值由输入特征通过*线性模型*的仿射变换决定,仿射变换由所选权重和偏差确定。 +给定一个数据集,我们的目标是寻找模型的权重 $\mathbf{w}$ 和偏置 $b$,使得根据模型做出的预测大体符合数据里的真实价格。输出的预测值由输入特征通过*线性模型*的仿射变换决定,仿射变换由所选权重和偏置确定。 有些学科往往只关注有少量特征的数据集。在这些学科中,建模时经常过通过显式地长形式表达。而在机器学习领域,我们通常使用的是高维数据集,建模时采用线性代数表示法会比较方便。当我们的输入包含 $d$ 个特征时,我们将预测结果 $\hat{y}$(通常使用 “尖角” 符号表示估计值)表示为: @@ -43,11 +43,11 @@ $$\hat{y} = \mathbf{w}^\top \mathbf{x} + b.$$ $${\hat{\mathbf{y}}} = \mathbf{X} \mathbf{w} + b$$ 这个过程的求和过程将使用广播机制。广播机制会在 :numref:`subsec_broadcasting`)详细介绍。 -给定训练数据特征 $\mathbf{X}$ 和对应的已知标签 $\mathbf{y}$ ,线性回归的目标是找到一组权重向量 $\mathbf{w}$ 和偏差 $b$。当给定从$\mathbf{X}$的同分布中取样的新样本特征时,找到的权重向量和偏差能够使得新样本预测标签的误差尽可能小。 +给定训练数据特征 $\mathbf{X}$ 和对应的已知标签 $\mathbf{y}$ ,线性回归的目标是找到一组权重向量 $\mathbf{w}$ 和偏置 $b$。当给定从$\mathbf{X}$的同分布中取样的新样本特征时,找到的权重向量和偏置能够使得新样本预测标签的误差尽可能小。 -虽然我们相信给定 $\mathbf{x}$ 预测 $y$ 的最佳模型会是线性的。但我们很难找到找到一个$n$个样本的真实数据集,其中 $y^{(i)}$ 完全等于 $\mathbf{w}^\top \mathbf{x}^{(i)}+b$。无论我们使用什么手段来观察特征 $\mathbf{X}$ 和标签 $\mathbf{y}$ ,都可能会出现少量的观测误差。因此,即使确信特征与标签的潜在关系是线性的,我们也会加入一个噪声项来考虑观测误差带来的影响。 +虽然我们相信给定 $\mathbf{x}$ 预测 $y$ 的最佳模型会是线性的。但我们很难找到找到一个有$n$个样本的真实数据集,其中 $y^{(i)}$ 完全等于 $\mathbf{w}^\top \mathbf{x}^{(i)}+b$。无论我们使用什么手段来观察特征 $\mathbf{X}$ 和标签 $\mathbf{y}$ ,都可能会出现少量的观测误差。因此,即使确信特征与标签的潜在关系是线性的,我们也会加入一个噪声项来考虑观测误差带来的影响。 -在我们开始寻找最好的 *参数*(parameters)(或称为 *模型参数*(model parameters))$\mathbf{w}$ 和 $b$ 之前,我们还需要两个东西:(1)一种模型质量的度量方式;(2)一种能够更新模型以提高模型预测质量的方法。 +在我们开始寻找最好的 *模型参数*(model parameters)$\mathbf{w}$ 和 $b$ 之前,我们还需要两个东西:(1)一种模型质量的度量方式;(2)一种能够更新模型以提高模型预测质量的方法。 ### 损失函数 @@ -55,7 +55,7 @@ $${\hat{\mathbf{y}}} = \mathbf{X} \mathbf{w} + b$$ $$l^{(i)}(\mathbf{w}, b) = \frac{1}{2} \left(\hat{y}^{(i)} - y^{(i)}\right)^2.$$ -常数$\frac{1}{2}$不会带来本质的差别,但这样在形式上稍微简单一些。当我们对损失函数求导后常数系数为1。由于训练数据集是给我们的,并不受我们控制,所以经验误差只是关于模型参数的函数。为了进一步说明,来看下面的例子,我们为一维情况下的回归问题绘制图像,如 :numref:`fig_fit_linreg` 所示。 +常数$\frac{1}{2}$不会带来本质的差别,但这样在形式上稍微简单一些。当我们对损失函数求导后常数系数为1。由于训练数据集并不受我们控制,所以经验误差只是关于模型参数的函数。为了进一步说明,来看下面的例子。我们为一维情况下的回归问题绘制图像,如 :numref:`fig_fit_linreg` 所示。 ![用线性模型拟合数据。](../img/fit-linreg.svg) :label:`fig_fit_linreg` @@ -70,7 +70,7 @@ $$\mathbf{w}^*, b^* = \operatorname*{argmin}_{\mathbf{w}, b}\ L(\mathbf{w}, b). ### 解析解 -线性回归刚好是一个很简单的优化问题。与我们将在本书中所讲到的其他大部分模型不同,线性回归的解可以用一个公式简单地表达出来,这类解叫作解析解(analytical solution)。首先,我们将偏差 $b$ 合并到参数 $\mathbf{w}$ 中。合并方法是在包含所有参数的矩阵中附加一列。我们的预测问题是最小化 $\|\mathbf{y} - \mathbf{X}\mathbf{w}\|^2$。这在损失平面上只有一个临界点,这个临界点对应于整个区域的损失最小值。将损失关于$\mathbf{w}$的导数设为0,得到解析解(闭合形式): +线性回归刚好是一个很简单的优化问题。与我们将在本书中所讲到的其他大部分模型不同,线性回归的解可以用一个公式简单地表达出来,这类解叫作解析解(analytical solution)。首先,我们将偏置 $b$ 合并到参数 $\mathbf{w}$ 中。合并方法是在包含所有参数的矩阵中附加一列。我们的预测问题是最小化 $\|\mathbf{y} - \mathbf{X}\mathbf{w}\|^2$。这在损失平面上只有一个临界点,这个临界点对应于整个区域的损失最小值。将损失关于$\mathbf{w}$的导数设为0,得到解析解(闭合形式): $$\mathbf{w}^* = (\mathbf X^\top \mathbf X)^{-1}\mathbf X^\top \mathbf{y}.$$ @@ -82,7 +82,7 @@ $$\mathbf{w}^* = (\mathbf X^\top \mathbf X)^{-1}\mathbf X^\top \mathbf{y}.$$ 本书中我们用到一种名为*梯度下降*(gradient descent)的方法,这种方法几乎可以优化所有深度学习模型。它通过不断地在降低损失的方向上更新参数来降低误差。 -梯度下降最简单的用法是计算数据集中所有样本的损失关于模型参数的导数(在这里也可以称为梯度)。但实际中可能执行会比较🈵️:因为在进行一次更新之前,我们必须遍历整个数据集。因此,我们通常会在每次需要计算更新的时候随机抽取一小批样本,这种变体叫做*小批量随机梯度下降*(minibatch stochastic gradient descent)。 +梯度下降最简单的用法是计算数据集中所有样本的损失关于模型参数的导数(在这里也可以称为梯度)。但实际中的执行可能会比较慢:因为在进行一次更新之前,我们必须遍历整个数据集。因此,我们通常会在每次需要计算更新的时候随机抽取一小批样本,这种变体叫做*小批量随机梯度下降*(minibatch stochastic gradient descent)。 在每次迭代中,我们首先随机抽样一个小批量$\mathcal{B}$,它是由固定数量的训练样本组成的。然后,我们计算小批量的平均损失关于模型参数的导数(也可以称为梯度)。最后,我们将梯度乘以一个预先确定的正数$\eta$,并从当前参数的值中减掉。 @@ -95,13 +95,13 @@ $$(\mathbf{w},b) \leftarrow (\mathbf{w},b) - \frac{\eta}{|\mathcal{B}|} \sum_{i $$\begin{aligned} \mathbf{w} &\leftarrow \mathbf{w} - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} \partial_{\mathbf{w}} l^{(i)}(\mathbf{w}, b) = \mathbf{w} - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} \mathbf{x}^{(i)} \left(\mathbf{w}^\top \mathbf{x}^{(i)} + b - y^{(i)}\right),\\ b &\leftarrow b - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} \partial_b l^{(i)}(\mathbf{w}, b) = b - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} \left(\mathbf{w}^\top \mathbf{x}^{(i)} + b - y^{(i)}\right). \end{aligned}$$ :eqlabel:`eq_linreg_batch_update` -公式 :eqref:`eq_linreg_batch_update` 中的$\mathbf{w}$ 和 $\mathbf{x}$ 都是向量。在这里,更优雅的向量表示法使数学比用系数表示法(如 $w_1, w_2, \ldots, w_d$)更具可读性。 +公式 :eqref:`eq_linreg_batch_update` 中的$\mathbf{w}$ 和 $\mathbf{x}$ 都是向量。在这里,更优雅的向量表示法比系数表示法(如 $w_1, w_2, \ldots, w_d$)更具可读性。 $|\mathcal{B}|$ 表示每个小批量中的样本数,这也称为*批量大小*(batch size)。$\eta$ 表示 *学习率*(learning rate)。批量大小和学习率的值通常是手动预先指定,而不是通过模型训练得到的。这些可以调整但不在训练过程中更新的参数称为 *超参数*(hyperparameter)。 -*调参*(hyperparameter tuning) 是选择超参数的过程。超参数通常是我们根据训练迭代结果来调整的,而训练迭代结果是在独立的*验证数据集*(validation dataset)(也称为*验证集*(validation set))上评估得到的。 +*调参*(hyperparameter tuning) 是选择超参数的过程。超参数通常是我们根据训练迭代结果来调整的,而训练迭代结果是在独立的*验证数据集*(validation dataset)上评估得到的。 在训练了预先确定的若干迭代次数后(或者直到满足某些其他停止条件后),我们记录估计的模型参数,表示为$\hat{\mathbf{w}}, \hat{b}$。但是,即使我们的函数真是线性的且无噪声。我们估计得到的参数也不会是损失的精确最小值。因为算法会使得损失向最小值缓慢收敛,但不能在有限的步数内非常精确地达到最小值。 -线性回归恰好是一个在整个域中只有一个最小值的学习问题。但是对于像深度神经网络这样复杂的模型来说,损失平面上通常包含许多个最小值。幸运的是,深度学习实践者很少努力寻找能够将 *训练集* 损失最小化的参数,虽然这么这么多的原因尚未被完全理解。事实上,更难做到的是是找到一组参数,这组参数能够在我们从未见过的数据上实现低的损失,这一挑战被称为“泛化”(generalization)。 +线性回归恰好是一个在整个域中只有一个最小值的学习问题。但是对于像深度神经网络这样复杂的模型来说,损失平面上通常包含许多个最小值。幸运的是,深度学习实践者很少努力寻找能够将 *训练集* 损失最小化的参数,虽然这么做原因尚未被完全理解。事实上,更难做到的是找到一组参数,这组参数能够在我们从未见过的数据上实现低的损失,这一挑战被称为 *泛化*(generalization)。 ### 用学习到的模型进行预测 @@ -151,7 +151,7 @@ a = d2l.ones(n) b = d2l.ones(n) ``` -由于在本书中我们将频繁地对运行时间进行基准测试,所以让我们定义一个计时器。 +由于在本书中我们将频繁地进行运行时间的基准测试,所以让我们定义一个计时器。 ```{.python .input} #@tab all @@ -205,7 +205,7 @@ for i in range(n): f'{timer.stop():.5f} sec' ``` -然后,我们使用重载的 `+` 运算符来计算逐元素的和。 +然后,我们使用重载的 `+` 运算符来计算按元素的和。 ```{.python .input} #@tab all @@ -219,9 +219,11 @@ f'{timer.stop():.5f} sec' ## 正态分布与平方损失 :label:`subsec_normal_distribution_and_squared_loss` -虽然你已经可以用上面的内容来动手实践了。接下来,我们通过对噪声分布的假设来更加正式地说明平方损失目标。 +接下来,我们通过对噪声分布的假设来解读平方损失目标。 -线性回归是高斯于 1795 年发明的,他也发现了正态分布(normal distribution)(也称为 *高斯分布*(Gaussian distribution))。正态分布和线性回归之间的关系很密切。回忆一下,具有均值 $\mu$ 和方差 $\sigma^2$(标准差 $\sigma$)的正态分布概率密度函数如下: +正态分布(normal distribution),也称为 *高斯分布*(Gaussian distribution),最早由德国数学家高斯(Gauss)应用于天文学研究。 +正态分布和线性回归之间的关系很密切。 +简单的说,若随机变量 $x$ 具有均值 $\mu$ 和方差 $\sigma^2$(标准差 $\sigma$),其正态分布概率密度函数如下: $$p(x) = \frac{1}{\sqrt{2 \pi \sigma^2}} \exp\left(-\frac{1}{2 \sigma^2} (x - \mu)^2\right).$$ @@ -248,7 +250,7 @@ d2l.plot(x, [normal(x, mu, sigma) for mu, sigma in params], xlabel='x', legend=[f'mean {mu}, std {sigma}' for mu, sigma in params]) ``` -就像我们所看到的,改变均值会产生沿 $x$ 轴的偏移,增加方差会将分散分布、降低其峰值。 +就像我们所看到的,改变均值会产生沿 $x$ 轴的偏移,增加方差将会分散分布、降低其峰值。 利用均方误差损失函数(简称均方损失)可以用于线性回归的一个原因是:假设观测中包含噪声,其中噪声服从正态分布。噪声正态分布如下式: @@ -281,14 +283,14 @@ $$-\log P(\mathbf y \mid \mathbf X) = \sum_{i=1}^n \frac{1}{2} \log(2 \pi \sigma 深度学习从业者喜欢绘制图表来可视化模型中正在发生的事情。 在 :numref:`fig_single_neuron` 中,我们将线性回归模型描述为一个神经网络。 -需要注意的是,该图只显示连接模式,即只显示每个输入如何连接到输出,隐去了权重和偏差的值。 +需要注意的是,该图只显示连接模式,即只显示每个输入如何连接到输出,隐去了权重和偏置的值。 ![线性回归是一个单层神经网络。](../img/singleneuron.svg) :label:`fig_single_neuron` -在 :numref:`fig_single_neuron` 所示的神经网络中,输入为 $x_1, \ldots, x_d$,因此输入层中的 *输入数*(或称为 *特征维度*(feature dimensionality))为 $d$。网络的输出为$o_1$,因此输出层中的 *输出数* 是 1。需要注意的是,输入值都是已经给定的,并且只有一个*计算* 神经元。由于模型重点在发生计算的地方,所以通常我们在计算层数时不考虑输入层。也就是说, :numref:`fig_single_neuron` 中神经网络的 *层数* 为1。我们可以将线性回归模型视为仅由单个人工神经元组成的神经网络,或称为单层神经网络。 +在 :numref:`fig_single_neuron` 所示的神经网络中,输入为 $x_1, \ldots, x_d$,因此输入层中的 *输入数*(或称为 *特征维度* feature dimensionality)为 $d$。网络的输出为$o_1$,因此输出层中的 *输出数* 是 1。需要注意的是,输入值都是已经给定的,并且只有一个*计算* 神经元。由于模型重点在发生计算的地方,所以通常我们在计算层数时不考虑输入层。也就是说, :numref:`fig_single_neuron` 中神经网络的 *层数* 为1。我们可以将线性回归模型视为仅由单个人工神经元组成的神经网络,或称为单层神经网络。 -对于线性回归,每个输入都与每个输出(在本例中只有一个输出)相连,我们将这种变换( :numref:`fig_single_neuron` 中的输出层)称为 *全连接层*(fully-connected layer)(或称为 *稠密层*(dense layer))。下一章将详细讨论由这些层组成的网络。 +对于线性回归,每个输入都与每个输出(在本例中只有一个输出)相连,我们将这种变换( :numref:`fig_single_neuron` 中的输出层)称为 *全连接层*(fully-connected layer)(或称为 *稠密层* dense layer)。下一章将详细讨论由这些层组成的网络。 ### 生物学 @@ -307,7 +309,7 @@ $$-\log P(\mathbf y \mid \mathbf X) = \sum_{i=1}^n \frac{1}{2} \log(2 \pi \sigma *Artificial Intelligence: A Modern Approach* :cite:`Russell.Norvig.2016`, 中所说:虽然飞机可能受到鸟类的启发。但几个世纪以来,鸟类学并不是航空创新的主要驱动力。同样地,如今在深度学习中的灵感同样或更多地来自数学、统计学和计算机科学。 -## 总结 +## 小结 * 机器学习模型中的关键要素是训练数据,损失函数,优化算法,还有模型本身。 * 矢量化使数学表达上更简洁,同时运行的更快。 @@ -319,7 +321,7 @@ $$-\log P(\mathbf y \mid \mathbf X) = \sum_{i=1}^n \frac{1}{2} \log(2 \pi \sigma 1. 假设我们有一些数据 $x_1, \ldots, x_n \in \mathbb{R}$。我们的目标是找到一个常数$b$,使得最小化 $\sum_i (x_i - b)^2$。 1. 找到最优值 $b$ 的解析解。 1. 这个问题及其解与正态分布有什么关系? -1. 推导出使用平方误差的线性回归优化问题的解析解。为了简化问题,可以忽略偏差$b$(我们可以通过向 $\mathbf X$ 添加所有值为1的一列来做到这一点)。 +1. 推导出使用平方误差的线性回归优化问题的解析解。为了简化问题,可以忽略偏置$b$(我们可以通过向 $\mathbf X$ 添加所有值为1的一列来做到这一点)。 1. 用矩阵和向量表示法写出优化问题(将所有数据视为单个矩阵,将所有目标值视为单个向量)。 1. 计算损失对$w$的梯度。 1. 通过将梯度设为0、求解矩阵方程来找到解析解。 diff --git a/chapter_linear-networks/softmax-regression-concise.md b/chapter_linear-networks/softmax-regression-concise.md index 4f7699005..eb1ab2cab 100644 --- a/chapter_linear-networks/softmax-regression-concise.md +++ b/chapter_linear-networks/softmax-regression-concise.md @@ -67,7 +67,7 @@ net.add(tf.keras.layers.Dense(10, kernel_initializer=weight_initializer)) 回想一下,softmax函数 $\hat y_j = \frac{\exp(o_j)}{\sum_k \exp(o_k)}$,其中$\hat y_j$是预测的概率分布。$o_j$是未归一化的预测$\mathbf{o}$的第$j$个元素。如果$o_k$中的一些数值非常大,那么 $\exp(o_k)$ 可能大于数据类型容许的最大数字(即 *上溢*(overflow))。这将使分母或分子变为`inf`(无穷大),我们最后遇到的是0、`inf` 或 `nan`(不是数字)的 $\hat y_j$。在这些情况下,我们不能得到一个明确定义的交叉熵的返回值。 -解决这个问题的一个技巧是,在继续softmax计算之前,先从所有$o_k$中减去$\max(o_k)$。你可以证明每个 $o_k$ 按常数进行的移动不会改变softmax的返回值。在减法和归一化步骤之后,可能有些 $o_j$ 具有较大的负值。由于精度受限, $\exp(o_j)$ 将有接近零的值(即 *下溢(underflow)*)。这些值可能会四舍五入为零,使 $\hat y_j$ 为零,并且使得 $\log(\hat y_j)$ 的值为 `-inf`。反向传播几步后,我们可能会发现自己面对一屏幕可怕的`nan`结果。 +解决这个问题的一个技巧是,在继续softmax计算之前,先从所有$o_k$中减去$\max(o_k)$。你可以证明每个 $o_k$ 按常数进行的移动不会改变softmax的返回值。在减法和归一化步骤之后,可能有些 $o_j$ 具有较大的负值。由于精度受限, $\exp(o_j)$ 将有接近零的值,即 *下溢*(underflow)。这些值可能会四舍五入为零,使 $\hat y_j$ 为零,并且使得 $\log(\hat y_j)$ 的值为 `-inf`。反向传播几步后,我们可能会发现自己面对一屏幕可怕的`nan`结果。 尽管我们要计算指数函数,但我们最终在计算交叉熵损失时会取它们的对数。 通过将softmax和交叉熵结合在一起,可以避免反向传播过程中可能会困扰我们的数值稳定性问题。如下面的等式所示,我们避免计算$\exp(o_j)$,而可以直接使用$o_j$。因为$\log(\exp(\cdot))$被抵消了。 @@ -127,7 +127,7 @@ d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer) 和以前一样,这个算法收敛到一个相当高的精度,而且这次的代码行比以前少了。 -## 总结 +## 小结 * 使用高级 API,我们可以更简洁地实现 softmax 回归。 * 从计算的角度来看,实现softmax回归比较复杂。在许多情况下,深度学习框架在这些著名的技巧之外采取了额外的预防措施,来确保数值的稳定性。这使我们避免了在实践中从零开始编写模型时可能遇到的陷阱。 diff --git a/chapter_linear-networks/softmax-regression-scratch.md b/chapter_linear-networks/softmax-regression-scratch.md index 106c9043c..8dc2af95e 100644 --- a/chapter_linear-networks/softmax-regression-scratch.md +++ b/chapter_linear-networks/softmax-regression-scratch.md @@ -34,7 +34,7 @@ train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size) 这里的每个样本都用固定长度向量表示。原始数据集中的每个样本都是 $28 \times 28$ 的图像。在本节中,我们将展平每个图像,将它们视为长度为784的向量。在以后的章节中,我们将讨论能够利用图像空间结构的复杂策略,但现在我仅将每个像素位置视为一个特征。 -回想一下,在softmax回归中,我们的输出与类别一样多。因为我们的数据集有10个类别,所以网络输出维度为 10。因此,权重将构成一个 $784 \times 10$ 的矩阵,偏差将构成一个 $1 \times 10$ 的行向量。与线性回归一样,我们将使用正态分布初始化我们的权重 `W`,偏差初始化为0。 +回想一下,在softmax回归中,我们的输出与类别一样多。因为我们的数据集有10个类别,所以网络输出维度为 10。因此,权重将构成一个 $784 \times 10$ 的矩阵,偏置将构成一个 $1 \times 10$ 的行向量。与线性回归一样,我们将使用正态分布初始化我们的权重 `W`,偏置初始化为0。 ```{.python .input} num_inputs = 784 @@ -67,7 +67,7 @@ b = tf.Variable(tf.zeros(num_outputs)) ## 定义softmax操作 -在实现softmax回归模型之前,让我们简要地回顾一下`sum`运算符如何沿着张量中的特定维度工作,如 :numref:`subseq_lin-alg-reduction` 和 :numref:`subseq_lin-alg-non-reduction` 所述。给定一个矩阵`X`,我们可以对所有元素求和(默认情况下),也可以只求同一个轴上的元素,即同一列(轴0)或同一行(轴1)。如果 `X` 是一个形状为(2, 3)的张量,我们对列进行求和,则结果将是一个具有形状(3,)的向量。当调用sum运算符时,我们可以指定保持在原始张量的轴数,而不折叠求和的维度。这将产生一个具有形状(1, 3)的二维张量。 +在实现softmax回归模型之前,让我们简要地回顾一下`sum`运算符如何沿着张量中的特定维度工作,如 :numref:`subseq_lin-alg-reduction` 和 :numref:`subseq_lin-alg-non-reduction` 所述。给定一个矩阵`X`,我们可以对所有元素求和(默认情况下),也可以只求同一个轴上的元素,即同一列(轴0)或同一行(轴1)。如果 `X` 是一个形状为 `(2, 3)` 的张量,我们对列进行求和,则结果将是一个具有形状 `(3,)` 的向量。当调用sum运算符时,我们可以指定保持在原始张量的轴数,而不折叠求和的维度。这将产生一个具有形状 `(1, 3)` 的二维张量。 ```{.python .input} #@tab pytorch diff --git a/chapter_linear-networks/softmax-regression.md b/chapter_linear-networks/softmax-regression.md index 3786c1c97..27020ee2e 100644 --- a/chapter_linear-networks/softmax-regression.md +++ b/chapter_linear-networks/softmax-regression.md @@ -20,20 +20,20 @@ 让我们从一个图像分类问题开始简单尝试一下。每次输入是一个 $2\times2$ 的灰度图像。我们可以用一个标量表示每个像素值,每个图像对应四个特征 $x_1, x_2, x_3, x_4$。此外,让我们假设每个图像属于类别 “猫”,“鸡” 和 “狗” 中的一个。 -接下来,我们要选择如何表示标签。我们有两个明显的选择。也许最直接的想法是选择 $y \in \{1, 2, 3\}$,其中整数分别代表 $\{\text{狗}, \text{猫}, \text{鸡}\}$。这是在计算机上*存储*此类信息的好方法。如果类别间有一些自然的排序,比如说我们试图预测 $\{\text{婴儿}, \text{儿童}, \text{青少年}, \text{青年人}, \text{中年人}, \text{老年人}\}$,那么将这个问题转变为回归问题并保留这种格式是有意义的。 +接下来,我们要选择如何表示标签。我们有两个明显的选择。也许最直接的想法是选择 $y \in \{1, 2, 3\}$,其中整数分别代表 $\{\text{狗}, \text{猫}, \text{鸡}\}$。这是在计算机上存储此类信息的好方法。如果类别间有一些自然的排序,比如说我们试图预测 $\{\text{婴儿}, \text{儿童}, \text{青少年}, \text{青年人}, \text{中年人}, \text{老年人}\}$,那么将这个问题转变为回归问题并保留这种格式是有意义的。 但是,一般的分类问题并不与类别之间的自然排序有关。幸运的是,统计学家很早以前就发明了一种表示分类数据的简单方法:*独热编码*(one-hot encoding)。独热编码是一个向量,它的分量和类别一样多。类别对应的分量设置为1,其他所有分量设置为0。 -在我们的例子中,标签 $y$ 将是一个三维向量,其中 $(1, 0, 0)$ 对应于 “猫”,$(0, 1, 0)$ 对应于 “鸡”,$(0, 0, 1)$ 对应于 “狗”: +在我们的例子中,标签 $y$ 将是一个三维向量,其中 $(1, 0, 0)$ 对应于 “猫”、$(0, 1, 0)$ 对应于 “鸡”、$(0, 0, 1)$ 对应于 “狗”: $$y \in \{(1, 0, 0), (0, 1, 0), (0, 0, 1)\}.$$ ## 网络结构 - + 为了估计所有可能类别的条件概率,我们需要一个有多个输出的模型,每个类别对应一个输出。 为了解决线性模型的分类问题,我们需要和输出一样多的仿射函数(affine function)。 每个输出对应于它自己的仿射函数。 -在我们的例子中,由于我们有4个特征和3个可能的输出类别,我们将需要12个标量来表示权重(带下标的$w$),3个标量来表示偏差(带下标的$b$)。 -下面我们为每个输入计算三个*未归一化的预测*(logits):$o_1$、o_2$和$o_3$。 +在我们的例子中,由于我们有4个特征和3个可能的输出类别,我们将需要12个标量来表示权重(带下标的$w$),3个标量来表示偏置(带下标的$b$)。 +下面我们为每个输入计算三个*未归一化的预测*(logits):$o_1$、$o_2$和$o_3$。 $$ \begin{aligned} @@ -50,14 +50,14 @@ $$ :label:`fig_softmaxreg` 为了更简洁地表达模型,我们仍然使用线性代数符号。 -通过向量形式表达为 $\mathbf{o} = \mathbf{W} \mathbf{x} + \mathbf{b}$,这是一种更适合数学和编写代码的形式。我们已经将所有权重放到一个 $3 \times 4$ 矩阵中。对于给定数据样本的特征 $\mathbf{x}$,我们的输出是由权重与输入特征进行矩阵-向量乘法加上偏差$\mathbf{b}$得到的。 +通过向量形式表达为 $\mathbf{o} = \mathbf{W} \mathbf{x} + \mathbf{b}$,这是一种更适合数学和编写代码的形式。我们已经将所有权重放到一个 $3 \times 4$ 矩阵中。对于给定数据样本的特征 $\mathbf{x}$,我们的输出是由权重与输入特征进行矩阵-向量乘法加上偏置$\mathbf{b}$得到的。 ## 全连接层的参数开销 :label:`subsec_parameterization-cost-fc-layers` 正如我们将在后续章节中看到的,在深度学习中,全连接层无处不在。 然而,顾名思义,全连接层是“完全”连接的。这可能有很多可学习的参数。 具体来说,对于任何具有$d$个输入和$q$个输出的全连接层,参数开销为$\mathcal{O}(dq)$,在实践中可能高得令人望而却步。 -幸运的是,将$d$个输入转换为$q$个输出的成本可以减少到$\mathcal{O}(\frac{dq}{n})$,其中超参数$n$可以由我们灵活指定,以在实际应用中平衡节省参数和模型有效性 :cite:`Zhang.Tay.Zhang.ea.2021`。 +幸运的是,将$d$个输入转换为$q$个输出的成本可以减少到$\mathcal{O}(\frac{dq}{n})$,其中超参数$n$可以由我们灵活指定,以在实际应用中平衡节省参数和模型有效性 :cite:`Zhang.Tay.Zhang.ea.2021` 。 @@ -90,7 +90,7 @@ $$ ## 小批量样本的矢量化 :label:`subsec_softmax_vectorization` -为了提高计算效率并且充分利用GPU,我们通常会针对小批量数据执行矢量计算。假设我们读取了一个批量的样本 $\mathbf{X}$ ,其中特征维度(输入数量)为$d$,批量大小为$n$。此外,假设我们在输出中有 $q$ 个类别。设小批量特征为 $\mathbf{X} \in \mathbb{R}^{n \times d}$ ,权重为 $\mathbf{W} \in \mathbb{R}^{d \times q}$,偏差为 $\mathbf{b} \in \mathbb{R}^{1\times q}$。softmax回归的矢量计算表达式为: +为了提高计算效率并且充分利用GPU,我们通常会针对小批量数据执行矢量计算。假设我们读取了一个批量的样本 $\mathbf{X}$ ,其中特征维度(输入数量)为$d$,批量大小为$n$。此外,假设我们在输出中有 $q$ 个类别。设小批量特征为 $\mathbf{X} \in \mathbb{R}^{n \times d}$ ,权重为 $\mathbf{W} \in \mathbb{R}^{d \times q}$,偏置为 $\mathbf{b} \in \mathbb{R}^{1\times q}$。softmax回归的矢量计算表达式为: $$ \begin{aligned} \mathbf{O} &= \mathbf{X} \mathbf{W} + \mathbf{b}, \\ \hat{\mathbf{Y}} & = \mathrm{softmax}(\mathbf{O}). \end{aligned} $$ :eqlabel:`eq_minibatch_softmax_reg` @@ -159,7 +159,7 @@ $$ ### 熵 -信息论的核心思想是量化数据中的信息内容。该数值对我们压缩数据的能力造成了严格限制。在信息论中,该数值被称为分布$P$ 的 *熵*。可以通过以下方程得到: +信息论的核心思想是量化数据中的信息内容,在信息论中,该数值被称为分布$P$ 的 *熵*(entropy)。可以通过以下方程得到: $$H[P] = \sum_j - P(j) \log P(j).$$ :eqlabel:`eq_softmax_reg_entropy` @@ -170,14 +170,14 @@ $$H[P] = \sum_j - P(j) \log P(j).$$ 你可能想知道压缩与预测有什么关系。想象一下,我们有一个要压缩的数据流。如果我们总是很容易预测下一个数据,那么这个数据很容易压缩!举一个极端的例子,数据流中的每个数据总是采用相同的值。这是一个非常无聊的数据流!由于它们总是相同的,所以很容易被预测,所以我们为了传递数据流的内容不必传输任何信息。当数据易于预测,也就易于压缩。 -但是,如果我们不能完全预测每一个事件,那么我们有时可能会感到惊讶。当我们赋予一个事件较低的概率时,我们的惊讶会更大。克劳德·香农决定用 $\log \frac{1}{P(j)} = -\log P(j)$来量化一个人的 *惊讶*(surprisal)。在观察一个事件 $j$,并赋予它(主观)概率 $P(j)$。在 :eqref:`eq_softmax_reg_entropy` 中定义的熵是当分配的概率真正匹配数据生成过程时的*预期惊讶*(expected surprisal)。 +但是,如果我们不能完全预测每一个事件,那么我们有时可能会感到惊异。当我们赋予一个事件较低的概率时,我们的惊异会更大。克劳德·香农决定用 $\log \frac{1}{P(j)} = -\log P(j)$来量化一个人的 *惊异*(surprisal)。在观察一个事件 $j$,并赋予它(主观)概率 $P(j)$。在 :eqref:`eq_softmax_reg_entropy` 中定义的熵是当分配的概率真正匹配数据生成过程时的*预期惊异*(expected surprisal)。 ### 重新审视交叉熵 -所以,如果熵是知道真实概率的人所经历的惊讶程度,那么你可能会想知道,什么是交叉熵? -交叉熵 *从* $P$ *到* $Q$,记为 $H(P, Q)$,是主观概率为$Q$的观察者在看到根据概率$P$实际生成的数据时的预期惊讶。当$P=Q$时,交叉熵达到最低。在这种情况下,从 $P$到$Q$ 的交叉熵是 $H(P, P)= H(P)$。 +所以,如果熵是知道真实概率的人所经历的惊异程度,那么你可能会想知道,什么是交叉熵? +交叉熵 *从* $P$ *到* $Q$,记为 $H(P, Q)$,是主观概率为$Q$的观察者在看到根据概率$P$实际生成的数据时的预期惊异。当$P=Q$时,交叉熵达到最低。在这种情况下,从 $P$到$Q$ 的交叉熵是 $H(P, P)= H(P)$。 -简而言之,我们可以从两方面来考虑交叉熵分类目标:(i)最大化观测数据的似然;(ii)尽量减少我们的惊讶所需的通讯标签。 +简而言之,我们可以从两方面来考虑交叉熵分类目标:(i)最大化观测数据的似然;(ii)尽量减少我们的惊异所需的通讯量。 ## 模型预测和评估 @@ -197,7 +197,7 @@ $$H[P] = \sum_j - P(j) \log P(j).$$ 1. 假设我们有三个类发生的概率相等,即概率向量是 $(\frac{1}{3}, \frac{1}{3}, \frac{1}{3})$。 1. 如果我们尝试为它设计二进制代码,有什么问题? 1. 你能设计一个更好的代码吗?提示:如果我们尝试编码两个独立的观察结果会发生什么?如果我们联合编码 $n$ 个观测值怎么办? -1. softmax是对上面介绍的映射的误用(但深度学习中的每个人都使用它)。真正的Softmax被定义为 $\mathrm{RealSoftMax}(a, b) = \log (\exp(a) + \exp(b))$。 +1. softmax是对上面介绍的映射的误用(但深度学习中的每个人都使用它)。真正的softmax被定义为 $\mathrm{RealSoftMax}(a, b) = \log (\exp(a) + \exp(b))$。 1. 证明 $\mathrm{RealSoftMax}(a, b) > \mathrm{max}(a, b)$。 1. 证明 $\lambda^{-1} \mathrm{RealSoftMax}(\lambda a, \lambda b)$成立,前提是 $\lambda > 0$。 1. 证明对于 $\lambda \to \infty$ ,有 $\lambda^{-1} \mathrm{RealSoftMax}(\lambda a, \lambda b) \to \mathrm{max}(a, b)$。 diff --git a/chapter_multilayer-perceptrons/backprop.md b/chapter_multilayer-perceptrons/backprop.md index d8467d745..c8b5f46e1 100644 --- a/chapter_multilayer-perceptrons/backprop.md +++ b/chapter_multilayer-perceptrons/backprop.md @@ -1,18 +1,18 @@ # 正向传播、反向传播和计算图 :label:`sec_backprop` -到目前为止,我们已经用小批量随机梯度下降训练了我们的模型。然而,当我们实现该算法时,我们只考虑了通过模型*正向传播*所涉及的计算。在计算梯度时,我们只调用了深度学习框架提供的反向传播函数。 +到目前为止,我们已经用小批量随机梯度下降训练了我们的模型。然而,当我们实现该算法时,我们只考虑了通过模型 *正向传播*(forward propagation)所涉及的计算。在计算梯度时,我们只调用了深度学习框架提供的反向传播函数。 梯度的自动计算(自动微分)大大简化了深度学习算法的实现。在自动微分之前,即使是对复杂模型的微小调整也需要手工重新计算复杂的导数。学术论文也不得不分配大量页面来推导更新规则。我们必须继续依赖于自动微分,这样我们就可以专注于有趣的部分,但是如果你想超过对深度学习的浅薄理解,你应当知道这些梯度是如何计算出来的。 -在本节中,我们将深入探讨*反向传播*(backward propagation或backpropagation)的细节。为了传达对这些技术及其实现的一些见解,我们依赖一些基本的数学和计算图。首先,我们将重点放在带权重衰减($L_2$正则化)的单隐藏层多层感知机上。 +在本节中,我们将深入探讨 *反向传播*(backward propagation 或 backpropagation)的细节。为了传达对这些技术及其实现的一些见解,我们依赖一些基本的数学和计算图。首先,我们将重点放在带权重衰减($L_2$正则化)的单隐藏层多层感知机上。 ## 正向传播 -*正向传播*(forward propagation或forward pass)指的是,按从输入层到输出层的顺序计算和存储 -神经网络的中间变量(包括输出)。我们现在一步一步地研究单隐藏层神经网络的机制,虽然这看起来很乏味。 +*正向传播*(forward propagation或forward pass)指的是:按顺序(从输入层到输出层)计算和存储 +神经网络中每层的结果。 -为了简单起见,我们假设输入样本是$\mathbf{x}\in \mathbb{R}^d$,并且我们的隐藏层不包括偏差项。这里的中间变量是: +我们将一步步研究单隐藏层神经网络的机制,为了简单起见,我们假设输入样本是 $\mathbf{x}\in \mathbb{R}^d$,并且我们的隐藏层不包括偏置项。这里的中间变量是: $$\mathbf{z}= \mathbf{W}^{(1)} \mathbf{x},$$ @@ -86,7 +86,7 @@ $$ = {\mathbf{W}^{(2)}}^\top \frac{\partial J}{\partial \mathbf{o}}. $$ -由于激活函数$\phi$是逐元素计算的,计算中间变量$\mathbf{z}$的梯度$\partial J/\partial \mathbf{z} \in \mathbb{R}^h$需要使用逐元素乘法运算符,我们用$\odot$表示: +由于激活函数$\phi$是按元素计算的,计算中间变量$\mathbf{z}$的梯度$\partial J/\partial \mathbf{z} \in \mathbb{R}^h$需要使用按元素乘法运算符,我们用$\odot$表示: $$ \frac{\partial J}{\partial \mathbf{z}} @@ -120,7 +120,7 @@ $$ ## 练习 1. 假设一些标量函数$\mathbf{X}$的输入$\mathbf{X}$是$n \times m$矩阵。$f$相对于$\mathbf{X}$的梯度维数是多少? -1. 向本节中描述的模型的隐藏层添加偏差项(不需要在正则化项中包含偏差项)。 +1. 向本节中描述的模型的隐藏层添加偏置项(不需要在正则化项中包含偏置项)。 1. 画出相应的计算图。 1. 推导正向和后向传播方程。 1. 计算本节所描述的模型,用于训练和预测的内存占用。 diff --git a/chapter_multilayer-perceptrons/dropout.md b/chapter_multilayer-perceptrons/dropout.md index d0b89cd4f..35d20e299 100644 --- a/chapter_multilayer-perceptrons/dropout.md +++ b/chapter_multilayer-perceptrons/dropout.md @@ -244,10 +244,13 @@ class Net(tf.keras.Model): def call(self, inputs, training=None): x = self.input_layer(inputs) x = self.hidden1(x) + # 只有在训练模型时才使用dropout if training: + # 在第一个全连接层之后添加一个dropout层 x = dropout_layer(x, dropout1) x = self.hidden2(x) if training: + # 在第二个全连接层之后添加一个dropout层 x = dropout_layer(x, dropout2) x = self.output_layer(x) return x diff --git a/chapter_multilayer-perceptrons/environment.md b/chapter_multilayer-perceptrons/environment.md index ec2046854..cab824862 100644 --- a/chapter_multilayer-perceptrons/environment.md +++ b/chapter_multilayer-perceptrons/environment.md @@ -39,7 +39,7 @@ ### 概念偏移 -我们也可能会遇到*概念偏移*的相关问题,当标签的定义发生变化时,就会出现这种问题。这听起来很奇怪——一只猫就是一只猫,不是吗?然而,其他类别会随着不同时间的用法而发生变化。精神疾病的诊断标准,所谓的时髦,以及工作头衔,都受到相当大的概念偏移的影响。事实证明,如果我们环游美国,根据所在的地理位置改变我们的数据来源,我们会发现关于*软饮*名称的分布发生了相当大的概念偏移,如 :numref:`fig_popvssoda` 所示。 +我们也可能会遇到*概念偏移*的相关问题,当标签的定义发生变化时,就会出现这种问题。这听起来很奇怪——一只猫就是一只猫,不是吗?然而,其他类别会随着不同时间的用法而发生变化。精神疾病的诊断标准,所谓的时髦,以及工作头衔,都受到相当大的概念偏移的影响。事实证明,如果我们环游美国,根据所在的地理位置改变我们的数据来源,我们会发现关于“软饮”名称的分布发生了相当大的概念偏移,如 :numref:`fig_popvssoda` 所示。 ![美国软饮名称的概念偏移。](../img/popvssoda.png) :width:`400px` @@ -55,19 +55,19 @@ 假设你想设计一个检测癌症的算法。你从健康人和病人那里收集数据,然后训练你的算法。它工作得很好,给你很高的准确性,然后你得出了你已经准备好在医疗诊断事业上取得成功的结论。请先别着急。 -产生训练数据的分布和你在实际中遇到的分布可能有很大的不同。这件事在一个不幸的初创公司身上发生过,我们中的一些人(作者)几年前和他们合作过。他们正在研究一种血液检测方法,主要针对一种影响老年男性的疾病,并希望利用他们从病人身上采集的血液样本进行研究。然而,从健康男性身上获取血样比中系统中已有的病人身上获取要困难得多。作为补偿,这家初创公司向一所大学校园内的学生征集献血,作为开发测试的健康对照样本。然后这家初创公司问我们是否可以帮助他们建立一个用于检测疾病的分类器。 +产生训练数据的分布和你在实际中遇到的分布可能有很大的不同。这件事在一个不幸的初创公司身上发生过,我们中的一些作者几年前和他们合作过。他们正在研究一种血液检测方法,主要针对一种影响老年男性的疾病,并希望利用他们从病人身上采集的血液样本进行研究。然而,从健康男性身上获取血样比中系统中已有的病人身上获取要困难得多。作为补偿,这家初创公司向一所大学校园内的学生征集献血,作为开发测试的健康对照样本。然后这家初创公司问我们是否可以帮助他们建立一个用于检测疾病的分类器。 正如我们向他们解释的那样,用近乎完美的准确度来区分健康和患病人群确实很容易。然而,这是因为受试者在年龄、激素水平、体力活动、饮食、饮酒以及其他许多与疾病无关的因素上存在差异。这对真正的病人可能并不适用。从他们的抽样程序出发,我们可能会遇到极端的协变量偏移。此外,这种情况不太可能通过常规方法加以纠正。简言之,他们浪费了一大笔钱。 ### 自动驾驶汽车 -比如一家公司想利用机器学习来开发自动驾驶汽车。这里的一个关键部件是路沿检测器。由于真实的注释数据获取成本很高,他们想出了一个(聪明却有问题的)想法,将游戏渲染引擎中的合成数据用作额外的训练数据。这对从渲染引擎中抽取的“测试数据”非常有效。但应用在一辆真正的汽车里真是一场灾难。正如事实证明的那样,路沿被渲染成一种非常简单的纹理。更重要的是,*所有的*路沿都被渲染成了相同的纹理,路沿检测器很快就学习到了这个“特征”。 +比如一家公司想利用机器学习来开发自动驾驶汽车。这里的一个关键部件是路沿检测器。由于真实的注释数据获取成本很高,他们想出了一个(聪明却有问题的)想法,将游戏渲染引擎中的合成数据用作额外的训练数据。这对从渲染引擎中抽取的“测试数据”非常有效。但应用在一辆真正的汽车里真是一场灾难。正如事实证明的那样,路沿被渲染成一种非常简单的纹理。更重要的是,所有的路沿都被渲染成了相同的纹理,路沿检测器很快就学习到了这个“特征”。 当美军第一次试图在森林中探测坦克时,也发生了类似的事情。他们在没有坦克的情况下拍摄了森林的航拍照片,然后把坦克开进森林,拍摄了另一组照片。分类器似乎工作得很好。不幸的是,它仅仅学会了如何区分有阴影的树和没有阴影的树——第一组照片是在清晨拍摄的,第二组是在中午拍摄的。 ### 非平稳分布 -当分布变化缓慢(也称为*非平稳分布*)并且模型没有得到充分更新时,就会出现更微妙的情况。以下是一些典型的情况。 +当分布变化缓慢并且模型没有得到充分更新时,就会出现更微妙的情况:*非平稳分布*(nonstationary distribution)。以下是一些典型的情况。 * 我们训练了一个计算广告模型,但却没有经常更新(例如,我们忘记了一个叫iPad的不知名新设备刚刚上市)。 * 我们建立了一个垃圾邮件过滤器。它能很好地检测到我们目前看到的所有垃圾邮件。但是,垃圾邮件发送者们变得聪明起来,制造出新的信息,看起来不像我们以前见过的任何垃圾邮件。 @@ -90,9 +90,9 @@ $$\mathop{\mathrm{minimize}}_f \frac{1}{n} \sum_{i=1}^n l(f(\mathbf{x}_i), y_i),$$ :eqlabel:`eq_empirical-risk-min` -其中$l$是损失函数,用来度量给定响应标签$y_i$,预测$f(\mathbf{x}_i)$的“糟糕程度”。统计学家称:eqref:`eq_empirical-risk-min`中的这一项为 *经验风险*。 -*经验风险*是 -为了近似*真实风险*,整个训练数据上的平均损失,即从其真实分布$p(\mathbf{x},y)$中抽取的所有数据的总体损失的期望值: +其中$l$是损失函数,用来度量给定响应标签$y_i$,预测$f(\mathbf{x}_i)$的“糟糕程度”。统计学家称 :eqref:`eq_empirical-risk-min` 中的这一项为经验风险。 +*经验风险* (empirical risk)是 +为了近似 *真实风险*(true risk),整个训练数据上的平均损失,即从其真实分布$p(\mathbf{x},y)$中抽取的所有数据的总体损失的期望值: $$E_{p(\mathbf{x}, y)} [l(f(\mathbf{x}), y)] = \int\int l(f(\mathbf{x}), y) p(\mathbf{x}, y) \;d\mathbf{x}dy.$$ :eqlabel:`eq_true-risk` @@ -115,7 +115,7 @@ $$ $$\beta_i \stackrel{\mathrm{def}}{=} \frac{p(\mathbf{x}_i)}{q(\mathbf{x}_i)}.$$ -将权重$\beta_i$代入到每个数据样本$(\mathbf{x}_i, y_i)$中,我们可以使用*加权经验风险最小化*来训练模型: +将权重$\beta_i$代入到每个数据样本$(\mathbf{x}_i, y_i)$中,我们可以使用”加权经验风险最小化“来训练模型: $$\mathop{\mathrm{minimize}}_f \frac{1}{n} \sum_{i=1}^n \beta_i l(f(\mathbf{x}_i), y_i).$$ :eqlabel:`eq_weighted-empirical-risk-min` @@ -205,9 +205,9 @@ $$ \mathrm{model} ~ f_{t+1} $$ -### 老虎机(Bandits) +### 老虎机 -*老虎机*是上述问题的一个特例。虽然在大多数学习问题中,我们有一个连续参数化的函数$f$,我们想学习它的参数(例如,一个深度网络),但在一个*老虎机*问题中,我们只有有限数量的手臂可以拉动,也就是说,我们可以采取的行动是有限的。对于这个更简单的问题,可以获得更强的最优性理论保证,这并不令人惊讶。我们之所以列出它,主要是因为这个问题经常被视为一个单独的学习问题的设定。 +*老虎机*(Bandits)是上述问题的一个特例。虽然在大多数学习问题中,我们有一个连续参数化的函数$f$,我们想学习它的参数(例如,一个深度网络),但在一个*老虎机*问题中,我们只有有限数量的手臂可以拉动,也就是说,我们可以采取的行动是有限的。对于这个更简单的问题,可以获得更强的最优性理论保证,这并不令人惊讶。我们之所以列出它,主要是因为这个问题经常被视为一个单独的学习问题的设定。 ### 控制 @@ -215,7 +215,9 @@ $$ ### 强化学习 -在具有记忆环境的更通用的情况中,我们可能会遇到环境试图与我们合作的情况(合作博弈,尤其是非零和博弈),或其他环境试图获胜的情况。国际象棋、围棋、西洋双陆棋或星际争霸都是*强化学习*的一些例子。类似地,我们可能想要为自动驾驶汽车制造一个好的控制器。其他汽车可能会以非平凡的方式对自动驾驶汽车的驾驶方式做出反应,例如,试图避开它,试图造成事故,并试图与其合作。 +*强化学习*(reinforcement learning)强调如何基于环境而行动,以取得最大化的预期利益。 +国际象棋、围棋、西洋双陆棋或星际争霸都是强化学习的一些例子。 +再比如,为自动驾驶汽车制造一个好的控制器,或者以其他方式对自动驾驶汽车的驾驶方式做出反应,例如,试图避开它,试图造成事故,并试图与其合作。 ### 考虑到环境 @@ -223,7 +225,7 @@ $$ ## 机器学习中的公平、责任和透明度 -最后,重要的是要记住,当你部署机器学习系统时,你不仅仅是在优化一个预测模型——你通常是在提供一个会被用来(部分或完全)进行自动化决策的工具。这些技术系统可能会通过其进行的决定而影响到个人的生活。从考虑预测到决策的飞跃不仅提出了新的技术问题,而且还提出了一系列必须仔细考虑的伦理问题。如果我们正在部署一个医疗诊断系统,我们需要知道它可能适用于哪些人群,哪些人群可能无效。忽视对一个亚群体的幸福的可预见风险可能会导致我们执行劣质的护理水平。此外,一旦我们规划整个决策系统,我们必须退后一步,重新考虑如何评估我们的技术。在这个视野变化所导致的结果中,我们会发现*准确率*很少成为合适的衡量标准。例如,当我们将预测转化为行动时,我们通常会考虑到各种方式犯错的潜在成本敏感性。如果对图像错误地分到某一类别可能被视为一种种族伎俩,而错误分到另一个类别是无害的,那么我们可能需要相应地调整我们的阈值,在设计决策方式时考虑到这些社会价值。我们还需要注意预测系统如何导致反馈循环。例如,考虑预测性警务系统,它将巡逻人员分配到预测犯罪率较高的地区。很容易看出一种令人担忧的模式是如何出现的: +最后,重要的是要记住,当你部署机器学习系统时,你不仅仅是在优化一个预测模型——你通常是在提供一个会被用来(部分或完全)进行自动化决策的工具。这些技术系统可能会通过其进行的决定而影响到个人的生活。从考虑预测到决策的飞跃不仅提出了新的技术问题,而且还提出了一系列必须仔细考虑的伦理问题。如果我们正在部署一个医疗诊断系统,我们需要知道它可能适用于哪些人群,哪些人群可能无效。忽视对一个亚群体的幸福的可预见风险可能会导致我们执行劣质的护理水平。此外,一旦我们规划整个决策系统,我们必须退后一步,重新考虑如何评估我们的技术。在这个视野变化所导致的结果中,我们会发现准确率很少成为合适的衡量标准。例如,当我们将预测转化为行动时,我们通常会考虑到各种方式犯错的潜在成本敏感性。如果对图像错误地分到某一类别可能被视为一种种族伎俩,而错误分到另一个类别是无害的,那么我们可能需要相应地调整我们的阈值,在设计决策方式时考虑到这些社会价值。我们还需要注意预测系统如何导致反馈循环。例如,考虑预测性警务系统,它将巡逻人员分配到预测犯罪率较高的地区。很容易看出一种令人担忧的模式是如何出现的: 1. 犯罪率高的社区会得到更多的巡逻。 2. 因此,在这些社区中会发现更多的犯罪行为,输入可用于未来迭代的训练数据。 diff --git a/chapter_multilayer-perceptrons/kaggle-house-price.md b/chapter_multilayer-perceptrons/kaggle-house-price.md index 9d3e3dad9..ce667c6ba 100644 --- a/chapter_multilayer-perceptrons/kaggle-house-price.md +++ b/chapter_multilayer-perceptrons/kaggle-house-price.md @@ -91,7 +91,7 @@ def download_all(): #@save ## 访问和读取数据集 -注意,竞赛数据分为训练集和测试集。每条记录都包括房屋的属性值和属性,如街道类型、施工年份、屋顶类型、地下室状况等。这些特征由各种数据类型组成。例如,建筑年份由整数表示,屋顶类型由离散类别表示,其他特征由浮点数表示。这就是现实让事情变得复杂的地方:例如,一些数据完全丢失了,缺失值被简单地标记为“na”。每套房子的价格只出现在训练集中(毕竟这是一场比赛)。我们将希望划分训练集以创建验证集,但是在将预测结果上传到Kaggle之后,我们只能在官方测试集中评估我们的模型。在 :numref:`fig_house_pricing` 中,"Data"选项卡有下载数据的链接。 +注意,竞赛数据分为训练集和测试集。每条记录都包括房屋的属性值和属性,如街道类型、施工年份、屋顶类型、地下室状况等。这些特征由各种数据类型组成。例如,建筑年份由整数表示,屋顶类型由离散类别表示,其他特征由浮点数表示。这就是现实让事情变得复杂的地方:例如,一些数据完全丢失了,缺失值被简单地标记为“NA”。每套房子的价格只出现在训练集中(毕竟这是一场比赛)。我们将希望划分训练集以创建验证集,但是在将预测结果上传到Kaggle之后,我们只能在官方测试集中评估我们的模型。在 :numref:`fig_house_pricing` 中,"Data"选项卡有下载数据的链接。 开始之前,我们将使用`pandas`读入并处理数据,这是我们在 :numref:`sec_pandas` 中引入的。因此,在继续操作之前,您需要确保已安装`pandas`。幸运的是,如果你正在用Jupyter阅读该书,你可以在不离开笔记本的情况下安装`pandas`。 @@ -463,7 +463,7 @@ train_and_pred(train_features, test_features, train_labels, test_data, 1. 你能通过直接最小化价格的对数来改进你的模型吗?如果你试图预测价格的对数而不是价格,会发生什么? 1. 用平均值替换缺失值总是好主意吗?提示:你能构造一个不随机丢失值的情况吗? 1. 通过$K$折交叉验证调整超参数,从而提高Kaggle的得分。 -1. 通过改进模型(例如,层、权重衰减和dropout)来提高分数。 +1. 通过改进模型(例如,层、权重衰减和dropout)来提高分数。 1. 如果我们没有像本节所做的那样标准化连续的数值特征,会发生什么? :begin_tab:`mxnet` diff --git a/chapter_multilayer-perceptrons/mlp-scratch.md b/chapter_multilayer-perceptrons/mlp-scratch.md index 6fa94052c..b9de1a7c8 100644 --- a/chapter_multilayer-perceptrons/mlp-scratch.md +++ b/chapter_multilayer-perceptrons/mlp-scratch.md @@ -32,7 +32,7 @@ train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size) 回想一下,Fashion-MNIST中的每个图像由$28 \times 28 = 784$个灰度像素值组成。所有图像共分为10个类别。忽略像素之间的空间结构,我们可以将每个图像视为具有784个输入特征和10个类的简单分类数据集。首先,我们将实现一个具有1个隐藏层的多层感知机,其中包含256个隐藏单元。注意,我们可以将这两个量都视为超参数。通常,我们选择2的幂次方作为层的宽度。因为内存在硬件中的分配和寻址方式,这么做往往可以在计算上更高效。 -我们用几个张量来表示我们的参数。注意,对于每一层我们都要记录一个权重矩阵和一个偏差向量。跟以前一样,我们要为这些参数的损失的梯度分配内存。 +我们用几个张量来表示我们的参数。注意,对于每一层我们都要记录一个权重矩阵和一个偏置向量。跟以前一样,我们要为这些参数的损失的梯度分配内存。 ```{.python .input} num_inputs, num_outputs, num_hiddens = 784, 10, 256 diff --git a/chapter_multilayer-perceptrons/mlp.md b/chapter_multilayer-perceptrons/mlp.md index 2b59ed220..a1ca2804c 100644 --- a/chapter_multilayer-perceptrons/mlp.md +++ b/chapter_multilayer-perceptrons/mlp.md @@ -5,7 +5,7 @@ ## 隐藏层 -我们在 :numref:`subsec_linear_model`中描述了仿射变换,它是一个带有偏差项的线性变换。首先,回想一下如 :numref:`fig_softmaxreg`中所示的softmax回归的模型结构。该模型通过单个仿射变换将我们的输入直接映射到我们的输出,然后进行softmax操作。如果我们的标签确实通过仿射变换后与我们的输入数据相关,那么这种方法就足够了。但是,仿射变换中的*线性*是一个很强的假设。 +我们在 :numref:`subsec_linear_model`中描述了仿射变换,它是一个带有偏置项的线性变换。首先,回想一下如 :numref:`fig_softmaxreg`中所示的softmax回归的模型结构。该模型通过单个仿射变换将我们的输入直接映射到我们的输出,然后进行softmax操作。如果我们的标签确实通过仿射变换后与我们的输入数据相关,那么这种方法就足够了。但是,仿射变换中的*线性*是一个很强的假设。 ### 线性模型可能会出错 @@ -32,7 +32,7 @@ ### 从线性到非线性 跟之前的章节一样,我们通过矩阵$\mathbf{X} \in \mathbb{R}^{n \times d}$来表示$n$个样本的小批量,其中每个样本具有$d$个输入(特征)。对于具有$h$个隐藏单元的单隐藏层多层感知机,用$\mathbf{H} \in \mathbb{R}^{n \times h}$表示隐藏层的输出,称为*隐藏表示*(hidden representations)。在数学或代码中,$\mathbf{H}$也被称为*隐藏层变量*(hidden-layer variable)或*隐藏变量*(hidden variable)。 -因为隐藏层和输出层都是全连接的,所以我们具有隐藏层权重$\mathbf{W}^{(1)} \in \mathbb{R}^{d \times h}$和隐藏层偏差$\mathbf{b}^{(1)} \in \mathbb{R}^{1 \times h}$以及输出层权重$\mathbf{W}^{(2)} \in \mathbb{R}^{h \times q}$和输出层偏差$\mathbf{b}^{(2)} \in \mathbb{R}^{1 \times q}$。形式上,我们按如下方式计算单隐藏层多层感知机的输出$\mathbf{O} \in \mathbb{R}^{n \times q}$: +因为隐藏层和输出层都是全连接的,所以我们具有隐藏层权重$\mathbf{W}^{(1)} \in \mathbb{R}^{d \times h}$和隐藏层偏置$\mathbf{b}^{(1)} \in \mathbb{R}^{1 \times h}$以及输出层权重$\mathbf{W}^{(2)} \in \mathbb{R}^{h \times q}$和输出层偏置$\mathbf{b}^{(2)} \in \mathbb{R}^{1 \times q}$。形式上,我们按如下方式计算单隐藏层多层感知机的输出$\mathbf{O} \in \mathbb{R}^{n \times q}$: $$ \begin{aligned} @@ -58,7 +58,7 @@ $$ \end{aligned} $$ -由于$\mathbf{X}$中的每一行对应于小批量中的一个样本,即我们定义非线性函数$\sigma$以逐行的方式应用于其输入,即,一次计算一个样本。我们在 :numref:`subsec_softmax_vectorization` 中以相同的方式使用了softmax符号来表示逐行操作。但是在本节中,我们应用于隐藏层的激活函数通常不仅仅是逐行的,而且也是逐元素。 +由于$\mathbf{X}$中的每一行对应于小批量中的一个样本,即我们定义非线性函数$\sigma$以按行的方式应用于其输入,即,一次计算一个样本。我们在 :numref:`subsec_softmax_vectorization` 中以相同的方式使用了softmax符号来表示按行操作。但是在本节中,我们应用于隐藏层的激活函数通常不仅仅是按行的,而且也是按元素。 这意味着在计算每一层的线性部分之后,我们可以计算每个激活值,而不需要查看其他隐藏单元所取的值。对于大多数激活函数都是这样。 为了构建更通用的多层感知机,我们可以继续堆叠这样的隐藏层,例如,$\mathbf{H}^{(1)} = \sigma_1(\mathbf{X} \mathbf{W}^{(1)} + \mathbf{b}^{(1)})$和$\mathbf{H}^{(2)} = \sigma_2(\mathbf{H}^{(1)} \mathbf{W}^{(2)} + \mathbf{b}^{(2)})$,一层叠一层,从而产生更有表达能力的模型。 @@ -92,7 +92,7 @@ import tensorflow as tf ## 激活函数 -激活函数通过计算加权和并加上偏差来确定神经元是否应该被激活。它们是将输入信号转换为输出的可微运算。大多数激活函数都是非线性的。由于激活函数是深度学习的基础,下面简要介绍一些常见的激活函数。 +激活函数通过计算加权和并加上偏置来确定神经元是否应该被激活。它们是将输入信号转换为输出的可微运算。大多数激活函数都是非线性的。由于激活函数是深度学习的基础,下面简要介绍一些常见的激活函数。 ### ReLU函数 diff --git a/chapter_multilayer-perceptrons/numerical-stability-and-init.md b/chapter_multilayer-perceptrons/numerical-stability-and-init.md index b00eca8d8..711921d34 100644 --- a/chapter_multilayer-perceptrons/numerical-stability-and-init.md +++ b/chapter_multilayer-perceptrons/numerical-stability-and-init.md @@ -13,9 +13,11 @@ $$\mathbf{h}^{(l)} = f_l (\mathbf{h}^{(l-1)}) \text{ 因此 } \mathbf{o} = f_L \ $$\partial_{\mathbf{W}^{(l)}} \mathbf{o} = \underbrace{\partial_{\mathbf{h}^{(L-1)}} \mathbf{h}^{(L)}}_{ \mathbf{M}^{(L)} \stackrel{\mathrm{def}}{=}} \cdot \ldots \cdot \underbrace{\partial_{\mathbf{h}^{(l)}} \mathbf{h}^{(l+1)}}_{ \mathbf{M}^{(l+1)} \stackrel{\mathrm{def}}{=}} \underbrace{\partial_{\mathbf{W}^{(l)}} \mathbf{h}^{(l)}}_{ \mathbf{v}^{(l)} \stackrel{\mathrm{def}}{=}}.$$ -换言之,该梯度是$L-l$个矩阵$\mathbf{M}^{(L)} \cdot \ldots \cdot \mathbf{M}^{(l+1)}$与梯度向量$\mathbf{v}^{(l)}$的乘积。因此,我们容易受到数值下溢问题的影响,当将太多的概率乘在一起时,这些问题经常会出现。在处理概率时,一个常见的技巧是切换到对数空间,即将数值表示的压力从尾数转移到指数。不幸的是,我们上面的问题更为严重:最初,矩阵$\mathbf{M}^{(l)}$可能具有各种各样的特征值。他们可能很小,也可能很大,他们的乘积可能*非常大*,也可能*非常小*。 +换言之,该梯度是$L-l$个矩阵$\mathbf{M}^{(L)} \cdot \ldots \cdot \mathbf{M}^{(l+1)}$与梯度向量 $\mathbf{v}^{(l)}$的乘积。因此,我们容易受到数值下溢问题的影响,当将太多的概率乘在一起时,这些问题经常会出现。在处理概率时,一个常见的技巧是切换到对数空间,即将数值表示的压力从尾数转移到指数。不幸的是,我们上面的问题更为严重:最初,矩阵 $\mathbf{M}^{(l)}$ 可能具有各种各样的特征值。他们可能很小,也可能很大,他们的乘积可能*非常大*,也可能*非常小*。 -不稳定梯度带来的风险不止在于数值表示。不稳定梯度也威胁到我们优化算法的稳定性。我们可能面临一些问题。要么参数更新过大,破坏了我们的模型(*梯度爆炸*问题);要么参数更新过小(*梯度消失*问题),参数在每次更新时几乎不会移动,导致无法学习。 +不稳定梯度带来的风险不止在于数值表示。不稳定梯度也威胁到我们优化算法的稳定性。我们可能面临一些问题。 +要么是 *梯度爆炸*(gradient exploding)问题:参数更新过大,破坏了模型的稳定收敛; +要么是 *梯度消失*(gradient vanishing)问题:参数更新过小,在每次更新时几乎不会移动,导致无法学习。 ### 梯度消失 diff --git a/chapter_multilayer-perceptrons/underfit-overfit.md b/chapter_multilayer-perceptrons/underfit-overfit.md index f5c9d97a4..0107906b9 100644 --- a/chapter_multilayer-perceptrons/underfit-overfit.md +++ b/chapter_multilayer-perceptrons/underfit-overfit.md @@ -87,7 +87,7 @@ $$\hat{y}= \sum_{i=0}^d x^i w_i$$ -这只是一个线性回归问题,我们的特征是$x$的幂给出的,模型的权重是$w_i$给出的,偏差是$w_0$给出的(因为对于所有的$x$都有$x^0 = 1$)。由于这只是一个线性回归问题,我们可以使用平方误差作为我们的损失函数。 +这只是一个线性回归问题,我们的特征是$x$的幂给出的,模型的权重是$w_i$给出的,偏置是$w_0$给出的(因为对于所有的$x$都有$x^0 = 1$)。由于这只是一个线性回归问题,我们可以使用平方误差作为我们的损失函数。 高阶多项式函数比低阶多项式函数复杂得多。高阶多项式的参数较多,模型函数的选择范围较广。因此在固定训练数据集的情况下,高阶多项式函数相对于低阶多项式的训练误差应该始终更低(最坏情况下是相等的)。事实上,当数据样本包含了$x$的不同值时,函数阶数等于数据样本数量的多项式函数就可以很好地拟合训练集。在 :numref:`fig_capacity_vs_error` 中,我们直观地描述了多项式的阶数和欠拟合与过拟合之间的关系。 @@ -154,7 +154,7 @@ labels = np.dot(poly_features, true_w) labels += np.random.normal(scale=0.1, size=labels.shape) ``` -同样,存储在`poly_features`中的单项式由gamma函数重新缩放,其中$\Gamma(n)=(n-1)!$。从生成的数据集中查看前2个样本。值1是与偏差相对应的常量特征。 +同样,存储在`poly_features`中的单项式由gamma函数重新缩放,其中$\Gamma(n)=(n-1)!$。从生成的数据集中查看前2个样本。值1是与偏置相对应的常量特征。 ```{.python .input} #@tab pytorch, tensorflow @@ -203,7 +203,7 @@ def train(train_features, test_features, train_labels, test_labels, num_epochs=400): loss = gluon.loss.L2Loss() net = nn.Sequential() - # 不设置偏差,因为我们已经在多项式特征中实现了它 + # 不设置偏置,因为我们已经在多项式特征中实现了它 net.add(nn.Dense(1, use_bias=False)) net.initialize() batch_size = min(10, train_labels.shape[0]) @@ -229,7 +229,7 @@ def train(train_features, test_features, train_labels, test_labels, num_epochs=400): loss = nn.MSELoss() input_shape = train_features.shape[-1] - # 不设置偏差,因为我们已经在多项式特征中实现了它 + # 不设置偏置,因为我们已经在多项式特征中实现了它 net = nn.Sequential(nn.Linear(input_shape, 1, bias=False)) batch_size = min(10, train_labels.shape[0]) train_iter = d2l.load_array((train_features, train_labels.reshape(-1,1)), @@ -254,7 +254,7 @@ def train(train_features, test_features, train_labels, test_labels, num_epochs=400): loss = tf.losses.MeanSquaredError() input_shape = train_features.shape[-1] - # 不设置偏差,因为我们已经在多项式特征中实现了它 + # 不设置偏置,因为我们已经在多项式特征中实现了它 net = tf.keras.Sequential() net.add(tf.keras.layers.Dense(1, use_bias=False)) batch_size = min(10, train_labels.shape[0]) diff --git a/chapter_multilayer-perceptrons/weight-decay.md b/chapter_multilayer-perceptrons/weight-decay.md index 150679684..8e7a11c75 100644 --- a/chapter_multilayer-perceptrons/weight-decay.md +++ b/chapter_multilayer-perceptrons/weight-decay.md @@ -17,7 +17,7 @@ $$L(\mathbf{w}, b) = \frac{1}{n}\sum_{i=1}^n \frac{1}{2}\left(\mathbf{w}^\top \mathbf{x}^{(i)} + b - y^{(i)}\right)^2.$$ -回想一下,$\mathbf{x}^{(i)}$是样本$i$的特征,$y^{(i)}$是样本$i$的标签。$(\mathbf{w}, b)$是权重和偏差参数。为了惩罚权重向量的大小,我们必须以某种方式在损失函数中添加$\| \mathbf{w} \|^2$,但是模型应该如何平衡这个新的额外惩罚的损失?实际上,我们通过*正则化常数*$\lambda$来描述这种权衡,这是一个非负超参数,我们使用验证数据拟合: +回想一下,$\mathbf{x}^{(i)}$是样本$i$的特征,$y^{(i)}$是样本$i$的标签。$(\mathbf{w}, b)$是权重和偏置参数。为了惩罚权重向量的大小,我们必须以某种方式在损失函数中添加$\| \mathbf{w} \|^2$,但是模型应该如何平衡这个新的额外惩罚的损失?实际上,我们通过*正则化常数*$\lambda$来描述这种权衡,这是一个非负超参数,我们使用验证数据拟合: $$L(\mathbf{w}, b) + \frac{\lambda}{2} \|\mathbf{w}\|^2,$$ @@ -37,7 +37,7 @@ $$ 根据之前章节所讲的,我们根据估计值与观测值之间的差异来更新$\mathbf{w}$。然而,我们同时也在试图将$\mathbf{w}$的大小缩小到零。这就是为什么这种方法有时被称为*权重衰减*。我们仅考虑惩罚项,优化算法在训练的每一步*衰减*权重。与特征选择相比,权重衰减为我们提供了一种连续的机制来调整函数的复杂度。较小的$\lambda$值对应较少约束的$\mathbf{w}$,而较大的$\lambda$值对$\mathbf{w}$的约束更大。 -是否对相应的偏差$b^2$进行惩罚在不同的实现中会有所不同。在神经网络的不同层中也会有所不同。通常,我们不正则化网络输出层的偏差项。 +是否对相应的偏置$b^2$进行惩罚在不同的实现中会有所不同。在神经网络的不同层中也会有所不同。通常,我们不正则化网络输出层的偏置项。 ## 高维线性回归 @@ -226,7 +226,7 @@ train(lambd=3) 由于权重衰减在神经网络优化中很常用,深度学习框架为了便于使用权重衰减,便将权重衰减集成到优化算法中,以便与任何损失函数结合使用。此外,这种集成还有计算上的好处,允许在不增加任何额外的计算开销的情况下向算法中添加权重衰减。由于更新的权重衰减部分仅依赖于每个参数的当前值,因此优化器必须至少接触每个参数一次。 :begin_tab:`mxnet` -在下面的代码中,我们在实例化`Trainer`时直接通过`wd`指定weight decay超参数。默认情况下,Gluon同时衰减权重和偏差。注意,更新模型参数时,超参数`wd`将乘以`wd_mult`。因此,如果我们将`wd_mult`设置为零,则偏差参数$b$将不会被衰减。 +在下面的代码中,我们在实例化`Trainer`时直接通过`wd`指定weight decay超参数。默认情况下,Gluon同时衰减权重和偏置。注意,更新模型参数时,超参数`wd`将乘以`wd_mult`。因此,如果我们将`wd_mult`设置为零,则偏置参数$b$将不会被衰减。 :end_tab: :begin_tab:`pytorch` @@ -246,7 +246,7 @@ def train_concise(wd): num_epochs, lr = 100, 0.003 trainer = gluon.Trainer(net.collect_params(), 'sgd', {'learning_rate': lr, 'wd': wd}) - # 偏差参数没有衰减。偏差名称通常以“Bias”结尾 + # 偏置参数没有衰减。偏置名称通常以“Bias”结尾 net.collect_params('.*bias').setattr('wd_mult', 0) animator = d2l.Animator(xlabel='epochs', ylabel='loss', yscale='log', xlim=[5, num_epochs], legend=['train', 'test']) @@ -270,7 +270,7 @@ def train_concise(wd): param.data.normal_() loss = nn.MSELoss() num_epochs, lr = 100, 0.003 - # 偏差参数没有衰减。 + # 偏置参数没有衰减。 trainer = torch.optim.SGD([ {"params":net[0].weight,'weight_decay': wd}, {"params":net[0].bias}], lr=lr) diff --git a/chapter_notation/index.md b/chapter_notation/index.md index ae61b18c7..cddd9295f 100644 --- a/chapter_notation/index.md +++ b/chapter_notation/index.md @@ -10,14 +10,14 @@ * $\mathbf{X}$:矩阵 * $\mathsf{X}$:张量 * $\mathbf{I}$:单位矩阵 -* $x_i$, $[\mathbf{x}]_i$:向量$\mathbf{x}$的第$i$个元素 +* $x_i$, $[\mathbf{x}]_i$:向量$\mathbf{x}$第$i$个元素 * $x_{ij}$, $[\mathbf{X}]_{ij}$:矩阵$\mathbf{X}$第$i$行第$j$列的元素 ## 集合论 * $\mathcal{X}$: 集合 -* $\mathbb{Z}$: 整数的集合 -* $\mathbb{R}$ 实数的集合 +* $\mathbb{Z}$: 整数集合 +* $\mathbb{R}$ 实数集合 * $\mathbb{R}^n$: $n$维实数向量 * $\mathbb{R}^{a\times b}$: 包含$a$行和$b$列的实数矩阵 * $\mathcal{A}\cup\mathcal{B}$: 集合$\mathcal{A}$和$\mathcal{B}$的并集 @@ -47,7 +47,7 @@ * $\frac{dy}{dx}$:$y$关于$x$的导数 * $\frac{\partial y}{\partial x}$:$y$关于$x$的偏导数 * $\nabla_{\mathbf{x}} y$:$y$关于$\mathbf{x}$的梯度 -* $\int_a^b f(x) \;dx$: $f$从$a$到$b$关于$x$的定积分 +* $\int_a^b f(x) \;dx$: $f$在$a$到$b$区间上关于$x$的定积分 * $\int f(x) \;dx$: $f$关于$x$的不定积分 ## 概率与信息论 @@ -70,4 +70,4 @@ * $\mathcal{O}$:大O标记 -[Discussions](https://discuss.d2l.ai/t/25) +[Discussions](https://discuss.d2l.ai/t/2089) diff --git a/chapter_preface/index.md b/chapter_preface/index.md index 15616105d..fbde76c01 100644 --- a/chapter_preface/index.md +++ b/chapter_preface/index.md @@ -1,63 +1,61 @@ # 序言 -就在几年前,大型公司和初创公司没有一批深度学习科学家开发智能产品和服务。当我们中最年轻的人(作者)进入这个领域时,机器学习并没有在日报上获得头条新闻。我们的父母不知道什么是机器学习,更不用说为什么我们更喜欢它而不是医学或法律职业。机器学习是一门具有前瞻性的学术学科,其中包括一系列狭窄的实际应用程序。这些应用程序,例如语音识别和计算机视觉,需要太多的领域知识,以至于它们往往被视为完全独立的领域,机器学习只是一个小组成部分。然后,神经网络,我们在这本书中关注的深度学习模型的先验,被认为是过时的工具。 +几年前,没有大量深度学习科学家在大公司和初创公司开发智能产品和服务。我们中年轻人(作者)进入这个领域时,机器学习并没有在报纸上获得头条新闻。我们的父母根本不知道什么是机器学习,更不用说为什么我们可能更喜欢机器学习,而不是从事医学或法律职业。机器学习是一门具有前瞻性的学科,在现实世界的应用范围很窄。而那些应用,例如语音识别和计算机视觉,需要大量的领域知识,以至于它们通常被认为是完全独立的领域,而机器学习对于这些领域来说只是一个小组件。因此,神经网络——我们在本书中关注的深度学习模型的前身,被认为是过时的工具。 -在过去的五年里,深度学习让世界感到惊讶,推动了计算机视觉、自然语言处理、自动语音识别、强化学习和统计建模等不同领域的快速发展。随着这些进步,我们现在可以打造出比以往任何时候都更具自主性的汽车(并且比某些公司更少的自主性),自动起草最平凡的电子邮件的智能回复系统,帮助人们从压迫性的大型收件箱中挖掘出来,以及软件代理人在棋盘游戏中主宰着世界上最好的人类,如 Go,这一壮举曾经被认为是几十年之遥。这些工具已经对工业和社会产生了越来越广泛的影响,改变了电影的制作方式,诊断疾病,并在从天体物理学到生物学的基础科学中扮演着越来越大的角色。 +就在过去的五年里,深度学习给世界带来了惊喜,推动了计算机视觉、自然语言处理、自动语音识别、强化学习和统计建模等领域的快速发展。有了这些进步,我们现在可以制造比以往任何时候都更自主的汽车(不过可能没有一些公司试图让你相信的那么自主),可以自动起草普通邮件的智能回复系统,帮助人们从令人压抑的大收件箱中挖掘出来。在围棋等棋类游戏中,软件超越了世界上最优秀的人,这曾被认为是几十年后的事。这些工具已经对工业和社会产生了越来越广泛的影响,改变了电影的制作方式、疾病的诊断方式,并在基础科学中扮演着越来越重要的角色——从天体物理学到生物学。 ## 关于本书 -这本书代表了我们努力使深度学习易于接近,教你 * 概念 *、* 上下文 * 和 * 代码 *。 +这本书代表了我们的尝试——让深度学习可平易近人,教会你*概念*、*背景*和*代码*。 -### 一种结合代码、数学和 HTML 的媒介 +### 一种结合了代码、数学和HTML的媒介 -为了使任何计算技术发挥全面影响,它必须得到充分理解、有充分记录,并得到成熟、维护良好的工具的支持。应当清楚地提炼关键的想法,最大限度地减少新从业人员所需的入职时间,让新从业人员了解最新情况。成熟的库应该自动执行常见任务,示例代码应该使从业人员能够轻松修改、应用和扩展常见应用程序以满足他们的需求。以动态 Web 应用程序为样本。尽管像亚马逊这样的许多公司在 1990 年代开发了成功的数据库驱动的 Web 应用程序,但在过去十年中,这项技术在帮助创意企业家方面的潜力得到了更大程度的实现,部分原因是开发了强大的、有文件记录的框架. +任何一种计算技术要想发挥其全部影响力,都必须得到充分的理解、充分的文档记录,并得到成熟的、维护良好的工具的支持。关键思想应该被清楚地提炼出来,尽可能减少需要让新的从业者跟上时代的入门时间。成熟的库应该自动化常见的任务,示例代码应该使从业者可以轻松地修改、应用和扩展常见的应用程序,以满足他们的需求。以动态网页应用为例。尽管许多公司,如亚马逊,在20世纪90年代开发了成功的数据库驱动网页应用程序。但在过去的10年里,这项技术在帮助创造性企业家方面的潜力已经得到了更大程度的发挥,部分原因是开发了功能强大、文档完整的框架。 -测试深度学习的潜力带来了独特的挑战,因为任何一个应用程序都汇集了不同的学科。应用深度学习需要同时了解 (一) 以特定方式解决问题的动机;(二) 特定模型方法的数学;(三) 将模型与数据拟合的优化算法;(四) 以及有效培训模型所需的工程,浏览数字计算的缺陷,并充分利用可用硬件。教授制定问题所需的批判性思维技巧、解决问题的数学技巧以及实施这些解决方案的软件工具都是艰巨的挑战。我们在这本书中的目标是提供一个统一的资源,以帮助潜在的从业者加快速度。 +测试深度学习的潜力带来了独特的挑战,因为任何一个应用都会将不同的学科结合在一起。应用深度学习需要同时了解(1)以特定方式提出问题的动机;(2)给定建模方法的数学;(3)将模型拟合数据的优化算法;(4)能够有效训练模型、克服数值计算缺陷并最大限度地利用现有硬件的工程方法。同时教授表述问题所需的批判性思维技能、解决问题所需的数学知识,以及实现这些解决方案所需的软件工具,这是一个巨大的挑战。 -在我们开始这本书项目的时候,没有资源可以同时更新 (i);(ii) 以极大的技术深度涵盖现代机器学习的全面范围;(iii) 交错展示一本引人入胜的教科书的质量,使用干净的可运行代码,人们希望在实践教程中找到。我们发现了很多代码示例,用于如何使用给定的深度学习框架(例如,如何在 TensorFlow 中使用矩阵进行基本数字计算)或实现特定技术(例如 LenNet,AlexNet,ResNet 等的代码片段)分布在各种博客文章和 GitHub 存储库中。但是,这些示例通常侧重于 -*如何 * 实施给定的方法, -但忽视了 * 为什么 * 某些算法决策的讨论。虽然一些互动资源偶尔出现,以解决某个特定主题,例如在网站 [Distill](http://distill.pub) 上发布的引人入胜的博客文章或个人博客,但它们只涉及深度学习中的选定主题,而且往往缺乏相关代码。另一方面,虽然出现了一些教科书,最值得注意的是 :cite:`Goodfellow.Bengio.Courville.2016`,它对深度学习背后的概念进行了全面的调查,但这些资源并没有将描述与代码中的概念的实现结合起来,有时让读者对如何实现这些概念毫不知道。此外,太多的资源隐藏在商业课程提供者的支付墙后面。 +在我们开始写这本书的时候,没有资源能够同时满足一些条件:(1)是最新的;(2)涵盖了现代机器学习的所有领域,技术深度丰富;(3)在一本引人入胜的教科书中,你可以在实践教程中找到干净的可运行代码,并从中穿插高质量的阐述。我们发现了大量关于如何使用给定的深度学习框架(例如,如何对TensorFlow中的矩阵进行基本的数值计算)或实现特定技术的代码示例(例如,LeNet、AlexNet、ResNet的代码片段),这些代码示例分散在各种博客帖子和GitHub库中。但是,这些示例通常关注如何实现给定的方法,但忽略了为什么做出某些算法决策的讨论。虽然一些互动资源已经零星地出现以解决特定主题。例如,在网站[Distill](http://distill.pub)上发布的引人入胜的博客帖子或个人博客,但它们仅覆盖深度学习中的选定主题,并且通常缺乏相关代码。另一方面,虽然已经出现了几本教科书,其中最著名的是:cite:`Goodfellow.Bengio.Courville.2016`(中文名《深度学习》),它对深度学习背后的概念进行了全面的调查,但这些资源并没有将这些概念的描述与这些概念的代码实现结合起来。有时会让读者对如何实现它们一无所知。此外,太多的资源隐藏在商业课程提供商的付费壁垒后面。 -我们着手创造一种资源,以便 (i) 每个人都可以免费使用;(ii) 提供足够的技术深度,为实际成为应用机器学习科学家的道路提供一个起点;(iii) 包括可运行的代码,向读者展示如何解决实践中的问题;(iv) 允许以获得我们和整个社区的快速更新;以及 (v) 辅以 [forum](http://discuss.d2l.ai),用于互动讨论技术细节和回答问题。 +我们着手创建的资源可以:(1)每个人都可以免费获得;(2)提供足够的技术深度,为真正成为一名应用机器学习科学家提供起步;(3)包括可运行的代码,向读者展示如何解决实践中的问题;(4)允许我们和社区的快速更新;(5)由一个[论坛](http://discuss.d2l.ai)作为补充,用于技术细节的互动讨论和回答问题。 -这些目标往往发生冲突。方程式、定理和引用最好在 LaTeX 中管理和布局。代码在 Python 中最好地描述。网页是原生的 HTML 和 JavaScript。此外,我们希望这些内容既可以作为可执行代码、实体书籍、可下载的 PDF,也可以作为网站在互联网上访问。目前没有工具,也没有完全适合这些需求的工作流程,所以我们必须组装自己的工作流程。我们在 :numref:`sec_how_to_contribute` 中详细描述了我们的方法。我们解决了 GitHub 来共享源代码并允许编辑,用于混合代码的木星笔记本,方程式和文本,狮身人面像作为渲染引擎来生成多个输出,以及论坛的话语。虽然我们的制度尚不完善,但这些选择在相互竞争的关切之间提供了良好的妥协。我们相信,这可能是第一本使用这样一个集成的工作流程出版的书。 +这些目标经常是相互冲突的。公式、定理和引用最好用LaTeX来管理和布局。代码最好用Python描述。网页原生是HTML和JavaScript的。此外,我们希望内容既可以作为可执行代码访问、作为纸质书访问,作为可下载的PDF访问,也可以作为网站在互联网上访问。目前还没有完全适合这些需求的工具和工作流程,所以我们不得不自行组装。我们在 :numref:`sec_how_to_contribute` 中详细描述了我们的方法。我们选择GitHub来共享源代码并允许编辑,选择Jupyter记事本来混合代码、公式和文本,选择Sphinx作为渲染引擎来生成多个输出,并为论坛提供讨论。虽然我们的体系尚不完善,但这些选择在相互冲突的问题之间提供了一个很好的妥协。我们相信,这可能是第一本使用这种集成工作流程出版的书。 -### 通过做学习 +### 在实践中学习 -许多教科书教授一系列主题,每一个都详尽无遗。样本,克里斯·毕夏普出色的教科书 :cite:`Bishop.2006`,教授每个主题如此彻底,到达关于线性回归的章节需要大量的工作。虽然专家喜欢这本书正是因为它的彻底性,对于初学者来说,这个属性限制了它作为一个介绍性文本的有用性。 +许多教科书教授一系列的主题,每一个都非常详细。例如,克里斯·毕晓普(Chris Bishop)的优秀教科书 :cite:`Bishop.2006` ,对每个主题都教得很透彻,以至于要读到线性回归这一章需要大量的工作。虽然专家们喜欢这本书正是因为它的透彻性,但对于初学者来说,这一特性限制了它作为介绍性文本的实用性。 -在这本书中,我们将教授大多数概念 * 只是及时 *。换句话说,你将学习概念的时刻,它们是为了实现一些实际目的而需要的。虽然我们在一开始就需要一些时间来教授基础预赛,比如线性代数和概率,但我们希望您在担心更深奥的概率分布之前尝试训练第一个模型的满意度。 +在这本书中,我们将适时教授大部分概念。换句话说,你将在实现某些实际目的所需的非常时刻学习概念。虽然我们在开始时花了一些时间来教授基础基础知识,如线性代数和概率,但我们希望你在担心更深奥的概率分布之前,先体会一下训练第一个模型的满足感。 -除了在基本数学背景下提供崩溃课程的一些初步笔记本电脑外,随后的每一章都介绍了合理数量的新概念,并提供了使用真实数据集的单独的工作示例。这是一个组织方面的挑战。某些型号可能在逻辑上分组到一个笔记本中。一些想法可能最好通过连续执行几个模型来教授。另一方面,遵守 *1 工作样本,1 笔记本 * 的政策有一个很大的优势:这使您可以通过利用我们的代码来启动自己的研究项目。只需复制笔记本并开始修改它。 +除了提供基本数学背景速成课程的几节初步课程外,后续的每一章都介绍了合理数量的新概念,并提供一个独立工作的例子——使用真实的数据集。这带来了组织上的挑战。某些模型可能在逻辑上组合在单节中。而一些想法可能最好是通过连续允许几个模型来传授。另一方面,坚持“一个工作例子一节”的策略有一个很大的好处:这使你可以通过利用我们的代码尽可能轻松地启动你自己的研究项目。只需复制这一节的内容并开始修改即可。 -我们将根据需要将可运行的代码与背景材料交替。一般来说,在完全解释之前,我们经常会在提供工具方面出错(我们将在稍后解释背景)。实例,在完全解释为什么它有用或为什么它有效之前,我们可能会使用 * 随机梯度降序 *。这有助于为从业者提供必要的弹药来快速解决问题,而牺牲读者要相信我们作出策展决定。 +我们将根据需要将可运行代码与背景材料交错。通常,在充分解释工具之前,我们常常会在提供工具这一方面犯错误(我们将在稍后解释背景)。例如,在充分解释*随机梯度下降*为什么有用或为什么有效之前,我们可以使用它。这有助于给从业者提供快速解决问题所需的弹药,同时需要读者相信我们的一些决定。 -这本书将从头开始教授深度学习概念。有时,我们希望深入研究有关模型的细节,这些模型通常会通过深度学习框架的高级抽象隐藏在用户身上。这尤其是在基本教程中出现,我们希望您了解给定图层或优化器中发生的一切。在这些情况下,我们经常提供两个版本的样本:一个版本我们从头开始实现所有内容,仅依赖 NumPy 接口和自动区分,另一个更实用的例子,我们使用 Gluon 编写简洁的代码。一旦我们教你一些组件是如何工作的,我们可以在后续教程中使用 Gluon 版本。 +这本书将从头开始教授深度学习的概念。有时,我们想深入研究模型的细节,这些的细节通常会被深度学习框架的高级抽象隐藏起来。特别是在基础教程中,我们希望你了解在给定层或优化器中发生的一切。在这些情况下,我们通常会提供两个版本的示例:一个是我们从零开始实现一切,仅依赖于NumPy接口和自动微分;另一个是更实际的示例,我们使用深度学习框架的高级API编写简洁的代码。一旦我们教了您一些组件是如何工作的,我们就可以在随后的教程中使用高级API了。 ### 内容和结构 -这本书可以大致分为三个部分,这些部分是由不同的颜色在 :numref:`fig_book_org`: +全书大致可分为三个部分,在 :numref:`fig_book_org` 中用不同的颜色呈现: -![Book structure](../img/book-org.svg) +![全书结构](../img/book-org.svg) :label:`fig_book_org` -* 第一部分包括基础知识和预赛。 -:numref:`chap_introduction` 提供了深度学习的介绍。然后,在 :numref:`chap_preliminaries` 中,我们可以快速了解深度学习所需的先决条件,例如如何存储和操作数据,以及如何根据线性代数、微积分和概率等基本概念应用各种数值运算。:numref:`chap_linear` 和 :numref:`chap_perceptrons` 涵盖了最多的深度学习的基本概念和技术, 例如线性回归, 多层感知和正则化. +* 第一部分包括基础知识和预备知识。 +:numref:`chap_introduction` 提供深度学习的入门课程。然后在 :numref:`chap_preliminaries` 中,我们将快速向你介绍实践深度学习所需的前提条件,例如如何存储和处理数据,以及如何应用基于线性代数、微积分和概率基本概念的各种数值运算。 :numref:`chap_linear` 和 :numref:`chap_perceptrons` 涵盖了深度学习的最基本概念和技术,例如线性回归、多层感知机和正则化。 -* 接下来的五章重点介绍现代深度学习技巧。 -:numref:`chap_computation` 描述了深度学习计算的各种关键组成部分,并为我们随后实施更复杂的模型奠定了基础。接下来,在 :numref:`chap_cnn` 和 :numref:`chap_modern_cnn` 中,我们介绍了卷积神经网络(CNN),这些功能强大的工具构成了大多数现代计算机视觉系统的骨干。随后,在 :numref:`chap_rnn` 和 :numref:`chap_modern_rnn` 中,我们引入了循环神经网络 (RNN),这些模型利用数据中的时间或顺序结构,通常用于自然语言处理和时间序列预测。在 :numref:`chap_attention` 中,我们引入了一类新的模型,它们采用了一种称为注意机制的技术,并且它们最近开始在自然语言处理中取代 RNs。这些部分将帮助您了解大多数现代深度学习应用背后的基本工具。 +* 接下来的五章集中讨论现代深度学习技术。 +:numref:`chap_computation` 描述了深度学习计算的各种关键组件,并为我们随后实现更复杂的模型奠定了基础。接下来,在 :numref:`chap_cnn` 和 :numref:`chap_modern_cnn` 中,我们介绍了卷积神经网络(convolutional neural network,CNN),这是构成大多数现代计算机视觉系统骨干的强大工具。随后,在 :numref:`chap_rnn` 和 :numref:`chap_modern_rnn` 中,我们引入了循环神经网络(recurrent neural network,RNN),这是一种利用数据中的时间或序列结构的模型,通常用于自然语言处理和时间序列预测。在 :numref:`chap_attention` 中,我们介绍了一类新的模型,它采用了一种称为注意力机制的技术,最近它们已经开始在自然语言处理中取代循环神经网络。这一部分将帮助你快速了解大多数现代深度学习应用背后的基本工具。 -* 第三部分讨论可扩展性、效率和应用程序。 -首先,在 :numref:`chap_optimization` 中,我们讨论了用于训练深度学习模型的几种常见优化算法。下一章 :numref:`chap_performance` 探讨了影响深度学习代码计算性能的几个关键因素。在 :numref:`chap_cv` 中,我们展示了深度学习在计算机视觉中的主要应用。在 :numref:`chap_nlp_pretrain` 和 :numref:`chap_nlp_app` 中,我们演示了如何预先训练语言表示模型并将其应用于自然语言处理任务。 +* 第三部分讨论可伸缩性、效率和应用程序。 +首先,在 :numref:`chap_optimization` 中,我们讨论了用于训练深度学习模型的几种常用优化算法。下一章 :numref:`chap_performance` 将探讨影响深度学习代码计算性能的几个关键因素。在 :numref:`chap_cv` 中,我们展示了深度学习在计算机视觉中的主要应用。在 :numref:`chap_nlp_pretrain` 和 :numref:`chap_nlp_app` 中,我们展示了如何预训练语言表示模型并将其应用于自然语言处理任务。 ### 代码 :label:`sec_code` -本书的大多数部分都特征可执行代码,因为我们相信交互式学习体验在深度学习中的重要性。目前,某些直觉只能通过试验和误差来形成,以小方式调整代码并观察结果。理想情况下,优雅的数学理论可能会告诉我们如何调整我们的代码以达到预期的结果。不幸的是,目前,这种优雅的理论没有我们。尽管我们尽了最大努力,但仍然缺乏对各种技术的正式解释,因为这些模型的数学特征可能非常困难,也因为对这些主题进行认真的调查最近才发展到高潮。我们希望,随着深度学习理论的发展,这本书的未来版本将能够在目前版本无法提供见解。 +本书的大部分章节都以可执行代码为特色,因为我们相信交互式学习体验在深度学习中的重要性。目前,某些直觉只能通过试错、小幅调整代码并观察结果来发展。理想情况下,一个优雅的数学理论可能会精确地告诉我们如何调整代码以达到期望的结果。不幸的是,这种优雅的理论目前还没有出现。尽管我们尽了最大努力,但仍然缺乏对各种技术的正式解释,这既是因为描述这些模型的数学可能非常困难,也是因为对这些主题的认真研究最近才进入高潮。我们希望随着深度学习理论的发展,这本书的未来版本将能够在当前版本无法提供的地方提供见解。 -有时,为了避免不必要的重复,我们将经常导入和引用的函数、类等封装在本书 `d2l` 包中。对于要保存在软件包中的任何块,如函数、类或多个导入,我们将标记为 `# @save `。我们在 :numref:`sec_d2l` 中提供了这些函数和类的详细概述。`d2l` 软件包重量轻,只需要以下软件包和模块作为依赖项: +有时,为了避免不必要的重复,我们将本书中经常导入和引用的函数、类等封装在`d2l`包中。对于要保存到包中的任何代码块,比如一个函数、一个类或者多个导入,我们都会标记为`#@save`。我们在 :numref:`sec_d2l` 中提供了这些函数和类的详细描述。`d2l`软件包是轻量级的,仅需要以下软件包和模块作为依赖项: -```{.python .input n=1} +```{.python .input} #@tab all #@save import collections @@ -80,36 +78,34 @@ d2l = sys.modules[__name__] ``` :begin_tab:`mxnet` -本书中的大部分代码都基于 Apache MXNet。MXNet 是深度学习的开源框架,是 AWS(Amazon Web 服务)以及许多学院和公司的首选选择。本书中的所有代码都通过了最新 MXNet 版本的测试。然而,由于深度学习的快速发展,一些代码 -*在未来版本的 MXNet 中可能无法正常工作。 -但是,我们计划保持在线版本最新。如果您遇到任何此类问题,请咨询 :ref:`chap_installation` 以更新您的代码和运行时环境。 +本书中的大部分代码都是基于Apache MXNet的。MXNet是深度学习的开源框架,是亚马逊以及许多大学和公司的首选。本书中的所有代码都通过了最新MXNet版本的测试。但是,由于深度学习的快速发展,一些在印刷版中代码 +可能在MXNet的未来版本无法正常工作。 +但是,我们计划使在线版本保持最新。如果你遇到任何此类问题,请查看 :ref:`chap_installation` 以更新你的代码和运行时环境。 -以下是我们如何从 MXNet 导入模块。 +下面是我们如何从MXNet导入模块。 :end_tab: :begin_tab:`pytorch` -这本书中的大部分代码都基于 PyTorch。PyTorch 是深度学习的开源框架,在研究界非常流行。本书中的所有代码都通过了最新的 PyTorch 下的测试。然而,由于深度学习的快速发展,一些代码 -*在未来版本的 PyTorch 中可能无法正常工作。 -但是,我们计划保持在线版本最新。如果您遇到任何此类问题,请咨询 :ref:`chap_installation` 以更新您的代码和运行时环境。 +本书中的大部分代码都是基于PyTorch的。PyTorch是一个开源的深度学习框架,在研究界非常受欢迎。本书中的所有代码都在最新版本的PyTorch下通过了测试。但是,由于深度学习的快速发展,一些在印刷版中代码可能在PyTorch的未来版本无法正常工作。 +但是,我们计划使在线版本保持最新。如果你遇到任何此类问题,请查看 :ref:`chap_installation` 以更新你的代码和运行时环境。 -以下是我们如何从 PyTorch 导入模块。 +下面是我们如何从PyTorch导入模块。 :end_tab: :begin_tab:`tensorflow` -本书中的大部分代码都基于 TensorFlow。TensorFlow 是深度学习的开源框架,在研究界和工业界都非常受欢迎。本书中的所有代码都在最新的 TensorFlow 下通过了测试。然而,由于深度学习的快速发展,一些代码 -*在未来版本的 TensorFlow 中可能无法正常工作。 -但是,我们计划保持在线版本最新。如果您遇到任何此类问题,请咨询 :ref:`chap_installation` 以更新您的代码和运行时环境。 +本书中的大部分代码都是基于TensorFlow的。TensorFlow是一个开源的深度学习框架,在研究界和产业界都非常受欢迎。本书中的所有代码都在最新版本的TensorFlow下通过了测试。但是,由于深度学习的快速发展,一些在印刷版中代码可能在TensorFlow的未来版本无法正常工作。 +但是,我们计划使在线版本保持最新。如果你遇到任何此类问题,请查看 :ref:`chap_installation` 以更新你的代码和运行时环境。 -以下是我们如何从 TensorFlow 导入模块。 +下面是我们如何从TensorFlow导入模块。 :end_tab: -```{.python .input n=1} +```{.python .input} #@save from mxnet import autograd, context, gluon, image, init, np, npx from mxnet.gluon import nn, rnn ``` -```{.python .input n=1} +```{.python .input} #@tab pytorch #@save import numpy as np @@ -119,9 +115,10 @@ from torch import nn from torch.nn import functional as F from torch.utils import data from torchvision import transforms +from PIL import Image ``` -```{.python .input n=1} +```{.python .input} #@tab tensorflow #@save import numpy as np @@ -130,40 +127,67 @@ import tensorflow as tf ### 目标受众 -这本书适用于学生(本科或研究生)、工程师和研究人员,他们寻求深度学习的实用技巧的坚实掌握。因为我们从头开始解释每一个概念,所以不需要以前的深度学习或机器学习背景。充分解释深度学习的方法需要一些数学和编程,但我们只会假设你有一些基础知识,包括(非常基本的)线性代数,微积分,概率和 Python 编程。此外,在附录中,我们提供了关于本书所涵盖的大部分数学的进修。大多数情况下,我们将优先考虑直觉和想法,而不是数学的严谨性。有许多非常棒的书籍,可以导致感兴趣的读者进一步.实例,贝拉博洛巴斯 :cite:`Bollobas.1999` 的线性分析非常深入地涵盖了线性代数和函数分析。所有统计数据 :cite:`Wasserman.2013` 是一个非常棒的统计数据指南。如果你之前没有使用过 Python,你可能想要细看这个 [Python tutorial](http://learnpython.org/)。 +本书面向学生(本科生或研究生)、工程师和研究人员,他们希望扎实掌握深度学习的实用技术。因为我们从头开始解释每个概念,所以不需要过往的深度学习或机器学习背景。全面解释深度学习的方法需要一些数学和编程,但我们只假设你了解一些基础知识,包括线性代数、微积分、概率和非常基础的Python编程。此外,在附录中,我们提供了本书所涵盖的大多数数学知识的复习。大多数时候,我们会优先考虑直觉和想法,而不是数学的严谨性。有许多很棒的书可以引导感兴趣的读者走得更远。Bela Bollobas的《线性分析》 :cite:`Bollobas.1999` 对线性代数和函数分析进行了深入的研究。 :cite:`Wasserman.2013` 是一本很好的统计学指南。如果你以前没有使用过Python语言,那么你可能想要仔细阅读这个[Python教程](http://learnpython.org/)。 ### 论坛 -与本书相关,我们推出了一个讨论论坛,位于 [discuss.d2l.ai](https://discuss.d2l.ai/)。当您对书籍的任何部分有疑问时,您可以在每章结尾处找到关联的讨论页面链接。 - -## 表示感谢 - -我们感谢数百名英文和中文草稿的贡献者。他们帮助改进了内容,并提供了宝贵的反馈。具体而言,我们感谢这份英文草稿的每一位撰稿人,让每个人都更好。他们的 GitHub ID 或名称是 (在没有特定的顺序): alxnorden, avinashingit, bowen0701, rettkoonce, Chaitanya Prakash Bapat, 加维德菲奥科, edgaroman, gkutiel, 约翰米特罗, 梁浦, 拉胡尔阿加瓦尔, 穆罕默德阿里, 斯图, 斯图卢, 斯图卢, 斯图卢, 斯图卢, 斯图卢, 斯图卢, 斯图卢, 斯图卢 (迈克斯图卢) 迈克穆勒, 恩劳施迈尔, 普拉哈斯里瓦斯塔夫,斯费米吉尔, 盛扎, sundeepteki, topecongiro, tpdi, 粉丝, 维沙尔卡普尔, 维什韦什拉维斯利马里, Yayab, 陈玉洪, 叶夫根尼斯米尔诺夫, lgov, 西蒙科尔斯顿-奥利弗, 伊戈尔德兹列耶夫, 哈阮, 普穆恩斯, 安德烈, 森科 vfdev-5, dweet, 穆罕默德·马赫迪·拉希米, 阿卜谢克·古普塔, uwsd, DOMKM, 丽莎奥克利, 博文李, 阿鲁什阿胡贾, 普拉桑特佛达里, 布里安迪, Mani2106, MTN, lkevinzc, 考吉林, 拉克希亚, 菲耶特吕尔, 苏尔比维贾瓦尔格亚, 金穆亨, dennismalmgren, 阿杜尔森, 阿杜尔森, 安吉拉尔青茨, 佩德罗·拉罗伊, lgov, ati-ozgur, 吴俊, 马蒂亚斯·布鲁姆, 林源, Gegunow, 乔什·加德纳, 马克西米利安伯瑟, 拉基布伊斯兰, 莱昂纳德劳森, 阿比纳夫 Upadhyay, rongruosong, 史蒂夫·塞德迈耶, 鲁斯兰·巴拉托夫, 拉斐尔·施拉特, liusy182, 詹尼斯·帕帕斯, ati-ozgur, dchoi77, 亚当·格森, 福乐, 马克·阿特拉, 林 Jjangga0214, 瑞歇辰, 诺埃洛, 汉森德, 吉尔杜普斯, 德文森特 1337, 白 D3VIL, 彼得·库利茨, 约瑟平尼拉, ahmaurya, karolszk, heytitle, 彼得·戈茨, rigtorp, tiepvupsu, sfilip, mlxd, 卡莱-AB 特塞拉, 桑贾尔·阿迪洛夫, 马特奥费拉拉, hsneto, 卡塔尔齐纳·比西亚尔斯卡, 格雷戈里·布鲁斯劳斯, 格雷戈里·布鲁斯劳斯劳斯, 杜鲁斯卡, 杜, 鲍伊斯, 鲍伊斯坦雷尔, 格雷敦, 明达 0711, sl7423, 黄再东, 王一达, CYS4, 克莱姆, 让卡杜尔, 奥斯丁姆, 特波姆斯, cuongvng, 帕维尔科马罗夫, vzlamal, 无其他系统, J-阿伦-马尼, 扬乔, 埃尔达库尔蒂, 伟大的沙兹机器人, 博士, 格杜查尔姆, 克劳斯, 丹尼尔-米埃琴, 白鼠, 阿巴希纳, 乔纳坦哈兰德尔, 伊斯雷尔, 诺达尔奥克罗什维利, 乌古尔卡普, 康济阳, 史蒂文乔克斯,托马尔·卡夫坦,利韦沃普,内蒂斯特,伊潘迪亚,尼尚塔拉尼,海利格尔。 - -我们感谢亚马逊网络服务,尤其是斯瓦米·西瓦苏布拉马尼亚、拉朱·古拉巴尼、查理·贝尔和安德鲁·贾西在撰写这本书时给予的慷慨支持。如果没有可用的时间,资源,与同事的讨论,以及不断的鼓励,这本书就不会发生。 - -## 摘要 - -* 深度学习已经彻底改变了模式识别,引入了现在支持广泛技术的技术,包括计算机视觉、自然语言处理、自动语音识别。 -* 要成功应用深度学习,您必须了解如何解决问题、建模的数学、将模型与数据拟合的算法以及实现这一切的工程技术。 -* 这本书提供了一个全面的资源,包括散文、数字、数学和代码,所有这些都在一个地方。 -* 要回答与本书相关的问题,请访问我们的论坛 https://discuss.d2l.ai/。 -* 所有笔记本电脑都可以在 GitHub 上下载。 +与本书相关,我们已经启动了一个论坛,在[discuss.d2l.ai](https://discuss.d2l.ai/)。当你对本书的任何一节有疑问时,你可以在每一节的末尾找到相关的讨论页链接。 + +## 确认 + +我们感谢数以百计的英文和中文草稿的撰稿人。他们帮助改进了内容或提供了有价值的反馈。特别地,我们要感谢每一位英文稿的撰稿人,感谢他们为大家做得更好。他们的GitHub ID或名称是(没有特定顺序):alxnorden, avinashingit, bowen0701, brettkoonce, Chaitanya Prakash Bapat, +cryptonaut, Davide Fiocco, edgarroman, gkutiel, John Mitro, Liang Pu, +Rahul Agarwal, Mohamed Ali Jamaoui, Michael (Stu) Stewart, Mike Müller, +NRauschmayr, Prakhar Srivastav, sad-, sfermigier, Sheng Zha, sundeepteki, +topecongiro, tpdi, vermicelli, Vishaal Kapoor, Vishwesh Ravi Shrimali, YaYaB, Yuhong Chen, +Evgeniy Smirnov, lgov, Simon Corston-Oliver, Igor Dzreyev, Ha Nguyen, pmuens, +Andrei Lukovenko, senorcinco, vfdev-5, dsweet, Mohammad Mahdi Rahimi, Abhishek Gupta, +uwsd, DomKM, Lisa Oakley, Bowen Li, Aarush Ahuja, Prasanth Buddareddygari, brianhendee, +mani2106, mtn, lkevinzc, caojilin, Lakshya, Fiete Lüer, Surbhi Vijayvargeeya, +Muhyun Kim, dennismalmgren, adursun, Anirudh Dagar, liqingnz, Pedro Larroy, +lgov, ati-ozgur, Jun Wu, Matthias Blume, Lin Yuan, geogunow, Josh Gardner, +Maximilian Böther, Rakib Islam, Leonard Lausen, Abhinav Upadhyay, rongruosong, +Steve Sedlmeyer, Ruslan Baratov, Rafael Schlatter, liusy182, Giannis Pappas, +ati-ozgur, qbaza, dchoi77, Adam Gerson, Phuc Le, Mark Atwood, christabella, vn09, +Haibin Lin, jjangga0214, RichyChen, noelo, hansent, Giel Dops, dvincent1337, WhiteD3vil, +Peter Kulits, codypenta, joseppinilla, ahmaurya, karolszk, heytitle, Peter Goetz, rigtorp, +Tiep Vu, sfilip, mlxd, Kale-ab Tessera, Sanjar Adilov, MatteoFerrara, hsneto, +Katarzyna Biesialska, Gregory Bruss, Duy–Thanh Doan, paulaurel, graytowne, Duc Pham, +sl7423, Jaedong Hwang, Yida Wang, cys4, clhm, Jean Kaddour, austinmw, trebeljahr, tbaums, +Cuong V. Nguyen, pavelkomarov, vzlamal, NotAnotherSystem, J-Arun-Mani, jancio, eldarkurtic, +the-great-shazbot, doctorcolossus, gducharme, cclauss, Daniel-Mietchen, hoonose, biagiom, +abhinavsp0730, jonathanhrandall, ysraell, Nodar Okroshiashvili, UgurKap, Jiyang Kang, +StevenJokes, Tomer Kaftan, liweiwp, netyster, ypandya, NishantTharani, heiligerl, SportsTHU, +Hoa Nguyen, manuel-arno-korfmann-webentwicklung, aterzis-personal, nxby, Xiaoting He, Josiah Yoder, +mathresearch, mzz2017, jroberayalas, iluu, ghejc, BSharmi, vkramdev, simonwardjones, LakshKD, +TalNeoran, djliden, Nikhil95, Oren Barkan, guoweis, haozhu233, pratikhack, 315930399, tayfununal, +steinsag, charleybeller, Andrew Lumsdaine, Jiekui Zhang, Deepak Pathak, Florian Donhauser, Tim Gates, +Adriaan Tijsseling, Ron Medina, Gaurav Saha, Murat Semerci, [Lei Mao](https://github.com/leimao) + +我们感谢Amazon Web Services,特别是Swami Sivasubramanian、Raju Gulabani、Charlie Bell和Andrew Jassy对撰写本书的慷慨支持。如果没有可用的时间、资源、与同事的讨论和不断的鼓励,这本书就不会出版。 + +## 小结 + +* 深度学习已经彻底改变了模式识别,引入了一系列技术,包括计算机视觉、自然语言处理、自动语音识别。 +* 要成功地应用深度学习,你必须知道如何抛出一个问题、建模的数学方法、将模型与数据拟合的算法,以及实现所有这些的工程技术。 +* 这本书提供了一个全面的资源,包括文本、图表、数学和代码,都集中在一个地方。 +* 要回答与本书相关的问题,请访问我们的论坛https://discuss.d2l.ai/. +* 所有Jupyter记事本都可以在GitHub上下载。 ## 练习 -1. 在这本书的讨论论坛上注册一个帐户 [discuss.d2l.ai](https://discuss.d2l.ai/). -1. 在计算机上安装 Python。 -1. 点击论坛部分底部的链接,您将能够寻求帮助和讨论这本书,并通过吸引作者和更广泛的社区来找到问题的答案。 +1. 在本书[discuss.d2l.ai](https://discuss.d2l.ai/)的论坛上注册帐户。 +1. 在你的计算机上安装Python。 +1. 沿着本节底部的链接进入论坛,在那里你可以寻求帮助、讨论这本书,并通过与作者和社区接触来找到问题的答案。 :begin_tab:`mxnet` -[Discussions](https://discuss.d2l.ai/t/18) +[Discussions](https://discuss.d2l.ai/t/2085) :end_tab: :begin_tab:`pytorch` -[Discussions](https://discuss.d2l.ai/t/20) +[Discussions](https://discuss.d2l.ai/t/2086) :end_tab: :begin_tab:`tensorflow` -[Discussions](https://discuss.d2l.ai/t/186) +[Discussions](https://discuss.d2l.ai/t/2087) :end_tab: diff --git a/chapter_preliminaries/autograd.md b/chapter_preliminaries/autograd.md index c48849910..e7a2db515 100644 --- a/chapter_preliminaries/autograd.md +++ b/chapter_preliminaries/autograd.md @@ -3,7 +3,7 @@ 正如我们在 :numref:`sec_calculus` 中所说的那样,求导是几乎所有深度学习优化算法的关键步骤。虽然求导的计算很简单,只需要一些基本的微积分,但对于复杂的模型,手工进行更新是一件很痛苦的事情(而且经常容易出错)。 -深度学习框架通过自动计算导数(即 *自动求导*(automatic differentiation))来加快这项工作。实际中,根据我们设计的模型,系统会构建一个 *计算图*(computational graph),来跟踪数据通过若干操作组合起来产生输出。自动求导使系统能够随后反向传播梯度。 +深度学习框架通过自动计算导数,即 *自动求导* (automatic differentiation),来加快这项工作。实际中,根据我们设计的模型,系统会构建一个 *计算图* (computational graph),来跟踪数据通过若干操作组合起来产生输出。自动求导使系统能够随后反向传播梯度。 这里,*反向传播*(backpropagate)只是意味着跟踪整个计算图,填充关于每个参数的偏导数。 @@ -40,9 +40,9 @@ x ```{.python .input} -# 我们通过调用attach_grad`来为一个张量的梯度分配内存 +# 我们通过调用`attach_grad`来为一个张量的梯度分配内存 x.attach_grad() -# 在我们计算关于`x`的梯度后,我们将能够通过' grad '属性访问它,它的值被初始化为0 +# 在我们计算关于`x`的梯度后,我们将能够通过'grad'属性访问它,它的值被初始化为0 x.grad ``` diff --git a/chapter_preliminaries/calculus.md b/chapter_preliminaries/calculus.md index 5595da0fd..bd5a39fe1 100644 --- a/chapter_preliminaries/calculus.md +++ b/chapter_preliminaries/calculus.md @@ -1,15 +1,15 @@ # 微分 :label:`sec_calculus` -直到至少2500年前,古希腊人把一个多边形分成三角形,并把它们的面积相加,才找到计算多边形面积的方法。 -为了求出曲线形状(比如圆)的面积,古希腊人在这样的形状上刻内接多边形。如 :numref:`fig_circle_area` 所示,内接多边形的等长边越多,就越接近圆。这个过程也被称为*逼近法*(method of exhaustion)。 +在2500年前,古希腊人把一个多边形分成三角形,并把它们的面积相加,才找到计算多边形面积的方法。 +为了求出曲线形状(比如圆)的面积,古希腊人在这样的形状上刻内接多边形。如 :numref:`fig_circle_area` 所示,内接多边形的等长边越多,就越接近圆。这个过程也被称为 *逼近法*(method of exhaustion)。 -![用穷举法求圆的面积。](../img/polygon-circle.svg) +![用逼近法求圆的面积。](../img/polygon-circle.svg) :label:`fig_circle_area` -事实上,逼近法就是 *积分*(integral calculus)(将在 :numref:`sec_integral_calculus` 中描述)的起源。2000 多年后,微积分的另一支,*微分*(differential calculus),被发明出来。在微分学最重要的应用中,优化问题考虑如何把事情做到*最好*。正如在 :numref:`subsec_norms_and_objectives` 中讨论的那样,这种问题在深度学习中是无处不在的。 +事实上,逼近法就是 *积分*(integral calculus)的起源,我们将在 :numref:`sec_integral_calculus` 中详细描述。2000 多年后,微积分的另一支,*微分*(differential calculus),被发明出来。在微分学最重要的应用是优化问题,即考虑如何把事情做到最好。正如在 :numref:`subsec_norms_and_objectives` 中讨论的那样,这种问题在深度学习中是无处不在的。 -在深度学习中,我们*训练*模型,不断更新它们,使它们在看到越来越多的数据时变得越来越好。通常情况下,变得更好意味着最小化一个*损失函数*(loss function),即一个衡量“我们的模型有多*糟糕*”这个问题的分数。这个问题比看上去要微妙得多。最终,我们真正关心的是生成一个能够在我们从未见过的数据上表现良好的模型。但我们只能将模型与我们实际能看到的数据相拟合。因此,我们可以将拟合模型的任务分解为两个关键问题:i) *优化*:用模型拟合观测数据的过程;ii) *泛化*:数学原理和实践者的智慧,能够指导我们生成出有效性超出用于训练的数据集本身的模型。 +在深度学习中,我们“训练”模型,不断更新它们,使它们在看到越来越多的数据时变得越来越好。通常情况下,变得更好意味着最小化一个 *损失函数*(loss function),即一个衡量“我们的模型有多糟糕”这个问题的分数。这个问题比看上去要微妙得多。最终,我们真正关心的是生成一个能够在我们从未见过的数据上表现良好的模型。但我们只能将模型与我们实际能看到的数据相拟合。因此,我们可以将拟合模型的任务分解为两个关键问题:(1)*优化*(optimization):用模型拟合观测数据的过程;(2)*泛化*(generalization):数学原理和实践者的智慧,能够指导我们生成出有效性超出用于训练的数据集本身的模型。 为了帮助你在后面的章节中更好地理解优化问题和方法,这里我们对深度学习中常用的微分知识提供了一个非常简短的入门教程。 @@ -81,13 +81,15 @@ $$f'(x) = y' = \frac{dy}{dx} = \frac{df}{dx} = \frac{d}{dx} f(x) = Df(x) = D_x f 其中符号 $\frac{d}{dx}$ 和 $D$ 是*微分运算符*,表示*微分*操作。我们可以使用以下规则来对常见函数求微分: -* $DC = 0$ ($C$ 是一个常数); -* $Dx^n = nx^{n-1}$ (*幂律*(power rule), $n$是任意实数); -* $De^x = e^x$, -* $D\ln(x) = 1/x.$ +* $DC = 0$ ($C$ 是一个常数) +* $Dx^n = nx^{n-1}$ (*幂律*(power rule), $n$是任意实数) +* $De^x = e^x$ +* $D\ln(x) = 1/x$ 为了微分一个由一些简单函数(如上面的常见函数)组成的函数,下面的法则使用起来很方便。 -假设函数$f$和$g$都是可微的,$C$是一个常数,我们有*常数相乘法则* +假设函数$f$和$g$都是可微的,$C$是一个常数,我们有: + +*常数相乘法则* $$\frac{d}{dx} [Cf(x)] = C \frac{d}{dx} f(x),$$ *加法法则* @@ -104,11 +106,11 @@ $$\frac{d}{dx} \left[\frac{f(x)}{g(x)}\right] = \frac{g(x) \frac{d}{dx} [f(x)] - 现在我们可以应用上述几个法则来计算 $u' = f'(x) = 3 \frac{d}{dx} x^2-4\frac{d}{dx}x = 6x-4$。因此,通过令 $x = 1$ ,我们有 $u' = 2$ :这一点得到了我们在本节前面的实验的支持,在这个实验中,数值结果接近$2$。当 $x=1$ 时,此导数也是曲线 $u = f(x)$ 切线的斜率。 -[**为了对导数的这种解释进行可视化,**]我们将使用 `matplotlib`,一个Python中流行的绘图库。要配置`matplotlib`生成图形的属性,我们需要(**定义几个函数**)。 +[**为了对导数的这种解释进行可视化,**]我们将使用 `matplotlib`,这是一个Python中流行的绘图库。要配置`matplotlib`生成图形的属性,我们需要(**定义几个函数**)。 在下面,`use_svg_display` 函数指定 `matplotlib` 软件包输出svg图表以获得更清晰的图像。 注意,注释`#@save`是一个特殊的标记,会将对应的函数、类或语句保存在`d2l`包中 -因此,以后无需重新定义就可以直接调用它们(例如,`d2l.use\u svg\u display()`)。 +因此,以后无需重新定义就可以直接调用它们(例如,`d2l.use_svg_display()`)。 ```{.python .input} #@tab all @@ -117,7 +119,7 @@ def use_svg_display(): #@save display.set_matplotlib_formats('svg') ``` -我们定义 `set_figsize` 函数来指定图表大小。注意,这里我们直接使用 `d2l.plt`,因为导入语句 `from matplotlib import pyplot as plt` 已在`d2l` 软件包的开头被标记为保存。 +我们定义 `set_figsize` 函数来设置图表大小。注意,这里我们直接使用 `d2l.plt`,因为导入语句 `from matplotlib import pyplot as plt` 已在前言中标记为保存到`d2l` 包中。 ```{.python .input} #@tab all @@ -160,7 +162,7 @@ def plot(X, Y=None, xlabel=None, ylabel=None, legend=None, xlim=None, set_figsize(figsize) axes = axes if axes else d2l.plt.gca() - # Return True if `X` (tensor or list) has 1 axis + # 如果 `X` 有一个轴,输出True def has_one_axis(X): return (hasattr(X, "ndim") and X.ndim == 1 or isinstance(X, list) and not hasattr(X[0], "__len__")) @@ -192,13 +194,13 @@ plot(x, [f(x), 2 * x - 3], 'x', 'f(x)', legend=['f(x)', 'Tangent line (x=1)']) ## 偏导数 -到目前为止,我们只讨论了仅含一个变量的函数的微分。在深度学习中,函数通常依赖于*许多*变量。因此,我们需要将微分的思想推广到这些*多元*函数上。 +到目前为止,我们只讨论了仅含一个变量的函数的微分。在深度学习中,函数通常依赖于许多变量。因此,我们需要将微分的思想推广到这些 *多元函数* (multivariate function)上。 -设 $y = f(x_1, x_2, \ldots, x_n)$ 是一个具有 $n$ 个变量的函数。$y$ 相对于第$i^\mathrm{th}$ 个参数$x_i$*偏导数*(partial derivative)为: +设 $y = f(x_1, x_2, \ldots, x_n)$ 是一个具有 $n$ 个变量的函数。$y$ 关于第$i$ 个参数$x_i$的*偏导数*(partial derivative)为: $$ \frac{\partial y}{\partial x_i} = \lim_{h \rightarrow 0} \frac{f(x_1, \ldots, x_{i-1}, x_i+h, x_{i+1}, \ldots, x_n) - f(x_1, \ldots, x_i, \ldots, x_n)}{h}.$$ -为了计算 $\frac{\partial y}{\partial x_i}$,我们可以简单地将 $x_1, \ldots, x_{i-1}, x_{i+1}, \ldots, x_n$ 看作常数,并计算 $y$相对于$x_i$ 的导数。对于偏导数的表示,以下是等价的: +为了计算 $\frac{\partial y}{\partial x_i}$,我们可以简单地将 $x_1, \ldots, x_{i-1}, x_{i+1}, \ldots, x_n$ 看作常数,并计算 $y$关于$x_i$ 的导数。对于偏导数的表示,以下是等价的: $$\frac{\partial y}{\partial x_i} = \frac{\partial f}{\partial x_i} = f_{x_i} = f_i = D_i f = D_{x_i} f.$$ @@ -213,9 +215,9 @@ $$\nabla_{\mathbf{x}} f(\mathbf{x}) = \bigg[\frac{\partial f(\mathbf{x})}{\parti 假设$\mathbf{x}$为$n$维向量,在微分多元函数时经常使用以下规则: -* 对于所有$\mathbf{A} \in \mathbb{R}^{m \times n}$,都有 $\nabla_{\mathbf{x}} \mathbf{A} \mathbf{x} = \mathbf{A}^\top$, -* 对于所有$\mathbf{A} \in \mathbb{R}^{n \times m}$,都有 $\nabla_{\mathbf{x}} \mathbf{x}^\top \mathbf{A} = \mathbf{A}$, -* 对于所有$\mathbf{A} \in \mathbb{R}^{n \times n}$,都有 $\nabla_{\mathbf{x}} \mathbf{x}^\top \mathbf{A} \mathbf{x} = (\mathbf{A} + \mathbf{A}^\top)\mathbf{x}$, +* 对于所有$\mathbf{A} \in \mathbb{R}^{m \times n}$,都有 $\nabla_{\mathbf{x}} \mathbf{A} \mathbf{x} = \mathbf{A}^\top$ +* 对于所有$\mathbf{A} \in \mathbb{R}^{n \times m}$,都有 $\nabla_{\mathbf{x}} \mathbf{x}^\top \mathbf{A} = \mathbf{A}$ +* 对于所有$\mathbf{A} \in \mathbb{R}^{n \times n}$,都有 $\nabla_{\mathbf{x}} \mathbf{x}^\top \mathbf{A} \mathbf{x} = (\mathbf{A} + \mathbf{A}^\top)\mathbf{x}$ * $\nabla_{\mathbf{x}} \|\mathbf{x} \|^2 = \nabla_{\mathbf{x}} \mathbf{x}^\top \mathbf{x} = 2\mathbf{x}$ 同样,对于任何矩阵 $\mathbf{X}$,我们都有 $\nabla_{\mathbf{X}} \|\mathbf{X} \|_F^2 = 2\mathbf{X}$。正如我们之后将看到的,梯度对于设计深度学习中的优化算法有很大用处。 @@ -223,7 +225,7 @@ $$\nabla_{\mathbf{x}} f(\mathbf{x}) = \bigg[\frac{\partial f(\mathbf{x})}{\parti ## 链式法则 然而,上面方法可能很难找到梯度。 -这是因为在深度学习中,多元函数通常是*复合*的,所以我们可能没法应用上述任何规则来微分这些函数。 +这是因为在深度学习中,多元函数通常是 *复合*(composite)的,所以我们可能没法应用上述任何规则来微分这些函数。 幸运的是,链式法则使我们能够微分复合函数。 让我们先考虑单变量函数。假设函数 $y=f(u)$ 和 $u=g(x)$ 都是可微的,根据链式法则: diff --git a/chapter_preliminaries/index.md b/chapter_preliminaries/index.md index c43ea3546..7637b8613 100644 --- a/chapter_preliminaries/index.md +++ b/chapter_preliminaries/index.md @@ -1,15 +1,15 @@ # 预备知识 :label:`chap_preliminaries` -要开始深度学习课程的学习,我们需要掌握一些基本技能。所有的机器学习方法都涉及从数据中提取信息。因此,我们首先将学习存储、操作和预处理数据的实用技能。 +要开始深度学习课程的学习,我们需要掌握一些基本技能。所有的机器学习方法都涉及从数据中提取信息。因此,我们首先将学习一些实用技能,包括存储、操作和预处理数据。 机器学习通常需要处理大型数据集。我们可以将数据集视为表,其中表的行对应于样本,列对应于属性。线性代数为我们提供了一些用来处理表格数据的技术。我们不会太深入细节,而是将重点放在矩阵运算的基本原理及其实现上。 -深度学习是关于优化的。我们有一个带有参数的模型,我们想要找到那些能拟合数据最好的模型。在算法的每个步骤中,决定以何种方式移动每个参数需要一点微积分知识。在本节中将简要介绍这些知识。幸运的是,`autograd`包会自动为我们计算微分,在本节中我们也将介绍它。 +深度学习是关于优化的。我们有一个带有参数的模型,我们想要找到那些能拟合数据的最好模型。在算法的每个步骤中,决定以何种方式调整参数需要一点微积分知识。在本节中将简要介绍这些知识。幸运的是,`autograd`包会自动为我们计算微分,在本节中我们也将介绍它。 接下来,机器学习涉及如何做出预测:给定我们观察到的信息,某些未知属性的可能值是多少?要在不确定的情况下进行严格的推理,我们需要引用概率语言。 -最后,官方文档提供了本书之外的大量描述和示例。作为本章的结束,我们将向你展示如何在文档中查找所需信息。 +最后,官方文档提供了本书之外的大量描述和示例。在本章的结尾,我们将向你展示如何在文档中查找所需信息。 这本书将对数学的要求保持在正确理解深度学习所需的最低限度。然而,这并不意味着这本书是没有数学的。 因此,本章提供了基本且常用的数学知识的快速介绍,使任何人能够至少理解书中的大部分数学内容。如果你希望理解全部的数学内容,进一步学习[数学的在线附录](https://d2l.ai/chapter_appendix-mathematics-for-deep-learning/index.html)就足够了。 diff --git a/chapter_preliminaries/linear-algebra.md b/chapter_preliminaries/linear-algebra.md index e1b52719d..b36c953c4 100644 --- a/chapter_preliminaries/linear-algebra.md +++ b/chapter_preliminaries/linear-algebra.md @@ -6,9 +6,9 @@ ## 标量 -如果你从来没有学过线性代数或机器学习,那么你过去的数学经历可能是一次只想一个数字。而且,如果你曾经报销过发票,或者在餐厅支付餐费,那么你已经知道如何做一些基本的事情,如在数字间相加或相乘。例如,北京的温度为 $52$ 华氏度(除了摄氏度外,另一种温度刻度)。严格来说,我们称仅包含一个数值的叫 *标量* (scalar)。如果要将此华氏度值转换为更常用的摄氏度,则可以计算表达式 $c = \frac{5}{9}(f - 32)$,并将 $f$ 赋为 $52$。在此等式中,每一项($5$、$9$ 和 $32$)都是标量值。符号 $c$ 和 $f$ 称为 *变量*(variables),它们表示未知的标量值。 +如果你从来没有学过线性代数或机器学习,那么你过去的数学经历可能是一次只想一个数字。如果你曾经报销过发票,或者在餐厅支付餐费,那么你已经知道如何做一些基本的事情,比如在数字间相加或相乘。例如,北京的温度为 $52$ 华氏度(除了摄氏度外,另一种温度刻度)。严格来说,我们称仅包含一个数值的叫 *标量* (scalar)。如果要将此华氏度值转换为更常用的摄氏度,则可以计算表达式 $c = \frac{5}{9}(f - 32)$,并将 $f$ 赋为 $52$。在此等式中,每一项($5$、$9$ 和 $32$)都是标量值。符号 $c$ 和 $f$ 称为 *变量*(variables),它们表示未知的标量值。 -在本书中,我们采用了数学表示法,其中标量变量由普通小写字母表示(例如,$x$、$y$ 和 $z$)。我们用 $\mathbb{R}$ 表示所有(连续)*实数* 标量的空间。为了方便,我们之后将严格定义 *空间*(space)是什么,但现在只要记住,表达式 $x \in \mathbb{R}$ 是表示$x$是一个实值标量的严格形式。符号 $\in$ 称为 “属于”,它表示“是集合中的成员”。我们可以用 $x, y \in \{0, 1\}$ 来表明 $x$ 和 $y$ 是值只能为 $0$ 或 $1$的数字。 +在本书中,我们采用了数学表示法,其中标量变量由普通小写字母表示(例如,$x$、$y$ 和 $z$)。我们用 $\mathbb{R}$ 表示所有(连续)*实数* 标量的空间。为了方便,我们之后将严格定义 *空间*(space)是什么,但现在只要记住,表达式 $x \in \mathbb{R}$ 是表示$x$是一个实值标量的正式形式。符号 $\in$ 称为 “属于”,它表示“是集合中的成员”。我们可以用 $x, y \in \{0, 1\}$ 来表明 $x$ 和 $y$ 是值只能为 $0$ 或 $1$的数字。 (**标量由只有一个元素的张量表示**)。在下面的代码中,我们实例化两个标量,并使用它们执行一些熟悉的算术运算,即加法,乘法,除法和指数。 @@ -44,7 +44,7 @@ x + y, x * y, x / y, x**y ## 向量 -[**你可以将向量视为标量值列表**]。我们将这些值称为向量的 *元素*(elements)或*分量*(components)。当我们的向量表示数据集中的样本时,它们的值具有一定的现实意义。例如,如果我们正在训练一个模型来预测贷款违约风险,我们可能会将每个申请人与一个向量相关联,其分量与其收入、工作年限、过往违约次数和其他因素相对应。如果我们正在研究医院患者可能面临的心脏病发作风险,我们可能会用一个向量来表示每个患者,其分量为最近的生命体征、胆固醇水平、每天运动时间等。在数学表示法中,我们通常将向量表示为粗体、小写的符号(例如,$\mathbf{x}$、$\mathbf{y}$和$\mathbf{z})$)。 +[**你可以将向量视为标量值组成的列表**]。我们将这些标量值称为向量的 *元素*(elements)或*分量*(components)。当我们的向量表示数据集中的样本时,它们的值具有一定的现实意义。例如,如果我们正在训练一个模型来预测贷款违约风险,我们可能会将每个申请人与一个向量相关联,其分量与其收入、工作年限、过往违约次数和其他因素相对应。如果我们正在研究医院患者可能面临的心脏病发作风险,我们可能会用一个向量来表示每个患者,其分量为最近的生命体征、胆固醇水平、每天运动时间等。在数学表示法中,我们通常将向量记为粗体、小写的符号(例如,$\mathbf{x}$、$\mathbf{y}$和$\mathbf{z})$)。 我们通过一维张量处理向量。一般来说,张量可以具有任意长度,取决于机器的内存限制。 @@ -65,7 +65,7 @@ x = tf.range(4) x ``` -我们可以使用下标来引用向量的任一元素。例如,我们可以通过 $x_i$ 来引用第 $i$ 个元素。注意,元素 $x_i$ 是一个标量,所以我们在引用它时不会加粗。大量文献认为列向量是向量的默认方向,在本书中也是如此。在数学中,向量 $\mathbf{x}$ 可以写为 +我们可以使用下标来引用向量的任一元素。例如,我们可以通过 $x_i$ 来引用第 $i$ 个元素。注意,元素 $x_i$ 是一个标量,所以我们在引用它时不会加粗。大量文献认为列向量是向量的默认方向,在本书中也是如此。在数学中,向量 $\mathbf{x}$ 可以写为: $$\mathbf{x} =\begin{bmatrix}x_{1} \\x_{2} \\ \vdots \\x_{n}\end{bmatrix},$$ :eqlabel:`eq_vec_def` @@ -122,7 +122,7 @@ x.shape x.shape ``` -请注意,“维度”(dimension)这个词在不同上下文时往往会有不同的含义,这往往会使人感到困惑。为了清楚起见,我们在此明确一下。*向量*或*轴*的维度被用来表示*向量*或*轴*的长度,即向量或轴的元素数量。然而,张量的维度用来表示张量具有的轴数。在这个意义上,张量的某个轴的维数就是这个轴的长度。 +请注意,*维度*(dimension)这个词在不同上下文时往往会有不同的含义,这经常会使人感到困惑。为了清楚起见,我们在此明确一下。*向量*或*轴*的维度被用来表示*向量*或*轴*的长度,即向量或轴的元素数量。然而,张量的维度用来表示张量具有的轴数。在这个意义上,张量的某个轴的维数就是这个轴的长度。 ## 矩阵 @@ -219,7 +219,7 @@ B == B.T B == tf.transpose(B) ``` -矩阵是有用的数据结构:它们允许我们组织具有不同变化模式的数据。例如,我们矩阵中的行可能对应于不同的房屋(数据样本),而列可能对应于不同的属性。如果你曾经使用过电子表格软件或已阅读过 :numref:`sec_pandas`,这应该听起来很熟悉。因此,尽管单个向量的默认方向是列向量,但在表示表格数据集的矩阵中,将每个数据样本视为矩阵中的行向量更为常见。而且,我们将在后面的章节中讲到。这种约定将支持常见的深度学习实践。例如,沿着张量的最外轴,我们可以访问或遍历小批量的数据样本。如果不存在小批量,我们也可以只访问数据样本。 +矩阵是有用的数据结构:它们允许我们组织具有不同变化模式的数据。例如,我们矩阵中的行可能对应于不同的房屋(数据样本),而列可能对应于不同的属性。如果你曾经使用过电子表格软件或已阅读过 :numref:`sec_pandas`,这应该听起来很熟悉。因此,尽管单个向量的默认方向是列向量,但在表示表格数据集的矩阵中,将每个数据样本作为矩阵中的行向量更为常见。我们将在后面的章节中讲到这点。这种约定将支持常见的深度学习实践。例如,沿着张量的最外轴,我们可以访问或遍历小批量的数据样本。如果不存在小批量,我们也可以只访问数据样本。 ## 张量 @@ -246,18 +246,18 @@ X ## 张量算法的基本性质 -标量、向量、矩阵和任意数量轴的张量(本小节中的 “张量” 指代数对象)有一些很好的属性,通常会派上用场。例如,你可能已经从逐元素操作的定义中注意到,任何逐元素的一元运算都不会改变其操作数的形状。同样,[**给定具有相同形状的任何两个张量,任何逐元素二元运算的结果都将是相同形状的张量**]。例如,将两个相同形状的矩阵相加会在这两个矩阵上执行元素加法。 +标量、向量、矩阵和任意数量轴的张量(本小节中的 “张量” 指代数对象)有一些很好的属性,通常会派上用场。例如,你可能已经从按元素操作的定义中注意到,任何按元素的一元运算都不会改变其操作数的形状。同样,[**给定具有相同形状的任何两个张量,任何按元素二元运算的结果都将是相同形状的张量**]。例如,将两个相同形状的矩阵相加会在这两个矩阵上执行元素加法。 ```{.python .input} A = np.arange(20).reshape(5, 4) -B = A.copy() # 通过分配新内存,将a的一个副本分配给B +B = A.copy() # 通过分配新内存,将A的一个副本分配给B A, A + B ``` ```{.python .input} #@tab pytorch A = torch.arange(20, dtype=torch.float32).reshape(5, 4) -B = A.clone() # 通过分配新内存,将a的一个副本分配给B +B = A.clone() # 通过分配新内存,将A的一个副本分配给B A, A + B ``` @@ -268,7 +268,7 @@ B = A # 不能通过分配新内存将A克隆到B A, A + B ``` -具体而言,[**两个矩阵的逐元素乘法称为 *哈达玛积*(Hadamard product)(数学符号 $\odot$)**]。对于矩阵 $\mathbf{B} \in \mathbb{R}^{m \times n}$,其中第 $i$ 行和第 $j$ 列的元素是 $b_{ij}$。矩阵$\mathbf{A}$(在 :eqref:`eq_matrix_def` 中定义)和 $\mathbf{B}$的哈达玛积为: +具体而言,[**两个矩阵的按元素乘法称为 *哈达玛积*(Hadamard product)(数学符号 $\odot$)**]。对于矩阵 $\mathbf{B} \in \mathbb{R}^{m \times n}$,其中第 $i$ 行和第 $j$ 列的元素是 $b_{ij}$。矩阵$\mathbf{A}$(在 :eqref:`eq_matrix_def` 中定义)和 $\mathbf{B}$的哈达玛积为: $$ \mathbf{A} \odot \mathbf{B} = @@ -480,7 +480,7 @@ A / sum_A A / sum_A ``` -如果我们想沿[**某个轴计算 `A` 元素的累积总和**],比如 `axis=0`(逐行计算),我们可以调用 `cumsum` 函数。此函数不会沿任何轴汇总输入张量。 +如果我们想沿[**某个轴计算 `A` 元素的累积总和**],比如 `axis=0`(按行计算),我们可以调用 `cumsum` 函数。此函数不会沿任何轴汇总输入张量。 ```{.python .input} A.cumsum(axis=0) @@ -498,10 +498,10 @@ tf.cumsum(A, axis=0) ## 点积(Dot Product) -到目前为止,我们只执行了逐元素操作、求和及平均值。如果这就是我们所能做的,那么线性代数可能就不需要单独一节了。 -但是,最基本的操作之一是点积。给定两个向量 $\mathbf{x}, \mathbf{y} \in \mathbb{R}^d$,它们的 *点积*(dot product) $\mathbf{x}^\top \mathbf{y}$(或 $\langle \mathbf{x}, \mathbf{y} \rangle$)是相同位置的逐元素乘积的和:$\mathbf{x}^\top \mathbf{y} = \sum_{i=1}^{d} x_i y_i$。 +到目前为止,我们只执行了按元素操作、求和及平均值。如果这就是我们所能做的,那么线性代数可能就不需要单独一节了。 +但是,最基本的操作之一是点积。给定两个向量 $\mathbf{x}, \mathbf{y} \in \mathbb{R}^d$,它们的 *点积*(dot product) $\mathbf{x}^\top \mathbf{y}$(或 $\langle \mathbf{x}, \mathbf{y} \rangle$)是相同位置的按元素乘积的和:$\mathbf{x}^\top \mathbf{y} = \sum_{i=1}^{d} x_i y_i$。 -[~~点积是相同位置的逐元素乘积的和~~] +[~~点积是相同位置的按元素乘积的和~~] ```{.python .input} y = np.ones(4) @@ -520,7 +520,7 @@ y = tf.ones(4, dtype=tf.float32) x, y, tf.tensordot(x, y, axes=1) ``` -注意,(**我们可以通过执行逐元素乘法,然后进行求和来表示两个向量的点积**): +注意,(**我们可以通过执行按元素乘法,然后进行求和来表示两个向量的点积**): ```{.python .input} np.sum(x * y) @@ -536,7 +536,7 @@ torch.sum(x * y) tf.reduce_sum(x * y) ``` -点积在很多场合都很有用。例如,给定一组由向量$\mathbf{x} \in \mathbb{R}^d$ 表示的值,和一组由 $\mathbf{w} \in \mathbb{R}^d$ 表示的权重。$\mathbf{x}$ 中的值根据权重 $\mathbf{w}$ 的加权和可以表示为点积 $\mathbf{x}^\top \mathbf{w}$。当权重为非负数且和为1(即 $\left(\sum_{i=1}^{d} {w_i} = 1\right)$)时,点积表示 *加权平均*。将两个向量归一化得到单位长度后,点积表示它们夹角的余弦。我们将在本节的后面正式介绍*长度*(length)的概念。 +点积在很多场合都很有用。例如,给定一组由向量$\mathbf{x} \in \mathbb{R}^d$ 表示的值,和一组由 $\mathbf{w} \in \mathbb{R}^d$ 表示的权重。$\mathbf{x}$ 中的值根据权重 $\mathbf{w}$ 的加权和可以表示为点积 $\mathbf{x}^\top \mathbf{w}$。当权重为非负数且和为1(即 $\left(\sum_{i=1}^{d} {w_i} = 1\right)$)时,点积表示 *加权平均*(weighted average)。将两个向量归一化得到单位长度后,点积表示它们夹角的余弦。我们将在本节的后面正式介绍*长度*(length)的概念。 ## 矩阵-向量积 @@ -591,7 +591,7 @@ A.shape, x.shape, tf.linalg.matvec(A, x) 如果你已经掌握了点积和矩阵-向量积的知识,那么 **矩阵-矩阵乘法**(matrix-matrix multiplication) 应该很简单。 -假设我们有两个矩阵$\mathbf{A} \in \mathbb{R}^{n \times k}$和$\mathbf{B} \in \mathbb{R}^{k \times m}$: +假设我们有两个矩阵 $\mathbf{A} \in \mathbb{R}^{n \times k}$ 和 $\mathbf{B} \in \mathbb{R}^{k \times m}$: $$\mathbf{A}=\begin{bmatrix} a_{11} & a_{12} & \cdots & a_{1k} \\ @@ -711,7 +711,7 @@ tf.norm(u) (**$$\|\mathbf{x}\|_1 = \sum_{i=1}^n \left|x_i \right|.$$**) -与 $L_2$ 范数相比,$L_1$ 范数受异常值的影响较小。为了计算 $L_1$ 范数,我们将绝对值函数和逐元素求和组合起来。 +与 $L_2$ 范数相比,$L_1$ 范数受异常值的影响较小。为了计算 $L_1$ 范数,我们将绝对值函数和按元素求和组合起来。 ```{.python .input} np.abs(u).sum() @@ -774,7 +774,7 @@ tf.norm(tf.ones((4, 9))) * 向量泛化自标量,矩阵泛化自向量。 * 标量、向量、矩阵和张量分别具有零、一、二和任意数量的轴。 * 一个张量可以通过`sum` 和 `mean`沿指定的轴汇总。 -* 两个矩阵的逐元素乘法被称为他们的哈达玛积。它与矩阵乘法不同。 +* 两个矩阵的按元素乘法被称为他们的哈达玛积。它与矩阵乘法不同。 * 在深度学习中,我们经常使用范数,如 $L_1$范数、$L_2$范数和弗罗贝尼乌斯范数。 * 我们可以对标量、向量、矩阵和张量执行各种操作。 @@ -783,12 +783,12 @@ tf.norm(tf.ones((4, 9))) 1. 证明一个矩阵 $\mathbf{A}$ 的转置的转置是 $\mathbf{A}$:$(\mathbf{A}^\top)^\top = \mathbf{A}$。 1. 给出两个矩阵 $\mathbf{A}$ 和 $\mathbf{B}$, 显示转置的和等于和的转置:$\mathbf{A}^\top + \mathbf{B}^\top = (\mathbf{A} + \mathbf{B})^\top$. 1. 给定任意方矩阵$\mathbf{A}$, $\mathbf{A} + \mathbf{A}^\top$总是对称的吗?为什么? -1. 我们在本节中定义了形状(2,3,4)的张量 `X`。`len(X)`的输出结果是什么? +1. 我们在本节中定义了形状(2, 3, 4)的张量 `X`。`len(X)`的输出结果是什么? 1. 对于任意形状的张量`X`, `len(X)`是否总是对应于`X`特定轴的长度?这个轴是什么? 1. 运行 `A / A.sum(axis=1)`,看看会发生什么。你能分析原因吗? 1. 当你在曼哈顿的两点之间旅行时,你需要在坐标上走多远,也就是说,就大街和街道而言?你能斜着走吗? -1. 考虑一个具有形状(2,3,4)的张量,在轴0,1,2上的求和输出是什么形状? -1. 向 `linalg.norm` 函数提供 3 个或更多轴的张量,并观察其输出。对于任意形状的张量这个函数计算什么? +1. 考虑一个具有形状(2, 3, 4)的张量,在轴 0,1,2 上的求和输出是什么形状? +1. 向 `linalg.norm` 函数提供 3 个或更多轴的张量,并观察其输出。对于任意形状的张量这个函数计算得到什么? :begin_tab:`mxnet` [Discussions](https://discuss.d2l.ai/t/1752) diff --git a/chapter_preliminaries/lookup-api.md b/chapter_preliminaries/lookup-api.md index 63fab7efa..ebd043022 100644 --- a/chapter_preliminaries/lookup-api.md +++ b/chapter_preliminaries/lookup-api.md @@ -1,14 +1,14 @@ # 查阅文档 :begin_tab:`mxnet` -由于这本书篇幅的限制,我们不可能介绍每一个 MXNet 函数和类(你也可能不希望我们这样做)。API文档、其他教程和示例提供了本书之外的大量文档。在本节中,我们为你提供了一些查看MXNet API 的指导。 +由于这本书篇幅的限制,我们不可能介绍每一个 MXNet 函数和类(你可能也不希望我们这样做)。API文档、其他教程和示例提供了本书之外的大量文档。在本节中,我们为你提供了一些查看MXNet API 的指导。 :end_tab: :begin_tab:`pytorch` -由于本书篇幅的限制,我们不可能介绍每一个PyTorch函数和类(你也可能不希望我们这样做)。API文档、其他教程和示例提供了本书之外的大量文档。在本节中,我们为你提供了一些查看PyTorch API的指导。 +由于本书篇幅的限制,我们不可能介绍每一个PyTorch函数和类(你可能也不希望我们这样做)。API文档、其他教程和示例提供了本书之外的大量文档。在本节中,我们为你提供了一些查看PyTorch API的指导。 :end_tab: :begin_tab:`tensorflow` -由于本书篇幅的限制,我们不可能介绍每一个TensorFlow函数和类(你也可能不希望我们这样做)。API文档、其他教程和示例提供了本书之外的大量文档。在本节中,我们为你提供了一些查TensorFlow API的指导。 +由于本书篇幅的限制,我们不可能介绍每一个TensorFlow函数和类(你可能也不希望我们这样做)。API文档、其他教程和示例提供了本书之外的大量文档。在本节中,我们为你提供了一些查TensorFlow API的指导。 :end_tab: ## 查找模块中的所有函数和类 @@ -32,7 +32,7 @@ import tensorflow as tf print(dir(tf.random)) ``` -通常,我们可以忽略以 `__` 开始和结束的函数(Python 中的特殊对象)或以单个 `_` 开始的函数(通常是内部函数)。根据剩余的函数名或属性名,我们可能会猜测这个模块提供了各种生成随机数的方法,包括从均匀分布 (`uniform`)、正态分布 (`normal`) 和多项分布 (`multinomial`) 中采样。 +通常,我们可以忽略以 `__` 开始和结束的函数(Python 中的特殊对象)或以单个 `_` 开始的函数(通常是内部函数)。根据剩余的函数名或属性名,我们可能会猜测这个模块提供了各种生成随机数的方法,包括从均匀分布(`uniform`)、正态分布 (`normal`)和多项分布(`multinomial`)中采样。 ## 查找特定函数和类的用法 @@ -68,7 +68,7 @@ torch.ones(4) tf.ones(4) ``` -在Jupyter记事本中,我们可以使用 `?`在另一个窗口中显示文档。例如,`list?`将创建与`help(list)` 几乎相同的内容,并在新的浏览器窗口中显示它。此外,如果我们使用两个问号,如 `list??`,将显示实现该函数的 Python 代码。 +在Jupyter记事本中,我们可以使用 `?` 在另一个窗口中显示文档。例如,`list?`将创建与`help(list)` 几乎相同的内容,并在新的浏览器窗口中显示它。此外,如果我们使用两个问号,如 `list??`,将显示实现该函数的 Python 代码。 ## 小结 diff --git a/chapter_preliminaries/ndarray.md b/chapter_preliminaries/ndarray.md index 729960f99..1d5eea1a0 100644 --- a/chapter_preliminaries/ndarray.md +++ b/chapter_preliminaries/ndarray.md @@ -1,14 +1,14 @@ # 数据操作 :label:`sec_ndarray` -为了能够完成各种操作,我们需要某种方法来存储和操作数据。一般来说,我们需要进行两件重要的事情:(1)获取数据;(2)在数据进入计算机后对其进行处理。如果没有某种方法来存储数据,那么获取数据是没有意义的。我们先尝试一个合成数据。首先,我们介绍$n$维数组,也称为 *张量*(tensor)。 +为了能够完成各种操作,我们需要某种方法来存储和操作数据。一般来说,我们需要做两件重要的事情:(1)获取数据;(2)在数据读入计算机后对其进行处理。如果没有某种方法来存储数据,那么获取数据是没有意义的。我们先尝试一个合成数据。首先,我们介绍$n$维数组,也称为 *张量*(tensor)。 -如果你使用过 Python 中最广泛使用的科学计算包 NumPy,那么你会感觉很熟悉本部分。无论你使用哪个框架,它的 *张量类*(在 MXNet 中为 `ndarray`,在 PyTorch 和TensorFlow中为 `Tensor`)与 Numpy 的 `ndarray` 类似,但都比Numpy 的 `ndarray`多一些重要功能。首先,GPU 很好地支持加速计算,而 NumPy 仅支持 CPU 计算。其次,张量类支持自动微分。这些功能使得张量类更适合深度学习。除非另有说明,在整本书中所说的张量指的是张量类的实例。 +如果你使用过 Python 中最广泛使用的科学计算包 NumPy,那么你会感觉怼本部分很熟悉。无论你使用哪个框架,它的 *张量类*(在 MXNet 中为 `ndarray`,在 PyTorch 和TensorFlow中为 `Tensor`)与 Numpy 的 `ndarray` 类似,但都比Numpy 的 `ndarray`多一些重要功能。首先,GPU 很好地支持加速计算,而 NumPy 仅支持 CPU 计算。其次,张量类支持自动微分。这些功能使得张量类更适合深度学习。除非另有说明,在整本书中所说的张量指的是张量类的实例。 ## 入门 -在本节中,我们的目标是帮助你开始了解并运行一些基本数值计算工具。在你阅读本书的过程中,将利用到这些工具。如果你很难理解一些数学概念或库函数,请不要担心。下面的章节将通过一些实际的例子来回顾这些内容。如果你已经有了一些背景知识,想要深入学习数学内容,可以就跳过这一节。 +在本节中,我们的目标是帮助你开始了解并运行一些基本数值计算工具。在你阅读本书的过程中,将用到这些工具。如果你很难理解一些数学概念或库函数,请不要担心。在后面的章节将通过一些实际的例子来回顾这些内容。如果你已经有了一些背景知识,想要深入学习数学内容,可以就跳过这一节。 :begin_tab:`mxnet` 首先,我们从MXNet导入 `np`(`numpy`)模块和 `npx`(`numpy_extension`)模块。`np` 模块包含了 NumPy 支持的函数。而 `npx` 模块包含了一组扩展函数,用来在类似 NumPy 的环境中实现深度学习开发。当使用张量时,我们几乎总是会调用 `set_np` 函数:这是为了兼容 MXNet 其他的张量处理组件。 @@ -67,8 +67,8 @@ x x.shape ``` -如果我们只想知道张量中元素的总数,即所有形状元素的乘积,我们可以检查它的大小(size)。 -因为这里在处理的是一个向量,所以它的`shape`与它的大小相同。 +如果我们只想知道张量中元素的总数,即形状的所有元素乘积,我们可以检查它的大小(size)。 +因为这里在处理的是一个向量,所以它的 `shape` 与它的 `size` 相同。 ```{.python .input} x.size @@ -85,7 +85,7 @@ tf.size(x) ``` [**要改变一个张量的形状而不改变元素数量和元素值,我们可以调用 `reshape` 函数。**] -例如,我们可以把张量 `x` 从形状为 (12,) 的行向量转换为形状 (3, 4) 的矩阵。这个新的张量包含与转换前相同的值,但是把它们看成一个三行四列的矩阵。要重点说明一下,虽然形状发生了改变,但元素值没有变。注意,通过改变张量的形状,张量的大小不会改变。 +例如,我们可以把张量 `x` 从形状为 (12, ) 的行向量转换为形状 (3, 4) 的矩阵。这个新的张量包含与转换前相同的值,但是把它们看成一个三行四列的矩阵。要重点说明一下,虽然形状发生了改变,但元素值没有变。注意,通过改变张量的形状,张量的大小不会改变。 ```{.python .input} @@ -137,7 +137,7 @@ torch.ones((2, 3, 4)) tf.ones((2, 3, 4)) ``` -有时我们想从某个概率分布中随机采样来得到张量中每个元素的值。例如,当我们构造数组来作为神经网络中的参数时,我们通常会随机初始化参数的值。以下代码创建一个形状为(3, 4)的张量。其中的每个元素都从均值为0,标准差为1的标准高斯(正态)分布中随机采样。 +有时我们想从某个概率分布中随机采样来得到张量中每个元素的值。例如,当我们构造数组来作为神经网络中的参数时,我们通常会随机初始化参数的值。以下代码创建一个形状为 (3, 4) 的张量。其中的每个元素都从均值为0、标准差为1的标准高斯(正态)分布中随机采样。 ```{.python .input} @@ -171,13 +171,13 @@ torch.tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]]) tf.constant([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]]) ``` -## 操作 +## 运算 -这本书不是关于软件工程的。我们的兴趣不仅仅限于从数组读取和写入数据。我们想在这些数组上执行数学运算。一些最简单且最有用的操作是 *逐元素*(elementwise) 操作。它们将标准标量运算应用于数组的每个元素。对于将两个数组作为输入的函数,逐元素运算将二元运算符应用于两个数组中的每对位置对应的元素。我们可以基于任何从标量到标量的函数来创建逐元素函数。 +这本书不是关于软件工程的。我们的兴趣不仅仅限于从数组读取和写入数据。我们想在这些数组上执行数学运算。一些最简单且最有用的操作是 *按元素*(elementwise) 操作。它们将标准标量运算符应用于数组的每个元素。对于将两个数组作为输入的函数,按元素运算将二元运算符应用于两个数组中的每对位置对应的元素。我们可以基于任何从标量到标量的函数来创建按元素函数。 -在数学表示法中,我们将通过符号 $f: \mathbb{R} \rightarrow \mathbb{R}$ 来表示 *一元* 标量运算符(只接收一个输入)。这意味着该函数从任何实数($\mathbb{R}$)映射到另一个实数。同样,我们通过符号 $f: \mathbb{R}, \mathbb{R} \rightarrow \mathbb{R}$ 表示 *二元* 标量运算符,这意味着该函数接收两个输入,并产生一个输出。给定同一形状的任意两个向量$\mathbf{u}$和$\mathbf{v}$ 和二元运算符 $f$,我们可以得到向量$\mathbf{c} = F(\mathbf{u},\mathbf{v})$。具体计算方法是$c_i \gets f(u_i, v_i)$ ,其中 $c_i, u_i$ 和 $v_i$ 分别是向量$\mathbf{c}, \mathbf{u}$和 $\mathbf{v}$中的元素。在这里,我们通过将标量函数升级为逐元素向量运算来生成向量值 $F: \mathbb{R}^d, \mathbb{R}^d \rightarrow \mathbb{R}^d$。 +在数学表示法中,我们将通过符号 $f: \mathbb{R} \rightarrow \mathbb{R}$ 来表示 *一元* 标量运算符(只接收一个输入)。这意味着该函数从任何实数($\mathbb{R}$)映射到另一个实数。同样,我们通过符号 $f: \mathbb{R}, \mathbb{R} \rightarrow \mathbb{R}$ 表示 *二元* 标量运算符,这意味着该函数接收两个输入,并产生一个输出。给定同一形状的任意两个向量$\mathbf{u}$和$\mathbf{v}$ 和二元运算符 $f$,我们可以得到向量$\mathbf{c} = F(\mathbf{u},\mathbf{v})$。具体计算方法是$c_i \gets f(u_i, v_i)$ ,其中 $c_i$、u_i$ 和 $v_i$ 分别是向量$\mathbf{c}$、$\mathbf{u}$ 和 $\mathbf{v}$中的元素。在这里,我们通过将标量函数升级为按元素向量运算来生成向量值 $F: \mathbb{R}^d, \mathbb{R}^d \rightarrow \mathbb{R}^d$。 -对于任意具有相同形状的张量,[**常见的标准算术运算符(`+`、`-`、`*`、`/` 和 `**`)都可以被升级为逐元素运算**]。我们可以在同一形状的任意两个张量上调用逐元素操作。在下面的例子中,我们使用逗号来表示一个具有5个元素的元组,其中每个元素都是逐元素操作的结果。 +对于任意具有相同形状的张量,[**常见的标准算术运算符(`+`、`-`、`*`、`/` 和 `**`)都可以被升级为按元素运算**]。我们可以在同一形状的任意两个张量上调用按元素操作。在下面的例子中,我们使用逗号来表示一个具有5个元素的元组,其中每个元素都是按元素操作的结果。 @@ -201,7 +201,7 @@ y = tf.constant([2.0, 2, 2, 2]) x + y, x - y, x * y, x / y, x ** y # **运算符是求幂运算 ``` -可以(**按逐元素方式应用更多的计算**),包括像求幂这样的一元运算符。 +可以(**按按元素方式应用更多的计算**),包括像求幂这样的一元运算符。 ```{.python .input} np.exp(x) @@ -217,7 +217,7 @@ torch.exp(x) tf.exp(x) ``` -除了逐元素计算外,我们还可以执行线性代数运算,包括向量点积和矩阵乘法。我们将在 :numref:`sec_linear-algebra` 中解释线性代数的重点内容(不需要先修知识)。 +除了按元素计算外,我们还可以执行线性代数运算,包括向量点积和矩阵乘法。我们将在 :numref:`sec_linear-algebra` 中解释线性代数的重点内容(不需要先修知识)。 [**我们也可以把多个张量连结在一起**],把它们端对端地叠起来形成一个更大的张量。 我们也可以 *连结*(concatenate) 多个张量在一起,将它们端到端堆叠以形成更大的张量。我们只需要提供张量列表,并给出沿哪个轴连结。下面的例子分别演示了当我们沿行(轴-0,形状的第一个元素)和按列(轴-1,形状的第二个元素)连结两个矩阵时会发生什么情况。我们可以看到,第一个输出张量的轴-0长度 ($6$) 是两个输入张量轴-0长度的总和 ($3 + 3$);第二个输出张量的轴-1长度 ($8$) 是两个输入张量轴-1长度的总和 ($4 + 4$)。 @@ -265,9 +265,9 @@ tf.reduce_sum(X) ## 广播机制 :label:`subsec_broadcasting` -在上面的部分中,我们看到了如何在相同形状的两个张量上执行逐元素操作。在某些情况下,[**即使形状不同,我们仍然可以通过调用 *广播机制*(broadcasting mechanism) 来执行逐元素操作**]。这种机制的工作方式如下:首先,通过适当复制元素来扩展一个或两个数组,以便在转换之后,两个张量具有相同的形状。其次,对生成的数组执行逐元素操作。 +在上面的部分中,我们看到了如何在相同形状的两个张量上执行按元素操作。在某些情况下,[**即使形状不同,我们仍然可以通过调用 *广播机制* (broadcasting mechanism) 来执行按元素操作**]。这种机制的工作方式如下:首先,通过适当复制元素来扩展一个或两个数组,以便在转换之后,两个张量具有相同的形状。其次,对生成的数组执行按元素操作。 -在大多数情况下,我们将沿着数组中长度为1的轴进行广播,如下样本: +在大多数情况下,我们将沿着数组中长度为1的轴进行广播,如下例子: ```{.python .input} @@ -290,7 +290,7 @@ b = tf.reshape(tf.range(2), (1, 2)) a, b ``` -由于 `a` 和 `b` 分别是 $3\times1$ 和 $1\times2$ 矩阵,如果我们让它们相加,它们的形状不匹配。我们将两个矩阵*广播*为一个更大的 $3\times2$ 矩阵,如下所示:矩阵 `a`将复制列,矩阵 `b`将复制行,然后再逐元素相加。 +由于 `a` 和 `b` 分别是 $3\times1$ 和 $1\times2$ 矩阵,如果我们让它们相加,它们的形状不匹配。我们将两个矩阵*广播*为一个更大的 $3\times2$ 矩阵,如下所示:矩阵 `a`将复制列,矩阵 `b`将复制行,然后再按元素相加。 ```{.python .input} #@tab all @@ -301,7 +301,7 @@ a + b 就像在任何其他 Python 数组中一样,张量中的元素可以通过索引访问。与任何 Python 数组一样:第一个元素的索引是 0;可以指定范围以包含第一个元素和最后一个之前的元素。与标准 Python 列表一样,我们可以通过使用负索引根据元素到列表尾部的相对位置访问元素。 -因此,我[**可以用`[-1]` 选择最后一个元素,可以用`[1:3]` 选择第二个元素和第三个元素**],如下所示: +因此,我们[**可以用 `[-1]` 选择最后一个元素,可以用 `[1:3]` 选择第二个和第三个元素**],如下所示: ```{.python .input} #@tab all @@ -309,7 +309,7 @@ X[-1], X[1:3] ``` :begin_tab:`mxnet, pytorch` -[**除读取之外,我们还可以通过指定索引来将元素写入矩阵。**] +[**除读取外,我们还可以通过指定索引来将元素写入矩阵。**] :end_tab: :begin_tab:`tensorflow` @@ -332,7 +332,7 @@ X_var ``` 如果我们想[**为多个元素赋值相同的值,我们只需要索引所有元素,然后为它们赋值。**] -例如,`[0:2, :]` 访问第1行和第2行,其中 `:` 代表沿轴 1(列)的所有元素。虽然我们讨论的是矩阵的索引,但这也适用于向量和超过2个维度的张量。 +例如,`[0:2, :]` 访问第1行和第2行,其中 “:” 代表沿轴 1(列)的所有元素。虽然我们讨论的是矩阵的索引,但这也适用于向量和超过2个维度的张量。 ```{.python .input} #@tab mxnet, pytorch @@ -360,14 +360,14 @@ Y = Y + X id(Y) == before ``` -这可能是不可取的,原因有两个。首先,我们不想总是不必要地分配内存。在机器学习中,我们可能有数百兆的参数,并且在一秒内多次更新所有参数。通常情况下,我们希望原地执行这些更新。其次,我们可能通过多个变量指向相同参数。如果我们不原地更新,其他引用仍然会指向旧的内存位置,这样我们的某些代码可能会无意中引用旧的参数。 +这可能是不可取的,原因有两个:首先,我们不想总是不必要地分配内存。在机器学习中,我们可能有数百兆的参数,并且在一秒内多次更新所有参数。通常情况下,我们希望原地执行这些更新。其次,我们可能通过多个变量指向相同参数。如果我们不原地更新,其他引用仍然会指向旧的内存位置,这样我们的某些代码可能会无意中引用旧的参数。 :begin_tab:`mxnet, pytorch` -幸运的是,(**执行原地操作**)非常简单。我们可以使用切片表示法将操作的结果分配给先前分配的数组,例如 `Y[:] = `。为了说明这个概念,我们首先创建一个新的矩阵 `Z`,其形状与另一个 `Y` 相同,使用 `zeros_like` 来分配一个全$0$的块。 +幸运的是,(**执行原地操作**)非常简单。我们可以使用切片表示法将操作的结果分配给先前分配的数组,例如 `Y[:] = `。为了说明这一点,我们首先创建一个新的矩阵 `Z`,其形状与另一个 `Y` 相同,使用 `zeros_like` 来分配一个全$0$的块。 :end_tab: :begin_tab:`tensorflow` -`Variables` 是TensorFlow中的可变容器。它们提供了一种存储模型参数的方法。我们可以通过`assign`将一个操作的结果分配给一个 `Variable`。为了说明这个概念,我们创建了一个与另一个张量 `Y` 相同的形状的 `Z`,使用 `zeros_like` 来分配一个全$0$的块。 +`Variables` 是TensorFlow中的可变容器。它们提供了一种存储模型参数的方法。我们可以通过`assign`将一个操作的结果分配给一个 `Variable`。为了说明这一点,我们创建了一个与另一个张量 `Y` 相同的形状的 `Z`,使用 `zeros_like` 来分配一个全$0$的块。 :end_tab: ```{.python .input} @@ -400,7 +400,7 @@ print('id(Z):', id(Z)) :begin_tab:`tensorflow` 即使你将状态持久存储在 `Variable` 中,你也可能希望避免为不是模型参数的张量过度分配内存,从而进一步减少内存使用量。 -由于 TensorFlow `Tensors` 是不可变的,而且梯度不会通过 `Variable` 流动,因此 TensorFlow 没有提供一种明确的方式来原地运行单个操作。 +由于 TensorFlow的 `Tensors` 是不可变的,而且梯度不会通过 `Variable` 流动,因此 TensorFlow 没有提供一种明确的方式来原地运行单个操作。 但是,TensorFlow提供了`tf.function`修饰符,将计算封装在TensorFlow图中,该图在运行前经过编译和优化。这允许TensorFlow删除未使用的值,并复用先前分配的且不再需要的值。这样可以最大限度地减少 TensorFlow 计算的内存开销。 :end_tab: @@ -428,7 +428,7 @@ computation(X, Y) ## 转换为其他 Python 对象 [**转换为 NumPy 张量**]很容易,反之也很容易。转换后的结果不共享内存。 -这个小的不便实际上是非常重要的:当等待Python的NumPy包希望使用相同的内存块执行其他操作时,且在 CPU 或 GPU 上执行操作时,你不希望停止计算。 +这个小的不便实际上是非常重要的:当你在 CPU 或 GPU 上执行操作的时候,此时Python的NumPy包也希望使用相同的内存块执行其他操作时,你不希望停止计算。 ```{.python .input} @@ -471,12 +471,12 @@ a, a.item(), float(a), int(a) ## 小结 -* 深度学习存储和操作数据的主要接口是张量($n$维数组)。它提供了各种功能,包括基本数学运算、广播、索引、切片、内存节省和转换为其他 Python 对象。 +* 深度学习存储和操作数据的主要接口是张量($n$维数组)。它提供了各种功能,包括基本数学运算、广播、索引、切片、内存节省和转换其他 Python 对象。 ## 练习 1. 运行本节中的代码。将本节中的条件语句 `X == Y` 更改为 `X < Y` 或 `X > Y`,然后看看你可以得到什么样的张量。 -1. 用其他形状(例如三维张量)替换广播机制中逐元素操作的两个张量。结果是否与预期相同? +1. 用其他形状(例如三维张量)替换广播机制中按元素操作的两个张量。结果是否与预期相同? :begin_tab:`mxnet` [Discussions](https://discuss.d2l.ai/t/1745) diff --git a/chapter_preliminaries/pandas.md b/chapter_preliminaries/pandas.md index 982783dea..5369a47e7 100644 --- a/chapter_preliminaries/pandas.md +++ b/chapter_preliminaries/pandas.md @@ -5,7 +5,7 @@ ## 读取数据集 -举一个例子,我们首先(**创建一个人工数据集,并存储在csv(逗号分隔值)文件**) `../data/house_tiny.csv` 中。以其他格式存储的数据也可以通过类似的方式进行处理。下面的`mkdir_if_not_exist` 函数可确保目录 `../data` 存在。注意,注释 `#@save`是一个特殊的标记,该标记下面的函数、类或语句将保存在 `d2l` 软件包中,以便以后可以直接调用它们(例如 `d2l.mkdir_if_not_exist(path)`)而无需重新定义。 +举一个例子,我们首先(**创建一个人工数据集,并存储在csv(逗号分隔值)文件**) `../data/house_tiny.csv` 中。以其他格式存储的数据也可以通过类似的方式进行处理。下面的`mkdir_if_not_exist` 函数可确保目录 `../data` 存在。注意,注释 `#@save`是一个特殊的标记,该标记下方的函数、类或语句将保存在 `d2l` 软件包中,以便以后可以直接调用它们(例如 `d2l.mkdir_if_not_exist(path)`)而无需重新定义。 下面我们将数据集按行写入 csv 文件中。 diff --git a/chapter_preliminaries/probability.md b/chapter_preliminaries/probability.md index 0692152a5..a5857c547 100644 --- a/chapter_preliminaries/probability.md +++ b/chapter_preliminaries/probability.md @@ -3,8 +3,8 @@ 在某种形式上,机器学习就是做出预测。 -根据病人的临床病史,我们可能想预测他们在下一年心脏病发作的*概率*。在异常检测中,我们可能想要评估飞机喷气发动机的一组读数是正常运行情况的*可能性*有多大。在强化学习中,我们希望智能体(agent)能在一个环境中智能地行动。这意味着我们需要考虑在每种可行的行为下获得高奖励的概率。当我们建立推荐系统时,我们也需要考虑概率。例如,*假设*我们为一家大型在线书店工作。我们可能希望估计特定用户购买特定图书的概率。为此,我们需要使用概率的语言。 -有完整的课程,专业,论文,职业,甚至院系,都致力于概率的工作。所以很自然地,我们在这部分的目标不是教授整个科目。相反,我们希望让你起步,教给你足够的知识,使你能够开始构建你的第一个深度学习模型,并让你对该主题有足够的了解,以便你可以开始自己探索它。 +根据病人的临床病史,我们可能想预测他们在下一年心脏病发作的*概率*。在异常检测中,我们可能想要评估飞机喷气发动机的一组读数是正常运行情况的*可能性*有多大。在强化学习中,我们希望智能体(agent)能在一个环境中智能地行动。这意味着我们需要考虑在每种可行的行为下获得高奖励的概率。当我们建立推荐系统时,我们也需要考虑概率。例如,假设我们为一家大型在线书店工作。我们可能希望估计特定用户购买特定图书的概率。为此,我们需要使用概率学。 +有完整的课程、专业、论文、职业、甚至院系,都致力于概率学的工作。所以很自然地,我们在这部分的目标不是教授整个科目。相反,我们希望让你起步,教给你足够的知识,使你能够开始构建你的第一个深度学习模型,并让你对该主题有足够的了解,以便你可以开始自己探索它。 在前面的章节中,我们已经提到了概率,但没有明确说明它们是什么,也没有给出具体的例子。现在让我们更认真地考虑第一个例子:根据照片区分猫和狗。这听起来可能很简单,但实际上是一个艰巨的挑战。首先,问题的难度可能取决于图像的分辨率。 @@ -14,18 +14,18 @@ 如 :numref:`fig_cat_dog` 所示,虽然人类很容易以 $160 \times 160$ 像素的分辨率识别猫和狗,但它在 $40 \times 40$ 像素上变得具有挑战性,而且在 $10 \times 10$ 像素下几乎是不可能的。换句话说,我们在很远的距离(从而降低分辨率)区分猫和狗的能力可能会接近不知情的猜测。 概率给了我们一种正式的途径来说明我们的确定性水平。 -如果我们完全肯定图像是一只猫,我们说标签$y$是"猫"的*概率*,表示为$P(y=$ "猫"$)$ 等于 $1$。如果我们没有证据表明 $y =$ “猫” 或 $y =$ “狗”,那么我们可以说这两种可能性是等可能的,把它表示为$P(y=$ "猫"$) = P(y=$ "狗"$) = 0.5$ +如果我们完全肯定图像是一只猫,我们说标签$y$是"猫"的*概率*,表示为$P(y=$ "猫"$)$ 等于 $1$。如果我们没有证据表明 $y =$ “猫” 或 $y =$ “狗”,那么我们可以说这两种可能性是等可能的,把它表示为$P(y=$ "猫"$) = P(y=$ "狗"$) = 0.5$。 如果我们有足够的信心,但不确定图像描绘的是一只猫,我们可以将概率赋值为$0.5 < P(y=$ "猫"$) < 1$。 -现在考虑第二个例子:给出一些天气监测数据,我们想预测明天北京下雨的概率。如果是夏季,如果是夏天,下雨的概率是0.5。 +现在考虑第二个例子:给出一些天气监测数据,我们想预测明天北京下雨的概率。如果是夏天,下雨的概率是0.5。 -在这两种情况下,我们有一定的兴趣价值。在这两种情况下,我们都不确定结果。但这两种情况之间有一个关键区别。在这第一种情况下,图像实际上是狗或猫,我们只是不知道哪个。在第二种情况下,结果实际上可能是一个随机的事件(如果你相信这些东西。大多数物理学家都相信)。因此,概率是一种灵活的语言,用于说明我们的确定程度,并且它可以有效地应用于广泛的上下文中。 +在这两种情况下,我们都不确定结果。但这两种情况之间有一个关键区别。在第一种情况中,图像实际上是狗或猫,我们只是不知道哪个。在第二种情况下,结果实际上可能是一个随机的事件(如果你相信这些东西。大多数物理学家都相信)。因此,概率是一种灵活的语言,用于说明我们的确定程度,并且它可以有效地应用于广泛的上下文中。 ## 基本概率论 -假设我们掷骰子,想知道看到1的几率有多大,而不是看到另一个数字。如果骰子是公平的,那么所有六个结果$\{1, \ldots, 6\}$都有相同的可能发生,因此我们将在每六次中看到一个$1$。我们正式声明$1$发生的概率为$\frac{1}{6}$。 +假设我们掷骰子,想知道看到1的几率有多大,而不是看到另一个数字。如果骰子是公平的,那么所有六个结果$\{1, \ldots, 6\}$都有相同的可能发生,因此我们将在每六次中看到一个$1$。我们可以说$1$发生的概率为$\frac{1}{6}$。 -对于我们从工厂收到的真实骰子,我们可能不知道那些比例,我们需要检查它是否有污染。调查骰子的唯一方法是多次投掷并记录结果。对于每个骰子,我们将观察到 $\{1, \ldots, 6\}$ 中的一个值。给定这些结果,我们想调查观察每个结果的概率。 +对于我们从工厂收到的真实骰子,我们可能不知道那些比例,我们需要检查它是否有污染。调查骰子的唯一方法是多次投掷并记录结果。对于每个骰子,我们将观察到 $\{1, \ldots, 6\}$ 中的一个值。给定这些结果,我们想调查每个结果的概率。 对于每个值,一种自然的方法是将单个计数的值除以投掷的总次数。 这给了我们一个给定*事件*的概率的*估计值*。*大数定律*(law of large numbers)告诉我们,随着投掷次数的增加,这个估计值会越来越接近真实的潜在概率。在深入了解这里的细节之前,让我们先试一试。 @@ -305,7 +305,7 @@ $$ ## 期望和差异 -为了概括概率分布的关键特征,我们需要一些测量方法。随机变量 $X$ 的 * 期望 *(或平均值)表示为 +为了概括概率分布的关键特征,我们需要一些测量方法。随机变量 $X$ 的 *期望*(或平均值)表示为 $$E[X] = \sum_{x} x P(X = x).$$ @@ -313,7 +313,7 @@ $$E[X] = \sum_{x} x P(X = x).$$ $$E_{x \sim P}[f(x)] = \sum_x f(x) P(x).$$ -在许多情况下,我们希望衡量随机变量 $X$ 与其期望值的偏差。这可以通过方差来量化 +在许多情况下,我们希望衡量随机变量 $X$ 与其期望值的偏置。这可以通过方差来量化 $$\mathrm{Var}[X] = E\left[(X - E[X])^2\right] = E[X^2] - E[X]^2.$$ diff --git a/chapter_recurrent-modern/bi-rnn.md b/chapter_recurrent-modern/bi-rnn.md index 17092cba3..e6b65ca27 100644 --- a/chapter_recurrent-modern/bi-rnn.md +++ b/chapter_recurrent-modern/bi-rnn.md @@ -72,7 +72,7 @@ $$P(x_j \mid x_{-j}) \propto \sum_{h_j} \pi_j(h_j) \rho_j(h_j) P(x_j \mid h_j).$ ## 双向模型 如果我们希望在 RNN 中有一种能够提供与隐藏马尔科夫模型相似的预测能力的机制,我们需要修改迄今为止看到的 RNN 设计。幸运的是,这在概念上很容易。我们不是仅在前进模式下从第一个令牌开始运行 RNN,而是从后一个令牌从后到前运行的最后一个令牌启动另一个令牌。 -*双向 rnNS* 添加一个隐藏层,向后传递信息,以便更灵活地处理此类信息。:numref:`fig_birnn` 说明了带有单个隐藏层的双向 RNN 的体系结构。 +*双向 rnNS* 添加一个隐藏层,向后传递信息,以便更灵活地处理此类信息。 :numref:`fig_birnn` 说明了带有单个隐藏层的双向 RNN 的体系结构。 ![Architecture of a bidirectional RNN.](../img/birnn.svg) :label:`fig_birnn` @@ -92,7 +92,7 @@ $$ \end{aligned} $$ -其中权重 $\mathbf{W}_{xh}^{(f)} \in \mathbb{R}^{d \times h}, \mathbf{W}_{hh}^{(f)} \in \mathbb{R}^{h \times h}, \mathbf{W}_{xh}^{(b)} \in \mathbb{R}^{d \times h}, \text{ and } \mathbf{W}_{hh}^{(b)} \in \mathbb{R}^{h \times h}$ 和偏差 $\mathbf{b}_h^{(f)} \in \mathbb{R}^{1 \times h} \text{ and } \mathbf{b}_h^{(b)} \in \mathbb{R}^{1 \times h}$ 都是模型参数。 +其中权重 $\mathbf{W}_{xh}^{(f)} \in \mathbb{R}^{d \times h}, \mathbf{W}_{hh}^{(f)} \in \mathbb{R}^{h \times h}, \mathbf{W}_{xh}^{(b)} \in \mathbb{R}^{d \times h}, \text{ and } \mathbf{W}_{hh}^{(b)} \in \mathbb{R}^{h \times h}$ 和偏置 $\mathbf{b}_h^{(f)} \in \mathbb{R}^{1 \times h} \text{ and } \mathbf{b}_h^{(b)} \in \mathbb{R}^{1 \times h}$ 都是模型参数。 接下来,我们连接向前和向后隐藏状态 $\overrightarrow{\mathbf{H}}_t$ 和 $\overleftarrow{\mathbf{H}}_t$ 以获得隐藏状态 $\mathbf{H}_t \in \mathbb{R}^{n \times 2h}$ 进入输出层。在具有多个隐藏层的深双向 RNN 中,此类信息将作为 * 输入 * 传递到下一个双向层。最后,输出层计算输出 $\mathbf{O}_t \in \mathbb{R}^{n \times q}$(输出数:$q$): diff --git a/chapter_recurrent-modern/deep-rnn.md b/chapter_recurrent-modern/deep-rnn.md index 96e28e611..f20f97fc3 100644 --- a/chapter_recurrent-modern/deep-rnn.md +++ b/chapter_recurrent-modern/deep-rnn.md @@ -20,7 +20,7 @@ $$\mathbf{H}_t^{(l)} = \phi_l(\mathbf{H}_t^{(l-1)} \mathbf{W}_{xh}^{(l)} + \mathbf{H}_{t-1}^{(l)} \mathbf{W}_{hh}^{(l)} + \mathbf{b}_h^{(l)}),$$ :eqlabel:`eq_deep_rnn_H` -其中权重 $\mathbf{W}_{xh}^{(l)} \in \mathbb{R}^{h \times h}$ 和 $\mathbf{W}_{hh}^{(l)} \in \mathbb{R}^{h \times h}$ 以及偏差 $\mathbf{b}_h^{(l)} \in \mathbb{R}^{1 \times h}$ 是 $l^\mathrm{th}$ 隐藏层的模型参数。 +其中权重 $\mathbf{W}_{xh}^{(l)} \in \mathbb{R}^{h \times h}$ 和 $\mathbf{W}_{hh}^{(l)} \in \mathbb{R}^{h \times h}$ 以及偏置 $\mathbf{b}_h^{(l)} \in \mathbb{R}^{1 \times h}$ 是 $l^\mathrm{th}$ 隐藏层的模型参数。 最后,输出图层的计算仅基于最终 $L^\mathrm{th}$ 隐藏层的隐藏状态: diff --git a/chapter_recurrent-modern/gru.md b/chapter_recurrent-modern/gru.md index 12cf8f4dc..6f750fd69 100644 --- a/chapter_recurrent-modern/gru.md +++ b/chapter_recurrent-modern/gru.md @@ -42,7 +42,7 @@ $\tilde{\mathbf{H}}_t \in \mathbb{R}^{n \times h}$ 在时间步骤 $t$: $$\tilde{\mathbf{H}}_t = \tanh(\mathbf{X}_t \mathbf{W}_{xh} + \left(\mathbf{R}_t \odot \mathbf{H}_{t-1}\right) \mathbf{W}_{hh} + \mathbf{b}_h),$$ :eqlabel:`gru_tilde_H` -其中 $\mathbf{W}_{xh} \in \mathbb{R}^{d \times h}$ 和 $\mathbf{W}_{hh} \in \mathbb{R}^{h \times h}$ 是重量参数,$\mathbf{b}_h \in \mathbb{R}^{1 \times h}$ 是偏差,符号 $\odot$ 是哈达马德(元素)产品运营商。在这里,我们使用 tanh 形式的非线性来确保候选隐藏状态中的值保持在区间 $(-1, 1)$。 +其中 $\mathbf{W}_{xh} \in \mathbb{R}^{d \times h}$ 和 $\mathbf{W}_{hh} \in \mathbb{R}^{h \times h}$ 是重量参数,$\mathbf{b}_h \in \mathbb{R}^{1 \times h}$ 是偏置,符号 $\odot$ 是哈达马德(元素)产品运营商。在这里,我们使用 tanh 形式的非线性来确保候选隐藏状态中的值保持在区间 $(-1, 1)$。 结果是 * 候选人 *,因为我们仍然需要纳入更新门的操作。与 :eqref:`rnn_h_with_state` 相比,现在可以通过 $\mathbf{R}_t$ 和 $\mathbf{H}_{t-1}$ 的元素乘法来降低以前各州的影响力。每当重置门 $\mathbf{R}_t$ 中的条目接近 1 时,我们就会恢复一个香草 RNN,例如 :eqref:`rnn_h_with_state`。对于重置门 $\mathbf{R}_t$ 中接近 0 的所有条目,候选隐藏状态是以 $\mathbf{X}_t$ 作为输入的 MLP 的结果。因此,任何预先存在的隐藏状态都是 * 重置 * 为默认值。 @@ -95,7 +95,7 @@ train_iter, vocab = d2l.load_data_time_machine(batch_size, num_steps) ### 初始化模型参数 -下一步是初始化模型参数。我们从标准差的高斯分布中绘制权重为 0.01,然后将偏差设置为 0。超参数 `num_hiddens` 定义了隐藏单位的数量。我们实例化与更新门、重置门、候选隐藏状态和输出层相关的所有权重和偏差。 +下一步是初始化模型参数。我们从标准差的高斯分布中绘制权重为 0.01,然后将偏置设置为 0。超参数 `num_hiddens` 定义了隐藏单位的数量。我们实例化与更新门、重置门、候选隐藏状态和输出层相关的所有权重和偏置。 ```{.python .input} def get_params(vocab_size, num_hiddens, device): diff --git a/chapter_recurrent-modern/lstm.md b/chapter_recurrent-modern/lstm.md index 6a1798336..d31f61571 100644 --- a/chapter_recurrent-modern/lstm.md +++ b/chapter_recurrent-modern/lstm.md @@ -94,7 +94,7 @@ train_iter, vocab = d2l.load_data_time_machine(batch_size, num_steps) ### 初始化模型参数 -接下来我们需要定义和初始化模型参数。与之前一样,超参数 `num_hiddens` 定义了隐藏单位的数量。我们在使用 0.01 标准差的高斯分布之后初始化权重,然后我们将偏差设置为 0。 +接下来我们需要定义和初始化模型参数。与之前一样,超参数 `num_hiddens` 定义了隐藏单位的数量。我们在使用 0.01 标准差的高斯分布之后初始化权重,然后我们将偏置设置为 0。 ```{.python .input} def get_lstm_params(vocab_size, num_hiddens, device): diff --git a/chapter_recurrent-neural-networks/bptt.md b/chapter_recurrent-neural-networks/bptt.md index e98b4b32c..c3809de19 100644 --- a/chapter_recurrent-neural-networks/bptt.md +++ b/chapter_recurrent-neural-networks/bptt.md @@ -25,7 +25,7 @@ $$L(x_1, \ldots, x_T, y_1, \ldots, y_T, w_h, w_o) = \frac{1}{T}\sum_{t=1}^T l(y_ 对于反向传播,问题有点棘手,特别是当我们计算参数$w_h$关于目标函数$L$的梯度时。具体来说,按照链式法则: -$$\begin{aligned}\frac{\partial L}{\partial w_h} & = \frac{1}{T}\sum_{t=1}^T \frac{\partial l(y_t, o_t)}{\partial w_h} \\& = \frac{1}{T}\sum_{t=1}^T \frac{\partial l(y_t, o_t)}{\partial o_t} \frac{\partial g(h_t, w_h)}{\partial h_t} \frac{\partial h_t}{\partial w_h}.\end{aligned}$$ +$$\begin{aligned}\frac{\partial L}{\partial w_h} & = \frac{1}{T}\sum_{t=1}^T \frac{\partial l(y_t, o_t)}{\partial w_h} \\& = \frac{1}{T}\sum_{t=1}^T \frac{\partial l(y_t, o_t)}{\partial o_t} \frac{\partial g(h_t, w_o)}{\partial h_t} \frac{\partial h_t}{\partial w_h}.\end{aligned}$$ :eqlabel:`eq_bptt_partial_L_wh` :eqref:`eq_bptt_partial_L_wh` 中乘积的第一项和第二个项很容易计算。第三个项 $\partial h_t/\partial w_h$ 是事情变得棘手的地方,因为我们需要重复计算参数 $w_h$ 对 $h_t$ 的影响。根据 :eqref:`eq_bptt_ht_ot` 中的递归计算,$h_t$既依赖于$h_{t-1}$又依赖于$w_h$,其中$h_{t-1}$的计算也依赖于$w_h$。因此,使用链式法则产生: @@ -97,7 +97,7 @@ $$L = \frac{1}{T} \sum_{t=1}^T l(\mathbf{o}_t, y_t).$$ ![显示具有三个时间步的循环神经网络模型依赖关系的计算图。框表示变量(未着色)或参数(着色),圆表示运算符。](../img/rnn-bptt.svg) :label:`fig_rnn_bptt` -正如刚才提到的,:numref:`fig_rnn_bptt`中的模型参数是$\mathbf{W}_{hx}$、$\mathbf{W}_{hh}$和$\mathbf{W}_{qh}$。通常,训练该模型需要对这些参数$\partial L/\partial \mathbf{W}_{hx}$、$\partial L/\partial \mathbf{W}_{hh}$和$\partial L/\partial \mathbf{W}_{qh}$进行梯度计算。根据:numref:`fig_rnn_bptt`中的依赖关系,我们可以沿箭头的相反方向遍历,依次计算和存储梯度。为了灵活地表示链式法则中不同形状的矩阵、向量和标量的乘法,我们继续使用$\text{prod}$运算符,如:numref:`sec_backprop`中所述。 +正如刚才提到的, :numref:`fig_rnn_bptt` 中的模型参数是$\mathbf{W}_{hx}$、$\mathbf{W}_{hh}$和$\mathbf{W}_{qh}$。通常,训练该模型需要对这些参数 $\partial L/\partial \mathbf{W}_{hx}$ 、 $\partial L/\partial \mathbf{W}_{hh}$ 和 $\partial L/\partial \mathbf{W}_{qh}$ 进行梯度计算。根据 :numref:`fig_rnn_bptt` 中的依赖关系,我们可以沿箭头的相反方向遍历,依次计算和存储梯度。为了灵活地表示链式法则中不同形状的矩阵、向量和标量的乘法,我们继续使用 $\text{prod}$ 运算符,如 :numref:`sec_backprop` 中所述。 首先,目标函数有关任意时间步$t$的模型输出的梯度很容易计算: @@ -112,7 +112,7 @@ $$ = \sum_{t=1}^T \frac{\partial L}{\partial \mathbf{o}_t} \mathbf{h}_t^\top, $$ -其中$\partial L/\partial \mathbf{o}_t$是由:eqref:`eq_bptt_partial_L_ot`给出的。 +其中$\partial L/\partial \mathbf{o}_t$是由 :eqref:`eq_bptt_partial_L_ot` 给出的。 接下来,如 :numref:`fig_rnn_bptt` 所示,在最后的时间步$T$,目标函数$L$仅通过$\mathbf{o}_T$依赖隐藏状态$\mathbf{h}_T$。因此,我们可以使用链式法则容易地得到梯度$\partial L/\partial \mathbf{h}_T \in \mathbb{R}^h$: @@ -132,7 +132,7 @@ $$\frac{\partial L}{\partial \mathbf{h}_t}= \sum_{i=t}^T {\left(\mathbf{W}_{hh}^ 我们可以从 :eqref:`eq_bptt_partial_L_ht` 中看到,这个简单的线性例子已经展现了长序列模型的一些关键问题:它涉及到 $\mathbf{W}_{hh}^\top$ 的潜在非常大的指数。其中,小于1的特征值消失,大于1的特征值发散。这在数值上是不稳定的,表现为梯度消失或梯度爆炸。解决此问题的一种方法是按照计算方便的大小截断时间步长,如 :numref:`subsec_bptt_analysis` 中所述。实际上,这种截断是通过在给定数量的时间步长之后分离梯度来实现的。稍后,我们将看到更复杂的序列模型(如长短期记忆)如何进一步缓解这一问题。 -最后,:numref:`fig_rnn_bptt`表明了,目标函数$L$通过隐藏状态$\mathbf{W}_{hx}$和$\mathbf{W}_{hh}$依赖隐藏层中的模型参数$\mathbf{h}_1, \ldots, \mathbf{h}_T$。为了计算有关这些参数的梯度$\partial L / \partial \mathbf{W}_{hx} \in \mathbb{R}^{h \times d}$和$\partial L / \partial \mathbf{W}_{hh} \in \mathbb{R}^{h \times h}$,我们应用链式规则: +最后, :numref:`fig_rnn_bptt` 表明了,目标函数$L$通过隐藏状态$\mathbf{h}_1, \ldots, \mathbf{h}_T$依赖隐藏层中的模型参数$\mathbf{W}_{hx}$和$\mathbf{W}_{hh}$。为了计算有关这些参数的梯度$\partial L / \partial \mathbf{W}_{hx} \in \mathbb{R}^{h \times d}$和$\partial L / \partial \mathbf{W}_{hh} \in \mathbb{R}^{h \times h}$,我们应用链式规则: $$ \begin{aligned} @@ -145,7 +145,7 @@ $$ \end{aligned} $$ -其中$\partial L/\partial \mathbf{h}_t$是由:eqref:`eq_bptt_partial_L_hT_final_step`和:eqref:`eq_bptt_partial_L_ht_recur`递归计算的,是影响数值稳定性的关键量。 +其中$\partial L/\partial \mathbf{h}_t$是由 :eqref:`eq_bptt_partial_L_hT_final_step` 和 :eqref:`eq_bptt_partial_L_ht_recur` 递归计算的,是影响数值稳定性的关键量。 正如我们在 :numref:`sec_backprop` 中所解释的那样,通过时间反向传播是反向传播在循环神经网络中的应用,训练循环神经网络交替使用通过时间前向传播和反向传播。通过时间的反向传播依次计算并存储上述梯度。具体而言,存储的中间值会被重复使用,以避免重复计算,例如存储 $\partial L/\partial \mathbf{h}_t$,以便在计算 $\partial L / \partial \mathbf{W}_{hx}$ 和 $\partial L / \partial \mathbf{W}_{hh}$ 时使用。 @@ -164,4 +164,4 @@ $$ 1. 上述结果对于循环神经网络中的梯度意味着什么? 1. 除了梯度裁剪,你还能想到其他方法来应对循环神经网络中的梯度爆炸吗? -[Discussions](https://discuss.d2l.ai/t/334) +[Discussions](https://discuss.d2l.ai/t/2107) diff --git a/chapter_recurrent-neural-networks/language-models-and-dataset.md b/chapter_recurrent-neural-networks/language-models-and-dataset.md index c2d756102..a156937f6 100644 --- a/chapter_recurrent-neural-networks/language-models-and-dataset.md +++ b/chapter_recurrent-neural-networks/language-models-and-dataset.md @@ -35,7 +35,7 @@ $$\begin{aligned} \hat{P}(x'' \mid x,x') & = \frac{n(x, x',x'') + \epsilon_3 \hat{P}(x'')}{n(x, x') + \epsilon_3}. \end{aligned}$$ -其中,$\epsilon_1,\epsilon_2$和$\epsilon_3$是超参数。以$\epsilon_1$为例:当为$\epsilon_1 = 0$时,不应用平滑;当$\epsilon_1$接近正无穷大时,$\hat{P}(x)$接近均匀概率$1/m$。以上是其他技术可以实现的:cite:`Wood.Gasthaus.Archambeau.ea.2011`的一个相当原始的变体。 +其中,$\epsilon_1,\epsilon_2$和$\epsilon_3$是超参数。以$\epsilon_1$为例:当为$\epsilon_1 = 0$时,不应用平滑;当$\epsilon_1$接近正无穷大时,$\hat{P}(x)$接近均匀概率$1/m$。以上是其他技术可以实现的 :cite:`Wood.Gasthaus.Archambeau.ea.2011` 的一个相当原始的变体。 不幸的是,像这样的模型很快就会变得笨拙,原因如下:首先,我们需要存储所有计数。第二,这完全忽略了单词的意思。例如,“猫”和“猫科动物”应该出现在相关的上下文中。很难将这些模型调整到额外的上下文中,而基于深度学习的语言模型很适合考虑到这一点。最后,长单词序列几乎肯定是新出现的,因此简单地统计过往看到单词序列频率的模型肯定表现不佳。 @@ -135,24 +135,24 @@ d2l.plot([freqs, bigram_freqs, trigram_freqs], xlabel='token: x', legend=['unigram', 'bigram', 'trigram']) ``` -这个数字相当令人兴奋,原因有很多。首先,除了单字词,单词序列似乎也遵循齐普夫定律,尽管:eqref:`eq_zipf_law`中的指数$\alpha$更小,这取决于序列长度。其次,$n$元组的数量并没有那么大。这给了我们希望,语言中有相当多的结构。第三,很多$n$元组很少出现,这使得拉普拉斯平滑非常不适合语言建模。相反,我们将使用基于深度学习的模型。 +这个数字相当令人兴奋,原因有很多。首先,除了单字词,单词序列似乎也遵循齐普夫定律,尽管 :eqref:`eq_zipf_law` 中的指数$\alpha$更小,这取决于序列长度。其次,$n$元组的数量并没有那么大。这给了我们希望,语言中有相当多的结构。第三,很多$n$元组很少出现,这使得拉普拉斯平滑非常不适合语言建模。相反,我们将使用基于深度学习的模型。 ## 读取长序列数据 由于序列数据本质上是连续的,我们需要解决处理这带来的问题。我们在 :numref:`sec_sequence` 以一种相当特别的方式做到了这一点。当序列变得太长而不能被模型一次全部处理时,我们可能希望拆分这样的序列以供阅读。现在让我们描述一下总体策略。在介绍该模型之前,假设我们将使用神经网络来训练语言模型,其中该网络一次处理具有预定义长度的一小批序列,例如$n$个时间步。现在的问题是如何随机读取小批量的特征和标签。 -首先,由于文本序列可以是任意长的,例如整个“时光机器”书,我们可以将这样长的序列划分为具有相同时间步数的子序列。当训练我们的神经网络时,子序列的小批量将被输入到模型中。假设网络一次处理$n$个时间步的子序列。:numref:`fig_timemachine_5gram`画出了从原始文本序列获得子序列的所有不同方式,其中$n=5$和每个时间步的标记对应于一个字符。请注意,我们有相当大的自由度,因为我们可以选择指示初始位置的任意偏移量。 +首先,由于文本序列可以是任意长的,例如整个“时光机器”书,我们可以将这样长的序列划分为具有相同时间步数的子序列。当训练我们的神经网络时,子序列的小批量将被输入到模型中。假设网络一次处理$n$个时间步的子序列。 :numref:`fig_timemachine_5gram` 画出了从原始文本序列获得子序列的所有不同方式,其中$n=5$和每个时间步的标记对应于一个字符。请注意,我们有相当大的自由度,因为我们可以选择指示初始位置的任意偏移量。 ![分割文本时,不同的偏移量会导致不同的子序列。](../img/timemachine-5gram.svg) :label:`fig_timemachine_5gram` -因此,我们应该从:numref:`fig_timemachine_5gram`中选择哪一个呢?其实,他们都一样好。然而,如果我们只选择一个偏移量,那么用于训练网络的所有可能子序列的覆盖范围都是有限的。因此,我们可以从随机偏移量开始划分序列,以获得*覆盖*(coverage)和*随机性*(randomness)。在下面,我们将描述如何实现*随机采样*和*顺序分区*策略。 +因此,我们应该从 :numref:`fig_timemachine_5gram` 中选择哪一个呢?其实,他们都一样好。然而,如果我们只选择一个偏移量,那么用于训练网络的所有可能子序列的覆盖范围都是有限的。因此,我们可以从随机偏移量开始划分序列,以获得*覆盖*(coverage)和*随机性*(randomness)。在下面,我们将描述如何实现*随机采样*和*顺序分区*策略。 ### 随机采样 在随机采样中,每个样本都是在原始长序列上任意捕获的子序列。迭代期间来自两个相邻随机小批量的子序列不一定在原始序列上相邻。对于语言建模,目标是根据我们到目前为止看到的标记来预测下一个标记,因此标签是原始序列移位了一个标记。 -下面的代码每次从数据随机生成一个小批量。这里,参数`batch_size`指定每个小批量中的子序列样本数目,`num_steps`是每个子序列中预定义的时间步数。 +下面的代码每次从数据随机生成一个小批量。这里,参数 `batch_size` 指定每个小批量中的子序列样本数目, `num_steps` 是每个子序列中预定义的时间步数。 ```{.python .input} #@tab all @@ -241,7 +241,7 @@ for X, Y in seq_data_iter_sequential(my_seq, batch_size=2, num_steps=5): ```{.python .input} #@tab all class SeqDataLoader: #@save - """An iterator to load sequence data.""" + """加载序列数据的迭代器。""" def __init__(self, batch_size, num_steps, use_random_iter, max_tokens): if use_random_iter: self.data_iter_fn = d2l.seq_data_iter_random @@ -254,7 +254,7 @@ class SeqDataLoader: #@save return self.data_iter_fn(self.corpus, self.batch_size, self.num_steps) ``` -最后,我们定义了一个函数`load_data_time_machine`,它同时返回数据迭代器和词表,因此我们可以与其他带有`load_data`前缀的函数(如 :numref:`sec_fashion_mnist` 中定义的`d2l.load_data_fashion_mnist`)类似地使用它。 +最后,我们定义了一个函数 `load_data_time_machine` ,它同时返回数据迭代器和词表,因此我们可以与其他带有 `load_data` 前缀的函数(如 :numref:`sec_fashion_mnist` 中定义的 `d2l.load_data_fashion_mnist` )类似地使用它。 ```{.python .input} #@tab all @@ -288,13 +288,13 @@ def load_data_time_machine(batch_size, num_steps, #@save 1. 如果我们希望一个序列样本是一个完整的句子,那么这在小批量抽样中会带来什么样的问题呢?我们怎样才能解决这个问题呢? :begin_tab:`mxnet` -[Discussions](https://discuss.d2l.ai/t/117) +[Discussions](https://discuss.d2l.ai/t/2096) :end_tab: :begin_tab:`pytorch` -[Discussions](https://discuss.d2l.ai/t/118) +[Discussions](https://discuss.d2l.ai/t/2097) :end_tab: :begin_tab:`tensorflow` -[Discussions](https://discuss.d2l.ai/t/1049) +[Discussions](https://discuss.d2l.ai/t/2098) :end_tab: diff --git a/chapter_recurrent-neural-networks/rnn-concise.md b/chapter_recurrent-neural-networks/rnn-concise.md index a182349f1..ac3fdda7a 100644 --- a/chapter_recurrent-neural-networks/rnn-concise.md +++ b/chapter_recurrent-neural-networks/rnn-concise.md @@ -26,7 +26,7 @@ train_iter, vocab = d2l.load_data_time_machine(batch_size, num_steps) ## 定义模型 -高级API提供了循环神经网络的实现。我们构造了一个具有256隐藏单元的单隐藏层的循环神经网络层`rnn_layer`。事实上,我们还没有讨论多层的含义——这将在 :numref:`sec_deep_rnn`介绍。现在,只要说多层仅仅相当于一层循环神经网络的输出被用作下一层循环神经网络的输入就足够了。 +高级API提供了循环神经网络的实现。我们构造了一个具有256隐藏单元的单隐藏层的循环神经网络层 `rnn_layer`。事实上,我们还没有讨论多层的含义——这将在 :numref:`sec_deep_rnn`介绍。现在,只要说多层仅仅相当于一层循环神经网络的输出被用作下一层循环神经网络的输入就足够了。 ```{.python .input} num_hiddens = 256 @@ -78,7 +78,7 @@ Y, state_new = rnn_layer(X, state) Y.shape, state_new.shape ``` -与 :numref:`sec_rnn_scratch` 类似,我们为一个完整的循环神经网络模型定义了一个`RNNModel`类。注意`rnn_layer`只包含隐藏循环层,我们需要创建一个单独的输出层。 +与 :numref:`sec_rnn_scratch` 类似,我们为一个完整的循环神经网络模型定义了一个 `RNNModel` 类。注意 `rnn_layer` 只包含隐藏循环层,我们需要创建一个单独的输出层。 ```{.python .input} #@save @@ -164,7 +164,7 @@ net = net.to(device) d2l.predict_ch8('time traveller', 10, net, vocab, device) ``` -很明显,这种模型根本不起作用。接下来,我们使用 :numref:`sec_rnn_scratch` 中定义的超参数调用`train_ch8`,并使用高级API训练模型。 +很明显,这种模型根本不起作用。接下来,我们使用 :numref:`sec_rnn_scratch` 中定义的超参数调用 `train_ch8`,并使用高级API训练模型。 ```{.python .input} #@tab all @@ -187,9 +187,9 @@ d2l.train_ch8(net, train_iter, vocab, lr, num_epochs, device) 1. 使用循环神经网络实现 :numref:`sec_sequence` 的自回归模型。 :begin_tab:`mxnet` -[Discussions](https://discuss.d2l.ai/t/335) +[Discussions](https://discuss.d2l.ai/t/2105) :end_tab: :begin_tab:`pytorch` -[Discussions](https://discuss.d2l.ai/t/1053) +[Discussions](https://discuss.d2l.ai/t/2106) :end_tab: diff --git a/chapter_recurrent-neural-networks/rnn-scratch.md b/chapter_recurrent-neural-networks/rnn-scratch.md index a82da339b..6fd8aaf05 100644 --- a/chapter_recurrent-neural-networks/rnn-scratch.md +++ b/chapter_recurrent-neural-networks/rnn-scratch.md @@ -44,7 +44,7 @@ train_random_iter, vocab_random_iter = d2l.load_data_time_machine( ## 独热编码 -回想一下,在`train_iter`中,每个标记都表示为一个数字索引。将这些数字直接输入神经网络可能会使学习变得困难。我们通常将每个标记表示为更具表现力的特征向量。最简单的表示称为“独热编码”(One-Hot Encoding),它在:numref:`subsec_classification-problem`中介绍过。 +回想一下,在`train_iter`中,每个标记都表示为一个数字索引。将这些数字直接输入神经网络可能会使学习变得困难。我们通常将每个标记表示为更具表现力的特征向量。最简单的表示称为“独热编码”(One-Hot Encoding),它在 :numref:`subsec_classification-problem` 中介绍过。 简言之,我们将每个索引映射到一个不同的单位向量:假设词表中不同的标记数为$N$(`len(vocab)`),标记索引的范围为0到$N-1$。如果标记的索引是整数$i$,那么我们创建一个长度为$N$的全0向量,并将$i$处的元素设置为1。此向量是原始标记的一个独热向量。索引为0和2的独热向量如下所示。 @@ -362,7 +362,7 @@ def predict_ch8(prefix, num_preds, net, vocab, params): #@save return ''.join([vocab.idx_to_token[i] for i in outputs]) ``` -现在我们可以测试`predict_ch8`函数。我们将前缀指定为`time traveller `,并让它生成10个后续字符。鉴于我们没有训练网络,它会产生荒谬的预测。 +现在我们可以测试 `predict_ch8` 函数。我们将前缀指定为 `time traveller ` ,并让它生成10个后续字符。鉴于我们没有训练网络,它会产生荒谬的预测。 ```{.python .input} #@tab mxnet,pytorch @@ -443,7 +443,7 @@ def grad_clipping(grads, theta): #@save ## 训练 -在训练模型之前,让我们定义一个函数来训练只有一个迭代周期的模型。它与我们训练:numref:`sec_softmax_scratch`模型的方式有三个不同之处: +在训练模型之前,让我们定义一个函数来训练只有一个迭代周期的模型。它与我们训练 :numref:`sec_softmax_scratch` 模型的方式有三个不同之处: 1. 顺序数据的不同采样方法(随机采样和顺序分区)将导致隐藏状态初始化的差异。 1. 我们在更新模型参数之前裁剪梯度。这确保了即使在训练过程中的某个点上梯度爆炸,模型也不会发散。 @@ -451,7 +451,7 @@ def grad_clipping(grads, theta): #@save 具体地说,当使用顺序分区时,我们只在每个迭代周期的开始处初始化隐藏状态。由于下一个小批量中的$i^\mathrm{th}$子序列样本与当前$i^\mathrm{th}$子序列样本相邻,因此当前小批量末尾的隐藏状态将用于初始化下一个小批量开头的隐藏状态。这样,存储在隐藏状态中的序列历史信息可以在一个迭代周期内流过相邻的子序列。然而,任何一点隐藏状态计算都依赖于同一迭代周期中所有的前一个小批量,这使得梯度计算变得复杂。为了降低计算量,我们在处理任何一个小批量之前先分离梯度,使得隐藏状态的梯度计算总是限制在一个小批量的时间步内。 -当使用随机抽样时,我们需要为每个迭代周期重新初始化隐藏状态,因为每个样本都是在一个随机位置抽样的。与 :numref:`sec_softmax_scratch` 中的 `train_epoch_ch3` 函数相同,`updater`是更新模型参数的常用函数。它既可以是从头开始实现的`d2l.sgd`函数,也可以是深度学习框架中的内置优化函数。 +当使用随机抽样时,我们需要为每个迭代周期重新初始化隐藏状态,因为每个样本都是在一个随机位置抽样的。与 :numref:`sec_softmax_scratch` 中的 `train_epoch_ch3` 函数相同,`updater`是更新模型参数的常用函数。它既可以是从头开始实现的 `d2l.sgd` 函数,也可以是深度学习框架中的内置优化函数。 ```{.python .input} #@save @@ -680,13 +680,13 @@ train_ch8(net, train_random_iter, vocab_random_iter, num_hiddens, lr, 1. 用ReLU替换本节中使用的激活函数,并重复本节中的实验。我们还需要梯度裁剪吗?为什么? :begin_tab:`mxnet` -[Discussions](https://discuss.d2l.ai/t/336) +[Discussions](https://discuss.d2l.ai/t/2102) :end_tab: :begin_tab:`pytorch` -[Discussions](https://discuss.d2l.ai/t/486) +[Discussions](https://discuss.d2l.ai/t/2103) :end_tab: :begin_tab:`tensorflow` -[Discussions](https://discuss.d2l.ai/t/1052) +[Discussions](https://discuss.d2l.ai/t/2104) :end_tab: diff --git a/chapter_recurrent-neural-networks/rnn.md b/chapter_recurrent-neural-networks/rnn.md index 194b972d5..a433684ca 100644 --- a/chapter_recurrent-neural-networks/rnn.md +++ b/chapter_recurrent-neural-networks/rnn.md @@ -10,7 +10,7 @@ $$P(x_t \mid x_{t-1}, \ldots, x_1) \approx P(x_t \mid h_{t-1}),$$ $$h_t = f(x_{t}, h_{t-1}).$$ :eqlabel:`eq_ht_xt` -对于足够强大的函数$f$(:eqref:`eq_ht_xt`),隐变量模型不是近似值。毕竟,$h_t$可能只是存储到目前为止观察到的所有数据。然而,它可能会使计算和存储都变得昂贵。 +对于足够强大的函数$f$( :eqref:`eq_ht_xt` ),隐变量模型不是近似值。毕竟,$h_t$可能只是存储到目前为止观察到的所有数据。然而,它可能会使计算和存储都变得昂贵。 回想一下,我们在 :numref:`chap_perceptrons` 中讨论过具有隐藏单元的隐藏层。值得注意的是,隐藏层和隐藏状态指的是两个截然不同的概念。如上所述,隐藏层是在从输入到输出的路径上从视图中隐藏的层。从技术上讲,隐藏状态是我们在给定步骤所做的任何事情的“输入”。隐藏状态只能通过查看先前时间点的数据来计算。 @@ -41,7 +41,7 @@ $$\mathbf{O} = \mathbf{H} \mathbf{W}_{hq} + \mathbf{b}_q,$$ $$\mathbf{H}_t = \phi(\mathbf{X}_t \mathbf{W}_{xh} + \mathbf{H}_{t-1} \mathbf{W}_{hh} + \mathbf{b}_h).$$ :eqlabel:`rnn_h_with_state` -与 :eqref:`rnn_h_without_state` 相比, :eqref:`rnn_h_with_state` 多添加了一项$\mathbf{H}_{t-1} \mathbf{W}_{hh}$,从而实例化了 :eqref:`eq_ht_xt`。从相邻时间步的隐藏变量$\mathbf{H}_t$和$\mathbf{H}_{t-1}$之间的关系可知,这些变量捕获并保留了序列直到其当前时间步的历史信息,就像神经网络的当前时间步的状态或记忆一样。因此,这样的隐藏变量被称为“隐藏状态”(hidden state)。由于隐藏状态使用与当前时间步中的前一个时间步相同的定义,因此 :eqref:`rnn_h_with_state` 的计算是*循环的*(recurrent)。因此,基于循环计算的隐状态神经网络被命名为*循环神经网络*(recurrent neural networks)。在循环神经网络中执行:eqref:`rnn_h_with_state`计算的层称为“循环层”(recurrent layers)。 +与 :eqref:`rnn_h_without_state` 相比, :eqref:`rnn_h_with_state` 多添加了一项$\mathbf{H}_{t-1} \mathbf{W}_{hh}$,从而实例化了 :eqref:`eq_ht_xt`。从相邻时间步的隐藏变量$\mathbf{H}_t$和$\mathbf{H}_{t-1}$之间的关系可知,这些变量捕获并保留了序列直到其当前时间步的历史信息,就像神经网络的当前时间步的状态或记忆一样。因此,这样的隐藏变量被称为“隐藏状态”(hidden state)。由于隐藏状态使用与当前时间步中的前一个时间步相同的定义,因此 :eqref:`rnn_h_with_state` 的计算是*循环的*(recurrent)。因此,基于循环计算的隐状态神经网络被命名为*循环神经网络*(recurrent neural networks)。在循环神经网络中执行 :eqref:`rnn_h_with_state` 计算的层称为“循环层”(recurrent layers)。 构建循环神经网络有许多不同的方法。具有由 :eqref:`rnn_h_with_state` 定义的隐藏状态的循环神经网络非常常见。对于时间步$t$,输出层的输出类似于多层感知机中的计算: @@ -98,12 +98,12 @@ d2l.matmul(d2l.concat((X, H), 1), d2l.concat((W_xh, W_hh), 0)) ## 基于循环神经网络的字符级语言模型 -回想一下,对于 :numref:`sec_language_model` 中的语言模型。我们的目标是根据当前和过去的标记预测下一个标记,因此我们将原始序列移位一个标记作为标签。Bengio等人:cite:`Bengio.Ducharme.Vincent.ea.2003`首先提出使用神经网络进行语言建模。接下来,我们将说明如何使用循环神经网络来构建语言模型。设小批量大小为1,文本序列为"machine"。为了简化后续部分的训练,我们将文本标记化为字符而不是单词,并考虑使用*字符级语言模型*(character-level language model)。:numref:`fig_rnn_train`演示了如何通过用于字符级语言建模的循环神经网络,基于当前字符和先前字符预测下一个字符。 +回想一下,对于 :numref:`sec_language_model` 中的语言模型。我们的目标是根据当前和过去的标记预测下一个标记,因此我们将原始序列移位一个标记作为标签。Bengio等人 :cite:`Bengio.Ducharme.Vincent.ea.2003` 首先提出使用神经网络进行语言建模。接下来,我们将说明如何使用循环神经网络来构建语言模型。设小批量大小为1,文本序列为"machine"。为了简化后续部分的训练,我们将文本标记化为字符而不是单词,并考虑使用*字符级语言模型*(character-level language model)。 :numref:`fig_rnn_train` 演示了如何通过用于字符级语言建模的循环神经网络,基于当前字符和先前字符预测下一个字符。 ![基于循环神经网络的字符级语言模型。输入序列和标签序列分别为“machin”和“achine”。](../img/rnn-train.svg) :label:`fig_rnn_train` -在训练过程中,我们对每个时间步长的输出层的输出进行softmax操作,然后利用交叉熵损失计算模型输出和标签之间的误差。由于隐藏层中隐藏状态的循环计算,:numref:`fig_rnn_train`中的时间步骤3的输出$\mathbf{O}_3$由文本序列“m”、“a”和“c”确定。由于训练数据中序列的下一个字符是“h”,因此时间步3的损失将取决于基于该时间步的特征序列“m”、“a”、“c”生成的下一个字符概率分布和标签“h”。 +在训练过程中,我们对每个时间步长的输出层的输出进行softmax操作,然后利用交叉熵损失计算模型输出和标签之间的误差。由于隐藏层中隐藏状态的循环计算, :numref:`fig_rnn_train` 中的时间步骤3的输出$\mathbf{O}_3$由文本序列“m”、“a”和“c”确定。由于训练数据中序列的下一个字符是“h”,因此时间步3的损失将取决于基于该时间步的特征序列“m”、“a”、“c”生成的下一个字符概率分布和标签“h”。 实际上,每个标记都由一个$d$维向量表示,我们使用批量大小$n>1$。因此,输入$\mathbf X_t$在时间步$t$将是$n\times d$矩阵,这与我们在 :numref:`subsec_rnn_w_hidden_states` 中讨论的相同。 @@ -121,12 +121,12 @@ d2l.matmul(d2l.concat((X, H), 1), d2l.concat((W_xh, W_hh), 0)) 我们可以通过计算序列的似然概率来衡量模型的质量。不幸的是,这是一个很难理解和难以比较的数字。毕竟,较短的序列比较长的序列更有可能出现,因此在托尔斯泰的巨著《战争与和平》上对该模型进行评估 不可避免地会比圣埃克苏佩里的中篇小说《小王子》产生的可能性要小得多。缺少的相当于平均数。 -信息论在这里派上了用场。。我们在引入softmax回归(:numref:`subsec_info_theory_basics`)时定义了熵、奇异熵和交叉熵,并在[信息论的在线附录](https://d2l.ai/chapter_appendix-mathematics-for-deep-learning/information-theory.html)中讨论了更多的信息论。如果我们想压缩文本,我们可以询问在给定当前标记集的情况下预测下一个标记。一个更好的语言模型应该能让我们更准确地预测下一个标记。因此,它应该允许我们在压缩序列时花费更少的比特。所以我们可以通过一个序列中所有$n$个标记的平均交叉熵损失来衡量: +信息论在这里派上了用场。。我们在引入softmax回归( :numref:`subsec_info_theory_basics` )时定义了熵、奇异熵和交叉熵,并在[信息论的在线附录](https://d2l.ai/chapter_appendix-mathematics-for-deep-learning/information-theory.html)中讨论了更多的信息论。如果我们想压缩文本,我们可以询问在给定当前标记集的情况下预测下一个标记。一个更好的语言模型应该能让我们更准确地预测下一个标记。因此,它应该允许我们在压缩序列时花费更少的比特。所以我们可以通过一个序列中所有$n$个标记的平均交叉熵损失来衡量: $$\frac{1}{n} \sum_{t=1}^n -\log P(x_t \mid x_{t-1}, \ldots, x_1),$$ :eqlabel:`eq_avg_ce_for_lm` -其中$P$由语言模型给出,$x_t$是在时间步$t$从该序列观察到的实际标记。这使得在不同长度的文档上的性能具有可比性。由于历史原因,自然语言处理的科学家更喜欢使用一个叫做“困惑度”(perplexity)的量。简而言之,它是:eqref:`eq_avg_ce_for_lm`的指数: +其中$P$由语言模型给出,$x_t$是在时间步$t$从该序列观察到的实际标记。这使得在不同长度的文档上的性能具有可比性。由于历史原因,自然语言处理的科学家更喜欢使用一个叫做“困惑度”(perplexity)的量。简而言之,它是 :eqref:`eq_avg_ce_for_lm` 的指数: $$\exp\left(-\frac{1}{n} \sum_{t=1}^n \log P(x_t \mid x_{t-1}, \ldots, x_1)\right).$$ @@ -154,13 +154,13 @@ $$\exp\left(-\frac{1}{n} \sum_{t=1}^n \log P(x_t \mid x_{t-1}, \ldots, x_1)\righ 1. 与本节中描述的语言模型相关的问题有哪些? :begin_tab:`mxnet` -[Discussions](https://discuss.d2l.ai/t/337) +[Discussions](https://discuss.d2l.ai/t/2099) :end_tab: :begin_tab:`pytorch` -[Discussions](https://discuss.d2l.ai/t/1050) +[Discussions](https://discuss.d2l.ai/t/2100) :end_tab: :begin_tab:`tensorflow` -[Discussions](https://discuss.d2l.ai/t/1051) +[Discussions](https://discuss.d2l.ai/t/2101) :end_tab: diff --git a/chapter_recurrent-neural-networks/sequence.md b/chapter_recurrent-neural-networks/sequence.md index 192e09f90..88b7cdb6e 100644 --- a/chapter_recurrent-neural-networks/sequence.md +++ b/chapter_recurrent-neural-networks/sequence.md @@ -10,7 +10,7 @@ * 在某些情况下,由于导演或演员在制作中的不当行为,电影变得不受欢迎。 * 有些电影在小圈子内被支持者喜爱及推崇,这是因为它们几乎滑稽可笑。 -简而言之,电影评分决不是固定不变的。因此,使用时间动力学可以得到更准确的电影推荐:cite:`Koren.2009`。当然,序列数据不仅仅是关于电影评分的。下面给出了更多的场景。 +简而言之,电影评分决不是固定不变的。因此,使用时间动力学可以得到更准确的电影推荐 :cite:`Koren.2009` 。当然,序列数据不仅仅是关于电影评分的。下面给出了更多的场景。 * 许多用户在打开应用程序时都有非常特殊的行为。例如,社交媒体应用在学生放学后更受欢迎。股市交易应用程序在市场开放时更常用。 * 要预测明天的股价要比填补我们昨天错过股价的空白困难得多,尽管两者都只是估计一个数字。毕竟,先见之明比事后诸葛亮难得多。在统计学中,前者(超出已知观测值的预测)称为*外推*(extrapolation),而后者(在现有观测值之间进行估计)称为*内插*(interpolation)。 @@ -192,7 +192,7 @@ def get_net(): loss = tf.keras.losses.MeanSquaredError() ``` -现在我们准备好训练模型了。下面的代码与前面几节中的训练代码实现基本相同,如:numref:`sec_linear_concise`。因此,我们不会深入探讨太多细节。 +现在我们准备好训练模型了。下面的代码与前面几节中的训练代码实现基本相同,如 :numref:`sec_linear_concise` 。因此,我们不会深入探讨太多细节。 ```{.python .input} def train(net, train_iter, loss, epochs, lr): @@ -269,7 +269,7 @@ $$ \ldots $$ -通常,对于直到$x_t$的观测序列,其在时间步长$\hat{x}_{t+k}$处的预测输出$t+k$被称为*$k$步预测*。由于我们已经观察到了$x_{604}$,它领先$k$步的预测是$\hat{x}_{604+k}$。换句话说,我们将不得不使用我们自己的预测来进行多步预测。让我们看看这件事进行得有多顺利。 +通常,对于直到$x_t$的观测序列,其在时间步长$\hat{x}_{t+k}$处的预测输出$t+k$被称为"$k$步预测"。由于我们已经观察到了$x_{604}$,它领先$k$步的预测是$\hat{x}_{604+k}$。换句话说,我们将不得不使用我们自己的预测来进行多步预测。让我们看看这件事进行得有多顺利。 ```{.python .input} #@tab mxnet, pytorch @@ -351,7 +351,7 @@ d2l.plot([time[tau + i - 1: T - max_steps + i] for i in steps], * 内插和外推在难度上有很大差别。因此,如果你有一个序列,在训练时始终要尊重数据的时间顺序,即永远不要对未来的数据进行训练。 * 序列模型需要专门的统计工具进行估计。两种流行的选择是自回归模型和隐变量自回归模型。 * 对于因果模型(例如,向前推进的时间),估计正向通常比反向容易得多。 -* 对于直到时间步$t$的观测序列,其在时间步$t+k$的预测输出是*$k$步预测*。随着我们在时间上进一步预测,增加$k$,误差会累积,预测的质量会下降。 +* 对于直到时间步$t$的观测序列,其在时间步$t+k$的预测输出是"$k$步预测"。随着我们在时间上进一步预测,增加$k$,误差会累积,预测的质量会下降。 ## 练习 @@ -365,13 +365,13 @@ d2l.plot([time[tau + i - 1: T - max_steps + i] for i in steps], 1. 举例说明什么时候可能需要隐变量自回归模型来捕捉数据的动力学模型。 :begin_tab:`mxnet` -[Discussions](https://discuss.d2l.ai/t/113) +[Discussions](https://discuss.d2l.ai/t/2090) :end_tab: :begin_tab:`pytorch` -[Discussions](https://discuss.d2l.ai/t/114) +[Discussions](https://discuss.d2l.ai/t/2091) :end_tab: :begin_tab:`tensorflow` -[Discussions](https://discuss.d2l.ai/t/1048) +[Discussions](https://discuss.d2l.ai/t/2092) :end_tab: diff --git a/chapter_recurrent-neural-networks/text-preprocessing.md b/chapter_recurrent-neural-networks/text-preprocessing.md index 426e1292f..cb3fef8d1 100644 --- a/chapter_recurrent-neural-networks/text-preprocessing.md +++ b/chapter_recurrent-neural-networks/text-preprocessing.md @@ -52,7 +52,7 @@ print(lines[10]) ## 标记化 -以下`tokenize`函数将列表作为输入,列表中的每个元素是文本序列(如,文本行)。每个文本序列被拆分成一个标记列表。*标记*(token)是文本的基本单位。最后返回一个标记列表,其中每个标记都是一个字符串(string)。 +以下 `tokenize` 函数将列表作为输入,列表中的每个元素是文本序列(如,文本行)。每个文本序列被拆分成一个标记列表。*标记*(token)是文本的基本单位。最后返回一个标记列表,其中每个标记都是一个字符串(string)。 ```{.python .input} #@tab all @@ -111,7 +111,7 @@ class Vocab: #@save def count_corpus(tokens): #@save """Count token frequencies.""" - # 这里的`tokens`是1D列表或2D列表 + # 这里的 `tokens` 是1D列表或2D列表 if len(tokens) == 0 or isinstance(tokens[0], list): # 将令牌列表展平 tokens = [token for line in tokens for token in line] @@ -137,7 +137,9 @@ for i in [0, 10]: ## 把所有的东西放在一起 -使用上述函数,我们将所有内容打包到`load_corpus_time_machine`函数中,该函数返回`corpus`(标记索引列表)和`vocab`(时光机器语料库的词汇表)。我们在这里所做的修改是:1、我们将文本标记化为字符,而不是单词,以简化后面部分中的训练;2、`corpus`是单个列表,而不是标记列表嵌套,因为时光机器数据集中的每个文本行不一定是句子或段落。 +使用上述函数,我们将所有内容打包到 `load_corpus_time_machine` 函数中,该函数返回 `corpus`(标记索引列表)和 `vocab`(时光机器语料库的词汇表)。我们在这里所做的修改是: +- 1、我们将文本 标记化为字符,而不是单词,以简化后面部分中的训练; +- 2、`corpus`是单个列表,而不是标记列表嵌套,因为时光机器数据集中的每个文本行不一定是句子或段落。 ```{.python .input} #@tab all @@ -165,6 +167,16 @@ len(corpus), len(vocab) ## 练习 1. 标记化是一个关键的预处理步骤。它因语言而异。尝试找到另外三种常用的文本标记方法。 -1. 在本节的实验中,将文本标记为单词,并更改`Vocab`实例的`min_freq`参数。这对词汇量有何影响? +1. 在本节的实验中,将文本标记为单词,并更改 `Vocab` 实例的 `min_freq` 参数。这对词汇量有何影响? -[Discussions](https://discuss.d2l.ai/t/115) +:begin_tab:`mxnet` +[Discussions](https://discuss.d2l.ai/t/2093) +:end_tab: + +:begin_tab:`pytorch` +[Discussions](https://discuss.d2l.ai/t/2094) +:end_tab: + +:begin_tab:`tensorflow` +[Discussions](https://discuss.d2l.ai/t/2095) +:end_tab: \ No newline at end of file diff --git a/config.ini b/config.ini index 6b058a026..30a7d422f 100644 --- a/config.ini +++ b/config.ini @@ -8,7 +8,7 @@ author = Aston Zhang, Zachary C. Lipton, Mu Li, and Alexander J. Smola copyright = 2021, All authors. Licensed under CC-BY-SA-4.0 and MIT-0. -release = 1.2.0 +release = 2.0.0-alpha0 lang = zh @@ -81,11 +81,11 @@ sphinx_configs = numfig_format = {'figure': '图%%s', 'table': '表%%s', 'code-b # (https://fontawesome.com/icons?d=gallery). Items are separated by commas. # PDF, http://numpy.d2l.ai/d2l-en.pdf, fas fa-file-pdf, header_links = 伯克利深度学习课程, https://courses.d2l.ai, fas fa-user-graduate, - PDF, https://d2l.ai/d2l-en.pdf, fas fa-file-pdf, - Jupyter 记事本文件, https://d2l.ai/d2l-en.zip, fas fa-download, + PDF, https://zh-v2.d2l.ai/d2l-zh.pdf, fas fa-file-pdf, + Jupyter 记事本文件, https://zh-v2.d2l.ai/d2l-zh.zip, fas fa-download, 讨论, https://discuss.d2l.ai/c/16, fab fa-discourse, GitHub, https://github.com/d2l-ai/d2l-zh, fab fa-github, - 英文版, https://d2l.ai, fas fa-external-link-alt + English, https://d2l.ai, fas fa-external-link-alt favicon = static/favicon.png diff --git a/contrib/chapter_recommender-systems/autorec.md b/contrib/chapter_recommender-systems/autorec.md index 91f6afdc8..9ca89ce60 100644 --- a/contrib/chapter_recommender-systems/autorec.md +++ b/contrib/chapter_recommender-systems/autorec.md @@ -104,7 +104,7 @@ d2l.train_recsys_rating(net, train_iter, test_iter, loss, trainer, num_epochs, ctx, evaluator, inter_mat=test_inter_mat) ``` -## 总结 +## 小结 * 我们可以使用自动编码器构建矩阵分解算法,同时还可以在其中整合非线性层和dropout正则化层。 * MovieLens-100K数据集上的实验表明,自动编码器的性能优于矩阵分解模型。 diff --git a/contrib/chapter_recommender-systems/ctr.md b/contrib/chapter_recommender-systems/ctr.md index 4323643a2..b828b5b8d 100644 --- a/contrib/chapter_recommender-systems/ctr.md +++ b/contrib/chapter_recommender-systems/ctr.md @@ -87,7 +87,7 @@ train_data[0] 如你所见,这34个字段都是分类特征。每个数值都代表了对应条目的独热索引,标签$0$表示没有被点击。这里的`CTRDataset`也可以用来加载其他的数据集,例如Criteo展示广告挑战赛[数据集](https://labs.criteo.com/2014/02/kaggle-display-advertising-challenge-dataset/)和Avazu点击率预测[数据集](https://www.kaggle.com/c/avazu-ctr-prediction) 。 -## 总结 +## 小结 * 点击率是一项很重要的指标,它能用于评估广告系统和推荐系统的性能。 * 点击率预测经常被转化为二分类问题。该问题的目标是,在给定特征后,预测广告或物品是否会被点击。 diff --git a/contrib/chapter_recommender-systems/fm.md b/contrib/chapter_recommender-systems/fm.md index d31395849..cbc690410 100644 --- a/contrib/chapter_recommender-systems/fm.md +++ b/contrib/chapter_recommender-systems/fm.md @@ -95,7 +95,7 @@ loss = gluon.loss.SigmoidBinaryCrossEntropyLoss() d2l.train_ch13(net, train_iter, test_iter, loss, trainer, num_epochs, ctx) ``` -## 总结 +## 小结 * 因子分解机是一种通用框架,它可以应用在回归、分类和排序等一系列不同的任务上。 * 对于预测任务来说,特征交互/交叉非常重要,而使用因子分解机可以高效地建模双路特征交互。 diff --git a/contrib/chapter_recommender-systems/mf.md b/contrib/chapter_recommender-systems/mf.md index 7967d212d..9e08992f8 100644 --- a/contrib/chapter_recommender-systems/mf.md +++ b/contrib/chapter_recommender-systems/mf.md @@ -154,7 +154,7 @@ scores = net(np.array([20], dtype='int', ctx=d2l.try_gpu()), scores ``` -## 总结 +## 小结 * 矩阵分解模型在推荐系统中有着广泛的应用。它可以用于预测用户对物品的评分。 * 我们可以为推荐系统实现和训练一个矩阵分解模型。 diff --git a/contrib/chapter_recommender-systems/movielens.md b/contrib/chapter_recommender-systems/movielens.md index f6e570851..bf0dbc4c6 100644 --- a/contrib/chapter_recommender-systems/movielens.md +++ b/contrib/chapter_recommender-systems/movielens.md @@ -93,7 +93,7 @@ def split_data_ml100k(data, num_users, num_items, ## 加载数据 -分割数据集后,为了方面使用,我们将训练集和测试集转化为了列表和字典(或者矩阵)。下面的函数逐行读取dataframe中数据,并且从0开始枚举用户和物品的索引。该函数的返回值为用户、物品和评分列表,以及一个记录了交互数据的字典或者矩阵。我们可以将返回的类型指定为`显式`或者`隐式`。 +分割数据集后,为了方面使用,我们将训练集和测试集转化为了列表和字典(或者矩阵)。下面的函数按行读取dataframe中数据,并且从0开始枚举用户和物品的索引。该函数的返回值为用户、物品和评分列表,以及一个记录了交互数据的字典或者矩阵。我们可以将返回的类型指定为`显式`或者`隐式`。 ```python #@save @@ -140,7 +140,7 @@ def split_and_load_ml100k(split_mode='seq-aware', feedback='explicit', return num_users, num_items, train_iter, test_iter ``` -## 总结 +## 小结 * MovieLens广泛用于推荐系统研究。它是免费且公开可用的。 * 为了能在后续章节中使用,我们定义了一些函数用来下载和预处理MovieLens-100k数据集。 diff --git a/contrib/to-rm-mx-contrib-text/chapter_natural-language-processing/machine-translation.md b/contrib/to-rm-mx-contrib-text/chapter_natural-language-processing/machine-translation.md index 862b9a2aa..d80454e6b 100644 --- a/contrib/to-rm-mx-contrib-text/chapter_natural-language-processing/machine-translation.md +++ b/contrib/to-rm-mx-contrib-text/chapter_natural-language-processing/machine-translation.md @@ -107,7 +107,7 @@ dense.initialize() dense(nd.zeros((3, 5, 7))).shape ``` -我们将实现[“注意力机制”](./attention.md)一节中定义的函数$a$:将输入连结后通过含单隐藏层的多层感知机变换。其中隐藏层的输入是解码器的隐藏状态与编码器在所有时间步上隐藏状态的一一连结,且使用tanh函数作为激活函数。输出层的输出个数为1。两个`Dense`实例均不使用偏差,且设`flatten=False`。其中函数$a$定义里向量$\boldsymbol{v}$的长度是一个超参数,即`attention_size`。 +我们将实现[“注意力机制”](./attention.md)一节中定义的函数$a$:将输入连结后通过含单隐藏层的多层感知机变换。其中隐藏层的输入是解码器的隐藏状态与编码器在所有时间步上隐藏状态的一一连结,且使用tanh函数作为激活函数。输出层的输出个数为1。两个`Dense`实例均不使用偏置,且设`flatten=False`。其中函数$a$定义里向量$\boldsymbol{v}$的长度是一个超参数,即`attention_size`。 ```{.python .input n=167} def attention_model(attention_size): diff --git a/d2l/__init__.py b/d2l/__init__.py index 74fab0645..4e5939acf 100644 --- a/d2l/__init__.py +++ b/d2l/__init__.py @@ -8,4 +8,4 @@ """ -__version__ = "1.2.0" +__version__ = "0.16.1" diff --git a/img/frontpage/jd-190715-en.png b/img/frontpage/jd-190715-en.png new file mode 100644 index 000000000..418028a79 Binary files /dev/null and b/img/frontpage/jd-190715-en.png differ diff --git a/img/frontpage/jd-190715-zh.png b/img/frontpage/jd-190715-zh.png new file mode 100644 index 000000000..de6ee4d2b Binary files /dev/null and b/img/frontpage/jd-190715-zh.png differ diff --git a/index.md b/index.md index 36a1474a6..26ed2f36f 100644 --- a/index.md +++ b/index.md @@ -10,7 +10,6 @@ ```toc :maxdepth: 1 -chapter_preface/index chapter_installation/index chapter_notation/index ``` diff --git a/static/build.yml b/static/build.yml index c62548d2d..ef0dd6939 100644 --- a/static/build.yml +++ b/static/build.yml @@ -5,11 +5,9 @@ dependencies: - .. # d2l - git+https://github.com/d2l-ai/d2l-book - mxnet-cu101==1.7.0 - - torch==1.8.0.dev20201225+cu101 - - --pre - - -f https://download.pytorch.org/whl/nightly/cu101/torch_nightly.html - - torchvision==0.9.0.dev20201225+cu101 - - --pre - - -f https://download.pytorch.org/whl/nightly/cu101/torch_nightly.html + - torch==1.8.0+cu101 + - -f https://download.pytorch.org/whl/torch_stable.html + - torchvision==0.9.0+cu101 + - -f https://download.pytorch.org/whl/torch_stable.html - tensorflow==2.3.1 - tensorflow-probability==0.11.1 diff --git a/static/frontpage/frontpage.html b/static/frontpage/frontpage.html index 8af95536c..88b9dda49 100644 --- a/static/frontpage/frontpage.html +++ b/static/frontpage/frontpage.html @@ -181,10 +181,11 @@
-

《动手学深度学习》

+

《动手学深度学习》
(第二版预览版)

面向中文读者的能运行、可讨论的深度学习教科书

NumPy/MXNetPyTorchTensorFlow实现

- 被全球40个国家175所大学用于教学 + 被全球40个国家175所大学用于教学

+ 本书第一版(已出版)

@@ -195,11 +196,11 @@

公告

-

如果你使用(或计划使用)本书教学并希望收到免费纸质版图书, +

如果你使用(或将要使用)本书教学并希望收到免费纸质版图书, 请联系我们