Switch to unified view

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