A fast, vectorized way to compute pairwise l2 distances between rows in `X` and `Y`. Notes ----- An entry of the pairwise Euclidean distance matrix for two vectors is .. math:: d[i, j] &= \sqrt{(x_i - y_i) @ (x_i - y_i)} \\\\ &= \sqrt{sum (x_i
(X, Y)
| 308 | |
| 309 | |
| 310 | def pairwise_l2_distances(X, Y): |
| 311 | """ |
| 312 | A fast, vectorized way to compute pairwise l2 distances between rows in `X` |
| 313 | and `Y`. |
| 314 | |
| 315 | Notes |
| 316 | ----- |
| 317 | An entry of the pairwise Euclidean distance matrix for two vectors is |
| 318 | |
| 319 | .. math:: |
| 320 | |
| 321 | d[i, j] &= \sqrt{(x_i - y_i) @ (x_i - y_i)} \\\\ |
| 322 | &= \sqrt{sum (x_i - y_j)^2} \\\\ |
| 323 | &= \sqrt{sum (x_i)^2 - 2 x_i y_j + (y_j)^2} |
| 324 | |
| 325 | The code below computes the the third line using numpy broadcasting |
| 326 | fanciness to avoid any for loops. |
| 327 | |
| 328 | Parameters |
| 329 | ---------- |
| 330 | X : :py:class:`ndarray <numpy.ndarray>` of shape `(N, C)` |
| 331 | Collection of `N` input vectors |
| 332 | Y : :py:class:`ndarray <numpy.ndarray>` of shape `(M, C)` |
| 333 | Collection of `M` input vectors. If None, assume `Y` = `X`. Default is |
| 334 | None. |
| 335 | |
| 336 | Returns |
| 337 | ------- |
| 338 | dists : :py:class:`ndarray <numpy.ndarray>` of shape `(N, M)` |
| 339 | Pairwise distance matrix. Entry (i, j) contains the `L2` distance between |
| 340 | :math:`x_i` and :math:`y_j`. |
| 341 | """ |
| 342 | D = -2 * X @ Y.T + np.sum(Y ** 2, axis=1) + np.sum(X ** 2, axis=1)[:, np.newaxis] |
| 343 | D[D < 0] = 0 # clip any value less than 0 (a result of numerical imprecision) |
| 344 | return np.sqrt(D) |