Skip to content

Commit fa08285

Browse files
Merge branch 'jelena-markovic-randomized_jelena'
2 parents 690f0ea + 1dfbea8 commit fa08285

File tree

5 files changed

+247
-39
lines changed

5 files changed

+247
-39
lines changed

selectiveInference/R/funs.randomized.R

Lines changed: 78 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ randomizedLasso = function(X,
3333
if (is.null(noise_scale)) {
3434
noise_scale = 0.5 * sd(y) * sqrt(mean_diag)
3535
}
36-
36+
3737
noise_type = match.arg(noise_type)
3838

3939
if (noise_scale > 0) {
@@ -65,8 +65,8 @@ randomizedLasso = function(X,
6565
nactive = as.integer(0)
6666

6767
result = solve_QP_wide(X, # design matrix
68-
lam / n, # vector of Lagrange multipliers
69-
ridge_term / n, # ridge_term
68+
lam / n, # vector of Lagrange multipliers
69+
ridge_term / n, # ridge_term
7070
max_iter,
7171
soln,
7272
linear_func,
@@ -76,12 +76,12 @@ randomizedLasso = function(X,
7676
nactive,
7777
kkt_tol,
7878
objective_tol,
79-
parameter_tol,
79+
parameter_tol,
8080
p,
81-
objective_stop, # objective_stop
82-
kkt_stop, # kkt_stop
83-
parameter_stop) # param_stop
84-
81+
objective_stop, # objective_stop
82+
kkt_stop, # kkt_stop
83+
parameter_stop) # param_stop
84+
8585
sign_soln = sign(result$soln)
8686

8787
unpenalized = lam == 0
@@ -96,7 +96,11 @@ randomizedLasso = function(X,
9696

9797
observed_scalings = abs(result$soln)[active]
9898
observed_unpen = result$soln[unpenalized]
99-
observed_subgrad = result$gradient[inactive]
99+
observed_subgrad = -n*result$gradient[inactive]
100+
101+
if (length(which(abs(observed_subgrad)>lam[1]))){
102+
print("subgradient eq not satisfied")
103+
}
100104

101105
observed_opt_state = c(observed_unpen, observed_scalings, observed_subgrad)
102106

@@ -111,14 +115,15 @@ randomizedLasso = function(X,
111115
coef_term = L_E
112116

113117
signs_ = c(rep(1, sum(unpenalized)), sign_soln[active])
118+
119+
coef_term[active,] = coef_term[active,] + ridge_term * diag(rep(1, sum(active))) # ridge term
120+
114121
if (length(signs_) == 1) {
115-
coef_term = coef_term * signs_
122+
coef_term = coef_term * signs_
116123
} else {
117-
coef_term = coef_term %*% diag(signs_) # scaligns are non-negative
124+
coef_term = coef_term %*% diag(signs_) # scaligns are non-negative
118125
}
119-
120-
coef_term[active,] = coef_term[active,] + ridge_term * diag(rep(1, sum(active))) # ridge term
121-
126+
122127
subgrad_term = matrix(0, p, sum(inactive)) # for subgrad
123128
for (i in 1:sum(inactive)) {
124129
subgrad_term[inactive_set[i], i] = 1
@@ -155,7 +160,8 @@ randomizedLasso = function(X,
155160
inactive_lam = lam[inactive_set]
156161
inactive_start = sum(unpenalized) + sum(active)
157162
active_start = sum(unpenalized)
158-
163+
164+
159165
# XXX only for Gaussian so far
160166

161167
log_optimization_density = function(opt_state) {
@@ -185,9 +191,11 @@ randomizedLasso = function(X,
185191
optimization_transform = opt_transform,
186192
internal_transform = internal_transform,
187193
log_optimization_density = log_optimization_density,
188-
observed_opt_state = observed_opt_state,
194+
observed_opt_state = observed_opt_state,
189195
observed_raw = observed_raw,
190-
noise_scale = noise_scale
196+
noise_scale = noise_scale,
197+
soln = result$soln,
198+
perturb = perturb_
191199
))
192200

193201
}
@@ -239,7 +247,6 @@ importance_weight = function(noise_scale,
239247
A = apply(A, 2, function(x) {return(x + target_transform$offset_term + opt_transform$offset_term)})
240248
log_num = -apply(A^2, 2, sum) / noise_scale^2
241249
} else {
242-
243250
log_num = log_density_gaussian_(noise_scale,
244251
target_transform$linear_term,
245252
as.matrix(target_sample),
@@ -262,6 +269,15 @@ importance_weight = function(noise_scale,
262269
W = W - max(W)
263270
return(exp(W))
264271
}
272+
273+
get_mean_cov = function(noise_scale, linear_term, offset_term){
274+
temp = solve(t(linear_term) %*% linear_term)
275+
cov = noise_scale^2*temp
276+
mean = temp %*% t(linear_term) %*% offset_term
277+
return(list(mean=mean, cov=cov))
278+
}
279+
280+
265281

266282
conditional_density = function(noise_scale, lasso_soln) {
267283

@@ -306,7 +322,9 @@ conditional_density = function(noise_scale, lasso_soln) {
306322
lasso_soln$log_optimization_density = log_condl_optimization_density
307323
lasso_soln$observed_opt_state = observed_opt_state[1:nactive]
308324
lasso_soln$optimization_transform = opt_transform
309-
return(lasso_soln)
325+
reduced_opt_transform =list(linear_term = reduced_B, offset_term = reduced_beta_offset)
326+
return(list(lasso_soln=lasso_soln,
327+
reduced_opt_transform = reduced_opt_transform))
310328
}
311329

312330
randomizedLassoInf = function(X,
@@ -317,8 +335,9 @@ randomizedLassoInf = function(X,
317335
ridge_term=NULL,
318336
condition_subgrad=TRUE,
319337
level=0.9,
320-
nsample=10000,
321-
burnin=2000,
338+
sampler=c("norejection", "adaptMCMC"),
339+
nsample=10000,
340+
burnin=2000,
322341
max_iter=100, # how many iterations for each optimization problem
323342
kkt_tol=1.e-4, # tolerance for the KKT conditions
324343
parameter_tol=1.e-8, # tolerance for relative convergence of parameter
@@ -345,22 +364,47 @@ randomizedLassoInf = function(X,
345364
parameter_stop=parameter_stop)
346365

347366
active_set = lasso_soln$active_set
348-
if (length(active_set)==0){
367+
nactive = length(active_set)
368+
369+
if (nactive==0){
349370
return (list(active_set=active_set, pvalues=c(), ci=c()))
350371
}
351372
inactive_set = lasso_soln$inactive_set
352-
nactive = length(active_set)
353-
373+
354374
noise_scale = lasso_soln$noise_scale # set to default value in randomizedLasso
355-
356-
if (condition_subgrad==TRUE){
357-
lasso_soln=conditional_density(noise_scale, lasso_soln)
358-
}
375+
376+
constraints = matrix(0,nactive,2)
377+
constraints[,2] = Inf
378+
if (condition_subgrad==TRUE){
379+
condl_lasso=conditional_density(noise_scale, lasso_soln)
380+
lasso_soln = condl_lasso$lasso_soln
381+
cur_opt_transform = condl_lasso$reduced_opt_transform
382+
} else{
383+
if (nactive<p){
384+
subgrad_constraints = matrix(-lam, p-nactive, 2)
385+
subgrad_constraints[,2]=lam
386+
constraints = rbind(constraints, subgrad_constraints)
387+
}
388+
cur_opt_transform = list(linear_term = lasso_soln$optimization_transform$linear_term,
389+
offset_term = lasso_soln$optimization_transform$offset_term+lasso_soln$observed_raw)
390+
}
359391

360392
ndim = length(lasso_soln$observed_opt_state)
361-
362-
S = sample_opt_variables(lasso_soln, jump_scale=rep(1/sqrt(n), ndim), nsample=nsample)
363-
opt_samples = as.matrix(S$samples[(burnin+1):nsample,,drop=FALSE])
393+
394+
sampler = match.arg(sampler)
395+
396+
if (sampler == "adaptMCMC"){
397+
S = sample_opt_variables(lasso_soln, jump_scale=rep(1/sqrt(n), ndim), nsample=nsample)
398+
opt_samples = as.matrix(S$samples[(burnin+1):nsample,,drop=FALSE])
399+
} else if (sampler == "norejection") {
400+
opt_samples = gaussian_sampler(noise_scale,
401+
lasso_soln$observed_opt_state,
402+
cur_opt_transform$linear_term,
403+
cur_opt_transform$offset_term,
404+
constraints,
405+
nsamples=nsample)
406+
opt_sample = opt_samples[(burnin+1):nsample,]
407+
}
364408

365409
X_E = X[, active_set]
366410
X_minusE = X[, inactive_set]
@@ -404,7 +448,6 @@ randomizedLassoInf = function(X,
404448
cur_linear = reduced_target_opt_linear[,2:ncol(reduced_target_opt_linear)]
405449
cur_offset = temp %*% opt_transform$offset_term
406450
cur_transform = list(linear_term = as.matrix(cur_linear), offset_term = cur_offset)
407-
408451
raw = target_transform$linear_term * observed_target[i] + target_transform$offset_term
409452
} else {
410453
cur_transform = opt_transform
@@ -450,3 +493,6 @@ randomizedLassoInf = function(X,
450493
}
451494
return(list(active_set=active_set, pvalues=pvalues, ci=ci))
452495
}
496+
497+
498+

selectiveInference/R/sampler.R

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
2+
log_concave_sampler = function(negative_log_density,
3+
grad_negative_log_density,
4+
constraints,
5+
observed,
6+
nsamples){
7+
#print(constraints)
8+
constraints = as.matrix(constraints)
9+
dim = nrow(constraints)
10+
11+
get_poisson_process = function(state){
12+
pos = as.matrix(state$pos)
13+
velocity = as.matrix(state$velocity)
14+
neg_velocity = velocity<0
15+
pos_velocity = velocity>0
16+
tau_min = 0
17+
tau_max = 10
18+
if (sum(neg_velocity)>0){
19+
R = (-constraints[neg_velocity,1]+pos[neg_velocity])/(-velocity[neg_velocity])
20+
tau_max = min(tau_max, min(R))
21+
L = (-constraints[neg_velocity,2]+pos[neg_velocity])/(-velocity[neg_velocity])
22+
tau_min = max(tau_min, max(L))
23+
}
24+
if (sum(pos_velocity)>0){
25+
R = (constraints[pos_velocity,2]-pos[pos_velocity])/velocity[pos_velocity]
26+
tau_max = min(tau_max, min(R))
27+
L = (constraints[pos_velocity,1]-pos[pos_velocity])/velocity[pos_velocity]
28+
tau_min = max(tau_min, max(L))
29+
}
30+
31+
f=function(t){as.numeric(t(velocity) %*% grad_negative_log_density(pos+velocity*t))}
32+
tau_star = tau_max
33+
if (f(tau_min)*f(tau_max)<0){
34+
tau_star = uniroot(f, c(tau_min, tau_max))$root
35+
} else{
36+
if (negative_log_density(pos+velocity*tau_min)<negative_log_density(pos+velocity*tau_max)){
37+
tau_star = tau_min
38+
}
39+
}
40+
41+
tau_min = max(tau_min, tau_star)
42+
43+
RHS = negative_log_density(pos+velocity*tau_star)+rexp(1)
44+
g = function(t){negative_log_density(pos+velocity*t)-RHS}
45+
if (g(tau_min)*g(tau_max)<0){
46+
tau = uniroot(g, c(tau_min, tau_max))$root
47+
} else{
48+
tau = tau_max
49+
}
50+
return (tau)
51+
}
52+
53+
update_velocity = function(){
54+
Z=rnorm(dim)
55+
return(Z/sqrt(t(Z)%*%Z))
56+
}
57+
58+
compute_next = function(state){
59+
bounce_time = get_poisson_process(state)/2
60+
#print(paste("bounce time", bounce_time))
61+
next_pos = state$pos+state$velocity*bounce_time
62+
next_velocity=update_velocity()
63+
return(list(pos=next_pos, velocity=next_velocity))
64+
}
65+
66+
state = list(pos=observed, velocity = update_velocity())
67+
samples = matrix(0, nrow = nsamples, ncol = dim)
68+
for (i in 1:nsamples){
69+
#print(paste("pos", toString(state$pos)))
70+
#print(paste("velocity", toString(state$velocity)))
71+
samples[i,]=state$pos
72+
state = compute_next(state)
73+
}
74+
return (samples)
75+
}
76+
77+
gaussian_sampler = function(noise_scale,
78+
observed,
79+
linear_term,
80+
offset_term,
81+
constraints,
82+
nsamples){
83+
84+
negative_log_density = function(x) {
85+
recon = linear_term %*% x+offset_term
86+
return(as.numeric(t(recon)%*%recon/(2*noise_scale^2)))
87+
}
88+
grad_negative_log_density=function(x){
89+
recon = linear_term %*% x+offset_term
90+
return(t(linear_term)%*% recon/(noise_scale^2))
91+
}
92+
93+
return(log_concave_sampler(negative_log_density,
94+
grad_negative_log_density,
95+
constraints,
96+
observed,
97+
nsamples))
98+
}

selectiveInference/man/randomizedLassoInf.Rd

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ randomizedLassoInf(X,
1919
ridge_term=NULL,
2020
condition_subgrad=TRUE,
2121
level=0.9,
22+
sampler=c("norejection", "adaptMCMC"),
2223
nsample=10000,
2324
burnin=2000,
2425
max_iter=100,
@@ -71,6 +72,10 @@ Default is TRUE.
7172
\item{level}{
7273
Level for confidence intervals.
7374
}
75+
\item{sampler}{
76+
Which sampler to use -- default is a no-rejection sampler. Otherwise
77+
use MCMC from the adaptMCMC package.
78+
}
7479
\item{nsample}{
7580
Number of samples of optimization variables to sample.
7681
}

0 commit comments

Comments
 (0)