2013-08-21 23 views
8

Sto provando a utilizzare parte del tag vocale dai pacchetti openNLP/NLP in parallelo. Ho bisogno che il codice funzioni su qualsiasi sistema operativo, quindi opto per utilizzare la funzione parLapply da parallela (ma sono aperta ad altre opzioni indipendenti del sistema operativo). In passato ho eseguito la funzione tagPOS dal pacchetto openNLP in parLapply senza problemi. Tuttavia, il pacchetto openNLP ha avuto alcune modifiche recenti che hanno eliminato tagPOS e aggiunto alcune opzioni più flessibili. Kurt è stato così gentile da aiutarmi a ricreare la funzione tagPOS dagli strumenti del nuovo pacchetto. Posso far funzionare la versione lapply ma non la versione parallela. Continua a dire che i nodi hanno bisogno di più variabili passate a loro finché non chiede finalmente una funzione non esportata da openNLP. Sembra strano che continuerebbe a chiedere che vengano passate sempre più variabili che mi dicono che sto configurando lo parLapply in modo errato. Come posso configurare il tagPOS per operare in modo parallelo, indipendente dal sistema operativo?impostazione parallela parLapp

library(openNLP) 
library(NLP) 
library(parallel) 

## POS tagger 
tagPOS <- function(x, pos_tag_annotator, ...) { 
    s <- as.String(x) 
    ## Need sentence and word token annotations. 
    word_token_annotator <- Maxent_Word_Token_Annotator() 
    a2 <- Annotation(1L, "sentence", 1L, nchar(s)) 
    a2 <- annotate(s, word_token_annotator, a2) 
    a3 <- annotate(s, pos_tag_annotator, a2) 

    ## Determine the distribution of POS tags for word tokens. 
    a3w <- a3[a3$type == "word"] 
    POStags <- unlist(lapply(a3w$features, `[[`, "POS")) 

    ## Extract token/POS pairs (all of them): easy. 
    POStagged <- paste(sprintf("%s/%s", s[a3w], POStags), collapse = " ") 
    list(POStagged = POStagged, POStags = POStags) 
} ## End of tagPOS function 

## Set up a parallel run 
text.var <- c("I like it.", "This is outstanding soup!", 
    "I really must get the recipe.") 
ntv <- length(text.var) 
PTA <- Maxent_POS_Tag_Annotator() 

cl <- makeCluster(mc <- getOption("cl.cores", detectCores()/2)) 
clusterExport(cl=cl, varlist=c("text.var", "ntv", 
    "tagPOS", "PTA", "as.String", "Maxent_Word_Token_Annotator"), 
    envir = environment()) 
m <- parLapply(cl, seq_len(ntv), function(i) { 
     x <- tagPOS(text.var[i], PTA) 
     return(x) 
    } 
) 
stopCluster(cl) 

## Error in checkForRemoteErrors(val) : 
## 3 nodes produced errors; first error: could not find function 
## "Maxent_Simple_Word_Tokenizer" 

openNLP::Maxent_Simple_Word_Tokenizer 

## >openNLP::Maxent_Simple_Word_Tokenizer 
## Error: 'Maxent_Simple_Word_Tokenizer' is not an exported 
##  object from 'namespace:openNLP' 

## It's a non exported function 
openNLP:::Maxent_Simple_Word_Tokenizer 


## Demo that it works with lapply 
lapply(seq_len(ntv), function(i) { 
    tagPOS(text.var[i], PTA) 
}) 

lapply(text.var, function(x) { 
    tagPOS(x, PTA) 
}) 

## >  lapply(seq_len(ntv), function(i) { 
## +   tagPOS(text.var[i], PTA) 
## +  }) 
## [[1]] 
## [[1]]$POStagged 
## [1] "I/PRP like/IN it/PRP ./." 
## 
## [[1]]$POStags 
## [1] "PRP" "IN" "PRP" "." 
## 
## [[1]]$word.count 
## [1] 3 
## 
## 
## [[2]] 
## [[2]]$POStagged 
## [1] "THis/DT is/VBZ outstanding/JJ soup/NN !/." 
## 
## [[2]]$POStags 
## [1] "DT" "VBZ" "JJ" "NN" "." 
## 
## [[2]]$word.count 
## [1] 4 
## 
## 
## [[3]] 
## [[3]]$POStagged 
## [1] "I/PRP really/RB must/MD get/VB the/DT recip/NN ./." 
## 
## [[3]]$POStags 
## [1] "PRP" "RB" "MD" "VB" "DT" "NN" "." 
## 
## [[3]]$word.count 
## [1] 6 

EDIT: per suggerimento di Steve

Annotare l'openNLP è nuovo di zecca. Ho installato ver 2.1 da un tar.gz da CRAN. Ottengo il seguente errore anche se questa funzione esiste.

libreria (openNLP); biblioteca (NLP); biblioteca (parallela)

tagPOS <- function(text.var, pos_tag_annotator, ...) { 
    s <- as.String(text.var) 

    ## Set up the POS annotator if missing (for parallel) 
    if (missing(pos_tag_annotator)) { 
     PTA <- Maxent_POS_Tag_Annotator() 
    } 

    ## Need sentence and word token annotations. 
    word_token_annotator <- Maxent_Word_Token_Annotator() 
    a2 <- Annotation(1L, "sentence", 1L, nchar(s)) 
    a2 <- annotate(s, word_token_annotator, a2) 
    a3 <- annotate(s, PTA, a2) 

    ## Determine the distribution of POS tags for word tokens. 
    a3w <- a3[a3$type == "word"] 
    POStags <- unlist(lapply(a3w$features, "[[", "POS")) 

    ## Extract token/POS pairs (all of them): easy. 
    POStagged <- paste(sprintf("%s/%s", s[a3w], POStags), collapse = " ") 
    list(POStagged = POStagged, POStags = POStags) 
} 

text.var <- c("I like it.", "This is outstanding soup!", 
    "I really must get the recipe.") 

cl <- makeCluster(mc <- getOption("cl.cores", detectCores()/2)) 
clusterEvalQ(cl, {library(openNLP); library(NLP)}) 
m <- parLapply(cl, text.var, tagPOS) 

## > m <- parLapply(cl, text.var, tagPOS) 
## Error in checkForRemoteErrors(val) : 
## 3 nodes produced errors; first error: could not find function "Maxent_POS_Tag_Annotator" 

stopCluster(cl) 


> packageDescription('openNLP') 
Package: openNLP 
Encoding: UTF-8 
Version: 0.2-1 
Title: Apache OpenNLP Tools Interface 
[email protected]: person("Kurt", "Hornik", role = c("aut", "cre"), email = 
      "[email protected]") 
Description: An interface to the Apache OpenNLP tools (version 1.5.3). The Apache OpenNLP 
      library is a machine learning based toolkit for the processing of natural language 
      text written in Java. It supports the most common NLP tasks, such as tokenization, 
      sentence segmentation, part-of-speech tagging, named entity extraction, chunking, 
      parsing, and coreference resolution. See http://opennlp.apache.org/ for more 
      information. 
Imports: NLP (>= 0.1-0), openNLPdata (>= 1.5.3-1), rJava (>= 0.6-3) 
SystemRequirements: Java (>= 5.0) 
License: GPL-3 
Packaged: 2013-08-20 13:23:54 UTC; hornik 
Author: Kurt Hornik [aut, cre] 
Maintainer: Kurt Hornik <[email protected]> 
NeedsCompilation: no 
Repository: CRAN 
Date/Publication: 2013-08-20 15:41:22 
Built: R 3.0.1; ; 2013-08-20 13:48:47 UTC; windows 

risposta

5

Dal momento che si sta chiamando funzioni dal NLP sui lavoratori a grappolo, si dovrebbe caricarlo su ciascuno dei lavoratori prima di chiamare parLapply. Puoi farlo dalla funzione operaio, ma io tendo a usare clusterCall o clusterEvalQ destra dopo aver creato l'oggetto cluster:

clusterEvalQ(cl, {library(openNLP); library(NLP)}) 

Dal as.String e Maxent_Word_Token_Annotator sono in quei pacchetti, non dovrebbero essere esportate.

Nota che durante l'esecuzione del tuo esempio sulla mia macchina, ho notato che l'oggetto PTA non funziona dopo essere stato esportato sulle macchine worker. Presumibilmente c'è qualcosa in quell'oggetto che non può essere serializzato in modo sicuro e non serializzato. Dopo aver creato quell'oggetto sui lavoratori utilizzando clusterEvalQ, l'esempio è stato eseguito correttamente. Eccolo, utilizzando openNLP 0,2-1:

library(parallel) 
tagPOS <- function(x, ...) { 
    s <- as.String(x) 
    word_token_annotator <- Maxent_Word_Token_Annotator() 
    a2 <- Annotation(1L, "sentence", 1L, nchar(s)) 
    a2 <- annotate(s, word_token_annotator, a2) 
    a3 <- annotate(s, PTA, a2) 
    a3w <- a3[a3$type == "word"] 
    POStags <- unlist(lapply(a3w$features, `[[`, "POS")) 
    POStagged <- paste(sprintf("%s/%s", s[a3w], POStags), collapse = " ") 
    list(POStagged = POStagged, POStags = POStags) 
} 
text.var <- c("I like it.", "This is outstanding soup!", 
    "I really must get the recipe.") 
cl <- makeCluster(mc <- getOption("cl.cores", detectCores()/2)) 
clusterEvalQ(cl, { 
    library(openNLP) 
    library(NLP) 
    PTA <- Maxent_POS_Tag_Annotator() 
}) 
m <- parLapply(cl, text.var, tagPOS) 
print(m) 
stopCluster(cl) 

Se clusterEvalQ fallisce perché Maxent_POS_Tag_Annotator non viene trovato, si potrebbe essere caricata la versione sbagliata di openNLP ai lavoratori. È possibile determinare quali versioni dei pacchetti che stai ricevendo sui lavoratori eseguendo sessionInfo con clusterEvalQ:

library(parallel) 
cl <- makeCluster(2) 
clusterEvalQ(cl, {library(openNLP); library(NLP)}) 
clusterEvalQ(cl, sessionInfo()) 

Ciò restituirà i risultati dell'esecuzione sessionInfo() su ciascuno dei lavoratori del cluster. Ecco le informazioni sulla versione per alcuni dei pacchetti che sto utilizzando e che funzionano per me:

other attached packages: 
[1] NLP_0.1-0  openNLP_0.2-1 

loaded via a namespace (and not attached): 
[1] openNLPdata_1.5.3-1 rJava_0.9-4 
+0

Grazie per l'informazione. Lo stesso errore persiste però. –

+0

@TylerRinker Ti aiuta se non esporti esplicitamente Maxent_Word_Token_Annototator? –

+0

Steve Grazie ancora per il tuo tempo. Ho fatto lo stesso errore. Vedi la mia modifica sopra. Puoi provare con openNLP 2.1. Non posso provare 2.0 perché non ho Internet sul mio computer. Notare i nuovi nomi per le funzioni in 2.1 –