- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试结合使用 quanteda
和 caret
包来根据训练样本对文本进行分类。作为测试运行,我想将 quanteda
的内置朴素贝叶斯分类器与 caret
中的分类器进行比较。但是,我似乎无法让 caret
正常工作。
这里是一些用于复制的代码。首先是 quanteda
方面:
library(quanteda)
library(quanteda.corpora)
library(caret)
corp <- data_corpus_movies
set.seed(300)
id_train <- sample(docnames(corp), size = 1500, replace = FALSE)
# get training set
training_dfm <- corpus_subset(corp, docnames(corp) %in% id_train) %>%
dfm(stem = TRUE)
# get test set (documents not in id_train, make features equal)
test_dfm <- corpus_subset(corp, !docnames(corp) %in% id_train) %>%
dfm(stem = TRUE) %>%
dfm_select(pattern = training_dfm,
selection = "keep")
# train model on sentiment
nb_quanteda <- textmodel_nb(training_dfm, docvars(training_dfm, "Sentiment"))
# predict and evaluate
actual_class <- docvars(test_dfm, "Sentiment")
predicted_class <- predict(nb_quanteda, newdata = test_dfm)
class_table_quanteda <- table(actual_class, predicted_class)
class_table_quanteda
#> predicted_class
#> actual_class neg pos
#> neg 202 47
#> pos 49 202
还不错。无需调整,准确率为 80.8%。现在 caret
中的情况相同(据我所知)
training_m <- convert(training_dfm, to = "matrix")
test_m <- convert(test_dfm, to = "matrix")
nb_caret <- train(x = training_m,
y = as.factor(docvars(training_dfm, "Sentiment")),
method = "naive_bayes",
trControl = trainControl(method = "none"),
tuneGrid = data.frame(laplace = 1,
usekernel = FALSE,
adjust = FALSE),
verbose = TRUE)
predicted_class_caret <- predict(nb_caret, newdata = test_m)
class_table_caret <- table(actual_class, predicted_class_caret)
class_table_caret
#> predicted_class_caret
#> actual_class neg pos
#> neg 246 3
#> pos 249 2
不仅准确率非常低(49.6% - 大致是偶然),而且 pos 类别几乎从未被预测过!所以我很确定我在这里遗漏了一些关键的东西,因为我认为实现应该非常相似,但不确定是什么。
我已经查看了 quanteda
函数的源代码(希望它可以构建在 caret
或底层包之上),并发现有一些权重并进行平滑处理。如果我在训练前将相同的方法应用于我的 dfm(稍后设置 laplace = 0),准确性会更好一些。但也只有 53%。
最佳答案
答案是 caret (使用 naivebayes 包中的 naive_bayes
)假设高斯分布,而 quanteda::textmodel_nb()
则采用高斯分布。基于更适合文本的多项分布(也可以选择伯努利分布)。
textmodel_nb()
的文档复制了 IIR 书中的示例(Manning、Raghavan 和 Schütze 2008),并且还引用了 Jurafsky 和 Martin(2018)的进一步示例。请参阅:
Manning、Christopher D.、Prabhakar Raghavan 和 Hinrich Schütze。 2008。信息检索简介。剑桥大学出版社(第 13 章)。 https://nlp.stanford.edu/IR-book/pdf/irbookonlinereading.pdf
尤拉夫斯基、丹尼尔和詹姆斯·H·马丁。 2018。语音和语言处理。自然语言处理、计算语言学和语音识别简介。第三版草案,2018 年 9 月 23 日(第 4 章)。 https://web.stanford.edu/~jurafsky/slp3/4.pdf
另一个包 e1071 产生的结果与您发现的结果相同,因为它也基于高斯分布。
library("e1071")
nb_e1071 <- naiveBayes(x = training_m,
y = as.factor(docvars(training_dfm, "Sentiment")))
nb_e1071_pred <- predict(nb_e1071, newdata = test_m)
table(actual_class, nb_e1071_pred)
## nb_e1071_pred
## actual_class neg pos
## neg 246 3
## pos 249 2
然而,caret 和 e1071 都适用于稠密矩阵,这也是它们与 quanteda 方法相比慢得令人 NumPy 的原因之一它在稀疏 dfm 上运行。因此,从分类器的适当性、效率和(根据您的结果)性能的角度来看,应该非常清楚哪个是首选!
library("rbenchmark")
benchmark(
quanteda = {
nb_quanteda <- textmodel_nb(training_dfm, docvars(training_dfm, "Sentiment"))
predicted_class <- predict(nb_quanteda, newdata = test_dfm)
},
caret = {
nb_caret <- train(x = training_m,
y = as.factor(docvars(training_dfm, "Sentiment")),
method = "naive_bayes",
trControl = trainControl(method = "none"),
tuneGrid = data.frame(laplace = 1,
usekernel = FALSE,
adjust = FALSE),
verbose = FALSE)
predicted_class_caret <- predict(nb_caret, newdata = test_m)
},
e1071 = {
nb_e1071 <- naiveBayes(x = training_m,
y = as.factor(docvars(training_dfm, "Sentiment")))
nb_e1071_pred <- predict(nb_e1071, newdata = test_m)
},
replications = 1
)
## test replications elapsed relative user.self sys.self user.child sys.child
## 2 caret 1 29.042 123.583 25.896 3.095 0 0
## 3 e1071 1 217.177 924.157 215.587 1.169 0 0
## 1 quanteda 1 0.235 1.000 0.213 0.023 0 0
关于r - Quanteda 中的朴素贝叶斯与插入符号 : wildly different results,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54427001/
是否有比 R quanteda::tokens_lookup() 更快的替代方法? 我使用“quanteda”R 包中的 tokens() 来标记包含 2000 个文档的数据框。每份文件为 50 -
我想明确替换 quanteda 包的 tokens 类对象中定义的特定标记。我未能复制适用于 stringr 的标准方法。 目标是用 c("XXX", "of") 形式的两个标记替换 "XXXof"
我想将一些元数据附加到kwic输出中,例如客户ID(请参见下文),以便可以轻松地对主文件进行查找。我尝试使用cbind附加数据,但没有正确匹配的内容。 如果可能的话,将不胜感激。 docna
相关问题可以在 here 中找到但不直接解决我在下面讨论的这个问题。 我的目标是删除与 token 一起出现的任何数字。例如,我希望能够摆脱以下情况下的数字:13f , 408-k , 10-k等。我
由于 Quanteda 中还没有现成的波兰语停用词实现,我想使用我自己的列表。我将其作为以空格分隔的列表形式保存在文本文件中。如果需要,我还可以准备一个以换行符分隔的列表。 如何从我的语料库中删除自定
我正在使用 quanteda 字典查找。我将尝试制定可以查找单词逻辑组合的条目。 例如: Teddybear = (fluffy AND adorable AND soft) 这可能吗?我只找到了一个
我有一些文本包含包含数字的短语,后跟一些符号。我想提取它们,例如,数字后跟百分比。使用 quanteda 包中的 kwic 函数似乎适用于数字作为正则表达式(例如 "\\d{1,}")。尽管如此,我没
我使用 quanteda 来构建文档术语矩阵: library(quanteda) mytext = "This is my old text" dtm <- dfm(mytext, tolower=
我有一个包含文档标记的字符向量列表。 list(doc1 = c("I", "like", "apples"), doc2 = c("You", "like", "apples", "too")) 我
我正在使用 Ken Benoit 和 Paul Nulty 的 quanteda 包来处理文本数据。 我的语料库包含带有完整德语句子的文本,我只想处理每个文本的名词。德语中的一个技巧是只使用大写单词,
我收到此警告消息。我使用这些数据: https://github.com/kbenoit/quanteda/tree/master/data/data_char_inaugural.RData RSt
我有一个包含 2 个文本字段的数据框:评论和主要帖子 基本上是这样的结构 id comment post_text
我正在尝试删除单字符和双字符标记。 这是一个例子: toks <- tokens(c("This is a sentence. This is a second sentence."), remove
有一个带有文本的数据框 df = data.frame(id=c(1,2), text = c("My best friend John works and Google", "However he
我正在尝试从数据文本分析中删除拼写错误。所以我使用 Quanteda 包的字典功能。对于 Unigrams 来说效果很好。但它为 Biggram 提供了意想不到的输出。不知道如何处理拼写错误,以免它们
我想分析一个大的(n=500,000)文档语料库。我使用 quanteda 期望 will be faster比 tm 中的 tm_map() 更好。我想逐步进行,而不是使用 dfm() 的自动化方式
我正在尝试删除单字符和双字符标记。 这是一个例子: toks <- tokens(c("This is a sentence. This is a second sentence."), remove
有一个带有文本的数据框 df = data.frame(id=c(1,2), text = c("My best friend John works and Google", "However he
Quanteda 包提供了稀疏文档特征矩阵 DFM,其方法包含 removeFeatures .我试过 dfm(x, removeFeatures="\\b[a-z]{1-3}\\b")删除太短的单词
所以我有一个 dfm_tfidf 并且我想过滤掉低于某个阈值的值。 代码: dfmat2 % as.dfm() #it works dfmat2 %>% dfm_trim(min_termfreq
我是一名优秀的程序员,十分优秀!