function [patterns, targets, label] = spectral_k_means(train_patterns, train_targets, params, plot_on) %Reduce the number of data points using the spectral k-means algorithm %The k largest eigenvectors of the kernel matrix of examples are clustered %using k-means % %Inputs: % train_patterns - Input patterns % train_targets - Input targets % params - [Number of output data points, Kernel type, kernel parameter, cluster_type] % Kernel can be one of: Gauss, RBF (Same as Gauss), Poly, Sigmoid, or Linear % The kernel parameters are: % RBF kernel - Gaussian width (One parameter) % Poly kernel - Polynomial degree % Sigmoid - The slope and constant of the sigmoid (in the format [1 2], with no separating commas) % Linear - None needed % Clustering type can be Multicut (Meila-Shi) or NJW (Ng, Jordan, Weiss) % plot_on - Unused % %Outputs % patterns - New patterns % targets - New targets % label - The labels given for each of the original patterns if (nargin < 4), plot_on = 0; end %Get parameters [Nmu, kernel, kernel_params, clustering_type] = process_params(params); max_iter = 1000; [Ndim, Nf] = size(train_patterns); label = zeros(1,Nf); %Kernelize the training patterns y = kernelize(kernel, kernel_params, train_patterns, train_patterns); D = diag(sum(y)); switch lower(clustering_type) case 'multicut' y = inv(D)*y; [v, d] = eig(y); kernel_patterns = v(end-Nmu+1:end, :); case 'njw' sqD = sqrtm(D); L = sqD*y*sqD; [v, d] = eig(L); kernel_patterns = v(end-Nmu+1:end, :); kernel_patterns = kernel_patterns ./ (sum(kernel_patterns'.^2)'*ones(1, Nf)); otherwise error('Unknown clustering type'); end [p, t, label] = k_means(kernel_patterns, train_targets, Nmu, []); Ul = unique(label); patterns= zeros(Ndim, length(Ul)); targets = zeros(1, length(Ul)); for i = 1:length(Ul) patterns(:, i) = mean(train_patterns(:, find(label == Ul(i)))')'; targets(:, i) = mean(train_targets(find(label == Ul(i)))')'; end %END kernel k-means function y = kernelize(kernel, kernel_params, patterns, base_patterns) Nf = size(patterns, 2); Nb = size(base_patterns, 2); y = zeros(Nb, Nf); switch kernel, case {'Gauss','RBF'}, for i = 1:Nf, y(:,i) = exp(-sum((base_patterns-patterns(:,i)*ones(1,Nb)).^2)'/(2*kernel_params^2)); end case {'Poly', 'Linear'} if strcmp(kernel, 'Linear') kernel_params = 1; end for i = 1:Nf, y(:,i) = (base_patterns'*patterns(:,i) + 1).^kernel_params; end case 'Sigmoid' kernel_params = str2num(kernel_params); if (length(kernel_params) ~= 2) error('This kernel needs two parameters to operate!') end for i = 1:Nf, y(:,i) = tanh(base_patterns'*patterns(:,i)*kernel_params(1)+kernel_params(2)); end otherwise error('Unknown kernel. Can be Gauss, Linear, Poly, or Sigmoid.') end