R 中基于语言的处理:选择具有特定逐点互信息 (PMI) 值的 dfm 中的特征

Language based processing in R: Selecting features in dfm with certain pointwise mutual information (PMI) value

我想在我的 dfm 中保留 2-3 个单词的短语 (i.e.features),其 PMI 值大于短语中单词数的 3 倍*。

PMI在此定义为:pmi(phrase) = log(p(phrase)/Product(p(word))

与 p(phrase): 短语基于其相对频率的概率 Product(p(word): 短语中每个词的概率的乘积。

到目前为止,我使用了以下代码,但是 PMI 值似乎不正确,但我找不到问题所在:

#creating dummy data
id <- c(1:5)
text <- c("positiveemoticon my name is positiveemoticon positiveemoticon i love you", "hello dont", "i love you", "i love you", "happy birthday")
ids_text_clean_test <- data.frame(id, text)
ids_text_clean_test$id <- as.character(ids_text_clean_test$id)
ids_text_clean_test$text <- as.character(ids_text_clean_test$text)

test_corpus <- corpus(ids_text_clean_test[["text"]], docnames = ids_text_clean_test[["id"]])

tokens_all_test <- tokens(test_corpus, remove_punct = TRUE)

## Create a document-feature matrix(dfm)
doc_phrases_matrix_test <- dfm(tokens_all_test, ngrams = 2:3) #extracting two- and three word phrases
doc_phrases_matrix_test

# calculating the pointwise mututal information for each phrase to identify phrases that occur at rates much higher than chance
tcmrs = Matrix::rowSums(doc_phrases_matrix_test) #number of words per user
tcmcs = Matrix::colSums(doc_phrases_matrix_test) #counts of each phrase
N = sum(tcmrs) #number of total words used 
colp = tcmcs/N #proportion of the phrases by total phrases
rowp = tcmrs/N #proportion of each users' words used by total words used
pp = doc_phrases_matrix_test@p + 1
ip = doc_phrases_matrix_test@i + 1
tmpx = rep(0,length(doc_phrases_matrix_test@x)) # new values go here, just a numeric vector
# iterate through sparse matrix:
for (i in 1:(length(doc_phrases_matrix_test@p) - 1) ) {
  ind = pp[i]:(pp[i + 1] - 1)
  not0 = ip[ind]
  icol = doc_phrases_matrix_test@x[ind]
  tmp = log( (icol/N) / (rowp[not0] * colp[i] )) # PMI
  tmpx[ind] = tmp
}

doc_phrases_matrix_test@x = tmpx
doc_phrases_matrix_test

我认为 PMI 不应因用户而在一个短语内发生变化,但我认为将 PMI 直接应用于 dfm 会更容易,因此更容易根据功能 PMI 对其进行子集化。

我尝试的另一种方法是将 PMI 直接应用于特征:

test_pmi <- textstat_keyness(doc_phrases_matrix_test,  measure =  "pmi",
                             sort = TRUE)
test_pmi

但是,首先,我在这里收到一条警告,指出生成了 NaN,其次,我不明白 PMI 值(例如,为什么会有负值)?

有没有人知道如何根据上面定义的 PMI 值提取特征?

非常感谢任何提示:)

*遵循 Park 等人 (2015)

您可以使用以下使用 udpipe R 包的 R 代码来获取您所要求的内容。关于作为 udpipe

一部分的标记化 data.frame 的示例
library(udpipe) 
data(brussels_reviews_anno, package = "udpipe") 
x <- subset(brussels_reviews_anno, language %in% "fr") 

## find keywords with PMI > 3 
keyw <- keywords_collocation(x, term = "lemma", 
                             group = c("doc_id", "sentence_id"), ngram_max = 3, n_min = 10) 
keyw <- subset(keyw, pmi > 3) 

## recodes to keywords 
x$term <- txt_recode_ngram(x$lemma, compound = keyw$keyword, ngram = keyw$ngram) 
## create DTM 
dtm <- document_term_frequencies(x = x$term, document = x$doc_id) 
dtm <- document_term_matrix(dtm) 

如果你想得到一个结构类似于x的数据集。只需使用 udpipe(text, "english") 或您选择的任何语言。如果你想使用 quanteda 进行标记化,你仍然可以将它变成一个更好的丰富 data.frame - 给出的例子 here and here。寻求 udpipe R 包的帮助,它有很多小插曲 (?udpipe)。

请注意,PMI 很有用,使用 udpipe R 包的依赖项解析输出更有用。如果你查看 dep_rel 字段,你会发现那里有识别多词表达式的类别(例如 dep_rel fixed/flat/compound 是在 http://universaldependencies.org/u/dep/index.html 中定义的多词表达式)你也可以使用这些将它们放入您的 document/term/matrix