Я ищу эффективный способ создать матрицу совместной встречаемости терминов для (каждого) целевого слова в корпусе, чтобы каждое вхождение слова составляло свой собственный вектор (строку) в tcm , где столбцы - это контекстные слова (т. е. модель совместной встречаемости на основе токенов). Это контрастирует с более распространенной оценкой, используемой в векторной семантике, где каждый термин (тип) получает строку и столбец в симметричном tcm, а значения агрегируются по (совместным) вхождениям токенов типов.
Очевидно, это можно сделать с нуля, используя базовую функциональность R, или взломать, отфильтровав tcm, сгенерированный одним из существующих пакетов, которые это делают, но данные корпуса, с которыми я имею дело, довольно большие (миллионы слов) - и есть уже доступные пакеты corpus / NLP для R, которые эффективно выполняют такого рода задачи и сохраняют результаты в удобных для памяти разреженных матрицах, таких как text2vec
(функция tcm
), quanteda (fcm
) и tidytext (cast_dtm
). Поэтому не имеет смысла изобретать велосипед (с точки зрения итераторов, хеширования и прочего). Но я также не могу найти простой способ создать tcm на основе токенов с любым из них; отсюда и этот вопрос.
Минимальный пример:
library(text2vec)
library(Matrix)
library(magrittr)
# default approach to tcm with text2vec:
corpus = strsplit(c("here is a short document", "here is a different short document"), " ")
it = itoken(corpus)
tcm = create_vocabulary(it) %>% vocab_vectorizer() %>% create_tcm(it, . , skip_grams_window = 2, weights = rep(1,2))
# results in this:
print(as.matrix(forceSymmetric(tcm, "U")))
different here short document is a
different 0 0 1 1 1 1
here 0 0 0 0 2 2
short 1 0 0 2 1 2
document 1 0 2 0 0 1
is 1 2 1 0 0 2
a 1 2 2 1 2 0
Попытка получить модель на основе токенов, для целевого слова «короткий»:
i=0
corpus = lapply(corpus, function(x)
ifelse(x == "short", {i<<-i+1;paste0("short", i)}, x )
) # appends index to each occurrence so itoken distinguishes them
it = itoken(corpus)
tcm = create_vocabulary(it) %>% vocab_vectorizer() %>% create_tcm(it, . , skip_grams_window = 2, weights = rep(1,2))
attempt = as.matrix(forceSymmetric(tcm, "U") %>%
.[grep("^short", rownames(.)), -grep("^short", colnames(.))]
) # filters the resulting full tcm
# yields intended result but is hacky/slow:
print(attempt)
different here document is a
short2 1 0 1 0 1
short1 0 0 1 1 1
Что является лучшей / более быстрой альтернативой этому подходу для получения tcm на основе токенов, как в последнем примере? (возможно, используя один из пакетов R, который уже выполняет tcms на основе типов)