# Source code for polylearn.kernels

```# Author: Vlad Niculae <vlad@vene.ro>

from sklearn.metrics.pairwise import polynomial_kernel
from sklearn.utils.extmath import safe_sparse_dot
from scipy.sparse import issparse

import numpy as np

[docs]def safe_power(X, degree=2):
"""Element-wise power supporting both sparse and dense data.

Parameters
----------
X : ndarray or sparse
The array whose entries to raise to the power.

degree : int, default: 2
The power to which to raise the elements.

Returns
-------

X_ret : ndarray or sparse
Same shape as X, but (x_ret)_ij = (x)_ij ^ degree
"""
if issparse(X):
if hasattr(X, 'power'):
return X.power(degree)
else:
# old scipy
X = X.copy()
X.data **= degree
return X
else:
return X ** degree

def _D(X, P, degree=2):
"""The "replacement" part of the homogeneous polynomial kernel.

D[i, j] = sum_k [(X_ik * P_jk) ** degree]
"""
return safe_sparse_dot(safe_power(X, degree), P.T ** degree)

[docs]def homogeneous_kernel(X, P, degree=2):
"""Convenience alias for homogeneous polynomial kernel between X and P::

K_P(x, p) = <x, p> ^ degree

Parameters
----------
X : ndarray of shape (n_samples_1, n_features)

Y : ndarray of shape (n_samples_2, n_features)

degree : int, default 2

Returns
-------
Gram matrix : array of shape (n_samples_1, n_samples_2)
"""
return polynomial_kernel(X, P, degree=degree, gamma=1, coef0=0)

[docs]def anova_kernel(X, P, degree=2):
"""ANOVA kernel between X and P::

K_A(x, p) = sum_i1>i2>...>id x_i1 p_i1 x_i2 p_i2 ... x_id p_id

See John Shawe-Taylor and Nello Cristianini,
Kernel Methods for Pattern Analysis section 9.2.

Parameters
----------
X : ndarray of shape (n_samples_1, n_features)

Y : ndarray of shape (n_samples_2, n_features)

degree : int, default 2

Returns
-------
Gram matrix : array of shape (n_samples_1, n_samples_2)
"""
if degree == 2:
K = homogeneous_kernel(X, P, degree=2)
K -= _D(X, P, degree=2)
K /= 2
elif degree == 3:
K = homogeneous_kernel(X, P, degree=3)
K -= 3 * _D(X, P, degree=2) * _D(X, P, degree=1)
K += 2 * _D(X, P, degree=3)
K /= 6
else:
raise NotImplementedError("ANOVA kernel for degree >= 4 not yet "
"implemented efficiently.")
return K

def _poly_predict(X, P, lams, kernel, degree=2):
if kernel == "anova":
K = anova_kernel(X, P, degree)
elif kernel == "poly":
K = homogeneous_kernel(X, P, degree)
else:
raise ValueError(("Unsuppported kernel: {}. Use one "
"of {{'anova'|'poly'}}").format(kernel))

return np.dot(K, lams)
```