Skip to content

Commit f52b7ba

Browse files
authored
Merge branch 'main' into fix_checkpoint_hyperparameter_tuning
2 parents 9cec1bc + 361c4c7 commit f52b7ba

12 files changed

+269
-13
lines changed

.jenkins/build.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ sudo apt-get update || sudo apt-get install libgnutls30
1515
sudo apt-get update
1616
sudo apt-get install -y --no-install-recommends unzip p7zip-full sox libsox-dev libsox-fmt-all rsync
1717

18+
# Install pandoc (does not install from pypi)
19+
sudo apt-get update
20+
sudo apt-get install -y pandoc
21+
1822
# NS: Path to python runtime should already be part of docker container
1923
# export PATH=/opt/conda/bin:$PATH
2024
rm -rf src
@@ -63,6 +67,9 @@ if [[ "${JOB_TYPE}" == "worker" ]]; then
6367
# Step 3: Run `make docs` to generate HTML files and static files for these tutorials
6468
make docs
6569

70+
# Step 3.1: Run the post-processing script:
71+
python .jenkins/post_process_notebooks.py
72+
6673
# Step 4: If any of the generated files are not related the tutorial files we want to run,
6774
# then we remove them
6875
set +x
@@ -140,6 +147,9 @@ elif [[ "${JOB_TYPE}" == "manager" ]]; then
140147
bash $DIR/remove_invisible_code_block_batch.sh docs
141148
python .jenkins/validate_tutorials_built.py
142149

150+
# Step 5.1: Run post-processing script on .ipynb files:
151+
python .jenkins/post_process_notebooks.py
152+
143153
# Step 6: Copy generated HTML files and static files to S3
144154
7z a manager.7z docs
145155
awsv2 s3 cp manager.7z s3://${BUCKET_NAME}/${COMMIT_ID}/manager.7z

.jenkins/custom_pandoc_filter.py

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
from pandocfilters import toJSONFilter, Div, RawBlock, Para, Str, Space, Link, Code, CodeBlock
2+
import markdown
3+
import html
4+
5+
def to_markdown(item, skip_octicon=False):
6+
# A handler function to process strings, links, code, and code
7+
# blocks
8+
if item['t'] == 'Str':
9+
return item['c']
10+
elif item['t'] == 'Space':
11+
return ' '
12+
elif item['t'] == 'Link':
13+
link_text = ''.join(to_markdown(i, skip_octicon) for i in item['c'][1])
14+
return f'<a href="{item["c"][2][0]}">{link_text}</a>'
15+
elif item['t'] == 'Code':
16+
# Need to remove icticon as they don't render in .ipynb
17+
if any(value == 'octicon' for key, value in item['c'][0][2]):
18+
return ''
19+
else:
20+
# Escape the code and wrap it in <code> tags
21+
return f'<code>{html.escape(item["c"][1])}</code>'
22+
elif item['t'] == 'CodeBlock':
23+
# Escape the code block and wrap it in <pre><code> tags
24+
return f'<pre><code>{html.escape(item["c"][1])}</code></pre>'
25+
else:
26+
return ''
27+
28+
29+
def process_admonitions(key, value, format, meta):
30+
# Replace admonitions with proper HTML.
31+
if key == 'Div':
32+
[[ident, classes, keyvals], contents] = value
33+
if 'note' in classes:
34+
color = '#54c7ec'
35+
label = 'NOTE:'
36+
elif 'tip' in classes:
37+
color = '#6bcebb'
38+
label = 'TIP:'
39+
elif 'warning' in classes:
40+
color = '#e94f3b'
41+
label = 'WARNING:'
42+
else:
43+
return
44+
45+
note_content = []
46+
for block in contents:
47+
if block.get('t') == 'Para':
48+
for item in block['c']:
49+
if item['t'] == 'Str':
50+
note_content.append(Str(item['c']))
51+
elif item['t'] == 'Space':
52+
note_content.append(Space())
53+
elif item['t'] == 'Link':
54+
note_content.append(Link(*item['c']))
55+
elif item['t'] == 'Code':
56+
note_content.append(Code(*item['c']))
57+
elif block.get('t') == 'CodeBlock':
58+
note_content.append(CodeBlock(*block['c']))
59+
60+
note_content_md = ''.join(to_markdown(item) for item in note_content)
61+
html_content = markdown.markdown(note_content_md)
62+
63+
return [{'t': 'RawBlock', 'c': ['html', f'<div style="background-color: {color}; color: #fff; font-weight: 700; padding-left: 10px; padding-top: 5px; padding-bottom: 5px"><strong>{label}</strong></div>']}, {'t': 'RawBlock', 'c': ['html', '<div style="background-color: #f3f4f7; padding-left: 10px; padding-top: 10px; padding-bottom: 10px; padding-right: 10px">']}, {'t': 'RawBlock', 'c': ['html', html_content]}, {'t': 'RawBlock', 'c': ['html', '</div>']}]
64+
elif key == 'RawBlock':
65+
# this is needed for the cells that have embedded video.
66+
# We add a special tag to those: ``` {python, .jupyter-code-cell}
67+
# The post-processing script then finds those and genrates separate
68+
# code cells that can load video.
69+
[format, content] = value
70+
if format == 'html' and 'iframe' in content:
71+
# Extract the video URL
72+
video_url = content.split('src="')[1].split('"')[0]
73+
# Create the Python code to display the video
74+
python_code = f"""
75+
from IPython.display import display, HTML
76+
html_code = \"""
77+
{content}
78+
\"""
79+
display(HTML(html_code))
80+
"""
81+
82+
return {'t': 'CodeBlock', 'c': [['', ['python', 'jupyter-code-cell'], []], python_code]}
83+
84+
85+
def process_images(key, value, format, meta):
86+
# Add https://pytorch.org/tutorials/ to images so that they
87+
# load correctly in the notebook.
88+
if key != 'Image':
89+
return None
90+
[ident, classes, keyvals], caption, [src, title] = value
91+
if not src.startswith('http'):
92+
while src.startswith('../'):
93+
src = src[3:]
94+
if src.startswith('/_static'):
95+
src = src[1:]
96+
src = 'https://pytorch.org/tutorials/' + src
97+
98+
return {'t': 'Image', 'c': [[ident, classes, keyvals], caption, [src, title]]}
99+
100+
101+
def process_grids(key, value, format, meta):
102+
# Generate side by side grid cards. Only for the two-cards layout
103+
# that we use in the tutorial template.
104+
if key == 'Div':
105+
[[ident, classes, keyvals], contents] = value
106+
if 'grid' in classes:
107+
columns = ['<div style="width: 45%; float: left; padding: 20px;">',
108+
'<div style="width: 45%; float: right; padding: 20px;">']
109+
column_num = 0
110+
for block in contents:
111+
if 't' in block and block['t'] == 'Div' and 'grid-item-card' in block['c'][0][1]:
112+
item_html = ''
113+
for item in block['c'][1]:
114+
if item['t'] == 'Para':
115+
item_html += '<h2>' + ''.join(to_markdown(i) for i in item['c']) + '</h2>'
116+
elif item['t'] == 'BulletList':
117+
item_html += '<ul>'
118+
for list_item in item['c']:
119+
item_html += '<li>' + ''.join(to_markdown(i) for i in list_item[0]['c']) + '</li>'
120+
item_html += '</ul>'
121+
columns[column_num] += item_html
122+
column_num = (column_num + 1) % 2
123+
columns = [column + '</div>' for column in columns]
124+
return {'t': 'RawBlock', 'c': ['html', ''.join(columns)]}
125+
126+
def is_code_block(item):
127+
return item['t'] == 'Code' and 'octicon' in item['c'][1]
128+
129+
130+
def process_all(key, value, format, meta):
131+
for transform in [process_admonitions, process_images, process_grids]:
132+
new_value = transform(key, value, format, meta)
133+
if new_value is not None:
134+
break
135+
return new_value
136+
137+
138+
if __name__ == "__main__":
139+
toJSONFilter(process_all)

.jenkins/post_process_notebooks.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import nbformat as nbf
2+
import os
3+
import re
4+
5+
"""
6+
This post-processing script needs to run after the .ipynb files are
7+
generated. The script removes extraneous ```{=html} syntax from the
8+
admonitions and splits the cells that have video iframe into a
9+
separate code cell that can be run to load the video directly
10+
in the notebook. This script is included in build.sh.
11+
"""
12+
13+
14+
# Pattern to search ``` {.python .jupyter-code-cell}
15+
pattern = re.compile(r'(.*?)``` {.python .jupyter-code-cell}\n\n(from IPython.display import display, HTML\nhtml_code = """\n.*?\n"""\ndisplay\(HTML\(html_code\)\))\n```(.*)', re.DOTALL)
16+
17+
18+
def process_video_cell(notebook_path):
19+
"""
20+
This function finds the code blocks with the
21+
"``` {.python .jupyter-code-cell}" code bocks and slices them
22+
into a separe code cell (instead of markdown) which allows to
23+
load the video in the notebook. The rest of the content is placed
24+
in a new markdown cell.
25+
"""
26+
print(f'Processing file: {notebook_path}')
27+
notebook = nbf.read(notebook_path, as_version=4)
28+
29+
# Iterate over markdown cells
30+
for i, cell in enumerate(notebook.cells):
31+
if cell.cell_type == 'markdown':
32+
match = pattern.search(cell.source)
33+
if match:
34+
print(f'Match found in cell {i}: {match.group(0)[:100]}...')
35+
# Extract the parts before and after the video code block
36+
before_html_block = match.group(1)
37+
code_block = match.group(2)
38+
39+
# Add a comment to run the cell to display the video
40+
code_block = "# Run this cell to load the video\n" + code_block
41+
# Create a new code cell
42+
new_code_cell = nbf.v4.new_code_cell(source=code_block)
43+
44+
# Replace the original markdown cell with the part before the code block
45+
cell.source = before_html_block
46+
47+
# Insert the new code cell after the current one
48+
notebook.cells.insert(i+1, new_code_cell)
49+
print(f'New code cell created with source: {new_code_cell.source}')
50+
51+
# If there is content after the HTML code block, create a new markdown cell
52+
if len(match.group(3).strip()) > 0:
53+
after_html_block = match.group(3)
54+
new_markdown_cell = nbf.v4.new_markdown_cell(source=after_html_block)
55+
# Create a new markdown cell and add the content after code block there
56+
notebook.cells.insert(i+2, new_markdown_cell)
57+
58+
else:
59+
# Remove ```{=html} from the code block
60+
cell.source = remove_html_tag(cell.source)
61+
62+
nbf.write(notebook, notebook_path)
63+
64+
65+
def remove_html_tag(content):
66+
"""
67+
Pandoc adds an extraneous ```{=html} ``` to raw HTML blocks which
68+
prevents it from rendering correctly. This function removes
69+
```{=html} that we don't need.
70+
"""
71+
content = re.sub(r'```{=html}\n<div', '<div', content)
72+
content = re.sub(r'">\n```', '">', content)
73+
content = re.sub(r'<\/div>\n```', '</div>\n', content)
74+
content = re.sub(r'```{=html}\n</div>\n```', '</div>\n', content)
75+
content = re.sub(r'```{=html}', '', content)
76+
content = re.sub(r'</p>\n```', '</p>', content)
77+
return content
78+
79+
80+
def walk_dir(downloads_dir):
81+
"""
82+
Walk the dir and process all notebook files in
83+
the _downloads directory and its subdirectories.
84+
"""
85+
for root, dirs, files in os.walk(downloads_dir):
86+
for filename in files:
87+
if filename.endswith('.ipynb'):
88+
process_video_cell(os.path.join(root, filename))
89+
90+
91+
def main():
92+
downloads_dir = './docs/_downloads'
93+
walk_dir(downloads_dir)
94+
95+
96+
if __name__ == "__main__":
97+
main()

advanced_source/super_resolution_with_onnxruntime.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
.. note::
66
As of PyTorch 2.1, there are two versions of ONNX Exporter.
77
8-
* ``torch.onnx.dynamo_export`is the newest (still in beta) exporter based on the TorchDynamo technology released with PyTorch 2.0.
8+
* ``torch.onnx.dynamo_export`` is the newest (still in beta) exporter based on the TorchDynamo technology released with PyTorch 2.0.
99
* ``torch.onnx.export`` is based on TorchScript backend and has been available since PyTorch 1.2.0.
1010
1111
In this tutorial, we describe how to convert a model defined

advanced_source/usb_semisup_learn.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181
# algorithm on dataset
8282
#
8383
# Note that a CUDA-enabled backend is required for training with the ``semilearn`` package.
84-
# See `Enabling CUDA in Google Colab <https://pytorch.org/tutorials/beginner/colab#using-cuda>`__ for instructions
84+
# See `Enabling CUDA in Google Colab <https://pytorch.org/tutorials/beginner/colab#enabling-cuda>`__ for instructions
8585
# on enabling CUDA in Google Colab.
8686
#
8787
import semilearn

beginner_source/ddp_series_multigpu.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,15 @@ Imports
7878
Constructing the process group
7979
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8080

81+
- First, before initializing the group process, call `set_device <https://pytorch.org/docs/stable/generated/torch.cuda.set_device.html?highlight=set_device#torch.cuda.set_device>`__,
82+
which sets the default GPU for each process. This is important to prevent hangs or excessive memory utilization on `GPU:0`
8183
- The process group can be initialized by TCP (default) or from a
8284
shared file-system. Read more on `process group
8385
initialization <https://pytorch.org/docs/stable/distributed.html#tcp-initialization>`__
8486
- `init_process_group <https://pytorch.org/docs/stable/distributed.html?highlight=init_process_group#torch.distributed.init_process_group>`__
8587
initializes the distributed process group.
8688
- Read more about `choosing a DDP
8789
backend <https://pytorch.org/docs/stable/distributed.html#which-backend-to-use>`__
88-
- `set_device <https://pytorch.org/docs/stable/generated/torch.cuda.set_device.html?highlight=set_device#torch.cuda.set_device>`__
89-
sets the default GPU for each process. This is important to prevent hangs or excessive memory utilization on `GPU:0`
9090

9191
.. code-block:: diff
9292
@@ -98,8 +98,9 @@ Constructing the process group
9898
+ """
9999
+ os.environ["MASTER_ADDR"] = "localhost"
100100
+ os.environ["MASTER_PORT"] = "12355"
101-
+ init_process_group(backend="nccl", rank=rank, world_size=world_size)
102101
+ torch.cuda.set_device(rank)
102+
+ init_process_group(backend="nccl", rank=rank, world_size=world_size)
103+
103104
104105
105106
Constructing the DDP model

beginner_source/knowledge_distillation_tutorial.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ def train_knowledge_distillation(teacher, student, train_loader, epochs, learnin
324324
soft_prob = nn.functional.log_softmax(student_logits / T, dim=-1)
325325

326326
# Calculate the soft targets loss. Scaled by T**2 as suggested by the authors of the paper "Distilling the knowledge in a neural network"
327-
soft_targets_loss = -torch.sum(soft_targets * soft_prob) / soft_prob.size()[0] * (T**2)
327+
soft_targets_loss = torch.sum(soft_targets * (soft_targets.log() - soft_prob)) / soft_prob.size()[0] * (T**2)
328328

329329
# Calculate the true label loss
330330
label_loss = ce_loss(student_logits, labels)

beginner_source/saving_loading_models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@
160160
# The 1.6 release of PyTorch switched ``torch.save`` to use a new
161161
# zip file-based format. ``torch.load`` still retains the ability to
162162
# load files in the old format. If for any reason you want ``torch.save``
163-
# to use the old format, pass the ``kwarg``parameter ``_use_new_zipfile_serialization=False``.
163+
# to use the old format, pass the ``kwarg`` parameter ``_use_new_zipfile_serialization=False``.
164164
#
165165
# When saving a model for inference, it is only necessary to save the
166166
# trained model’s learned parameters. Saving the model’s *state_dict* with

conf.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@
4242
import distutils.file_util
4343
import re
4444
from get_sphinx_filenames import SPHINX_SHOULD_RUN
45-
45+
import pandocfilters
46+
import pypandoc
4647
import plotly.io as pio
4748
pio.renderers.default = 'sphinx_gallery'
4849

@@ -74,7 +75,8 @@
7475
'sphinx.ext.intersphinx',
7576
'sphinx_copybutton',
7677
'sphinx_gallery.gen_gallery',
77-
'sphinx_design'
78+
'sphinx_design',
79+
'nbsphinx'
7880
]
7981

8082
intersphinx_mapping = {
@@ -107,7 +109,10 @@ def reset_seeds(gallery_conf, fname):
107109
"# https://pytorch.org/tutorials/beginner/colab\n"
108110
"%matplotlib inline"),
109111
'reset_modules': (reset_seeds),
110-
'ignore_pattern': r'_torch_export_nightly_tutorial.py'
112+
'ignore_pattern': r'_torch_export_nightly_tutorial.py',
113+
'pypandoc': {'extra_args': ['--mathjax', '--toc'],
114+
'filters': ['.jenkins/custom_pandoc_filter.py'],
115+
},
111116
}
112117

113118
if os.getenv('GALLERY_PATTERN'):

intermediate_source/char_rnn_generation_tutorial.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
**Author**: `Sean Robertson <https://github.com/spro>`_
66
77
This is our second of three tutorials on "NLP From Scratch".
8-
In the `first tutorial </intermediate/char_rnn_classification_tutorial>`_
8+
In the `first tutorial </tutorials/intermediate/char_rnn_classification_tutorial>`_
99
we used a RNN to classify names into their language of origin. This time
1010
we'll turn around and generate names from languages.
1111

recipes_source/quantization.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ The full documentation of the `quantize_dynamic` API call is `here <https://pyto
8181
3. Post Training Static Quantization
8282
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8383

84-
This method converts both the weights and the activations to 8-bit integers beforehand so there won't be on-the-fly conversion on the activations during the inference, as the dynamic quantization does, hence improving the performance significantly.
84+
This method converts both the weights and the activations to 8-bit integers beforehand so there wont be on-the-fly conversion on the activations during the inference, as the dynamic quantization does. While post-training static quantization can significantly enhance inference speed and reduce model size, this method may degrade the original model's accuracy more compared to post training dynamic quantization.
8585

8686
To apply static quantization on a model, run the following code:
8787

0 commit comments

Comments
 (0)