├── OMVFS.m └── README.md /OMVFS.m: -------------------------------------------------------------------------------- 1 | function [w, run_time,Loss] = OMVFS(X, option) 2 | % Multi view feature selection 3 | % X cell array, contains multi view data. each matrix is N by d_v 4 | % option.block_size 5 | % option.buffer_size 6 | % option.beta vector of size n_v 7 | % option.num_cluster 8 | % option.pass 9 | % option.maxiter 10 | % option.tol 11 | num_passes = option.pass; 12 | max_buffer_size = option.buffer_size; 13 | beta = option.beta; 14 | alpha = option.alpha; 15 | lambda = option.lambda; 16 | maxIter = option.maxiter; 17 | num_clusters = option.num_cluster; 18 | block_size = option.block_size; 19 | tol = option.tol; 20 | gamma = option.gamma; 21 | num_views = numel(X); 22 | num_feature = zeros(num_views,1); 23 | total = size(X{1},1); 24 | for i = 1:num_views 25 | num_feature(i) = size(X{i},2); 26 | end 27 | 28 | current_buffer_size = 0; 29 | 30 | % Initialize U and V 31 | U_buff = []; 32 | V = cell(num_views,1); 33 | for i = 1:num_views 34 | V{i} = rand(num_feature(i),num_clusters); 35 | end 36 | 37 | A = cell(num_views,1); 38 | B = cell(num_views,2); 39 | for i =1:num_views 40 | A{i} = zeros(size(V{i})); 41 | B{i} = zeros(num_clusters, num_clusters); 42 | end 43 | 44 | num_block = ceil(total/block_size); 45 | Loss = zeros(num_passes, num_block); 46 | 47 | index_sofa = 0; 48 | U_sofar = cell(num_views,1); 49 | for i = 1:num_views 50 | U_sofa{i} = []; 51 | end 52 | for pass = 1:num_passes 53 | X_buff = cell(num_views,1); 54 | for i = 1:num_views 55 | X_buff{i} = []; 56 | end 57 | for block_index = 1:num_block 58 | data_range = (block_index-1)*block_size+1:block_index*block_size; 59 | if block_index == num_block 60 | data_range = (block_index-1)*block_size+1:total; 61 | end 62 | 63 | X_i = cell(num_views,1); 64 | 65 | D = cell(num_views, 1); 66 | L = cell(num_views, 1); 67 | DD = cell(num_views, 1); 68 | SS = cell(num_views, 1); 69 | for i = 1:num_views 70 | if size(X_buff{i},1) + numel(data_range) <= max_buffer_size 71 | X_buff{i} = [X_buff{i}; X{i}(data_range,:)]; 72 | else 73 | X_buff{i} = [X_buff{i}; X{i}(data_range,:)]; 74 | X_buff{i} = X_buff{i}(end- max_buffer_size+1:end,:); 75 | end 76 | X_i{i} = X{i}(data_range,:); 77 | [L{i}, DD{i}, SS{i}] = construct_Laplacian(X_buff{i}); 78 | D{i} = diag(sparse(ones(1,num_feature(i)))); 79 | end 80 | 81 | for i = 1:num_views 82 | U_buff{i} = rand(size(X_buff{i},1), num_clusters); 83 | U_i{i} = U_buff{i}(end-numel(data_range)+1:end,:); 84 | if size( U_buff{i},1 ) > max_buffer_size 85 | U_buff{i} = U_buff{i}(end- max_buffer_size+1:end,:); 86 | end 87 | U_sofar{i} = [U_sofar{i}; U_i{i}]; 88 | end 89 | U_star_buff = rand(size(U_buff{1})); 90 | index_sofa = index_sofa + numel(data_range); 91 | 92 | 93 | M = alpha(1)*L{1}; 94 | for ii = 2:num_views 95 | M = M + alpha(ii)*L{ii}; 96 | end 97 | M_plus = 0.5*(abs(M) + M); 98 | M_minus = 0.5*(abs(M) - M); 99 | 100 | iter = 0; 101 | converge = 0; 102 | step_u = 0.5; 103 | step_v = ones(num_views,1); 104 | beta_search = 0.1; 105 | while iter < maxIter && converge ==0 106 | % update U_star_buff 107 | U_star_buff = lambda(1)*U_buff{1}; 108 | for i = 2:num_views 109 | U_star_buff = U_star_buff + lambda(i)*U_buff{2}; 110 | end 111 | U_star_buff = U_star_buff/sum(lambda); 112 | 113 | % Update U_i 114 | for i = 1:num_views 115 | upper_tmp = X_buff{i}*V{i} + U_star_buff + gamma*U_buff; 116 | lower_tmp = U_buff{i}*(V{i}'*V{i}) + alpha(i)*L{i}*U_buff{i} + U_buff{i}+ gamma*U_buff*(U_buff'*U_buff); 117 | U_buff{i} = U_buff{i}.*(upper_tmp./max(lower_tmp,1e-20)).^step_u; 118 | end 119 | U_i{i} = U_buff(end-numel(data_range)+1:end,:); 120 | 121 | % Update V_i 122 | for i = 1:num_views 123 | upper_tmp = A{i} + X_i{i}' * U_i{i}; 124 | lower_tmp = V{i} * (B{i} + (U_i{i}' * U_i{i})); 125 | % construct D 126 | D{i} = diag(sparse(0.5./max(sqrt(sum(V{i}.^2,2)),1e-20))); 127 | lower_tmp = lower_tmp + beta(i) * D{i} * V{i}; 128 | V{i} = V{i} .* (upper_tmp./max(lower_tmp, 1e-20)).^step_u; 129 | end 130 | 131 | for i = 1:num_views 132 | U_sofar{i}(data_range,:) = U_i{i}; 133 | end 134 | iter = iter + 1; 135 | end 136 | log = 0; 137 | % Update A and B 138 | for i = 1:num_views 139 | A{i} = A{i} + X_i{i}' * U_i{i}; 140 | B{i} = B{i} + U_i{i}' * U_i{i}; 141 | end 142 | fprintf('Done with block %d in %d iterations and log is %d\n', block_index, iter, log); 143 | end 144 | fprintf('Done with pass %d\n', pass); 145 | end 146 | for i = 1:num_views 147 | w{i} = sqrt(sum(V{i}.^2,2)); 148 | end 149 | end 150 | 151 | function [result] = L21(X) 152 | % L2,1 norm of X, the sum of row norms 153 | result = sum(sqrt(sum(X.^2,2))); 154 | end 155 | 156 | function [L,V,S] = construct_Laplacian(X) 157 | n=size(X,1); 158 | S = kernelmatrix(X,1); 159 | V = zeros(size(S)); 160 | for i = 1:size(V,1) 161 | V(i,i) = sum(S(:,i)); 162 | end 163 | L = V - S; 164 | end 165 | 166 | function K = kernelmatrix(coord, sig) 167 | n=size(coord,1); 168 | K=coord*coord'/sig^2; 169 | d=diag(K); 170 | K=K-ones(n,1)*d'/2; 171 | K=K-d*ones(1,n)/2; 172 | K=exp(K); 173 | end 174 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Online-Unsupervised-Multiview-Feature-Selection 2 | 3 | This project contains the source code for paper 4 | Weixiang Shao, Lifang He, Chun-Ta Lu, Xiaokai Wei, Philip S. Yu Online Unsupervised Multi-view Feature Selection, ICDM 2016 5 | The full version of this paper can also be found as arXiv:1609.08286 https://arxiv.org/abs/1609.08286 6 | --------------------------------------------------------------------------------