r""" Compute left and right factors corresponding to the Nystroem method on the Gaussian kernel :math:`K(x^s_i, x^t_j) = \exp(-\|x^s_i-x^t_j\|^2/2\sigma^2)`. The Nystroem approximation is computed by sampling :math:`\min(n, \lceil(c / 2))\rceil)` components in each distribution, where :m
(X_s, X_t, anchors=50, sigma=1.0, random_state=None)
| 528 | |
| 529 | |
| 530 | def kernel_nystroem(X_s, X_t, anchors=50, sigma=1.0, random_state=None): |
| 531 | r""" |
| 532 | Compute left and right factors corresponding to the Nystroem method on the Gaussian kernel :math:`K(x^s_i, x^t_j) = \exp(-\|x^s_i-x^t_j\|^2/2\sigma^2)`. |
| 533 | The Nystroem approximation is computed by sampling :math:`\min(n, \lceil(c / 2))\rceil)` components in each distribution, |
| 534 | where :math:`n` is the number of samples in the distribution and :math:`c` the total number of anchor points. |
| 535 | |
| 536 | Parameters |
| 537 | ---------- |
| 538 | X_s : array-like, shape (n_samples_a, dim) |
| 539 | samples in the source domain |
| 540 | X_t : array-like, shape (n_samples_b, dim) |
| 541 | samples in the target domain |
| 542 | anchors : int, optional |
| 543 | The total number of anchors sampled for the Nystroem approximation (anchors/2 in each distribution), default 50. |
| 544 | sigma : float, optional |
| 545 | The standard deviation parameter for the Gaussian kernel. |
| 546 | random_state : int, optional |
| 547 | The random state for sampling the components in each distribution. |
| 548 | |
| 549 | Returns |
| 550 | ------- |
| 551 | left_factor : array-like, shape (n_samples_a, dim_r) |
| 552 | Left factor of Nystroem |
| 553 | right_factor : array-like, shape (n_samples_b, dim_r) |
| 554 | Right factor of Nystroem |
| 555 | """ |
| 556 | nx = get_backend(X_s, X_t) |
| 557 | if random_state is not None: |
| 558 | nx.seed(random_state) |
| 559 | |
| 560 | n, m = X_s.shape[0], X_t.shape[0] |
| 561 | |
| 562 | if not isinstance(anchors, int) or anchors < 2: |
| 563 | raise ValueError("anchors must be an integer >= 2") |
| 564 | |
| 565 | n_components_source = min(n, anchors // 2) |
| 566 | n_components_target = min(m, anchors // 2) |
| 567 | # draw n_components/2 points in each distribution |
| 568 | inds_source = nx.randperm(n) # sample n_components_source uniformly |
| 569 | basis_source = X_s[inds_source[:n_components_source]] |
| 570 | |
| 571 | inds_target = nx.randperm(m) |
| 572 | basis_target = X_t[inds_target[:n_components_target]] |
| 573 | |
| 574 | basis = nx.concatenate((basis_source, basis_target)) |
| 575 | |
| 576 | Mzz = dist(basis, metric="sqeuclidean") # compute \|z_i - z_j\|_2^2 |
| 577 | basis_kernel = nx.exp(-Mzz / (2.0 * sigma**2)) |
| 578 | |
| 579 | normalization = nx.pinv(basis_kernel, hermitian=True) |
| 580 | |
| 581 | Mxz = dist(X_s, basis, metric="sqeuclidean") |
| 582 | Myz = dist(X_t, basis, metric="sqeuclidean") |
| 583 | |
| 584 | left_factor = nx.exp(-Mxz / (2.0 * sigma**2)) @ normalization |
| 585 | right_factor = nx.exp(-Myz / (2.0 * sigma**2)) |
| 586 | |
| 587 | return left_factor, right_factor # left_factor @ right_factor.T approx K |
no test coverage detected