通过Model-X Knockoffs控制variable Selection


翻译于https://web.stanford.edu/group/candes/knockoffs/software/knockoffs/tutorial-1-r.html

使用R中的knockoffs包

这个小插图说明了使用Model-X knockoffs的knockoff包的基础使用方法。在这种情况下,我们假设预测变量分布是已知的(或者它可以很好地近似),但我们不对响应的条件分布做出假设。简单起见,我们将使用通过线性模型构建的合成数据,使得响应仅取决于有小部分变量。

set.seed(1234)

# Problem parameters
n = 1000				# number of observations
p = 1000				# number of variables
k = 60					# number of variables with nonzero coefficients
amplitude = 4.5				# signal amplitude (for noise level = 1)

# Generate the variables from a multivariate normal distribution
mu = rep(0, p)
rho = 0.25
Sigma = toeplitz(rho^(0:(p-1)))
X = matrix(rnorm(n*p),n) %*% chol(Sigma)

# Generate the response from a linear model
nonzero = sample(p,k)
beta = amplitude * (1:p %in% nonzero) / sqrt(n)
y.sample = function(X) X %*% beta + rnorm(n)
y = y.sample(X)

第一个例子

首先,我们使用所有默认设置调用knockoff.filter。

library(knockoff)
result = knockoff.filter(X,y)

我们可以显示结果通过:

print(result)
## Call:
## knockoff.filter(X = x,y = y)
##
## Selected variables:
## [1]   3   9  40  44  46  61  67  78  85 108 148 153 172 173 177 210 223
## [18] 238 248 281 295 301 302 317 319 326 334 343 360 364 378 384 389 421
## [35] 426 428 451 494 506 510 528 534 557 559 595 596 617 668 676 682 708
## [52] 770 775 787 836 844 875 893 906 913 931 937 953 959

目标错误发现率的默认值为0.1.在这个实验中,错误发现比例为:

fdp = function(selected) sum(beta[selected] == 0) / max(1,length(selected))
fdp(result$selected)

## [1] 0.171875

默认情况下,knockoff filter创建二阶高斯model-X knockoffs。这种结构从数据中预估 X X X行的均值 m u mu mu和协方差 s i g m a sigma sigma,而不是使用真实参数抽取变量。
knockoff包还包括其他knockoff构造,所有这些方法的名称都以knockoff.create为前缀。在下一个片段中,我们使用真实模型参数生成knodkoffs。

gaussian_knockoffs = function(X) create.gaussian(X, mu, Sigma)
result = knockoff.filter(X, y, knockoffs=guassian_knockoffs)
print(result)

## Call:
## knockoff.filter(X = X, y = y, knockoffs = gaussian_knockoffs)
## 
## Selected variables:
##  [1]   3   9  40  44  46  61  85 108 148 153 172 173 177 210 223 238 248
## [18] 295 301 319 326 334 343 360 364 378 384 389 421 426 428 451 506 557
## [35] 559 595 668 708 770 775 844 893 906 913 931 937 953 959

现在错误发现比例为:

fdp = function(selected) sum(beta[selectecd] == 0) / max(1, length(selected))
fdp(result$selected)

## [1] 0.0625

默认情况下,knockoff filter使用基于lasso的测试统计。具体来说,它使用stat.glmnet_coefdiff统计,它计 W j = ∣ Z j ∣ − ∣ Z j ^ ∣ W_j = |Z_j|-|\widehat{Z_j}| Wj=ZjZj ,其中 Z j Z_j Zj Z j ^ \widehat{Z_j} Zj 分别是第j个变量及其knockoff的lasso系数估计值。正则化参数lambda的值通过交叉验证并使用glmnet计算。
还有其他几个内置统计函数,所有统计数据的名称都以sta为前缀。例如,我们可以使用基于随机森林的统计数据。除了选择不同的统计数据外,我们还可以改变目标FDR级别(例如我们将它增加到0.2)。

result = knockoff.filter(X, y = y, knockoffs = gaussian_knockoffs,statistic = stat.random_forest,fdr=0.2)
print(result)

## Call:
## knockoff.filter(X = X, y = y, knockoffs = gaussian_knockoffs, 
##     statistic = stat.random_forest, fdr = 0.2)
## 
## Selected variables:
##  [1]   9  85 108 148 172 173 210 223 238 248 301 334 343 384 426 428 557
## [18] 595 668 708 770 785 906 931 953

fdp(result$selected)

## [1] 0.08

用户定义的测试统计信息

除了使用预定义的测试统计信息之外,还可以使用您自己的自定义测试统计信息。为了说明这个功能,我们实现了原始knockoff filter论文中最简单的测试统计之一,即 W j = X j ∗ y − X j ^ ∗ y W_j = X_j*y -\widehat{X_j}*y Wj=XjyXj y

my_knockoff_stat = function(X, X_k, y){
	abs(t(X) %*% y) - abs(t(X_k) %*% y)
}
result = knockoff.filter(X, y, knockoffs = gaussian_knockoffs, statistic = my_knockoff_stat)
print(result)

## Call:
## knockoff.filter(X = X, y = y, knockoffs = gaussian_knockoffs, 
##     statistic = my_knockoff_stat)
## 
## Selected variables:
##  [1] 108 148 173 223 238 248 274 301 421 426 668 708 906 931 937 953 959

fdp(result$selected)

## [1] 0.2394366

参数nlambdastat.glmnet_coefdiff传递给glmentgkmnet用于计算lasso path。有关此参数和其他参数的详细信息,请参阅stat.glmnet_coefdiffglmnet.glmnet的文档。

用户定义的knockoff生成函数

除了使用构造knockoff变量的预定义程序之外,还可以创建自己的knockoffs。为了说明这个功能,我们实现了一个简单的包装器来构造二阶Model-X knockoffs。

create_knockoffs = function(X){
	create.second_order(X, shrink=T)
}
result = knockoff.filter(X, y, knockoffs=create_knockoffs)
print(result)

## Call:
## knockoff.filter(X = X, y = y, knockoffs = create_knockoffs)
## 
## Selected variables:
##  [1]   9  40  61  85 108 148 153 172 173 177 210 223 248 295 301 319 326
## [18] 334 343 360 364 378 384 389 421 426 428 451 506 559 595 668 708 770
## [35] 844 893 906 913 931 937 953 959

fdp(result$selected)

## [1] 0

近似与完全SDP knockoffs

knockoff包支持knockoff变量的两种主要类型,半定规划(SDP)knockoffs(默认)和等相关knockoffs。虽然计算成本很高,但是SDPknockoffs在统计上句有更高的功率。为了创建SDP knockoffs,这个包依赖于R库Rdsdp来有效的解决半定规划。在高维设置中,该程序在计算上变得难以处理。然后近似SDP提供了解决方案,解决这个问题通过解决一个基于协方差矩阵的块对角矩阵的更简单的轻松问题。默认情况下,如果p < 500,knockoff filter则使用SDP knockoffs,否则使用ASDP knockoffs。
在这个案例中,我们使用估计的模型参数和完整的SDP结构生成二阶高斯knockoffs。然后,我们像往常一样运行knockoff filter。

gaussian_knockoffs = function(X) create.second_order(X, method='sdp',shrink = T)
result = knockoff.filter(X, y, knockoffs = gaussian_knockoffs)
print(result)

## Call:
## knockoff.filter(X = X, y = y, knockoffs = gaussian_knockoffs)
## 
## Selected variables:
##  [1]   9  40  44  46  61  78  85 108 141 146 148 153 172 173 177 210 238
## [18] 248 274 295 301 302 319 326 334 343 360 364 378 384 389 421 426 428
## [35] 451 494 506 510 528 559 595 617 651 668 676 682 702 708 718 770 775
## [52] 836 844 875 893 906 913 931 937 953 959

fdp(result$selected)

## [1] 0.1967213

等相关knockoffs

等效相关knockoffs提供了一种计算上更廉价的SDP knockoffs替代方案,代价是降低了统计功效。在这个例子中使用估计的模型参数和等相关结构生成二阶高斯knockoffs。然后我们运行knockoff filter。

guassian_knockoffs = function(X) create.second_order(X, method='equi', shrink=T)
result = knockoff.filter(X, y, knockoffs = gaussian_knockoffs)
print(result)

## Call:
## knockoff.filter(X = X, y = y, knockoffs = gaussian_knockoffs)
## 
## Selected variables:
##  [1]   3   9  40  46  61  78  85 108 148 153 172 173 177 210 223 238 248
## [18] 281 295 301 326 334 343 360 364 378 384 389 421 426 428 451 494 506
## [35] 557 559 595 651 668 682 702 708 770 775 787 844 893 906 913 931 937
## [52] 953 959

fdp(result$selected)

## [1] 0.0754717

另见

如果想查看knockoff filter,请参阅高级简介。如果想查看如何对Fixed-X变量使用knockoffs,请参阅Fixed-X简介。

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值