<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="4.3.2">Jekyll</generator><link href="https://www.cs.rpi.edu/~gittea/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.cs.rpi.edu/~gittea/" rel="alternate" type="text/html" hreflang="en" /><updated>2025-08-28T11:31:35-04:00</updated><id>https://www.cs.rpi.edu/~gittea/feed.xml</id><title type="html">blank</title><subtitle>Alex Gittens&apos; academic website. Based on [*folio](https://github.com/bogoli/-folio) design.
</subtitle><entry><title type="html">Teaching kernel learning</title><link href="https://www.cs.rpi.edu/~gittea/blog/2023/teaching-kernel-learning/" rel="alternate" type="text/html" title="Teaching kernel learning" /><published>2023-10-05T15:11:56-04:00</published><updated>2023-10-05T15:11:56-04:00</updated><id>https://www.cs.rpi.edu/~gittea/blog/2023/teaching-kernel-learning</id><content type="html" xml:base="https://www.cs.rpi.edu/~gittea/blog/2023/teaching-kernel-learning/"><![CDATA[<p>Here’s a neat approach to teaching kernel learning (for empirical risk minimization), following section 2.2.6 of the book “First-order and Stochastic Optimization Methods for Machine Learning” by Guanghui Lan. It is a straightforward approach, based on the first-order optimality condition, and I have not seen it elsewhere.</p>

<p>Consider the convex empirical risk minimization problem</p>

<p>\[ \omega^\star = \text{argmin}_{\omega \in \mathbb{R}^d} \frac{1}{n} \sum_{i=1}^n \ell(\omega^T x_i, y_i) + \lambda \|\omega\|_2^2.\]</p>

<p>Fermat’s condition implies that the optimal model weights are in the span of the training data points, \(\omega^\star = \sum_{i=1}^n \alpha_i x_i \), so the problem can be recast as</p>

<p>\[ \alpha^\star = \min_{\alpha \in \mathbb{R}^n} \frac{1}{n} \sum_{i=1}^n \ell( \sum_{j=1}^n \alpha_j \langle x_i, x_j \rangle, y_i) + \lambda \sum_{i=1}^n \sum_{j=1}^n \alpha_i \alpha_j \langle x_i, x_j \rangle. \]</p>

<p>Define the <em>linear kernel matrix</em> \(K = [ \langle x_i, x_j \rangle ]_{i,j=1,\ldots,n}\), and this becomes</p>

<p>\[ \alpha^\star = \text{argmin}_{\alpha \in \mathbb{R}^n} \frac{1}{n} \sum_{i=1}^n \ell( (K \alpha)_i, y_i) + \lambda \alpha^T K \alpha, \]</p>

<p>which is again a convex optimization problem. Once \(\alpha^\star\) is known, the model can be used to predict the value of the target given a new input, also in terms of the <em>kernel function</em> \( \kappa(x_1, x_2) = \langle x_1, x_2 \rangle \) :</p>

<p>\[ (\omega^\star)^T x = \sum_{i=1}^n \alpha_i \langle x_i, x \rangle = \sum_{i=1}^n \alpha_i \kappa(x_i, x). \]</p>

<p>This reformulation of the ERM is not particularly useful unless \(d &gt; n\), as the original ERM involved a \(d\)-dimensional optimization problem while the latter involves a \(n\)-dimensional optimization problem and involves forming and working with an \(n \times n\) kernel matrix. However, if \(d\) is larger than \(n\), the <em>kernel trick</em> that led to the second ERM is useful, as the latter ERM may be more efficient to work with.</p>

<p>Now, consider that we want to learn using linear combinations of some fixed functions of the raw features \(x\), e.g. we want to learn using the features \(x_1, x_2, x_1^2, x_2^2, x_1 x_2, \ldots\). One can imagine that using such features could be of benefit over simply using the raw features. Let \(\phi(x)\) denote the <em>feature map</em> that maps the raw features from \(d\) dimensions into \(D\) new features, then the ERM of interest is</p>

<p>\[ \min_{\omega \in \mathbb{R}^D} \frac{1}{n} \sum_{i=1}^n \ell(\omega^T \phi(x_i), y_i) + \lambda \|\omega\|_2^2,\]</p>

<p>and the same reasoning as before tells us that \(\omega^\star = \sum_{i=1}^n \alpha_i \phi(x_i)\). Defining the <em>nonlinear kernel function</em> \( \kappa(x_1, x_2) = \langle \phi(x_1), \phi(x_2) \rangle \) and the corresponding <em>nonlinear kernel matrix</em> \(K = [ \kappa(x_1, x_2) ]_{i,j=1,\ldots,n}\) corresponding to the feature map \(\phi\), we see that we can fit this model by solving</p>

<p>\[ \min_{\alpha \in \mathbb{R}^n} \frac{1}{n} \sum_{i=1}^n \ell( (K \alpha)_i, y_i) + \lambda \alpha^T K \alpha, \]</p>

<p>the exact same convex problem as before, and also predict using</p>

<p>\[ (\omega^\star)^T \phi(x) = \sum_{i=1}^n \alpha_i \langle \phi(x_i), \phi(x) \rangle = \sum_{i=1}^n \alpha_i \kappa(x_i, x). \]</p>

<p>Note that \(\phi\) could even be infinite-dimensional, and this approach still works: the ERM stated in terms of the feature map is not solvable on a computer, but the latter is, as it involves working with only an \(n\)-dimensional optimization problem. In practice, even if \(\phi\) is finite-dimensional, \(D\) is taken to be sufficiently high that the kernel version of the ERM is more efficiently solvable than the feature map version of the ERM. Further, \(\phi\) is chosen so that the kernel function is efficiently evaluable.</p>

<p>The canonical example of the feature map used in kernel learning is the Gaussian/radial basis feature map, an infinite dimensional feature map that consists of all the monomials in the raw features, each downweighed by an appropriate exponential weight (it’s tedious to write out, you can look it up). The nice thing is that this choice of feature map leads to the RBF kernel function that we all know and love</p>

\[\kappa(x_1, x_2) = \exp\left(-\frac{\|x_1 – x_2\|_2^2}{2\sigma^2} \right),\]

<p>where \(\sigma^2\) is a hyperparameter.</p>]]></content><author><name></name></author><category term="kernel" /><category term="learning;" /><category term="machine" /><category term="optimization" /><summary type="html"><![CDATA[Here’s a neat approach to teaching kernel learning (for empirical risk minimization), following section 2.2.6 of the book “First-order and Stochastic Optimization Methods for Machine Learning” by Guanghui Lan. It is a straightforward approach, based on the first-order optimality condition, and I have not seen it elsewhere.]]></summary></entry><entry><title type="html">Nystrom vs Random Feature Maps</title><link href="https://www.cs.rpi.edu/~gittea/2014/12/26/nystrom-vs-random-feature-maps/" rel="alternate" type="text/html" title="Nystrom vs Random Feature Maps" /><published>2014-12-26T22:37:49-05:00</published><updated>2014-12-26T22:37:49-05:00</updated><id>https://www.cs.rpi.edu/~gittea/2014/12/26/nystrom-vs-random-feature-maps</id><content type="html" xml:base="https://www.cs.rpi.edu/~gittea/2014/12/26/nystrom-vs-random-feature-maps/"><![CDATA[<p>I haven’t seen a truly convincing study comparing Nystrom approximations to Random Feature Map approximations. On the one hand, a <a href="http://papers.nips.cc/paper/4588-nystrom-method-vs-random-fourier-features-a-theoretical-and-empirical-comparison" title="Nystrom Methods vs Random Feature Maps: A Theoretical and Empirical Comparison">NIPS 2012 paper compared the two</a> and argued that because the bases Nystrom approximations use are adaptive to the problem, whereas those used by RFMs are not, Nystrom approximations are more efficient.</p>

<p>This is an indisputable point, but the experiments done in the paper are not convincing: they used the same number of samples in Nystrom approximations as random features in RFMS. Instead, the fair comparison is to allot both methods the same number of FLOPs; since Nystrom methods involve an additional pseudoinversion of a (huge, for a large number of samples) matrix, one can potentially use more random features than sample points for the same number of FLOPs. Also, as always, it is important to choose an appropriate kernel — this paper only considered RBF kernels.</p>

<p>On the other hand, recently IBM researchers have used <a href="http://arxiv.org/abs/1409.0940" title="High-performance Kernel Machines with Implicit Distributed Optimization and Randomization">large-scale RFM approaches</a> to get <a href="http://www.ifp.illinois.edu/~huang146/papers/Kernel_DNN_ICASSP2014.pdf" title="Kernel methods match deep neural networks on TIMIT">state-of-the-art performance</a> on vision and speech tasks. Their results use the simplest of RFM approaches: linear regression on top of a very large number (~400K) random fourier features. The key to their success is a well-engineered ADMM approach to parallelizing the solution of the system. It’s not clear to me that a similar approach couldn’t be used to scale up a Nystrom-based solution and obtain similar results. Also, I’ve not seen anyone implement Wainwright et al.’s divide and conquer approach to kernel regression; theoretically, this could also be used to distribute the cost of a truly large-scale Nystrom implementation.</p>

<p>Personally, I’m of the opinion that a well-engineered Nystrom solution (using uniform sampling, even) should always outperform a well-engineered RFM solution. But, I’m interested in seeing this convincingly demonstrated.</p>]]></content><author><name>swiftset</name></author><category term="Uncategorized" /><summary type="html"><![CDATA[I haven’t seen a truly convincing study comparing Nystrom approximations to Random Feature Map approximations. On the one hand, a NIPS 2012 paper compared the two and argued that because the bases Nystrom approximations use are adaptive to the problem, whereas those used by RFMs are not, Nystrom approximations are more efficient.]]></summary></entry><entry><title type="html">Mirror descent is, in a precise sense, a second order algorithm</title><link href="https://www.cs.rpi.edu/~gittea/2014/10/01/mirror-descent-is-in-a-precise-sense-a-second-order-algorithm/" rel="alternate" type="text/html" title="Mirror descent is, in a precise sense, a second order algorithm" /><published>2014-10-01T22:47:15-04:00</published><updated>2014-10-01T22:47:15-04:00</updated><id>https://www.cs.rpi.edu/~gittea/2014/10/01/mirror-descent-is-in-a-precise-sense-a-second-order-algorithm</id><content type="html" xml:base="https://www.cs.rpi.edu/~gittea/2014/10/01/mirror-descent-is-in-a-precise-sense-a-second-order-algorithm/"><![CDATA[<p>For one of our projects at eBay, I’ve been attempting to do a Poisson MLE fit on a large enough dataset that <a href="http://en.wikipedia.org/wiki/Scoring_algorithm" title="Fisher scoring">Fisher scoring</a> is not feasible. The problem is that the data also has such large variance in the scales of the observation that stochastic gradient descent does not work, period — because of the exponentiation involved, you need to take a very tiny step size to avoid overflow errors, but this step size is shared by all the parameters, so you can’t make progress in this way.</p>

<p>An alternative is <a href="http://jmlr.org/papers/v12/duchi11a.html" title="Adaptive Subgradient Methods for Online Learning and Stochastic Optimization">adagrad</a>, which maintains separate stepsizes for each parameter, but that seems to run into the same divergence issue, albeit much slower — slow enough that it’s unclear to me whether the fit is actually diverging, or if it ‘just’ needs to run a couple hundred of iterations before it converges. So for the past week I’ve been massaging the initial conditions and amount of information I hard-bake into the parametrization of the problem to see if I can get Adagrad to work reasonably. Still no luck.</p>

<p>I just came across Raskutti’s and Mukherjee’s paper “<a href="http://arxiv.org/abs/1310.7780" title="The information geometry of mirror descent">The information geometry of mirror descent</a>“, which seems relevant to my situation and is a nice (albeit, in need of proof-reading) read. The main result of the paper is that the mirror descent algorithm associated with the Bregman divergence of a function \(G\) is equivalent to natural gradient descent in the dual manifold with metric tensor defined by Hessian of the convex conjugate of \(G.\) This sounds wonderful, because the connection between exponential families and Bregman divergences suggests that one can then perform a first-order optimization in a certain dual manifold, and reap all the benefits of having done Fisher scoring, a second-order algorithm, in parameter space. I have to reread the paper carefully to get a handle on the precise manipulations required, but this may be a nice alternative to Adagrad for my problem.</p>

<p>I wonder: is there a similarly geometric interpretation of what <a href="http://eprints.pascal-network.org/archive/00007140/" title="Composite Objective Mirror Descent">composite mirror descent</a> does?</p>

<p><strong>Update</strong>: A more readable recent paper, <a href="http://www.auai.org/uai2014/proceedings/individuals/271.pdf" title="Stochastic Discriminative EM">“Stochastic Discriminative EM”</a> from UAI 2014, does a better job of explaining the interpretation of the dual manifold and has a very similar algorithm.</p>]]></content><author><name>swiftset</name></author><category term="Uncategorized" /><summary type="html"><![CDATA[For one of our projects at eBay, I’ve been attempting to do a Poisson MLE fit on a large enough dataset that Fisher scoring is not feasible. The problem is that the data also has such large variance in the scales of the observation that stochastic gradient descent does not work, period — because of the exponentiation involved, you need to take a very tiny step size to avoid overflow errors, but this step size is shared by all the parameters, so you can’t make progress in this way.]]></summary></entry><entry><title type="html">Algebra: it matters</title><link href="https://www.cs.rpi.edu/~gittea/2014/09/15/algebra-it-matters/" rel="alternate" type="text/html" title="Algebra: it matters" /><published>2014-09-15T16:42:38-04:00</published><updated>2014-09-15T16:42:38-04:00</updated><id>https://www.cs.rpi.edu/~gittea/2014/09/15/algebra-it-matters</id><content type="html" xml:base="https://www.cs.rpi.edu/~gittea/2014/09/15/algebra-it-matters/"><![CDATA[<p>I’m looking at two different models for learning polynomial functions, and trying to determine if they are equivalent. After a couple days of thinking, I’ve reduced the question to the following:</p>

<blockquote>
  <p>Can every symmetric polynomial of degree \(r\) in \(d\) variables that has no constant term be written as a sum of the \(r\)-th powers of linear polynomials in \(d\) degrees and a homogeneous polynomial of degree \(r\) each of whose monomials involves at most \(d-1\) variables?</p>
</blockquote>]]></content><author><name>swiftset</name></author><category term="Uncategorized" /><summary type="html"><![CDATA[I’m looking at two different models for learning polynomial functions, and trying to determine if they are equivalent. After a couple days of thinking, I’ve reduced the question to the following:]]></summary></entry><entry><title type="html">Eigenvector two-condition number for a product of PSD matrices</title><link href="https://www.cs.rpi.edu/~gittea/2014/04/07/eigenvector-two-condition-number-for-a-product-of-psd-matrices/" rel="alternate" type="text/html" title="Eigenvector two-condition number for a product of PSD matrices" /><published>2014-04-07T09:31:20-04:00</published><updated>2014-04-07T09:31:20-04:00</updated><id>https://www.cs.rpi.edu/~gittea/2014/04/07/eigenvector-two-condition-number-for-a-product-of-psd-matrices</id><content type="html" xml:base="https://www.cs.rpi.edu/~gittea/2014/04/07/eigenvector-two-condition-number-for-a-product-of-psd-matrices/"><![CDATA[<p>I’m pushing to submit a preprint on the Nystrom method that has been knocking around for the longest time.</p>

<p>I find myself running into problems centering around expressions of the type \(B^{-1}A\), where \(A, B\) are SPSD matrices satisfying \(B \preceq A\). This expression will be familiar to numerical linear algebraists: there \(B\) would be a preconditioner for a linear system \(A x = b,\) and the relevant quantity of interest is the spectral radius of \(B^{-1} A\).</p>

<p>It’s not hard to show that the spectral radius of this product is at most 1… but instead, I’m interested in the norm of this product. Because the spectral radius of the product is at most 1, we can use the bound<br />
\[<br />
\|B^{-1} A\|_2 \leq \kappa(U_{B^{-1}A})<br />
\]<br />
where \(\kappa(U_{B^{-1}A})\) is the two-condition number of the matrix of eigenvectors of \(B^{-1}A \).</p>

<p>In the applications I’m interested in, some rough numerical experiments show that this bound is good enough for my purposes (the two terms are of the same order). Assuming this is the case, how can I get a good theoretical bound on this condition number?</p>]]></content><author><name>swiftset</name></author><category term="Uncategorized" /><summary type="html"><![CDATA[I’m pushing to submit a preprint on the Nystrom method that has been knocking around for the longest time.]]></summary></entry><entry><title type="html">Canonical Correlation Analysis (CCA)</title><link href="https://www.cs.rpi.edu/~gittea/2014/04/07/canonical-correlation-analysis-cca/" rel="alternate" type="text/html" title="Canonical Correlation Analysis (CCA)" /><published>2014-04-07T09:20:11-04:00</published><updated>2014-04-07T09:20:11-04:00</updated><id>https://www.cs.rpi.edu/~gittea/2014/04/07/canonical-correlation-analysis-cca</id><content type="html" xml:base="https://www.cs.rpi.edu/~gittea/2014/04/07/canonical-correlation-analysis-cca/"><![CDATA[<p>I am not completely satisfied with the expositions of CCA that I’ve come across, so I decided to write one that reflects my own intuition.</p>

<p>CCA is useful in the case where you observe two random variables that are both noisy linear functions of some underlying latent random variable, and you want to use this fact to help you guess the latent variable. Formally, assume<br />
\[<br />
x = T_X z + n_x, \quad \text{ and } \quad y = T_Y z + n_y,<br />
\]<br />
where, without loss of generality, we assume that the entries of \(z\) are uncorrelated and unit variance. Here \(T_X\) and \(T_Y\) are matrices whose image spaces may be of different dimension, and \(n_x\) and \(n_y\) are white noise. For convenience, we assume that \(z\) is mean-zero, so that \(x\) and \(y\) are also.</p>

<p>In order to recover \(z\) from \(x\) and \(y\), we phrase the following question: find two transformations \(\Phi_X\) and \(\Phi_Y\) so that the entries of \(\Phi_X x\) are uncorrelated and unit variance, as are those of \(\Phi_Y y\), and the correlation of \(\Phi_X x\) with \(\Phi_Y y\) is maximized.</p>

<p>We could use PCA to whiten \(x\) and \(y\) individually to get two different noisy estimates of \(z\), but this would ignore the fact that knowing both \(x\) and \(y\) gives us more information on \(z\). Indeed, the requirement that the correlation of \(\Phi_X x\) and \(\Phi_Y y\) be maximized should tend to choose \(\Phi_X\) and \(\Phi_Y\) which remove the directions containing the noise \(n_x\) and \(n_y\).</p>

<p>CCA can then be formulated as the following:<br />
\[<br />
\max_{\Phi_X, \Phi_Y} \mathbb{E} \langle \Phi_X x, \Phi_Y y \rangle \text{ subject to }<br />
\mathbb{E} \Phi_X x (\Phi_X x)^T = \mathbb{E} \Phi_Y y (\Phi_Y y)^T = I,<br />
\]<br />
or equivalently,<br />
\[<br />
\max_{\Phi_X, \Phi_Y} \text{Trace}(\Phi_Y C_{y x} \Phi_X^T) \text{ subject to } \Phi_X C_{xx} \Phi_X^T = \Phi_Y C_{yy} \Phi_Y^T = I,<br />
\]<br />
where \(C_{xx}, C_{yy}\) are the covariance matrices of \(x\) and \(y\) and \(C_{yx}\) is the cross-covariance matrix of \(y\) and \(x\) given by \(C_{yx} = \mathbb{E} (yx^T).\)</p>

<p>Since \(C_{xx}\) and \(C_{yy}\) are full-rank, by taking \(\Phi_X^\prime = \Phi_X C_{xx}^{1/2}\) and \(\Phi_Y^\prime = \Phi_Y C_{yy}^{1/2}, \)this program can be transformed to<br />
\[<br />
\max_{\Phi_X^\prime, \Phi_Y^\prime} \text{Trace}(\Phi_Y^\prime C_{yy}^{-1/2} C_{yx} C_{xx}^{-1/2} \Phi_X^{\prime T}) \text{ subject to } \Phi_x^\prime \Phi_x^{\prime T} = \Phi_Y^\prime \Phi_Y^{\prime T} = I.<br />
\]</p>

<p>From the standard characterization of the SVD, it is clear that the solution \(\Phi_X^\prime\) and \(\Phi_Y^\prime\) are given by the top right and left singular vectors of the matrix \(C_{yy}^{-1/2} C_{yx} C_{xx}^{-1/2}.\) Equivalently, they are the top eigenvectors of the two matrices \(C_{xx}^{-1/2} C_{xy} C_{yy}^{-1} C_{yx} C_{xx}^{-1/2}\) and \(C_{yy}^{-1/2} C_{yx} C_{xx}^{-1} C_{xy} C_{yy}^{-1}.\) The eigenvectors of these two unwieldy matrices are also the top eigenvectors of the generalized eigenvalue problems given by<br />
\begin{align*}<br />
C_{xy} C_{yy}^{-1} C_{yx} \phi_i^x &amp; = \lambda_i C_{xx} \phi_i^x \\<br />
C_{yx} C_{xx}^{-1} C_{xy} \phi_i^y &amp; = \lambda_i C_{yy} \phi_i^y.<br />
\end{align*}<br />
Here the \(\lambda_i\) are the squared canonical correlations, and the \(\phi^x_i, \phi^y_i\) are the canonical correlation basis vectors.</p>

<p>None of the non-variational characterizations given so far seem terribly efficiently, since they all involve two matrix inversion. It turns out that CCA can be done by using a QR decomposition instead. See <a href="http://www.ams.org/journals/mcom/1973-27-123/S0025-5718-1973-0348991-3/" title="Numerical methods for computing angles between linear subspaces">Björck and Golub, 1973</a> for the details of the algorithm, and the connection between CCA and the principle angles between subspaces.</p>]]></content><author><name>swiftset</name></author><category term="Uncategorized" /><summary type="html"><![CDATA[I am not completely satisfied with the expositions of CCA that I’ve come across, so I decided to write one that reflects my own intuition.]]></summary></entry><entry><title type="html">Adagrad and projections onto ellipsoids</title><link href="https://www.cs.rpi.edu/~gittea/2014/02/06/adagrad-and-projections-onto-ellipsoids/" rel="alternate" type="text/html" title="Adagrad and projections onto ellipsoids" /><published>2014-02-06T22:16:32-05:00</published><updated>2014-02-06T22:16:32-05:00</updated><id>https://www.cs.rpi.edu/~gittea/2014/02/06/adagrad-and-projections-onto-ellipsoids</id><content type="html" xml:base="https://www.cs.rpi.edu/~gittea/2014/02/06/adagrad-and-projections-onto-ellipsoids/"><![CDATA[<p>((<strong>Caveat!</strong> I am not sure the manipulations done in this post are correct, but the gist is certainly there.))</p>

<p>One of my favorite optimization techniques is <a href="http://jmlr.org/papers/v12/duchi11a.html" title="Adaptive Subgradient Methods for Online Learning and Stochastic Optimization">Adagrad</a>, a first-order technique that approximates the Hessian by using all the gradients up to that point. It calls for updates of the form:<br />
\[<br />
x_{t+1} = \Pi_{\mathcal{X}}^{G_t^{1/2}} (x_t – \eta G_{t}^{-1/2} g_t),<br />
\]<br />
or more practically for high-dimensional problems,<br />
\[<br />
x_{t+1} = \Pi_{\mathcal{X}}^{\text{diag}(G_t)^{1/2}} (x_t – \eta \text{diag}(G_{t})^{-1/2} g_t).<br />
\]<br />
Here, \(g_t\) denotes the gradient at step \(t\), \(\eta\) is a <em>fixed</em> stepsize, \(\mathcal{X}\) is the constraint set for your optimization problem,<br />
\[<br />
G_t = \sum_{i=1}^t g_t g_t^T,<br />
\]<br />
and \(\Pi_{\mathcal{X}}^A\) is the projection onto the constraint set with respect to a distance function defined by a positive-definite matrix \(A\):<br />
\[<br />
\Pi_{\mathcal{X}}^A (y) := \text{argmin}_x \langle x – y, A (x-y) \rangle = \|A^{1/2} (x-y)\|_2^2.<br />
\]<br />
By convention \(\Pi_{\mathcal{X}} = \Pi_{\mathcal{X}}^I\) denotes the Euclidean projection operator.</p>

<p>The neat thing about Adagrad is that it chooses different effective step sizes for each variable, rather than using one fixed step size for all of them. I’ve found that Adagrad outperforms sgd in my non-constrained optimization problems.</p>

<p>Now I need to use adagrad on a ball constrained problem: \(\mathcal{X} = \{ x : \|x\|_2 \leq B \}\). Computing the associated projection operator \(\Pi_{\mathcal{X}}^A)\) was a nice enough exercise in basic convex optimization that it seems worth recording here. Actually, given the ubiquity of this constraint set, I’m surprised the authors didn’t seem to provide this as an example in their paper (I may have missed it, since I only read the absolute minimum to get the gist of the idea and then skimmed the rest).</p>

<h3 id="adagrads-connection-to-euclidean-projection-onto-ellipsoids">Adagrad’s connection to Euclidean projection onto ellipsoids</h3>

<p>Our first step is to observe that<br />
\[<br />
\min_{\|x\|_2 \leq B} \|A^{1/2} (x- y)\|_2^2 = \min_{\|A^{-1/2} x\| \leq B} \|x – A^{1/2}y\|_2^2<br />
\]<br />
since \(A^{1/2}\) is invertible, and that the unique minimizer of the first program is a linear transformation of the unique minimizer of the second. Concretely,<br />
\begin{align*}<br />
\Pi_{\|x\|_2 \leq B}^{A}(y) &amp; = A^{-1/2} \text{argmin}_{\|A^{-1/2} x\| \leq B} \|x – A^{1/2}y\|_2^2 \\<br />
 &amp; = A^{-1/2} \Pi_{\|A^{-1/2} x\|_2 \leq B} (A^{1/2} y).<br />
\end{align*}</p>

<h3 id="the-lagrangian-dual-to-euclidean-projection-onto-an-ellipsoid">The Lagrangian dual to Euclidean projection onto an ellipsoid</h3>

<p>Thus, it suffices to determine the Euclidean projection operator onto an ellipsoid, \(\Pi_{\|Q x\|_2 \leq B}(z)\), where \(Q\) is positive-semidefinite. To do so, let’s write out the optimization problem that defines this projection operator:<br />
\[<br />
\min_{x^T Q^T Q x \leq B^2} (x – z)^T(x-z).<br />
\]<br />
The associated Lagrangian is:<br />
\begin{align*}<br />
L(x,\lambda) &amp;= (x-z)^T(x-z) – \lambda ( B^2 – x^TQ^TQx) \\<br />
&amp; = x^T( I + \lambda Q^TQ) x – 2z^T x + z^Tz – \lambda B^2.<br />
\end{align*}<br />
Recall that \(L(x,\lambda)\) is a lower bound on the objective whenever \(x\) is feasible and \(\lambda \geq 0.\) To find a uniform lower bound, we minimize \(L\) with respect to \(x\) by setting \(\nabla_x L = 0\). This occurs when<br />
\[<br />
x = (I + \lambda Q^TQ)^{-1} z,<br />
\]<br />
and gives the uniform lower bound<br />
\[<br />
g(\lambda) = \min_x L(x, \lambda) = z^T[ I – (I + \lambda Q^TQ)^{-1} ]z – \lambda B^2.<br />
\]<br />
The optimization problem we’re looking at satisfies strong duality, so we know that maximizing \(g\) over the set of nonnegative \(\lambda\) gives the same optimal value of the original problem, and corresponding to the optimal \(\lambda\) there is an optimal \(x\). We now find the optimal \(\lambda\) and show how to recover the optimal \(x\).</p>

<h3 id="from-the-dual-optimal-point-to-the-primal-optimal-point">From the dual optimal point to the primal optimal point</h3>

<p>First write the SVD of \(Q^TQ\) as \(Q^TQ = U \Sigma U^T.\) It follows that<br />
\[<br />
I – (I + \lambda Q^TQ)^{-1} = \left[ \frac{\lambda \sigma_{i}}{1 + \lambda \sigma_{i}} \right]_{ii},<br />
\]<br />
where \(\sigma_i = \Sigma_{ii}.\) The optimal \(\lambda\) then is the nonnegative \(\lambda\) which maximizes<br />
\begin{align*}<br />
g(\lambda) &amp; = z^T[ I – (I + \lambda Q^TQ)^{-1} ]z – \lambda B^2 \\<br />
 &amp; = \sum\nolimits_i (U^Tz)_i^2 \frac{\lambda \sigma_{i}}{1 + \lambda \sigma_{i}} – \lambda B^2.<br />
\end{align*}</p>

<p>Observe that \(g(\lambda)\) is concave on \(\mathbb{R}^+,\) so its maximum occurs at \(0\) or the point where \(g^\prime(\lambda) = 0\). Thus, if the equation<br />
\[<br />
\sum\nolimits_i (U^Tz)_i^2 \frac{\sigma_i}{(1 + \lambda \sigma_i)^2} = \|Q(I + \lambda Q^TQ)^{-1} z\|_2^2 = B^2<br />
\]<br />
has a nonnegative solution, that solution is the optimal \(\lambda\). If not, then the optimal \(\lambda\) is \(0.\)</p>

<p>Given this optimal \(\lambda,\) the corresponding optimal \(x\) is given by<br />
\[<br />
x = \Pi_{\|Qx\|_2 \leq B}(z) = (I + \lambda Q^TQ)^{-1} z.<br />
\]</p>

<h3 id="from-the-euclidean-projection-on-an-ellipsoid-back-to-the-adagrad-projector">From the Euclidean projection on an ellipsoid back to the Adagrad projector</h3>

<p>Putting all the pieces together, we get the following expression for the projection operator needed in Adagrad:<br />
\begin{align*}<br />
\Pi_{\|x\|_2 \leq B}^A(y) &amp; = A^{-1/2} \Pi_{\|A^{-1/2}x\|_2 \leq B}(A^{1/2}y) \\<br />
 &amp; = A^{-1/2} ( I + \lambda A^{-1})^{-1} A^{1/2} y \\<br />
 &amp; = (I + \lambda A^{-1})^{-1}y = A(A + \lambda I)^{-1}y,<br />
\end{align*}<br />
where \(\lambda\) is either the nonnegative solution to the nonlinear equation<br />
\begin{align*}<br />
\sum\nolimits_i (\Sigma^{1/2} V^T y)_{n-i+1}^2 \frac{\sigma_i(A^{-1})}{(1 + \lambda \sigma_i(A^{-1}))^2} &amp; \\<br />
 &amp; = \|(I + \lambda A^{-1})^{-1} y \|_2^2 \\<br />
 &amp; = \|A(A + \lambda I)^{-1} y\|_2^2 = B^2,<br />
\end{align*}<br />
where \(A = U \Sigma U^T,\) or if such a solution does not exist, \(0.\)</p>]]></content><author><name>swiftset</name></author><category term="Uncategorized" /><summary type="html"><![CDATA[((Caveat! I am not sure the manipulations done in this post are correct, but the gist is certainly there.))]]></summary></entry><entry><title type="html">Back of the envelope calculations of how fast your computer can do linear algebra operations</title><link href="https://www.cs.rpi.edu/~gittea/2014/01/23/back-of-the-envelope-calculations-of-how-fast-your-computer-can-do-linear-algebra-operations/" rel="alternate" type="text/html" title="Back of the envelope calculations of how fast your computer can do linear algebra operations" /><published>2014-01-23T15:28:14-05:00</published><updated>2014-01-23T15:28:14-05:00</updated><id>https://www.cs.rpi.edu/~gittea/2014/01/23/back-of-the-envelope-calculations-of-how-fast-your-computer-can-do-linear-algebra-operations</id><content type="html" xml:base="https://www.cs.rpi.edu/~gittea/2014/01/23/back-of-the-envelope-calculations-of-how-fast-your-computer-can-do-linear-algebra-operations/"><![CDATA[<p>Let’s talk about CPU speed, practically. By practically, I mean, how fast can your CPU do linear algebra operations. And by linear algebra operations, I mean matrix-matrix multiplies.</p>

<p>First, you need to calculate how many FLOPS your computer can do. The following formula comes in handy:<br />
\[<br />
\text{nFLOPS} = \text{cores} \cdot \frac{\text{clock cycles}}{\text{second}} \cdot \frac{\text{FLOPS}}{\text{cycle}}.<br />
\]<br />
You probably already know the number of cores in your computer, and the number of clock cyles. The interesting thing here is the number of FLOPS per cycle: this depends on the architecture of your CPU and what exactly you take to be the size of a float.</p>

<p>It’s standard to take a float to consist of 32 bits, so the number of FLOPS per cycle depends on how many multiples of 32 bits can fit into your registers. SSE capable CPUs have 128 bit registers, so can do 4 FLOPS per cycle (this is the most common set of CPUs). AVX capable CPUs have 256 bit registers, so can do 8 FLOPS per cycle (e.g. the latest Macbook Pros are AVX capable).</p>

<p>Putting these bits together, I get that my workstation, which has 2 hexa-core SSE-capable CPUS each running at 2 GHz achieves<br />
\[<br />
\text{nFLOPS} = (2*6) * (2*10^9)*4 = 96 \text{GFLOPS}.<br />
\]</p>

<p>The cost of a matrix-matrix multiply of two \(n\)-by-\(n\) matrices is essentially \(n^3\) floating point operations. Thus it should take this workstation about \(\frac{n^3}{96} * 10^{-9}\) seconds to do this multiply.</p>

<p>E.g., in my case, the predicted time of squaring two \(16\text{K} \times 16\text{K}\) matrices is about 42.6 seconds. A quick Matlab check shows it does take about 43 seconds.</p>]]></content><author><name>swiftset</name></author><category term="Uncategorized" /><summary type="html"><![CDATA[Let’s talk about CPU speed, practically. By practically, I mean, how fast can your CPU do linear algebra operations. And by linear algebra operations, I mean matrix-matrix multiplies.]]></summary></entry><entry><title type="html">A useful trick for computing gradients w.r.t. matrix arguments, with some examples</title><link href="https://www.cs.rpi.edu/~gittea/2013/11/12/a-useful-trick-for-computing-gradients-w-r-t-matrix-arguments-with-some-examples/" rel="alternate" type="text/html" title="A useful trick for computing gradients w.r.t. matrix arguments, with some examples" /><published>2013-11-12T19:56:52-05:00</published><updated>2013-11-12T19:56:52-05:00</updated><id>https://www.cs.rpi.edu/~gittea/2013/11/12/a-useful-trick-for-computing-gradients-w-r-t-matrix-arguments-with-some-examples</id><content type="html" xml:base="https://www.cs.rpi.edu/~gittea/2013/11/12/a-useful-trick-for-computing-gradients-w-r-t-matrix-arguments-with-some-examples/"><![CDATA[<p>I’ve spent hours this week and last week computing, recomputing, and checking expressions for matrix gradients of functions. It turns out that except in the simplest of cases, the most painfree method for finding such gradients is to use the Frechet derivative (this is one of the few concrete benefits I derived from the differential geometry course I took back in grad school).</p>

<p>Remember that the Frechet derivative of a function \(f : X \rightarrow \mathbb{R}\) at a point \(x\) is defined as the unique linear operator \(d\) that is tangent to \(f\) at \(x\), i.e. that satisfies<br />
\[<br />
f(x+h) = f(x) + d(h) + o(\|h\|).<br />
\]<br />
This definition of differentiability makes sense whenever \(X\) is a normed linear space. If \(f\) has a gradient, then the Frechet derivative exists and the gradient satisfies the relation \(d(h) = \langle \nabla f(x), h \rangle.\)</p>

<h3 id="simple-application">Simple application</h3>

<p>As an example application, lets compute the gradient of the function<br />
\[<br />
f(X) = \langle A, XX^T \rangle := \mathrm{trace}(A^T XX^T) = \sum_{ij} A_{ij} (XX^T)_{ij}<br />
\]<br />
over the linear space of \(m\) by \(n\) real-valued matrices equipped with the Frobenius norm. First we can expand out \(f(X+H)\) as<br />
\[<br />
f(X + H) = \langle A, (X+H)(X+H)^T \rangle = \langle A, XX^T + XH^T + HX^T + HH^T \rangle<br />
\]<br />
Now we observe that the terms which involve more than one power of \(H\) are \(O(\|H\|^2) = o(\|H\|)\) as \(H \rightarrow 0\), so<br />
\[<br />
f(X + H) = f(X) + \langle A, XH^T + HX^T \rangle + o(\|H\|).<br />
\]<br />
It follows that<br />
\[<br />
d(H) = \langle A, XH^T + HX^T \rangle = \mathrm{trace}(A^TXH^T) + \mathrm{trace}(A^THX^T),<br />
\]<br />
which is clearly a linear function of \(H\) as desired. To write this in a way that exposes the gradient, we use the<br />
cyclicity properties of the trace, and exploit its invariance under transposes to see that<br />
\begin{align}<br />
d(H) &amp; = \mathrm{trace}(HX^TA) + \mathrm{trace}(X^TA^T H) \\<br />
 &amp; = \mathrm{trace}(X^TAH) + \mathrm{trace}(X^TA^T H) \\<br />
&amp; = \langle AX, H \rangle + \langle A^TX, H \rangle \\<br />
&amp; = \langle (A + A^T)X, H \rangle.<br />
\end{align}<br />
The gradient of \(f\) at \(X\) is evidently \((A + A^T)X\).</p>

<h3 id="more-complicated-application">More complicated application</h3>

<p>If you have the patience to work through a lot of algebra, you could probably calculate the above gradient component by component using the standard rules of differential calculus, then back out the simple matrix expression \((A + A^T)X\). But what if we partitioned \(X\) into \(X = [\begin{matrix}X_1^T &amp; X_2^T \end{matrix}]^T\) and desired the derivative of<br />
\[<br />
f(X_1, X_2) = \mathrm{trace}\left(A \left[\begin{matrix} X_1 \\ X_2 \end{matrix}\right] \left[\begin{matrix}X_1 \\ X_2 \end{matrix} \right]^T\right)<br />
\]<br />
with respect to \(X_2\)? Then the bookkeeping necessary becomes even more tedious if you want to compute component by component derivatives (I imagine, not having attempted it). On the other hand, the Frechet derivative route is not significantly more complicated.</p>

<p>Some basic manipulations allow us to claim<br />
\begin{align}<br />
f(X_1, X_2 + H) &amp; = \mathrm{trace}\left(A \left[\begin{matrix} X_1 \\ X_2 + H \end{matrix}\right] \left[\begin{matrix}X_1 \\ X_2 + H \end{matrix} \right]^T\right) \\<br />
 &amp; = f(X_1, X_2) + \mathrm{trace}\left(A \left[\begin{matrix} 0 &amp; X_1 H^T \\<br />
 H X_2^T &amp; H X_2^T + X_2 H^T + H H^T \end{matrix} \right]\right)<br />
\end{align}<br />
Once again we drop the \(o(\|H\|)\) terms to see that<br />
\[<br />
d(H) = \mathrm{trace}\left(A \left[\begin{matrix} 0 &amp; X_1 H^T \\<br />
 H X_2^T &amp; H X_2^T + X_2 H^T \end{matrix} \right]\right).<br />
\]<br />
To find a simple expression for the gradient, we partition \(A\) (conformally with our partitioning of \(X\) into \(X_1\) and \(X_2\)) as<br />
\[<br />
A = \left[\begin{matrix} A_1 &amp; A_2 \\ A_3 &amp; A_4 \end{matrix} \right].<br />
\]<br />
Given this partitioning,<br />
\begin{align}<br />
d(H) &amp; = \mathrm{trace}\left(\left[\begin{matrix}<br />
A_2 H X_1^T &amp; \\<br />
&amp; A_3 X_1 H^T + A_4 H X_2^T + A_4 X_2 H^T<br />
\end{matrix}\right] \right) \\<br />
 &amp; = \langle A_2^TX_1, H \rangle + \langle A_3X_1, H \rangle + \langle A_4^T X_2, H \rangle + \langle A_4X_2, H \rangle \\<br />
 &amp; = \langle (A_2^T + A_3)X_1 + (A_4^T + A_4)X_2, H \rangle.<br />
\end{align}<br />
The first equality comes from noting that the trace of a block matrix is simply the trace of its diagonal parts, and the second comes from manipulating the traces using their cyclicity and invariance to transposes.</p>

<p>Thus \(\nabla_{X_2} f(X_1, X_2) = (A_2^T + A_3)X_1 + (A_4^T + A_4)X_2.\)</p>

<h3 id="a-masterclass-application">A masterclass application</h3>

<p>Maybe you didn’t find the last example convincing. Here’s a function I needed to compute the matrix gradient for— a task which I defy you to accomplish using standard calculus operations—:<br />
\[<br />
f(V) = \langle 1^T K^T, \log(1^T \mathrm{e}^{VV^T}) \rangle = \log(1^T \mathrm{e}^{VV^T})K1.<br />
\]<br />
Here, \(K\) is an \(n \times n\) matrix (nonsymmetric in general), \(V\) is an \(n \times d\) matrix, and \(1\) is a column vector of ones of length \(n\). The exponential \(\mathrm{e}^{VV^T}\) is computed entrywise, as is the \(\log\).</p>

<p>To motivate why you might want to take the gradient of this function, consider the situation that \(K_{ij}\) measures how similar items \(i\) and \(j\) are in a nonsymmetric manner, and the rows of \(V\) are coordinates for representations of the items in Euclidean space. Then \((1^T K)_j\) measures how similar item \(j\) is to all the items, and<br />
\[<br />
(1^T \mathrm{e}^{VV^T})_j = \sum_{\ell=1}^n \mathrm{e}^{v_\ell^T v_j}<br />
\]<br />
is a measure of how similar the embedding \(v_j\) is to the embeddings of all the items. Thus, if we constrain all the embeddings to have norm 1, maximizing \(f(V)\) with respect to \(V\) ensures that the embeddings capture the item similarities in some sense. (Why do you care about this particular sense? That’s another story altogether.)</p>

<p>Ignoring the constraints (you could use a projected gradient method for the optimization problem), we’re now interested in finding the gradient of \(f\). In the following, I use the notation \(A \odot B\) to indicate the pointwise product of two matrices.<br />
\begin{align}<br />
f(V + H) &amp; = \langle 1^T K, \log(1^T \mathrm{e}^{(V+H)(V+H)^T} \rangle \\<br />
 &amp; = \langle 1^T K, \log(1^T [\mathrm{e}^{VV^T} \odot \mathrm{e}^{VH^T} \odot \mathrm{e}^{HV^T} \odot \mathrm{e}^{HH^T} ]) \rangle<br />
\end{align}<br />
One can use the series expansion of the exponential to see that<br />
\begin{align}<br />
\mathrm{e}^{VH^T} &amp; = 11^T + VH^T + o(\|H\|), \\<br />
\mathrm{e}^{HV^T} &amp; = 11^T + HV^T + o(\|H\|), \text{ and}\\<br />
\mathrm{e}^{HH^T} &amp; = 11^T + o(\|H\|).<br />
\end{align}<br />
It follows that<br />
\begin{multline}<br />
f(V + H) = \langle 1^T K, \log(1^T [\mathrm{e}^{VV^T} \odot (11^T + VH^T + o(\|H\|)) \\<br />
 \odot (11^T + HV^T + o(\|H\|)) \odot (11^T + o(\|H\|)) ]) \rangle.<br />
\end{multline}<br />
This readily simplifies to<br />
\begin{align}<br />
f(V + H) &amp; = \langle 1^T K, \log(1^T [\mathrm{e}^{VV^T} \odot(11^T + VH^T + HV^T + o(\|H\|) )]) \rangle \\<br />
 &amp; = \langle 1^T K, \log(1^T [\mathrm{e}^{VV^T} + e^{VV^T} \odot (VH^T + HV^T) + o(\|H\|) )]) \rangle<br />
\end{align}<br />
Now recall the linear approximation of \(\log\):<br />
\[<br />
\log(x) = \log(x_0) + \frac{1}{x_0} (x-x_0) + o(|x- x_0|^2).<br />
\]<br />
Apply this approximation pointwise to conclude that<br />
\begin{multline}<br />
f(V + H) = \langle 1^T K, \log(1^T \mathrm{e}^{VV^T}) + \\<br />
\{1^T \mathrm{e}^{VV^T}\}^{-1}\odot (1^T [\mathrm{e}^{VV^T} \odot (VH^T + HV^T) + o(\|H\|)]) \rangle,<br />
\end{multline}<br />
where \(\{x\}^{-1}\) denotes the pointwise inverse of a vector.<br />
Take \(D\) to be the diagonal matrix with diagonal entries given by \(1^T \mathrm{e}^{VV^T}\). We have shown that<br />
\[<br />
f(V + H) = f(V) + \langle K^T1, D^{-1} [\mathrm{e}^{VV^T} \odot (VH^T + HV^T)]1 \rangle + o(\|H\|),<br />
\]<br />
so<br />
\begin{align}<br />
d(H) &amp; = \langle K^T1, D^{-1} [\mathrm{e}^{VV^T} \odot (VH^T + HV^T)]1 \rangle \\<br />
 &amp; = \langle D^{-1}K^T 11^T, \mathrm{e}^{VV^T} \odot (VH^T + HV^T) \rangle \\<br />
 &amp; = \langle \mathrm{e}^{VV^T} \odot D^{-1}K^T 11^T, (VH^T + HV^T) \rangle.<br />
\end{align}<br />
The second inequality follows from the standard properties of inner products and the third from the observation that<br />
\[<br />
\langle A, B\odot C \rangle = \sum_{ij} A_{ij}*B_{ij}*C_{ij} = \langle B \odot A, C \rangle.<br />
\]<br />
Finally, manipulations in the vein of the two preceding examples allow us to claim that<br />
\[<br />
\nabla_V f(V) = [\mathrm{e}^{VV^T} \odot (11^T K D^{-1} + D^{-1} K^T 11^T)] V.<br />
\]</p>

<p>As a caveat, note that if instead \(f(V) = \log(1^T \mathrm{e}^{VV^T} ) K^T 1\), then one should substitute \(K\) for \(K^T\) in the last expression.</p>]]></content><author><name>swiftset</name></author><category term="Uncategorized" /><summary type="html"><![CDATA[I’ve spent hours this week and last week computing, recomputing, and checking expressions for matrix gradients of functions. It turns out that except in the simplest of cases, the most painfree method for finding such gradients is to use the Frechet derivative (this is one of the few concrete benefits I derived from the differential geometry course I took back in grad school).]]></summary></entry><entry><title type="html">Quick note on the Chen, Chi, Goldsmith covariance sketching paper</title><link href="https://www.cs.rpi.edu/~gittea/2013/10/07/quick-note-on-the-chen-chi-goldsmith-covariance-sketching-paper/" rel="alternate" type="text/html" title="Quick note on the Chen, Chi, Goldsmith covariance sketching paper" /><published>2013-10-07T15:19:12-04:00</published><updated>2013-10-07T15:19:12-04:00</updated><id>https://www.cs.rpi.edu/~gittea/2013/10/07/quick-note-on-the-chen-chi-goldsmith-covariance-sketching-paper</id><content type="html" xml:base="https://www.cs.rpi.edu/~gittea/2013/10/07/quick-note-on-the-chen-chi-goldsmith-covariance-sketching-paper/"><![CDATA[<p><strong>NB</strong>: I will update this post as I read the paper, in case it turns out that the first issue I raised is not legitimately a concern.</p>

<p>Covariance estimation (and the natural extension, precision estimation) has always been an interesting topic for me because it (can) represent a concise, concrete, and very broadly applicable instance of applied nonasymptotic random matrix theory. Likewise, I’m also quite interested in matrix sketching algorithms. Thus I was very excited to see the latest preprint by <a href="http://arxiv.org/abs/1310.0807" title="Exact and Stable Covariance Estimation from Quadratic Sampling via Convex Programming">Chen, Chi, and Goldsmith on arxiv</a> which presents a convex optimization algorithm for recovering covariance matrices from randomized sketches obtained in a streaming manner. Their convex optimization problem is essentially the <a href="https://oldwww.math.ucdavis.edu/~strohmer/papers/2011/ExactPR.pdf" title="PhaseLift: Exact and Stable Signal Recovery from Magnitude Measurements via Convex Programming">PhaseLift</a> formulation used for recovering phase from magnitude, but their proof shows that it works for covariance matrix recovery.</p>

<p>I have only just started reading this paper, and I’m still excited, but I have two concerns already: first, it is not clear to me that the algorithm they propose is actually the algorithm they provide a guarantee for! At the least, the text must be corrected to make it clear that this is indeed the case. To be more precise, their algorithm is to compute a few random sketching vectors ahead of time, then as the rows of the matrix come in, compute the magnitude of the projection of each row onto *one* randomly chosen sketching vector. The measurement model described mathematically seems to compute the magnitude of the projection of each row onto *each* of the sketching vectors. Big difference there.</p>

<p>Second, their algorithm provides a Frobenius norm guarantee, which is par for the course, but they make claims about things like subspace detection, for which afaik, Frobenius norm guarantees are too weak to really be of interest. But here, this may be a matter of preference, and practitioners probably don’t care about sharp guarantees as long as it works in practice and has at least a semblance of theoretical support.</p>]]></content><author><name>swiftset</name></author><category term="Uncategorized" /><summary type="html"><![CDATA[NB: I will update this post as I read the paper, in case it turns out that the first issue I raised is not legitimately a concern.]]></summary></entry></feed>