R:将 LIME 应用于 quanteda 文本模型的问题
Posted
技术标签:
【中文标题】R:将 LIME 应用于 quanteda 文本模型的问题【英文标题】:R: problems applying LIME to quanteda text model 【发布时间】:2018-10-21 18:43:16 【问题描述】:这是我的previous question 的修改版本:我正在尝试在我的quanteda
文本模型上运行 LIME,它以Trump & Clinton tweets data 为基础。我按照 Thomas Pedersen 在他的Understanding LIME 中给出的示例和@Weihuang Wong 提供的有用 SO 答案运行它:
library(dplyr)
library(stringr)
library(quanteda)
library(lime)
#data prep
tweet_csv <- read_csv("tweets.csv")
# creating corpus and dfm for train and test sets
get_matrix <- function(df)
corpus <- quanteda::corpus(df)
dfm <- quanteda::dfm(corpus, remove_url = TRUE, remove_punct = TRUE, remove = stopwords("english"))
set.seed(32984)
trainIndex <- sample.int(n = nrow(tweet_csv), size = floor(.8*nrow(tweet_csv)), replace = F)
train_dfm <- get_matrix(tweet_csv$text[trainIndex])
train_raw <- tweet_csv[, c("text", "tweet_num")][as.vector(trainIndex), ]
train_labels <- tweet_csv$author[as.vector(trainIndex)] == "realDonaldTrump"
test_dfm <- get_matrix(tweet_csv$text[-trainIndex])
test_raw <- tweet_csv[, c("text", "tweet_num")][-as.vector(trainIndex), ]
test_labels <- tweet_csv$author[-as.vector(trainIndex)] == "realDonaldTrump"
#### make sure that train & test sets have exactly same features
test_dfm <- dfm_select(test_dfm, train_dfm)
### Naive Bayes model using quanteda::textmodel_nb ####
nb_model <- quanteda::textmodel_nb(train_dfm, train_labels)
nb_preds <- predict(nb_model, test_dfm) #> 0.5
# select only correct predictions
predictions_tbl <- data.frame(predict_label = nb_preds$nb.predicted,
actual_label = test_labels,
tweet_name = rownames(nb_preds$posterior.prob)
) %>%
mutate(tweet_num =
as.integer(
str_trim(
str_replace_all(tweet_name, "text", ""))
))
correct_pred <- predictions_tbl %>%
filter(actual_label == predict_label)
# pick a sample of tweets for explainer
tweets_to_explain <- test_raw %>%
filter(tweet_num %in% correct_pred$tweet_num) %>%
head(4)
### set up correct model class and predict functions
class(nb_model)
model_type.textmodel_nb_fitted <- function(x, ...)
return("classification")
# have to modify the textmodel_nb_fitted so that
predict_model.textmodel_nb_fitted <- function(x, newdata, type, ...)
X <- corpus(newdata)
X <- dfm_select(dfm(X), x$data$x)
res <- predict(x, newdata = X, ...)
switch(
type,
raw = data.frame(Response = res$nb.predicted, stringsAsFactors = FALSE),
prob = as.data.frame(res$posterior.prob, check.names = FALSE)
)
### run the explainer - no problems here
explainer <- lime(tweets_to_explain$text, # lime returns error on different features in explainer and explanations, even if I use the same dataset in both. Raised an issue on Github and asked a question on SO
model = nb_model,
preprocess = get_matrix)
但是当我运行解释器时...
corr_explanation <- lime::explain(tweets_to_explain$text,
explainer,
n_labels = 1,
n_features = 6,
cols = 2,
verbose = 0)
...我收到以下错误:
UseMethod("corpus") 中的错误: 没有适用于“语料库”的方法应用于类“c('dfm','dgCMatrix','CsparseMatrix','dsparseMatrix','generalMatrix','dCsparseMatrix','dMatrix','sparseMatrix','compMatrix' ', '矩阵', 'xMatrix', 'mMatrix', 'Mnumeric', 'replValueSp')"
回到将corpus()
应用到newdata
:
5.corpus(newdata)
4.predict_model.textmodel_nb_fitted(x = explainer$model, newdata = permutations_tokenized,
type = o_type)
3.predict_model(x = explainer$model, newdata = permutations_tokenized,
type = o_type)
2.explain.character(tweets_to_explain$text, explainer, n_labels = 1,
n_features = 6, cols = 2, verbose = 0)
1.lime::explain(tweets_to_explain$text, explainer, n_labels = 1,
n_features = 6, cols = 2, verbose = 0)
但我不明白为什么这会导致任何问题,因为新数据是文本向量?
感谢任何提示
【问题讨论】:
【参考方案1】:corpus
不必运行。尝试如下重新定义predict_model.textmodel_nb_fitted
,其中唯一的修改是添加dfm_select
这一步:
predict_model.textmodel_nb_fitted <- function(x, newdata, type, ...)
X <- dfm_select(dfm(newdata), x$data$x)
res <- predict(x, newdata = X, ...)
switch(
type,
raw = data.frame(Response = res$nb.predicted, stringsAsFactors = FALSE),
prob = as.data.frame(res$posterior.prob, check.names = FALSE)
)
正如您的 traceback()
输出所示,corpus
会引发错误。为了调试,我在predict_model.textmodel_nb_fitted
函数的第一行插入了print(str(newdata))
。这说明newdata
已经是dfm
对象,所以可以直接传入predict.textmodel_nb_fitted
(用dfm_select
处理后)。
在quanteda
的更新版本中,textmodel_nb()
返回类textmodel_nb
、textmodel
和list
的对象。这首先需要model_type
的对应方法:
model_type.textmodel_nb <- function(x, ...)
return("classification")
然后我们还必须为predict_model
编写一个textmodel_nb
方法:
predict_model.textmodel_nb <- function(x, newdata, type, ...)
X <- dfm_select(dfm(newdata), x$x)
res <- predict(x, newdata = X, ...)
switch(
type,
raw = data.frame(Response = res$nb.predicted, stringsAsFactors = FALSE),
prob = as.data.frame(res$posterior.prob, check.names = FALSE)
)
请注意,dfm_select
的第二个参数与 predict_model.textmodel_nb_fitted
中的第二个参数不同(来自答案的原始版本)。这是因为x
对象的结构——textmodel_nb()
的输出——发生了变化。
【讨论】:
好的,要添加一层复杂性!当我从一台 Mac 运行代码时,class(nb_model)
返回"textmodel_nb_fitted" "list"
,并且上面的代码有效。但是,在 Windows 计算机上 Macbook 2008 的输出是 "textmodel_nb" "textmodel" "list"
,为什么?而且,无论我将 predict.model 和 model_type 修改为 .textmodel
还是 .textmodel_nb
,当解释器下雨时,我仍然会遇到 newdata 和训练集中的不同特征的问题。真的不知道如何在我应该在星期一给出的研讨会之前解决这个问题;)我会很感激这里的任何建议!
顺便说一句,我不确定模型类中的差异是来自不同的计算机还是只是不同版本的 R/Rstudio/packages,但是仍然存在差异
对——经过一番研究,我意识到在较新版本的quanteda
中,textmodel_nb
返回一个结构略有不同的对象。请参阅我的更新答案。我想您应该建议您的研讨会参与者安装最新版本的quanteda
。
它现在可以工作了,太棒了!非常感谢您在这里的指导和澄清。它拯救了我们的研讨会 :) 让我想到 SO、R 和开源社区总体上是多么了不起。感谢您参与其中以上是关于R:将 LIME 应用于 quanteda 文本模型的问题的主要内容,如果未能解决你的问题,请参考以下文章
R语言构建文本分类模型并使用LIME进行模型解释实战:文本数据预处理构建词袋模型构建xgboost文本分类模型基于文本训练数据以及模型构建LIME解释器解释一个测试语料的预测结果并可视化
R语言构建文本分类模型并使用LIME进行模型解释实战:文本数据预处理构建词袋模型构建xgboost文本分类模型基于文本训练数据以及模型构建LIME解释器解释多个测试语料的预测结果并可视化
将 LIME 解释应用于我的微调 BERT 以进行序列分类模型?