quanteda 中的 tokens_compound() 改变了特征的顺序
tokens_compound() in quanteda changes the order of features
我发现 quanteda 中的 tokens_compound()
更改了不同 R 会话中标记的顺序。也就是说,即使种子值是固定的,每次重新启动会话后结果都会有所不同,尽管它在单个会话中不会改变。
复制过程如下:
- 查找搭配、复合标记并保存。
library(quanteda)
set.seed(12345)
data(data_corpus_inaugural)
toks <- data_corpus_inaugural %>%
tokens(remove_punct = TRUE,
remove_symbol = TRUE,
padding = TRUE) %>%
tokens_tolower()
col <- toks %>%
textstat_collocations()
toks.col <- toks %>%
tokens_compound(pattern = col[col$z > 3])
write(attr(toks.col, "types"), "col1.txt")
结束并重新启动 R 会话并再次 运行 上述代码,将“col1.txt”替换为“col2.txt”。
比较两组token,发现不一样
col1 <- read.table("col1.txt")
col2 <- read.table("col2.txt")
identical(col1$V1, col2$V1) # This should return FALSE.
col1$V1[head(which(col1$V1 != col2$V1))]
col2$V1[head(which(col1$V1 != col2$V1))]
这在很多情况下并不重要,但 LDA(通过 {topicmodels})的结果在不同的会话中会发生变化。我猜是这样,因为如果我将 tokens
中的特征顺序重置为 as.list()
然后 as.tokens()
(dfm_sort()
不适用于此)。
我想知道这是否只发生在我身上(Ubuntu 18.04.5、R 4.0.4 和 quanteda 2.1.2),很高兴听到另一个(更简单的)解决方案。
2 月 20 日更新
比如LDA的输出没有复现
lis <- list()
for (i in seq_len(2)) {
set.seed(123)
lis[[i]] <- tokens_compound(toks, pattern = col[col$z > 3]) %>%
dfm() %>%
convert(to = "topicmodels") %>%
LDA(k = 5,
method = "Gibbs",
control = list(seed = 12345,
iter = 100))
}
head(lis[[1]]@gamma)
head(lis[[2]]@gamma)
一项有趣的调查,但这既不是错误,也不是什么值得关注的事情。在 quanteda 令牌对象中,在 textstat_compound()
等处理步骤之后,类型的顺序是不确定的。这是因为此函数在 C++ 中是并行化的,并且这些线程的操作方式并未由 R 中的 set.seed()
确定。但这不会影响重要部分,即类型集或有关标记本身的任何内容。如果你希望你提取的类型的顺序相同,那么你应该在提取时对它们进行排序。
library("quanteda")
## Package version: 2.1.2
toks <- data_corpus_inaugural %>%
tokens(
remove_punct = TRUE,
remove_symbol = TRUE,
padding = TRUE
) %>%
tokens_tolower()
col <- quanteda.textstats::textstat_collocations(toks)
事实证明,您不需要保存输出或重新启动 R - 这会在单个会话中发生。
# types are differently indexed, but are the same set
lis <- list()
for (i in seq_len(2)) {
set.seed(123)
toks.col <- tokens_compound(toks, pattern = col[col$z > 3])
lis <- c(lis, list(types = types(toks.col)))
}
dframe <- data.frame(lis)
sum(dframe$types != dframe$types.1)
## [1] 19898
head(dframe[dframe$types != dframe$types.1, ])
## types types.1
## 8897 at_this_second my_fellow_citizens
## 8898 to_take_the_oath_of_the_presidential_office no_people
## 8899 there_is on_earth
## 8900 occasion_for cause_to_be_thankful
## 8901 an_extended this_is_said
## 8902 there_was spirit_of
但是(无序的)类型集是相同的:
# but
setequal(dframe$types, dframe$types.1)
## [1] TRUE
更重要的是,当我们比较有序的每个标记的值时,它们是相同的:
# tokens are the same
lis <- list()
for (i in seq_len(2)) {
set.seed(123)
toks.col <- tokens_compound(toks, pattern = col[col$z > 3])
lis <- c(lis, list(toks = as.character(toks.col)))
}
dframe <- data.frame(lis)
all.equal(dframe$toks, dframe$toks.1)
## [1] TRUE
由 reprex package (v1.0.0)
于 2021-02-18 创建
附加评论,此分析强调了其重要性:我们强烈反对直接访问对象属性。如上所述使用 types(x)
,而不是 attr(x, "types")
。前者将永远有效。后者依赖于我们对对象的实现,它可能会随着我们改进包而改变。
我发现 quanteda 中的 tokens_compound()
更改了不同 R 会话中标记的顺序。也就是说,即使种子值是固定的,每次重新启动会话后结果都会有所不同,尽管它在单个会话中不会改变。
复制过程如下:
- 查找搭配、复合标记并保存。
library(quanteda)
set.seed(12345)
data(data_corpus_inaugural)
toks <- data_corpus_inaugural %>%
tokens(remove_punct = TRUE,
remove_symbol = TRUE,
padding = TRUE) %>%
tokens_tolower()
col <- toks %>%
textstat_collocations()
toks.col <- toks %>%
tokens_compound(pattern = col[col$z > 3])
write(attr(toks.col, "types"), "col1.txt")
结束并重新启动 R 会话并再次 运行 上述代码,将“col1.txt”替换为“col2.txt”。
比较两组token,发现不一样
col1 <- read.table("col1.txt")
col2 <- read.table("col2.txt")
identical(col1$V1, col2$V1) # This should return FALSE.
col1$V1[head(which(col1$V1 != col2$V1))]
col2$V1[head(which(col1$V1 != col2$V1))]
这在很多情况下并不重要,但 LDA(通过 {topicmodels})的结果在不同的会话中会发生变化。我猜是这样,因为如果我将 tokens
中的特征顺序重置为 as.list()
然后 as.tokens()
(dfm_sort()
不适用于此)。
我想知道这是否只发生在我身上(Ubuntu 18.04.5、R 4.0.4 和 quanteda 2.1.2),很高兴听到另一个(更简单的)解决方案。
2 月 20 日更新
比如LDA的输出没有复现
lis <- list()
for (i in seq_len(2)) {
set.seed(123)
lis[[i]] <- tokens_compound(toks, pattern = col[col$z > 3]) %>%
dfm() %>%
convert(to = "topicmodels") %>%
LDA(k = 5,
method = "Gibbs",
control = list(seed = 12345,
iter = 100))
}
head(lis[[1]]@gamma)
head(lis[[2]]@gamma)
一项有趣的调查,但这既不是错误,也不是什么值得关注的事情。在 quanteda 令牌对象中,在 textstat_compound()
等处理步骤之后,类型的顺序是不确定的。这是因为此函数在 C++ 中是并行化的,并且这些线程的操作方式并未由 R 中的 set.seed()
确定。但这不会影响重要部分,即类型集或有关标记本身的任何内容。如果你希望你提取的类型的顺序相同,那么你应该在提取时对它们进行排序。
library("quanteda")
## Package version: 2.1.2
toks <- data_corpus_inaugural %>%
tokens(
remove_punct = TRUE,
remove_symbol = TRUE,
padding = TRUE
) %>%
tokens_tolower()
col <- quanteda.textstats::textstat_collocations(toks)
事实证明,您不需要保存输出或重新启动 R - 这会在单个会话中发生。
# types are differently indexed, but are the same set
lis <- list()
for (i in seq_len(2)) {
set.seed(123)
toks.col <- tokens_compound(toks, pattern = col[col$z > 3])
lis <- c(lis, list(types = types(toks.col)))
}
dframe <- data.frame(lis)
sum(dframe$types != dframe$types.1)
## [1] 19898
head(dframe[dframe$types != dframe$types.1, ])
## types types.1
## 8897 at_this_second my_fellow_citizens
## 8898 to_take_the_oath_of_the_presidential_office no_people
## 8899 there_is on_earth
## 8900 occasion_for cause_to_be_thankful
## 8901 an_extended this_is_said
## 8902 there_was spirit_of
但是(无序的)类型集是相同的:
# but
setequal(dframe$types, dframe$types.1)
## [1] TRUE
更重要的是,当我们比较有序的每个标记的值时,它们是相同的:
# tokens are the same
lis <- list()
for (i in seq_len(2)) {
set.seed(123)
toks.col <- tokens_compound(toks, pattern = col[col$z > 3])
lis <- c(lis, list(toks = as.character(toks.col)))
}
dframe <- data.frame(lis)
all.equal(dframe$toks, dframe$toks.1)
## [1] TRUE
由 reprex package (v1.0.0)
于 2021-02-18 创建附加评论,此分析强调了其重要性:我们强烈反对直接访问对象属性。如上所述使用 types(x)
,而不是 attr(x, "types")
。前者将永远有效。后者依赖于我们对对象的实现,它可能会随着我们改进包而改变。