Как представить каждое вхождение слова как отдельный вектор tcm в R? - PullRequest
0 голосов
/ 23 октября 2018

Я ищу эффективный способ создания матрицы совпадений терминов для (каждого) целевого слова в корпусе, чтобы каждое вхождение слова составляло свой собственный вектор (строку) вtcm, где столбцы - это слова контекста (т. е. модель совместного использования на основе токенов).Это контрастирует с более распространенным подходом, используемым в векторной семантике, где каждый член (тип) получает строку и столбец в симметричном tcm, а значения агрегируются по (со) вхождениям токенов типов.

Очевидно, что это можно сделать с нуля, используя базовую функциональность R, или взломать, отфильтровав tcm, сгенерированный одним из существующих пакетов, которые делают это, но данные корпуса, с которыми я имею дело, довольно велики (миллионыслова) - и для R уже есть хорошие пакеты корпусов / НЛП, которые эффективно выполняют такие задачи и сохраняют результаты в разреженных матрицах, таких как text2vec (функция tcm), quanteda (fcm)) и тидитекст (cast_dtm).Поэтому, кажется, нет смысла пытаться заново изобрести колесо (с точки зрения итераторов, хэширования и тому подобного).Но я не могу найти простой способ создания токена на основе токена с любым из них;отсюда этот вопрос.

Минимальный пример:

  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

Попытка получить модель на основе токена, для целевого слова "short":

  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

Что лучше/ более быстрая альтернатива этому подходу для получения токена на основе токена, как в последнем примере?(возможно, с использованием одного из пакетов R, которые уже делают tcms на основе типов)

1 Ответ

0 голосов
/ 23 октября 2018
Fcm

quanteda - это очень эффективный способ создания матриц совместного использования объектов на уровне документа или в пользовательском контексте.Это приводит к разреженной, симметричной матрице признаков за особенностью.Но звучит так, будто вы хотите, чтобы каждая уникальная функция была отдельной строкой, а вокруг нее должны быть целевые слова

Из примера видно, что вам нужно контекстное окно из +/- 2 слов, поэтому я сделал это для целевого слова "short".

Сначала мы получаем контекст, используяключевые слова в контексте:

library("quanteda")
txt <- c("here is a short document", "here is a different short document")

(shortkwic <- kwic(txt, "short", window = 2))
#                                          
# [text1, 4]        is a | short | document
# [text2, 5] a different | short | document

Затем создайте корпус из контекста с ключевым словом в качестве уникального имени документа:

shortcorp <- corpus(shortkwic, split_context = FALSE, extract_keyword = TRUE)
docnames(shortcorp) <- make.unique(docvars(shortcorp, "keyword"))
texts(shortcorp)
#                 short                      short.1 
# "is a short document" "a different short document" 

Затем создайте dfm, выбрав все слова,но удаляя цель:

dfm(shortcorp) %>%
  dfm_select(dfm(txt)) %>%
  dfm_remove("short")
# Document-feature matrix of: 2 documents, 5 features (40% sparse).
# 2 x 5 sparse Matrix of class "dfm"
#          features
# docs      here is a document different
#   short      0  1 1        1         0
#   short.1    0  0 1        1         1
...