Skip to content

Commit 50601d2

Browse files
merging with upstream
2 parents 2d685c0 + 232760d commit 50601d2

26 files changed

+1729
-1611
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "C-software"]
2+
path = C-software
3+
url = https://github.com/selective-inference/C-software.git

.travis.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,10 @@ warnings_are_errors: true
1212
before_install:
1313
- tlmgr install index # for texlive and vignette?
1414
- R -e 'install.packages(c("Rcpp", "intervals"), repos="http://cloud.r-project.org")'
15+
- cd C-software
16+
- git submodule init
17+
- git submodule update
18+
- cd ..
19+
- make src
1520
- make Rcpp
1621
- cd selectiveInference

C-software

Submodule C-software added at a3d9a17

Makefile

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@ Rcpp:
33
- rm -f selectiveInference/R/RcppExports.R
44
Rscript -e "library(Rcpp); Rcpp::compileAttributes('selectiveInference')"
55

6-
install: Rcpp
6+
install: Rcpp src
77
R CMD INSTALL selectiveInference
88

9-
build:
9+
build: src
1010
R CMD build selectiveInference
1111

12-
check: Rcpp build
12+
src:
13+
cp C-software/src/* selectiveInference/src
14+
15+
check: Rcpp build
1316
R CMD build selectiveInference
1417
R CMD check selectiveInference_1.2.2.tar.gz # fix this to be a script variable

selectiveInference/DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Maintainer: Rob Tibshirani <[email protected]>
99
Depends:
1010
glmnet,
1111
intervals,
12-
survival
12+
survival,
1313
Suggests:
1414
Rmpfr
1515
Description: New tools for post-selection inference, for use with forward

selectiveInference/NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,6 @@ importFrom("stats", dnorm, lsfit, pexp, pnorm, predict,
4343
qnorm, rnorm, sd, uniroot, dchisq, model.matrix, pchisq)
4444
importFrom("stats", "coef", "df", "lm", "pf")
4545
importFrom("stats", "glm", "residuals", "vcov")
46+
importFrom("stats", "rbinom", "rexp")
4647
importFrom("Rcpp", "sourceCpp")
4748
importFrom("distr", "Norm", "DExp")

selectiveInference/R/funs.fixed.R

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -319,16 +319,19 @@ debiasingMatrix = function(Xinfo, # could be X or t(X) %*% X / n d
319319
nsample,
320320
rows,
321321
verbose=FALSE,
322-
mu=NULL, # starting value of mu
322+
bound=NULL, # starting value of bound
323323
linesearch=TRUE, # do a linesearch?
324324
scaling_factor=1.5, # multiplicative factor for linesearch
325325
max_active=NULL, # how big can active set get?
326326
max_try=10, # how many steps in linesearch?
327327
warn_kkt=FALSE, # warn if KKT does not seem to be satisfied?
328-
max_iter=100, # how many iterations for each optimization problem
328+
max_iter=50, # how many iterations for each optimization problem
329+
kkt_stop=TRUE, # stop based on KKT conditions?
330+
parameter_stop=TRUE, # stop based on relative convergence of parameter?
331+
objective_stop=TRUE, # stop based on relative decrease in objective?
329332
kkt_tol=1.e-4, # tolerance for the KKT conditions
330333
parameter_tol=1.e-4, # tolerance for relative convergence of parameter
331-
objective_tol=1.e-8 # tolerance for relative decrease in objective
334+
objective_tol=1.e-4 # tolerance for relative decrease in objective
332335
) {
333336

334337

@@ -339,8 +342,8 @@ debiasingMatrix = function(Xinfo, # could be X or t(X) %*% X / n d
339342
p = ncol(Xinfo);
340343
M = matrix(0, length(rows), p);
341344

342-
if (is.null(mu)) {
343-
mu = (1/sqrt(nsample)) * qnorm(1-(0.1/(p^2)))
345+
if (is.null(bound)) {
346+
bound = (1/sqrt(nsample)) * qnorm(1-(0.1/(p^2)))
344347
}
345348

346349
xperc = 0;
@@ -356,13 +359,16 @@ debiasingMatrix = function(Xinfo, # could be X or t(X) %*% X / n d
356359
output = debiasingRow(Xinfo, # could be X or t(X) %*% X / n depending on is_wide
357360
is_wide,
358361
row,
359-
mu,
362+
bound,
360363
linesearch=linesearch,
361364
scaling_factor=scaling_factor,
362365
max_active=max_active,
363366
max_try=max_try,
364367
warn_kkt=FALSE,
365368
max_iter=max_iter,
369+
kkt_stop=kkt_stop,
370+
parameter_stop=parameter_stop,
371+
objective_stop=objective_stop,
366372
kkt_tol=kkt_tol,
367373
parameter_tol=parameter_tol,
368374
objective_tol=objective_tol)
@@ -387,16 +393,23 @@ debiasingMatrix = function(Xinfo, # could be X or t(X) %*% X / n d
387393
debiasingRow = function (Xinfo, # could be X or t(X) %*% X / n depending on is_wide
388394
is_wide,
389395
row,
390-
mu,
396+
bound,
391397
linesearch=TRUE, # do a linesearch?
392398
scaling_factor=1.5, # multiplicative factor for linesearch
393399
max_active=NULL, # how big can active set get?
394400
max_try=10, # how many steps in linesearch?
395401
warn_kkt=FALSE, # warn if KKT does not seem to be satisfied?
396-
max_iter=100, # how many iterations for each optimization problem
402+
max_iter=50, # how many iterations for each optimization problem
403+
kkt_stop=TRUE, # stop based on KKT conditions?
404+
parameter_stop=TRUE, # stop based on relative convergence of parameter?
405+
objective_stop=TRUE, # stop based on relative decrease in objective?
397406
kkt_tol=1.e-4, # tolerance for the KKT conditions
398407
parameter_tol=1.e-4, # tolerance for relative convergence of parameter
408+
<<<<<<< HEAD
399409
objective_tol=1.e-8 # tolerance for relative decrease in objective
410+
=======
411+
objective_tol=1.e-4 # tolerance for relative decrease in objective
412+
>>>>>>> 232760d6aef5182e040b82e30555f4af5ad6803c
400413
) {
401414

402415
p = ncol(Xinfo)
@@ -405,9 +418,11 @@ debiasingRow = function (Xinfo, # could be X or t(X) %*% X / n dep
405418
max_active = min(nrow(Xinfo), ncol(Xinfo))
406419
}
407420

421+
408422
# Initialize variables
409423

410424
soln = rep(0, p)
425+
soln = as.numeric(soln)
411426
ever_active = rep(0, p)
412427
ever_active[1] = row # 1-based
413428
ever_active = as.integer(ever_active)
@@ -423,11 +438,15 @@ debiasingRow = function (Xinfo, # could be X or t(X) %*% X / n dep
423438

424439
last_output = NULL
425440

441+
if (is_wide) {
442+
Xsoln = as.numeric(rep(0, nrow(Xinfo)))
443+
}
444+
426445
while (counter_idx < max_try) {
427446

428447
if (!is_wide) {
429448
result = solve_QP(Xinfo, # this is non-neg-def matrix
430-
mu,
449+
bound,
431450
max_iter,
432451
soln,
433452
linear_func,
@@ -438,6 +457,7 @@ debiasingRow = function (Xinfo, # could be X or t(X) %*% X / n dep
438457
objective_tol,
439458
parameter_tol,
440459
max_active,
460+
<<<<<<< HEAD
441461
FALSE, # objective_stop
442462
FALSE, # kkt_stop
443463
TRUE) # param_stop
@@ -446,6 +466,15 @@ debiasingRow = function (Xinfo, # could be X or t(X) %*% X / n dep
446466
result = solve_QP_wide(Xinfo, # this is a design matrix
447467
rep(mu, p), # vector of Lagrange multipliers
448468
0, # ridge_term
469+
=======
470+
kkt_stop,
471+
objective_stop,
472+
parameter_stop)
473+
} else {
474+
result = solve_QP_wide(Xinfo, # this is a design matrix
475+
as.numeric(rep(bound, p)), # vector of Lagrange multipliers
476+
0, # ridge_term
477+
>>>>>>> 232760d6aef5182e040b82e30555f4af5ad6803c
449478
max_iter,
450479
soln,
451480
linear_func,
@@ -457,9 +486,15 @@ debiasingRow = function (Xinfo, # could be X or t(X) %*% X / n dep
457486
objective_tol,
458487
parameter_tol,
459488
max_active,
489+
<<<<<<< HEAD
460490
FALSE, # objective_stop
461491
FALSE, # kkt_stop
462492
TRUE) # param_stop
493+
=======
494+
kkt_stop,
495+
objective_stop,
496+
parameter_stop)
497+
>>>>>>> 232760d6aef5182e040b82e30555f4af5ad6803c
463498

464499
}
465500

@@ -483,13 +518,13 @@ debiasingRow = function (Xinfo, # could be X or t(X) %*% X / n dep
483518
if ((iter < (max_iter+1)) && (counter_idx > 1)) {
484519
break; # we've found a feasible point and solved the problem
485520
}
486-
mu = mu * scaling_factor;
521+
bound = bound * scaling_factor;
487522
} else { # trying to drop the bound parameter further
488523
if ((iter == (max_iter + 1)) && (counter_idx > 1)) {
489524
result = last_output; # problem seems infeasible because we didn't solve it
490525
break; # so we revert to previously found solution
491526
}
492-
mu = mu / scaling_factor;
527+
bound = bound / scaling_factor;
493528
}
494529

495530
# If the active set has grown to a certain size
@@ -515,7 +550,8 @@ debiasingRow = function (Xinfo, # could be X or t(X) %*% X / n dep
515550
}
516551

517552
return(list(soln=result$soln,
518-
kkt_check=result$kkt_check))
553+
kkt_check=result$kkt_check,
554+
gradient=result$gradient))
519555

520556
}
521557

selectiveInference/R/funs.fixedCox.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ b1= -(mydiag(sign_bhat)%*%MM)%*%sign_bhat*lambda
7373
vup[jj]=junk$vup
7474
sd[jj]=junk$sd
7575

76-
junk2=TG.interval(bbar, A1, b1, vj, MM, alpha)
76+
junk2=TG.interval(bbar, A1, b1, vj, MM, alpha, flip=(sign_bhat[jj]==-1))
7777
ci[jj,]=junk2$int
7878
tailarea[jj,] = junk2$tailarea
7979

selectiveInference/R/funs.fixedLogit.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ fixedLogitLassoInf=function(x,y,beta,lambda,alpha=.1, type=c("partial"), tol.bet
9696
vup[jj]=junk$vup
9797
sd[jj]=junk$sd
9898

99-
junk2=TG.interval(bbar, A1, b1, vj, MM,alpha=alpha)
99+
junk2=TG.interval(bbar, A1, b1, vj, MM,alpha=alpha, flip=(sign_bhat[jj+1]==-1))
100100

101101
ci[jj,]=junk2$int
102102
tailarea[jj,] = junk2$tailarea

selectiveInference/R/funs.randomized.R

Lines changed: 80 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,19 @@
33
#
44
# min 1/2 || y - \beta_0 - X \beta ||_2^2 + \lambda || \beta ||_1 - \omega^T\beta + \frac{\epsilon}{2} \|\beta\|^2_2
55

6-
fit_randomized_lasso = function(X,
7-
y,
8-
lam,
9-
noise_scale,
10-
ridge_term,
11-
noise_type=c('gaussian', 'laplace'),
12-
max_iter=100, # how many iterations for each optimization problem
13-
kkt_tol=1.e-4, # tolerance for the KKT conditions
14-
parameter_tol=1.e-8, # tolerance for relative convergence of parameter
15-
objective_tol=1.e-8, # tolerance for relative decrease in objective
16-
objective_stop=FALSE,
17-
kkt_stop=TRUE,
18-
param_stop=TRUE)
6+
randomizedLASSO = function(X,
7+
y,
8+
lam,
9+
noise_scale,
10+
ridge_term,
11+
noise_type=c('gaussian', 'laplace'),
12+
max_iter=100, # how many iterations for each optimization problem
13+
kkt_tol=1.e-4, # tolerance for the KKT conditions
14+
parameter_tol=1.e-8, # tolerance for relative convergence of parameter
15+
objective_tol=1.e-8, # tolerance for relative decrease in objective
16+
objective_stop=FALSE,
17+
kkt_stop=TRUE,
18+
param_stop=TRUE)
1919
{
2020

2121
n = nrow(X); p = ncol(X)
@@ -24,12 +24,11 @@ fit_randomized_lasso = function(X,
2424

2525
if (noise_scale > 0) {
2626
if (noise_type == 'gaussian') {
27-
D = Norm(mean=0, sd=noise_scale)
27+
perturb_ = rnorm(p) * noise_scale
2828
}
2929
else if (noise_type == 'laplace') {
30-
D = DExp(rate = 1 / noise_scale) # D is a Laplace distribution with rate = 1.
30+
perturb_ = rexp(p) * (2 * rbinom(p, 1, 0.5) - 1) * noise_scale
3131
}
32-
perturb_ = distr::r(D)(p)
3332
} else {
3433
perturb_ = rep(0, p)
3534
}
@@ -38,19 +37,21 @@ fit_randomized_lasso = function(X,
3837
if (length(lam) == 1) {
3938
lam = rep(lam, p)
4039
}
40+
4141
if (length(lam) != p) {
4242
stop("Lagrange parameter should be single float or of length ncol(X)")
4343
}
4444

4545
soln = rep(0, p)
4646
Xsoln = rep(0, n)
47-
linear_func = (- t(X) %*% y - perturb_)
47+
linear_func = (- t(X) %*% y - perturb_) / n
48+
4849
gradient = 1. * linear_func
4950
ever_active = rep(0, p)
5051
nactive = as.integer(0)
5152

5253
result = solve_QP_wide(X, # design matrix
53-
lam, # vector of Lagrange multipliers
54+
lam / n, # vector of Lagrange multipliers
5455
ridge_term / n, # ridge_term
5556
max_iter,
5657
soln,
@@ -66,5 +67,65 @@ fit_randomized_lasso = function(X,
6667
objective_stop, # objective_stop
6768
kkt_stop, # kkt_stop
6869
param_stop) # param_stop
69-
return(result)
70+
71+
sign_soln = sign(result$soln)
72+
73+
unpenalized = lam == 0
74+
active = (!unpenalized) & (sign_soln != 0)
75+
inactive = (!unpenalized) & (sign_soln == 0)
76+
77+
unpenalized_set = which(unpenalized)
78+
active_set = which(active)
79+
inactive_set = which(inactive)
80+
81+
# affine transform for optimization variables
82+
83+
E = c(unpenalized_set, active_set)
84+
I = inactive_set
85+
X_E = X[,E]
86+
X_I = X[,I]
87+
L_E = t(X) %*% X[,E]
88+
89+
coef_term = L_E
90+
coef_term = coef_term %*% diag(c(rep(1, sum(unpenalized)), sign_soln[active])) # coefficients are non-negative
91+
coef_term[active,] = coef_term[active,] + ridge_term * diag(rep(1, sum(active))) # ridge term
92+
93+
subgrad_term = matrix(0, p, sum(inactive)) # for subgrad
94+
for (i in 1:sum(inactive)) {
95+
subgrad_term[inactive_set[i], i] = 1
96+
}
97+
98+
linear_term = cbind(coef_term,
99+
subgrad_term)
100+
101+
offset_term = rep(0, p)
102+
offset_term[active] = lam[active] * sign_soln[active]
103+
104+
opt_transform = list(linear_term=linear_term,
105+
offset_term=offset_term)
106+
107+
# affine transform for internal (data) variables
108+
# for now just use parametric in terms of
109+
# (\bar{\beta}_E, X_{-E}^T(y-X_E\bar{\beta}_E)
110+
#
111+
# we have to reconstruct -X^TY from this pair
112+
#
113+
114+
active_term = -L_E # for \bar{\beta}_E
115+
116+
inactive_term = -subgrad_term
117+
linear_term = cbind(active_term,
118+
inactive_term)
119+
offset_term = rep(0, p)
120+
internal_transform = list(linear_term = linear_term,
121+
offset_term = offset_term)
122+
123+
return(list(active_set = active_set,
124+
inactive_set = inactive_set,
125+
unpenalized_set = unpenalized_set,
126+
sign_soln = sign_soln,
127+
optimization_transform = opt_transform,
128+
internal_transform = internal_transform
129+
))
130+
70131
}

0 commit comments

Comments
 (0)