<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Jack Valmadre</title>
    <description>Computer vision researcher working on detection, tracking and 3D reconstruction.</description>
    <link>https://jack.valmadre.net/</link>
    <atom:link href="https://jack.valmadre.net/feed.xml" rel="self" type="application/rss+xml" />
    <pubDate>Sun, 08 Dec 2024 01:22:39 +0000</pubDate>
    <lastBuildDate>Sun, 08 Dec 2024 01:22:39 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>An accurate detection is not all you need to combat label noise in web-noisy dataset</title>
        <description>&lt;p&gt;ECCV 2024,
&lt;a href=&quot;https://eccv.ecva.net/virtual/2024/poster/2673&quot;&gt;Paper&lt;/a&gt;,
&lt;a href=&quot;https://github.com/PaulAlbert31/LSA&quot;&gt;Code&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Sun, 01 Sep 2024 00:00:00 +0000</pubDate>
        <link>https://jack.valmadre.net/papers/2024/09/01/linear-noise-separation/</link>
        <guid isPermaLink="true">https://jack.valmadre.net/papers/2024/09/01/linear-noise-separation/</guid>
        
        
        <category>papers</category>
        
      </item>
    
      <item>
        <title>Oops, I sampled it again: Reinterpreting confidence intervals in few-shot learning</title>
        <description>&lt;p&gt;TMLR 2024,
&lt;a href=&quot;https://openreview.net/forum?id=JxxkKt9yrx&quot;&gt;Paper&lt;/a&gt;,
&lt;a href=&quot;https://github.com/RafLaf/FSL-benchmark-again&quot;&gt;Code&lt;/a&gt;,
&lt;a href=&quot;https://www.youtube.com/watch?v=OB95-BLxE0s&quot;&gt;Video&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Sun, 01 Sep 2024 00:00:00 +0000</pubDate>
        <link>https://jack.valmadre.net/papers/2024/09/01/confidence-intervals/</link>
        <guid isPermaLink="true">https://jack.valmadre.net/papers/2024/09/01/confidence-intervals/</guid>
        
        
        <category>papers</category>
        
      </item>
    
      <item>
        <title>On skip connections and normalisation layers in deep optimisation</title>
        <description>&lt;p&gt;NeurIPS 2024,
&lt;a href=&quot;https://proceedings.neurips.cc/paper_files/paper/2023/hash/2f4d6f8e0f4f543db12260696b2a3551-Abstract-Conference.html&quot;&gt;Paper&lt;/a&gt;,
&lt;a href=&quot;https://github.com/lemacdonald/skip-connections-normalisation/&quot;&gt;Code&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Fri, 01 Dec 2023 00:00:00 +0000</pubDate>
        <link>https://jack.valmadre.net/papers/2023/12/01/skip-norm/</link>
        <guid isPermaLink="true">https://jack.valmadre.net/papers/2023/12/01/skip-norm/</guid>
        
        
        <category>papers</category>
        
      </item>
    
      <item>
        <title>On progressive sharpening, flat minima and generalisation</title>
        <description>&lt;p&gt;Tech report 2023,
&lt;a href=&quot;https://arxiv.org/abs/2305.14683&quot;&gt;Paper&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Mon, 01 May 2023 00:00:00 +0000</pubDate>
        <link>https://jack.valmadre.net/papers/2023/05/01/progressive-sharpening/</link>
        <guid isPermaLink="true">https://jack.valmadre.net/papers/2023/05/01/progressive-sharpening/</guid>
        
        
        <category>papers</category>
        
      </item>
    
      <item>
        <title>Hierarchical classification at multiple operating points</title>
        <description>&lt;p&gt;NeurIPS 2022,
&lt;a href=&quot;https://arxiv.org/abs/2210.10929&quot;&gt;Paper&lt;/a&gt;,
&lt;a href=&quot;https://github.com/jvlmdr/hiercls&quot;&gt;Code&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Tue, 01 Nov 2022 00:00:00 +0000</pubDate>
        <link>https://jack.valmadre.net/papers/2022/11/01/neurips-hiercls/</link>
        <guid isPermaLink="true">https://jack.valmadre.net/papers/2022/11/01/neurips-hiercls/</guid>
        
        
        <category>papers</category>
        
      </item>
    
      <item>
        <title>Learning with neighbor consistency for noisy labels</title>
        <description>&lt;p&gt;CVPR 2022,
&lt;a href=&quot;https://openaccess.thecvf.com/content/CVPR2022/html/Iscen_Learning_With_Neighbor_Consistency_for_Noisy_Labels_CVPR_2022_paper.html&quot;&gt;Paper&lt;/a&gt;,
&lt;a href=&quot;https://github.com/google-research/scenic/tree/main/scenic/projects/ncr&quot;&gt;Code&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Sun, 19 Jun 2022 00:00:00 +0000</pubDate>
        <link>https://jack.valmadre.net/papers/2022/06/19/cvpr-neighbor-consistency/</link>
        <guid isPermaLink="true">https://jack.valmadre.net/papers/2022/06/19/cvpr-neighbor-consistency/</guid>
        
        
        <category>papers</category>
        
      </item>
    
      <item>
        <title>Local metrics for multi-object tracking</title>
        <description>&lt;p&gt;Tech report 2021,
&lt;a href=&quot;https://arxiv.org/abs/2104.02631&quot;&gt;Paper&lt;/a&gt;,
&lt;a href=&quot;https://github.com/google-research/localmot&quot;&gt;Code&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Thu, 01 Apr 2021 00:00:00 +0000</pubDate>
        <link>https://jack.valmadre.net/papers/2021/04/01/localmot/</link>
        <guid isPermaLink="true">https://jack.valmadre.net/papers/2021/04/01/localmot/</guid>
        
        
        <category>papers</category>
        
      </item>
    
      <item>
        <title>Linear assignment with non-perfect matching</title>
        <description>&lt;p&gt;The &lt;a href=&quot;https://en.wikipedia.org/wiki/Assignment_problem&quot;&gt;linear assignment problem&lt;/a&gt; (or simply assignment problem) is the problem of finding a matching between two sets that minimizes the sum of pair-wise assignment costs.
This can be expressed as finding a &lt;a href=&quot;https://en.wikipedia.org/wiki/Matching_(graph_theory)&quot;&gt;matching&lt;/a&gt; (or independent edge set) in a &lt;a href=&quot;https://en.wikipedia.org/wiki/Bipartite_graph&quot;&gt;bipartite graph&lt;/a&gt; \(G = (U, V, E)\) that minimizes the sum of edge weights.
The edge weights may be positive or negative and the bipartite graph does not need to be &lt;a href=&quot;https://en.wikipedia.org/wiki/Complete_bipartite_graph&quot;&gt;complete&lt;/a&gt;: if there is no edge between two vertices then they cannot be associated.
Note that a maximum-weight assignment can be obtained by negating the weights and finding a minimum-weight assignment.&lt;/p&gt;

&lt;p&gt;The simplest form of the assignment problem assumes that the bipartite graph is &lt;em&gt;balanced&lt;/em&gt; (the two sets of vertices are the same size) and that there exists a &lt;em&gt;perfect&lt;/em&gt; matching (in which every vertex has a match).
Let \(n\) be the number of elements in each set and let \(C\) be a square matrix of size \(n \times n\) that contains the edge weights.
Missing edges are represented by \(\infty\), such that \(C_{i j} &amp;lt; \infty \Leftrightarrow (i, j) \in E\).
The assignment problem can then be clearly expressed as an &lt;a href=&quot;https://en.wikipedia.org/wiki/Integer_programming&quot;&gt;integer linear program&lt;/a&gt;: (note that the problem is not actually solved using a general-purpose ILP solver, it is just a convenient framework in which to express the problem)&lt;/p&gt;

\[\begin{aligned}
\text{minimize } &amp;amp; \textstyle \sum_{i, j} A_{i j} W_{i j} \\
\text{subject to }
&amp;amp; \textstyle A \in \{0, 1\}^{n \times n} \\
&amp;amp; \textstyle \forall i : \sum_{j} A_{i j} = 1 \\
&amp;amp; \textstyle \forall j : \sum_{i} A_{i j} = 1
\end{aligned}\]

&lt;p&gt;The constraint that the sum of each row and column is equal to one ensures that each element has exactly one match.
However, what happens when the graph is not balanced or does not contain a perfect matching?
We cannot enforce the sums to be equal to one.
Which problem should be solved?&lt;/p&gt;

&lt;p&gt;I recommend reading the tech report &lt;a href=&quot;https://www.hpl.hp.com/techreports/2012/HPL-2012-40R1.pdf&quot;&gt;“On Minimum-Cost Assignments in Unbalanced Bipartite Graphs”&lt;/a&gt; by Lyle Ramshaw and Robert E. Tarjan.
I will summarize some of the main points here.&lt;/p&gt;

&lt;p&gt;Let us consider a more general, rectangular problem of size \(r \times n\) and assume (without loss of generality) that \(r \le n\).
If \(r = n\) then the problem is balanced, if \(r &amp;lt; n\) it is unbalanced.&lt;/p&gt;

&lt;p&gt;Clearly an unbalanced probem cannot have a perfect matching, since there will be at least \(n - r\) unmatched elements in the larger set.
However, it may be possible to find a matching in which every vertex in the smaller set has a match.
This is referred to as a &lt;em&gt;one-sided perfect&lt;/em&gt; matching and the optimization problem can be expressed:&lt;/p&gt;

\[\begin{aligned}
\text{minimize } &amp;amp; \textstyle \sum_{i, j} A_{i j} W_{i j} \\
\text{subject to }
&amp;amp; \textstyle A \in \{0, 1\}^{r \times n} \\
&amp;amp; \textstyle \forall i : \sum_{j} A_{i j} = 1 \\
&amp;amp; \textstyle \forall j : \sum_{i} A_{i j} \le 1
\end{aligned}\]

&lt;p&gt;The inequality constraints enforce that each element in the smaller set has &lt;em&gt;exactly&lt;/em&gt; one match while each element in the larger set has &lt;em&gt;at most&lt;/em&gt; one match.
Ramshaw and Tarjan outline a method to reduce from an unbalanced problem to a balanced problem while preserving sparsity.
A simple alternative is to add \(n - r\) rows of zeros and then exclude these edges from the eventual solution.
Most libraries for the assignment problem solve either the balanced or unbalanced version of this problem (see the later section).&lt;/p&gt;

&lt;p&gt;However, whether balanced or unbalanced, it may still occur that the constraint set is infeasible, meaning that there does not exist a (one-sided) perfect matching.
Let \(\nu(W) \le r\) denote the size of the largest matching in the graph.
If \(\nu(W) &amp;lt; r\), then there does not exist a one-sided perfect matching and all possible matchings are imperfect.&lt;/p&gt;

&lt;p&gt;Ramshaw and Tarjan actually outline three different versions of the assignment problem:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;perfect matching&lt;/li&gt;
  &lt;li&gt;imperfect matching&lt;/li&gt;
  &lt;li&gt;minimum-weight matching&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The imperfect matching problem is to find the matching of size \(\nu(G)\) with the minimum cost.
The minimum-weight matching problem is to find the matching of &lt;em&gt;any&lt;/em&gt; size with the minimum cost.
If \(\nu(G) = r = n\), then perfect and imperfect matching coincide.
Otherwise, when \(\nu(G) &amp;lt; n\), there does not exist a perfect matching.&lt;/p&gt;

&lt;p&gt;The imperfect matching problem can be expressed&lt;/p&gt;

\[\begin{aligned}
\text{minimize } &amp;amp; \textstyle \sum_{i, j} A_{i j} W_{i j} \\
\text{subject to }
&amp;amp; \textstyle A \in \{0, 1\}^{r \times n} \\
&amp;amp; \textstyle \forall i : \sum_{j} A_{i j} \le 1 \\
&amp;amp; \textstyle \forall j : \sum_{i} A_{i j} \le 1 \\
&amp;amp; \textstyle \sum_{i, j} A_{i j} = \nu(W)
\end{aligned}\]

&lt;p&gt;and the minimum-weight matching problem can be expressed&lt;/p&gt;

\[\begin{aligned}
\text{minimize } &amp;amp; \textstyle \sum_{i, j} A_{i j} W_{i j} \\
\text{subject to }
&amp;amp; \textstyle A \in \{0, 1\}^{r \times n} \\
&amp;amp; \textstyle \forall i : \sum_{j} A_{i j} \le 1 \\
&amp;amp; \textstyle \forall j : \sum_{i} A_{i j} \le 1
\end{aligned}\]

&lt;p&gt;Ramshaw and Tarjan show that both of these problems can be reduced to finding a perfect matching in a balanced graph.
When using linear assignment, we should carefully consider which of the three problems we actually want to solve.&lt;/p&gt;

&lt;h3 id=&quot;remarks&quot;&gt;Remarks&lt;/h3&gt;

&lt;h4 id=&quot;in-support-of-minimum-weight-matching&quot;&gt;In support of minimum-weight matching&lt;/h4&gt;

&lt;p&gt;The minimum-weight matching problem is often the most natural choice, since it puts no constraint on the size of the matching.
To illustrate the difference between this and the other problems, consider the following balanced problem:&lt;/p&gt;

\[\begin{bmatrix}
2 &amp;amp; -1 \\
-2 &amp;amp; -4 \\
\end{bmatrix}\]

&lt;p&gt;The solution to perfect (or imperfect) matching is to choose -1 and -2 for a total score of -3 and a cardinality of 2.
The solution to minimum-weight matching is to choose -4 with a cardinality of 1.&lt;/p&gt;

&lt;p&gt;Minimum-weight matching will never select an edge with positive cost: it is better to simply leave it unselected.
Edges with zero cost have no impact.&lt;/p&gt;

&lt;p&gt;It may be more natural to consider the maximization of positive weights than the minimization of negative costs.&lt;/p&gt;

&lt;h4 id=&quot;min-cost-imperfect-matching-with-positive-weights&quot;&gt;Min-cost imperfect matching with positive weights&lt;/h4&gt;

&lt;p&gt;Be careful when solving imperfect matching problems with positive edge weights!
I would avoid this situation altogether due to the tension that exists between maximizing the number of matches and minimizing the sum of (positive) costs.
This may result in the unexpected behaviour that &lt;em&gt;adding&lt;/em&gt; an edge to the graph &lt;em&gt;increases&lt;/em&gt; the minimum cost.
For example, compare the following two problems:&lt;/p&gt;

\[W = \begin{bmatrix}
  ~ &amp;amp; 1 &amp;amp; 2 \\
  3 &amp;amp; ~ &amp;amp; ~ \\
  4 &amp;amp; ~ &amp;amp; ~ \\
\end{bmatrix}
\quad \Rightarrow \quad
\langle A^{\star}, W \rangle = 1 + 3 = 4\]

\[W = \begin{bmatrix}
~ &amp;amp; 1 &amp;amp; 2 \\
3 &amp;amp; 5 &amp;amp; ~ \\
4 &amp;amp; ~ &amp;amp; ~ \\
\end{bmatrix}
\quad \Rightarrow \quad 
\langle A^{\star}, W \rangle = 2 + 5 + 4 = 11\]

&lt;h4 id=&quot;quick-and-dirty-transformations&quot;&gt;Quick and dirty transformations&lt;/h4&gt;

&lt;p&gt;Ramshaw and Tarjan above describes some clever techniques to transform imperfect and minimum-weight matching problems into perfect matching problems while preserving sparsity.
Here we describe some quick and dirty alternatives.&lt;/p&gt;

&lt;p&gt;We can always transform an unbalanced (and therefore imperfect) problem into a balanced problem by adding \(n - r\) rows of zeros.
The resulting balanced graph has a perfect matching if and only if the original unbalanced graph had a matching of size \(r\) (in which every vertex in the smaller set is matched).&lt;/p&gt;

&lt;p&gt;If we need to solve imperfect matching but we only have a solver for perfect matching, it suffices to replace the infinite edge weights with a large, finite cost (e.g. larger than the total absolute value of all weights).
The resulting graph must contain a perfect matching since it is a complete bipartite graph, and each high-cost edge is worth more than all original edges combined.
The high-cost edges can be excluded at the end.&lt;/p&gt;

&lt;p&gt;Most existing packages either solve perfect, one-sided perfect or imperfect matching.
To use one of these solvers for the minimum-weight matching problem, it suffices to replace all positive edges (including infinite edges) with zero.
If using a solver that leverages sparsity, it is better to use the technique described by Ramshaw and Tarjan.&lt;/p&gt;

&lt;h3 id=&quot;python-packages&quot;&gt;Python packages&lt;/h3&gt;

&lt;p&gt;The table below outlines the different behaviour of several popular packages.
The code that was used to determine the behaviour is available as a &lt;a href=&quot;https://gist.github.com/jvlmdr/cfdef3de27653bed0aec93bbfb41481c&quot;&gt;Jupyter notebook&lt;/a&gt;.&lt;/p&gt;

&lt;table class=&quot;table&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Module&lt;/th&gt;
      &lt;th&gt;Function&lt;/th&gt;
      &lt;th&gt;Behaviour&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;https://github.com/src-d/lapjv&quot;&gt;lapjv&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lapjv()&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Requires that problem is balanced (or else raises an exception). Requires that a perfect matching exists (or else returns infinite cost).&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;https://github.com/gatagat/lap&quot;&gt;lap&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lapjv()&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Supports unbalanced problems (with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extend_cost=True&lt;/code&gt;; although check issues &lt;a href=&quot;https://github.com/gatagat/lap/issues/21&quot;&gt;#21&lt;/a&gt;, &lt;a href=&quot;https://github.com/gatagat/lap/issues/22&quot;&gt;#22&lt;/a&gt;). Requires that a one-sided perfect matching exists (or else returns infinite cost).&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;https://docs.scipy.org/doc/scipy/reference/optimize.html&quot;&gt;scipy&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;linear_sum_assignment()&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Supports unbalanced problems. Requires that a one-sided perfect matching exists (or else raises an exception).&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;https://github.com/cheind/py-lapsolver&quot;&gt;lapsolver&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;solve_dense()&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Supports unbalanced problems. Supports imperfect matching.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;https://developers.google.com/optimization/assignment/linear_assignment&quot;&gt;ortools&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LinearSumAssignment&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Requires problem is balanced. Requires that a perfect matching exists (or else raises an exception). Requires that costs are integer-valued.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

</description>
        <pubDate>Tue, 08 Dec 2020 00:00:00 +0000</pubDate>
        <link>https://jack.valmadre.net/notes/2020/12/08/non-perfect-linear-assignment/</link>
        <guid isPermaLink="true">https://jack.valmadre.net/notes/2020/12/08/non-perfect-linear-assignment/</guid>
        
        
        <category>notes</category>
        
      </item>
    
      <item>
        <title>Inf-norm versus squared two-norm on probability simplex</title>
        <description>&lt;p&gt;The \(\pi\) be an \(n\)-dimensional vector on the probability simplex, that is \(\pi_{i} \ge 0\) and \(\sum_{i} \pi_{i} = 1\).&lt;/p&gt;

&lt;p&gt;It is trivial to show that \(\|\pi\|_{2} \ge \|\pi\|_{\infty}\).
Let us instead compare the &lt;em&gt;squared&lt;/em&gt; 2-norm to the infinity norm.
Without loss of generality, assume that \(\pi_{1}\) is the largest element.&lt;/p&gt;

\[\begin{align}
\|\pi\|_2^2 - \|\pi\|_{\infty}
&amp;amp; = \pi_{1}^{2} + \cdots + \pi_{n}^{2} - \pi_{1} \\
&amp;amp; = -\pi_{1}(1 - \pi_{1}) + \cdots + \pi_{n}^{2} \\
&amp;amp; = -\pi_{1}(\pi_{2} + \cdots + \pi_{n}) + \pi_{2}^{2} + \cdots + \pi_{n}^{2} \\
&amp;amp; = \underbrace{\pi_{2}}_{\ge 0} \underbrace{(\pi_{2} - \pi_{1})}_{\le 0} + \cdots + \pi_{n} (\pi_{n} - \pi_{1}) \le 0
\end{align}\]

&lt;p&gt;Overall we have \(\|\pi\|_{2}^{2} \le \|\pi\|_{\infty} \le \|\pi\|_{2}\).&lt;/p&gt;

&lt;p&gt;This also provides a sufficient (and probably necessary) condition for equality: \(\pi_{i} = 0\) or \(\pi_{i} = \pi_{1}\) for all \(i\).&lt;/p&gt;
</description>
        <pubDate>Thu, 25 Jun 2020 00:00:00 +0000</pubDate>
        <link>https://jack.valmadre.net/notes/2020/06/25/squared-two-norm-convex/</link>
        <guid isPermaLink="true">https://jack.valmadre.net/notes/2020/06/25/squared-two-norm-convex/</guid>
        
        
        <category>notes</category>
        
      </item>
    
      <item>
        <title>Choosing an escape key for screen and tmux</title>
        <description>&lt;p&gt;Usually I don’t like to change the default terminal configuration because it becomes impossible to use someone else’s computer or for them to use yours.
However, the default choices of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-a&lt;/code&gt; in screen and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-b&lt;/code&gt; in tmux are awful if you’re used to emacs-style text navigation.
I have been using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-]&lt;/code&gt; for a few years and I’m pretty happy with it.
I wanted to document the reasoning behind this choice.&lt;/p&gt;

&lt;p&gt;The criteria for an escape key are:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;it should not be a shortcut that you need to use often,&lt;/li&gt;
  &lt;li&gt;it should not have dramatic consequences outside of screen and&lt;/li&gt;
  &lt;li&gt;it should be easy to type (single modifier key).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is an evaluation of all 32 ASCII control characters in order.&lt;/p&gt;

&lt;table class=&quot;table&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Key&lt;/th&gt;
      &lt;th&gt;Code&lt;/th&gt;
      &lt;th&gt;Rating&lt;/th&gt;
      &lt;th&gt;Reason&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-SPC&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;emacs (set mark)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-a&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;emacs (start of line)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-b&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;emacs (move cursor back)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-c&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;bash (sends SIGINT)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-d&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;end of transmission, exit shell; vim (page down)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-e&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;emacs (end of line)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-f&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;6&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;emacs (move cursor forward)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-g&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;7&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;emacs (abort command)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-h&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;8&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;backspace key; emacs (help prefix)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-i&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;9&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;tab key &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\t&lt;/code&gt;; vim (move cursor to next position in history)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-j&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;line feed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\n&lt;/code&gt;; emacs (evaluate lisp expression)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-k&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;11&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;emacs (kill to end of line)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-l&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;12&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;bash (clear screen); emacs (scroll such that current line is at top/middle/bottom)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-m&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;13&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\r&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-n&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;14&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;emacs (next line)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-o&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;15&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;vim (move cursor to previous position in history)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-p&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;16&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;emacs (previous line)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-q&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;17&lt;/td&gt;
      &lt;td&gt;maybe&lt;/td&gt;
      &lt;td&gt;emacs (quoted insert; toggle read-only status)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-r&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;18&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;vim (redo); shell (reverse search)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-s&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;19&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;emacs (save current file)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-t&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;20&lt;/td&gt;
      &lt;td&gt;maybe&lt;/td&gt;
      &lt;td&gt;emacs (transpose characters/lines)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-u&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;21&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;bash (kill to start of line); vim (page up)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-v&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;22&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;emacs (page down); vim (block-selection mode; insert control key)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-w&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;23&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;emacs (kill region); bash (kill previous word); vimdiff (switch panes)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-x&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;24&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;emacs (start of key sequence)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-y&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;25&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;emacs (yank)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-z&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;26&lt;/td&gt;
      &lt;td&gt;maybe&lt;/td&gt;
      &lt;td&gt;bash (sends SIGSTOP)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-[&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;27&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;escape key (prohibitive for vim)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-\&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;28&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;bash (sends SIGQUIT)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-]&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;29&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-^&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;30&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;no easy way to type?&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-/&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;31&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;emacs (redo)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C--&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;31&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;equal to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-/&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Note that the key combinations &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-;&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-&apos;&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-.&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-,&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-=&lt;/code&gt; do not correspond to control characters.&lt;/p&gt;

&lt;p&gt;Just be careful; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-]&lt;/code&gt; can be right next to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-\&lt;/code&gt;, which sends SIGQUIT.&lt;/p&gt;

&lt;p&gt;Update (Nov 2021): Thanks to Jay Freeman for pointing out that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-]&lt;/code&gt; is used to &lt;a href=&quot;https://vim.fandom.com/wiki/Browsing_programs_with_tags&quot;&gt;jump to a tag&lt;/a&gt; in vim.&lt;/p&gt;
</description>
        <pubDate>Thu, 06 Feb 2020 00:00:00 +0000</pubDate>
        <link>https://jack.valmadre.net/notes/2020/02/06/escape-key/</link>
        <guid isPermaLink="true">https://jack.valmadre.net/notes/2020/02/06/escape-key/</guid>
        
        
        <category>notes</category>
        
      </item>
    
  </channel>
</rss>
