Improve CRPS Optimiality slides

This commit is contained in:
2025-06-21 14:58:55 +02:00
parent 9bc402b926
commit b49fa7d0db
2 changed files with 408 additions and 417 deletions

View File

@@ -26217,13 +26217,11 @@ Berrisch, J. <span class="citation" data-cites="berrisch2025rcpptimer">(<a href=
<p>Strictly proper for <em>median</em> predictions</p>
</div></div>
</section>
<section id="popular-algorithms-and-the-risk" class="slide level2">
<h2>Popular Algorithms and the Risk</h2>
<p><br></p>
<section id="section-1" class="slide level2">
<h2> </h2>
<div class="columns">
<div class="column" style="width:48%;">
<h3 id="popular-aggregation-algorithms">Popular Aggregation Algorithms</h3>
<p><br></p>
<h4 id="the-naive-combination">The naive combination</h4>
<p><span class="math display">\[\begin{equation}
w_{t,k}^{\text{Naive}} = \frac{1}{K}\label{eq:naive_combination}
@@ -26239,12 +26237,14 @@ w_{t,k}^{\text{Naive}} = \frac{1}{K}\label{eq:naive_combination}
</div><div class="column" style="width:4%;">
</div><div class="column" style="width:48%;">
<h3 id="optimality">Optimality</h3>
<p>In stochastic settings, the cumulative Risk should be analyzed <span class="citation" data-cites="wintenberger2017optimal">Wintenberger (<a href="#/references" role="doc-biblioref" onclick>2017</a>)</span>: <span class="math display">\[\begin{align}
<h3 id="risk">Risk</h3>
<p>In stochastic settings, the cumulative Risk should be analyzed <span class="citation" data-cites="wintenberger2017optimal">Wintenberger (<a href="#/references" role="doc-biblioref" onclick>2017</a>)</span>:</p>
<p><span class="math display">\[\begin{align}
&amp;\underbrace{\widetilde{\mathcal{R}}_t = \sum_{i=1}^t \mathbb{E}[\ell(\widetilde{X}_{i},Y_i)|\mathcal{F}_{i-1}]}_{\text{Cumulative Risk of Forecaster}} \\
&amp;\underbrace{\widehat{\mathcal{R}}_{t,k} = \sum_{i=1}^t \mathbb{E}[\ell(\widehat{X}_{i,k},Y_i)|\mathcal{F}_{i-1}]}_{\text{Cumulative Risk of Experts}}
\label{eq_def_cumrisk}
\end{align}\]</span></p>
<p><i class="fa fa-fw fa-arrow-right" style="color:var(--col_grey_9);"></i> (7) expected loss of the algorithm (lower = better)</p>
</div></div>
</section>
<section id="optimal-convergence" class="slide level2">
@@ -26283,18 +26283,17 @@ w_{t,k}^{\text{Naive}} = \frac{1}{K}\label{eq:naive_combination}
</ul>
</div></div>
</section>
<section id="section-1" class="slide level2">
<section id="section-2" class="slide level2">
<h2></h2>
<div class="columns">
<div class="column" style="width:48%;">
<h3 id="optimal-convergence-1">Optimal Convergence</h3>
<p><br></p>
<h4 id="requirements">Requirements:</h4>
<p>EWA satisfies optimal selection convergence <span class="math inline">\(\eqref{eq_optp_select}\)</span> in a deterministic setting if:</p>
<ul>
<li>Loss <span class="math inline">\(\ell\)</span> is exp-concave</li>
<li>Learning-rate <span class="math inline">\(\eta\)</span> is chosen correctly</li>
</ul>
<p>Those results can be converted to any stochastic setting <span class="citation" data-cites="wintenberger2017optimal">Wintenberger (<a href="#/references" role="doc-biblioref" onclick>2017</a>)</span>.</p>
<p><i class="fa fa-fw fa-triangle-exclamation" style="color:var(--col_amber_9);"></i> Loss <span class="math inline">\(\ell\)</span> is exp-concave</p>
<p><i class="fa fa-fw fa-triangle-exclamation" style="color:var(--col_amber_9);"></i> Learning-rate <span class="math inline">\(\eta\)</span> is chosen correctly</p>
<p>Those results can be converted to <em>any</em> stochastic setting <span class="citation" data-cites="wintenberger2017optimal">Wintenberger (<a href="#/references" role="doc-biblioref" onclick>2017</a>)</span>.</p>
<p>Optimal convex aggregation convergence <span class="math inline">\(\eqref{eq_optp_conv}\)</span> can be satisfied by applying the kernel-trick:</p>
<p><span class="math display">\[\begin{align}
\ell^{\nabla}(x,y) = \ell&#39;(\widetilde{X},y) x
@@ -26305,13 +26304,13 @@ w_{t,k}^{\text{Naive}} = \frac{1}{K}\label{eq:naive_combination}
</div><div class="column" style="width:48%;">
<h3 id="probabilistic-setting">Probabilistic Setting</h3>
<p><br></p>
<p><strong>An appropriate choice:</strong></p>
<h4 id="an-appropriate-choice">An appropriate choice:</h4>
<p><span class="math display">\[\begin{equation*}
\text{CRPS}(F, y) = \int_{\mathbb{R}} {(F(x) - \mathbb{1}\{ x &gt; y \})}^2 dx \label{eq:crps}
\end{equation*}\]</span></p>
<p>Its strictly proper <span class="citation" data-cites="gneiting2007strictly">(<a href="#/references" role="doc-biblioref" onclick>Gneiting &amp; Raftery, 2007</a>)</span>.</p>
<p>Using the CRPS, we can calculate time-adaptive weights <span class="math inline">\(w_{t,k}\)</span>. However, what if the experts performance varies in parts of the distribution?</p>
<p><i class="fa fa-fw fa-lightbulb" style="color:var(--col_yellow_9);"></i> Utilize this relation:</p>
<p><i class="fa fa-fw fa-lightbulb" style="color:var(--col_yellow_8);"></i> Utilize this relation:</p>
<p><span class="math display">\[\begin{equation*}
\text{CRPS}(F, y) = 2 \int_0^{1} \text{QL}_p(F^{-1}(p), y) dp.\label{eq_crps_qs}
\end{equation*}\]</span></p>
@@ -26321,17 +26320,18 @@ w_{t,k}^{\text{Naive}} = \frac{1}{K}\label{eq:naive_combination}
<section id="crps-learning-optimality" class="slide level2">
<h2>CRPS Learning Optimality</h2>
<div class="panel-tabset">
<ul id="tabset-2" class="panel-tabset-tabby"><li><a data-tabby-default href="#tabset-2-1">Almost Optimal Convergence</a></li><li><a href="#tabset-2-2">Conditions + Lemma</a></li><li><a href="#tabset-2-3">Proposition + Theorem</a></li></ul>
<ul id="tabset-2" class="panel-tabset-tabby"><li><a data-tabby-default href="#tabset-2-1">Almost Optimal Convergence</a></li><li><a href="#tabset-2-2">Proposition + Conditions</a></li><li><a href="#tabset-2-3">Proposition + Theorem</a></li></ul>
<div class="tab-content">
<div id="tabset-2-1">
<div style="font-size: 90%;">
<p><i class="fa fa-fw fa-exclamation" style="color:var(--col_orange_10);"></i> QL is convex, but not exp-concave</p>
<div style="font-size: 85%;">
<p><i class="fa fa-fw fa-triangle-exclamation" style="color:var(--col_amber_9);"></i> QL is convex, but not exp-concave</p>
<p><i class="fa fa-fw fa-arrow-right" style="color:var(--col_grey_10);"></i> Bernstein Online Aggregation (BOA) lets us weaken the exp-concavity condition. It satisfies that there exist a <span class="math inline">\(C&gt;0\)</span> such that for <span class="math inline">\(x&gt;0\)</span> it holds that</p>
<p><span class="math display">\[\begin{equation}
P\left( \frac{1}{t}\left(\widetilde{\mathcal{R}}_t - \widehat{\mathcal{R}}_{t,\pi} \right) \leq C \log(\log(t)) \left(\sqrt{\frac{\log(K)}{t}} + \frac{\log(K)+x}{t}\right) \right) \geq
1-e^{-x}
\label{eq_boa_opt_conv}
\end{equation}\]</span></p>
<p>if the loss function is convex.</p>
<p><i class="fa fa-fw fa-arrow-right" style="color:var(--col_grey_10);"></i> Almost optimal w.r.t. <em>convex aggregation</em> <span class="math inline">\(\eqref{eq_optp_conv}\)</span> <span class="citation" data-cites="wintenberger2017optimal">Wintenberger (<a href="#/references" role="doc-biblioref" onclick>2017</a>)</span>.</p>
<p>The same algorithm satisfies that there exist a <span class="math inline">\(C&gt;0\)</span> such that for <span class="math inline">\(x&gt;0\)</span> it holds that <span class="math display">\[\begin{equation}
P\left( \frac{1}{t}\left(\widetilde{\mathcal{R}}_t - \widehat{\mathcal{R}}_{t,\min} \right) \leq
@@ -26339,7 +26339,7 @@ w_{t,k}^{\text{Naive}} = \frac{1}{K}\label{eq:naive_combination}
1-2e^{-x}
\label{eq_boa_opt_select}
\end{equation}\]</span></p>
<p>if <span class="math inline">\(Y_t\)</span> is bounded, the considered loss <span class="math inline">\(\ell\)</span> is convex, <span class="math inline">\(G\)</span>-Lipschitz, and weak exp-concave in its first coordinate.</p>
<p>if the loss <span class="math inline">\(\ell\)</span> is <span class="math inline">\(G\)</span>-Lipschitz and weak exp-concave in its first coordinate</p>
<p><i class="fa fa-fw fa-arrow-right" style="color:var(--col_grey_10);"></i> Almost optimal w.r.t. <em>selection</em> <span class="math inline">\(\eqref{eq_optp_select}\)</span> <span class="citation" data-cites="gaillard2018efficient">Gaillard &amp; Wintenberger (<a href="#/references" role="doc-biblioref" onclick>2018</a>)</span>.</p>
<p><i class="fa fa-fw fa-arrow-right" style="color:var(--col_grey_10);"></i> We show that this holds for QL under feasible conditions.</p>
</div>
@@ -26347,7 +26347,7 @@ w_{t,k}^{\text{Naive}} = \frac{1}{K}\label{eq:naive_combination}
<div id="tabset-2-2">
<div class="columns">
<div class="column" style="width:48%;">
<p><strong>Lemma 1</strong></p>
<p><strong>Proposition 1: The Power of Flexibility</strong></p>
<p><span class="math display">\[\begin{align}
2\overline{\widehat{\mathcal{R}}}^{\text{QL}}_{t,\min}
&amp; \leq \widehat{\mathcal{R}}^{\text{CRPS}}_{t,\min}
@@ -26357,18 +26357,20 @@ w_{t,k}^{\text{Naive}} = \frac{1}{K}\label{eq:naive_combination}
\label{eq_risk_ql_crps_convex}
\end{align}\]</span></p>
<p>Pointwise can outperform constant procedures</p>
<p>QL is convex but not exp-concave:</p>
<p><i class="fa fa-fw fa-arrow-right" style="color:var(--col_grey_10);"></i> Almost optimal convergence w.r.t. <em>convex aggregation</em> <span class="math inline">\(\eqref{eq_boa_opt_conv}\)</span> <i class="fa fa-fw fa-check" style="color:var(--col_green_9);"></i> <br></p>
<p>For almost optimal congerence w.r.t. <em>selection</em> <span class="math inline">\(\eqref{eq_boa_opt_select}\)</span> we need to check <strong>A1</strong> and <strong>A2</strong>:</p>
<p>QL is Lipschitz continuous:</p>
<p><i class="fa fa-fw fa-arrow-right" style="color:var(--col_grey_10);"></i> <strong>A1</strong> holds <i class="fa fa-fw fa-check" style="color:var(--col_orange_9);"></i></p>
<p><i class="fa fa-fw fa-arrow-right" style="color:var(--col_grey_10);"></i> <span class="math inline">\(\text{QL}\)</span> is convex: almost optimal convergence w.r.t. <em>convex aggregation</em> <span class="math inline">\(\eqref{eq_boa_opt_conv}\)</span> <i class="fa fa-fw fa-check" style="color:var(--col_green_9);"></i> <br></p>
<p>For almost optimal congerence w.r.t. <em>selection</em> <span class="math inline">\(\eqref{eq_boa_opt_select}\)</span> we need:</p>
<p><strong>A1: Lipschitz Continuity</strong></p>
<p><strong>A2: Weak Exp-Concavity</strong></p>
<p>QL is Lipschitz continuous with <span class="math inline">\(G=\max(p, 1-p)\)</span>:</p>
<p><i class="fa fa-fw fa-arrow-right" style="color:var(--col_grey_10);"></i> <strong>A1</strong> holds <i class="fa fa-fw fa-check" style="color:var(--col_green_9);"></i></p>
</div><div class="column" style="width:4%;">
</div><div class="column" style="width:48%;">
<p><strong>A1</strong></p>
<p><strong>A1: Lipschitz Continuity</strong></p>
<p>For some <span class="math inline">\(G&gt;0\)</span> it holds for all <span class="math inline">\(x_1,x_2\in \mathbb{R}\)</span> and <span class="math inline">\(t&gt;0\)</span> that</p>
<p><span class="math display">\[ | \ell(x_1, Y_t)-\ell(x_2, Y_t) | \leq G |x_1-x_2|\]</span></p>
<p><strong>A2</strong> For some <span class="math inline">\(\alpha&gt;0\)</span>, <span class="math inline">\(\beta\in[0,1]\)</span> it holds for all <span class="math inline">\(x_1,x_2 \in \mathbb{R}\)</span> and <span class="math inline">\(t&gt;0\)</span> that</p>
<p><strong>A2 Weak Exp-Concavity</strong></p>
<p>For some <span class="math inline">\(\alpha&gt;0\)</span>, <span class="math inline">\(\beta\in[0,1]\)</span> it holds for all <span class="math inline">\(x_1,x_2 \in \mathbb{R}\)</span> and <span class="math inline">\(t&gt;0\)</span> that</p>
<p><span class="math display">\[\begin{align*}
\mathbb{E}[
&amp; \ell(x_1, Y_t)-\ell(x_2, Y_t) | \mathcal{F}_{t-1}] \leq \\
@@ -26376,7 +26378,7 @@ w_{t,k}^{\text{Naive}} = \frac{1}{K}\label{eq:naive_combination}
&amp; +
\mathbb{E}\left[ \left. \left( \alpha(\ell&#39;(x_1, Y_t)(x_1 - x_2))^{2}\right)^{1/\beta} \right|\mathcal{F}_{t-1}\right]
\end{align*}\]</span></p>
<p><i class="fa fa-fw fa-arrow-right" style="color:var(--col_grey_10);"></i> Almost optimal w.r.t. <em>selection</em> <span class="math inline">\(\eqref{eq_optp_select}\)</span> <span class="citation" data-cites="gaillard2018efficient">Gaillard &amp; Wintenberger (<a href="#/references" role="doc-biblioref" onclick>2018</a>)</span>.</p>
<p>If <span class="math inline">\(\beta=1\)</span> we get strong-convexity, which implies weak exp-concavity</p>
</div></div>
</div>
<div id="tabset-2-3">
@@ -26384,35 +26386,22 @@ w_{t,k}^{\text{Naive}} = \frac{1}{K}\label{eq:naive_combination}
<div class="column" style="width:48%;">
<p>Conditional quantile risk: <span class="math inline">\(\mathcal{Q}_p(x) = \mathbb{E}[ \text{QL}_p(x, Y_t) | \mathcal{F}_{t-1}]\)</span>.</p>
<p><i class="fa fa-fw fa-arrow-right" style="color:var(--col_grey_10);"></i> convexity properties of <span class="math inline">\(\mathcal{Q}_p\)</span> depend on the conditional distribution <span class="math inline">\(Y_t|\mathcal{F}_{t-1}\)</span>.</p>
<p><strong>Proposition 1</strong></p>
<p>Let <span class="math inline">\(Y\)</span> be a univariate random variable with (Radon-Nikodym) <span class="math inline">\(\nu\)</span>-density <span class="math inline">\(f\)</span>, then for the second subderivative of the quantile risk <span class="math inline">\(\mathcal{Q}_p(x) = \mathbb{E}[ \text{QL}_p(x, Y) ]\)</span> of <span class="math inline">\(Y\)</span> it holds for all <span class="math inline">\(p\in(0,1)\)</span> that <span class="math inline">\(\mathcal{Q}_p&#39;&#39; = f.\)</span> Additionally, if <span class="math inline">\(f\)</span> is a continuous Lebesgue-density with <span class="math inline">\(f\geq\gamma&gt;0\)</span> for some constant <span class="math inline">\(\gamma&gt;0\)</span> on its support <span class="math inline">\(\text{spt}(f)\)</span> then is <span class="math inline">\(\mathcal{Q}_p\)</span> is <span class="math inline">\(\gamma\)</span>-strongly convex.</p>
<p>Strong convexity with <span class="math inline">\(\beta=1\)</span> implies weak exp-concavity <strong>A2</strong> <i class="fa fa-fw fa-check" style="color:var(--col_green_9);"></i> <span class="citation" data-cites="gaillard2018efficient">Gaillard &amp; Wintenberger (<a href="#/references" role="doc-biblioref" onclick>2018</a>)</span></p>
<p><strong>Proposition 2</strong></p>
<p>Let <span class="math inline">\(Y\)</span> be a univariate random variable with (Radon-Nikodym) <span class="math inline">\(\nu\)</span>-density <span class="math inline">\(f\)</span>, then for the second subderivative of the quantile risk <span class="math inline">\(\mathcal{Q}_p(x) = \mathbb{E}[ \text{QL}_p(x, Y) ]\)</span> of <span class="math inline">\(Y\)</span> it holds for all <span class="math inline">\(p\in(0,1)\)</span> that <span class="math inline">\(\mathcal{Q}_p&#39;&#39; = f.\)</span> Additionally, if <span class="math inline">\(f\)</span> is a continuous Lebesgue-density with <span class="math inline">\(f\geq\gamma&gt;0\)</span> for some constant <span class="math inline">\(\gamma&gt;0\)</span> on its support <span class="math inline">\(\text{spt}(f)\)</span> then <span class="math inline">\(\mathcal{Q}_p\)</span> is <span class="math inline">\(\gamma\)</span>-strongly convex, which implies satisfaction of condition</p>
<p><strong>A2</strong> with <span class="math inline">\(\beta=1\)</span> <i class="fa fa-fw fa-check" style="color:var(--col_green_9);"></i> <span class="citation" data-cites="gaillard2018efficient">Gaillard &amp; Wintenberger (<a href="#/references" role="doc-biblioref" onclick>2018</a>)</span></p>
</div><div class="column" style="width:4%;">
</div><div class="column" style="width:48%;">
<p><i class="fa fa-fw fa-arrow-right" style="color:var(--col_grey_10);"></i> <strong>A1</strong> and <strong>A2</strong> give us almost optimal convergence w.r.t. selection <span class="math inline">\(\eqref{eq_boa_opt_select}\)</span> <i class="fa fa-fw fa-check" style="color:var(--col_green_9);"></i> <br></p>
<p><strong>Theorem 1</strong></p>
<p>The gradient based fully adaptive Bernstein online aggregation (BOAG) applied pointwise for all <span class="math inline">\(p\in(0,1)\)</span> on <span class="math inline">\(\text{QL}\)</span> satisfies <span class="math inline">\(\eqref{eq_boa_opt_conv}\)</span> with minimal CRPS given by</p>
<p><span class="math display">\[\widehat{\mathcal{R}}_{t,\pi} = 2\overline{\widehat{\mathcal{R}}}^{\text{QL}}_{t,\pi}.\]</span></p>
<p>If <span class="math inline">\(Y_t|\mathcal{F}_{t-1}\)</span> is bounded and has a pdf <span class="math inline">\(f_t\)</span> satifying <span class="math inline">\(f_t&gt;\gamma &gt;0\)</span> on its support <span class="math inline">\(\text{spt}(f_t)\)</span> then <span class="math inline">\(\ref{eq_boa_opt_select}\)</span> holds with <span class="math inline">\(\beta=1\)</span> and</p>
<p><span class="math display">\[\widehat{\mathcal{R}}_{t,\min} = 2\overline{\widehat{\mathcal{R}}}^{\text{QL}}_{t,\min}\]</span>.</p>
<p>If <span class="math inline">\(Y_t|\mathcal{F}_{t-1}\)</span> is bounded and has a pdf <span class="math inline">\(f_t\)</span> satifying <span class="math inline">\(f_t&gt;\gamma &gt;0\)</span> on its support <span class="math inline">\(\text{spt}(f_t)\)</span> then <span class="math inline">\(\eqref{eq_boa_opt_select}\)</span> holds with <span class="math inline">\(\beta=1\)</span> and</p>
<p><span class="math display">\[\widehat{\mathcal{R}}_{t,\min} = 2\overline{\widehat{\mathcal{R}}}^{\text{QL}}_{t,\min}\]</span></p>
<p><i class="fa fa-fw fa-check-double" style="color:var(--col_green_9);"></i> BOAG with <span class="math inline">\(\text{QL}\)</span> satisfies <span class="math inline">\(\eqref{eq_boa_opt_conv}\)</span> and <span class="math inline">\(\eqref{eq_boa_opt_select}\)</span></p>
</div></div>
</div>
</div>
</div>
<aside class="notes">
<p>We apply Bernstein Online Aggregation (BOA). It lets us weaken the exp-concavity condition while almost keeping the optimalities <span class="math inline">\(\ref{eq_optp_select}\)</span> and <span class="math inline">\(\ref{eq_optp_conv}\)</span>.</p>
<style type="text/css">
span.MJX_Assistive_MathML {
position:absolute!important;
clip: rect(1px, 1px, 1px, 1px);
padding: 1px 0 0 0!important;
border: 0!important;
height: 1px!important;
width: 1px!important;
overflow: hidden!important;
display:block!important;
}</style></aside>
</section>
<section id="a-probabilistic-example" class="slide level2">
<h2>A Probabilistic Example</h2>
@@ -26621,7 +26610,7 @@ w_{t,k}^{\text{smooth}} = \sum_{l=1}^L \beta_l \varphi_l = \beta&#39;\varphi
</div><div class="column" style="width:4%;">
</div><div class="column" style="width:58%;">
<h3 id="section-2"> </h3>
<h3 id="section-3"> </h3>
<div class="cell" data-layout-align="center">
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
@@ -27241,7 +27230,7 @@ Y_{t} = \mu + Y_{t-1} + \varepsilon_t \quad \text{with} \quad \varepsilon_t = \
<div class="tab-content">
<div id="tabset-12-1">
<div class="cell">
<div class="sourceCode cell-code hidden" id="cb5" data-startfrom="2714" data-source-offset="0"><pre class="sourceCode numberSource js number-lines code-with-copy"><code class="sourceCode javascript" style="counter-reset: source-line 2713;"><span id="cb5-2714"><a href></a>bsplineData <span class="op">=</span> <span class="fu">FileAttachment</span>(<span class="st">&quot;assets/mcrps_learning/basis_functions.csv&quot;</span>)<span class="op">.</span><span class="fu">csv</span>({ <span class="dt">typed</span><span class="op">:</span> <span class="kw">true</span> })</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="sourceCode cell-code hidden" id="cb5" data-startfrom="2716" data-source-offset="0"><pre class="sourceCode numberSource js number-lines code-with-copy"><code class="sourceCode javascript" style="counter-reset: source-line 2715;"><span id="cb5-2716"><a href></a>bsplineData <span class="op">=</span> <span class="fu">FileAttachment</span>(<span class="st">&quot;assets/mcrps_learning/basis_functions.csv&quot;</span>)<span class="op">.</span><span class="fu">csv</span>({ <span class="dt">typed</span><span class="op">:</span> <span class="kw">true</span> })</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output cell-output-display">
<div id="ojs-cell-4" data-nodetype="declaration">
@@ -27249,194 +27238,194 @@ Y_{t} = \mu + Y_{t-1} + \varepsilon_t \quad \text{with} \quad \varepsilon_t = \
</div>
</div>
<div class="cell">
<div class="sourceCode cell-code hidden" id="cb6" data-startfrom="2718" data-source-offset="0"><pre class="sourceCode numberSource js number-lines code-with-copy"><code class="sourceCode javascript" style="counter-reset: source-line 2717;"><span id="cb6-2718"><a href></a><span class="co">// Defined above</span></span>
<span id="cb6-2719"><a href></a><span class="co">// function updateChartInner(g, x, y, linesGroup, color, line, data) {</span></span>
<span id="cb6-2720"><a href></a><span class="co">// // Update axes with transitions</span></span>
<span id="cb6-2721"><a href></a><span class="co">// x.domain([0, d3.max(data, d =&gt; d.x)]);</span></span>
<span id="cb6-2722"><a href></a><span class="co">// g.select(&quot;.x-axis&quot;).transition().duration(1500).call(d3.axisBottom(x).ticks(10));</span></span>
<span id="cb6-2723"><a href></a><span class="co">// y.domain([0, d3.max(data, d =&gt; d.y)]);</span></span>
<span id="cb6-2724"><a href></a><span class="co">// g.select(&quot;.y-axis&quot;).transition().duration(1500).call(d3.axisLeft(y).ticks(5));</span></span>
<span id="cb6-2725"><a href></a></span>
<span id="cb6-2726"><a href></a><span class="co">// // Group data by basis function</span></span>
<span id="cb6-2727"><a href></a><span class="co">// const dataByFunction = Array.from(d3.group(data, d =&gt; d.b));</span></span>
<span id="cb6-2728"><a href></a><span class="co">// const keyFn = d =&gt; d[0];</span></span>
<span id="cb6-2729"><a href></a></span>
<span id="cb6-2730"><a href></a><span class="co">// // Update basis function lines</span></span>
<span id="cb6-2731"><a href></a><span class="co">// const u = linesGroup.selectAll(&quot;path&quot;).data(dataByFunction, keyFn);</span></span>
<span id="cb6-2732"><a href></a><span class="co">// u.join(</span></span>
<span id="cb6-2733"><a href></a><span class="co">// enter =&gt; enter.append(&quot;path&quot;).attr(&quot;fill&quot;,&quot;none&quot;).attr(&quot;stroke-width&quot;,3)</span></span>
<span id="cb6-2734"><a href></a><span class="co">// .attr(&quot;stroke&quot;, (_, i) =&gt; color(i)).attr(&quot;d&quot;, d =&gt; line(d[1].map(pt =&gt; ({x: pt.x, y: 0}))))</span></span>
<span id="cb6-2735"><a href></a><span class="co">// .style(&quot;opacity&quot;,0),</span></span>
<span id="cb6-2736"><a href></a><span class="co">// update =&gt; update,</span></span>
<span id="cb6-2737"><a href></a><span class="co">// exit =&gt; exit.transition().duration(1000).style(&quot;opacity&quot;,0).remove()</span></span>
<span id="cb6-2738"><a href></a><span class="co">// )</span></span>
<span id="cb6-2739"><a href></a><span class="co">// .transition().duration(1000)</span></span>
<span id="cb6-2740"><a href></a><span class="co">// .attr(&quot;d&quot;, d =&gt; line(d[1]))</span></span>
<span id="cb6-2741"><a href></a><span class="co">// .attr(&quot;stroke&quot;, (_, i) =&gt; color(i))</span></span>
<span id="cb6-2742"><a href></a><span class="co">// .style(&quot;opacity&quot;,1);</span></span>
<span id="cb6-2743"><a href></a><span class="co">// }</span></span>
<span id="cb6-2744"><a href></a></span>
<span id="cb6-2745"><a href></a>chart0 <span class="op">=</span> {</span>
<span id="cb6-2746"><a href></a> <span class="co">// State variables for selected parameters</span></span>
<span id="cb6-2747"><a href></a> <span class="kw">let</span> selectedMu <span class="op">=</span> <span class="fl">0.5</span><span class="op">;</span></span>
<span id="cb6-2748"><a href></a> <span class="kw">let</span> selectedSig <span class="op">=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb6-2749"><a href></a> <span class="kw">let</span> selectedNonc <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb6-2750"><a href></a> <span class="kw">let</span> selectedTailw <span class="op">=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb6-2751"><a href></a> <span class="kw">const</span> filteredData <span class="op">=</span> () <span class="kw">=&gt;</span> bsplineData<span class="op">.</span><span class="fu">filter</span>(d <span class="kw">=&gt;</span></span>
<span id="cb6-2752"><a href></a> <span class="bu">Math</span><span class="op">.</span><span class="fu">abs</span>(selectedMu <span class="op">-</span> d<span class="op">.</span><span class="at">mu</span>) <span class="op">&lt;</span> <span class="fl">0.001</span> <span class="op">&amp;&amp;</span></span>
<span id="cb6-2753"><a href></a> d<span class="op">.</span><span class="at">sig</span> <span class="op">===</span> selectedSig <span class="op">&amp;&amp;</span></span>
<span id="cb6-2754"><a href></a> d<span class="op">.</span><span class="at">nonc</span> <span class="op">===</span> selectedNonc <span class="op">&amp;&amp;</span></span>
<span id="cb6-2755"><a href></a> d<span class="op">.</span><span class="at">tailw</span> <span class="op">===</span> selectedTailw</span>
<span id="cb6-2756"><a href></a> )<span class="op">;</span></span>
<span id="cb6-2757"><a href></a> <span class="kw">const</span> container <span class="op">=</span> d3<span class="op">.</span><span class="fu">create</span>(<span class="st">&quot;div&quot;</span>)</span>
<span id="cb6-2758"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;max-width&quot;</span><span class="op">,</span> <span class="st">&quot;none&quot;</span>)</span>
<span id="cb6-2759"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;width&quot;</span><span class="op">,</span> <span class="st">&quot;100%&quot;</span>)<span class="op">;;</span></span>
<span id="cb6-2760"><a href></a> <span class="kw">const</span> controlsContainer <span class="op">=</span> container<span class="op">.</span><span class="fu">append</span>(<span class="st">&quot;div&quot;</span>)</span>
<span id="cb6-2761"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;display&quot;</span><span class="op">,</span> <span class="st">&quot;flex&quot;</span>)</span>
<span id="cb6-2762"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;gap&quot;</span><span class="op">,</span> <span class="st">&quot;20px&quot;</span>)<span class="op">;</span></span>
<span id="cb6-2763"><a href></a> <span class="co">// slider controls</span></span>
<span id="cb6-2764"><a href></a> <span class="kw">const</span> sliders <span class="op">=</span> [</span>
<span id="cb6-2765"><a href></a> { <span class="dt">label</span><span class="op">:</span> <span class="st">&#39;Mu&#39;</span><span class="op">,</span> <span class="kw">get</span><span class="op">:</span> () <span class="kw">=&gt;</span> selectedMu<span class="op">,</span> <span class="kw">set</span><span class="op">:</span> v <span class="kw">=&gt;</span> selectedMu <span class="op">=</span> v<span class="op">,</span> <span class="dt">min</span><span class="op">:</span> <span class="fl">0.1</span><span class="op">,</span> <span class="dt">max</span><span class="op">:</span> <span class="fl">0.9</span><span class="op">,</span> <span class="dt">step</span><span class="op">:</span> <span class="fl">0.2</span> }<span class="op">,</span></span>
<span id="cb6-2766"><a href></a> { <span class="dt">label</span><span class="op">:</span> <span class="st">&#39;Sigma&#39;</span><span class="op">,</span> <span class="kw">get</span><span class="op">:</span> () <span class="kw">=&gt;</span> <span class="bu">Math</span><span class="op">.</span><span class="fu">log2</span>(selectedSig)<span class="op">,</span> <span class="kw">set</span><span class="op">:</span> v <span class="kw">=&gt;</span> selectedSig <span class="op">=</span> <span class="dv">2</span> <span class="op">**</span> v<span class="op">,</span> <span class="dt">min</span><span class="op">:</span> <span class="op">-</span><span class="dv">2</span><span class="op">,</span> <span class="dt">max</span><span class="op">:</span> <span class="dv">2</span><span class="op">,</span> <span class="dt">step</span><span class="op">:</span> <span class="dv">1</span> }<span class="op">,</span></span>
<span id="cb6-2767"><a href></a> { <span class="dt">label</span><span class="op">:</span> <span class="st">&#39;Noncentrality&#39;</span><span class="op">,</span> <span class="kw">get</span><span class="op">:</span> () <span class="kw">=&gt;</span> selectedNonc<span class="op">,</span> <span class="kw">set</span><span class="op">:</span> v <span class="kw">=&gt;</span> selectedNonc <span class="op">=</span> v<span class="op">,</span> <span class="dt">min</span><span class="op">:</span> <span class="op">-</span><span class="dv">4</span><span class="op">,</span> <span class="dt">max</span><span class="op">:</span> <span class="dv">4</span><span class="op">,</span> <span class="dt">step</span><span class="op">:</span> <span class="dv">2</span> }<span class="op">,</span></span>
<span id="cb6-2768"><a href></a> { <span class="dt">label</span><span class="op">:</span> <span class="st">&#39;Tailweight&#39;</span><span class="op">,</span> <span class="kw">get</span><span class="op">:</span> () <span class="kw">=&gt;</span> <span class="bu">Math</span><span class="op">.</span><span class="fu">log2</span>(selectedTailw)<span class="op">,</span> <span class="kw">set</span><span class="op">:</span> v <span class="kw">=&gt;</span> selectedTailw <span class="op">=</span> <span class="dv">2</span> <span class="op">**</span> v<span class="op">,</span> <span class="dt">min</span><span class="op">:</span> <span class="op">-</span><span class="dv">2</span><span class="op">,</span> <span class="dt">max</span><span class="op">:</span> <span class="dv">2</span><span class="op">,</span> <span class="dt">step</span><span class="op">:</span> <span class="dv">1</span> }</span>
<span id="cb6-2769"><a href></a> ]<span class="op">;</span></span>
<span id="cb6-2770"><a href></a> <span class="co">// Build slider controls with D3 data join</span></span>
<span id="cb6-2771"><a href></a> <span class="kw">const</span> sliderCont <span class="op">=</span> controlsContainer<span class="op">.</span><span class="fu">selectAll</span>(<span class="st">&#39;div&#39;</span>)<span class="op">.</span><span class="fu">data</span>(sliders)<span class="op">.</span><span class="fu">join</span>(<span class="st">&#39;div&#39;</span>)</span>
<span id="cb6-2772"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&#39;display&#39;</span><span class="op">,</span><span class="st">&#39;flex&#39;</span>)<span class="op">.</span><span class="fu">style</span>(<span class="st">&#39;align-items&#39;</span><span class="op">,</span><span class="st">&#39;center&#39;</span>)<span class="op">.</span><span class="fu">style</span>(<span class="st">&#39;gap&#39;</span><span class="op">,</span><span class="st">&#39;10px&#39;</span>)</span>
<span id="cb6-2773"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&#39;flex&#39;</span><span class="op">,</span><span class="st">&#39;1&#39;</span>)<span class="op">.</span><span class="fu">style</span>(<span class="st">&#39;min-width&#39;</span><span class="op">,</span><span class="st">&#39;0px&#39;</span>)<span class="op">;</span></span>
<span id="cb6-2774"><a href></a> sliderCont<span class="op">.</span><span class="fu">append</span>(<span class="st">&#39;label&#39;</span>)<span class="op">.</span><span class="fu">text</span>(d <span class="kw">=&gt;</span> d<span class="op">.</span><span class="at">label</span> <span class="op">+</span> <span class="st">&#39;:&#39;</span>)<span class="op">.</span><span class="fu">style</span>(<span class="st">&#39;font-size&#39;</span><span class="op">,</span><span class="st">&#39;20px&#39;</span>)<span class="op">;</span></span>
<span id="cb6-2775"><a href></a> sliderCont<span class="op">.</span><span class="fu">append</span>(<span class="st">&#39;input&#39;</span>)</span>
<span id="cb6-2776"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&#39;type&#39;</span><span class="op">,</span><span class="st">&#39;range&#39;</span>)<span class="op">.</span><span class="fu">attr</span>(<span class="st">&#39;min&#39;</span><span class="op">,</span> d <span class="kw">=&gt;</span> d<span class="op">.</span><span class="at">min</span>)<span class="op">.</span><span class="fu">attr</span>(<span class="st">&#39;max&#39;</span><span class="op">,</span> d <span class="kw">=&gt;</span> d<span class="op">.</span><span class="at">max</span>)<span class="op">.</span><span class="fu">attr</span>(<span class="st">&#39;step&#39;</span><span class="op">,</span> d <span class="kw">=&gt;</span> d<span class="op">.</span><span class="at">step</span>)</span>
<span id="cb6-2777"><a href></a> <span class="op">.</span><span class="fu">property</span>(<span class="st">&#39;value&#39;</span><span class="op">,</span> d <span class="kw">=&gt;</span> d<span class="op">.</span><span class="fu">get</span>())</span>
<span id="cb6-2778"><a href></a> <span class="op">.</span><span class="fu">on</span>(<span class="st">&#39;input&#39;</span><span class="op">,</span> <span class="kw">function</span>(<span class="bu">event</span><span class="op">,</span> d) {</span>
<span id="cb6-2779"><a href></a> <span class="kw">const</span> val <span class="op">=</span> <span class="op">+</span><span class="kw">this</span><span class="op">.</span><span class="at">value</span><span class="op">;</span> d<span class="op">.</span><span class="fu">set</span>(val)<span class="op">;</span></span>
<span id="cb6-2780"><a href></a> d3<span class="op">.</span><span class="fu">select</span>(<span class="kw">this</span><span class="op">.</span><span class="at">parentNode</span>)<span class="op">.</span><span class="fu">select</span>(<span class="st">&#39;span&#39;</span>)<span class="op">.</span><span class="fu">text</span>(d<span class="op">.</span><span class="at">label</span><span class="op">.</span><span class="fu">match</span>(<span class="ss">/Sigma</span><span class="sc">|</span><span class="ss">Tailweight/</span>) <span class="op">?</span> <span class="dv">2</span><span class="op">**</span>val <span class="op">:</span> val)<span class="op">;</span></span>
<span id="cb6-2781"><a href></a> <span class="fu">updateChart</span>(<span class="fu">filteredData</span>())<span class="op">;</span></span>
<span id="cb6-2782"><a href></a> })</span>
<span id="cb6-2783"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&#39;width&#39;</span><span class="op">,</span> <span class="st">&#39;100%&#39;</span>)<span class="op">;</span></span>
<span id="cb6-2784"><a href></a> sliderCont<span class="op">.</span><span class="fu">append</span>(<span class="st">&#39;span&#39;</span>)<span class="op">.</span><span class="fu">text</span>(d <span class="kw">=&gt;</span> (d<span class="op">.</span><span class="at">label</span><span class="op">.</span><span class="fu">match</span>(<span class="ss">/Sigma</span><span class="sc">|</span><span class="ss">Tailweight/</span>) <span class="op">?</span> d<span class="op">.</span><span class="fu">get</span>() <span class="op">:</span> d<span class="op">.</span><span class="fu">get</span>()))</span>
<span id="cb6-2785"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&#39;font-size&#39;</span><span class="op">,</span><span class="st">&#39;20px&#39;</span>)<span class="op">;</span></span>
<span id="cb6-2786"><a href></a> </span>
<span id="cb6-2787"><a href></a> <span class="co">// Add Reset button to clear all sliders to their defaults</span></span>
<span id="cb6-2788"><a href></a> controlsContainer<span class="op">.</span><span class="fu">append</span>(<span class="st">&#39;button&#39;</span>)</span>
<span id="cb6-2789"><a href></a> <span class="op">.</span><span class="fu">text</span>(<span class="st">&#39;Reset&#39;</span>)</span>
<span id="cb6-2790"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&#39;font-size&#39;</span><span class="op">,</span> <span class="st">&#39;20px&#39;</span>)</span>
<span id="cb6-2791"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&#39;align-self&#39;</span><span class="op">,</span> <span class="st">&#39;center&#39;</span>)</span>
<span id="cb6-2792"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&#39;margin-left&#39;</span><span class="op">,</span> <span class="st">&#39;auto&#39;</span>)</span>
<span id="cb6-2793"><a href></a> <span class="op">.</span><span class="fu">on</span>(<span class="st">&#39;click&#39;</span><span class="op">,</span> () <span class="kw">=&gt;</span> {</span>
<span id="cb6-2794"><a href></a> <span class="co">// reset state vars</span></span>
<span id="cb6-2795"><a href></a> selectedMu <span class="op">=</span> <span class="fl">0.5</span><span class="op">;</span></span>
<span id="cb6-2796"><a href></a> selectedSig <span class="op">=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb6-2797"><a href></a> selectedNonc <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb6-2798"><a href></a> selectedTailw <span class="op">=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb6-2799"><a href></a> <span class="co">// update input positions</span></span>
<span id="cb6-2800"><a href></a> sliderCont<span class="op">.</span><span class="fu">selectAll</span>(<span class="st">&#39;input&#39;</span>)<span class="op">.</span><span class="fu">property</span>(<span class="st">&#39;value&#39;</span><span class="op">,</span> d <span class="kw">=&gt;</span> d<span class="op">.</span><span class="fu">get</span>())<span class="op">;</span></span>
<span id="cb6-2801"><a href></a> <span class="co">// update displayed labels</span></span>
<span id="cb6-2802"><a href></a> sliderCont<span class="op">.</span><span class="fu">selectAll</span>(<span class="st">&#39;span&#39;</span>)</span>
<span id="cb6-2803"><a href></a> <span class="op">.</span><span class="fu">text</span>(d <span class="kw">=&gt;</span> d<span class="op">.</span><span class="at">label</span><span class="op">.</span><span class="fu">match</span>(<span class="ss">/Sigma</span><span class="sc">|</span><span class="ss">Tailweight/</span>) <span class="op">?</span> (<span class="dv">2</span><span class="op">**</span>d<span class="op">.</span><span class="fu">get</span>()) <span class="op">:</span> d<span class="op">.</span><span class="fu">get</span>())<span class="op">;</span></span>
<span id="cb6-2804"><a href></a> <span class="co">// redraw chart</span></span>
<span id="cb6-2805"><a href></a> <span class="fu">updateChart</span>(<span class="fu">filteredData</span>())<span class="op">;</span></span>
<span id="cb6-2806"><a href></a> })<span class="op">;</span></span>
<span id="cb6-2807"><a href></a></span>
<span id="cb6-2808"><a href></a> <span class="co">// Build SVG</span></span>
<span id="cb6-2809"><a href></a> <span class="kw">const</span> width <span class="op">=</span> <span class="dv">1200</span><span class="op">;</span></span>
<span id="cb6-2810"><a href></a> <span class="kw">const</span> height <span class="op">=</span> <span class="dv">450</span><span class="op">;</span></span>
<span id="cb6-2811"><a href></a> <span class="kw">const</span> margin <span class="op">=</span> {<span class="dt">top</span><span class="op">:</span> <span class="dv">40</span><span class="op">,</span> <span class="dt">right</span><span class="op">:</span> <span class="dv">20</span><span class="op">,</span> <span class="dt">bottom</span><span class="op">:</span> <span class="dv">40</span><span class="op">,</span> <span class="dt">left</span><span class="op">:</span> <span class="dv">40</span>}<span class="op">;</span></span>
<span id="cb6-2812"><a href></a> <span class="kw">const</span> innerWidth <span class="op">=</span> width <span class="op">-</span> margin<span class="op">.</span><span class="at">left</span> <span class="op">-</span> margin<span class="op">.</span><span class="at">right</span><span class="op">;</span></span>
<span id="cb6-2813"><a href></a> <span class="kw">const</span> innerHeight <span class="op">=</span> height <span class="op">-</span> margin<span class="op">.</span><span class="at">top</span> <span class="op">-</span> margin<span class="op">.</span><span class="at">bottom</span><span class="op">;</span></span>
<span id="cb6-2814"><a href></a></span>
<span id="cb6-2815"><a href></a> <span class="co">// Set controls container width to match SVG plot width</span></span>
<span id="cb6-2816"><a href></a> controlsContainer<span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;max-width&quot;</span><span class="op">,</span> <span class="st">&quot;none&quot;</span>)<span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;width&quot;</span><span class="op">,</span> <span class="st">&quot;100%&quot;</span>)<span class="op">;</span></span>
<span id="cb6-2817"><a href></a> <span class="co">// Distribute each control evenly and make sliders full-width</span></span>
<span id="cb6-2818"><a href></a> controlsContainer<span class="op">.</span><span class="fu">selectAll</span>(<span class="st">&quot;div&quot;</span>)<span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;flex&quot;</span><span class="op">,</span> <span class="st">&quot;1&quot;</span>)<span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;min-width&quot;</span><span class="op">,</span> <span class="st">&quot;0px&quot;</span>)<span class="op">;</span></span>
<span id="cb6-2819"><a href></a> controlsContainer<span class="op">.</span><span class="fu">selectAll</span>(<span class="st">&quot;input&quot;</span>)<span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;width&quot;</span><span class="op">,</span> <span class="st">&quot;100%&quot;</span>)<span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;box-sizing&quot;</span><span class="op">,</span> <span class="st">&quot;border-box&quot;</span>)<span class="op">;</span></span>
<span id="cb6-2820"><a href></a> </span>
<span id="cb6-2821"><a href></a> <span class="co">// Create scales</span></span>
<span id="cb6-2822"><a href></a> <span class="kw">const</span> x <span class="op">=</span> d3<span class="op">.</span><span class="fu">scaleLinear</span>()</span>
<span id="cb6-2823"><a href></a> <span class="op">.</span><span class="fu">domain</span>([<span class="dv">0</span><span class="op">,</span> <span class="dv">1</span>])</span>
<span id="cb6-2824"><a href></a> <span class="op">.</span><span class="fu">range</span>([<span class="dv">0</span><span class="op">,</span> innerWidth])<span class="op">;</span></span>
<span id="cb6-2825"><a href></a> </span>
<span id="cb6-2826"><a href></a> <span class="kw">const</span> y <span class="op">=</span> d3<span class="op">.</span><span class="fu">scaleLinear</span>()</span>
<span id="cb6-2827"><a href></a> <span class="op">.</span><span class="fu">domain</span>([<span class="dv">0</span><span class="op">,</span> <span class="dv">1</span>])</span>
<span id="cb6-2828"><a href></a> <span class="op">.</span><span class="fu">range</span>([innerHeight<span class="op">,</span> <span class="dv">0</span>])<span class="op">;</span></span>
<span id="cb6-2829"><a href></a> </span>
<span id="cb6-2830"><a href></a> <span class="co">// Create a color scale for the basis functions</span></span>
<span id="cb6-2831"><a href></a> <span class="kw">const</span> color <span class="op">=</span> d3<span class="op">.</span><span class="fu">scaleOrdinal</span>(d3<span class="op">.</span><span class="at">schemeCategory10</span>)<span class="op">;</span></span>
<span id="cb6-2832"><a href></a> </span>
<span id="cb6-2833"><a href></a> <span class="co">// Create SVG</span></span>
<span id="cb6-2834"><a href></a> <span class="kw">const</span> svg <span class="op">=</span> d3<span class="op">.</span><span class="fu">create</span>(<span class="st">&quot;svg&quot;</span>)</span>
<span id="cb6-2835"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;width&quot;</span><span class="op">,</span> <span class="st">&quot;100%&quot;</span>)</span>
<span id="cb6-2836"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;height&quot;</span><span class="op">,</span> <span class="st">&quot;auto&quot;</span>)</span>
<span id="cb6-2837"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;viewBox&quot;</span><span class="op">,</span> [<span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> width<span class="op">,</span> height])</span>
<span id="cb6-2838"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;preserveAspectRatio&quot;</span><span class="op">,</span> <span class="st">&quot;xMidYMid meet&quot;</span>)</span>
<span id="cb6-2839"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;style&quot;</span><span class="op">,</span> <span class="st">&quot;max-width: 100%; height: auto;&quot;</span>)<span class="op">;</span></span>
<span id="cb6-2840"><a href></a> </span>
<span id="cb6-2841"><a href></a> <span class="co">// Create the chart group</span></span>
<span id="cb6-2842"><a href></a> <span class="kw">const</span> g <span class="op">=</span> svg<span class="op">.</span><span class="fu">append</span>(<span class="st">&quot;g&quot;</span>)</span>
<span id="cb6-2843"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;transform&quot;</span><span class="op">,</span> <span class="vs">`translate(</span><span class="sc">${</span>margin<span class="op">.</span><span class="at">left</span><span class="sc">}</span><span class="vs">,</span><span class="sc">${</span>margin<span class="op">.</span><span class="at">top</span><span class="sc">}</span><span class="vs">)`</span>)<span class="op">;</span></span>
<span id="cb6-2844"><a href></a> </span>
<span id="cb6-2845"><a href></a> <span class="co">// Add axes</span></span>
<span id="cb6-2846"><a href></a> <span class="kw">const</span> xAxis <span class="op">=</span> g<span class="op">.</span><span class="fu">append</span>(<span class="st">&quot;g&quot;</span>)</span>
<span id="cb6-2847"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;transform&quot;</span><span class="op">,</span> <span class="vs">`translate(0,</span><span class="sc">${</span>innerHeight<span class="sc">}</span><span class="vs">)`</span>)</span>
<span id="cb6-2848"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;class&quot;</span><span class="op">,</span> <span class="st">&quot;x-axis&quot;</span>)</span>
<span id="cb6-2849"><a href></a> <span class="op">.</span><span class="fu">call</span>(d3<span class="op">.</span><span class="fu">axisBottom</span>(x)<span class="op">.</span><span class="fu">ticks</span>(<span class="dv">10</span>))</span>
<span id="cb6-2850"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;font-size&quot;</span><span class="op">,</span> <span class="st">&quot;20px&quot;</span>)<span class="op">;</span></span>
<span id="cb6-2851"><a href></a> </span>
<span id="cb6-2852"><a href></a> <span class="kw">const</span> yAxis <span class="op">=</span> g<span class="op">.</span><span class="fu">append</span>(<span class="st">&quot;g&quot;</span>)</span>
<span id="cb6-2853"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;class&quot;</span><span class="op">,</span> <span class="st">&quot;y-axis&quot;</span>)</span>
<span id="cb6-2854"><a href></a> <span class="op">.</span><span class="fu">call</span>(d3<span class="op">.</span><span class="fu">axisLeft</span>(y)<span class="op">.</span><span class="fu">ticks</span>(<span class="dv">5</span>))</span>
<span id="cb6-2855"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;font-size&quot;</span><span class="op">,</span> <span class="st">&quot;20px&quot;</span>)<span class="op">;</span></span>
<span id="cb6-2856"><a href></a> </span>
<span id="cb6-2857"><a href></a> <span class="co">// Add a horizontal line at y = 0</span></span>
<span id="cb6-2858"><a href></a> g<span class="op">.</span><span class="fu">append</span>(<span class="st">&quot;line&quot;</span>)</span>
<span id="cb6-2859"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;x1&quot;</span><span class="op">,</span> <span class="dv">0</span>)</span>
<span id="cb6-2860"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;x2&quot;</span><span class="op">,</span> innerWidth)</span>
<span id="cb6-2861"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;y1&quot;</span><span class="op">,</span> <span class="fu">y</span>(<span class="dv">0</span>))</span>
<span id="cb6-2862"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;y2&quot;</span><span class="op">,</span> <span class="fu">y</span>(<span class="dv">0</span>))</span>
<span id="cb6-2863"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;stroke&quot;</span><span class="op">,</span> <span class="st">&quot;#000&quot;</span>)</span>
<span id="cb6-2864"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;stroke-opacity&quot;</span><span class="op">,</span> <span class="fl">0.2</span>)<span class="op">;</span></span>
<span id="cb6-2865"><a href></a> </span>
<span id="cb6-2866"><a href></a> <span class="co">// Add gridlines</span></span>
<span id="cb6-2867"><a href></a> g<span class="op">.</span><span class="fu">append</span>(<span class="st">&quot;g&quot;</span>)</span>
<span id="cb6-2868"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;class&quot;</span><span class="op">,</span> <span class="st">&quot;grid-lines&quot;</span>)</span>
<span id="cb6-2869"><a href></a> <span class="op">.</span><span class="fu">selectAll</span>(<span class="st">&quot;line&quot;</span>)</span>
<span id="cb6-2870"><a href></a> <span class="op">.</span><span class="fu">data</span>(y<span class="op">.</span><span class="fu">ticks</span>(<span class="dv">5</span>))</span>
<span id="cb6-2871"><a href></a> <span class="op">.</span><span class="fu">join</span>(<span class="st">&quot;line&quot;</span>)</span>
<span id="cb6-2872"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;x1&quot;</span><span class="op">,</span> <span class="dv">0</span>)</span>
<span id="cb6-2873"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;x2&quot;</span><span class="op">,</span> innerWidth)</span>
<span id="cb6-2874"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;y1&quot;</span><span class="op">,</span> d <span class="kw">=&gt;</span> <span class="fu">y</span>(d))</span>
<span id="cb6-2875"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;y2&quot;</span><span class="op">,</span> d <span class="kw">=&gt;</span> <span class="fu">y</span>(d))</span>
<span id="cb6-2876"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;stroke&quot;</span><span class="op">,</span> <span class="st">&quot;#ccc&quot;</span>)</span>
<span id="cb6-2877"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;stroke-opacity&quot;</span><span class="op">,</span> <span class="fl">0.5</span>)<span class="op">;</span></span>
<span id="cb6-2878"><a href></a> </span>
<span id="cb6-2879"><a href></a> <span class="co">// Create a line generator</span></span>
<span id="cb6-2880"><a href></a> <span class="kw">const</span> line <span class="op">=</span> d3<span class="op">.</span><span class="fu">line</span>()</span>
<span id="cb6-2881"><a href></a> <span class="op">.</span><span class="fu">x</span>(d <span class="kw">=&gt;</span> <span class="fu">x</span>(d<span class="op">.</span><span class="at">x</span>))</span>
<span id="cb6-2882"><a href></a> <span class="op">.</span><span class="fu">y</span>(d <span class="kw">=&gt;</span> <span class="fu">y</span>(d<span class="op">.</span><span class="at">y</span>))</span>
<span id="cb6-2883"><a href></a> <span class="op">.</span><span class="fu">curve</span>(d3<span class="op">.</span><span class="at">curveBasis</span>)<span class="op">;</span></span>
<span id="cb6-2884"><a href></a> </span>
<span id="cb6-2885"><a href></a> <span class="co">// Group to contain the basis function lines</span></span>
<span id="cb6-2886"><a href></a> <span class="kw">const</span> linesGroup <span class="op">=</span> g<span class="op">.</span><span class="fu">append</span>(<span class="st">&quot;g&quot;</span>)</span>
<span id="cb6-2887"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;class&quot;</span><span class="op">,</span> <span class="st">&quot;basis-functions&quot;</span>)<span class="op">;</span></span>
<span id="cb6-2888"><a href></a> </span>
<span id="cb6-2889"><a href></a> <span class="co">// Store the current basis functions for transition</span></span>
<span id="cb6-2890"><a href></a> <span class="kw">let</span> currentBasisFunctions <span class="op">=</span> <span class="kw">new</span> <span class="bu">Map</span>()<span class="op">;</span></span>
<span id="cb6-2891"><a href></a> </span>
<span id="cb6-2892"><a href></a> <span class="co">// Function to update the chart with new data</span></span>
<span id="cb6-2893"><a href></a> <span class="kw">function</span> <span class="fu">updateChart</span>(data) {</span>
<span id="cb6-2894"><a href></a> <span class="fu">updateChartInner</span>(g<span class="op">,</span> x<span class="op">,</span> y<span class="op">,</span> linesGroup<span class="op">,</span> color<span class="op">,</span> line<span class="op">,</span> data)<span class="op">;</span></span>
<span id="cb6-2895"><a href></a> }</span>
<span id="cb6-2896"><a href></a> </span>
<span id="cb6-2897"><a href></a> <span class="co">// Store the update function</span></span>
<span id="cb6-2898"><a href></a> svg<span class="op">.</span><span class="fu">node</span>()<span class="op">.</span><span class="at">update</span> <span class="op">=</span> updateChart<span class="op">;</span></span>
<span id="cb6-2899"><a href></a> </span>
<span id="cb6-2900"><a href></a> <span class="co">// Initial render</span></span>
<span id="cb6-2901"><a href></a> <span class="fu">updateChart</span>(<span class="fu">filteredData</span>())<span class="op">;</span></span>
<span id="cb6-2902"><a href></a> </span>
<span id="cb6-2903"><a href></a> container<span class="op">.</span><span class="fu">node</span>()<span class="op">.</span><span class="fu">appendChild</span>(svg<span class="op">.</span><span class="fu">node</span>())<span class="op">;</span></span>
<span id="cb6-2904"><a href></a> <span class="cf">return</span> container<span class="op">.</span><span class="fu">node</span>()<span class="op">;</span></span>
<span id="cb6-2905"><a href></a>}</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="sourceCode cell-code hidden" id="cb6" data-startfrom="2720" data-source-offset="0"><pre class="sourceCode numberSource js number-lines code-with-copy"><code class="sourceCode javascript" style="counter-reset: source-line 2719;"><span id="cb6-2720"><a href></a><span class="co">// Defined above</span></span>
<span id="cb6-2721"><a href></a><span class="co">// function updateChartInner(g, x, y, linesGroup, color, line, data) {</span></span>
<span id="cb6-2722"><a href></a><span class="co">// // Update axes with transitions</span></span>
<span id="cb6-2723"><a href></a><span class="co">// x.domain([0, d3.max(data, d =&gt; d.x)]);</span></span>
<span id="cb6-2724"><a href></a><span class="co">// g.select(&quot;.x-axis&quot;).transition().duration(1500).call(d3.axisBottom(x).ticks(10));</span></span>
<span id="cb6-2725"><a href></a><span class="co">// y.domain([0, d3.max(data, d =&gt; d.y)]);</span></span>
<span id="cb6-2726"><a href></a><span class="co">// g.select(&quot;.y-axis&quot;).transition().duration(1500).call(d3.axisLeft(y).ticks(5));</span></span>
<span id="cb6-2727"><a href></a></span>
<span id="cb6-2728"><a href></a><span class="co">// // Group data by basis function</span></span>
<span id="cb6-2729"><a href></a><span class="co">// const dataByFunction = Array.from(d3.group(data, d =&gt; d.b));</span></span>
<span id="cb6-2730"><a href></a><span class="co">// const keyFn = d =&gt; d[0];</span></span>
<span id="cb6-2731"><a href></a></span>
<span id="cb6-2732"><a href></a><span class="co">// // Update basis function lines</span></span>
<span id="cb6-2733"><a href></a><span class="co">// const u = linesGroup.selectAll(&quot;path&quot;).data(dataByFunction, keyFn);</span></span>
<span id="cb6-2734"><a href></a><span class="co">// u.join(</span></span>
<span id="cb6-2735"><a href></a><span class="co">// enter =&gt; enter.append(&quot;path&quot;).attr(&quot;fill&quot;,&quot;none&quot;).attr(&quot;stroke-width&quot;,3)</span></span>
<span id="cb6-2736"><a href></a><span class="co">// .attr(&quot;stroke&quot;, (_, i) =&gt; color(i)).attr(&quot;d&quot;, d =&gt; line(d[1].map(pt =&gt; ({x: pt.x, y: 0}))))</span></span>
<span id="cb6-2737"><a href></a><span class="co">// .style(&quot;opacity&quot;,0),</span></span>
<span id="cb6-2738"><a href></a><span class="co">// update =&gt; update,</span></span>
<span id="cb6-2739"><a href></a><span class="co">// exit =&gt; exit.transition().duration(1000).style(&quot;opacity&quot;,0).remove()</span></span>
<span id="cb6-2740"><a href></a><span class="co">// )</span></span>
<span id="cb6-2741"><a href></a><span class="co">// .transition().duration(1000)</span></span>
<span id="cb6-2742"><a href></a><span class="co">// .attr(&quot;d&quot;, d =&gt; line(d[1]))</span></span>
<span id="cb6-2743"><a href></a><span class="co">// .attr(&quot;stroke&quot;, (_, i) =&gt; color(i))</span></span>
<span id="cb6-2744"><a href></a><span class="co">// .style(&quot;opacity&quot;,1);</span></span>
<span id="cb6-2745"><a href></a><span class="co">// }</span></span>
<span id="cb6-2746"><a href></a></span>
<span id="cb6-2747"><a href></a>chart0 <span class="op">=</span> {</span>
<span id="cb6-2748"><a href></a> <span class="co">// State variables for selected parameters</span></span>
<span id="cb6-2749"><a href></a> <span class="kw">let</span> selectedMu <span class="op">=</span> <span class="fl">0.5</span><span class="op">;</span></span>
<span id="cb6-2750"><a href></a> <span class="kw">let</span> selectedSig <span class="op">=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb6-2751"><a href></a> <span class="kw">let</span> selectedNonc <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb6-2752"><a href></a> <span class="kw">let</span> selectedTailw <span class="op">=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb6-2753"><a href></a> <span class="kw">const</span> filteredData <span class="op">=</span> () <span class="kw">=&gt;</span> bsplineData<span class="op">.</span><span class="fu">filter</span>(d <span class="kw">=&gt;</span></span>
<span id="cb6-2754"><a href></a> <span class="bu">Math</span><span class="op">.</span><span class="fu">abs</span>(selectedMu <span class="op">-</span> d<span class="op">.</span><span class="at">mu</span>) <span class="op">&lt;</span> <span class="fl">0.001</span> <span class="op">&amp;&amp;</span></span>
<span id="cb6-2755"><a href></a> d<span class="op">.</span><span class="at">sig</span> <span class="op">===</span> selectedSig <span class="op">&amp;&amp;</span></span>
<span id="cb6-2756"><a href></a> d<span class="op">.</span><span class="at">nonc</span> <span class="op">===</span> selectedNonc <span class="op">&amp;&amp;</span></span>
<span id="cb6-2757"><a href></a> d<span class="op">.</span><span class="at">tailw</span> <span class="op">===</span> selectedTailw</span>
<span id="cb6-2758"><a href></a> )<span class="op">;</span></span>
<span id="cb6-2759"><a href></a> <span class="kw">const</span> container <span class="op">=</span> d3<span class="op">.</span><span class="fu">create</span>(<span class="st">&quot;div&quot;</span>)</span>
<span id="cb6-2760"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;max-width&quot;</span><span class="op">,</span> <span class="st">&quot;none&quot;</span>)</span>
<span id="cb6-2761"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;width&quot;</span><span class="op">,</span> <span class="st">&quot;100%&quot;</span>)<span class="op">;;</span></span>
<span id="cb6-2762"><a href></a> <span class="kw">const</span> controlsContainer <span class="op">=</span> container<span class="op">.</span><span class="fu">append</span>(<span class="st">&quot;div&quot;</span>)</span>
<span id="cb6-2763"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;display&quot;</span><span class="op">,</span> <span class="st">&quot;flex&quot;</span>)</span>
<span id="cb6-2764"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;gap&quot;</span><span class="op">,</span> <span class="st">&quot;20px&quot;</span>)<span class="op">;</span></span>
<span id="cb6-2765"><a href></a> <span class="co">// slider controls</span></span>
<span id="cb6-2766"><a href></a> <span class="kw">const</span> sliders <span class="op">=</span> [</span>
<span id="cb6-2767"><a href></a> { <span class="dt">label</span><span class="op">:</span> <span class="st">&#39;Mu&#39;</span><span class="op">,</span> <span class="kw">get</span><span class="op">:</span> () <span class="kw">=&gt;</span> selectedMu<span class="op">,</span> <span class="kw">set</span><span class="op">:</span> v <span class="kw">=&gt;</span> selectedMu <span class="op">=</span> v<span class="op">,</span> <span class="dt">min</span><span class="op">:</span> <span class="fl">0.1</span><span class="op">,</span> <span class="dt">max</span><span class="op">:</span> <span class="fl">0.9</span><span class="op">,</span> <span class="dt">step</span><span class="op">:</span> <span class="fl">0.2</span> }<span class="op">,</span></span>
<span id="cb6-2768"><a href></a> { <span class="dt">label</span><span class="op">:</span> <span class="st">&#39;Sigma&#39;</span><span class="op">,</span> <span class="kw">get</span><span class="op">:</span> () <span class="kw">=&gt;</span> <span class="bu">Math</span><span class="op">.</span><span class="fu">log2</span>(selectedSig)<span class="op">,</span> <span class="kw">set</span><span class="op">:</span> v <span class="kw">=&gt;</span> selectedSig <span class="op">=</span> <span class="dv">2</span> <span class="op">**</span> v<span class="op">,</span> <span class="dt">min</span><span class="op">:</span> <span class="op">-</span><span class="dv">2</span><span class="op">,</span> <span class="dt">max</span><span class="op">:</span> <span class="dv">2</span><span class="op">,</span> <span class="dt">step</span><span class="op">:</span> <span class="dv">1</span> }<span class="op">,</span></span>
<span id="cb6-2769"><a href></a> { <span class="dt">label</span><span class="op">:</span> <span class="st">&#39;Noncentrality&#39;</span><span class="op">,</span> <span class="kw">get</span><span class="op">:</span> () <span class="kw">=&gt;</span> selectedNonc<span class="op">,</span> <span class="kw">set</span><span class="op">:</span> v <span class="kw">=&gt;</span> selectedNonc <span class="op">=</span> v<span class="op">,</span> <span class="dt">min</span><span class="op">:</span> <span class="op">-</span><span class="dv">4</span><span class="op">,</span> <span class="dt">max</span><span class="op">:</span> <span class="dv">4</span><span class="op">,</span> <span class="dt">step</span><span class="op">:</span> <span class="dv">2</span> }<span class="op">,</span></span>
<span id="cb6-2770"><a href></a> { <span class="dt">label</span><span class="op">:</span> <span class="st">&#39;Tailweight&#39;</span><span class="op">,</span> <span class="kw">get</span><span class="op">:</span> () <span class="kw">=&gt;</span> <span class="bu">Math</span><span class="op">.</span><span class="fu">log2</span>(selectedTailw)<span class="op">,</span> <span class="kw">set</span><span class="op">:</span> v <span class="kw">=&gt;</span> selectedTailw <span class="op">=</span> <span class="dv">2</span> <span class="op">**</span> v<span class="op">,</span> <span class="dt">min</span><span class="op">:</span> <span class="op">-</span><span class="dv">2</span><span class="op">,</span> <span class="dt">max</span><span class="op">:</span> <span class="dv">2</span><span class="op">,</span> <span class="dt">step</span><span class="op">:</span> <span class="dv">1</span> }</span>
<span id="cb6-2771"><a href></a> ]<span class="op">;</span></span>
<span id="cb6-2772"><a href></a> <span class="co">// Build slider controls with D3 data join</span></span>
<span id="cb6-2773"><a href></a> <span class="kw">const</span> sliderCont <span class="op">=</span> controlsContainer<span class="op">.</span><span class="fu">selectAll</span>(<span class="st">&#39;div&#39;</span>)<span class="op">.</span><span class="fu">data</span>(sliders)<span class="op">.</span><span class="fu">join</span>(<span class="st">&#39;div&#39;</span>)</span>
<span id="cb6-2774"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&#39;display&#39;</span><span class="op">,</span><span class="st">&#39;flex&#39;</span>)<span class="op">.</span><span class="fu">style</span>(<span class="st">&#39;align-items&#39;</span><span class="op">,</span><span class="st">&#39;center&#39;</span>)<span class="op">.</span><span class="fu">style</span>(<span class="st">&#39;gap&#39;</span><span class="op">,</span><span class="st">&#39;10px&#39;</span>)</span>
<span id="cb6-2775"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&#39;flex&#39;</span><span class="op">,</span><span class="st">&#39;1&#39;</span>)<span class="op">.</span><span class="fu">style</span>(<span class="st">&#39;min-width&#39;</span><span class="op">,</span><span class="st">&#39;0px&#39;</span>)<span class="op">;</span></span>
<span id="cb6-2776"><a href></a> sliderCont<span class="op">.</span><span class="fu">append</span>(<span class="st">&#39;label&#39;</span>)<span class="op">.</span><span class="fu">text</span>(d <span class="kw">=&gt;</span> d<span class="op">.</span><span class="at">label</span> <span class="op">+</span> <span class="st">&#39;:&#39;</span>)<span class="op">.</span><span class="fu">style</span>(<span class="st">&#39;font-size&#39;</span><span class="op">,</span><span class="st">&#39;20px&#39;</span>)<span class="op">;</span></span>
<span id="cb6-2777"><a href></a> sliderCont<span class="op">.</span><span class="fu">append</span>(<span class="st">&#39;input&#39;</span>)</span>
<span id="cb6-2778"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&#39;type&#39;</span><span class="op">,</span><span class="st">&#39;range&#39;</span>)<span class="op">.</span><span class="fu">attr</span>(<span class="st">&#39;min&#39;</span><span class="op">,</span> d <span class="kw">=&gt;</span> d<span class="op">.</span><span class="at">min</span>)<span class="op">.</span><span class="fu">attr</span>(<span class="st">&#39;max&#39;</span><span class="op">,</span> d <span class="kw">=&gt;</span> d<span class="op">.</span><span class="at">max</span>)<span class="op">.</span><span class="fu">attr</span>(<span class="st">&#39;step&#39;</span><span class="op">,</span> d <span class="kw">=&gt;</span> d<span class="op">.</span><span class="at">step</span>)</span>
<span id="cb6-2779"><a href></a> <span class="op">.</span><span class="fu">property</span>(<span class="st">&#39;value&#39;</span><span class="op">,</span> d <span class="kw">=&gt;</span> d<span class="op">.</span><span class="fu">get</span>())</span>
<span id="cb6-2780"><a href></a> <span class="op">.</span><span class="fu">on</span>(<span class="st">&#39;input&#39;</span><span class="op">,</span> <span class="kw">function</span>(<span class="bu">event</span><span class="op">,</span> d) {</span>
<span id="cb6-2781"><a href></a> <span class="kw">const</span> val <span class="op">=</span> <span class="op">+</span><span class="kw">this</span><span class="op">.</span><span class="at">value</span><span class="op">;</span> d<span class="op">.</span><span class="fu">set</span>(val)<span class="op">;</span></span>
<span id="cb6-2782"><a href></a> d3<span class="op">.</span><span class="fu">select</span>(<span class="kw">this</span><span class="op">.</span><span class="at">parentNode</span>)<span class="op">.</span><span class="fu">select</span>(<span class="st">&#39;span&#39;</span>)<span class="op">.</span><span class="fu">text</span>(d<span class="op">.</span><span class="at">label</span><span class="op">.</span><span class="fu">match</span>(<span class="ss">/Sigma</span><span class="sc">|</span><span class="ss">Tailweight/</span>) <span class="op">?</span> <span class="dv">2</span><span class="op">**</span>val <span class="op">:</span> val)<span class="op">;</span></span>
<span id="cb6-2783"><a href></a> <span class="fu">updateChart</span>(<span class="fu">filteredData</span>())<span class="op">;</span></span>
<span id="cb6-2784"><a href></a> })</span>
<span id="cb6-2785"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&#39;width&#39;</span><span class="op">,</span> <span class="st">&#39;100%&#39;</span>)<span class="op">;</span></span>
<span id="cb6-2786"><a href></a> sliderCont<span class="op">.</span><span class="fu">append</span>(<span class="st">&#39;span&#39;</span>)<span class="op">.</span><span class="fu">text</span>(d <span class="kw">=&gt;</span> (d<span class="op">.</span><span class="at">label</span><span class="op">.</span><span class="fu">match</span>(<span class="ss">/Sigma</span><span class="sc">|</span><span class="ss">Tailweight/</span>) <span class="op">?</span> d<span class="op">.</span><span class="fu">get</span>() <span class="op">:</span> d<span class="op">.</span><span class="fu">get</span>()))</span>
<span id="cb6-2787"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&#39;font-size&#39;</span><span class="op">,</span><span class="st">&#39;20px&#39;</span>)<span class="op">;</span></span>
<span id="cb6-2788"><a href></a> </span>
<span id="cb6-2789"><a href></a> <span class="co">// Add Reset button to clear all sliders to their defaults</span></span>
<span id="cb6-2790"><a href></a> controlsContainer<span class="op">.</span><span class="fu">append</span>(<span class="st">&#39;button&#39;</span>)</span>
<span id="cb6-2791"><a href></a> <span class="op">.</span><span class="fu">text</span>(<span class="st">&#39;Reset&#39;</span>)</span>
<span id="cb6-2792"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&#39;font-size&#39;</span><span class="op">,</span> <span class="st">&#39;20px&#39;</span>)</span>
<span id="cb6-2793"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&#39;align-self&#39;</span><span class="op">,</span> <span class="st">&#39;center&#39;</span>)</span>
<span id="cb6-2794"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&#39;margin-left&#39;</span><span class="op">,</span> <span class="st">&#39;auto&#39;</span>)</span>
<span id="cb6-2795"><a href></a> <span class="op">.</span><span class="fu">on</span>(<span class="st">&#39;click&#39;</span><span class="op">,</span> () <span class="kw">=&gt;</span> {</span>
<span id="cb6-2796"><a href></a> <span class="co">// reset state vars</span></span>
<span id="cb6-2797"><a href></a> selectedMu <span class="op">=</span> <span class="fl">0.5</span><span class="op">;</span></span>
<span id="cb6-2798"><a href></a> selectedSig <span class="op">=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb6-2799"><a href></a> selectedNonc <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb6-2800"><a href></a> selectedTailw <span class="op">=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb6-2801"><a href></a> <span class="co">// update input positions</span></span>
<span id="cb6-2802"><a href></a> sliderCont<span class="op">.</span><span class="fu">selectAll</span>(<span class="st">&#39;input&#39;</span>)<span class="op">.</span><span class="fu">property</span>(<span class="st">&#39;value&#39;</span><span class="op">,</span> d <span class="kw">=&gt;</span> d<span class="op">.</span><span class="fu">get</span>())<span class="op">;</span></span>
<span id="cb6-2803"><a href></a> <span class="co">// update displayed labels</span></span>
<span id="cb6-2804"><a href></a> sliderCont<span class="op">.</span><span class="fu">selectAll</span>(<span class="st">&#39;span&#39;</span>)</span>
<span id="cb6-2805"><a href></a> <span class="op">.</span><span class="fu">text</span>(d <span class="kw">=&gt;</span> d<span class="op">.</span><span class="at">label</span><span class="op">.</span><span class="fu">match</span>(<span class="ss">/Sigma</span><span class="sc">|</span><span class="ss">Tailweight/</span>) <span class="op">?</span> (<span class="dv">2</span><span class="op">**</span>d<span class="op">.</span><span class="fu">get</span>()) <span class="op">:</span> d<span class="op">.</span><span class="fu">get</span>())<span class="op">;</span></span>
<span id="cb6-2806"><a href></a> <span class="co">// redraw chart</span></span>
<span id="cb6-2807"><a href></a> <span class="fu">updateChart</span>(<span class="fu">filteredData</span>())<span class="op">;</span></span>
<span id="cb6-2808"><a href></a> })<span class="op">;</span></span>
<span id="cb6-2809"><a href></a></span>
<span id="cb6-2810"><a href></a> <span class="co">// Build SVG</span></span>
<span id="cb6-2811"><a href></a> <span class="kw">const</span> width <span class="op">=</span> <span class="dv">1200</span><span class="op">;</span></span>
<span id="cb6-2812"><a href></a> <span class="kw">const</span> height <span class="op">=</span> <span class="dv">450</span><span class="op">;</span></span>
<span id="cb6-2813"><a href></a> <span class="kw">const</span> margin <span class="op">=</span> {<span class="dt">top</span><span class="op">:</span> <span class="dv">40</span><span class="op">,</span> <span class="dt">right</span><span class="op">:</span> <span class="dv">20</span><span class="op">,</span> <span class="dt">bottom</span><span class="op">:</span> <span class="dv">40</span><span class="op">,</span> <span class="dt">left</span><span class="op">:</span> <span class="dv">40</span>}<span class="op">;</span></span>
<span id="cb6-2814"><a href></a> <span class="kw">const</span> innerWidth <span class="op">=</span> width <span class="op">-</span> margin<span class="op">.</span><span class="at">left</span> <span class="op">-</span> margin<span class="op">.</span><span class="at">right</span><span class="op">;</span></span>
<span id="cb6-2815"><a href></a> <span class="kw">const</span> innerHeight <span class="op">=</span> height <span class="op">-</span> margin<span class="op">.</span><span class="at">top</span> <span class="op">-</span> margin<span class="op">.</span><span class="at">bottom</span><span class="op">;</span></span>
<span id="cb6-2816"><a href></a></span>
<span id="cb6-2817"><a href></a> <span class="co">// Set controls container width to match SVG plot width</span></span>
<span id="cb6-2818"><a href></a> controlsContainer<span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;max-width&quot;</span><span class="op">,</span> <span class="st">&quot;none&quot;</span>)<span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;width&quot;</span><span class="op">,</span> <span class="st">&quot;100%&quot;</span>)<span class="op">;</span></span>
<span id="cb6-2819"><a href></a> <span class="co">// Distribute each control evenly and make sliders full-width</span></span>
<span id="cb6-2820"><a href></a> controlsContainer<span class="op">.</span><span class="fu">selectAll</span>(<span class="st">&quot;div&quot;</span>)<span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;flex&quot;</span><span class="op">,</span> <span class="st">&quot;1&quot;</span>)<span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;min-width&quot;</span><span class="op">,</span> <span class="st">&quot;0px&quot;</span>)<span class="op">;</span></span>
<span id="cb6-2821"><a href></a> controlsContainer<span class="op">.</span><span class="fu">selectAll</span>(<span class="st">&quot;input&quot;</span>)<span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;width&quot;</span><span class="op">,</span> <span class="st">&quot;100%&quot;</span>)<span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;box-sizing&quot;</span><span class="op">,</span> <span class="st">&quot;border-box&quot;</span>)<span class="op">;</span></span>
<span id="cb6-2822"><a href></a> </span>
<span id="cb6-2823"><a href></a> <span class="co">// Create scales</span></span>
<span id="cb6-2824"><a href></a> <span class="kw">const</span> x <span class="op">=</span> d3<span class="op">.</span><span class="fu">scaleLinear</span>()</span>
<span id="cb6-2825"><a href></a> <span class="op">.</span><span class="fu">domain</span>([<span class="dv">0</span><span class="op">,</span> <span class="dv">1</span>])</span>
<span id="cb6-2826"><a href></a> <span class="op">.</span><span class="fu">range</span>([<span class="dv">0</span><span class="op">,</span> innerWidth])<span class="op">;</span></span>
<span id="cb6-2827"><a href></a> </span>
<span id="cb6-2828"><a href></a> <span class="kw">const</span> y <span class="op">=</span> d3<span class="op">.</span><span class="fu">scaleLinear</span>()</span>
<span id="cb6-2829"><a href></a> <span class="op">.</span><span class="fu">domain</span>([<span class="dv">0</span><span class="op">,</span> <span class="dv">1</span>])</span>
<span id="cb6-2830"><a href></a> <span class="op">.</span><span class="fu">range</span>([innerHeight<span class="op">,</span> <span class="dv">0</span>])<span class="op">;</span></span>
<span id="cb6-2831"><a href></a> </span>
<span id="cb6-2832"><a href></a> <span class="co">// Create a color scale for the basis functions</span></span>
<span id="cb6-2833"><a href></a> <span class="kw">const</span> color <span class="op">=</span> d3<span class="op">.</span><span class="fu">scaleOrdinal</span>(d3<span class="op">.</span><span class="at">schemeCategory10</span>)<span class="op">;</span></span>
<span id="cb6-2834"><a href></a> </span>
<span id="cb6-2835"><a href></a> <span class="co">// Create SVG</span></span>
<span id="cb6-2836"><a href></a> <span class="kw">const</span> svg <span class="op">=</span> d3<span class="op">.</span><span class="fu">create</span>(<span class="st">&quot;svg&quot;</span>)</span>
<span id="cb6-2837"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;width&quot;</span><span class="op">,</span> <span class="st">&quot;100%&quot;</span>)</span>
<span id="cb6-2838"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;height&quot;</span><span class="op">,</span> <span class="st">&quot;auto&quot;</span>)</span>
<span id="cb6-2839"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;viewBox&quot;</span><span class="op">,</span> [<span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> width<span class="op">,</span> height])</span>
<span id="cb6-2840"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;preserveAspectRatio&quot;</span><span class="op">,</span> <span class="st">&quot;xMidYMid meet&quot;</span>)</span>
<span id="cb6-2841"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;style&quot;</span><span class="op">,</span> <span class="st">&quot;max-width: 100%; height: auto;&quot;</span>)<span class="op">;</span></span>
<span id="cb6-2842"><a href></a> </span>
<span id="cb6-2843"><a href></a> <span class="co">// Create the chart group</span></span>
<span id="cb6-2844"><a href></a> <span class="kw">const</span> g <span class="op">=</span> svg<span class="op">.</span><span class="fu">append</span>(<span class="st">&quot;g&quot;</span>)</span>
<span id="cb6-2845"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;transform&quot;</span><span class="op">,</span> <span class="vs">`translate(</span><span class="sc">${</span>margin<span class="op">.</span><span class="at">left</span><span class="sc">}</span><span class="vs">,</span><span class="sc">${</span>margin<span class="op">.</span><span class="at">top</span><span class="sc">}</span><span class="vs">)`</span>)<span class="op">;</span></span>
<span id="cb6-2846"><a href></a> </span>
<span id="cb6-2847"><a href></a> <span class="co">// Add axes</span></span>
<span id="cb6-2848"><a href></a> <span class="kw">const</span> xAxis <span class="op">=</span> g<span class="op">.</span><span class="fu">append</span>(<span class="st">&quot;g&quot;</span>)</span>
<span id="cb6-2849"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;transform&quot;</span><span class="op">,</span> <span class="vs">`translate(0,</span><span class="sc">${</span>innerHeight<span class="sc">}</span><span class="vs">)`</span>)</span>
<span id="cb6-2850"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;class&quot;</span><span class="op">,</span> <span class="st">&quot;x-axis&quot;</span>)</span>
<span id="cb6-2851"><a href></a> <span class="op">.</span><span class="fu">call</span>(d3<span class="op">.</span><span class="fu">axisBottom</span>(x)<span class="op">.</span><span class="fu">ticks</span>(<span class="dv">10</span>))</span>
<span id="cb6-2852"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;font-size&quot;</span><span class="op">,</span> <span class="st">&quot;20px&quot;</span>)<span class="op">;</span></span>
<span id="cb6-2853"><a href></a> </span>
<span id="cb6-2854"><a href></a> <span class="kw">const</span> yAxis <span class="op">=</span> g<span class="op">.</span><span class="fu">append</span>(<span class="st">&quot;g&quot;</span>)</span>
<span id="cb6-2855"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;class&quot;</span><span class="op">,</span> <span class="st">&quot;y-axis&quot;</span>)</span>
<span id="cb6-2856"><a href></a> <span class="op">.</span><span class="fu">call</span>(d3<span class="op">.</span><span class="fu">axisLeft</span>(y)<span class="op">.</span><span class="fu">ticks</span>(<span class="dv">5</span>))</span>
<span id="cb6-2857"><a href></a> <span class="op">.</span><span class="fu">style</span>(<span class="st">&quot;font-size&quot;</span><span class="op">,</span> <span class="st">&quot;20px&quot;</span>)<span class="op">;</span></span>
<span id="cb6-2858"><a href></a> </span>
<span id="cb6-2859"><a href></a> <span class="co">// Add a horizontal line at y = 0</span></span>
<span id="cb6-2860"><a href></a> g<span class="op">.</span><span class="fu">append</span>(<span class="st">&quot;line&quot;</span>)</span>
<span id="cb6-2861"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;x1&quot;</span><span class="op">,</span> <span class="dv">0</span>)</span>
<span id="cb6-2862"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;x2&quot;</span><span class="op">,</span> innerWidth)</span>
<span id="cb6-2863"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;y1&quot;</span><span class="op">,</span> <span class="fu">y</span>(<span class="dv">0</span>))</span>
<span id="cb6-2864"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;y2&quot;</span><span class="op">,</span> <span class="fu">y</span>(<span class="dv">0</span>))</span>
<span id="cb6-2865"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;stroke&quot;</span><span class="op">,</span> <span class="st">&quot;#000&quot;</span>)</span>
<span id="cb6-2866"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;stroke-opacity&quot;</span><span class="op">,</span> <span class="fl">0.2</span>)<span class="op">;</span></span>
<span id="cb6-2867"><a href></a> </span>
<span id="cb6-2868"><a href></a> <span class="co">// Add gridlines</span></span>
<span id="cb6-2869"><a href></a> g<span class="op">.</span><span class="fu">append</span>(<span class="st">&quot;g&quot;</span>)</span>
<span id="cb6-2870"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;class&quot;</span><span class="op">,</span> <span class="st">&quot;grid-lines&quot;</span>)</span>
<span id="cb6-2871"><a href></a> <span class="op">.</span><span class="fu">selectAll</span>(<span class="st">&quot;line&quot;</span>)</span>
<span id="cb6-2872"><a href></a> <span class="op">.</span><span class="fu">data</span>(y<span class="op">.</span><span class="fu">ticks</span>(<span class="dv">5</span>))</span>
<span id="cb6-2873"><a href></a> <span class="op">.</span><span class="fu">join</span>(<span class="st">&quot;line&quot;</span>)</span>
<span id="cb6-2874"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;x1&quot;</span><span class="op">,</span> <span class="dv">0</span>)</span>
<span id="cb6-2875"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;x2&quot;</span><span class="op">,</span> innerWidth)</span>
<span id="cb6-2876"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;y1&quot;</span><span class="op">,</span> d <span class="kw">=&gt;</span> <span class="fu">y</span>(d))</span>
<span id="cb6-2877"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;y2&quot;</span><span class="op">,</span> d <span class="kw">=&gt;</span> <span class="fu">y</span>(d))</span>
<span id="cb6-2878"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;stroke&quot;</span><span class="op">,</span> <span class="st">&quot;#ccc&quot;</span>)</span>
<span id="cb6-2879"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;stroke-opacity&quot;</span><span class="op">,</span> <span class="fl">0.5</span>)<span class="op">;</span></span>
<span id="cb6-2880"><a href></a> </span>
<span id="cb6-2881"><a href></a> <span class="co">// Create a line generator</span></span>
<span id="cb6-2882"><a href></a> <span class="kw">const</span> line <span class="op">=</span> d3<span class="op">.</span><span class="fu">line</span>()</span>
<span id="cb6-2883"><a href></a> <span class="op">.</span><span class="fu">x</span>(d <span class="kw">=&gt;</span> <span class="fu">x</span>(d<span class="op">.</span><span class="at">x</span>))</span>
<span id="cb6-2884"><a href></a> <span class="op">.</span><span class="fu">y</span>(d <span class="kw">=&gt;</span> <span class="fu">y</span>(d<span class="op">.</span><span class="at">y</span>))</span>
<span id="cb6-2885"><a href></a> <span class="op">.</span><span class="fu">curve</span>(d3<span class="op">.</span><span class="at">curveBasis</span>)<span class="op">;</span></span>
<span id="cb6-2886"><a href></a> </span>
<span id="cb6-2887"><a href></a> <span class="co">// Group to contain the basis function lines</span></span>
<span id="cb6-2888"><a href></a> <span class="kw">const</span> linesGroup <span class="op">=</span> g<span class="op">.</span><span class="fu">append</span>(<span class="st">&quot;g&quot;</span>)</span>
<span id="cb6-2889"><a href></a> <span class="op">.</span><span class="fu">attr</span>(<span class="st">&quot;class&quot;</span><span class="op">,</span> <span class="st">&quot;basis-functions&quot;</span>)<span class="op">;</span></span>
<span id="cb6-2890"><a href></a> </span>
<span id="cb6-2891"><a href></a> <span class="co">// Store the current basis functions for transition</span></span>
<span id="cb6-2892"><a href></a> <span class="kw">let</span> currentBasisFunctions <span class="op">=</span> <span class="kw">new</span> <span class="bu">Map</span>()<span class="op">;</span></span>
<span id="cb6-2893"><a href></a> </span>
<span id="cb6-2894"><a href></a> <span class="co">// Function to update the chart with new data</span></span>
<span id="cb6-2895"><a href></a> <span class="kw">function</span> <span class="fu">updateChart</span>(data) {</span>
<span id="cb6-2896"><a href></a> <span class="fu">updateChartInner</span>(g<span class="op">,</span> x<span class="op">,</span> y<span class="op">,</span> linesGroup<span class="op">,</span> color<span class="op">,</span> line<span class="op">,</span> data)<span class="op">;</span></span>
<span id="cb6-2897"><a href></a> }</span>
<span id="cb6-2898"><a href></a> </span>
<span id="cb6-2899"><a href></a> <span class="co">// Store the update function</span></span>
<span id="cb6-2900"><a href></a> svg<span class="op">.</span><span class="fu">node</span>()<span class="op">.</span><span class="at">update</span> <span class="op">=</span> updateChart<span class="op">;</span></span>
<span id="cb6-2901"><a href></a> </span>
<span id="cb6-2902"><a href></a> <span class="co">// Initial render</span></span>
<span id="cb6-2903"><a href></a> <span class="fu">updateChart</span>(<span class="fu">filteredData</span>())<span class="op">;</span></span>
<span id="cb6-2904"><a href></a> </span>
<span id="cb6-2905"><a href></a> container<span class="op">.</span><span class="fu">node</span>()<span class="op">.</span><span class="fu">appendChild</span>(svg<span class="op">.</span><span class="fu">node</span>())<span class="op">;</span></span>
<span id="cb6-2906"><a href></a> <span class="cf">return</span> container<span class="op">.</span><span class="fu">node</span>()<span class="op">;</span></span>
<span id="cb6-2907"><a href></a>}</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output cell-output-display">
<div id="ojs-cell-5" data-nodetype="declaration">

View File

@@ -1141,9 +1141,7 @@ Strictly proper for *median* predictions
::::
## Popular Algorithms and the Risk
<br/>
## &nbsp;
:::: {.columns}
@@ -1151,8 +1149,6 @@ Strictly proper for *median* predictions
### Popular Aggregation Algorithms
<br/>
#### The naive combination
@@ -1178,15 +1174,18 @@ w_{t,k}^{\text{Naive}} = \frac{1}{K}\label{eq:naive_combination}
::: {.column width="48%"}
### Optimality
### Risk
In stochastic settings, the cumulative Risk should be analyzed @wintenberger2017optimal:
\begin{align}
&\underbrace{\widetilde{\mathcal{R}}_t = \sum_{i=1}^t \mathbb{E}[\ell(\widetilde{X}_{i},Y_i)|\mathcal{F}_{i-1}]}_{\text{Cumulative Risk of Forecaster}} \\
&\underbrace{\widehat{\mathcal{R}}_{t,k} = \sum_{i=1}^t \mathbb{E}[\ell(\widehat{X}_{i,k},Y_i)|\mathcal{F}_{i-1}]}_{\text{Cumulative Risk of Experts}}
\label{eq_def_cumrisk}
\end{align}
<i class="fa fa-fw fa-arrow-right" style="color:var(--col_grey_9);"></i> (7) expected loss of the algorithm (lower = better)
:::
::::
@@ -1256,12 +1255,15 @@ Algorithms can statisfy both \eqref{eq_optp_select} and \eqref{eq_optp_conv} dep
<br/>
#### Requirements:
EWA satisfies optimal selection convergence \eqref{eq_optp_select} in a deterministic setting if:
- Loss $\ell$ is exp-concave
- Learning-rate $\eta$ is chosen correctly
<i class="fa fa-fw fa-triangle-exclamation" style="color:var(--col_amber_9);"></i> Loss $\ell$ is exp-concave
Those results can be converted to any stochastic setting @wintenberger2017optimal.
<i class="fa fa-fw fa-triangle-exclamation" style="color:var(--col_amber_9);"></i> Learning-rate $\eta$ is chosen correctly
Those results can be converted to *any* stochastic setting @wintenberger2017optimal.
Optimal convex aggregation convergence \eqref{eq_optp_conv} can be satisfied by applying the kernel-trick:
@@ -1283,7 +1285,7 @@ $\ell'$ is the subgradient of $\ell$ at forecast combination $\widetilde{X}$.
<br/>
**An appropriate choice:**
#### An appropriate choice:
\begin{equation*}
\text{CRPS}(F, y) = \int_{\mathbb{R}} {(F(x) - \mathbb{1}\{ x > y \})}^2 dx \label{eq:crps}
@@ -1293,7 +1295,7 @@ It's strictly proper [@gneiting2007strictly].
Using the CRPS, we can calculate time-adaptive weights $w_{t,k}$. However, what if the experts' performance varies in parts of the distribution?
<i class="fa fa-fw fa-lightbulb" style="color:var(--col_yellow_9);"></i> Utilize this relation:
<i class="fa fa-fw fa-lightbulb" style="color:var(--col_yellow_8);"></i> Utilize this relation:
\begin{equation*}
\text{CRPS}(F, y) = 2 \int_0^{1} \text{QL}_p(F^{-1}(p), y) dp.\label{eq_crps_qs}
@@ -1311,9 +1313,9 @@ Using the CRPS, we can calculate time-adaptive weights $w_{t,k}$. However, what
## Almost Optimal Convergence
:::: {style="font-size: 90%;"}
:::: {style="font-size: 85%;"}
<i class="fa fa-fw fa-exclamation" style="color:var(--col_orange_10);"></i> QL is convex, but not exp-concave
<i class="fa fa-fw fa-triangle-exclamation" style="color:var(--col_amber_9);"></i> QL is convex, but not exp-concave
<i class="fa fa-fw fa-arrow-right" style="color:var(--col_grey_10);"></i> Bernstein Online Aggregation (BOA) lets us weaken the exp-concavity condition. It satisfies that there exist a $C>0$ such that for $x>0$ it holds that
@@ -1323,6 +1325,8 @@ Using the CRPS, we can calculate time-adaptive weights $w_{t,k}$. However, what
\label{eq_boa_opt_conv}
\end{equation}
if the loss function is convex.
<i class="fa fa-fw fa-arrow-right" style="color:var(--col_grey_10);"></i> Almost optimal w.r.t. *convex aggregation* \eqref{eq_optp_conv} @wintenberger2017optimal.
The same algorithm satisfies that there exist a $C>0$ such that for $x>0$ it holds that
@@ -1333,7 +1337,7 @@ The same algorithm satisfies that there exist a $C>0$ such that for $x>0$ it hol
\label{eq_boa_opt_select}
\end{equation}
if $Y_t$ is bounded, the considered loss $\ell$ is convex, $G$-Lipschitz, and weak exp-concave in its first coordinate.
if the loss $\ell$ is $G$-Lipschitz and weak exp-concave in its first coordinate
<i class="fa fa-fw fa-arrow-right" style="color:var(--col_grey_10);"></i> Almost optimal w.r.t. *selection* \eqref{eq_optp_select} @gaillard2018efficient.
@@ -1341,14 +1345,14 @@ if $Y_t$ is bounded, the considered loss $\ell$ is convex, $G$-Lipschitz, and we
:::
## Conditions + Lemma
## Proposition + Conditions
:::: {.columns}
::: {.column width="48%"}
**Lemma 1**
**Proposition 1: The Power of Flexibility**
\begin{align}
2\overline{\widehat{\mathcal{R}}}^{\text{QL}}_{t,\min}
@@ -1361,15 +1365,17 @@ if $Y_t$ is bounded, the considered loss $\ell$ is convex, $G$-Lipschitz, and we
Pointwise can outperform constant procedures
QL is convex but not exp-concave:
<i class="fa fa-fw fa-arrow-right" style="color:var(--col_grey_10);"></i> $\text{QL}$ is convex: almost optimal convergence w.r.t. *convex aggregation* \eqref{eq_boa_opt_conv} <i class="fa fa-fw fa-check" style="color:var(--col_green_9);"></i> </br>
<i class="fa fa-fw fa-arrow-right" style="color:var(--col_grey_10);"></i> Almost optimal convergence w.r.t. *convex aggregation* \eqref{eq_boa_opt_conv} <i class="fa fa-fw fa-check" style="color:var(--col_green_9);"></i> </br>
For almost optimal congerence w.r.t. *selection* \eqref{eq_boa_opt_select} we need:
For almost optimal congerence w.r.t. *selection* \eqref{eq_boa_opt_select} we need to check **A1** and **A2**:
**A1: Lipschitz Continuity**
QL is Lipschitz continuous:
**A2: Weak Exp-Concavity**
<i class="fa fa-fw fa-arrow-right" style="color:var(--col_grey_10);"></i> **A1** holds <i class="fa fa-fw fa-check" style="color:var(--col_orange_9);"></i>
QL is Lipschitz continuous with $G=\max(p, 1-p)$:
<i class="fa fa-fw fa-arrow-right" style="color:var(--col_grey_10);"></i> **A1** holds <i class="fa fa-fw fa-check" style="color:var(--col_green_9);"></i>
:::
@@ -1379,14 +1385,16 @@ QL is Lipschitz continuous:
::: {.column width="48%"}
**A1**
**A1: Lipschitz Continuity**
For some $G>0$ it holds
for all $x_1,x_2\in \mathbb{R}$ and $t>0$ that
$$ | \ell(x_1, Y_t)-\ell(x_2, Y_t) | \leq G |x_1-x_2|$$
**A2** For some $\alpha>0$, $\beta\in[0,1]$ it holds
**A2 Weak Exp-Concavity**
For some $\alpha>0$, $\beta\in[0,1]$ it holds
for all $x_1,x_2 \in \mathbb{R}$ and $t>0$ that
\begin{align*}
@@ -1397,7 +1405,7 @@ for all $x_1,x_2 \in \mathbb{R}$ and $t>0$ that
\mathbb{E}\left[ \left. \left( \alpha(\ell'(x_1, Y_t)(x_1 - x_2))^{2}\right)^{1/\beta} \right|\mathcal{F}_{t-1}\right]
\end{align*}
<i class="fa fa-fw fa-arrow-right" style="color:var(--col_grey_10);"></i> Almost optimal w.r.t. *selection* \eqref{eq_optp_select} @gaillard2018efficient.
If $\beta=1$ we get strong-convexity, which implies weak exp-concavity
:::
@@ -1414,16 +1422,15 @@ Conditional quantile risk: $\mathcal{Q}_p(x) = \mathbb{E}[ \text{QL}_p(x, Y_t) |
<i class="fa fa-fw fa-arrow-right" style="color:var(--col_grey_10);"></i> convexity properties of $\mathcal{Q}_p$ depend on the
conditional distribution $Y_t|\mathcal{F}_{t-1}$.
**Proposition 1**
**Proposition 2**
Let $Y$ be a univariate random variable with (Radon-Nikodym) $\nu$-density $f$, then for the second subderivative of the quantile risk
$\mathcal{Q}_p(x) = \mathbb{E}[ \text{QL}_p(x, Y) ]$
of $Y$ it holds for all $p\in(0,1)$ that
$\mathcal{Q}_p'' = f.$
Additionally, if $f$ is a continuous Lebesgue-density with $f\geq\gamma>0$ for some constant $\gamma>0$ on its support $\text{spt}(f)$ then
is $\mathcal{Q}_p$ is $\gamma$-strongly convex.
Additionally, if $f$ is a continuous Lebesgue-density with $f\geq\gamma>0$ for some constant $\gamma>0$ on its support $\text{spt}(f)$ then $\mathcal{Q}_p$ is $\gamma$-strongly convex, which implies satisfaction of condition
Strong convexity with $\beta=1$ implies weak exp-concavity **A2** <i class="fa fa-fw fa-check" style="color:var(--col_green_9);"></i> @gaillard2018efficient
**A2** with $\beta=1$ <i class="fa fa-fw fa-check" style="color:var(--col_green_9);"></i> @gaillard2018efficient
:::
@@ -1433,8 +1440,6 @@ Strong convexity with $\beta=1$ implies weak exp-concavity **A2** <i class="fa f
::: {.column width="48%"}
<i class="fa fa-fw fa-arrow-right" style="color:var(--col_grey_10);"></i> **A1** and **A2** give us almost optimal convergence w.r.t. selection \eqref{eq_boa_opt_select} <i class="fa fa-fw fa-check" style="color:var(--col_green_9);"></i> </br>
**Theorem 1**
The gradient based fully adaptive Bernstein online aggregation (BOAG) applied pointwise for all $p\in(0,1)$ on $\text{QL}$ satisfies
@@ -1444,9 +1449,11 @@ $$\widehat{\mathcal{R}}_{t,\pi} = 2\overline{\widehat{\mathcal{R}}}^{\text{QL}}_
If $Y_t|\mathcal{F}_{t-1}$ is bounded
and has a pdf $f_t$ satifying $f_t>\gamma >0$ on its
support $\text{spt}(f_t)$ then \ref{eq_boa_opt_select} holds with $\beta=1$ and
support $\text{spt}(f_t)$ then \eqref{eq_boa_opt_select} holds with $\beta=1$ and
$$\widehat{\mathcal{R}}_{t,\min} = 2\overline{\widehat{\mathcal{R}}}^{\text{QL}}_{t,\min}$$.
$$\widehat{\mathcal{R}}_{t,\min} = 2\overline{\widehat{\mathcal{R}}}^{\text{QL}}_{t,\min}$$
<i class="fa fa-fw fa-check-double" style="color:var(--col_green_9);"></i> BOAG with $\text{QL}$ satisfies \eqref{eq_boa_opt_conv} and \eqref{eq_boa_opt_select}
:::
@@ -1454,12 +1461,6 @@ $$\widehat{\mathcal{R}}_{t,\min} = 2\overline{\widehat{\mathcal{R}}}^{\text{QL}}
::::
:::: {.notes}
We apply Bernstein Online Aggregation (BOA). It lets us weaken the exp-concavity condition while almost keeping the optimalities \ref{eq_optp_select} and \ref{eq_optp_conv}.
::::
## A Probabilistic Example
@@ -2054,7 +2055,7 @@ for (i.p in 1:MO) {
table_col[, i.p] <- rgb(fred, fgreen, fblue, maxColorValue = 1)
table[, i.p] <- paste0(
table[, i.p],
'<sup>(', Pallout[i.p], ")</sup>"
"<sup>(", Pallout[i.p], ")</sup>"
)
}
@@ -2062,7 +2063,8 @@ table_out <- kbl(
table,
align = rep("c", ncol(table)),
bootstrap_options = c("condensed"),
escape = FALSE) %>%
escape = FALSE
) %>%
kable_paper(full_width = TRUE) %>%
row_spec(0:nrow(table), color = cols[9, "grey"])
@@ -2477,11 +2479,11 @@ table_performance <- performance_loss_tibble %>%
kbl(
padding = -1L,
col.names = c(
'Description',
'Parameter Tuning',
'BOA',
'ML-Poly',
'EWA'
"Description",
"Parameter Tuning",
"BOA",
"ML-Poly",
"EWA"
),
bootstrap_options = "condensed",
# Dont replace any string, dataframe has to be valid latex code ...