# Author: Vlad Niculae <vlad@vene.ro>
# License: Simplified BSD
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)