В настоящее время я работаю над циклом For в R. Если я запускаю цикл For для своих собственных данных, это занимает много времени, и я верю, потому что я сделал что-то неэффективное в своем коде. Не могли бы вы помочь мне улучшить его?
# Loop through the samples, explaining one instance at a time.
shap_values <- vector("list", nrow(X)) # initialize the results list.
system.time({
for (i in seq_along(shap_values)) {
set.seed(224)
shap_values[[i]] <- iml::Shapley$new(predictor, x.interest = X[i, ],sample.size = 30)$results
shap_values[[i]]$predicted_value <- iml::Shapley$new(predictor, x.interest = X[i, ],sample.size = 30)$y.hat.interest
shap_values[[i]]$sample_num <- i # identifier to track our instances.
}
data_shap_values <- dplyr::bind_rows(shap_values) # collapse the list.
})
Я считаю, что моя проблема в
shap_values[[i]]$sample_num
переменная, так как я переделываю там вычисления предыдущих
shap_values[[i]]$predicted_value
переменная. Причина, по которой я добавил эту переменную, заключалась в том, что мне нужно было
$y.hat.interest
как часть нового фрейма данных (который называется «shap_values», а затем «data_shap_values»).
Воспроизводимый пример: (начинается с "Это важная часть:)
#Example Shapley
#https://cran.r-project.org/web/packages/iml/vignettes/intro.html
data("Boston", package = "MASS")
head(Boston)
set.seed(42)
#install.packages("iml")
library("iml")
library("randomForest")
data("Boston", package = "MASS")
rf = randomForest(medv ~ ., data = Boston, ntree = 50)
# We create a Predictor object, that holds the model and the data.
# The iml package uses R6 classes: New objects can be created by calling Predictor$new()
X = Boston[which(names(Boston) != "medv")]
predictor = Predictor$new(rf, data = X, y = Boston$medv)
# Feature Importance
## Shifting each future, and measring how much the performance drops ##
imp = FeatureImp$new(predictor, loss = "mae")
plot(imp)
# Shapley value. Assume that for 1 data point, the feature values play a game together, in which
# they get the prediction as payout. Tells us how fairly distibute the payout among the feature values.
View(X)
shapley = Shapley$new(predictor, x.interest = X[1,])
shapley$plot()
# Reuse the object to explain other data points
shapley$explain(x.interest = X[2,])
shapley$plot()
# Results in data.frame form can be extracted like this:
results = shapley$results
head(results)
# THIS IS THE IMPORTANT PART:
# It might make sense for testing, to reduce the data:
X = X[1:10,]
# Loop through the samples, explaining one instance at a time.
shap_values <- vector("list", nrow(X)) # initialize the results list.
system.time({
for (i in seq_along(shap_values)) {
set.seed(224)
shap_values[[i]] <- iml::Shapley$new(predictor, x.interest = X[i, ],sample.size = 30)$results
shap_values[[i]]$predicted_value <- iml::Shapley$new(predictor, x.interest = X[i, ],sample.size = 30)$y.hat.interest
shap_values[[i]]$sample_num <- i # identifier to track our instances.
}
data_shap_values <- dplyr::bind_rows(shap_values) # collapse the list.
})
Обновление
По запросу @Ralf Stubner для профилирования цикла for: