<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Posts | 🤖</title><link>https://aleksandr-lomakin.netlify.app/post/</link><atom:link href="https://aleksandr-lomakin.netlify.app/post/index.xml" rel="self" type="application/rss+xml"/><description>Posts</description><generator>Hugo Blox Builder (https://hugoblox.com)</generator><language>en-us</language><image><url>https://aleksandr-lomakin.netlify.app/media/icon_hu6f4f7114d634595c679a100330856427_19746_512x512_fill_lanczos_center_3.png</url><title>Posts</title><link>https://aleksandr-lomakin.netlify.app/post/</link></image><item><title>Stereo Transformer &amp; Sinkhorn Iterations</title><link>https://aleksandr-lomakin.netlify.app/post/sinkhorn/</link><pubDate>Fri, 08 Mar 2024 00:00:00 +0000</pubDate><guid>https://aleksandr-lomakin.netlify.app/post/sinkhorn/</guid><description>&lt;p>&lt;strong>Revisiting Stereo Depth Estimation from a Sequence-to-Sequence Perspective with Transformers&lt;/strong>&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>.&lt;/p>
&lt;p>This may seem like an outdated paper from prehistoric 2021, especially in the contemporary high-speed deep learning race, but it&amp;rsquo;s full of original ideas:&lt;/p>
&lt;ul>
&lt;li>Using transformer&amp;rsquo;s cross-attention for stereo matching without restriction to a disparity range and without the need for constructing highly memory-demanding discrete cost volumes.&lt;/li>
&lt;li>Clever use of entropy-regularised optimal transport to impose a uniqueness constraint on disparity with the elegant differentiable Sinkhorn algorithm.&lt;/li>
&lt;li>No finite and fixed discrete disparity values, instead a dense continuous disparity function allowing for a sub-pixel resolution.&lt;/li>
&lt;li>Naturally handles occlusions by using a learnable parameter to assign the cost of an unmatched pixel.&lt;/li>
&lt;/ul>
&lt;p>Let&amp;rsquo;s scratch a little bit on the surface of the theory of optimal transport and see how it came to be useful in the modern deep learning workflow.&lt;/p>
&lt;hr>
&lt;p>The &lt;strong>optimal transport&lt;/strong> problem originated from Gaspard Monge&amp;rsquo;s 1781 paper on the optimality of moving a pile of dirt from one place to another. It minimises the total work required, taking into account the transportation cost, which is determined by the amount of mass moved and the distance taken:&lt;/p>
&lt;figure class="mongo_dark" >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/sinkhorn/monge_dark_hu2544f3b7e601579f00b9128036b78367_405861_a6e65af50ba2bd69691ecdf004d8a01d.webp 400w,
/post/sinkhorn/monge_dark_hu2544f3b7e601579f00b9128036b78367_405861_b0d1ba19c1d84614be175c4d296b7a27.webp 760w,
/post/sinkhorn/monge_dark_hu2544f3b7e601579f00b9128036b78367_405861_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://aleksandr-lomakin.netlify.app/post/sinkhorn/monge_dark_hu2544f3b7e601579f00b9128036b78367_405861_a6e65af50ba2bd69691ecdf004d8a01d.webp"
width="400"
height="760"
loading="lazy" data-zoomable class=" img-dark" />&lt;/div>
&lt;/div>&lt;/figure>
&lt;figure class="mongo_light" >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/sinkhorn/monge_light_huacab4fec9272b98f8daff08ff4dd543c_193815_ff751af06e9a88b447f37faea3b12a68.webp 400w,
/post/sinkhorn/monge_light_huacab4fec9272b98f8daff08ff4dd543c_193815_fe1b8781005120e6e4d2c8402c4290a0.webp 760w,
/post/sinkhorn/monge_light_huacab4fec9272b98f8daff08ff4dd543c_193815_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://aleksandr-lomakin.netlify.app/post/sinkhorn/monge_light_huacab4fec9272b98f8daff08ff4dd543c_193815_ff751af06e9a88b447f37faea3b12a68.webp"
width="400"
height="760"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;p>This formulation is a special case of the optimal transport problem where the cost of transportation is given by Euclidean distance. It is commonly referred as &lt;strong>Earth Mover&amp;rsquo;s Distance&lt;/strong>.&lt;/p>
&lt;p>Sometimes we need to measure the distance between two distributions (
$ \pi $ and
$ p $ ), for example in GANs or variational autoencoders.&lt;/p>
&lt;div id="chart-952643871" class="chart">&lt;/div>
&lt;script>
(function() {
let a = setInterval( function() {
if ( typeof window.Plotly === 'undefined' ) {
return;
}
clearInterval( a );
Plotly.d3.json("./two_distributions.json", function(chart) {
Plotly.plot('chart-952643871', chart.data, chart.layout, {responsive: true});
});
}, 500 );
})();
&lt;/script>
&lt;p>For this purpose we already have a well known family of
$ f $-divergencies
$ D_f(\pi || p) = \mathbb{E}_{p(x)} f\left ( \frac{\pi(x)}{p(x)} \right )$, Kullback–Leibler or Jensen-Shannon to name a few. But for disjoint manifolds or distributions with disjoint supports they no longer represent a feasible distance as
$ KL(\pi ||p ) = \infty $ and
$ JSD(\pi || p) = \log(2) $, let alone proper gradient propagation.&lt;/p>
&lt;p>Another application might be interpolation between distributions, where we can find a smooth transition expressed in barycentric coordinates:&lt;/p>
&lt;div id="chart-742136985" class="chart">&lt;/div>
&lt;script>
(function() {
let a = setInterval( function() {
if ( typeof window.Plotly === 'undefined' ) {
return;
}
clearInterval( a );
Plotly.d3.json("./wasser_barycenteric.json", function(chart) {
Plotly.plot('chart-742136985', chart.data, chart.layout, {responsive: true});
});
}, 500 );
})();
&lt;/script>
&lt;p>Suppose we have two descrete distributions of size
$ n $ and a cost matrix
$ \mathbf{C} \in \mathbb{R}^{n \times n} $. Gaspard Monge&amp;rsquo;s optimal assignment problem looks for a mapping that associates to each point
$ x_i $ a single point
$ y_i $ or in other words it attempts to find a bijective function
$ \sigma $ in the set of permutations of
$ n $ elements to minimize:&lt;/p>
$$
\min_{ \sigma \in \mathrm{Perm}(n) } \frac{1}{n} \sum_{i=1}^{n} \mathbf{C}_{i, \sigma(i)} .
$$
&lt;p>This formulation of optimal assignment has some drawbacks: the problem itself is nonconvex, it may have several optimal solutions and sometimes a feasible solution does not exist. To overcome these inconveniences &lt;a href="https://en.wikipedia.org/wiki/Leonid_Kantorovich" target="_blank" rel="noopener">Kantorovich&lt;/a> proposed to relax this deterministic nature of assignment. Originally a source point
$ x_i $ can only be assigned to another point
$ y_{\sigma_i} $, but Kantorovich suggested instead that the mass at any point
$ x_i $ can be potentially dispatched across several locations or it can be splitted from a source towards several targets. This relaxation allows, in place of permutations
$ \sigma $, to use a transportation matrix
$ \mathbf{P} \in \mathbb{R}^{n \times m}_{+} $:&lt;/p>
$$
\begin{split}
\mu = \sum_{i=1}^{n} a_i \delta_{x_i} \; \nu = \sum_{j=1}^{m} b_j \delta_{y_j}. \\ \\
\mathbf{C} = [D(x_i, y_i)^p]_{ij} \\ \\
\mathbf{U}( \mathbf{a}, \mathbf{b} )= \{ \mathbf{P} \in \mathbb{R}^{n \times m}_{+} \; \| \; \mathbf{P} \mathbb{1}_m = \mathbf{a}, \mathbf{P}^{ \mathbf{T} } \mathbb{1}_n = \mathbf{b} \} \\ \\
\mathbf{L_{\mathbf{C}}}( \mathbf{a}, \mathbf{b} ) = \min_{ \mathbf{P} \in \mathbf{U}( \mathbf{a}, \mathbf{b})} \langle \mathbf{C}, \mathbf{P} \rangle
\end{split}
$$
&lt;p>where
$ \mu, \nu $ — discrete measures with weights
$ a_i, b_j $ at locations
$ x_i, y_j $;
$ \delta_x, \delta_y $ — Dirac functions;
$ \mathbf{a}, \mathbf{b} $ — marginal source and target distrubutions;
$ \mathbf{C} $ — a transporatation cost matrix or a matrix of pairwise distances;
$ \mathbf{P} $ — a transportation plan matrix we are looking for, with a constraint that its columns and rows sums should match marginals.&lt;br>
$ P_{i,j} $ describes the amount of mass flowing from location
$ i $ to location
$ j $.&lt;/p>
&lt;p>It looks like a linear program, so there must exist a dual which was formulated by Kantorovich (probably furnished him the Nobel Prize in economics):&lt;/p>
$$
\begin{split}
\mathbf{L}_{ \mathbf{C} } ( \mathbf{a} , \mathbf{b} ) = \max_{
\begin{split}
\alpha \in \mathbb{R}^n, \beta \in \mathbb{R}^m \\
\alpha_i + \beta_j \le \mathbf{C}_{i,j}
\end{split}
} \alpha^T \mathbf{a} + \beta^T \mathbf{b}
\end{split}
$$
&lt;p>Here we are looking for optimal dual variables
$ \alpha, \beta $ (Kantorovich potentials). We can write the Lagrangian of the primal problem:&lt;/p>
$$
\min_{ \mathbf{P} \ge 0 } \max_{ \alpha \in \mathbb{R}^n, \beta \in \mathbb{R}^m } \langle \mathbf{C}, \mathbf{P} \rangle + \langle \mathbf{a} - \mathbf{P} \mathbb{1}_m, \alpha \rangle
+ \langle \mathbf{b} - \mathbf{P}^{\mathrm{T}} \mathbb{1}_n, \beta \rangle.
$$
&lt;p>After exchanging the min and the max we obtain:&lt;/p>
$$
\max_{ \alpha \in \mathbb{R}^n, \beta \in \mathbb{R}^m } \langle \mathbf{a}, \alpha \rangle + \langle \mathbf{b}, \beta \rangle +
\min_{ \mathbf{P} \ge 0 } \langle \mathbf{C} - \alpha \mathbb{1}_m^{\mathrm{T}} - \mathbb{1}_n \beta^{\mathrm{T}}, \mathbf{P} \rangle.
$$
&lt;p>We can observe that for any
$ \mathbf{Q} $:&lt;/p>
$$
\min_{\mathbf{P} \ge 0} \langle \mathbf{Q}, \mathbf{P} \rangle =
\begin{cases}
0 &amp; \text{ if } \mathbf{Q} \ge 0, \\
-\infty &amp; \text{ otherwise }
\end{cases},
$$
&lt;p>so that the constraints definetely are
$ \mathbf{C} - \alpha \mathbb{1}_m^{\mathrm{T}} - \mathbb{1}_n \beta^{\mathrm{T}} \ge 0 $ or
$
\alpha_i + \beta_j \le \mathbf{C}_{i, j} $.&lt;/p>
&lt;p>Returning to the original problem, we can see that the set of matrices
$ \mathbf{U} ( \mathbf{a}, \mathbf{b}) $ is defined by
$ n+m $ equality constraints that form a convex polytope of feasible solutions with a cost vector
$ \mathbf{C} $ and the optimal solution
$ \mathbf{P}^{\star} $ located at a vertex:&lt;/p>
&lt;figure class="mongo_dark" >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt=""
src="https://aleksandr-lomakin.netlify.app/post/sinkhorn/ot_loss_dark_01.svg"
loading="lazy" data-zoomable width="250" />&lt;/div>
&lt;/div>&lt;/figure>
&lt;figure class="mongo_light" >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt=""
src="https://aleksandr-lomakin.netlify.app/post/sinkhorn/ot_loss_light_01.svg"
loading="lazy" data-zoomable width="250" />&lt;/div>
&lt;/div>&lt;/figure>
&lt;p>The problem could be solved with a network flow solver with
$ O(n^3log(n)) $ complexity&lt;sup id="fnref:2">&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref">2&lt;/a>&lt;/sup>. But unfortunately, this solution is not differentiable on discrete inputs, making it unsuitable for use in a deep learning pipeline. To complicate things more, the solution
$ \mathbf{ P } ^{\star} $ is not stable upon small changes in the input distrubutions and not always unique when the cost vector
$ \mathbf{C} $ is orthogonal to a face of the polytope:&lt;/p>
&lt;figure class="mongo_dark" >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt=""
src="https://aleksandr-lomakin.netlify.app/post/sinkhorn/ot_loss_dark_02.svg"
loading="lazy" data-zoomable width="250" />&lt;/div>
&lt;/div>&lt;/figure>
&lt;figure class="mongo_light" >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt=""
src="https://aleksandr-lomakin.netlify.app/post/sinkhorn/ot_loss_light_02.svg"
loading="lazy" data-zoomable width="250" />&lt;/div>
&lt;/div>&lt;/figure>
&lt;p>To address these inconveniences, sacrifices must be made and the particular one is giving up on the exact solution.&lt;/p>
&lt;p>The idea of the entropic regularization of optimal transport is to use the entropy of the transport matrix as a regularisation function to obtaine an approximate solution to the original problem&lt;sup id="fnref:3">&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref">3&lt;/a>&lt;/sup>.&lt;/p>
$$
\mathbf{L}_\mathbf{C}^{ \gamma } = \min_{ \mathbf{P} \in \mathbf{U}( \mathbf{a}, \mathbf{b} )} \langle \mathbf{P}, \mathbf{C} \rangle - \gamma \mathbf{H}(\mathbf{P}) ,
$$
&lt;p>where&lt;/p>
$$
\mathbf{H}(\mathbf{P}) = -\sum_{i,j}P_{i,j}( \log P_{i,j} - 1 )
$$
&lt;p>is the discrete entropy of the transport matrix,
$ \gamma $ — determines the extent to which entropy influences the solution.&lt;/p>
&lt;p>This augmented objective function has a solution which is no longer located on a vertex of the polytope. The entropy term pushes the original solution away from the boundary to the regularized entropic minimum. You can see the impact of increasing
$ \gamma $ on the cost landscape of the linear problem:&lt;/p>
&lt;figure class="mongo_dark" >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt=""
src="https://aleksandr-lomakin.netlify.app/post/sinkhorn/reg_dark.svg"
loading="lazy" data-zoomable width="700" />&lt;/div>
&lt;/div>&lt;/figure>
&lt;figure class="mongo_light" >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt=""
src="https://aleksandr-lomakin.netlify.app/post/sinkhorn/reg_light.svg"
loading="lazy" data-zoomable width="700" />&lt;/div>
&lt;/div>&lt;/figure>
&lt;p>Formally the unique solution converges to the optimal one with the maximum entropy:&lt;/p>
$$
\mathbf{P}_{\gamma} \xrightarrow{\gamma \rightarrow 0 } \mathop{\mathrm{argmin}}\limits_{\mathbf{P}} \{ -\mathbf{H}(\mathbf{P}) : \mathbf{P} \in \mathbf{U}(\mathbf{a}, \mathbf{b}), \langle \mathbf{P}, \mathbf{C} \rangle = \mathbf{L}_{\mathbf{C}}( \mathbf{a}, \mathbf{b} ) \}.
$$
&lt;p>In the edge cases, when
$ \gamma \rightarrow 0 $, it converges to the linear program solution:&lt;/p>
$$
\mathbf{P}_{\gamma} \xrightarrow{\gamma \rightarrow 0 } \mathbf{L}_{\mathbf{C}}( \mathbf{a}, \mathbf{b} ),
$$
&lt;p>and for a large regularization
$ \gamma \rightarrow \infty $, the solution converges to the joint probability between two independent random variables distributed according to marginals
$ \mathbf{a} $ and
$ \mathbf{b} $:&lt;/p>
$$
\mathbf{P}_{\gamma} \xrightarrow{\gamma \rightarrow \infty } \mathbf{a} \mathbf{b}^{\mathrm{T}}.
$$
&lt;p>A natural way to solve a constrained minimization problem is to make a Lagrangian:&lt;/p>
$$
\mathcal{L}(P, \alpha, \beta) = \sum_{i,j} P_{ij} C_{ij} + \gamma P_{i,j}( \log P_{i,j} - 1 ) + \alpha^{\mathrm{T}} ( \mathbf{P} \mathbb{1}_m - \mathbf{a} ) + \beta^{\mathrm{T}} ( \mathbf{P}^{\mathrm{T}} \mathbb{1}_n - \mathbf{b}).
$$
&lt;p>After having assigned derivatives over components
$ P_{i,j} $ to zero, we can express the solution for
$ \mathbf{P} $:&lt;/p>
$$
\begin{split}
\frac{ \partial{ \mathcal{L} } }{ \partial{ P_{i,j} } } = C_{i,j} + \gamma (\log P_{i,j} - 1) + \gamma P_{i,j} \times \frac{1}{P_{i,j}} + \alpha_i + \beta_j = 0. \\
\log P_{i,j} = -\frac{\alpha_i}{\gamma} - \frac{C_{i,j}}{\gamma} - \frac{\beta_j}{\gamma}. \\
P_{i,j} = \exp( -\frac{\alpha_i}{\gamma} ) \exp( -\frac{C_{i,j}}{\gamma} ) \exp( -\frac{ \beta_j }{\gamma} ) \\
\end{split}
$$
&lt;p>If we assume:&lt;/p>
$$
u_i = \exp( -\frac{\alpha_i}{\gamma} ), \; K_{i,j} = \exp( -\frac{C_{i,j}}{\gamma} ), \; v_j = \exp( -\frac{ \beta_j }{\gamma} )
$$
&lt;p>we can rewrite the expression in a vector form:&lt;/p>
$$
\mathbf{P} = \mathrm{diag}(\mathbf{u}) \mathbf{K} \mathrm{diag}(\mathbf{v}),
$$
&lt;p>
$ \mathbf{K} $ is called Gibbs kernel and
$ \mathbf{u}, \mathbf{v} $ are Sinkhorn scalings.&lt;/p>
&lt;p>Let&amp;rsquo;s use the normalization constraints
$ \mathbf{P} \mathbb{1}_m = \mathbf{a}, \mathbf{P}^{\mathrm{T}} \mathbb{1}_n = \mathbf{b} $:&lt;/p>
$$
\begin{split}
\mathbf{P} \mathbb{1}_m = \mathrm{diag}(\mathbf{u}) \mathbf{K} \mathrm{diag}(\mathbf{v}) \mathbb{1}_m = \mathrm{diag}(\mathbf{u}) \mathbf{K} \mathbf{v} = \mathbf{a} \\
\mathbf{P}^{\mathrm{T}} \mathbb{1}_n = \mathrm{diag}(\mathbf{v}) \mathbf{K}^{\mathrm{T}} \mathrm{diag}(\mathbf{u}) \mathbb{1}_n = \mathrm{diag}(\mathbf{v}) \mathbf{K}^{\mathrm{T}} \mathbf{u} = \mathbf{b}
\end{split}
$$
&lt;p>or simpler:&lt;/p>
$$
\begin{split}
\mathbf{u} \odot \mathbf{K} \mathbf{v} = \mathbf{a} \\
\mathbf{v} \odot \mathbf{K}^{\mathrm{T}} \mathbf{u} = \mathbf{b}
\end{split}
$$
&lt;p>where
$ \odot $ is Hadamard product. Solving this for
$ \mathbf{u} $ and
$ \mathbf{v} $ gives us an iterative solution know as famous Sinkhorn algorithm&lt;sup id="fnref:4">&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref">4&lt;/a>&lt;/sup> with
$ O(nm) $ complexity&lt;sup id="fnref:5">&lt;a href="#fn:5" class="footnote-ref" role="doc-noteref">5&lt;/a>&lt;/sup>:&lt;/p>
$$
\begin{split}
\mathbf{u} = \mathbf{a} \oslash (\mathbf{K} \mathbf{v}) \\
\mathbf{v} = \mathbf{b} \oslash (\mathbf{K}^{\mathrm{T}} \mathbf{u}) \\
\end{split}
$$
&lt;p>where
$ \oslash $ stands for an element-wise division.&lt;/p>
&lt;p>We can see the impact of the regularzation parameter
$ \gamma $ on the solution, wich behaves like a temperature:&lt;/p>
&lt;div id="chart-817295436" class="chart">&lt;/div>
&lt;script>
(function() {
let a = setInterval( function() {
if ( typeof window.Plotly === 'undefined' ) {
return;
}
clearInterval( a );
Plotly.d3.json("./optimal_transport.json", function(chart) {
Plotly.plot('chart-817295436', chart.data, chart.layout, {responsive: true});
});
}, 500 );
})();
&lt;/script>
&lt;p>If we let the temperature approach zero, we approximate the exact solution. Conversely, if we let
$ \gamma $ go to infinity, the solution is just an outer product of the two marginal distributions.&lt;br>
So Sinkhorn procedure involves a sequence of vector matrix multiplication that is perfectly differentiable. This allows it to be used within a neural network, taking advantage of GPU acceleration and PyTorch auto-differentiation.&lt;/p>
&lt;p>And this is a suitable place to return to Stereo Transformer paper.&lt;br>
The achitecture of the network consists of a feature extractor backbone, a bunch of self- and cross-attention Transformer blocks and finally, a regression head with the Context Adjustment Layer:
&lt;figure class="mongo_dark" id="figure-image-credit-li-et-al-revisiting-stereo-depth-estimation-from-a-sequence-to-sequence-perspective-with-transformershttpsarxivorgabs201102910">
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Image credit: [Li et al. Revisiting Stereo Depth Estimation From a Sequence-to-Sequence Perspective with Transformers](https://arxiv.org/abs/2011.02910)" srcset="
/post/sinkhorn/sttr_light_hu1cbdc410821621f8e6091b688dfba288_73309_b81ea60490877a4fde077927e89ed962.webp 400w,
/post/sinkhorn/sttr_light_hu1cbdc410821621f8e6091b688dfba288_73309_c06635842c6f485ba99b6c552e7d42e8.webp 760w,
/post/sinkhorn/sttr_light_hu1cbdc410821621f8e6091b688dfba288_73309_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://aleksandr-lomakin.netlify.app/post/sinkhorn/sttr_light_hu1cbdc410821621f8e6091b688dfba288_73309_b81ea60490877a4fde077927e89ed962.webp"
width="760"
height="203"
loading="lazy" data-zoomable class=" img-light" />&lt;/div>
&lt;/div>&lt;figcaption>
Image credit: &lt;a href="https://arxiv.org/abs/2011.02910" target="_blank" rel="noopener">Li et al. Revisiting Stereo Depth Estimation From a Sequence-to-Sequence Perspective with Transformers&lt;/a>
&lt;/figcaption>&lt;/figure>
&lt;/p>
&lt;figure class="mongo_light" id="figure-image-credit-li-et-al-revisiting-stereo-depth-estimation-from-a-sequence-to-sequence-perspective-with-transformershttpsarxivorgabs201102910">
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Image credit: [Li et al. Revisiting Stereo Depth Estimation From a Sequence-to-Sequence Perspective with Transformers](https://arxiv.org/abs/2011.02910)" srcset="
/post/sinkhorn/sttr_light_01_hub6c06d7096a2701146aa548652800e8a_74686_23014fa507db25957fb12ddb61a8a74c.webp 400w,
/post/sinkhorn/sttr_light_01_hub6c06d7096a2701146aa548652800e8a_74686_87a809dd4b38adfcd04efa504301fb58.webp 760w,
/post/sinkhorn/sttr_light_01_hub6c06d7096a2701146aa548652800e8a_74686_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://aleksandr-lomakin.netlify.app/post/sinkhorn/sttr_light_01_hub6c06d7096a2701146aa548652800e8a_74686_23014fa507db25957fb12ddb61a8a74c.webp"
width="760"
height="203"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;figcaption>
Image credit: &lt;a href="https://arxiv.org/abs/2011.02910" target="_blank" rel="noopener">Li et al. Revisiting Stereo Depth Estimation From a Sequence-to-Sequence Perspective with Transformers&lt;/a>
&lt;/figcaption>&lt;/figure>
&lt;!--
&lt;figure id="figure-image-credit-li-et-al-revisiting-stereo-depth-estimation-from-a-sequence-to-sequence-perspective-with-transformershttpsarxivorgabs201102910">
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Image credit: [Li et al. Revisiting Stereo Depth Estimation From a Sequence-to-Sequence Perspective with Transformers](https://arxiv.org/abs/2011.02910)" srcset="
/post/sinkhorn/sttr_light_hu1cbdc410821621f8e6091b688dfba288_73309_b81ea60490877a4fde077927e89ed962.webp 400w,
/post/sinkhorn/sttr_light_hu1cbdc410821621f8e6091b688dfba288_73309_c06635842c6f485ba99b6c552e7d42e8.webp 760w,
/post/sinkhorn/sttr_light_hu1cbdc410821621f8e6091b688dfba288_73309_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://aleksandr-lomakin.netlify.app/post/sinkhorn/sttr_light_hu1cbdc410821621f8e6091b688dfba288_73309_b81ea60490877a4fde077927e89ed962.webp"
width="800"
height="203"
loading="lazy" data-zoomable class=" img-light" />&lt;/div>
&lt;/div>&lt;figcaption>
Image credit: &lt;a href="https://arxiv.org/abs/2011.02910" target="_blank" rel="noopener">Li et al. Revisiting Stereo Depth Estimation From a Sequence-to-Sequence Perspective with Transformers&lt;/a>
&lt;/figcaption>&lt;/figure>
-->
&lt;p>The optimal transport finds its place in the last transformer&amp;rsquo;s cross-attention block and it is replacing the Softmax operator usually used in the Transformer achitecture.&lt;/p>
&lt;p>The optimal transport problem is formulated as follows:&lt;/p>
&lt;ul>
&lt;li>The cost matrix
$ \mathbf{C} $ is set to the negative cross-attention. Softmax is not used as optimal transport normalizes the attention values.&lt;/li>
&lt;li>The two marginal distributions
$ \mathbf{a} $ and
$ \mathbf{b} $ are uniform, which imposes a soft uniquness constraint and mitigates ambiguity.&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>If the two marginal distribution have equal length and
$ \mathbf{a} = \mathbf{b} = \mathbb{1}_n / n $, then the optimal assignment problem becomes the optimal matching problem and there exists an optimal solution
$ \mathbf{P}_{\sigma^{\star} } $, which is a permutation matrix associated to an optimal permutation
$ \sigma^{\star} \in \mathrm{Perm}(n) $&lt;sup id="fnref1:3">&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref">3&lt;/a>&lt;/sup>.&lt;/p>
&lt;/blockquote>
&lt;p>Additional boilerplate is done to add a learnable dustbin
$ \phi $ responsible for unmached occluded pixels.
The intuition behind the optimal transport solution
$ \mathbf{P} $ is that entries
$ P_{i,j} $ could be interpreted as pair-wise pixel matching probabilities.&lt;/p>
&lt;p>Let&amp;rsquo;s examine the code and analyse how it was &lt;a href="https://github.com/mli0603/stereo-transformer/blob/44703b01d59c8accff1d396ec842c3d1b9a8fb9a/module/regression_head.py#L143" target="_blank" rel="noopener">implemented&lt;/a>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">_optimal_transport&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">attn&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">iters&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> Perform Differentiable Optimal Transport in Log-space for stability
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> Adapted from SuperGlue (https://github.com/magicleap/SuperGluePretrainedNetwork)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> :param attn: raw attention weight, [N,H,W,W]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> :param iters: number of iterations to run sinkhorn
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> :return: updated attention weight, [N,H,W+1,W+1]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">bs&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">h&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">w&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">attn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># set marginal to be uniform distribution&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">marginal&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cat&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ones&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="n">w&lt;/span>&lt;span class="p">]),&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tensor&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="n">w&lt;/span>&lt;span class="p">])&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">float&lt;/span>&lt;span class="p">()])&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">w&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">log_mu&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">marginal&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">log&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">to&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">attn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">device&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">expand&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bs&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">h&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">w&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">log_nu&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">marginal&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">log&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">to&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">attn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">device&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">expand&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bs&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">h&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">w&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># add dustbins&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">similarity_matrix&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cat&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="n">attn&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">phi&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">expand&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bs&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">h&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">w&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">to&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">attn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">device&lt;/span>&lt;span class="p">)],&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">similarity_matrix&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cat&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="n">similarity_matrix&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">phi&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">expand&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bs&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">h&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">w&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">to&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">attn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">device&lt;/span>&lt;span class="p">)],&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># sinkhorn&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">attn_ot&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_sinkhorn&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">similarity_matrix&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">log_mu&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">log_nu&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">iters&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># convert back from log space, recover probabilities by normalization 2W&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">attn_ot&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">attn_ot&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">log&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tensor&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="mf">2.0&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">w&lt;/span>&lt;span class="p">])&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">to&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">attn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">device&lt;/span>&lt;span class="p">)))&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exp&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">attn_ot&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>The iterative process is done in logarithmic space for better numerical stability.&lt;/li>
&lt;li>The two marginals
$ \nu $ and
$ \mu $ are initialized as log of the uniform distribution.&lt;/li>
&lt;li>The shape of the attention tensor is &lt;code>[bs, n, h, w, w]&lt;/code>, the shape of marginals is &lt;code>[bs, h, w + 1]&lt;/code>, the last value here is for the dustbin
$ \phi $.&lt;/li>
&lt;li>All the values in the range &lt;code>[1:w]&lt;/code> are initialized to &lt;code>1/(2*w)&lt;/code> and the last value is &lt;code>0.5&lt;/code>, so the whole distribution sums up to &lt;code>1&lt;/code>. Increased weight on the dustbin here is for balancing out its influence with the disparity bins.&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># set marginal to be uniform distribution&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">marginal&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cat&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ones&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="n">w&lt;/span>&lt;span class="p">]),&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tensor&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="n">w&lt;/span>&lt;span class="p">])&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">float&lt;/span>&lt;span class="p">()])&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">w&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">log_mu&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">marginal&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">log&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">to&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">attn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">device&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">expand&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bs&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">h&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">w&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">log_nu&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">marginal&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">log&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">to&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">attn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">device&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">expand&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bs&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">h&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">w&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then a &lt;code>similarity_matrix&lt;/code> (optimal transport matrix) is constructed by adding the learnable dustbin &lt;code>phi&lt;/code> to the last row and column of the attention tensor:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># add dustbins&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">similarity_matrix&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cat&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="n">attn&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">phi&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">expand&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bs&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">h&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">w&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">to&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">attn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">device&lt;/span>&lt;span class="p">)],&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">similarity_matrix&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cat&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="n">similarity_matrix&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">phi&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">expand&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bs&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">h&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">w&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">to&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">attn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">device&lt;/span>&lt;span class="p">)],&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>phi&lt;/code> is a learnable scalar parameter previously defined in the &lt;a href="https://github.com/mli0603/stereo-transformer/blob/44703b01d59c8accff1d396ec842c3d1b9a8fb9a/module/regression_head.py#L22" target="_blank" rel="noopener">constructor&lt;/a>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">phi&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">nn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Parameter&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tensor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">0.0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">requires_grad&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="c1"># dustbin cost&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The last step is to run a few Sinkhorn interations and recover the transport matrix by exponentiation.
Number of iterations is set to &lt;a href="https://github.com/mli0603/stereo-transformer/blob/44703b01d59c8accff1d396ec842c3d1b9a8fb9a/module/regression_head.py#L244" target="_blank" rel="noopener">10&lt;/a>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># sinkhorn&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">attn_ot&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_sinkhorn&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">similarity_matrix&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">log_mu&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">log_nu&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">iters&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># convert back from log space, recover probabilities by normalization 2W&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">attn_ot&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">attn_ot&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">log&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tensor&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="mf">2.0&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">w&lt;/span>&lt;span class="p">])&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">to&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">attn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">device&lt;/span>&lt;span class="p">)))&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exp&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Let&amp;rsquo;s look into &lt;code>_sinkhorn&lt;/code> method:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">_sinkhorn&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">attn&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">log_mu&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">log_nu&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">iters&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> Sinkhorn Normalization in Log-space as matrix scaling problem.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> Regularization strength is set to 1 to avoid manual checking for numerical issues
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> Adapted from SuperGlue (https://github.com/magicleap/SuperGluePretrainedNetwork)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> :param attn: input attention weight, [N,H,W+1,W+1]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> :param log_mu: marginal distribution of left image, [N,H,W+1]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> :param log_nu: marginal distribution of right image, [N,H,W+1]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> :param iters: number of iterations
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> :return: updated attention weight
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">u&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">v&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">zeros_like&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">log_mu&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">zeros_like&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">log_nu&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">idx&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">iters&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># scale v first then u to ensure row sum is 1, col sum slightly larger than 1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">v&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">log_nu&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">logsumexp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">attn&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">u&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">unsqueeze&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">dim&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">u&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">log_mu&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">logsumexp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">attn&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">v&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">unsqueeze&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">dim&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">attn&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">u&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">unsqueeze&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">v&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">unsqueeze&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Firstly vectors
$ \mathbf{u} $ and
$ \mathbf{v} $ are zero initialized. Then the cost matrix
$ \mathbf{C} $ is set to the negative attention &lt;code>attn&lt;/code>, which is intuitively understandable: the most attended pixels have the least transportation cost. The regularization parameter
$ \gamma = 1 $.&lt;/p>
&lt;p>With these assumptions in mind we can rewrite the kernel
$ \mathbf{K} $ as:&lt;/p>
$$
\mathbf{K} = \exp( -\frac{\mathbf{C}}{ \gamma} ) = \exp( \mathrm{attn} ).
$$
&lt;p>Plugging this kernel into the Sinkhorn update and taking log of the equality, we achieve the original expression:&lt;/p>
$$
\begin{align}
\log(\mathbf{v}) &amp;= \log(\nu) - \log(\sum_i \mathbf{K}_{i,j} u_i ) \\ &amp;= \log(\nu) - \log( \sum_i \exp( \mathrm{attn}_{i,j} + \log( u_i ) ) ), \\
\log(\mathbf{u}) &amp;= \log(\mu) - \log(\sum_j \mathbf{K}_{i,j} v_j ) \\ &amp;= \log(\mu) - \log( \sum_j \exp( \mathrm{attn}_{i,j} + \log( v_j ) ) ).
\end{align}
$$
&lt;p>This conсludes the matter. It is worth mentioning that in the ablation studies section, it was demonstrated that the soft uniqueness constraint imposed by optimal transport improved all the metrics: end-point-error (EPE), 3px error and occlusion IOU.&lt;/p>
&lt;p>Finally, I would like to express my gratitude to the authors for their outstanding work and for providing a clear example of how Optimal Transport can effectively complement existing deep learning techniques.&lt;/p>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>&lt;a href="https://arxiv.org/abs/2011.02910" target="_blank" rel="noopener">Li et al. Revisiting Stereo Depth Estimation From a Sequence-to-Sequence Perspective with Transformers&lt;/a>&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:2">
&lt;p>&lt;a href="https://www.semanticscholar.org/paper/Fast-and-robust-Earth-Mover%27s-Distances-Pele-Werman/8ab6d616f812a3108ae85b4ab130b62b650c5677" target="_blank" rel="noopener">Pele, Werman. Fast and robust earth mover&amp;rsquo;s distances&lt;/a>&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:3">
&lt;p>&lt;a href="https://arxiv.org/abs/1803.00567" target="_blank" rel="noopener">Peyré, Cuturi. Computational Optimal Transport&lt;/a>&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&amp;#160;&lt;a href="#fnref1:3" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:4">
&lt;p>&lt;a href="https://arxiv.org/abs/1306.0895" target="_blank" rel="noopener">M. Cuturi. Sinkhorn Distances: Lightspeed Computation of Optimal Transport&lt;/a>&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:5">
&lt;p>&lt;a href="https://www.semanticscholar.org/paper/The-Sinkhorn-Knopp-Algorithm%3A-Convergence-and-Knight/4db5c0119d99b089c537f3c70024d1436528dbd2" target="_blank" rel="noopener">P. Knight. The Sinkhorn-Knopp Algorithm: Convergence and Applications&lt;/a>&amp;#160;&lt;a href="#fnref:5" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item><item><title>Homography from the Correspondences of Lines</title><link>https://aleksandr-lomakin.netlify.app/post/h_from_lines/</link><pubDate>Thu, 08 Feb 2024 00:00:00 +0000</pubDate><guid>https://aleksandr-lomakin.netlify.app/post/h_from_lines/</guid><description>
&lt;figure class="mongo_dark" >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt=""
src="https://aleksandr-lomakin.netlify.app/post/h_from_lines/h_from_lines_dark.svg"
loading="lazy" data-zoomable width="700" />&lt;/div>
&lt;/div>&lt;/figure>
&lt;figure class="mongo_light" >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt=""
src="https://aleksandr-lomakin.netlify.app/post/h_from_lines/h_from_lines_light.svg"
loading="lazy" data-zoomable width="700" />&lt;/div>
&lt;/div>&lt;/figure>
&lt;p>Recently I stumbled upon a task where I had to find a mapping between a camera and a target plane, but with a little twist. I could define line equations in the plane, and once I had captured the image and found the corresponding lines, the problem boiled down to calculating the homography based on line correspondences. Following the famous solution from the Multiple View Geometry book &lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>, I arrived at a simple result.&lt;/p>
&lt;p>Let&amp;rsquo;s assume we have a line in the target plane
$ L_i $ given by&lt;/p>
$$
\begin{equation}
L_i = ( a_i^p, b_i^p, c_i^p )^T :\ L_i^T \mathbf{X}^p = 0, \qquad \qquad (1)
\label{ref:eq1}
\end{equation}
$$
&lt;p>where
$ \mathbf{X}^p =
\begin{pmatrix}
x^p \\ y^p \\ 1
\end{pmatrix} $
— point in the target plane. It&amp;rsquo;s projection in the image we denote as
$ l_i $:&lt;/p>
$$
l_i = (a_i^i, b_i^i, c_i^i)^T :\ l_i^T \mathbf{ X}^i = 0,
$$
&lt;p>
$ \mathbf{X}^i =
\begin{pmatrix}
x^i \\ y^i \\ 1
\end{pmatrix} $ — being a point in the image.&lt;br>
A homography
$ \mathbf{H} $ takes a point in the projector plane
$ \mathbf{X}^p $ and sends it to the image plane:
$$
\mathbf{X}^i = \mathbf{H} \mathbf{X}^p.
$$
&lt;/p>
&lt;p>So for any point in the laser plane satisfying
$ (1) $ we can write:&lt;/p>
$$
l_i^T \mathbf{H} \mathbf{X}^p = 0.
$$
&lt;p>Line
$ L_i $ may be represented by any two points
$ \mathbf{X}_0^p $ and
$ \mathbf{X}_1^p $, so we have two equations for
$ L_i \rightarrow l_i $ correspondence:&lt;/p>
$$
\begin{equation}
\begin{split}
l_i^T \mathbf{H} \mathbf{X}_0^p &amp;= 0, \qquad \qquad (2) \\
l_i^T \mathbf{H} \mathbf{X}_1^p &amp;= 0.
\end{split}
\label{ref:eq2}
\end{equation}
$$
&lt;p>If the
$ j $-th row of the matrix H is denoted by
$ \mathbf{h}^{iT} $, then we may write:&lt;/p>
$$
\mathbf{H} \mathbf{X}^p = \begin{pmatrix}
\mathbf{h}^{1T} \mathbf{X}^p \\
\mathbf{h}^{2T} \mathbf{X}^p \\
\mathbf{h}^{3T} \mathbf{X}^p
\end{pmatrix}
$$
&lt;p>We can rewrite
$ (2) $ in terms of
$ \mathbf{h}^{iT} $:&lt;/p>
$$
\begin{equation}
\begin{split}
a_i^i \mathbf{h}^{1T} \mathbf{X}_0^p + b_i^i \mathbf{h}^{2T} \mathbf{X}_0^p + c_i^i \mathbf{h}^{3T} \mathbf{X}_0^p &amp;= 0, \qquad (3) \\
a_i^i \mathbf{h}^{1T} \mathbf{X}_1^p + b_i^i \mathbf{h}^{2T} \mathbf{X}_1^p + c_i^i \mathbf{h}^{3T} \mathbf{X}_1^p &amp;= 0.
\end{split}
\label{ref:eq3}
\end{equation}
$$
&lt;p>We can take any two points on
$ L_i $, but for the simplicity we may choose these ones:&lt;/p>
$$
\begin{equation}
\begin{split}
\mathbf{X}_0^p =
\begin{pmatrix}
-\dfrac{c_i^p}{a_i^p} \\
0\\
1
\end{pmatrix}, \quad
\mathbf{X}_1^p =
\begin{pmatrix}
0 \\
-\dfrac{c_i^p}{b_i^p} \\
1
\end{pmatrix}.
\end{split}
\qquad \qquad (4)
\label{ref:eq4}
\end{equation}
$$
&lt;p>Plugging
$ (4) $ into
$ (3) $ and having components of
$ \mathbf{H} =
\begin{pmatrix}
h_{00} &amp; h_{01} &amp; h_{02} \\
h_{10} &amp; h_{11} &amp; h_{12} \\
h_{20} &amp; h_{21} &amp; h_{22}
\end{pmatrix} $ we are obtaining:&lt;/p>
$$
\begin{equation}
\begin{split}
a_i^i ( -\dfrac{c_i^p}{a_i^p} h_{00} + h_{02} ) +
b_i^i ( -\dfrac{c_i^p}{a_i^p} h_{10} + h_{12} ) +
c_i^i ( -\dfrac{c_i^p}{a_i^p} h_{20} + h_{22} ) &amp;= 0, \\
a_i^i ( -\dfrac{c_i^p}{b_i^p} h_{01} + h_{02} ) +
b_i^i ( -\dfrac{c_i^p}{b_i^p} h_{11} + h_{12} ) +
c_i^i ( -\dfrac{c_i^p}{b_i^p} h_{21} + h_{22} ) &amp;= 0.
\end{split}
\end{equation}
$$
&lt;p>After collecting terms around
$ h $ we can write:&lt;/p>
$$
\begin{equation}
\begin{split}
\begin{pmatrix}
-a_i^i \dfrac{c_i^p}{a_i^p} &amp; 0 &amp; a_i^i &amp; -b_i^i \dfrac{c_i^p}{a_i^p} &amp; 0 &amp; b_i^i &amp; -c_i^i \dfrac{c_i^p}{a_i^p} &amp; 0 &amp; c_i^i \\
0 &amp; -a_i^i \dfrac{c_i^p}{b_i^p} &amp; a_i^i &amp; 0 &amp; -b_i^i \dfrac{c_i^p}{b_i^p} &amp; b_i^i &amp; 0 &amp; -c_i^i \dfrac{c_i^p}{b_i^p} &amp; c_i^i
\end{pmatrix}
\times \\ \times
\begin{pmatrix}
h_{00} &amp; h_{01} &amp; h_{02} &amp; h_{10} &amp; h_{11} &amp; h_{12} &amp; h_{20} &amp; h_{21} &amp; h_{22}
\end{pmatrix}^T
= 0
\end{split}
\end{equation}
$$
&lt;p>or simply:&lt;/p>
$$
\begin{equation}
\begin{split}
\mathbf{A}_i \mathbf{h} = 0.
\end{split}
\end{equation}
$$
&lt;p>Each line correspondence gives two constraints on
$ \mathbf{H} $. Given a set of such line correspondences, we obtain a set of equations
$ \mathbf{A} \mathbf{h} = 0 $. To solve this, one might use SVD of
$ \mathbf{A} $ and the unit singular vector corresponding to the smallest singular value is the solution
$ \mathbf{h} $. Note, that lines shouldn&amp;rsquo;t be all mutually collinear, otherwise we would have an underdetermined system.&lt;/p>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>Richard Hartley, Andrew Zisserman. Multiple View Geometry in Computer Vision. 2003.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item><item><title>LoRa and Projection to a Matrix Subspace</title><link>https://aleksandr-lomakin.netlify.app/post/lora/</link><pubDate>Fri, 05 Jan 2024 00:00:00 +0000</pubDate><guid>https://aleksandr-lomakin.netlify.app/post/lora/</guid><description>
&lt;figure class="mongo_dark" >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt=""
src="https://aleksandr-lomakin.netlify.app/post/lora/lora_dark.svg"
loading="lazy" data-zoomable width="500" />&lt;/div>
&lt;/div>&lt;/figure>
&lt;figure class="mongo_light" >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt=""
src="https://aleksandr-lomakin.netlify.app/post/lora/lora_light.svg"
loading="lazy" data-zoomable width="500" />&lt;/div>
&lt;/div>&lt;/figure>
&lt;p>&lt;a href="https://arxiv.org/abs/2106.09685" target="_blank" rel="noopener">&lt;strong>L&lt;/strong>ow-&lt;strong>R&lt;/strong>ank &lt;strong>A&lt;/strong>daptation technique&lt;/a> was introduced to adapt large language models to a specific downstream task while keeping the original model intact and, by doing that, dramatically reducing the number of trainbale parameters. No only it lowers the hardware requirments to implement a task-specific adaptation but also it adds no inference latency when deployed.&lt;/p>
&lt;p>Based on the assumption that pretrained language models have a &lt;strong>low intrinsic dimension&lt;/strong>, authors constrain the update of a pre-trained weight matrix
$ W_q \in \mathbb{R}^{d \times k } $
with a low-rank decomposition:
$$ h = W_q x + \Delta W_q x = W_q x + B A x, $$
where
$ B \in \mathbb{R}^{d \times r}, A \in \mathbb{R}^{r \times k}$ , and the adapted rank
$ r \ll min\{ d, k \} $.
In the paper they applied LoRa only to the attention weights of the Transformer architecture. This is why we see in the adaptation here a Transformer&amp;rsquo;s query matrix
$W_q$.&lt;/p>
&lt;p>To gain a deeper understanding of the relationship between the increment
$ \Delta W $ and the original
$ W $ matrices, it seems reasonable to project
$W$, onto a subspace of
$ \Delta W $ and to compute the Frobenius norm
$ \| U^T W_q V^T \|_F $, where
$ U $ and
$ V $ are the left and the right singular-vector matrices of
$ \Delta W $. Let&amp;rsquo;s see the reason behind this.&lt;/p>
&lt;p>Suppose we have a matrix
$ A $ with linearly independent comlumns. Then the projection matrix onto subspace of
$ A $ would be:&lt;/p>
$$
P = A(A^T A)^{-1}A^T.
$$
&lt;p>In our case, if we want to project on the subspace of
$ \Delta W_q $, we can express the projection matrix as (bearing in mind that SVD of
$ \Delta W_q $ is
$ U \Sigma V^T $):
$$
\begin{split}
P = \Delta W_q ( \Delta W_q^T \Delta W_q )^{-1} \Delta W_q^T = \\
U \Sigma V^T ( (U \Sigma V^T)^T U \Sigma V^T )^{-1} (U \Sigma V^T)^T = \\
U \Sigma V^T ( V \Sigma U^T U \Sigma V^T )^{-1} V \Sigma U^T = \\
U \Sigma V^T ( V \Sigma^2 V^T )^{-1} V \Sigma U^T = \\
U \Sigma V^T V^{-T} \Sigma^{-2} V^{-1} V \Sigma U^T = \\
U \Sigma \Sigma^{-2} \Sigma U^T = U U^T.
\end{split}
$$
&lt;/p>
&lt;p>And finally, the projection itself of matrix
$ W_q $ is
$ P W_q = U U^T W_q $ or
$ U U^T W_q V^T V $, as matrix
$ V $ is unitary,
$ V^TV = I $.&lt;br>
As Frobenius norm is invariant under unitary operations
$ U $ and
$ V $ (follows from the cyclic nature of the trace), we can state that
$ \| U U^T W_q V^T V \|_F = \| U^T W_q V^T \|_F $. From where comes the &lt;em>Feature amplificaiton factor&lt;/em> mentioned in the paper:&lt;/p>
&lt;p>
$$
\frac{ \left \| \Delta W_q \right \|_F }{ \left \| U^T W_q V^T \right \|_F }
$$
This factor demonstrates the interaction between subspaces and helps to understand what the adaptation is doing. For instance, experimental evaluation revealed that the matrix
$ \Delta W $ amplifies singular directions that are not emphasized in the original matrix
$W$ and the amplification factor is quite significant. It can be deduced from this that&lt;/p>
&lt;blockquote>
&lt;p>the low-rank adaptation matrix potentially amplifies the important features for specific downstream tasks that were learned but not emphasized in the general pre-training model &lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>.&lt;/p>
&lt;/blockquote>
&lt;p>Another tool that can shed light on the mechanics behind the adaptation is the measurement of similarity between subspaces with different adaptation ranks
$ r $. This quantity can be calculated by using a normalized subspace similarity based on the &lt;a href="https://www.researchgate.net/publication/221346037_Grassmann_Discriminant_Analysis_a_Unifying_View_on_Subspace-Based_Learning" target="_blank" rel="noopener">&lt;strong>Grassmann distance&lt;/strong>&lt;/a>.&lt;/p>
&lt;figure class="mongo_dark" >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt=""
src="https://aleksandr-lomakin.netlify.app/post/lora/grassman_dark.svg"
loading="lazy" data-zoomable width="600" />&lt;/div>
&lt;/div>&lt;/figure>
&lt;figure class="mongo_light" >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt=""
src="https://aleksandr-lomakin.netlify.app/post/lora/grassman_light.svg"
loading="lazy" data-zoomable width="600" />&lt;/div>
&lt;/div>&lt;/figure>
&lt;p>Suppose we have two adaptation matrices
$ A_{r=8} $ and
$ A_{r=64} $ with different ranks. Then we compute SVD for each of them and obtain the right singular matrices
$ U_{r=8} $ and
$ U_{r=64} $. The proposed in the paper &lt;em>similarity metric&lt;/em>
$ \phi $ helps to understand how much of the subspace spanned by the top
$ i $ singular vectors in
$ U_{r=8} $ is contained in the subspace spanned by top
$ j $ singular vectors of
$ U_{r=64} $:&lt;/p>
$$
\phi(A_{r=8}, A_{r=64}, i, j) = \frac{ \| U_{A_{r=8}}^{iT} U_{A_{r=64}}^{j} \|_F^2 }{ min(i,j) },
$$
&lt;p>where
$ U_{A_{r=8}}^i $ represents the columns of
$ U_{A_{r=8}} $ corresponding to the top
$ i $ singular vectors. This similarity metric resembles very much the well-known Projection metric which measures the distance between subspaces.&lt;/p>
&lt;p>According to the definition, the Grassmann manifold
$ \mathcal{G}(m,D) $ is a set of
$ m $-dimensional linear subspaces of the Euclidean space
$ \mathbb{R}^D $. Let&amp;rsquo;s take any two elements of the manifold
$ \mathcal{G}(m,D) $ — the orthonormal matrices
$ A $ and
$ B $ of size
$ (D \times m) $. In the same time
$ span(A) $ and
$ span(B) $ represent two subspaces in
$ \mathbb{R}^D $. The distance between two subspaces
$ span(A) $ and
$ span(B) $ can be measured using the pricipal angles
$ [\theta_1, \dots, \theta_m] $ as the usual dot-product of vectors. In the Grassmann manifold however, these two subspaces are represented simply by two points and the Riemannian distance between them is simply
$ d(A, B) = \| \theta \|_2 $.&lt;br>
The set of principal angles
$ 0 \le \theta_1 \le \dots \le \theta_m \le \pi/2 $ between two subspaces
$ span(A) $ and
$ span(B) $ are defined by
$$
cos \theta_k = \max_{u_k \in span(A)} \max_{v_k \in span(B)} u_k^Tv_k.
$$
&lt;/p>
&lt;p>where
$ u_k $ spans
$ A $,
$ v_k $ spans
$ B $ and
$$
\begin{split}
u_k^T u_k = 1, v_k^T V_k = 1, \\
u_k^T u_i = 0, v_k^T v_i = 0, ( i = 1, \dots, k-1 ).
\end{split}
$$
&lt;/p>
&lt;blockquote>
&lt;p>In other words, the first principal angle
$ \theta_1 $ is the smallest angle between all pairs of unit vectors in the first and the second subspaces &lt;sup id="fnref:2">&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref">2&lt;/a>&lt;/sup>.&lt;/p>
&lt;/blockquote>
&lt;p>To compute these principal angles we need to find the SVD of
$ A^TB $:&lt;/p>
$$
A^TB = U diag(\sigma_1, \dots, \sigma_m) V^T = U(cos\Theta)V^T,
$$
&lt;p>where
$ U = [u_1, \dots, u_m], V = [v_1, \dots, v_m] $ and
$ cos\Theta $ is the diagonal matrix
$ cos \Theta = diag(cos\theta_1, \dots, cos\theta_m ) $.&lt;br>
Another popular expression of a distance betwen subspaces is the Projection Metric (2-norm of the sine of principal angles):
$$
d_P(A,B) = \left ( \sum_{i=1}^m sin^2 \theta_i \right )^{1/2} = \left ( m - \sum_{i=1}^m cos^2 \theta_i \right )^{1/2} = \left ( m - \sum_{i=1}^m \sigma_i^2 \right )^{1/2}.
$$
&lt;/p>
&lt;p>Let&amp;rsquo;s return to the similarity metric
$ \phi $. If the singular values of the product
$ U_{A_{r=8}}^{iT} U_{A_{r=64}}^j $ are
$ \sigma_1, \sigma_2, \dots, \sigma_p $, where
$ p = min(i,j) $, then the similarity is defined as:&lt;/p>
&lt;p>
$$
\begin{split}
\phi(A_{r=8}, A_{r=64}, i, j) = \frac{ \| U_{A_{r=8}}^{iT} U_{A_{r=64}}^{j} \|_F^2 }{ min(i,j) } = \\
= \frac{ \sum_{i=1}^{p} \sigma_i^2 }{p} = \frac{1}{p} \left ( 1 - d_P( U_{A_{r=8}}^{iT}, U_{A_{r=64}}^{j} ) \right ),
\end{split}
$$
which is exactly a reverse of the Projection Metric defined earlier.&lt;/p>
&lt;p>Using this similarity metric and having carried out multiple experiments the authors concluded&lt;/p>
&lt;blockquote>
&lt;p>that the top singular-vector directions of
$ A_{r=8} $ and
$ A_{r=64} $ are the most useful, while other directions potentially contain mostly random noises accumulated during training. Hence, the adaptation matrix can indeed have a very low rank &lt;sup id="fnref1:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>.&lt;/p>
&lt;/blockquote>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>Hu et al. LoRA: Low-Rank Adaptation of Large Language Models. 2021.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&amp;#160;&lt;a href="#fnref1:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:2">
&lt;p>Ham and Daniel D. Lee. Grassmann discriminant analysis: a unifying view on subspace-based learning. In ICML, pp. 376–383, 2008.&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item></channel></rss>