Compare commits
27 Commits
Author | SHA1 | Date |
---|---|---|
|
3edee269d4 | |
|
e42ebff63d | |
|
450277f3a2 | |
|
28e11145ae | |
|
7f205d2e8c | |
|
e5cfa315fe | |
|
b3cacaebec | |
|
e51c411719 | |
|
2d9071c02b | |
|
0e3803ddf0 | |
|
62c272344e | |
|
b87af57674 | |
|
8770d10e11 | |
|
7d60eaeccc | |
|
35b0b2de8c | |
|
098eb16190 | |
|
fee3287214 | |
|
b177a44507 | |
|
94dc7d092b | |
|
dae3fdac13 | |
|
36405486a1 | |
|
20ef4d238d | |
|
87bd3f61e9 | |
|
a1e2a3643d | |
|
c0cbd84d20 | |
|
c68a39f180 | |
|
24158fb704 |
|
@ -1,57 +0,0 @@
|
|||
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
|
|
@ -1,91 +0,0 @@
|
|||
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
|
|
@ -1,45 +0,0 @@
|
|||
#!/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/*'"
|
|
@ -1,44 +0,0 @@
|
|||
#!/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
|
|
@ -1,37 +0,0 @@
|
|||
#!/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
|
|
@ -1,41 +0,0 @@
|
|||
#!/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
|
|
@ -1,39 +0,0 @@
|
|||
#!/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
|
|
@ -1,18 +0,0 @@
|
|||
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"
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
#!/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"
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
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
|
|
@ -1,142 +0,0 @@
|
|||
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 }}
|
|
@ -1,39 +0,0 @@
|
|||
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
|
|
@ -0,0 +1,94 @@
|
|||
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}/")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
# 动手学深度学习(Dive into Deep Learning,D2L.ai)
|
||||
|
||||
[](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>
|
||||
|
@ -28,12 +30,11 @@
|
|||
如果本书对你有帮助,请Star (★) 本仓库或引用本书的英文版:
|
||||
|
||||
```
|
||||
@book{zhang2023dive,
|
||||
@article{zhang2021dive,
|
||||
title={Dive into Deep Learning},
|
||||
author={Zhang, Aston and Lipton, Zachary C. and Li, Mu and Smola, Alexander J.},
|
||||
publisher={Cambridge University Press},
|
||||
note={\url{https://D2L.ai}},
|
||||
year={2023}
|
||||
journal={arXiv preprint arXiv:2106.11342},
|
||||
year={2021}
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
## 数据并行训练
|
||||
|
||||
让我们回顾一下在分布式架构中数据并行的训练方法,因为在实践中它的实现相对简单,因此本节将排除其他内容只对其进行介绍。由于当今的GPU拥有大量的显存,因此在实际场景中(不包括图深度学习)只有数据并行这种并行训练策略值得推荐。图 :numref:`fig_parameterserver`描述了在 :numref:`sec_multi_gpu`中实现的数据并行的变体。其中的关键是梯度的聚合需要在单个GPU(GPU 0)上完成,然后再将更新后的参数广播给所有GPU。
|
||||
让我们回顾一下在分布式架构中数据并行的训练方法,因为在实践中它的实现相对简单,因此本节将排除其他内容只对其进行介绍。由于当今的GPU拥有大量的显存,因此在实际场景中(不包括图深度学习)只有数据并行这种并行训练策略值得推荐。图 :numref:`fig_parameterserver`描述了在 :numref:`sec_multi_gpu`中实现的数据并行的变体。其中的关键是梯度的聚合需要在GPU 0上完成,然后再将更新后的参数广播给所有GPU。
|
||||
|
||||

|
||||
:label:`fig_parameterserver`
|
||||
|
@ -64,7 +64,7 @@
|
|||

|
||||
: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`)。特别是,确保多台机器只在没有不合理延迟的情况下工作是相当困难的。
|
||||
以上这些操作似乎都相当简单,而且事实上它们可以在一台机器内高效地执行,但是当我们考虑多台机器时,就会发现中央的参数服务器成为了瓶颈。毕竟,每个服务器的带宽是有限的,因此对$m$个工作节点来说,将所有梯度发送到服务器所需的时间是$\mathcal{O}(m)$。我们也可以通过将参数服务器数量增加到$n$来突破这一障碍。此时,每个服务器只需要存储$\mathcal{O}(1/n)$个参数,因此更新和优化的总时间变为$\mathcal{O}(m/n)$。这两个数字的匹配会产生稳定的伸缩性,而不用在乎我们需要处理多少工作节点。在实际应用中,我们使用同一台机器既作为工作节点还作为服务器。设计说明请参考 :numref:`fig_ps_multips`(技术细节请参考 :cite:`Li.Andersen.Park.ea.2014`)。特别是,确保多台机器只在没有不合理延迟的情况下工作是相当困难的。我们在下面忽略了关于阻塞的细节,只简单介绍一下同步和异步(unsynchronized)更新。
|
||||
|
||||

|
||||
:label:`fig_ps_multips`
|
||||
|
|
|
@ -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$的条件中,将得到初始化值域:
|
||||
|
||||
|
|
|
@ -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|
|
||||
|:--|:-|:-|:-|:-|
|
||||
|
|
|
@ -144,7 +144,7 @@ d2l.train_ch11(adadelta, init_adadelta_states(feature_dim),
|
|||
{'rho': 0.9}, data_iter, feature_dim);
|
||||
```
|
||||
|
||||
为了简洁实现,我们只需使用高级API中的Adadelta算法。
|
||||
为了简洁实现,我们只需使用`Trainer`类中的`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:
|
|
@ -235,10 +235,7 @@ 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()
|
||||
|
@ -250,19 +247,6 @@ 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
|
||||
|
|
|
@ -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,)).item()
|
||||
g2 += d2l.normal(0.0, 1, (1,)).item()
|
||||
g1 += d2l.normal(0.0, 1, (1,))
|
||||
g2 += d2l.normal(0.0, 1, (1,))
|
||||
eta_t = eta * lr()
|
||||
return (x1 - eta_t * g1, x2 - eta_t * g2, 0, 0)
|
||||
```
|
||||
|
|
|
@ -79,7 +79,7 @@ print(inputs)
|
|||
```{.python .input}
|
||||
from mxnet import np
|
||||
|
||||
X, y = np.array(inputs.to_numpy(dtype=float)), np.array(outputs.to_numpy(dtype=float))
|
||||
X, y = np.array(inputs.values), np.array(outputs.values)
|
||||
X, y
|
||||
```
|
||||
|
||||
|
@ -87,8 +87,7 @@ X, y
|
|||
#@tab pytorch
|
||||
import torch
|
||||
|
||||
X = torch.tensor(inputs.to_numpy(dtype=float))
|
||||
y = torch.tensor(outputs.to_numpy(dtype=float))
|
||||
X, y = torch.tensor(inputs.values), torch.tensor(outputs.values)
|
||||
X, y
|
||||
```
|
||||
|
||||
|
@ -96,8 +95,7 @@ X, y
|
|||
#@tab tensorflow
|
||||
import tensorflow as tf
|
||||
|
||||
X = tf.constant(inputs.to_numpy(dtype=float))
|
||||
y = tf.constant(outputs.to_numpy(dtype=float))
|
||||
X, y = tf.constant(inputs.values), tf.constant(outputs.values)
|
||||
X, y
|
||||
```
|
||||
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
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"]
|
|
@ -1,31 +0,0 @@
|
|||
# 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"]
|
|
@ -1,31 +0,0 @@
|
|||
# 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"]
|
|
@ -1,28 +0,0 @@
|
|||
# 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"]
|
|
@ -1,28 +0,0 @@
|
|||
# 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"]
|
|
@ -1,68 +0,0 @@
|
|||
#!/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
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/bash
|
||||
python3 print_versions.py $1
|
||||
/bin/bash
|
|
@ -1,288 +0,0 @@
|
|||
#!/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
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
#!/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
|
|
@ -1,51 +0,0 @@
|
|||
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
|
@ -1,202 +0,0 @@
|
|||
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()
|
|
@ -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'), sep='\t',
|
||||
names=names, engine='python')
|
||||
data = pd.read_csv(os.path.join(data_dir, 'u.data'), '\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
|
||||
|
|
1011
d2l/mxnet.py
801
d2l/torch.py
Before Width: | Height: | Size: 619 KiB After Width: | Height: | Size: 619 KiB |
Before Width: | Height: | Size: 599 KiB After Width: | Height: | Size: 599 KiB |
Before Width: | Height: | Size: 718 KiB |
Before Width: | Height: | Size: 615 KiB |
Before Width: | Height: | Size: 999 KiB |
Before Width: | Height: | Size: 1.9 MiB |
Before Width: | Height: | Size: 436 KiB |
Before Width: | Height: | Size: 8.1 MiB |
Before Width: | Height: | Size: 2.5 MiB |
Before Width: | Height: | Size: 1020 KiB |
Before Width: | Height: | Size: 1.0 MiB |
Before Width: | Height: | Size: 2.7 MiB |
Before Width: | Height: | Size: 2.7 MiB |
Before Width: | Height: | Size: 441 KiB |
Before Width: | Height: | Size: 570 KiB |
Before Width: | Height: | Size: 2.5 MiB |
Before Width: | Height: | Size: 704 KiB |
Before Width: | Height: | Size: 646 KiB |
Before Width: | Height: | Size: 1.0 MiB |
Before Width: | Height: | Size: 574 KiB |
Before Width: | Height: | Size: 744 KiB |
Before Width: | Height: | Size: 1.0 MiB |
Before Width: | Height: | Size: 460 KiB |
|
@ -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>被全球 70 多个国家 500 多所大学用于教学</p>
|
||||
<p>被全球 60 多个国家 400 多所大学用于教学</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,18 +213,13 @@ a {
|
|||
<h3>公告</h3>
|
||||
<div align="left">
|
||||
<ul>
|
||||
<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实现。
|
||||
<li><b>【重磅升级】</b>
|
||||
第二版纸质书——《动手学深度学习(PyTorch版)》预计于2023年元旦面世。第二版在线内容新增PaddlePaddle实现。
|
||||
关注本书的<a href="https://github.com/d2l-ai/d2l-zh">中文开源项目</a>和<a href="https://github.com/d2l-ai/d2l-en">英文开源项目</a>以及时获取最新信息。
|
||||
</li>
|
||||
<li><b>【第一版纸质书】</b>
|
||||
可在
|
||||
<li><b>【购买第一版纸质书(上架4周重印2次,累计3万+册)】</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>
|
||||
|
@ -237,7 +232,8 @@ 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>
|
||||
<li><b>【免费资源(新增中文版课件)】</b>
|
||||
在校学生和老师可以申请用于本书学习或教学的<a href="http://zh.d2l.ai/aws4learn.html">免费计算资源</a>。
|
||||
课件、作业、教学视频等资源可参考伯克利“深度学习导论”
|
||||
<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>)。
|
||||
|
@ -261,28 +257,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>
|
||||
|
||||
|
@ -293,21 +289,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>
|
||||
|
@ -316,7 +312,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>
|
||||
|
@ -328,42 +324,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>Akuity<br><i>TensorFlow改编</i></p>
|
||||
<p>蚂蚁集团高级工程师<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>
|
||||
|
||||
|
@ -374,14 +370,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>
|
||||
|
||||
|
@ -922,7 +918,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">
|
||||
|
@ -1318,6 +1314,9 @@ 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; }
|
||||
|
@ -1333,12 +1332,11 @@ a {
|
|||
<div class="highlight-python notranslate">
|
||||
<div class="highlight">
|
||||
<tt>
|
||||
<pre>@book{zhang2023dive,
|
||||
<pre>@article{zhang2021dive,
|
||||
title={Dive into Deep Learning},
|
||||
author={Zhang, Aston and Lipton, Zachary C. and Li, Mu and Smola, Alexander J.},
|
||||
publisher={Cambridge University Press},
|
||||
note={\url{https://D2L.ai}},
|
||||
year={2023}
|
||||
journal={arXiv preprint arXiv:2106.11342},
|
||||
year={2021}
|
||||
}</pre>
|
||||
</tt>
|
||||
</div>
|
||||
|
|