19 / 19
附录:深度学习工具
为了充分利用《动手学深度学习》,本书将在本附录中介绍不同工具,
例如如何运行这本交互式开源书籍和为本书做贡献。
:maxdepth: 2
jupyter
sagemaker
aws
selecting-servers-gpus
contributing
d2l
使用Jupyter Notebook
本节介绍如何使用Jupyter Notebook编辑和运行本书各章中的代码。确保你已按照 :ref:chap_installation中的说明安装了Jupyter并下载了代码。如果你想了解更多关于Jupyter的信息,请参阅其文档中的优秀教程。
在本地编辑和运行代码
假设本书代码的本地路径为xx/yy/d2l-en/。使用shell将目录更改为此路径(cd xx/yy/d2l-en)并运行命令jupyter notebook。如果浏览器未自动打开,请打开http://localhost:8888。此时你将看到Jupyter的界面以及包含本书代码的所有文件夹,如 :numref:fig_jupyter00所示

:width:600px
你可以通过单击网页上显示的文件夹来访问notebook文件。它们通常有后缀“.ipynb”。为了简洁起见,我们创建了一个临时的“test.ipynb”文件。单击后显示的内容如 :numref:fig_jupyter01所示。此notebook包括一个标记单元格和一个代码单元格。标记单元格中的内容包括“This Is a Title”和“This is text.”。代码单元包含两行Python代码。

:width:600px
双击标记单元格以进入编辑模式。在单元格末尾添加一个新的文本字符串“Hello world.”,如 :numref:fig_jupyter02所示。

:width:600px
如 :numref:fig_jupyter03所示,单击菜单栏中的“Cell” “Run Cells”以运行编辑后的单元格。

:width:600px
运行后,markdown单元格如 :numref:fig_jupyter04所示。

:width:600px
接下来,单击代码单元。将最后一行代码后的元素乘以2,如 :numref:fig_jupyter05所示。

:width:600px
你还可以使用快捷键(默认情况下为Ctrl+Enter)运行单元格,并从 :numref:fig_jupyter06获取输出结果。

:width:600px
当一个notebook包含更多单元格时,我们可以单击菜单栏中的“Kernel”“Restart & Run All”来运行整个notebook中的所有单元格。通过单击菜单栏中的“Help”“Edit Keyboard Shortcuts”,可以根据你的首选项编辑快捷键。
高级选项
除了本地编辑,还有两件事非常重要:以markdown格式编辑notebook和远程运行Jupyter。当我们想要在更快的服务器上运行代码时,后者很重要。前者很重要,因为Jupyter原生的ipynb格式存储了大量辅助数据,这些数据实际上并不特定于notebook中的内容,主要与代码的运行方式和运行位置有关。这让git感到困惑,并且使得合并贡献非常困难。幸运的是,还有另一种选择——在markdown中进行本地编辑。
Jupyter中的Markdown文件
如果你希望对本书的内容有所贡献,则需要在GitHub上修改源文件(md文件,而不是ipynb文件)。使用notedown插件,我们可以直接在Jupyter中修改md格式的notebook。
首先,安装notedown插件,运行Jupyter Notebook并加载插件:
pip install d2l-notedown # 你可能需要卸载原始notedown
jupyter notebook --NotebookApp.contents_manager_class='notedown.NotedownContentsManager'
要在运行Jupyter Notebook时默认打开notedown插件,请执行以下操作:首先,生成一个Jupyter Notebook配置文件(如果已经生成了,可以跳过此步骤)。
jupyter notebook --generate-config
然后,在Jupyter Notebook配置文件的末尾添加以下行(对于Linux/macOS,通常位于~/.jupyter/jupyter_notebook_config.py):
c.NotebookApp.contents_manager_class = 'notedown.NotedownContentsManager'
在这之后,你只需要运行jupyter notebook命令就可以默认打开notedown插件。
在远程服务器上运行Jupyter Notebook
有时,你可能希望在远程服务器上运行Jupyter Notebook,并通过本地计算机上的浏览器访问它。如果本地计算机上安装了Linux或MacOS(Windows也可以通过PuTTY等第三方软件支持此功能),则可以使用端口转发:
ssh myserver -L 8888:localhost:8888
以上是远程服务器myserver的地址。然后我们可以使用http://localhost:8888 访问运行Jupyter Notebook的远程服务器myserver。下一节将详细介绍如何在AWS实例上运行Jupyter Notebook。
执行时间
我们可以使用ExecuteTime插件来计算Jupyter Notebook中每个代码单元的执行时间。使用以下命令安装插件:
pip install jupyter_contrib_nbextensions
jupyter contrib nbextension install --user
jupyter nbextension enable execute_time/ExecuteTime
小结
- 使用Jupyter Notebook工具,我们可以编辑、运行和为本书做贡献。
- 使用端口转发在远程服务器上运行Jupyter Notebook。
练习
- 在本地计算机上使用Jupyter Notebook编辑并运行本书中的代码。
- 使用Jupyter Notebook通过端口转发来远程编辑和运行本书中的代码。
- 对于两个方矩阵,测量与在中的运行时间。哪一个更快?
使用Amazon SageMaker
深度学习程序可能需要很多计算资源,这很容易超出你的本地计算机所能提供的范围。云计算服务允许你使用功能更强大的计算机更轻松地运行本书的GPU密集型代码。本节将介绍如何使用Amazon SageMaker运行本书的代码。
注册
首先,我们需要在注册一个帐户https://aws.amazon.com/。 为了增加安全性,鼓励使用双因素身份验证。设置详细的计费和支出警报也是一个好主意,以避免任何意外,例如,当忘记停止运行实例时。登录AWS帐户后,转到console并搜索“Amazon SageMaker”(参见 :numref:fig_sagemaker),然后单击它打开SageMaker面板。

:width:300px
创建SageMaker实例
接下来,让我们创建一个notebook实例,如 :numref:fig_sagemaker-create所示。

:width:400px
SageMaker提供多个具有不同计算能力和价格的实例类型。创建notebook实例时,可以指定其名称和类型。在 :numref:fig_sagemaker-create-2中,我们选择ml.p3.2xlarge:使用一个Tesla V100 GPU和一个8核CPU,这个实例的性能足够本书的大部分内容使用。

:width:400px
用于与SageMaker一起运行的ipynb格式的整本书可从https://github.com/d2l-ai/d2l-pytorch-sagemaker获得。
我们可以指定此GitHub存储库URL( :numref:fig_sagemaker-create-3),以允许SageMaker在创建实例时克隆它。

:width:400px
运行和停止实例
创建实例可能需要几分钟的时间。当实例准备就绪时,单击它旁边的“Open Jupyter”链接( :numref:fig_sagemaker-open),以便你可以在此实例上编辑并运行本书的所有Jupyter Notebook(类似于 :numref:sec_jupyter中的步骤)。

:width:400px
完成工作后,不要忘记停止实例以避免进一步收费( :numref:fig_sagemaker-stop)。

:width:300px
更新Notebook
这本开源书的notebook将定期在GitHub上的d2l-ai/d2l-pytorch-sagemaker存储库中更新。要更新至最新版本,你可以在SageMaker实例( :numref:fig_sagemaker-terminal)上打开终端。

:width:300px
你可能希望在从远程存储库提取更新之前提交本地更改。否则,只需在终端中使用以下命令放弃所有本地更改:
cd SageMaker/d2l-pytorch-sagemaker/
git reset --hard
git pull
小结
- 我们可以使用Amazon SageMaker创建一个GPU的notebook实例来运行本书的密集型代码。
- 我们可以通过Amazon SageMaker实例上的终端更新notebooks。
练习
- 使用Amazon SageMaker编辑并运行任何需要GPU的部分。
- 打开终端以访问保存本书所有notebooks的本地目录。
使用Amazon EC2实例
本节将展示如何在原始Linux机器上安装所有库。回想一下, :numref:sec_sagemaker讨论了如何使用Amazon SageMaker,而在云上自己构建实例的成本更低。本演示包括三个步骤。
- 从AWS EC2请求GPU Linux实例。
- 安装CUDA(或使用预装CUDA的Amazon机器映像)。
- 安装深度学习框架和其他库以运行本书的代码。
此过程也适用于其他实例(和其他云),尽管需要一些细微的修改。在继续操作之前,你需要创建一个AWS帐户,有关更多详细信息,请参阅 :numref:sec_sagemaker。
创建和运行EC2实例
登录到你的aws账户后,单击“EC2”(在 :numref:fig_aws中用红色方框标记)进入EC2面板。

:width:400px
:numref:fig_ec2显示EC2面板,敏感帐户信息变为灰色。

:width:700px
预置位置
选择附近的数据中心以降低延迟,例如“Oregon”(俄勒冈)( :numref:fig_ec2右上角的红色方框)。如果你位于中国,你可以选择附近的亚太地区,例如首尔或东京。请注意,某些数据中心可能没有GPU实例。
增加限制
在选择实例之前,请点击 :numref:fig_ec2所示左侧栏中的“Limits”(限制)标签查看是否有数量限制。 :numref:fig_limits显示了此类限制的一个例子。账号目前无法按地域打开p2.xlarge实例。如果你需要打开一个或多个实例,请点击“Request limit increase”(请求增加限制)链接,申请更高的实例配额。一般来说,需要一个工作日的时间来处理申请。

:width:700px
启动实例
接下来,单击 :numref:fig_ec2中红框标记的“Launch Instance”(启动实例)按钮,启动你的实例。
我们首先选择一个合适的Amazon机器映像(Amazon Machine Image,AMI)。在搜索框中输入“ubuntu”( :numref:fig_ubuntu中的红色框标记)。

:width:700px
EC2提供了许多不同的实例配置可供选择。对初学者来说,这有时会让人感到困惑。 :numref:tab_ec2列出了不同合适的计算机。
:不同的EC2实例类型
| Name | GPU | Notes |
|---|---|---|
| g2 | Grid K520 | 过时的 |
| p2 | Kepler K80 | 旧的GPU但Spot实例通常很便宜 |
| g3 | Maxwell M60 | 好的平衡 |
| p3 | Volta V100 | FP16的高性能 |
| g4 | Turing T4 | FP16/INT8推理优化 |
所有这些服务器都有多种类型,显示了使用的GPU数量。例如,p2.xlarge有1个GPU,而p2.16xlarge有16个GPU和更多内存。有关更多详细信息,请参阅Amazon EC2 文档。

:width:700px
注意,你应该使用支持GPU的实例以及合适的驱动程序和支持GPU的深度学习框架。否则,你将感受不到使用GPU的任何好处。
到目前为止,我们已经完成了启动EC2实例的七个步骤中的前两个步骤,如 :numref:fig_disk顶部所示。在本例中,我们保留“3. Configure Instance”(3. 配置实例)、“5. Add Tags”(5. 添加标签)和“6. Configure Security Group”(6. 配置安全组)步骤的默认配置。点击“4.添加存储”并将默认硬盘大小增加到64GB( :numref:fig_disk中的红色框标记)。请注意,CUDA本身已经占用了4GB空间。

:width:700px
最后,进入“7. Review”(7. 查看),点击“Launch”(启动),即可启动配置好的实例。系统现在将提示你选择用于访问实例的密钥对。如果你没有密钥对,请在 :numref:fig_keypair的第一个下拉菜单中选择“Create a new key pair”(新建密钥对),即可生成密钥对。之后,你可以在此菜单中选择“Choose an existing key pair”(选择现有密钥对),然后选择之前生成的密钥对。单击“Launch Instances”(启动实例)即可启动创建的实例。

:width:500px
如果生成了新密钥对,请确保下载密钥对并将其存储在安全位置。这是你通过SSH连接到服务器的唯一方式。单击 :numref:fig_launching中显示的实例ID可查看该实例的状态。

:width:700px
连接到实例
如 :numref:fig_connect所示,实例状态变为绿色后,右键单击实例,选择Connect(连接)查看实例访问方式。

:width:700px
如果这是一个新密钥,它必须是不可公开查看的,SSH才能工作。转到存储D2L_key.pem的文件夹,并执行以下命令以使密钥不可公开查看:
chmod 400 D2L_key.pem

:width:400px
现在,复制 :numref:fig_chmod下方红色框中的ssh命令并粘贴到命令行:
ssh -i "D2L_key.pem" ubuntu@ec2-xx-xxx-xxx-xxx.y.compute.amazonaws.com
当命令行提示“Are you sure you want to continue connecting (yes/no)”(“你确定要继续连接吗?(是/否)”)时,输入“yes”并按回车键登录实例。
你的服务器现在已就绪。
安装CUDA
在安装CUDA之前,请确保使用最新的驱动程序更新实例。
sudo apt-get update && sudo apt-get install -y build-essential git libgfortran3
我们在这里下载CUDA 10.1。访问NVIDIA的官方存储库 以找到下载链接,如 :numref:fig_cuda中所示。

:width:500px
将说明复制粘贴到终端上,以安装CUDA 10.1。
# 链接和文件名可能会发生更改,以NVIDIA的官方为准
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-ubuntu1804.pin
sudo mv cuda-ubuntu1804.pin /etc/apt/preferences.d/cuda-repository-pin-600
wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-ubuntu1804-10-1-local-10.1.243-418.87.00_1.0-1_amd64.deb
sudo dpkg -i cuda-repo-ubuntu1804-10-1-local-10.1.243-418.87.00_1.0-1_amd64.deb
sudo apt-key add /var/cuda-repo-10-1-local-10.1.243-418.87.00/7fa2af80.pub
sudo apt-get update
sudo apt-get -y install cuda
安装程序后,运行以下命令查看GPU:
nvidia-smi
最后,将CUDA添加到库路径以帮助其他库找到它。
echo "export LD_LIBRARY_PATH=\${LD_LIBRARY_PATH}:/usr/local/cuda/lib64" >> ~/.bashrc
安装库以运行代码
要运行本书的代码,只需在EC2实例上为linux用户执行 :ref:chap_installation中的步骤,并使用以下提示在远程linux服务器上工作。
- 要在Miniconda安装页面下载bash脚本,请右击下载链接并选择“copy Link address”,然后执行
wget [copied link address]。 - 运行
~/miniconda3/bin/conda init, 你可能需要执行source~/.bashrc,而不是关闭并重新打开当前shell。
远程运行Jupyter笔记本
要远程运行Jupyter笔记本,你需要使用SSH端口转发。毕竟,云中的服务器没有显示器或键盘。为此,请从你的台式机(或笔记本电脑)登录到你的服务器,如下所示:
# 此命令必须在本地命令行中运行
ssh -i "/path/to/key.pem" ubuntu@ec2-xx-xxx-xxx-xxx.y.compute.amazonaws.com -L 8889:localhost:8888
接下来,转到EC2实例上本书下载的代码所在的位置,然后运行:
conda activate d2l
jupyter notebook
:numref:fig_jupyter显示了运行Jupyter笔记本后可能的输出。最后一行是端口8888的URL。

:width:700px
由于你使用端口转发到端口8889,请复制 :numref:fig_jupyter红色框中的最后一行,将URL中的“8888”替换为“8889”,然后在本地浏览器中打开它。
关闭未使用的实例
由于云服务是按使用时间计费的,你应该关闭不使用的实例。请注意,还有其他选择:
- “Stopping”(停止)实例意味着你可以重新启动它。这类似于关闭常规服务器的电源。但是,停止的实例仍将按保留的硬盘空间收取少量费用;
- “Terminating”(终止)实例将删除与其关联的所有数据。这包括磁盘,因此你不能再次启动它。只有在你知道将来不需要它的情况下才这样做。
如果你想要将该实例用作更多实例的模板,请右击 :numref:fig_connect中的例子,然后选择“Image”“Create”以创建该实例的镜像。完成后,选择“实例状态”“终止”以终止实例。下次要使用此实例时,可以按照本节中的步骤基于保存的镜像创建实例。唯一的区别是,在 :numref:fig_ubuntu所示的“1.选择AMI”中,你必须使用左侧的“我的AMI”选项来选择你保存的镜像。创建的实例将保留镜像硬盘上存储的信息。例如,你不必重新安装CUDA和其他运行时环境。
小结
- 我们可以按需启动和停止实例,而不必购买和制造我们自己的计算机。
- 在使用支持GPU的深度学习框架之前,我们需要安装CUDA。
- 我们可以使用端口转发在远程服务器上运行Jupyter笔记本。
练习
- 云提供了便利,但价格并不便宜。了解如何启动spot实例以降低成本。
- 尝试使用不同的GPU服务器。它们有多快?
- 尝试使用多GPU服务器。你能把事情扩大到什么程度?
选择服务器和GPU
深度学习训练通常需要大量的计算。目前,GPU是深度学习最具成本效益的硬件加速器。与CPU相比,GPU更便宜,性能更高,通常超过一个数量级。此外,一台服务器可以支持多个GPU,高端服务器最多支持8个GPU。更典型的数字是工程工作站最多4个GPU,这是因为热量、冷却和电源需求会迅速增加,超出办公楼所能支持的范围。对于更大的部署,云计算(例如亚马逊的P3和G4实例)是一个更实用的解决方案。
选择服务器
通常不需要购买具有多个线程的高端CPU,因为大部分计算都发生在GPU上。这就是说,由于Python中的全局解释器锁(GIL),CPU的单线程性能在有4-8个GPU的情况下可能很重要。所有的条件都是一样的,这意味着核数较少但时钟频率较高的CPU可能是更经济的选择。例如,当在6核4GHz和8核3.5GHz CPU之间进行选择时,前者更可取,即使其聚合速度较低。一个重要的考虑因素是,GPU使用大量的电能,从而释放大量的热量。这需要非常好的冷却和足够大的机箱来容纳GPU。如有可能,请遵循以下指南:
- 电源。GPU使用大量的电源。每个设备预计高达350W(检查显卡的峰值需求而不是一般需求,因为高效代码可能会消耗大量能源)。如果电源不能满足需求,系统会变得不稳定。
- 机箱尺寸。GPU很大,辅助电源连接器通常需要额外的空间。此外,大型机箱更容易冷却。
- GPU散热。如果有大量的GPU,可能需要投资水冷。此外,即使风扇较少,也应以“公版设计”为目标,因为它们足够薄,可以在设备之间进气。当使用多风扇GPU,安装多个GPU时,它可能太厚而无法获得足够的空气。
- PCIe插槽。在GPU之间来回移动数据(以及在GPU之间交换数据)需要大量带宽。建议使用16通道的PCIe 3.0插槽。当安装了多个GPU时,请务必仔细阅读主板说明,以确保在同时使用多个GPU时16带宽仍然可用,并且使用的是PCIe3.0,而不是用于附加插槽的PCIe2.0。在安装多个GPU的情况下,一些主板的带宽降级到8甚至4。这部分是由于CPU提供的PCIe通道数量限制。
简而言之,以下是构建深度学习服务器的一些建议。
- 初学者。购买低功耗的低端GPU(适合深度学习的廉价游戏GPU,功耗150-200W)。如果幸运的话,大家现在常用的计算机将支持它。
- 1个GPU。一个4核的低端CPU就足够了,大多数主板也足够了。以至少32 GB的DRAM为目标,投资SSD进行本地数据访问。600W的电源应足够。买一个有很多风扇的GPU。
- 2个GPU。一个4-6核的低端CPU就足够了。可以考虑64 GB的DRAM并投资于SSD。两个高端GPU将需要1000瓦的功率。对于主板,请确保它们具有两个PCIe 3.0 x16插槽。如果可以,请使用PCIe 3.0 x16插槽之间有两个可用空间(60毫米间距)的主板,以提供额外的空气。在这种情况下,购买两个具有大量风扇的GPU。
- 4个GPU。确保购买的CPU具有相对较快的单线程速度(即较高的时钟频率)。可能需要具有更多PCIe通道的CPU,例如AMD Threadripper。可能需要相对昂贵的主板才能获得4个PCIe 3.0 x16插槽,因为它们可能需要一个PLX来多路复用PCIe通道。购买带有公版设计的GPU,这些GPU很窄,并且让空气进入GPU之间。需要一个1600-2000W的电源,而办公室的插座可能不支持。此服务器可能在运行时声音很大,很热。不想把它放在桌子下面。建议使用128 GB的DRAM。获取一个用于本地存储的SSD(1-2 TB NVMe)和RAID配置的硬盘来存储数据。
- 8 GPU。需要购买带有多个冗余电源的专用多GPU服务器机箱(例如,每个电源为1600W时为2+1)。这将需要双插槽服务器CPU、256 GB ECC DRAM、快速网卡(建议使用10 GBE),并且需要检查服务器是否支持GPU的物理外形。用户GPU和服务器GPU之间的气流和布线位置存在显著差异(例如RTX 2080和Tesla V100)。这意味着可能无法在服务器中安装消费级GPU,因为电源线间隙不足或缺少合适的接线(本书一位合著者痛苦地发现了这一点)。
选择GPU
目前,AMD和NVIDIA是专用GPU的两大主要制造商。NVIDIA是第一个进入深度学习领域的公司,通过CUDA为深度学习框架提供更好的支持。因此,大多数买家选择NVIDIA GPU。
NVIDIA提供两种类型的GPU,针对个人用户(例如,通过GTX和RTX系列)和企业用户(通过其Tesla系列)。这两种类型的GPU提供了相当的计算能力。但是,企业用户GPU通常使用强制(被动)冷却、更多内存和ECC(纠错)内存。这些GPU更适用于数据中心,通常成本是消费者GPU的十倍。
如果是一个拥有100个服务器的大公司,则应该考虑英伟达Tesla系列,或者在云中使用GPU服务器。对于实验室或10+服务器的中小型公司,英伟达RTX系列可能是最具成本效益的,可以购买超微或华硕机箱的预配置服务器,这些服务器可以有效地容纳4-8个GPU。
GPU供应商通常每一到两年发布一代,例如2017年发布的GTX 1000(Pascal)系列和2019年发布的RTX 2000(Turing)系列。每个系列都提供几种不同的型号,提供不同的性能级别。GPU性能主要是以下三个参数的组合:
- 计算能力。通常大家会追求32位浮点计算能力。16位浮点训练(FP16)也进入主流。如果只对预测感兴趣,还可以使用8位整数。最新一代图灵GPU提供4-bit加速。不幸的是,目前训练低精度网络的算法还没有普及;
- 内存大小。随着模型变大或训练期间使用的批量变大,将需要更多的GPU内存。检查HBM2(高带宽内存)与GDDR6(图形DDR)内存。HBM2速度更快,但成本更高;
- 内存带宽。当有足够的内存带宽时,才能最大限度地利用计算能力。如果使用GDDR6,请追求宽内存总线。
对于大多数用户,只需看看计算能力就足够了。请注意,许多GPU提供不同类型的加速。例如,NVIDIA的Tensor Cores将操作符子集的速度提高了5。确保所使用的库支持这一点。GPU内存应不小于4GB(8GB更好)。尽量避免将GPU也用于显示GUI(改用内置显卡)。如果无法避免,请添加额外的2GB RAM以确保安全。
:numref:fig_flopsvsprice比较了各种GTX 900、GTX 1000和RTX 2000系列的(GFlops)和价格(Price)。价格是维基百科上的建议价格。
由上图,可以看出很多事情:
- 在每个系列中,价格和性能大致成比例。Titan因拥有大GPU内存而有相当的溢价。然而,通过比较980 Ti和1080 Ti可以看出,较新型号具有更好的成本效益。RTX 2000系列的价格似乎没有多大提高。然而,它们提供了更优秀的低精度性能(FP16、INT8和INT4);
- GTX 1000系列的性价比大约是900系列的两倍;
- 对于RTX 2000系列,浮点计算能力是价格的“仿射”函数。
:numref:fig_wattvsprice显示了能耗与计算量基本成线性关系。其次,后一代更有效率。这似乎与对应于RTX 2000系列的图表相矛盾。然而,这是TensorCore不成比例的大能耗的结果。
小结
- 在构建服务器时,请注意电源、PCIe总线通道、CPU单线程速度和散热。
- 如果可能,应该购买最新一代的GPU。
- 使用云进行大型部署。
- 高密度服务器可能不与所有GPU兼容。在购买之前,请检查一下机械和散热规格。
- 为提高效率,请使用FP16或更低的精度。
为本书做贡献
读者们的投稿大大帮助我们改进了本书的质量。
如果你发现笔误、无效的链接、一些你认为我们遗漏了引文的地方,
代码看起来不优雅,或者解释不清楚的地方,请回复我们以帮助读者。
在常规书籍中,两次印刷之间的间隔(即修订笔误的间隔)常常需要几年,
但这本书的改进通常需要几小时到几天的时间。
由于版本控制和持续自动集成(CI)测试,这一切颇为高效。
为此,你需要向gihub存储库提交一个
pull request。
当你的pull请求被作者合并到代码库中时,
你将成为贡献者。
提交微小更改
最常见的贡献是编辑一句话或修正笔误。
我们建议你在GitHub存储库
中查找源文件,以定位源文件(一个markdown文件)。
然后单击右上角的“Edit this file”按钮,在markdown文件中进行更改。

:width:300px
完成后,在页面底部的“Propose file change”(“提交文件修改”)
面板中填写更改说明,然后单击“Propose file change”按钮。
它会重定向到新页面以查看你的更改( :numref:fig_git_createpr)。
如果一切正常,你可以通过点击“Create pull request”按钮提交pull请求。
大量文本或代码修改
如果你计划修改大量文本或代码,那么你需要更多地了解本书使用的格式。
源文件基于markdown格式,
并通过d2lbook包提供了一组扩展,
例如引用公式、图像、章节和引文。
你可以使用任何markdown编辑器打开这些文件并进行更改。
如果你想要更改代码,我们建议你使用Jupyter Notebook打开这些标记文件,
如 :numref:sec_jupyter中所述。
这样你就可以运行并测试你的更改。
请记住在提交更改之前清除所有输出,我们的CI系统将执行你更新的部分以生成输出。
某些部分可能支持多个框架实现。如果你添加的新代码块不是使用mxnet,
请使用#@tab来标记代码块的起始行。
例如#@tab pytorch用于一个PyTorch代码块,
#@tab tensorflow用于一个TensorFlow代码块,
#@tab paddle用于一个PaddlePaddle代码块,
或者#@tab all是所有实现的共享代码块。
你可以参考d2lbook包了解更多信息。
提交主要更改
我们建议你使用标准的Git流程提交大量修改。
简而言之,该过程的工作方式如 :numref:fig_contribute中所述。
我们将向你详细介绍这些步骤。
如果你已经熟悉Git,可以跳过本部分。
在介绍时,我们假设贡献者的用户名为“astonzhang”。
安装Git
Git开源书籍描述了如何安装git。
这通常通过Ubuntu Linux上的apt install git,
在MacOS上安装Xcode开发人员工具或使用gihub的
桌面客户端来实现。
如果你没有GitHub帐户,则需要注册一个帐户。
登录GitHub
在浏览器中输入本书代码存储库的地址。
单击 :numref:fig_git_fork右上角红色框中的Fork按钮,以复制本书的存储库。
这将是你的副本,你可以随心所欲地更改它。

:width:700px
现在,本书的代码库将被分叉(即复制)到你的用户名,
例如astonzhang/d2l-en显示在 :numref:fig_git_forked的左上角。

:width:700px
克隆存储库
要克隆存储库(即制作本地副本),我们需要获取其存储库地址。
点击 :numref:fig_git_clone中的绿色按钮显示此信息。
如果你决定将此分支保留更长时间,请确保你的本地副本与主存储库保持最新。
现在,只需按照 :ref:chap_installation中的说明开始。
主要区别在于,你现在下载的是你自己的存储库分支。

:width:700px
# 将your_github_username替换为你的github用户名
git clone https://github.com/your_github_username/d2l-en.git
编辑和推送
现在是编辑这本书的时候了。最好按照 :numref:sec_jupyter中的说明在Jupyter Notebook中编辑它。进行更改并检查它们是否正常。假设我们已经修改了文件~/d2l-en/chapter_appendix_tools/how-to-contribute.md中的一个拼写错误。你可以检查你更改了哪些文件。
此时,Git将提示chapter_appendix_tools/how-to-contribute.md文件已被修改。
mylaptop:d2l-en me$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: chapter_appendix_tools/how-to-contribute.md
在确认这是你想要的之后,执行以下命令:
git add chapter_appendix_tools/how-to-contribute.md
git commit -m 'fix typo in git documentation'
git push
然后,更改后的代码将位于存储库的个人分支中。要请求添加更改,你必须为本书的官方存储库创建一个Pull请求。
提交Pull请求
如 :numref:fig_git_newpr所示,进入gihub上的存储库分支,选择“New pull request”。这将打开一个页面,显示你的编辑与本书主存储库中的当前内容之间的更改。

:width:700px
最后,单击按钮提交Pull请求,如 :numref:fig_git_createpr所示。请务必描述你在Pull请求中所做的更改。这将使作者更容易审阅它,并将其与本书合并。根据更改的不同,这可能会立即被接受,也可能会被拒绝,或者更有可能的是,你会收到一些关于更改的反馈。一旦你把它们合并了,你就做完了。

:width:700px
小结
- 你可以使用GitHub为本书做贡献。
- 你可以直接在GitHub上编辑文件以进行微小更改。
- 要进行重大更改,请分叉存储库,在本地编辑内容,并在准备好后再做出贡献。
- 尽量不要提交巨大的Pull请求,因为这会使它们难以理解和合并。最好拆分为几个小一点的。
练习
- 启动并分叉
d2l-ai/d2l-en存储库。 - 如果发现任何需要改进的地方(例如,缺少引用),请提交Pull请求。
- 通常更好的做法是使用新分支创建Pull请求。学习如何用Git分支来做这件事。
d2l API 文档
d2l包以下成员的实现及其定义和解释部分可在源文件中找到。