2013-08-21 6 views
8

Ich versuche, Teil der Rede Tagging von den openNLP/NLP-Pakete parallel zu verwenden. Ich brauche den Code, um auf jedem Betriebssystem zu arbeiten, also benutze ich die parLapply Funktion von parallel (aber offen für andere OS unabhängige Optionen). In der Vergangenheit lief ich tagPOS Funktion aus dem openNLP-Paket in parLapply ohne Problem. Das openNLP-Paket enthielt jedoch einige Änderungen, die tagPOS beseitigten und einige flexiblere Optionen hinzufügten. Kurt war so freundlich, mir dabei zu helfen, die tagPOS Funktion aus den Tools des neuen Pakets neu zu erstellen. Ich kann die lapply Version zu arbeiten, aber nicht die parallele Version. Es sagt weiter, dass die Knoten mehr Variablen benötigen, die an sie übergeben werden, bis sie schließlich nach einer nicht exportierten Funktion von openNLP fragen. Das scheint merkwürdig, es würde immer wieder nach immer mehr Variablen fragen, die mir sagen, dass ich die parLapply falsch einrichte. Wie kann ich den tagPOS so einrichten, dass er parallel und unabhängig vom Betriebssystem arbeitet?parallel parLapply setup

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: pro Steves Vorschlag

Notiere die openNLP ist ganz neu. Ich habe ver 2.1 von einem tar.gz von CRAN installiert. Ich erhalte den folgenden Fehler, obwohl diese Funktion existiert.

Bibliothek (openNLP); Bibliothek (NLP); Bibliothek (parallel)

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 

Antwort

5

Da Sie Funktionen von NLP auf den Cluster-Arbeiter fordern, können Sie es auf jeder der Arbeiter vor dem Aufruf parLapply laden sollte. Sie können von der Arbeiter-Funktion das tun, aber ich neige clusterCall oder clusterEvalQ direkt nach dem Erstellen des Cluster-Objekt zu verwenden:

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

Da as.String und Maxent_Word_Token_Annotator in diesen Paketen sind, sollten sie nicht exportiert werden.

Beachten Sie, dass beim Ausführen Ihres Beispiels auf meinem Computer festgestellt, dass das Objekt PTA nicht funktioniert, nachdem es auf den Arbeitscomputer exportiert wurde. Vermutlich befindet sich etwas in diesem Objekt, das nicht sicher serialisiert und unserialisiert werden kann. Nachdem ich dieses Objekt auf den Arbeitern mit clusterEvalQ erstellt hatte, wurde das Beispiel erfolgreich ausgeführt. Hier ist sie, mit 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) 

Wenn clusterEvalQ schlägt fehl, da Maxent_POS_Tag_Annotator nicht gefunden wird, müssen Sie möglicherweise die falsche Version von openNLP auf die Arbeiter werden geladen. Sie können bestimmen, welche Paketversionen Sie auf die Arbeiter durch die Ausführung sessionInfo mit clusterEvalQ sind immer:

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

Dadurch kehren die Ergebnisse der Ausführung sessionInfo() auf jedem der Cluster Arbeiter. Hier ist die Versionsinformation für einige der Pakete, die ich benutze und die für mich arbeiten:

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

Vielen Dank für die Informationen. Derselbe Fehler bleibt jedoch bestehen. –

+0

@TylerRinker Hilft es, wenn Maxent_Word_Token_Annotator nicht explizit exportiert wird? –

+0

Steve Vielen Dank noch einmal für Ihre Zeit. Ich bekomme den gleichen Fehler. Siehe meine Bearbeitung oben. Kannst du es mit openNLP 2.1 versuchen? Ich kann 2.0 nicht versuchen, da ich kein Internet zu meinem Computer habe. Beachten Sie die neuen Namen für Funktionen in 2.1 –