|
a |
|
b/MLFre/example_tree_LeastR.m |
|
|
1 |
clear; |
|
|
2 |
addpath(genpath([pwd '/DPC'])); |
|
|
3 |
|
|
|
4 |
% This is an example for running the function tree_LeastR |
|
|
5 |
% |
|
|
6 |
% Problem: |
|
|
7 |
% |
|
|
8 |
% min 1/2 || A x - y||^2 + z * sum_j w_j ||x_{G_j}|| |
|
|
9 |
% |
|
|
10 |
% G_j's are nodes with tree structure |
|
|
11 |
% |
|
|
12 |
% The tree structured group information is contained in |
|
|
13 |
% opts.ind, which is a 3 x nodes matrix, where nodes denotes the number of |
|
|
14 |
% nodes of the tree. |
|
|
15 |
% |
|
|
16 |
% opts.ind(1,:) contains the starting index |
|
|
17 |
% opts.ind(2,:) contains the ending index |
|
|
18 |
% opts.ind(3,:) contains the corresponding weight (w_j) |
|
|
19 |
% |
|
|
20 |
% Note: |
|
|
21 |
% 1) If each element of x is a leaf node of the tree and the weight for |
|
|
22 |
% this leaf node are the same, we provide an alternative "efficient" input |
|
|
23 |
% for this kind of node, by creating a "super node" with |
|
|
24 |
% opts.ind(1,1)=-1; opts.ind(2,1)=-1; and opts.ind(3,1)=the common weight. |
|
|
25 |
% |
|
|
26 |
% 2) If the features are well ordered in that, the features of the left |
|
|
27 |
% tree is always less than those of the right tree, opts.ind(1,:) and |
|
|
28 |
% opts.ind(2,:) contain the "real" starting and ending indices. That is to |
|
|
29 |
% say, x( opts.ind(1,j):opts.ind(2,j) ) denotes x_{G_j}. In this case, |
|
|
30 |
% the entries in opts.ind(1:2,:) are within 1 and n. |
|
|
31 |
% |
|
|
32 |
% |
|
|
33 |
% If the features are not well ordered, please use the input opts.G for |
|
|
34 |
% specifying the index so that |
|
|
35 |
% x( opts.G ( opts.ind(1,j):opts.ind(2,j) ) ) denotes x_{G_j}. |
|
|
36 |
% In this case, the entries of opts.G are within 1 and n, and the entries of |
|
|
37 |
% opts.ind(1:2,:) are within 1 and length(opts.G). |
|
|
38 |
% |
|
|
39 |
%% Related papers |
|
|
40 |
% |
|
|
41 |
% [1] Jun Liu and Jieping Ye, Moreau-Yosida Regularization for |
|
|
42 |
% Grouped Tree Structure Learning, NIPS 2010 |
|
|
43 |
% |
|
|
44 |
%% load data |
|
|
45 |
|
|
|
46 |
%profile on; |
|
|
47 |
|
|
|
48 |
rng(1) |
|
|
49 |
% ---------------------- generate random data ---------------------- |
|
|
50 |
|
|
|
51 |
N = 250; |
|
|
52 |
p = 50000; |
|
|
53 |
d = 3; % the depth of the tree excluding the root node |
|
|
54 |
nns = [1,10,50,p]; % the size of each node at different levels |
|
|
55 |
ratio = [1,0.2,0.5]; |
|
|
56 |
|
|
|
57 |
% data_name = ['syn1_' num2str(N) '_' num2str(p)]; |
|
|
58 |
% [ X, y, ind ] = gen_sync1( p, N, d, nns, ratio ); |
|
|
59 |
|
|
|
60 |
data_name = ['syn2_' num2str(N) '_' num2str(p)]; |
|
|
61 |
[ X, y, beta, ind ] = gen_sync2( p, N, d, nns, ratio ); |
|
|
62 |
|
|
|
63 |
|
|
|
64 |
%% In this example, the tree is set as: |
|
|
65 |
% |
|
|
66 |
% root, 1:100, with weight 0 |
|
|
67 |
% its children nodes, 1:50, and 51:100 |
|
|
68 |
% |
|
|
69 |
% For 1:50, its children are 1:20, 21:40, and 41:50 |
|
|
70 |
% |
|
|
71 |
% For 51:100, its children are 51:70, and 71:100 |
|
|
72 |
% |
|
|
73 |
% These nodes in addition have each individual features (they contain) as |
|
|
74 |
% children nodes. |
|
|
75 |
% |
|
|
76 |
%% |
|
|
77 |
|
|
|
78 |
%% One efficient way |
|
|
79 |
% We make use of the fact that the indices of the left nodes of the tree |
|
|
80 |
% are smaller than the right nodes. |
|
|
81 |
|
|
|
82 |
%----------------------- Set optional items ----------------------- |
|
|
83 |
opts=[]; |
|
|
84 |
|
|
|
85 |
% Starting point |
|
|
86 |
opts.init=1; % 2: starting from a zero point |
|
|
87 |
% 1: warm start |
|
|
88 |
|
|
|
89 |
% Termination |
|
|
90 |
opts.tFlag=5; % run .maxIter iterations |
|
|
91 |
opts.maxIter=1000; % maximum number of iterations |
|
|
92 |
|
|
|
93 |
% regularization |
|
|
94 |
opts.rFlag=1; % 1: use ratio |
|
|
95 |
% 0: use the true value |
|
|
96 |
% Normalization |
|
|
97 |
opts.nFlag=0; % without normalization |
|
|
98 |
|
|
|
99 |
% Group Property |
|
|
100 |
opts.ind = ind; |
|
|
101 |
% opts.ind=[[-1, -1, 1]',... % leave nodes (each node contains one feature) |
|
|
102 |
% [1, 20, sqrt(20)]', [21, 40, sqrt(20)]',... % the layer above the leaf |
|
|
103 |
% [41, 50, sqrt(10)]', [51, 70, sqrt(20)]', [71,90, sqrt(20)]', [91,100, sqrt(10)]',... |
|
|
104 |
% [1, 50, sqrt(50)]', [51, 100, sqrt(50)]']; % the higher layer |
|
|
105 |
% |
|
|
106 |
% opts.depth = d; |
|
|
107 |
|
|
|
108 |
% ----------------- set the parameter values ------------------ |
|
|
109 |
ub = 1; |
|
|
110 |
lb = 0.05; |
|
|
111 |
npar = 100; |
|
|
112 |
scale = 'log'; |
|
|
113 |
Lambda = get_lambda(lb, ub, npar, scale); |
|
|
114 |
|
|
|
115 |
%----------------------- Run the code tree_LeastR ----------------------- |
|
|
116 |
|
|
|
117 |
% --------------------- experiments ---------------- |
|
|
118 |
npar = length(Lambda); |
|
|
119 |
rej_ratio = zeros(d,npar); |
|
|
120 |
run_solver = 1; |
|
|
121 |
run_time = []; |
|
|
122 |
ntrial = 1; |
|
|
123 |
|
|
|
124 |
for trial = 1:ntrial |
|
|
125 |
fprintf('\ntrial %d:\n\n',trial); |
|
|
126 |
%X = data_matrix; |
|
|
127 |
%y = response; |
|
|
128 |
% run the solver without screening |
|
|
129 |
if run_solver == 1 |
|
|
130 |
if trial == 1 |
|
|
131 |
run_time.solver = 0; |
|
|
132 |
run_time.solver_step = zeros(1,npar); |
|
|
133 |
end |
|
|
134 |
fprintf('computing the ground truth by solver...\n'); |
|
|
135 |
starts = tic; |
|
|
136 |
[Sol_GT,funVal,tsol]=pathSolutionTGL(X, y, Lambda, opts); % ground truth solution |
|
|
137 |
tsolver = toc(starts); |
|
|
138 |
run_time.solver=run_time.solver + tsolver; |
|
|
139 |
run_time.solver_step = run_time.solver_step + tsol; |
|
|
140 |
fprintf('Running Time of solver without MLFre: %f\n',tsolver); |
|
|
141 |
fprintf('Effective number of parameter values: %f\n',nnz(sum(Sol_GT.*Sol_GT)>=1e-20)); |
|
|
142 |
end |
|
|
143 |
|
|
|
144 |
if opts.tFlag == 2 |
|
|
145 |
opts.funVal = funVal; |
|
|
146 |
end |
|
|
147 |
|
|
|
148 |
% Compute the solution with screening MLFre |
|
|
149 |
if trial == 1 |
|
|
150 |
run_time.MLFre_solver = 0; |
|
|
151 |
run_time.solver_MLFre_step = zeros(1,npar); |
|
|
152 |
run_time.MLFre = 0; |
|
|
153 |
end |
|
|
154 |
fprintf('computing the solution with screening MLFre...\n'); |
|
|
155 |
starts = tic; |
|
|
156 |
[Sol_MLFre, ind_zf_MLFre, ts_MLFre] = MLFre_TGL(X, y, Lambda, opts); |
|
|
157 |
tMLFre_solver = toc(starts); |
|
|
158 |
tMLFre = tMLFre_solver - sum(ts_MLFre); |
|
|
159 |
run_time.MLFre_solver = run_time.MLFre_solver + tMLFre_solver; |
|
|
160 |
run_time.solver_MLFre_step = run_time.solver_MLFre_step + ts_MLFre; |
|
|
161 |
run_time.MLFre = run_time.MLFre + tMLFre; |
|
|
162 |
fprintf('Running time of MLFre: %f\n',tMLFre); |
|
|
163 |
fprintf('Running Time of solver with MLFre: %f\n',tMLFre_solver); |
|
|
164 |
|
|
|
165 |
% --------------------- compute the rejection ratio --------------------- % |
|
|
166 |
if run_solver == 1 |
|
|
167 |
Sol = Sol_GT; |
|
|
168 |
fprintf('numerical error by MLFre: %f\n', ... |
|
|
169 |
norm(Sol_GT-Sol_MLFre,'fro')); |
|
|
170 |
else |
|
|
171 |
Sol = Sol_MLFre; |
|
|
172 |
end |
|
|
173 |
ind_zf = abs(Sol)<1e-12; |
|
|
174 |
|
|
|
175 |
rej_ratio = rej_ratio + reshape(sum(ind_zf_MLFre),d,npar)./repmat(sum(ind_zf),d,1); |
|
|
176 |
|
|
|
177 |
end |
|
|
178 |
|
|
|
179 |
if run_solver == 1 |
|
|
180 |
run_time.solver = run_time.solver / ntrial; |
|
|
181 |
run_time.solver_step = run_time.solver_step / ntrial; |
|
|
182 |
end |
|
|
183 |
run_time.MLFre_solver = run_time.MLFre_solver / ntrial; |
|
|
184 |
run_time.solver_MLFre_step = run_time.solver_MLFre_step / ntrial; |
|
|
185 |
run_time.MLFre = run_time.MLFre / ntrial; |
|
|
186 |
rej_ratio = rej_ratio / ntrial; |
|
|
187 |
|
|
|
188 |
if run_solver == 1 |
|
|
189 |
speedup = run_time.solver/run_time.MLFre_solver; |
|
|
190 |
fprintf('speedup: %f\n',speedup); |
|
|
191 |
end |
|
|
192 |
|
|
|
193 |
% ---------------------------- save the result ---------------------------- |
|
|
194 |
result_path = ['result/' data_name]; |
|
|
195 |
if ~exist(result_path,'dir') |
|
|
196 |
mkdir(result_path); |
|
|
197 |
end |
|
|
198 |
result_path = [result_path '/' scale]; |
|
|
199 |
if ~exist(result_path,'dir') |
|
|
200 |
mkdir(result_path); |
|
|
201 |
end |
|
|
202 |
result_path = [result_path '/']; |
|
|
203 |
result_name = [data_name '_result_' scale]; |
|
|
204 |
if run_solver == 1 |
|
|
205 |
save([result_path result_name],'data_name','Lambda','rej_ratio','run_time','speedup'); |
|
|
206 |
else |
|
|
207 |
save([result_path result_name],'data_name','Lambda','rej_ratio','run_time'); |
|
|
208 |
end |
|
|
209 |
%% plot the rejection ratio |
|
|
210 |
|
|
|
211 |
plot_rej_ratio(Lambda,rej_ratio,scale,data_name,result_path) |
|
|
212 |
|
|
|
213 |
%profile viewer; |
|
|
214 |
|
|
|
215 |
|