def fit(self, X, y=None):
N = X.shape[<NUM_LIT:0>]<EOL>if y is None:<EOL><INDENT>y = np.zeros(N)<EOL><DEDENT>self.classes = list(set(y))<EOL>self.classes.sort()<EOL>self.n_classes = len(self.classes)<EOL>if not self.sigma:<EOL><INDENT>self.sigma = median_kneighbour_distance(X)<EOL>self.gamma = self.sigma**-<NUM_LIT:2><EOL><DEDENT>if not self.gamma:<EOL><INDENT>self.gamma = self.sigma**-<NUM_LIT:2><EOL><DEDENT>if not self.rho:<EOL><INDENT>self.rho = <NUM_LIT:0.1><EOL><DEDENT>if self.kernel_pos is None:<EOL><INDENT>B = min(self.n_kernels_max, N)<EOL>kernel_idx = np.random.permutation(N)<EOL>self.kernel_pos = X[kernel_idx[:B]]<EOL><DEDENT>else:<EOL><INDENT>B = self.kernel_pos.shape[<NUM_LIT:0>]<EOL><DEDENT>Phi = metrics.pairwise.rbf_kernel(X, self.kernel_pos, self.gamma)<EOL>theta = {}<EOL>Phi_PhiT = np.dot(Phi.T, Phi)<EOL>inverse_term = np.linalg.inv(Phi_PhiT + self.rho*np.eye(B))<EOL>for c in self.classes:<EOL><INDENT>m = (y == c).astype(int)<EOL>theta[c] = np.dot(inverse_term, np.dot(Phi.T, m))<EOL><DEDENT>self.theta = theta<EOL>
Fit the inlier model given training data.

This function attempts to choose reasonable defaults for parameters
sigma and rho if none are specified, which could then be adjusted
to improve performance.

Parameters
----------
X : array
    Examples of inlier data, of dimension N times d (rows are
    examples, columns are data dimensions)
y : array, optional
    If the inliers have multiple classes, then y contains the class
    assignments as a vector of length N. If this is specified then
    the model will attempt to assign test data to one of the inlier
    classes or to the outlier class.