我想使用R包“sensitivity”执行Sobol敏感性分析。但是,我不确定如何在sobol
函数中创建第一个和第二个随机样本(X1, X2)
。我假设X1
和X2
都是输入数据的子集,然而,最终结果似乎是不正确的。
library(tidymodels)
library(sensitivity)
# Example data
set.seed(123)
x1 = runif(100)
x2 = runif(100)
x3 = runif(100)
y = 3 * x1 + 2 * x2 + x3 + rnorm(100)
data <- data.frame(x1, x2, x3, y)
# Split data into training and testing sets
set.seed(234)
data_split <- initial_split(data, prop = 0.8)
train_data <- training(data_split)
test_data <- testing(data_split)
# Create a linear regression model using tidymodels
lm_spec <- linear_reg() %>%
set_engine("lm") %>%
set_mode("regression")
lm_fit <- lm_spec %>%
fit(y ~ x1 + x2 + x3, data = train_data)
# Define a model function
model_function <- function(x) {
new_data <- data.frame(x1 = x[, 1], x2 = x[, 2], x3 = x[, 3])
predict(lm_fit, new_data)$`.pred`
}
# Perform Sobol sensitivity analysis
set.seed(345)
X_index1 = sample(x=1:100, size = 50, replace = FALSE)
X_index2 = c(1:length(data$x1))[-X_index1]
sobol_results <- sobol(model = model_function,
X1 = data[X_index1, -4],
X2 = data[X_index2, -4],
nboot = 1000, order = 2)
sobol_results
sobol_results
表明灵敏度按以下顺序排列:x2> x1> x3。根据函数y = 3 * x1 + 2 * x2 + x3 + rnorm(100)
,“x1”应该具有更高的灵敏度,因为它是3 * x1
。我应该如何纠正我的代码?谢谢你。
1条答案
按热度按时间wkyowqbh1#
根据我对
sensitivity#sobol()
function的理解,它需要以特定的方式编写模型。它期望一个函数接受一个输入矩阵并返回一个输出向量。在您的示例中,model_function
的定义似乎是正确的。参见RDocumentation。但是
sobol
函数还需要两组样本,X1
和X2
,它们是矩阵,其中每行是输入的独立实现。它们应该从输入的联合分布中生成,而不是现有数据的子集。您当前的代码将
X1
和X2
视为数据的子集,这是不正确的。在您的原始代码中,创建
X1
和X2
如下:这意味着
X_index1
和X_index2
是通过对原始数据集的索引进行采样而创建的。X_index1
是50个索引的随机样本,X_index2
是所有剩余索引的集合。然后使用这些索引将原始数据集子集划分为X1
和X2
。因此,
X1
和X2
不是来自输入变量联合分布的独立样本。相反,它们是原始数据的子集。但是,
sensitivity
包中的sobol
函数要求X1
和X2
是来自输入变量联合分布的独立样本。这是必要的,因为sobol
函数使用X1
和X2
来系统地改变每个输入变量,同时保持其他变量不变,以估计模型输出对每个输入变量的敏感度。当
X1
和X2
是数据的子集时,它们不能独立地覆盖输入变量的联合分布,这可能导致不正确的敏感性估计。这就是您获得的Sobol敏感性分析结果与基于模型系数的预期不匹配的原因。您应该从输入变量的联合分布中生成
X1
和X2
作为独立样本。如果你的输入变量均匀分布在0和1之间(就像你的例子中一样),你可以生成X1
和X2
,如下所示:然后可以将这些作为
X1
和X2
参数传递给sobol
函数。类似于:
此更新的代码使用
runif
function为X1
和X2
生成代表输入变量的均匀随机数(假设它们均匀分布)。矩阵X1
和X2
是来自输入变量联合分布的独立样本,这是sobol
函数所需要的。请记住,这样做的目的是了解输入变量的变化如何影响模型的输出。
sobol
函数通过一次系统地改变一个参数,同时保持其他参数不变来实现这一点,这些独立的样本X1
和X2
实现了这一过程。user10085在评论中写道:
我想知道
data.frame(x1 = x[, 1], x2 = x[, 2], x3 = x[, 3])
和matrix(runif(3*n), ncol = 3)
如何自动适应任何数据集?要使此代码更灵活并适应任何数据集,您可以:
首先,您将添加
num_vars
和feature_names
的计算:这些是更新代码中的新步骤。num_vars
(输入变量的数量)计算为训练数据中的列数减1(以排除响应变量),feature_names
(输入变量的名称)定义为训练数据中不包括响应变量的列名。它们用于生成具有正确列数的
X1
和X2
,并确保在模型函数中创建的新数据框具有正确的列名。这些步骤使代码适用于具有任意数量输入变量的任何数据集。然后更新
X1
和X2
的生成:在前面的校正代码中,X1
和X2
是用硬编码的列数(3)生成的。在更新后的代码中,需要生成列数等于数据中输入变量数的列。这确保X1
和X2
具有用于Sobol敏感性分析的正确结构,而不管数据中的输入变量的数量。最后,你可以修改
model
函数:在先前的校正代码中,模型函数是用三个输入变量的假设来定义的。它显式地构造了一个新的 Dataframe ,列为x1
、x2
和x3
。在更新的代码中,模型函数现在将构造一个新的 Dataframe ,其列数等于数据中输入变量的数量,并使用
feature_names
向量分配正确的列名。这允许模型函数与任何数量的输入变量一起工作。最终结果将类似于:
因此,完整的更新代码将是:
这些修改使代码更加灵活,并可适应具有不同数量的输入变量的不同数据集。