mirror of
https://github.com/facebookresearch/pytorch3d.git
synced 2025-08-01 03:12:49 +08:00
876 lines
64 KiB
HTML
876 lines
64 KiB
HTML
<!DOCTYPE html><html lang=""><head><meta charSet="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><title>PyTorch3D · A library for deep learning with 3D data</title><meta name="viewport" content="width=device-width, initial-scale=1.0"/><meta name="generator" content="Docusaurus"/><meta name="description" content="A library for deep learning with 3D data"/><meta property="og:title" content="PyTorch3D · A library for deep learning with 3D data"/><meta property="og:type" content="website"/><meta property="og:url" content="https://pytorch3d.org/"/><meta property="og:description" content="A library for deep learning with 3D data"/><meta property="og:image" content="https://pytorch3d.org/img/pytorch3dlogoicon.svg"/><meta name="twitter:card" content="summary"/><meta name="twitter:image" content="https://pytorch3d.org/img/pytorch3dlogoicon.svg"/><link rel="shortcut icon" href="/img/pytorch3dfavicon.png"/><link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css"/><script>
|
||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||
|
||
ga('create', 'UA-157376881-1', 'auto');
|
||
ga('send', 'pageview');
|
||
</script><script type="text/javascript" src="https://buttons.github.io/buttons.js"></script><script src="/js/scrollSpy.js"></script><link rel="stylesheet" href="/css/main.css"/><script src="/js/codetabs.js"></script></head><body><div class="fixedHeaderContainer"><div class="headerWrapper wrapper"><header><a href="/"><img class="logo" src="/img/pytorch3dfavicon.png" alt="PyTorch3D"/><h2 class="headerTitleWithLogo">PyTorch3D</h2></a><div class="navigationWrapper navigationSlider"><nav class="slidingNav"><ul class="nav-site nav-site-internal"><li class=""><a href="/docs/why_pytorch3d" target="_self">Docs</a></li><li class=""><a href="/tutorials" target="_self">Tutorials</a></li><li class=""><a href="https://pytorch3d.readthedocs.io/" target="_self">API</a></li><li class=""><a href="https://github.com/facebookresearch/pytorch3d" target="_self">GitHub</a></li></ul></nav></div></header></div></div><div class="navPusher"><div class="docMainWrapper wrapper"><div class="container docsNavContainer" id="docsNav"><nav class="toc"><div class="toggleNav"><section class="navWrapper wrapper"><div class="navBreadcrumb wrapper"><div class="navToggle" id="navToggler"><div class="hamburger-menu"><div class="line1"></div><div class="line2"></div><div class="line3"></div></div></div><h2><i>›</i><span></span></h2><div class="tocToggler" id="tocToggler"><i class="icon-toc"></i></div></div><div class="navGroups"><div class="navGroup"><h3 class="navGroupCategoryTitle">Tutorials</h3><ul class=""><li class="navListItem"><a class="navItem" href="/tutorials/">Overview</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">3D operators</h3><ul class=""><li class="navListItem"><a class="navItem" href="/tutorials/deform_source_mesh_to_target_mesh">Fit Mesh</a></li><li class="navListItem"><a class="navItem" href="/tutorials/bundle_adjustment">Bundle Adjustment</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Rendering</h3><ul class=""><li class="navListItem"><a class="navItem" href="/tutorials/render_textured_meshes">Render Textured Meshes</a></li><li class="navListItem"><a class="navItem" href="/tutorials/render_densepose">Render DensePose Meshes</a></li><li class="navListItem"><a class="navItem" href="/tutorials/render_colored_points">Render Colored Pointclouds</a></li><li class="navListItem"><a class="navItem" href="/tutorials/fit_textured_mesh">Fit a Mesh with Texture via Rendering</a></li><li class="navListItem"><a class="navItem" href="/tutorials/camera_position_optimization_with_differentiable_rendering">Camera Position Optimization with Differentiable Rendering</a></li><li class="navListItem"><a class="navItem" href="/tutorials/fit_textured_volume">Fit a volume via raymarching</a></li><li class="navListItem"><a class="navItem" href="/tutorials/fit_simple_neural_radiance_field">Fit a simplified NeRF via raymarching</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Dataloaders</h3><ul class=""><li class="navListItem"><a class="navItem" href="/tutorials/dataloaders_ShapeNetCore_R2N2">Data loaders for ShapeNetCore and R2N2</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Implicitron</h3><ul class=""><li class="navListItem"><a class="navItem" href="/tutorials/implicitron_volumes">Training a custom volumes function with implicitron</a></li><li class="navListItem navListItemActive"><a class="navItem" href="/tutorials/implicitron_config_system">Implicitron config system deep dive</a></li></ul></div></div></section></div><script>
|
||
var coll = document.getElementsByClassName('collapsible');
|
||
var checkActiveCategory = true;
|
||
for (var i = 0; i < coll.length; i++) {
|
||
var links = coll[i].nextElementSibling.getElementsByTagName('*');
|
||
if (checkActiveCategory){
|
||
for (var j = 0; j < links.length; j++) {
|
||
if (links[j].classList.contains('navListItemActive')){
|
||
coll[i].nextElementSibling.classList.toggle('hide');
|
||
coll[i].childNodes[1].classList.toggle('rotate');
|
||
checkActiveCategory = false;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
coll[i].addEventListener('click', function() {
|
||
var arrow = this.childNodes[1];
|
||
arrow.classList.toggle('rotate');
|
||
var content = this.nextElementSibling;
|
||
content.classList.toggle('hide');
|
||
});
|
||
}
|
||
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
createToggler('#navToggler', '#docsNav', 'docsSliderActive');
|
||
createToggler('#tocToggler', 'body', 'tocActive');
|
||
|
||
var headings = document.querySelector('.toc-headings');
|
||
headings && headings.addEventListener('click', function(event) {
|
||
var el = event.target;
|
||
while(el !== headings){
|
||
if (el.tagName === 'A') {
|
||
document.body.classList.remove('tocActive');
|
||
break;
|
||
} else{
|
||
el = el.parentNode;
|
||
}
|
||
}
|
||
}, false);
|
||
|
||
function createToggler(togglerSelector, targetSelector, className) {
|
||
var toggler = document.querySelector(togglerSelector);
|
||
var target = document.querySelector(targetSelector);
|
||
|
||
if (!toggler) {
|
||
return;
|
||
}
|
||
|
||
toggler.onclick = function(event) {
|
||
event.preventDefault();
|
||
|
||
target.classList.toggle(className);
|
||
};
|
||
}
|
||
});
|
||
</script></nav></div><div class="container mainContainer"><div class="wrapper"><div class="tutorialButtonsWrapper"><div class="tutorialButtonWrapper buttonWrapper"><a class="tutorialButton button" download="" href="https://colab.research.google.com/github/facebookresearch/pytorch3d/blob/stable/docs/tutorials/implicitron_config_system.ipynb" target="_blank"><img class="colabButton" align="left" src="/img/colab_icon.png"/>Run in Google Colab</a></div><div class="tutorialButtonWrapper buttonWrapper"><a class="tutorialButton button" download="" href="/files/implicitron_config_system.ipynb" target="_blank"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="file-download" class="svg-inline--fa fa-file-download fa-w-12" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path fill="currentColor" d="M224 136V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm76.45 211.36l-96.42 95.7c-6.65 6.61-17.39 6.61-24.04 0l-96.42-95.7C73.42 337.29 80.54 320 94.82 320H160v-80c0-8.84 7.16-16 16-16h32c8.84 0 16 7.16 16 16v80h65.18c14.28 0 21.4 17.29 11.27 27.36zM377 105L279.1 7c-4.5-4.5-10.6-7-17-7H256v128h128v-6.1c0-6.3-2.5-12.4-7-16.9z"></path></svg>Download Tutorial Jupyter Notebook</a></div><div class="tutorialButtonWrapper buttonWrapper"><a class="tutorialButton button" download="" href="/files/implicitron_config_system.py" target="_blank"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="file-download" class="svg-inline--fa fa-file-download fa-w-12" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path fill="currentColor" d="M224 136V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm76.45 211.36l-96.42 95.7c-6.65 6.61-17.39 6.61-24.04 0l-96.42-95.7C73.42 337.29 80.54 320 94.82 320H160v-80c0-8.84 7.16-16 16-16h32c8.84 0 16 7.16 16 16v80h65.18c14.28 0 21.4 17.29 11.27 27.36zM377 105L279.1 7c-4.5-4.5-10.6-7-17-7H256v128h128v-6.1c0-6.3-2.5-12.4-7-16.9z"></path></svg>Download Tutorial Source Code</a></div></div><div class="tutorialBody">
|
||
<script
|
||
src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js">
|
||
</script>
|
||
<script
|
||
src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js">
|
||
</script>
|
||
<div class="notebook">
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="c1"># Copyright (c) Meta Platforms, Inc. and affiliates. All rights reserved.</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<h1 id="Implicitron's-config-system">Implicitron's config system<a class="anchor-link" href="#Implicitron's-config-system">¶</a></h1>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<p>Implicitron's components are all based on a unified hierarchical configuration system.
|
||
This allows configurable variables and all defaults to be defined separately for each new component.
|
||
All configs relevant to an experiment are then automatically composed into a single configuration file that fully specifies the experiment.
|
||
An especially important feature is extension points where users can insert their own sub-classes of Implicitron's base components.</p>
|
||
<p>The file which defines this system is <a href="https://github.com/facebookresearch/pytorch3d/blob/main/pytorch3d/implicitron/tools/config.py">here</a> in the PyTorch3D repo.
|
||
The Implicitron volumes tutorial contains a simple example of using the config system.
|
||
This tutorial provides detailed hands-on experience in using and modifying Implicitron's configurable components.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<h2 id="0.-Install-and-import-modules">0. Install and import modules<a class="anchor-link" href="#0.-Install-and-import-modules">¶</a></h2><p>Ensure <code>torch</code> and <code>torchvision</code> are installed. If <code>pytorch3d</code> is not installed, install it using the following cell:</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="kn">import</span> <span class="nn">os</span>
|
||
<span class="kn">import</span> <span class="nn">sys</span>
|
||
<span class="kn">import</span> <span class="nn">torch</span>
|
||
<span class="n">need_pytorch3d</span><span class="o">=</span><span class="kc">False</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="kn">import</span> <span class="nn">pytorch3d</span>
|
||
<span class="k">except</span> <span class="ne">ModuleNotFoundError</span><span class="p">:</span>
|
||
<span class="n">need_pytorch3d</span><span class="o">=</span><span class="kc">True</span>
|
||
<span class="k">if</span> <span class="n">need_pytorch3d</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="n">torch</span><span class="o">.</span><span class="n">__version__</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"2.2."</span><span class="p">)</span> <span class="ow">and</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"linux"</span><span class="p">):</span>
|
||
<span class="c1"># We try to install PyTorch3D via a released wheel.</span>
|
||
<span class="n">pyt_version_str</span><span class="o">=</span><span class="n">torch</span><span class="o">.</span><span class="n">__version__</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"+"</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">"."</span><span class="p">,</span> <span class="s2">""</span><span class="p">)</span>
|
||
<span class="n">version_str</span><span class="o">=</span><span class="s2">""</span><span class="o">.</span><span class="n">join</span><span class="p">([</span>
|
||
<span class="sa">f</span><span class="s2">"py3</span><span class="si">{</span><span class="n">sys</span><span class="o">.</span><span class="n">version_info</span><span class="o">.</span><span class="n">minor</span><span class="si">}</span><span class="s2">_cu"</span><span class="p">,</span>
|
||
<span class="n">torch</span><span class="o">.</span><span class="n">version</span><span class="o">.</span><span class="n">cuda</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">"."</span><span class="p">,</span><span class="s2">""</span><span class="p">),</span>
|
||
<span class="sa">f</span><span class="s2">"_pyt</span><span class="si">{</span><span class="n">pyt_version_str</span><span class="si">}</span><span class="s2">"</span>
|
||
<span class="p">])</span>
|
||
<span class="o">!</span>pip<span class="w"> </span>install<span class="w"> </span>fvcore<span class="w"> </span>iopath
|
||
<span class="o">!</span>pip<span class="w"> </span>install<span class="w"> </span>--no-index<span class="w"> </span>--no-cache-dir<span class="w"> </span>pytorch3d<span class="w"> </span>-f<span class="w"> </span>https://dl.fbaipublicfiles.com/pytorch3d/packaging/wheels/<span class="o">{</span>version_str<span class="o">}</span>/download.html
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="c1"># We try to install PyTorch3D from source.</span>
|
||
<span class="o">!</span>pip<span class="w"> </span>install<span class="w"> </span><span class="s1">'git+https://github.com/facebookresearch/pytorch3d.git@stable'</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<p>Ensure omegaconf is installed. If not, run this cell. (It should not be necessary to restart the runtime.)</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="o">!</span>pip<span class="w"> </span>install<span class="w"> </span>omegaconf
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="kn">from</span> <span class="nn">dataclasses</span> <span class="kn">import</span> <span class="n">dataclass</span>
|
||
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Optional</span><span class="p">,</span> <span class="n">Tuple</span>
|
||
|
||
<span class="kn">import</span> <span class="nn">torch</span>
|
||
<span class="kn">from</span> <span class="nn">omegaconf</span> <span class="kn">import</span> <span class="n">DictConfig</span><span class="p">,</span> <span class="n">OmegaConf</span>
|
||
<span class="kn">from</span> <span class="nn">pytorch3d.implicitron.tools.config</span> <span class="kn">import</span> <span class="p">(</span>
|
||
<span class="n">Configurable</span><span class="p">,</span>
|
||
<span class="n">ReplaceableBase</span><span class="p">,</span>
|
||
<span class="n">expand_args_fields</span><span class="p">,</span>
|
||
<span class="n">get_default_args</span><span class="p">,</span>
|
||
<span class="n">registry</span><span class="p">,</span>
|
||
<span class="n">run_auto_creation</span><span class="p">,</span>
|
||
<span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<h2 id="1.-Introducing-dataclasses">1. Introducing dataclasses<a class="anchor-link" href="#1.-Introducing-dataclasses">¶</a></h2><p><a href="https://docs.python.org/3/library/typing.html">Type hints</a> give a taxonomy of types in Python. <a href="https://docs.python.org/3/library/dataclasses.html">Dataclasses</a> let you create a class based on a list of members which have names, types and possibly default values. The <code>__init__</code> function is created automatically, and calls a <code>__post_init__</code> function if present as a final step. For example</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="nd">@dataclass</span>
|
||
<span class="k">class</span> <span class="nc">MyDataclass</span><span class="p">:</span>
|
||
<span class="n">a</span><span class="p">:</span> <span class="nb">int</span>
|
||
<span class="n">b</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">8</span>
|
||
<span class="n">c</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Tuple</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="o">...</span><span class="p">]]</span> <span class="o">=</span> <span class="kc">None</span>
|
||
|
||
<span class="k">def</span> <span class="nf">__post_init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"created with a = </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">a</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">d</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">b</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="n">my_dataclass_instance</span> <span class="o">=</span> <span class="n">MyDataclass</span><span class="p">(</span><span class="n">a</span><span class="o">=</span><span class="mi">18</span><span class="p">)</span>
|
||
<span class="k">assert</span> <span class="n">my_dataclass_instance</span><span class="o">.</span><span class="n">d</span> <span class="o">==</span> <span class="mi">16</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<p>👷 Note that the <code>dataclass</code> decorator here is function which modifies the definition of the class itself.
|
||
It runs immediately after the definition.
|
||
Our config system requires that implicitron library code contains classes whose modified versions need to be aware of user-defined implementations.
|
||
Therefore we need the modification of the class to be delayed. We don't use a decorator.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<h2 id="2.-Introducing-omegaconf-and-OmegaConf.structured">2. Introducing omegaconf and OmegaConf.structured<a class="anchor-link" href="#2.-Introducing-omegaconf-and-OmegaConf.structured">¶</a></h2><p>The <a href="https://github.com/omry/omegaconf/">omegaconf</a> library provides a DictConfig class which is like a <code>dict</code> with str keys, but with extra features for ease-of-use as a configuration system.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="n">dc</span> <span class="o">=</span> <span class="n">DictConfig</span><span class="p">({</span><span class="s2">"a"</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="s2">"b"</span><span class="p">:</span> <span class="kc">True</span><span class="p">,</span> <span class="s2">"c"</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span> <span class="s2">"d"</span><span class="p">:</span> <span class="s2">"hello"</span><span class="p">})</span>
|
||
<span class="k">assert</span> <span class="n">dc</span><span class="o">.</span><span class="n">a</span> <span class="o">==</span> <span class="n">dc</span><span class="p">[</span><span class="s2">"a"</span><span class="p">]</span> <span class="o">==</span> <span class="mi">2</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<p>OmegaConf has a serialization to and from yaml. The <a href="https://hydra.cc/">Hydra</a> library relies on this for its configuration files.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="nb">print</span><span class="p">(</span><span class="n">OmegaConf</span><span class="o">.</span><span class="n">to_yaml</span><span class="p">(</span><span class="n">dc</span><span class="p">))</span>
|
||
<span class="k">assert</span> <span class="n">OmegaConf</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">OmegaConf</span><span class="o">.</span><span class="n">to_yaml</span><span class="p">(</span><span class="n">dc</span><span class="p">))</span> <span class="o">==</span> <span class="n">dc</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<p>OmegaConf.structured provides a DictConfig from a dataclass or instance of a dataclass. Unlike a normal DictConfig, it is type-checked and only known keys can be added.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="n">structured</span> <span class="o">=</span> <span class="n">OmegaConf</span><span class="o">.</span><span class="n">structured</span><span class="p">(</span><span class="n">MyDataclass</span><span class="p">)</span>
|
||
<span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">structured</span><span class="p">,</span> <span class="n">DictConfig</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">structured</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">()</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">OmegaConf</span><span class="o">.</span><span class="n">to_yaml</span><span class="p">(</span><span class="n">structured</span><span class="p">))</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<p><code>structured</code> knows it is missing a value for <code>a</code>.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<p>Such an object has members compatible with the dataclass, so an initialisation can be performed as follows.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="n">structured</span><span class="o">.</span><span class="n">a</span> <span class="o">=</span> <span class="mi">21</span>
|
||
<span class="n">my_dataclass_instance2</span> <span class="o">=</span> <span class="n">MyDataclass</span><span class="p">(</span><span class="o">**</span><span class="n">structured</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">my_dataclass_instance2</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<p>You can also call OmegaConf.structured on an instance.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="n">structured_from_instance</span> <span class="o">=</span> <span class="n">OmegaConf</span><span class="o">.</span><span class="n">structured</span><span class="p">(</span><span class="n">my_dataclass_instance</span><span class="p">)</span>
|
||
<span class="n">my_dataclass_instance3</span> <span class="o">=</span> <span class="n">MyDataclass</span><span class="p">(</span><span class="o">**</span><span class="n">structured_from_instance</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">my_dataclass_instance3</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<h2 id="3.-Our-approach-to-OmegaConf.structured">3. Our approach to OmegaConf.structured<a class="anchor-link" href="#3.-Our-approach-to-OmegaConf.structured">¶</a></h2><p>We provide functions which are equivalent to <code>OmegaConf.structured</code> but support more features.
|
||
To achieve the above using our functions, the following is used.
|
||
Note that we indicate configurable classes using a special base class <code>Configurable</code>, not a decorator.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="k">class</span> <span class="nc">MyConfigurable</span><span class="p">(</span><span class="n">Configurable</span><span class="p">):</span>
|
||
<span class="n">a</span><span class="p">:</span> <span class="nb">int</span>
|
||
<span class="n">b</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">8</span>
|
||
<span class="n">c</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Tuple</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="o">...</span><span class="p">]]</span> <span class="o">=</span> <span class="kc">None</span>
|
||
|
||
<span class="k">def</span> <span class="nf">__post_init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"created with a = </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">a</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">d</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">b</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="c1"># The expand_args_fields function modifies the class like @dataclasses.dataclass.</span>
|
||
<span class="c1"># If it has not been called on a Configurable object before it has been instantiated, it will</span>
|
||
<span class="c1"># be called automatically.</span>
|
||
<span class="n">expand_args_fields</span><span class="p">(</span><span class="n">MyConfigurable</span><span class="p">)</span>
|
||
<span class="n">my_configurable_instance</span> <span class="o">=</span> <span class="n">MyConfigurable</span><span class="p">(</span><span class="n">a</span><span class="o">=</span><span class="mi">18</span><span class="p">)</span>
|
||
<span class="k">assert</span> <span class="n">my_configurable_instance</span><span class="o">.</span><span class="n">d</span> <span class="o">==</span> <span class="mi">16</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="c1"># get_default_args also calls expand_args_fields automatically</span>
|
||
<span class="n">our_structured</span> <span class="o">=</span> <span class="n">get_default_args</span><span class="p">(</span><span class="n">MyConfigurable</span><span class="p">)</span>
|
||
<span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">our_structured</span><span class="p">,</span> <span class="n">DictConfig</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">OmegaConf</span><span class="o">.</span><span class="n">to_yaml</span><span class="p">(</span><span class="n">our_structured</span><span class="p">))</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="n">our_structured</span><span class="o">.</span><span class="n">a</span> <span class="o">=</span> <span class="mi">21</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">MyConfigurable</span><span class="p">(</span><span class="o">**</span><span class="n">our_structured</span><span class="p">))</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<h2 id="4.-First-enhancement:-nested-types-🪺">4. First enhancement: nested types 🪺<a class="anchor-link" href="#4.-First-enhancement:-nested-types-🪺">¶</a></h2><p>Our system allows Configurable classes to contain each other.
|
||
One thing to remember: add a call to <code>run_auto_creation</code> in <code>__post_init__</code>.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="k">class</span> <span class="nc">Inner</span><span class="p">(</span><span class="n">Configurable</span><span class="p">):</span>
|
||
<span class="n">a</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">8</span>
|
||
<span class="n">b</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">True</span>
|
||
<span class="n">c</span><span class="p">:</span> <span class="n">Tuple</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="o">...</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">6</span><span class="p">)</span>
|
||
|
||
|
||
<span class="k">class</span> <span class="nc">Outer</span><span class="p">(</span><span class="n">Configurable</span><span class="p">):</span>
|
||
<span class="n">inner</span><span class="p">:</span> <span class="n">Inner</span>
|
||
<span class="n">x</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="s2">"hello"</span>
|
||
<span class="n">xx</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span>
|
||
|
||
<span class="k">def</span> <span class="nf">__post_init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="n">run_auto_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="n">outer_dc</span> <span class="o">=</span> <span class="n">get_default_args</span><span class="p">(</span><span class="n">Outer</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">OmegaConf</span><span class="o">.</span><span class="n">to_yaml</span><span class="p">(</span><span class="n">outer_dc</span><span class="p">))</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="n">outer</span> <span class="o">=</span> <span class="n">Outer</span><span class="p">(</span><span class="o">**</span><span class="n">outer_dc</span><span class="p">)</span>
|
||
<span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">outer</span><span class="p">,</span> <span class="n">Outer</span><span class="p">)</span>
|
||
<span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">outer</span><span class="o">.</span><span class="n">inner</span><span class="p">,</span> <span class="n">Inner</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="nb">vars</span><span class="p">(</span><span class="n">outer</span><span class="p">))</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">outer</span><span class="o">.</span><span class="n">inner</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<p>Note how inner_args is an extra member of outer. <code>run_auto_creation(self)</code> is equivalent to</p>
|
||
<pre><code> self.inner = Inner(**self.inner_args)</code></pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<h2 id="5.-Second-enhancement:-pluggable/replaceable-components-🔌">5. Second enhancement: pluggable/replaceable components 🔌<a class="anchor-link" href="#5.-Second-enhancement:-pluggable/replaceable-components-🔌">¶</a></h2><p>If a class uses <code>ReplaceableBase</code> as a base class instead of <code>Configurable</code>, we call it a replaceable.
|
||
It indicates that it is designed for child classes to use in its place.
|
||
We might use <code>NotImplementedError</code> to indicate functionality which subclasses are expected to implement.
|
||
The system maintains a global <code>registry</code> containing subclasses of each ReplaceableBase.
|
||
The subclasses register themselves with it with a decorator.</p>
|
||
<p>A configurable class (i.e. a class which uses our system, i.e. a child of <code>Configurable</code> or <code>ReplaceableBase</code>) which contains a ReplaceableBase must also
|
||
contain a corresponding class_type field of type <code>str</code> which indicates which concrete child class to use.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="k">class</span> <span class="nc">InnerBase</span><span class="p">(</span><span class="n">ReplaceableBase</span><span class="p">):</span>
|
||
<span class="k">def</span> <span class="nf">say_something</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
|
||
|
||
|
||
<span class="nd">@registry</span><span class="o">.</span><span class="n">register</span>
|
||
<span class="k">class</span> <span class="nc">Inner1</span><span class="p">(</span><span class="n">InnerBase</span><span class="p">):</span>
|
||
<span class="n">a</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">1</span>
|
||
<span class="n">b</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="s2">"h"</span>
|
||
|
||
<span class="k">def</span> <span class="nf">say_something</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"hello from an Inner1"</span><span class="p">)</span>
|
||
|
||
|
||
<span class="nd">@registry</span><span class="o">.</span><span class="n">register</span>
|
||
<span class="k">class</span> <span class="nc">Inner2</span><span class="p">(</span><span class="n">InnerBase</span><span class="p">):</span>
|
||
<span class="n">a</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">2</span>
|
||
|
||
<span class="k">def</span> <span class="nf">say_something</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"hello from an Inner2"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="k">class</span> <span class="nc">Out</span><span class="p">(</span><span class="n">Configurable</span><span class="p">):</span>
|
||
<span class="n">inner</span><span class="p">:</span> <span class="n">InnerBase</span>
|
||
<span class="n">inner_class_type</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="s2">"Inner1"</span>
|
||
<span class="n">x</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">19</span>
|
||
|
||
<span class="k">def</span> <span class="nf">__post_init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="n">run_auto_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">talk</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">inner</span><span class="o">.</span><span class="n">say_something</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="n">Out_dc</span> <span class="o">=</span> <span class="n">get_default_args</span><span class="p">(</span><span class="n">Out</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">OmegaConf</span><span class="o">.</span><span class="n">to_yaml</span><span class="p">(</span><span class="n">Out_dc</span><span class="p">))</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="n">Out_dc</span><span class="o">.</span><span class="n">inner_class_type</span> <span class="o">=</span> <span class="s2">"Inner2"</span>
|
||
<span class="n">out</span> <span class="o">=</span> <span class="n">Out</span><span class="p">(</span><span class="o">**</span><span class="n">Out_dc</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">out</span><span class="o">.</span><span class="n">inner</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="n">out</span><span class="o">.</span><span class="n">talk</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<p>Note in this case there are many <code>args</code> members. It is usually fine to ignore them in the code. They are needed for the config.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="nb">print</span><span class="p">(</span><span class="nb">vars</span><span class="p">(</span><span class="n">out</span><span class="p">))</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<h2 id="6.-Example-with-torch.nn.Module--🔥">6. Example with torch.nn.Module 🔥<a class="anchor-link" href="#6.-Example-with-torch.nn.Module--🔥">¶</a></h2><p>Typically in implicitron, we use this system in combination with <a href="https://pytorch.org/docs/stable/generated/torch.nn.Module.html"><code>Module</code></a>s.
|
||
Note in this case it is necessary to call <code>Module.__init__</code> explicitly in <code>__post_init__</code>.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="k">class</span> <span class="nc">MyLinear</span><span class="p">(</span><span class="n">torch</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">Module</span><span class="p">,</span> <span class="n">Configurable</span><span class="p">):</span>
|
||
<span class="n">d_in</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">2</span>
|
||
<span class="n">d_out</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">200</span>
|
||
|
||
<span class="k">def</span> <span class="nf">__post_init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">()</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">linear</span> <span class="o">=</span> <span class="n">torch</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">Linear</span><span class="p">(</span><span class="n">in_features</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">d_in</span><span class="p">,</span> <span class="n">out_features</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">d_out</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">forward</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">linear</span><span class="o">.</span><span class="n">forward</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="n">my_linear</span> <span class="o">=</span> <span class="n">MyLinear</span><span class="p">()</span>
|
||
<span class="nb">input</span> <span class="o">=</span> <span class="n">torch</span><span class="o">.</span><span class="n">zeros</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
|
||
<span class="n">output</span> <span class="o">=</span> <span class="n">my_linear</span><span class="p">(</span><span class="nb">input</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"output shape:"</span><span class="p">,</span> <span class="n">output</span><span class="o">.</span><span class="n">shape</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<p><code>my_linear</code> has all the usual features of a Module.
|
||
E.g. it can be saved and loaded with <code>torch.save</code> and <code>torch.load</code>.
|
||
It has parameters:</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">my_linear</span><span class="o">.</span><span class="n">named_parameters</span><span class="p">():</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="o">.</span><span class="n">shape</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<h2 id="7.-Example-of-implementing-your-own-pluggable-component">7. Example of implementing your own pluggable component<a class="anchor-link" href="#7.-Example-of-implementing-your-own-pluggable-component">¶</a></h2><p>Let's say I am using a library with <code>Out</code> like in section <strong>5</strong> but I want to implement my own child of InnerBase.
|
||
All I need to do is register its definition, but I need to do this before expand_args_fields is explicitly or implicitly called on Out.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="nd">@registry</span><span class="o">.</span><span class="n">register</span>
|
||
<span class="k">class</span> <span class="nc">UserImplementedInner</span><span class="p">(</span><span class="n">InnerBase</span><span class="p">):</span>
|
||
<span class="n">a</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">200</span>
|
||
|
||
<span class="k">def</span> <span class="nf">say_something</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"hello from the user"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<p>At this point, we need to redefine the class Out.
|
||
Otherwise if it has already been expanded without UserImplementedInner, then the following would not work,
|
||
because the implementations known to a class are fixed when it is expanded.</p>
|
||
<p>If you are running experiments from a script, the thing to remember here is that you must import your own modules, which register your own implementations,
|
||
before you <em>use</em> the library classes.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="k">class</span> <span class="nc">Out</span><span class="p">(</span><span class="n">Configurable</span><span class="p">):</span>
|
||
<span class="n">inner</span><span class="p">:</span> <span class="n">InnerBase</span>
|
||
<span class="n">inner_class_type</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="s2">"Inner1"</span>
|
||
<span class="n">x</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">19</span>
|
||
|
||
<span class="k">def</span> <span class="nf">__post_init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="n">run_auto_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">talk</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">inner</span><span class="o">.</span><span class="n">say_something</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="n">out2</span> <span class="o">=</span> <span class="n">Out</span><span class="p">(</span><span class="n">inner_class_type</span><span class="o">=</span><span class="s2">"UserImplementedInner"</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">out2</span><span class="o">.</span><span class="n">inner</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<h2 id="8:-Example-of-making-a-subcomponent-pluggable">8: Example of making a subcomponent pluggable<a class="anchor-link" href="#8:-Example-of-making-a-subcomponent-pluggable">¶</a></h2><p>Let's look what needs to happen if we have a subcomponent which we make pluggable, to allow users to supply their own.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="k">class</span> <span class="nc">SubComponent</span><span class="p">(</span><span class="n">Configurable</span><span class="p">):</span>
|
||
<span class="n">x</span><span class="p">:</span> <span class="nb">float</span> <span class="o">=</span> <span class="mf">0.25</span>
|
||
|
||
<span class="k">def</span> <span class="nf">apply</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">a</span><span class="p">:</span> <span class="nb">float</span><span class="p">)</span> <span class="o">-></span> <span class="nb">float</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="n">a</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">x</span>
|
||
|
||
|
||
<span class="k">class</span> <span class="nc">LargeComponent</span><span class="p">(</span><span class="n">Configurable</span><span class="p">):</span>
|
||
<span class="n">repeats</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">4</span>
|
||
<span class="n">subcomponent</span><span class="p">:</span> <span class="n">SubComponent</span>
|
||
|
||
<span class="k">def</span> <span class="nf">__post_init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="n">run_auto_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">apply</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">a</span><span class="p">:</span> <span class="nb">float</span><span class="p">)</span> <span class="o">-></span> <span class="nb">float</span><span class="p">:</span>
|
||
<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">repeats</span><span class="p">):</span>
|
||
<span class="n">a</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">subcomponent</span><span class="o">.</span><span class="n">apply</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="n">a</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="n">large_component</span> <span class="o">=</span> <span class="n">LargeComponent</span><span class="p">()</span>
|
||
<span class="k">assert</span> <span class="n">large_component</span><span class="o">.</span><span class="n">apply</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span> <span class="o">==</span> <span class="mi">4</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">OmegaConf</span><span class="o">.</span><span class="n">to_yaml</span><span class="p">(</span><span class="n">LargeComponent</span><span class="p">))</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<p>Made generic:</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="k">class</span> <span class="nc">SubComponentBase</span><span class="p">(</span><span class="n">ReplaceableBase</span><span class="p">):</span>
|
||
<span class="k">def</span> <span class="nf">apply</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">a</span><span class="p">:</span> <span class="nb">float</span><span class="p">)</span> <span class="o">-></span> <span class="nb">float</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
|
||
|
||
|
||
<span class="nd">@registry</span><span class="o">.</span><span class="n">register</span>
|
||
<span class="k">class</span> <span class="nc">SubComponent</span><span class="p">(</span><span class="n">SubComponentBase</span><span class="p">):</span>
|
||
<span class="n">x</span><span class="p">:</span> <span class="nb">float</span> <span class="o">=</span> <span class="mf">0.25</span>
|
||
|
||
<span class="k">def</span> <span class="nf">apply</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">a</span><span class="p">:</span> <span class="nb">float</span><span class="p">)</span> <span class="o">-></span> <span class="nb">float</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="n">a</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">x</span>
|
||
|
||
|
||
<span class="k">class</span> <span class="nc">LargeComponent</span><span class="p">(</span><span class="n">Configurable</span><span class="p">):</span>
|
||
<span class="n">repeats</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">4</span>
|
||
<span class="n">subcomponent</span><span class="p">:</span> <span class="n">SubComponentBase</span>
|
||
<span class="n">subcomponent_class_type</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="s2">"SubComponent"</span>
|
||
|
||
<span class="k">def</span> <span class="nf">__post_init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="n">run_auto_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">apply</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">a</span><span class="p">:</span> <span class="nb">float</span><span class="p">)</span> <span class="o">-></span> <span class="nb">float</span><span class="p">:</span>
|
||
<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">repeats</span><span class="p">):</span>
|
||
<span class="n">a</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">subcomponent</span><span class="o">.</span><span class="n">apply</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="n">a</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="n">large_component</span> <span class="o">=</span> <span class="n">LargeComponent</span><span class="p">()</span>
|
||
<span class="k">assert</span> <span class="n">large_component</span><span class="o">.</span><span class="n">apply</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span> <span class="o">==</span> <span class="mi">4</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">OmegaConf</span><span class="o">.</span><span class="n">to_yaml</span><span class="p">(</span><span class="n">LargeComponent</span><span class="p">))</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<p>The following things had to change:</p>
|
||
<ul>
|
||
<li>The base class SubComponentBase was defined.</li>
|
||
<li>SubComponent gained a <code>@registry.register</code> decoration and had its base class changed to the new one.</li>
|
||
<li><code>subcomponent_class_type</code> was added as a member of the outer class.</li>
|
||
<li>In any saved configuration yaml files, the key <code>subcomponent_args</code> had to be changed to <code>subcomponent_SubComponent_args</code>.</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<h2 id="Appendix:-gotchas-⚠️">Appendix: gotchas ⚠️<a class="anchor-link" href="#Appendix:-gotchas-⚠️">¶</a></h2><ul>
|
||
<li>Omitting to define <code>__post_init__</code> or not calling <code>run_auto_creation</code> in it.</li>
|
||
<li>Omitting a type annotation on a field. For example, writing
|
||
<pre><code> subcomponent_class_type = "SubComponent"</code></pre>
|
||
instead of
|
||
<pre><code> subcomponent_class_type: str = "SubComponent"</code></pre>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div></div></div></div></div><footer class="nav-footer" id="footer"><section class="sitemap"><div class="footerSection"><div class="social"><a class="github-button" href="https://github.com/facebookresearch/pytorch3d" data-count-href="https://github.com/facebookresearch/pytorch3d/stargazers" data-show-count="true" data-count-aria-label="# stargazers on GitHub" aria-label="Star PyTorch3D on GitHub">pytorch3d</a></div></div></section><a href="https://opensource.facebook.com/" target="_blank" rel="noreferrer noopener" class="fbOpenSource"><img src="/img/oss_logo.png" alt="Facebook Open Source" width="170" height="45"/></a><section class="copyright">Copyright © 2024 Meta Platforms, Inc<br/>Legal:<a href="https://opensource.facebook.com/legal/privacy/" target="_blank" rel="noreferrer noopener">Privacy</a><a href="https://opensource.facebook.com/legal/terms/" target="_blank" rel="noreferrer noopener">Terms</a></section></footer></div></body></html> |