Compare commits

..

48 Commits

Author SHA1 Message Date
Aston Zhang e6b18ccea7
Update frontpage.html 2023-08-17 21:59:12 -07:00
Aston Zhang 52c82e8d30
Update README.md 2023-08-17 21:58:34 -07:00
Aston Zhang 5ce505e58d
Update README.md 2023-08-17 21:53:55 -07:00
Aston Zhang 23b97b2888
Update frontpage.html 2023-08-17 21:52:38 -07:00
Aston Zhang 5a882e7e6d mv img/frontpage to static/frontpage/_images/sales 2023-08-18 01:38:34 +00:00
Anirudh Dagar 0cef09e6f1
Use d2lbook==1.0.0 for all containers 2023-08-18 00:53:39 +02:00
Aston Zhang ca095bd3c7
Update README.md 2023-08-17 15:48:24 -07:00
Anirudh Dagar 8a621eba83
CI: Remove Jenkins (#1283)
[skip CI]
2023-08-13 16:31:08 +02:00
Aston Zhang 3a176e1f52
Update frontpage.html 2023-08-13 01:12:35 -07:00
Anirudh Dagar 3f26ae50b1
CI: pin d2l==0.17.6 and numpy==1.24.4 for torch build 2023-08-10 20:30:18 +02:00
Anirudh Dagar 78b0fc66cc
BLD: Fix glove latex error pdf build 2023-08-10 18:32:32 +02:00
Anirudh Dagar be5d0272a9
CI: Fix paddle dockerfile add opencv deps
[skip torch] [skip tf] [skip mxnet]
2023-08-09 19:25:19 +02:00
Anirudh Dagar 75dfd08fac
CI: Fix d2l-zh-paddle dockerfile opencv requirement
[skip torch] [skip tf] [skip mxnet]
2023-08-09 18:53:11 +02:00
Anirudh Dagar 54f324a261
CI: Enable paddle paddle evaluation
Follow up #1281
Adds the missing evaluation of paddlepaddle in the D2L Infra 2.0 for d2l-zh.
2023-08-09 17:43:12 +02:00
Anirudh Dagar e709c64883
PyTorch: Fix SGD ValueError 2023-08-09 17:09:43 +02:00
Anirudh Dagar 042c11c11c
PyTorch: Fix meshgrid indexing 2023-08-09 16:13:56 +02:00
Anirudh Dagar 2f69aef391
CI: Fix cache directory; mxnet is default 2023-08-09 16:12:13 +02:00
Anirudh Dagar ffffd94d2c
CI: Fix pytorch use newer numpy version 2023-08-09 15:07:01 +02:00
Anirudh Dagar ad3cf0bc1a
CI: remove jax requirement for d2l-builder 2023-08-09 14:02:56 +02:00
Anirudh Dagar b28579262f
CI: Setup D2L Infra 2.0 with Github Actions (#1281)
* CI: Setup github actions

* Sync d2l lib; fix movielens and pandas

* CI: Fix job definition naming

* CI: only release support required
2023-08-09 14:00:00 +02:00
Aston Zhang 5c53925063 update 2023-05-05 12:46:47 -07:00
Aston Zhang 6c6bda362b rm 2023-05-05 12:46:10 -07:00
Aston Zhang 34861319c8
Add files via upload 2023-05-05 12:44:13 -07:00
Aston Zhang 0360e5ebb4 Update mapping 2023-05-05 12:41:00 -07:00
Aston Zhang acf461ecbe map jd-20230208-zh-6.png to 020304 2023-05-05 12:33:13 -07:00
Aston Zhang b963ae034f Add 02--04 2023-05-05 12:18:36 -07:00
Aston Zhang 769c1d8dc0 frontpage imgs 2023-04-19 19:51:47 -07:00
Aston Zhang 05a1d1c3d0
add all AI 2023-04-19 19:45:56 -07:00
Aston Zhang 1aca2e93d3
Link jd-20230208-zh-6 to jd-202303-zh-6 2023-04-19 19:34:42 -07:00
Aston Zhang 63f849dee4
Add files via upload 2023-04-19 19:33:53 -07:00
Aston Zhang e892e3903c
Link jd-20230208-zh-6 to jd-202303-zh-6.png 2023-04-19 19:32:03 -07:00
Aston Zhang 92d97a17e5
Add files via upload 2023-04-19 19:31:23 -07:00
Aston Zhang 2fec870b99 Update allsales 2023-03-02 20:38:13 -08:00
Aston Zhang c982e012bd Link jd-20230208-zh-6 to jd-202302-zh-4.png 2023-03-02 20:34:55 -08:00
Aston Zhang 634d1663de
Add files via upload 2023-03-02 20:32:24 -08:00
Aston Zhang 68575f3af9 Add weekly bestseller 2023-02-12 22:25:07 -08:00
Aston Zhang bd5e1457ed
Update frontpage.html 2023-02-08 20:30:34 -08:00
Aston Zhang 6b74f705f6
Add jd ranking 2023-02-08 20:28:34 -08:00
Aston Zhang 152196db0c Revert "Disable deploy slides"
This reverts commit e2fafe47ff.
2023-02-07 00:26:53 +00:00
Aston Zhang e2fafe47ff
Disable deploy slides 2023-02-06 15:57:21 -08:00
Aston Zhang de50356c94
Add 2e hardcopy links 2023-02-06 14:56:06 -08:00
Aston Zhang dd095aea4c
Update frontpage.html 2023-01-30 11:19:31 -08:00
Aston Zhang c434459ca8
Update frontpage.html 2023-01-08 22:27:12 -08:00
Aston Zhang e3803379ee
Update parameterserver.md 2023-01-08 16:10:47 -08:00
Aston Zhang d76784d558
Update parameterserver.md 2023-01-08 16:10:28 -08:00
Aston Zhang 88506b89a4
Update adadelta.md 2023-01-08 16:09:39 -08:00
Aston Zhang efd2940cf3
Update numerical-stability-and-init.md 2023-01-08 16:08:42 -08:00
Yuan Tang ac0e460707
Update my affiliation (#1233) 2022-12-08 11:51:24 -08:00
61 changed files with 2436 additions and 1485 deletions

View File

@ -0,0 +1,57 @@
name: "Setup Env Vars"
runs:
using: "composite"
steps:
- name: Get Commit SHA (For Push Event)
if: ${{ github.event_name == 'push' }}
shell: bash
env:
SHA: ${{ github.sha }}
git_repo_full: ${{ github.repository }}
pr_number: ""
run: |
short_sha=$(git rev-parse --short "$SHA")
echo "SHORT_SHA=$short_sha" >> $GITHUB_ENV
echo "PR_NUMBER=$pr_number" >> $GITHUB_ENV
target_branch=${GITHUB_REF##*/}
echo "TARGET_BRANCH=$target_branch" >> $GITHUB_ENV
repo_name=${git_repo_full##*/}
echo "REPO_NAME=$repo_name" >> $GITHUB_ENV
IFS='-' read -ra name_parts <<< "$repo_name"
echo "LANG=${name_parts[1]}" >> $GITHUB_ENV
job_name=${repo_name}/${target_branch}
echo "JOB_NAME=$job_name" >> $GITHUB_ENV
echo "CACHE_DIR=ci_cache_push" >> $GITHUB_ENV
- name: Get Commit SHA (For Pull Request)
if: ${{ github.event_name == 'pull_request_target' }}
shell: bash
env:
SHA: ${{ github.event.pull_request.head.sha }}
target_branch: ${{ github.event.pull_request.base.ref }}
git_repo_full: ${{ github.event.pull_request.base.repo.full_name }}
pr_number: PR-${{ github.event.number }}
run: |
short_sha=$(git rev-parse --short "$SHA")
echo "SHORT_SHA=$short_sha" >> $GITHUB_ENV
echo "PR_NUMBER=$pr_number" >> $GITHUB_ENV
echo "TARGET_BRANCH=$target_branch" >> $GITHUB_ENV
repo_name=${git_repo_full##*/}
echo "REPO_NAME=$repo_name" >> $GITHUB_ENV
IFS='-' read -ra name_parts <<< "$repo_name"
echo "LANG=${name_parts[1]}" >> $GITHUB_ENV
job_name=${repo_name}/${pr_number}/${short_sha}
echo "JOB_NAME=$job_name" >> $GITHUB_ENV
echo "CACHE_DIR=ci_cache_pr" >> $GITHUB_ENV

91
.github/actions/submit-job/action.yml vendored Normal file
View File

@ -0,0 +1,91 @@
name: "Submit Job to AWS Batch"
inputs:
job-type:
required: true
job-name:
required: true
work-dir:
required: false
default: .
command:
required: true
runs:
using: "composite"
steps:
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: arn:aws:iam::650140442593:role/D2L_CI_Batch
role-duration-seconds: 14400 # this requires changing max session duration to 4hrs in AWS Console for D2L_CI_Batch
aws-region: us-west-2
- name: Install dependencies
shell: bash
run: |
pip install boto3
- name: Check for Actor Permissions
id: check
continue-on-error: true
uses: prince-chrismc/check-actor-permissions-action@88995341900ae4e7aa248df51d32aeb981cc62f5 # v2
with:
github_token: ${{ github.token }}
permission: write
- name: Submit Job (For Push on development branches)
if: ${{ github.event_name == 'push' && github.ref != 'refs/heads/release' && github.ref != 'refs/heads/classic' }}
shell: bash
run: |
echo "Start submitting job for a Push Event on a Development Branch"
# Add "-push" for all these jobs to use elevated push level job-def permissions
python ./ci/submit-job.py --job-type ${{ inputs.job-type }}-push \
--name ${{ inputs.job-name }}-'${{ github.ref }}' \
--source-ref '${{ github.ref }}' \
--work-dir ${{ inputs.work-dir }} \
--remote https://github.com/'${{ github.repository }}' \
--command "${{ inputs.command }}" \
--safe-to-use-script \
--wait
- name: Submit Job (For Push on Release/Classic)
if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/release' || github.ref == 'refs/heads/classic') }}
shell: bash
run: |
echo "Start submitting job for a Push Event on Release/Classic Branch"
# Add "-release" for all these jobs to use elevated release level job-def permissions
python ./ci/submit-job.py --job-type ${{ inputs.job-type }}-release \
--name ${{ inputs.job-name }}-'${{ github.ref }}' \
--source-ref '${{ github.ref }}' \
--work-dir ${{ inputs.work-dir }} \
--remote https://github.com/'${{ github.repository }}' \
--command "${{ inputs.command }}" \
--safe-to-use-script \
--wait
- name: Submit Job (For Pull Request Safe Scripts)
if: ${{ github.event_name == 'pull_request_target' && steps.check.outputs.permitted == 'true' }}
shell: bash
run: |
echo "Start submitting job for PR Safe Scripts"
python ./ci/submit-job.py --job-type ${{ inputs.job-type }} \
--name ${{ inputs.job-name }}-PR#'${{ github.event.number }}' \
--source-ref '${{ github.event.pull_request.head.sha }}' \
--work-dir ${{ inputs.work-dir }} \
--remote https://github.com/'${{ github.event.pull_request.head.repo.full_name }}' \
--command "${{ inputs.command }}" \
--safe-to-use-script \
--wait
- name: Submit Job (For Pull Request Not Safe Scripts)
if: ${{ github.event_name == 'pull_request_target' && steps.check.outputs.permitted != 'true' }}
shell: bash
run: |
echo "Start submitting job for PR Unsafe Scripts"
python ./ci/submit-job.py --job-type ${{ inputs.job-type }} \
--name ${{ inputs.job-name }}-PR#'${{ github.event.number }}' \
--source-ref '${{ github.event.pull_request.head.sha }}' \
--work-dir ${{ inputs.work-dir }} \
--remote https://github.com/'${{ github.event.pull_request.head.repo.full_name }}' \
--command "${{ inputs.command }}" \
--wait

45
.github/workflow_scripts/build_and_deploy.sh vendored Executable file
View File

@ -0,0 +1,45 @@
#!/bin/bash
# Move all scripts related to html here!
set -ex
REPO_NAME="$1" # Eg. 'd2l-zh'
TARGET_BRANCH="$2" # Eg. 'master' ; if PR raised to master
JOB_NAME="$3" # Eg. 'd2l-zh/master' or 'd2l-zh/PR-2453/21be1a4'
LANG="$4" # Eg. 'en','zh' etc.
CACHE_DIR="$5" # Eg. 'ci_cache_pr' or 'ci_cache_push'
pip3 install d2l==0.17.6
mkdir _build
source $(dirname "$0")/utils.sh
# Move aws copy commands for cache restore outside
measure_command_time "aws s3 sync s3://preview.d2l.ai/"$CACHE_DIR"/"$REPO_NAME"-"$TARGET_BRANCH"/_build _build --delete --quiet --exclude 'eval*/data/*'"
# Build D2L Website
./.github/workflow_scripts/build_html.sh
# Build PDFs
d2lbook build pdf
d2lbook build pdf --tab pytorch
# Check if the JOB_NAME is "$REPO_NAME/release"
if [[ "$JOB_NAME" == "$REPO_NAME/release" ]]; then
# Setup D2L Bot
source $(dirname "$0")/setup_git.sh
setup_git
d2lbook build pkg
d2lbook deploy html pdf pkg colab sagemaker slides --s3 "s3://${LANG}-v2.d2l.ai/"
else
# Run d2lbook preview deployment
d2lbook deploy html pdf --s3 "s3://preview.d2l.ai/${JOB_NAME}/"
fi
# Move aws copy commands for cache store outside
measure_command_time "aws s3 sync _build s3://preview.d2l.ai/"$CACHE_DIR"/"$REPO_NAME"-"$TARGET_BRANCH"/_build --acl public-read --quiet --exclude 'eval*/data/*'"

44
.github/workflow_scripts/build_mxnet.sh vendored Normal file
View File

@ -0,0 +1,44 @@
#!/bin/bash
set -ex
# Used to capture status exit of build eval command
ss=0
REPO_NAME="$1" # Eg. 'd2l-zh'
TARGET_BRANCH="$2" # Eg. 'master' ; if PR raised to master
CACHE_DIR="$3" # Eg. 'ci_cache_pr' or 'ci_cache_push'
pip3 install d2l==0.17.6
mkdir _build
source $(dirname "$0")/utils.sh
# Move sanity check outside
d2lbook build outputcheck tabcheck
# Move aws copy commands for cache restore outside
if [ "$DISABLE_CACHE" = "false" ]; then
echo "Retrieving mxnet build cache from "$CACHE_DIR""
measure_command_time "aws s3 sync s3://preview.d2l.ai/"$CACHE_DIR"/"$REPO_NAME"-"$TARGET_BRANCH"/_build/eval/ _build/eval/ --delete --quiet --exclude 'data/*'"
fi
# MXNet training for the following notebooks is slow in the container;
# Setting NTHREADS=4 below seems to fix the issue:
# 1. chapter_multilayer-perceptrons/dropout.md
# 2. chapter_multilayer-perceptrons/mlp-implementation.md
# 3. chapter_linear-classification/softmax-regression-concise.md
# 4. chapter_linear-classification/softmax-regression-scratch.md
export MXNET_CPU_WORKER_NTHREADS=4
# Continue the script even if some notebooks in build fail to
# make sure that cache is copied to s3 for the successful notebooks
d2lbook build eval || ((ss=1))
# Move aws copy commands for cache store outside
echo "Upload mxnet build cache to s3"
measure_command_time "aws s3 sync _build s3://preview.d2l.ai/"$CACHE_DIR"/"$REPO_NAME"-"$TARGET_BRANCH"/_build --acl public-read --quiet --exclude 'eval*/data/*'"
# Exit with a non-zero status if evaluation failed
if [ "$ss" -ne 0 ]; then
exit 1
fi

View File

@ -0,0 +1,37 @@
#!/bin/bash
set -ex
# Used to capture status exit of build eval command
ss=0
REPO_NAME="$1" # Eg. 'd2l-zh'
TARGET_BRANCH="$2" # Eg. 'master' ; if PR raised to master
CACHE_DIR="$3" # Eg. 'ci_cache_pr' or 'ci_cache_push'
pip3 install d2l==0.17.6
mkdir _build
source $(dirname "$0")/utils.sh
# Move sanity check outside
d2lbook build outputcheck tabcheck
# Move aws copy commands for cache restore outside
if [ "$DISABLE_CACHE" = "false" ]; then
echo "Retrieving paddle build cache from "$CACHE_DIR""
measure_command_time "aws s3 sync s3://preview.d2l.ai/"$CACHE_DIR"/"$REPO_NAME"-"$TARGET_BRANCH"/_build/eval_paddle/ _build/eval_paddle/ --delete --quiet --exclude 'data/*'"
fi
# Continue the script even if some notebooks in build fail to
# make sure that cache is copied to s3 for the successful notebooks
d2lbook build eval --tab paddle || ((ss=1))
# Move aws copy commands for cache store outside
echo "Upload paddle build cache to s3"
measure_command_time "aws s3 sync _build s3://preview.d2l.ai/"$CACHE_DIR"/"$REPO_NAME"-"$TARGET_BRANCH"/_build --acl public-read --quiet --exclude 'eval*/data/*'"
# Exit with a non-zero status if evaluation failed
if [ "$ss" -ne 0 ]; then
exit 1
fi

View File

@ -0,0 +1,41 @@
#!/bin/bash
set -ex
# Used to capture status exit of build eval command
ss=0
REPO_NAME="$1" # Eg. 'd2l-zh'
TARGET_BRANCH="$2" # Eg. 'master' ; if PR raised to master
CACHE_DIR="$3" # Eg. 'ci_cache_pr' or 'ci_cache_push'
pip3 install d2l==0.17.6
pip3 install numpy==1.24.4 # numpy version installed by d2l==0.17.6 is too old
mkdir _build
source $(dirname "$0")/utils.sh
# Move sanity check outside
d2lbook build outputcheck tabcheck
# Move aws copy commands for cache restore outside
if [ "$DISABLE_CACHE" = "false" ]; then
echo "Retrieving pytorch build cache from "$CACHE_DIR""
measure_command_time "aws s3 sync s3://preview.d2l.ai/"$CACHE_DIR"/"$REPO_NAME"-"$TARGET_BRANCH"/_build/eval_pytorch/ _build/eval_pytorch/ --delete --quiet --exclude 'data/*'"
echo "Retrieving pytorch slides cache from "$CACHE_DIR""
aws s3 sync s3://preview.d2l.ai/"$CACHE_DIR"/"$REPO_NAME"-"$TARGET_BRANCH"/_build/slides _build/slides --delete --quiet --exclude 'data/*'
fi
# Continue the script even if some notebooks in build fail to
# make sure that cache is copied to s3 for the successful notebooks
d2lbook build eval --tab pytorch || ((ss=1))
d2lbook build slides --tab pytorch
# Move aws copy commands for cache store outside
echo "Upload pytorch build cache to s3"
measure_command_time "aws s3 sync _build s3://preview.d2l.ai/"$CACHE_DIR"/"$REPO_NAME"-"$TARGET_BRANCH"/_build --acl public-read --quiet --exclude 'eval*/data/*'"
# Exit with a non-zero status if evaluation failed
if [ "$ss" -ne 0 ]; then
exit 1
fi

39
.github/workflow_scripts/build_tf.sh vendored Normal file
View File

@ -0,0 +1,39 @@
#!/bin/bash
set -ex
# Used to capture status exit of build eval command
ss=0
REPO_NAME="$1" # Eg. 'd2l-zh'
TARGET_BRANCH="$2" # Eg. 'master' ; if PR raised to master
CACHE_DIR="$3" # Eg. 'ci_cache_pr' or 'ci_cache_push'
pip3 install d2l==0.17.6
mkdir _build
source $(dirname "$0")/utils.sh
# Move sanity check outside
d2lbook build outputcheck tabcheck
# Move aws copy commands for cache restore outside
if [ "$DISABLE_CACHE" = "false" ]; then
echo "Retrieving tensorflow build cache from "$CACHE_DIR""
measure_command_time "aws s3 sync s3://preview.d2l.ai/"$CACHE_DIR"/"$REPO_NAME"-"$TARGET_BRANCH"/_build/eval_tensorflow/ _build/eval_tensorflow/ --delete --quiet --exclude 'data/*'"
fi
export TF_CPP_MIN_LOG_LEVEL=3
export TF_FORCE_GPU_ALLOW_GROWTH=true
# Continue the script even if some notebooks in build fail to
# make sure that cache is copied to s3 for the successful notebooks
d2lbook build eval --tab tensorflow || ((ss=1))
# Move aws copy commands for cache store outside
echo "Upload tensorflow build cache to s3"
measure_command_time "aws s3 sync _build s3://preview.d2l.ai/"$CACHE_DIR"/"$REPO_NAME"-"$TARGET_BRANCH"/_build --acl public-read --quiet --exclude 'eval*/data/*'"
# Exit with a non-zero status if evaluation failed
if [ "$ss" -ne 0 ]; then
exit 1
fi

18
.github/workflow_scripts/setup_git.sh vendored Normal file
View File

@ -0,0 +1,18 @@
function setup_git {
# Turn off logging
set +x
mkdir -p $HOME/.ssh
echo "yes" | ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts
# Retrieve the SSH key securely from AWS Secrets Manager
GIT_SSH_KEY=$(aws secretsmanager get-secret-value --secret-id d2l_bot_github --query SecretString --output text --region us-west-2)
# Write the SSH key to a file
echo "$GIT_SSH_KEY" > $HOME/.ssh/id_rsa
chmod 600 $HOME/.ssh/id_rsa
git config --global user.name "d2l-bot"
git config --global user.email "100248899+d2l-bot@users.noreply.github.com"
echo "Successfully Configured Bot"
}

26
.github/workflow_scripts/utils.sh vendored Normal file
View File

@ -0,0 +1,26 @@
#!/bin/bash
# By default, all builds are cached
DISABLE_CACHE=false # Eg. 'true' or 'false'
# Function to measure command execution time
measure_command_time() {
local command="$1"
# Start timing
local start_time=$(date +%s)
# Run the command
eval "$command"
# Calculate the time taken
local end_time=$(date +%s)
local elapsed_time=$((end_time - start_time))
# Format the elapsed time for display
local formatted_time=$(printf "%02dhr %02dmin %02dsec" $((elapsed_time / 3600)) $(((elapsed_time % 3600) / 60)) $((elapsed_time % 60)))
# Print the elapsed time
echo "Time taken for $command: $formatted_time"
}

88
.github/workflows/build-docker.yml vendored Normal file
View File

@ -0,0 +1,88 @@
name: Build Docker Image
on:
workflow_dispatch:
inputs:
image_torch:
type: boolean
description: Build PyTorch Image
image_tf:
type: boolean
description: Build TensorFlow Image
image_mxnet:
type: boolean
description: Build MXNet Image
image_paddle:
type: boolean
description: Build Paddle Image
image_builder:
type: boolean
description: Build D2L Builder Image
permissions:
id-token: write
contents: read
jobs:
build_docker_image:
name: Build D2L Docker Images
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./ci/docker
steps:
- uses: actions/checkout@v3
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: arn:aws:iam::650140442593:role/D2L_CI_Docker
role-duration-seconds: 3600
aws-region: us-west-2
- name: Build D2L PyTorch Image
if: github.event.inputs.image_torch == 'true'
run: |
chmod +x ./login_ecr.sh; ./login_ecr.sh
docker build -f Dockerfile.d2l-zh-torch -t d2l-containers:d2l-zh-torch-latest .
docker tag d2l-containers:d2l-zh-torch-latest 650140442593.dkr.ecr.us-west-2.amazonaws.com/d2l-containers:d2l-zh-torch-latest
docker push 650140442593.dkr.ecr.us-west-2.amazonaws.com/d2l-containers:d2l-zh-torch-latest
# Clean up to reclaim space
echo "y" | docker system prune -a
- name: Build D2L TensorFlow Image
if: github.event.inputs.image_tf == 'true'
run: |
chmod +x ./login_ecr.sh; ./login_ecr.sh
docker build -f Dockerfile.d2l-zh-tf -t d2l-containers:d2l-zh-tensorflow-latest .
docker tag d2l-containers:d2l-zh-tensorflow-latest 650140442593.dkr.ecr.us-west-2.amazonaws.com/d2l-containers:d2l-zh-tensorflow-latest
docker push 650140442593.dkr.ecr.us-west-2.amazonaws.com/d2l-containers:d2l-zh-tensorflow-latest
# Clean up to reclaim space
echo "y" | docker system prune -a
- name: Build D2L MXNet Image
if: github.event.inputs.image_mxnet == 'true'
run: |
chmod +x ./login_ecr.sh; ./login_ecr.sh
docker build -f Dockerfile.d2l-zh-mxnet -t d2l-containers:d2l-zh-mxnet-latest .
docker tag d2l-containers:d2l-zh-mxnet-latest 650140442593.dkr.ecr.us-west-2.amazonaws.com/d2l-containers:d2l-zh-mxnet-latest
docker push 650140442593.dkr.ecr.us-west-2.amazonaws.com/d2l-containers:d2l-zh-mxnet-latest
# Clean up to reclaim space
echo "y" | docker system prune -a
- name: Build D2L Paddle Image
if: github.event.inputs.image_paddle == 'true'
run: |
chmod +x ./login_ecr.sh; ./login_ecr.sh
docker build -f Dockerfile.d2l-zh-paddle -t d2l-containers:d2l-zh-paddle-latest .
docker tag d2l-containers:d2l-zh-paddle-latest 650140442593.dkr.ecr.us-west-2.amazonaws.com/d2l-containers:d2l-zh-paddle-latest
docker push 650140442593.dkr.ecr.us-west-2.amazonaws.com/d2l-containers:d2l-zh-paddle-latest
# Clean up to reclaim space
echo "y" | docker system prune -a
- name: Build D2L CPU Builder Image
if: github.event.inputs.image_builder == 'true'
run: |
chmod +x ./login_ecr.sh; ./login_ecr.sh
docker build -f Dockerfile.d2l-builder -t d2l-containers:d2l-builder-latest .
docker tag d2l-containers:d2l-builder-latest 650140442593.dkr.ecr.us-west-2.amazonaws.com/d2l-containers:d2l-builder-latest
docker push 650140442593.dkr.ecr.us-west-2.amazonaws.com/d2l-containers:d2l-builder-latest

142
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,142 @@
name: Continuous Integration
on:
# Triggers the workflow on push or pull request events only for the specified branches
push:
branches:
- master
- release
pull_request_target:
branches:
- master
- release
permissions:
id-token: write
pull-requests: write
defaults:
run:
shell: bash
jobs:
build_torch:
name: Build PyTorch
if: "github.repository == 'd2l-ai/d2l-zh' && !contains(github.event.head_commit.message, '[skip torch]') && !contains(github.event.head_commit.message, '[skip frameworks]')"
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Setup Env Vars
uses: ./.github/actions/setup_env_vars
- name: Evaluate PyTorch on AWS Batch
uses: ./.github/actions/submit-job
with:
job-type: ci-gpu-torch
job-name: D2L-Build-PyTorch
command: chmod +x ./.github/workflow_scripts/build_pytorch.sh && ./.github/workflow_scripts/build_pytorch.sh "${{ env.REPO_NAME }}" "${{ env.TARGET_BRANCH }}" "${{ env.CACHE_DIR }}"
- name: Terminate Batch Job on Cancellation
if: ${{ cancelled() && env.Batch_JobID }}
run: |
echo "Terminating Submitted AWS Batch Job: "${{ env.Batch_JobID }}""
aws batch terminate-job --job-id "${{ env.Batch_JobID }}" --reason "Job terminated by cancelled workflow"
build_tf:
name: Build Tensorflow
if: "github.repository == 'd2l-ai/d2l-zh' && !contains(github.event.head_commit.message, '[skip tf]') && !contains(github.event.head_commit.message, '[skip frameworks]')"
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Setup Env Vars
uses: ./.github/actions/setup_env_vars
- name: Evaluate Tensorflow on AWS Batch
uses: ./.github/actions/submit-job
with:
job-type: ci-gpu-tf
job-name: D2L-Build-Tensorflow
command: chmod +x ./.github/workflow_scripts/build_tf.sh && ./.github/workflow_scripts/build_tf.sh "${{ env.REPO_NAME }}" "${{ env.TARGET_BRANCH }}" "${{ env.CACHE_DIR }}"
- name: Terminate Batch Job on Cancellation
if: ${{ cancelled() && env.Batch_JobID }}
run: |
echo "Terminating Submitted AWS Batch Job: "${{ env.Batch_JobID }}""
aws batch terminate-job --job-id "${{ env.Batch_JobID }}" --reason "Job terminated by cancelled workflow"
build_mxnet:
name: Build MXNet
if: "github.repository == 'd2l-ai/d2l-zh' && !contains(github.event.head_commit.message, '[skip mxnet]') && !contains(github.event.head_commit.message, '[skip frameworks]')"
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Setup Env Vars
uses: ./.github/actions/setup_env_vars
- name: Evaluate MXNet on AWS Batch
uses: ./.github/actions/submit-job
with:
job-type: ci-gpu-mxnet
job-name: D2L-Build-MXNet
command: chmod +x ./.github/workflow_scripts/build_mxnet.sh && ./.github/workflow_scripts/build_mxnet.sh "${{ env.REPO_NAME }}" "${{ env.TARGET_BRANCH }}" "${{ env.CACHE_DIR }}"
- name: Terminate Batch Job on Cancellation
if: ${{ cancelled() && env.Batch_JobID }}
run: |
echo "Terminating Submitted AWS Batch Job: "${{ env.Batch_JobID }}""
aws batch terminate-job --job-id "${{ env.Batch_JobID }}" --reason "Job terminated by cancelled workflow"
build_paddle:
name: Build Paddle
if: "github.repository == 'd2l-ai/d2l-zh' && !contains(github.event.head_commit.message, '[skip paddle]') && !contains(github.event.head_commit.message, '[skip frameworks]')"
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Setup Env Vars
uses: ./.github/actions/setup_env_vars
- name: Evaluate Paddle on AWS Batch
uses: ./.github/actions/submit-job
with:
job-type: ci-gpu-paddle
job-name: D2L-Build-Paddle
command: chmod +x ./.github/workflow_scripts/build_paddle.sh && ./.github/workflow_scripts/build_paddle.sh "${{ env.REPO_NAME }}" "${{ env.TARGET_BRANCH }}" "${{ env.CACHE_DIR }}"
- name: Terminate Batch Job on Cancellation
if: ${{ cancelled() && env.Batch_JobID }}
run: |
echo "Terminating Submitted AWS Batch Job: "${{ env.Batch_JobID }}""
aws batch terminate-job --job-id "${{ env.Batch_JobID }}" --reason "Job terminated by cancelled workflow"
build_and_deploy:
name: Build Website/PDF & Publish
needs: [build_torch, build_tf, build_mxnet, build_paddle]
if: |
always() &&
github.repository == 'd2l-ai/d2l-zh' &&
!contains(github.event.head_commit.message, '[skip builder]') &&
(needs.build_torch.result == 'success' || needs.build_torch.result == 'skipped') &&
(needs.build_tf.result == 'success' || needs.build_tf.result == 'skipped') &&
(needs.build_mxnet.result == 'success' || needs.build_mxnet.result == 'skipped') &&
(needs.build_paddle.result == 'success' || needs.build_paddle.result == 'skipped')
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Setup Env Vars
uses: ./.github/actions/setup_env_vars
- name: Build Website & PDFs on AWS Batch
uses: ./.github/actions/submit-job
with:
job-type: ci-cpu
job-name: D2L-Builder
command: chmod +x ./.github/workflow_scripts/build_and_deploy.sh ./.github/workflow_scripts/build_html.sh && ./.github/workflow_scripts/build_and_deploy.sh "${{ env.REPO_NAME }}" "${{ env.TARGET_BRANCH }}" "${{ env.JOB_NAME }}" "${{ env.LANG }}" "${{ env.CACHE_DIR }}"
- name: Terminate Batch Job on Cancellation
if: ${{ cancelled() && env.Batch_JobID }}
run: |
echo "Terminating Submitted AWS Batch Job: "${{ env.Batch_JobID }}""
aws batch terminate-job --job-id "${{ env.Batch_JobID }}" --reason "Job terminated by cancelled workflow"
- name: Comment on PR
if: ${{ github.event_name == 'pull_request_target' }}
uses: peter-evans/create-or-update-comment@38e799a33166c9a254f2e3660d4d49ecd67eb80c # v3
with:
issue-number: ${{ github.event.number }}
body: |
Job PR-${{ github.event.number }}-${{ env.SHORT_SHA }} is done.
Check the results at http://preview.d2l.ai/${{ env.JOB_NAME }}

39
.github/workflows/clear-cache.yml vendored Normal file
View File

@ -0,0 +1,39 @@
name: Clear CI Cache
on:
workflow_dispatch:
inputs:
target_branch:
type: choice
description: Choose the cache associated branch
options:
- master
- release
cache_dir:
type: choice
description: Choose cache type, pull requests or push events
options:
- ci_cache_pr
- ci_cache_push
permissions:
id-token: write
contents: read
jobs:
clear_cache:
name: Clear CI Cache
runs-on: ubuntu-latest
steps:
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: arn:aws:iam::650140442593:role/D2L_CI_Clear_Cache
role-duration-seconds: 3600
aws-region: us-west-2
- name: Delete Cache
run: |
CACHE_S3_URL="s3://preview.d2l.ai/${{ github.event.inputs.cache_dir }}/d2l-zh-${{ github.event.inputs.target_branch }}/"
echo "Removing cache in $CACHE_S3_URL"
aws s3 rm --recursive $CACHE_S3_URL

94
Jenkinsfile vendored
View File

@ -1,94 +0,0 @@
stage("Build and Publish") {
// such as d2l-en and d2l-zh
def REPO_NAME = env.JOB_NAME.split('/')[0]
// such as en and zh
def LANG = REPO_NAME.split('-')[1]
// The current branch or the branch this PR will merge into
def TARGET_BRANCH = env.CHANGE_TARGET ? env.CHANGE_TARGET : env.BRANCH_NAME
// such as d2l-en-master
def TASK = REPO_NAME + '-' + TARGET_BRANCH
node('d2l-worker') {
ws("workspace/${TASK}") {
checkout scm
// conda environment
def ENV_NAME = "${TASK}-${EXECUTOR_NUMBER}";
sh label: "Build Environment", script: """set -ex
conda env update -n ${ENV_NAME} -f static/build.yml
conda activate ${ENV_NAME}
pip uninstall -y d2lbook
pip install git+https://github.com/d2l-ai/d2l-book
pip list
nvidia-smi
"""
sh label: "Sanity Check", script: """set -ex
conda activate ${ENV_NAME}
d2lbook build outputcheck tabcheck
"""
sh label: "Execute Notebooks", script: """set -ex
conda activate ${ENV_NAME}
./static/cache.sh restore _build/eval/data
d2lbook build eval
./static/cache.sh store _build/eval/data
"""
sh label: "Execute Notebooks [Pytorch]", script: """set -ex
conda activate ${ENV_NAME}
./static/cache.sh restore _build/eval_pytorch/data
d2lbook build eval --tab pytorch
d2lbook build slides --tab pytorch
./static/cache.sh store _build/eval_pytorch/data
"""
sh label: "Execute Notebooks [Tensorflow]", script: """set -ex
conda activate ${ENV_NAME}
./static/cache.sh restore _build/eval_tensorflow/data
export TF_CPP_MIN_LOG_LEVEL=3
export TF_FORCE_GPU_ALLOW_GROWTH=true
d2lbook build eval --tab tensorflow
./static/cache.sh store _build/eval_tensorflow/data
"""
sh label: "Execute Notebooks [Paddlepaddle]", script: """set -ex
conda activate ${ENV_NAME}
./static/cache.sh restore _build/eval_paddle/data
d2lbook build eval --tab paddle
./static/cache.sh store _build/eval_paddle/data
"""
sh label:"Build HTML", script:"""set -ex
conda activate ${ENV_NAME}
./static/build_html.sh
"""
sh label:"Build PDF", script:"""set -ex
conda activate ${ENV_NAME}
d2lbook build pdf
"""
sh label:"Build Pytorch PDF", script:"""set -ex
conda activate ${ENV_NAME}
d2lbook build pdf --tab pytorch
"""
if (env.BRANCH_NAME == 'release') {
sh label:"Release", script:"""set -ex
conda activate ${ENV_NAME}
d2lbook build pkg
d2lbook deploy html pdf slides pkg colab sagemaker --s3 s3://${LANG}-v2.d2l.ai
"""
} else {
sh label:"Publish", script:"""set -ex
conda activate ${ENV_NAME}
d2lbook deploy html pdf --s3 s3://preview.d2l.ai/${JOB_NAME}/
"""
if (env.BRANCH_NAME.startsWith("PR-")) {
pullRequest.comment("Job ${JOB_NAME}/${BUILD_NUMBER} is complete. \nCheck the results at http://preview.d2l.ai/${JOB_NAME}/")
}
}
}
}
}

View File

@ -1,7 +1,5 @@
# 动手学深度学习Dive into Deep LearningD2L.ai
[![Build Status](http://ci.d2l.ai/job/d2l-zh/job/master/badge/icon)](http://ci.d2l.ai/job/d2l-zh/job/master/)
[第二版zh.D2L.ai](https://zh.d2l.ai) | [第一版zh-v1.D2L.ai](https://zh-v1.d2l.ai/) | 安装和使用书中源代码: [第二版](https://zh.d2l.ai/chapter_installation/index.html) [第一版](https://zh-v1.d2l.ai/chapter_prerequisite/install.html)
<h5 align="center"><i>理解深度学习的最佳方法是学以致用。</i></h5>
@ -30,11 +28,12 @@
如果本书对你有帮助请Star (★) 本仓库或引用本书的英文版:
```
@article{zhang2021dive,
@book{zhang2023dive,
title={Dive into Deep Learning},
author={Zhang, Aston and Lipton, Zachary C. and Li, Mu and Smola, Alexander J.},
journal={arXiv preprint arXiv:2106.11342},
year={2021}
publisher={Cambridge University Press},
note={\url{https://D2L.ai}},
year={2023}
}
```

View File

@ -7,7 +7,7 @@
## 数据并行训练
让我们回顾一下在分布式架构中数据并行的训练方法因为在实践中它的实现相对简单因此本节将排除其他内容只对其进行介绍。由于当今的GPU拥有大量的显存因此在实际场景中不包括图深度学习只有数据并行这种并行训练策略值得推荐。图 :numref:`fig_parameterserver`描述了在 :numref:`sec_multi_gpu`中实现的数据并行的变体。其中的关键是梯度的聚合需要在GPU 0上完成然后再将更新后的参数广播给所有GPU。
让我们回顾一下在分布式架构中数据并行的训练方法因为在实践中它的实现相对简单因此本节将排除其他内容只对其进行介绍。由于当今的GPU拥有大量的显存因此在实际场景中不包括图深度学习只有数据并行这种并行训练策略值得推荐。图 :numref:`fig_parameterserver`描述了在 :numref:`sec_multi_gpu`中实现的数据并行的变体。其中的关键是梯度的聚合需要在单个GPUGPU 0上完成然后再将更新后的参数广播给所有GPU。
![左图是单GPU训练右图是多GPU训练的一个变体1计算损失和梯度2所有梯度聚合在一个GPU上3发生参数更新并将参数重新广播给所有GPU](../img/ps.svg)
:label:`fig_parameterserver`
@ -64,7 +64,7 @@
![多机多GPU分布式并行训练](../img/ps-multimachine.svg)
:label:`fig_ps_multimachine`
以上这些操作似乎都相当简单,而且事实上它们可以在一台机器内高效地执行,但是当我们考虑多台机器时,就会发现中央的参数服务器成为了瓶颈。毕竟,每个服务器的带宽是有限的,因此对$m$个工作节点来说,将所有梯度发送到服务器所需的时间是$\mathcal{O}(m)$。我们也可以通过将参数服务器数量增加到$n$来突破这一障碍。此时,每个服务器只需要存储$\mathcal{O}(1/n)$个参数,因此更新和优化的总时间变为$\mathcal{O}(m/n)$。这两个数字的匹配会产生稳定的伸缩性,而不用在乎我们需要处理多少工作节点。在实际应用中,我们使用同一台机器既作为工作节点还作为服务器。设计说明请参考 :numref:`fig_ps_multips`(技术细节请参考 :cite:`Li.Andersen.Park.ea.2014`)。特别是,确保多台机器只在没有不合理延迟的情况下工作是相当困难的。我们在下面忽略了关于阻塞的细节只简单介绍一下同步和异步unsynchronized更新。
以上这些操作似乎都相当简单,而且事实上它们可以在一台机器内高效地执行,但是当我们考虑多台机器时,就会发现中央的参数服务器成为了瓶颈。毕竟,每个服务器的带宽是有限的,因此对$m$个工作节点来说,将所有梯度发送到服务器所需的时间是$\mathcal{O}(m)$。我们也可以通过将参数服务器数量增加到$n$来突破这一障碍。此时,每个服务器只需要存储$\mathcal{O}(1/n)$个参数,因此更新和优化的总时间变为$\mathcal{O}(m/n)$。这两个数字的匹配会产生稳定的伸缩性,而不用在乎我们需要处理多少工作节点。在实际应用中,我们使用同一台机器既作为工作节点还作为服务器。设计说明请参考 :numref:`fig_ps_multips`(技术细节请参考 :cite:`Li.Andersen.Park.ea.2014`)。特别是,确保多台机器只在没有不合理延迟的情况下工作是相当困难的。
![上图:单参数服务器是一个瓶颈,因为它的带宽是有限的;下图:多参数服务器使用聚合带宽存储部分参数](../img/ps-multips.svg)
:label:`fig_ps_multips`

View File

@ -244,7 +244,7 @@ $$
通常Xavier初始化从均值为零方差
$\sigma^2 = \frac{2}{n_\mathrm{in} + n_\mathrm{out}}$
的高斯分布中采样权重。
我们也可以利用Xavier的直觉来选择从均匀分布中抽取权重时的方差。
我们也可以将其改为选择从均匀分布中抽取权重时的方差。
注意均匀分布$U(-a, a)$的方差为$\frac{a^2}{3}$。
将$\frac{a^2}{3}$代入到$\sigma^2$的条件中,将得到初始化值域:

View File

@ -50,7 +50,7 @@ $$\sum_{i\in\mathcal{V}} \sum_{j\in\mathcal{V}} h(x_{ij}) \left(\mathbf{u}_j^\to
我们也可以从另一个角度来理解GloVe模型。使用 :numref:`subsec_skipgram-global`中的相同符号,设$p_{ij} \stackrel{\mathrm{def}}{=} P(w_j \mid w_i)$为生成上下文词$w_j$的条件概率,给定$w_i$作为语料库中的中心词。 :numref:`tab_glove`根据大量语料库的统计数据列出了给定单词“ice”和“steam”的共现概率及其比值。
:大型语料库中的词-词共现概率及其比值(根据 :cite:`Pennington.Socher.Manning.2014`中的表1改编
大型语料库中的词-词共现概率及其比值(根据 :cite:`Pennington.Socher.Manning.2014`中的表1改编
|$w_k$=|solid|gas|water|fashion|
|:--|:-|:-|:-|:-|

View File

@ -144,7 +144,7 @@ d2l.train_ch11(adadelta, init_adadelta_states(feature_dim),
{'rho': 0.9}, data_iter, feature_dim);
```
为了简洁实现,我们只需使用`Trainer`类中的`adadelta`算法。
为了简洁实现,我们只需使用高级API中的Adadelta算法。
```{.python .input}
d2l.train_concise_ch11('adadelta', {'rho': 0.9}, data_iter)
@ -197,4 +197,4 @@ d2l.train_concise_ch11(trainer, {'rho': 0.9}, data_iter)
:begin_tab:`paddle`
[Discussions](https://discuss.d2l.ai/t/11854)
:end_tab:
:end_tab:

View File

@ -235,7 +235,10 @@ def train_2d(trainer, steps=20, f_grad=None): #@save
results.append((x1, x2))
print(f'epoch {i + 1}, x1: {float(x1):f}, x2: {float(x2):f}')
return results
```
```{.python .input}
#@tab mxnet, tensorflow
def show_trace_2d(f, results): #@save
"""显示优化过程中2D变量的轨迹"""
d2l.set_figsize()
@ -247,6 +250,19 @@ def show_trace_2d(f, results): #@save
d2l.plt.ylabel('x2')
```
```{.python .input}
#@tab pytorch
def show_trace_2d(f, results): #@save
"""显示优化过程中2D变量的轨迹"""
d2l.set_figsize()
d2l.plt.plot(*zip(*results), '-o', color='#ff7f0e')
x1, x2 = d2l.meshgrid(d2l.arange(-5.5, 1.0, 0.1),
d2l.arange(-3.0, 1.0, 0.1), indexing='ij')
d2l.plt.contour(x1, x2, f(x1, x2), colors='#1f77b4')
d2l.plt.xlabel('x1')
d2l.plt.ylabel('x2')
```
```{.python .input}
#@tab paddle
def train_2d(trainer, steps=20, f_grad=None): #@save

View File

@ -75,8 +75,8 @@ def f_grad(x1, x2): # 目标函数的梯度
def sgd(x1, x2, s1, s2, f_grad):
g1, g2 = f_grad(x1, x2)
# 模拟有噪声的梯度
g1 += d2l.normal(0.0, 1, (1,))
g2 += d2l.normal(0.0, 1, (1,))
g1 += d2l.normal(0.0, 1, (1,)).item()
g2 += d2l.normal(0.0, 1, (1,)).item()
eta_t = eta * lr()
return (x1 - eta_t * g1, x2 - eta_t * g2, 0, 0)
```

View File

@ -79,7 +79,7 @@ print(inputs)
```{.python .input}
from mxnet import np
X, y = np.array(inputs.values), np.array(outputs.values)
X, y = np.array(inputs.to_numpy(dtype=float)), np.array(outputs.to_numpy(dtype=float))
X, y
```
@ -87,7 +87,8 @@ X, y
#@tab pytorch
import torch
X, y = torch.tensor(inputs.values), torch.tensor(outputs.values)
X = torch.tensor(inputs.to_numpy(dtype=float))
y = torch.tensor(outputs.to_numpy(dtype=float))
X, y
```
@ -95,7 +96,8 @@ X, y
#@tab tensorflow
import tensorflow as tf
X, y = tf.constant(inputs.values), tf.constant(outputs.values)
X = tf.constant(inputs.to_numpy(dtype=float))
y = tf.constant(outputs.to_numpy(dtype=float))
X, y
```

View File

@ -0,0 +1,39 @@
FROM ubuntu:latest
RUN adduser --disabled-password --disabled-login ci
WORKDIR /home/ci
# Add d2l_job script
ADD d2l_job.sh .
RUN chmod +x d2l_job.sh; chown ci d2l_job.sh
# Copy git timesync for caching
ADD git-timesync /home/ci/.local/bin/
RUN chmod +x /home/ci/.local/bin/git-timesync
RUN apt-get update && apt-get -y install build-essential git wget
# Install pdf dependencies
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y texlive-full
RUN apt-get install -y librsvg2-bin xindy pandoc
# Install fonts
RUN wget https://raw.githubusercontent.com/d2l-ai/utils/master/install_fonts.sh
# Remove "sudo " from the fonts script
RUN sed -i 's/sudo //g' install_fonts.sh
RUN chmod +x install_fonts.sh; ./install_fonts.sh
RUN apt-get install -y python3 python3-pip python-is-python3
# Allow permissions for pip installations and git-timesync
RUN chown -R ci:ci /home/ci/.local
USER ci
ENV PATH="/home/ci/.local/bin:$PATH"
# Install d2lbook using pip
# Install all libraries (cpu) to make sure API reference works for PDF builds
RUN pip3 install d2lbook==1.0.0 torch torchvision tensorflow mxnet
CMD ["/bin/bash"]

View File

@ -0,0 +1,31 @@
# Use MXNet 1.9.1 (April 2023)
FROM nvcr.io/nvidia/mxnet:23.04-py3
RUN adduser --disabled-password --disabled-login ci
WORKDIR /home/ci
# Copy d2l_job script
ADD d2l_job.sh .
RUN chmod +x d2l_job.sh; chown ci d2l_job.sh
# Copy git timesync for caching
ADD git-timesync /home/ci/.local/bin/
RUN chmod +x /home/ci/.local/bin/git-timesync
# Allow permissions for pip installations and git-timesync
RUN chown -R ci:ci /home/ci/.local
# Allow write permissions for downloading data to opt/mxnet/data
RUN chown -R ci:ci /opt
USER ci
ENV PATH="/home/ci/.local/bin:$PATH"
# Install d2lbook using pip
RUN pip3 install d2lbook==1.0.0
# Python script to print framework versions
ADD print_versions.py .
CMD ["/bin/bash"]

View File

@ -0,0 +1,31 @@
# Use Paddle 2.3.2 (Dec 2022)
FROM nvcr.io/nvidia/paddlepaddle:22.12-py3
RUN adduser --disabled-password --disabled-login ci
WORKDIR /home/ci
# Copy d2l_job script
ADD d2l_job.sh .
RUN chmod +x d2l_job.sh; chown ci d2l_job.sh
# opencv dependencies required by paddle
RUN apt-get update && apt-get install libgl1 -y
# Copy git timesync for caching
ADD git-timesync /home/ci/.local/bin/
RUN chmod +x /home/ci/.local/bin/git-timesync
# Allow permissions for pip installations and git-timesync
RUN chown -R ci:ci /home/ci/.local
USER ci
ENV PATH="/home/ci/.local/bin:$PATH"
# Install d2lbook using pip + paddlepaddle dependencies
RUN pip3 install d2lbook==1.0.0 "opencv-python==4.6.0.66"
# Python script to print framework versions
ADD print_versions.py .
CMD ["/bin/bash"]

View File

@ -0,0 +1,28 @@
# Use Tensorflow 2.9.1 (Sept 2023)
FROM nvcr.io/nvidia/tensorflow:22.09-tf2-py3
RUN adduser --disabled-password --disabled-login ci
WORKDIR /home/ci
# Copy d2l_job script
ADD d2l_job.sh .
RUN chmod +x d2l_job.sh; chown ci d2l_job.sh
# Copy git timesync for caching
ADD git-timesync /home/ci/.local/bin/
RUN chmod +x /home/ci/.local/bin/git-timesync
# Allow permissions for pip installations and git-timesync
RUN chown -R ci:ci /home/ci/.local
USER ci
ENV PATH="/home/ci/.local/bin:$PATH"
# Install d2lbook using pip + dependencies for tensorflow d2l
RUN pip3 install d2lbook==1.0.0 tensorflow-probability==0.17.0
# Python script to print framework versions
ADD print_versions.py .
CMD ["/bin/bash"]

View File

@ -0,0 +1,28 @@
# Use PyTorch 1.12 (May 2022)
FROM nvcr.io/nvidia/pytorch:22.06-py3
RUN adduser --disabled-password --disabled-login ci
WORKDIR /home/ci
# Copy d2l_job script
ADD d2l_job.sh .
RUN chmod +x d2l_job.sh; chown ci d2l_job.sh
# Copy git timesync for caching
ADD git-timesync /home/ci/.local/bin/
RUN chmod +x /home/ci/.local/bin/git-timesync
# Allow permissions for pip installations and git-timesync
RUN chown -R ci:ci /home/ci/.local
USER ci
ENV PATH="/home/ci/.local/bin:$PATH"
# Install d2lbook using pip + dependencies for torch d2l
RUN pip3 install d2lbook==1.0.0
# Python script to print framework versions
ADD print_versions.py .
CMD ["/bin/bash"]

68
ci/docker/d2l_job.sh Normal file
View File

@ -0,0 +1,68 @@
#!/bin/bash
date
echo "Args: $@"
env
echo "jobId: $AWS_BATCH_JOB_ID"
echo "jobQueue: $AWS_BATCH_JQ_NAME"
echo "computeEnvironment: $AWS_BATCH_CE_NAME"
SOURCE_REF=$1
WORK_DIR=$2
COMMAND=$3
############### NOT USED ATM ##################
SAVED_OUTPUT=$4
SAVE_PATH=$5
###############################################
REMOTE=$6
SAFE_TO_USE_SCRIPT=$7
ORIGINAL_REPO=${8:-'d2l-zh'}
# TODO @anirudhdagar: hardcode ORIGINAL_ORG
# Avoid ability to change org by restricting
# job definition arguments defined in d2l-infra
# This is only changed for testing purposes
ORIGINAL_ORG=${9:-'d2l-ai'}
# Copy the workflow from master branch
git clone https://github.com/"$ORIGINAL_ORG"/"$ORIGINAL_REPO".git
WORKFLOW_SCRIPTS="$ORIGINAL_REPO"/.github/workflow_scripts
if [ -d "$WORKFLOW_SCRIPTS" ]; then
cp -R "$ORIGINAL_REPO"/.github/workflow_scripts .
fi
cd "$ORIGINAL_REPO"
if [ ! -z $REMOTE ]; then
git remote set-url origin $REMOTE
fi
git fetch origin $SOURCE_REF:working
git checkout working
# Reset modification times for all notebooks using git-timesync
# We use this to make sure d2lbook build eval caching is valid
# even after cloning the repo for each run
# Modification times for original repo files are corrected and are now
# good for comparing with modification times of build files coming
# from the S3 bucket
git timesync *.md **/*.md
# If not safe to use script, we overwrite with the script from master branch
TRUE=true
if [[ ${SAFE_TO_USE_SCRIPT,,} != ${TRUE,,} ]]; then
if [ -d ../workflow_scripts ]; then
rm -rf .github/workflow_scripts
mv ../workflow_scripts .github/
else
echo Not safe to use user provided script, and could not find script from master branches
exit 1
fi
fi
cd $WORK_DIR
/bin/bash -o pipefail -c "eval $COMMAND"
COMMAND_EXIT_CODE=$?
exit $COMMAND_EXIT_CODE

3
ci/docker/entry.sh Normal file
View File

@ -0,0 +1,3 @@
#!/bin/bash
python3 print_versions.py $1
/bin/bash

288
ci/docker/git-timesync Normal file
View File

@ -0,0 +1,288 @@
#!/bin/sh
# This script has been lifted from https://github.com/tst2005/git-timesync/
# and all credits for this belong to @tst2005
# shellcheck disable=SC2004,SC3043,SC2155,SC2039
#### About shellcheck
# I disable:
# - SC2004 (style): $/${} is unnecessary on arithmetic variables.
# Because: I prefere `$( $x - $y ))` than `$(( x - y ))`.
# I disable:
# - SC2039: In POSIX sh, 'local' is undefined.
# - SC3043: In POSIX sh, 'local' is undefined.
# Because:
# local is too usefull, all modern shell support it.
# If you really want to run git-timesync on a strict POSIX shell,
# then remove all local prefixes : 's/local //g'.
#
# I disable :
# - SC2155 (warning): Declare and assign separately to avoid masking return values.
# Because:
# It not relevant : the return code is not used.
# I prefer `local foo="$(bar)"` than `local foo;foo="$(bar)"`.
####
set -e
####
# Author: TsT worldmaster.fr <tst2005@gmail.com>
#
# Improvements:
# - dry-run ("-n" flag)
# - pass files to check as argument
# - do not time sync modified files
# - do not time sync untracked files
# - performance improvment
# - be able to apply timesync only on files present in the N last commits
####
####
# The original version of this script can be found at: https://gist.github.com/jeffery/1115504
#
# Helper script to update the Last modified timestamp of files in a Git SCM
# Projects working Copy
#
# When you clone a Git repository, it sets the timestamp of all the files to the
# time when you cloned the repository.
#
# This becomes a problem when you want the cloned repository, which is part of a
# Web application have a proper cacheing mechanism so that it can re-cache files
# (into a webtree) that have been modified since the last cache.
#
# @see http://stackoverflow.com/questions/1964470/whats-the-equivalent-of-use-commit-times-for-git
#
# Author: Jeffery Fernandez <jeffery@fernandez.net.au>
####
showUsage() {
echo 'Usage: git-timesync [-n] [-q] [-v] [--] [<paths>...]'
echo 'Usage: git-timesync [-n] [-q] [-v] -<N>'
echo
echo ' -h, --help '\
'Print this help message'
echo ' -n, --dry-run, --dryrun '\
'Perform a dry-run to see which files are OK'\
'and which ones need to be synchronized'
echo ' -q, --quiet '\
'Quiet mode: drop everything that is OK and show only the files'\
'which timestamp needs to be synchronized'
echo ' -v, --verbose '\
'Verbose mode: show info for each file (opposite of --quiet)'
echo ' -1 '\
'Apply timesync on files present in the last commit'
echo ' -23 '\
'Apply timesync on files present in the 23 last commits'
echo ' -N '\
'Apply timesync on files present in the N last commits'\
'(with 1 <= N <= 9999)'
}
# Get the last revision hash of a particular file in the git repository
getFileLastRevision() {
git rev-list HEAD -n 1 -- "$1"
}
#getFileMTimeByRef() {
# git show --pretty=format:%at --abbrev-commit "$1" | head -n 1
#}
getFileMTimeByPath() {
# shellcheck disable=SC2155
git rev-list --pretty=format:'date %at' --date-order -n 1 HEAD -- "$1" |
(
local IFS=" ";
# shellcheck disable=SC2034
while read -r key value _misc; do
[ "$key" != "date" ] || echo "$value";
done
)
}
# Extract the actual last modified timestamp of the file and Update the timestamp
updateFileTimeStamp() {
# shellcheck disable=SC2155
# if target does not exists and it's is not a [dead]link, raise an error
if [ ! -e "$1" ] && [ ! -h "$1" ]; then
if [ -n "$(git ls-files -t -d -- "$1")" ]; then
if $verbose; then echo "? $1 (deleted)"; fi
return
fi
echo >&2 "ERROR: Unknown bug ?! No such target $1"
return 1
fi
local tracked="$(git ls-files -t -c -- "$1")"
if [ -z "$tracked" ]; then
if $verbose; then echo "? $1"; fi
return
fi
# Extract the last modified timestamp
# Get the File last modified time
local FILE_MODIFIED_TIME="$(getFileMTimeByPath "$1")"
if [ -z "$FILE_MODIFIED_TIME" ]; then
echo "?! $1 (not found in git)"
return
fi
# Check if the file is modified
local uncommited="$(git ls-files -t -dm -- "$1")"
# for displaying the date in readable format
#local FORMATTED_TIMESTAMP="$(date --date="${FILE_MODIFIED_TIME}" +'%d-%m-%Y %H:%M:%S %z')"
#local FORMATTED_TIMESTAMP="@${FILE_MODIFIED_TIME}"
# Modify the last modified timestamp
#echo "[$(date -d "$FORMATTED_TIMESTAMP")]: $1"
#echo "$FILE_MODIFIED_TIME $1"
local current_mtime="$(getmtime "$1")"
if $debug; then
echo >&2 "DEBUG: $1 (git_time=$FILE_MODIFIED_TIME current_time=$current_mtime delta=$(( ${current_mtime:-0} - ${FILE_MODIFIED_TIME:-0} )))"
fi
if [ "$current_mtime" = "$FILE_MODIFIED_TIME" ]; then
if ${verbose:-true}; then echo "ok $1"; fi
return
fi
if [ -n "$uncommited" ]; then
echo "C $1 (modified, not commited, $(( $current_mtime - $FILE_MODIFIED_TIME ))s recent)"
return
fi
if ${dryrun:-true}; then
echo "!! $1 (desync: $(( $current_mtime - $FILE_MODIFIED_TIME ))s, no change)"
return
fi
echo "!! $1 (desync: $(( $current_mtime - $FILE_MODIFIED_TIME ))s, syncing...)"
#[ -h "$1" ] && touch -c -h -d "$FORMATTED_TIMESTAMP" -- "$1" || \
#touch -c -d "$FORMATTED_TIMESTAMP" -- "$1"
unixtime_touch -c -h -- "$1"
}
# Make sure we are not running this on a bare Repository
is_not_base_repo() {
case "$(git config core.bare)" in
false) ;;
true)
echo "$(pwd): Cannot run this script on a bare Repository"
return 1
;;
*) echo "$(pwd): Error appended during core.bare detection. Are you really inside a repository ?"
return 1
esac
return 0
}
updateFileTimeStampInCwd() {
is_not_base_repo || return
git ls-files -z \
| tr '\0' '\n' \
| (
while read -r file; do
if [ -z "$(git ls-files -t -d -- "$file")" ]; then
updateFileTimeStamp "${file}"
fi
done
)
}
timesyncThisFile() {
if [ -d "$1" ] && [ ! -h "$1" ]; then # is a real directory (not a symlink to a directory)
echo "now inside $1"
# shellcheck disable=SC2015
( cd -- "$1" && updateFileTimeStampInCwd || true; )
else
if $need_check_bare; then
is_not_base_repo || return 1
need_check_bare=false
fi
updateFileTimeStamp "$1"
fi
}
# ... for Linux ... and MINGW64 (used by Windows GIT Bash)
linux_unixtime_touch() {
# shellcheck disable=SC2155
local FORMATTED_TIMESTAMP="@${FILE_MODIFIED_TIME}"
touch -d "$FORMATTED_TIMESTAMP" "$@"
}
linux_getmtime() {
stat -c %Y -- "$1"
}
# ... for FreeBSD and Mac OS X
bsd_unixtime_touch() {
# shellcheck disable=SC2155
local FORMATTED_TIMESTAMP="$(date -j -r "${FILE_MODIFIED_TIME}" +'%Y%m%d%H%M.%S')"
touch -t "$FORMATTED_TIMESTAMP" "$@"
}
bsd_getmtime() {
stat -f %m -- "$1"
}
################################################################################
############################## MAIN SCRIPT LOGIC ###############################
################################################################################
dryrun=false
verbose=true
debug=false
fromrecent=''
while [ $# -gt 0 ]; do
case "$1" in
--) shift; break ;;
-h|--help) showUsage; exit 0;;
-n|--dryrun|--dry-run) dryrun=true ;;
-v) verbose=true ;;
-q) verbose=false ;;
-[1-9]|-[1-9][0-9]|-[1-9][0-9][0-9]|-[1-9][0-9][0-9][0-9]) fromrecent="$1" ;;
--debug) debug=true ;;
-*) echo >&2 "$0: invalid option $1"; exit 1;;
*) break
esac
shift
done
# Obtain the Operating System
case "${GIT_TIMESYNC_FORCE_UNAME:-$(uname)}" in
('Linux'|'MINGW64'*)
unixtime_touch() { linux_unixtime_touch "$@"; }
getmtime() { linux_getmtime "$@"; }
;;
('Darwin'|'FreeBSD')
unixtime_touch() { bsd_unixtime_touch "$@"; }
getmtime() { bsd_getmtime "$@"; }
;;
(*)
echo >&2 "Unknown Operating System to perform timestamp update"
exit 1
;;
esac
if [ $# -eq 0 ] && [ -z "$fromrecent" ]; then
# Loop through and fix timestamps on all files in our checked-out repository
updateFileTimeStampInCwd
else
need_check_bare=true
# Loop through and fix timestamps on all specified files
if [ -n "$fromrecent" ]; then
git log --format='format:' --name-only "$fromrecent" |
sort -u |
while read -r file; do
[ -n "$file" ] || continue
[ -e "$file" ] || continue
timesyncThisFile "$file"
done
else
for file in "$@"; do
timesyncThisFile "$file"
done
fi
fi

3
ci/docker/login_ecr.sh Normal file
View File

@ -0,0 +1,3 @@
#!/bin/bash
aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin 650140442593.dkr.ecr.us-west-2.amazonaws.com

View File

@ -0,0 +1,51 @@
import os
import sys
if len(sys.argv) > 1:
framework_name = sys.argv[1]
else:
# Assume using d2l-builder docker container
# Here all the frameworks are installed and no CUDA support
framework_name = None
print("*"*10, "D2L Framework Version Details", "*"*10)
if framework_name:
# Print CUDA version
print("nvcc --version")
print(os.system("nvcc --version"))
if framework_name=="pytorch":
# Print PyTorch versions
print(f"Framework Name: {framework_name}")
import torch; print(f"torch version: {torch.__version__}")
import torchvision; print(f"torchvision version: {torchvision.__version__}")
import gym; print(f"gym version: {gym.__version__}")
import gpytorch; print(f"gpytorch version: {gpytorch.__version__}")
import syne_tune; print(f"syne_tune version: {syne_tune.__version__}")
if framework_name=="tensorflow":
# Print TensorFlow versions
print(f"Framework Name: {framework_name}")
import tensorflow; print(f"tensorflow version: {tensorflow.__version__}")
import tensorflow_probability; print(f"tensorflow_probability version: {tensorflow_probability.__version__}")
if framework_name=="jax":
# Print JAX versions
print(f"Framework Name: {framework_name}")
import jax; print(f"jax version: {jax.__version__}")
import jaxlib; print(f"jaxlib version: {jaxlib.__version__}")
import flax; print(f"flax version: {flax.__version__}")
import tensorflow_datasets; print(f"tensorflow_datasets version: {tensorflow_datasets.__version__}")
if framework_name=="mxnet":
# Print MXNet versions
print(f"Framework Name: {framework_name}")
import mxnet; print(f"MXNet version: {mxnet.__version__}")
# Print d2lbook version
import d2lbook; print(f"d2lbook version: {d2lbook.__version__}")
print("*"*10, "D2L Framework Version Details", "*"*10)

202
ci/submit-job.py Normal file
View File

@ -0,0 +1,202 @@
import argparse
import random
import os
import re
import sys
import time
from datetime import datetime
import boto3
from botocore.compat import total_seconds
from botocore.config import Config
job_type_info = {
'ci-cpu': {
'job_definition': 'd2l-ci-cpu-builder:2',
'job_queue': 'D2L-CI-CPU'
},
'ci-cpu-push': {
'job_definition': 'd2l-ci-cpu-builder-push:7',
'job_queue': 'D2L-CI-CPU'
},
'ci-cpu-release': {
'job_definition': 'd2l-ci-cpu-builder-release:1',
'job_queue': 'D2L-CI-CPU'
},
'ci-gpu-torch': {
'job_definition': 'd2l-ci-zh-gpu-torch:1',
'job_queue': 'D2L-CI-GPU'
},
'ci-gpu-tf': {
'job_definition': 'd2l-ci-zh-gpu-tf:1',
'job_queue': 'D2L-CI-GPU'
},
'ci-gpu-mxnet': {
'job_definition': 'd2l-ci-zh-gpu-mxnet:1',
'job_queue': 'D2L-CI-GPU'
},
'ci-gpu-paddle': {
'job_definition': 'd2l-ci-zh-gpu-paddle:1',
'job_queue': 'D2L-CI-GPU'
}
}
# Create push job types for GPUs with same definitions
for job_type in list(job_type_info.keys()):
if job_type.startswith('ci-gpu'):
job_type_info[job_type+'-push'] = job_type_info[job_type]
job_type_info[job_type+'-release'] = job_type_info[job_type]
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--profile', help='profile name of aws account.', type=str,
default=None)
parser.add_argument('--region', help='Default region when creating new connections', type=str,
default='us-west-2')
parser.add_argument('--name', help='name of the job', type=str, default='d2l-ci')
parser.add_argument('--job-type', help='type of job to submit.', type=str,
choices=job_type_info.keys(), default='ci-cpu')
parser.add_argument('--source-ref',
help='ref in d2l-zh main github. e.g. master, refs/pull/500/head',
type=str, default='master')
parser.add_argument('--work-dir',
help='working directory inside the repo. e.g. scripts/preprocess',
type=str, default='.')
parser.add_argument('--saved-output',
help='output to be saved, relative to working directory. '
'it can be either a single file or a directory',
type=str, default='None')
parser.add_argument('--save-path',
help='s3 path where files are saved.',
type=str, default='batch/temp/{}'.format(datetime.now().isoformat()))
parser.add_argument('--command', help='command to run', type=str,
default='git rev-parse HEAD | tee stdout.log')
parser.add_argument('--remote',
help='git repo address. https://github.com/d2l-ai/d2l-zh',
type=str, default="https://github.com/d2l-ai/d2l-zh")
parser.add_argument('--safe-to-use-script',
help='whether the script changes from the actor is safe. We assume it is safe if the actor has write permission to our repo',
action='store_true')
parser.add_argument('--original-repo', help='name of the repo', type=str, default='d2l-zh')
parser.add_argument('--wait', help='block wait until the job completes. '
'Non-zero exit code if job fails.', action='store_true')
parser.add_argument('--timeout', help='job timeout in seconds', default=7200, type=int)
args = parser.parse_args()
session = boto3.Session(profile_name=args.profile, region_name=args.region)
config = Config(
retries = dict(
max_attempts = 20
)
)
batch, cloudwatch = [session.client(service_name=sn, config=config) for sn in ['batch', 'logs']]
def printLogs(logGroupName, logStreamName, startTime):
kwargs = {'logGroupName': logGroupName,
'logStreamName': logStreamName,
'startTime': startTime,
'startFromHead': True}
lastTimestamp = startTime - 1
while True:
logEvents = cloudwatch.get_log_events(**kwargs)
for event in logEvents['events']:
lastTimestamp = event['timestamp']
timestamp = datetime.utcfromtimestamp(lastTimestamp / 1000.0).isoformat()
print('[{}] {}'.format((timestamp + '.000')[:23] + 'Z', event['message']))
nextToken = logEvents['nextForwardToken']
if nextToken and kwargs.get('nextToken') != nextToken:
kwargs['nextToken'] = nextToken
else:
break
return lastTimestamp
def nowInMillis():
endTime = int(total_seconds(datetime.utcnow() - datetime(1970, 1, 1))) * 1000
return endTime
def main():
spin = ['-', '/', '|', '\\', '-', '/', '|', '\\']
logGroupName = '/aws/batch/job'
jobName = re.sub('[^A-Za-z0-9_\-]', '', args.name)[:128] # Enforce AWS Batch jobName rules
jobType = args.job_type
jobQueue = job_type_info[jobType]['job_queue']
jobDefinition = job_type_info[jobType]['job_definition']
wait = args.wait
safe_to_use_script = 'False'
if args.safe_to_use_script:
safe_to_use_script = 'True'
parameters = {
'SOURCE_REF': args.source_ref,
'WORK_DIR': args.work_dir,
'SAVED_OUTPUT': args.saved_output,
'SAVE_PATH': args.save_path,
'COMMAND': f"\"{args.command}\"", # wrap command with double quotation mark, so that batch can treat it as a single command
'REMOTE': args.remote,
'SAFE_TO_USE_SCRIPT': safe_to_use_script,
'ORIGINAL_REPO': args.original_repo
}
kwargs = dict(
jobName=jobName,
jobQueue=jobQueue,
jobDefinition=jobDefinition,
parameters=parameters,
)
if args.timeout is not None:
kwargs['timeout'] = {'attemptDurationSeconds': args.timeout}
submitJobResponse = batch.submit_job(**kwargs)
jobId = submitJobResponse['jobId']
# Export Batch_JobID to Github Actions Environment Variable
with open(os.environ['GITHUB_ENV'], 'a') as f:
f.write(f'Batch_JobID={jobId}\n')
os.environ['batch_jobid'] = jobId
print('Submitted job [{} - {}] to the job queue [{}]'.format(jobName, jobId, jobQueue))
spinner = 0
running = False
status_set = set()
startTime = 0
logStreamName = None
while wait:
time.sleep(random.randint(5, 10))
describeJobsResponse = batch.describe_jobs(jobs=[jobId])
status = describeJobsResponse['jobs'][0]['status']
if status == 'SUCCEEDED' or status == 'FAILED':
if logStreamName:
startTime = printLogs(logGroupName, logStreamName, startTime) + 1
print('=' * 80)
print('Job [{} - {}] {}'.format(jobName, jobId, status))
sys.exit(status == 'FAILED')
elif status == 'RUNNING':
logStreamName = describeJobsResponse['jobs'][0]['container']['logStreamName']
if not running:
running = True
print('\rJob [{}, {}] is RUNNING.'.format(jobName, jobId))
if logStreamName:
print('Output [{}]:\n {}'.format(logStreamName, '=' * 80))
if logStreamName:
startTime = printLogs(logGroupName, logStreamName, startTime) + 1
elif status not in status_set:
status_set.add(status)
print('\rJob [%s - %s] is %-9s... %s' % (jobName, jobId, status, spin[spinner % len(spin)]),)
sys.stdout.flush()
spinner += 1
if __name__ == '__main__':
main()

View File

@ -28,8 +28,8 @@ def read_data_ml100k():
"""读取MovieLens-100k数据集"""
data_dir = d2l.download_extract('ml-100k')
names = ['user_id', 'item_id', 'rating', 'timestamp']
data = pd.read_csv(os.path.join(data_dir, 'u.data'), '\t', names=names,
engine='python')
data = pd.read_csv(os.path.join(data_dir, 'u.data'), sep='\t',
names=names, engine='python')
num_users = data.user_id.unique().shape[0]
num_items = data.item_id.unique().shape[0]
return data, num_users, num_items

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

Before

Width:  |  Height:  |  Size: 619 KiB

After

Width:  |  Height:  |  Size: 619 KiB

View File

Before

Width:  |  Height:  |  Size: 599 KiB

After

Width:  |  Height:  |  Size: 599 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 718 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 615 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 999 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1020 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 570 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 646 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 744 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 KiB

View File

@ -203,7 +203,7 @@ a {
<p class="version"> 跳转<a href="https://zh-v1.d2l.ai/">第一版</a></p>
<p>面向中文读者的能运行、可讨论的深度学习教科书</p>
<p>含 PyTorch、NumPy/MXNet、TensorFlow 和 PaddlePaddle 实现</p>
<p>被全球 60 多个国家 400 多所大学用于教学</p>
<p>被全球 70 多个国家 500 多所大学用于教学</p>
<p><a class="github-button" href="https://github.com/d2l-ai/d2l-zh" data-icon="octicon-star" data-size="large" data-show-count="true" aria-label="Star d2l-ai/d2l-zh on GitHub">Star</a></p>
</div>
</div>
@ -213,13 +213,18 @@ a {
<h3>公告</h3>
<div align="left">
<ul>
<li><b>【重磅升级】</b>
第二版纸质书——《动手学深度学习PyTorch版》预计于2023年元旦面世。第二版在线内容新增PaddlePaddle实现。
<li><b>【重磅升级,<a href="https://raw.githubusercontent.com/d2l-ai/d2l-zh/master/static/frontpage/_images/sales/jd-20230208-zh-6.png">新书榜第一</a></b>
第二版纸质书——《动手学深度学习PyTorch版黑白平装版
已在
<a href="https://item.jd.com/13628339.html">京东</a>
<a href="https://product.dangdang.com/29511471.html">当当</a>
上架。
纸质书在内容上与在线版大致相同,但力求在样式、术语标注、语言表述、用词规范、标点以及图、表、章节的索引上符合出版标准和学术规范。
第二版在线内容新增PaddlePaddle实现。
关注本书的<a href="https://github.com/d2l-ai/d2l-zh">中文开源项目</a><a href="https://github.com/d2l-ai/d2l-en">英文开源项目</a>以及时获取最新信息。
</li>
<li><b>【购买第一版纸质书上架4周重印2次累计3万+册)】</b>
纸质书在内容上与在线版大致相同,但力求在样式、术语标注、语言表述、用词规范、标点以及图、表、章节的索引上符合出版标准和学术规范。
可以在
<li><b>【第一版纸质书】</b>
可在
<a href="https://item.jd.com/12613094.html">京东</a>
<a href="http://product.dangdang.com/27872783.html">当当</a>
<a href="https://detail.tmall.com/item.htm?id=594937167055">天猫</a>
@ -232,8 +237,7 @@ a {
[<a href="https://raw.githubusercontent.com/d2l-ai/d2l-zh/v1/img/frontpage/jd-190715-zh.png">新书榜</a>]
[<a href="https://zhuanlan.zhihu.com/p/66689123">关于样书</a>]
</li>
<li><b>【免费资源(新增中文版课件)】</b>
在校学生和老师可以申请用于本书学习或教学的<a href="http://zh.d2l.ai/aws4learn.html">免费计算资源</a>
<li><b>【免费资源】</b>
课件、作业、教学视频等资源可参考伯克利“深度学习导论”
<a href="https://courses.d2l.ai/berkeley-stat-157/syllabus.html">课程大纲</a>
中的链接(<a href="https://github.com/d2l-ai/berkeley-stat-157/tree/master/slides-zh">中文版课件</a>)。
@ -257,28 +261,28 @@ a {
<div class="author-item">
<img src="./_images/aston.jpg"/>
<h3><a href="https://astonzhang.github.io/">阿斯顿·张 </a></h3>
<p>亚马逊资深科学家</p>
<p>亚马逊</p>
</div>
</div>
<div class = "mdl-cell mdl-cell--3-col mdl-cell--top">
<div class="author-item">
<img src="./_images/zack.jpg"/>
<h3><a href="http://zacklipton.com/">扎卡里 C. 立顿</a></h3>
<p> 亚马逊科学家,美国卡内基梅隆大学助理教授</p>
<p> 美国卡内基梅隆大学、亚马逊</p>
</div>
</div>
<div class = "mdl-cell mdl-cell--3-col mdl-cell--top">
<div class="author-item">
<img src="./_images/mu.jpg"/>
<h3><a href="http://www.cs.cmu.edu/~muli/">李沐</a></h3>
<p>亚马逊资深首席科学家</p>
<p>亚马逊</p>
</div>
</div>
<div class = "mdl-cell mdl-cell--3-col mdl-cell--top">
<div class="author-item">
<img src="./_images/alex.jpg"/>
<h3><a href="https://alex.smola.org/">亚历山大 J. 斯莫拉</a></h3>
<p>亚马逊副总裁/杰出科学家</p>
<p>亚马逊</p>
</div>
</div>
@ -289,21 +293,21 @@ a {
<div class="author-item">
<img src="./_images/brent.jpg"/>
<h3><a href="https://www.linkedin.com/in/brent-werness-1506471b7/">布伦特 沃尼斯</a></h3>
<p>亚马逊资深科学家<br><i><a href="http://d2l.ai/chapter_appendix-mathematics-for-deep-learning/index.html">深度学习的数学</a></i></p>
<p>亚马逊<br><i><a href="http://d2l.ai/chapter_appendix-mathematics-for-deep-learning/index.html">深度学习的数学</a></i></p>
</div>
</div>
<div class = "mdl-cell mdl-cell--3-col mdl-cell--top">
<div class="author-item">
<img src="./_images/rachel.jpeg"/>
<h3><a href="https://www.linkedin.com/in/rachelsonghu/">瑞潮儿·胡</a></h3>
<p> 亚马逊科学家<br><i><a href="http://d2l.ai/chapter_appendix-mathematics-for-deep-learning/index.html">深度学习的数学</a></i></p>
<p> 亚马逊<br><i><a href="http://d2l.ai/chapter_appendix-mathematics-for-deep-learning/index.html">深度学习的数学</a></i></p>
</div>
</div>
<div class = "mdl-cell mdl-cell--3-col mdl-cell--top">
<div class="author-item">
<img src="./_images/shuai.jpg"/>
<h3><a href="https://shuaizhang.tech/">张帅</a></h3>
<p>苏黎世联邦理工学院博士后
<p>亚马逊
<br><i><a href="http://d2l.ai/chapter_recommender-systems/index.html">推荐系统</a></i></p>
</div>
</div>
@ -312,7 +316,7 @@ a {
<div class="author-item">
<img src="./_images/yi.jpg"/>
<h3><a href="https://vanzytay.github.io/">郑毅</a></h3>
<p>谷歌科学家
<p>谷歌
<br><i><a href="http://d2l.ai/chapter_recommender-systems/index.html">推荐系统</a></i></p>
</div>
</div>
@ -324,42 +328,42 @@ a {
<div class="author-item">
<img src="./_images/anirudh.jpg"/>
<h3><a href="https://github.com/AnirudhDagar">阿尼如 达格</a></h3>
<p>印度理工学院罗克分校<br><i>PyTorch改编</i></p>
<p>亚马逊<br><i>PyTorch改编</i></p>
</div>
</div>
<div class = "mdl-cell mdl-cell--3-col mdl-cell--top">
<div class="author-item">
<img src="./_images/yuan.jpg"/>
<h3><a href="https://terrytangyuan.github.io/about/">唐源</a></h3>
<p>蚂蚁集团高级工程师<br><i>TensorFlow改编</i></p>
<p>Akuity<br><i>TensorFlow改编</i></p>
</div>
</div>
<div class = "mdl-cell mdl-cell--3-col mdl-cell--top">
<div class="author-item">
<img src="./_images/wugaosheng.jpg"/>
<h3><a href="https://github.com/w5688414">吴高升</a></h3>
<p>百度飞桨高级工程师<br><i>飞桨改编</i></p>
<p>百度<br><i>飞桨改编</i></p>
</div>
</div>
<div class = "mdl-cell mdl-cell--3-col mdl-cell--top">
<div class="author-item">
<img src="./_images/huliujun.jpg"/>
<h3><a href="https://github.com/tensorfly-gpu">胡刘俊</a></h3>
<p>飞桨开发者技术专家<br><i>飞桨改编</i></p>
<p>百度<br><i>飞桨改编</i></p>
</div>
</div>
<div class = "mdl-cell mdl-cell--3-col mdl-cell--top">
<div class="author-item">
<img src="./_images/zhangge.jpg"/>
<h3><a href="https://github.com/Shelly111111">张戈</a></h3>
<p>飞桨开发者技术专家<br><i>飞桨改编</i></p>
<p>百度<br><i>飞桨改编</i></p>
</div>
</div>
<div class = "mdl-cell mdl-cell--3-col mdl-cell--top">
<div class="author-item">
<img src="./_images/xiejiehang.jpg"/>
<h3><a href="https://github.com/JiehangXie">谢杰航</a></h3>
<p>飞桨开发者技术专家<br><i>飞桨改编</i></p>
<p>百度<br><i>飞桨改编</i></p>
</div>
</div>
@ -370,14 +374,14 @@ a {
<div class="author-item">
<img src="./_images/xiaoting.jpg"/>
<h3><a href="https://github.com/xiaotinghe">何孝霆</a></h3>
<p>亚马逊解决方案架构师</p>
<p>亚马逊</p>
</div>
</div>
<div class = "mdl-cell mdl-cell--3-col mdl-cell--top">
<div class="author-item">
<img src="./_images/rachel.jpeg"/>
<h3><a href="https://www.linkedin.com/in/rachelsonghu/">瑞潮儿·胡</a></h3>
<p>亚马逊科学家</p>
<p>亚马逊</p>
</div>
</div>
@ -918,7 +922,7 @@ a {
<!--end of the map-->
<button class="collapsible">
<center>[+] <i>点击以显示完整名单</i></center>
<center>[+] <i>点击以显示完整名单</i></center>
</button>
<div class="expansion">
<div class="institute mdl-grid">
@ -1314,9 +1318,6 @@ a {
</div> <!-- mdl-grid -->
</div>
<h4>如果你使用(或将要使用)本书教学并希望收到免费纸质版图书,
<a href="https://raw.githubusercontent.com/d2l-ai/d2l-en/master/static/frontpage/attachments/hardcopy.txt" target="_blank">联系我们</a></h4>
<!-- reverse the changes by google map... -->
<style>
a { font-weight: 400; }
@ -1332,11 +1333,12 @@ a {
<div class="highlight-python notranslate">
<div class="highlight">
<tt>
<pre>@article{zhang2021dive,
<pre>@book{zhang2023dive,
title={Dive into Deep Learning},
author={Zhang, Aston and Lipton, Zachary C. and Li, Mu and Smola, Alexander J.},
journal={arXiv preprint arXiv:2106.11342},
year={2021}
publisher={Cambridge University Press},
note={\url{https://D2L.ai}},
year={2023}
}</pre>
</tt>
</div>