r parallel-processing text-mining tm doparallel

Comportamiento inconsistente con las funciones de transformación tm_map cuando se usan múltiples núcleos



parallel-processing text-mining (0)

Otro título potencial para esta publicación podría ser "Cuando el procesamiento paralelo en r, ¿la proporción entre el número de núcleos, el tamaño del fragmento de bucle y el tamaño del objeto es importante?

Tengo un corpus Estoy ejecutando algunas transformaciones al usar el paquete tm. Dado que el corpus es grande, estoy usando procesamiento paralelo con el paquete doparallel.

A veces las transformaciones hacen la tarea, pero a veces no lo hacen. Por ejemplo, tm::removeNumbers() . El primer documento en el corpus tiene un valor de contenido de "n417". Por lo tanto, si el preprocesamiento es exitoso, entonces este documento se transformará a solo "n".

El corpus de muestra se encuentra abajo para su reproducción. Aquí está el bloque de código:

library(tidyverse) library(qdap) library(stringr) library(tm) library(textstem) library(stringi) library(foreach) library(doParallel) library(SnowballC) corpus <- (see below) n <- 100 # this is the size of each chunk in the loop # split the corpus into pieces for looping to get around memory issues with transformation nr <- length(corpus) pieces <- split(corpus, rep(1:ceiling(nr/n), each=n, length.out=nr)) lenp <- length(pieces) rm(corpus) # save memory # save pieces to rds files since not enough RAM tmpfile <- tempfile() for (i in seq_len(lenp)) { saveRDS(pieces[[i]], paste0(tmpfile, i, ".rds")) } rm(pieces) # save memory # doparallel registerDoParallel(cores = 12) pieces <- foreach(i = seq_len(lenp)) %dopar% { piece <- readRDS(paste0(tmpfile, i, ".rds")) # regular transformations piece <- tm_map(piece, content_transformer(removePunctuation), preserve_intra_word_dashes = T) piece <- tm_map(piece, content_transformer(function(x, ...) qdap::rm_stopwords(x, stopwords = tm::stopwords("english"), separate = F))) piece <- tm_map(piece, removeNumbers) saveRDS(piece, paste0(tmpfile, i, ".rds")) return(1) # hack to get dopar to forget the piece to save memory since now saved to rds } stopImplicitCluster() # combine the pieces back into one corpus corpus <- list() corpus <- foreach(i = seq_len(lenp)) %do% { corpus[[i]] <- readRDS(paste0(tmpfile, i, ".rds")) } corpus_done <- do.call(function(...) c(..., recursive = TRUE), corpus)

Y here hay un enlace a datos de muestra. Necesito pegar una muestra suficientemente grande de 2k documentos para recrear y SO no me deja pegar tanto, así que por favor vea el documento vinculado para obtener información.

corpus <- VCorpus(VectorSource([paste the chr vector from link above]))

Si ejecuto mi bloque de código como arriba con n = a 200, mire los resultados y veo que los números permanecen donde deberían haber sido eliminados por tm::removeNumbers()

> lapply(1:10, function(i) print(corpus_done[[i]]$content)) %>% unlist [1] "n417" [1] "disturbance" [1] "grand theft auto"

Sin embargo, si cambio el tamaño del fragmento (el valor de la variable "n") a 100:

> lapply(1:10, function(i) print(corpus_done[[i]]$content)) %>% unlist [1] "n" [1] "disturbance" [1] "grand theft auto"

Los números han sido eliminados.

Pero, esto es inconsistente. Intenté reducirlo probando en 150, luego en 125 ... y descubrí que funcionaría o no funcionaría entre 120 y 125 unidades. Luego, después de iterar la función entre 120: 125, a veces funcionaría y luego no para el mismo tamaño de fragmento.

Creo que tal vez exista una relación con este problema entre 3 variables: el tamaño del corpus, el tamaño del fragmento y la cantidad de núcleos en registerdoparallel() . Simplemente no sé lo que es.

¿Puede alguien echar una mano o incluso reproducir con el corpus de muestra vinculado? Estoy preocupado ya que puedo reproducir el error a veces, otras veces no puedo. Cambiar el tamaño del trozo le da un tipo de habilidad para ver el error al eliminar números, pero no siempre.

Actualizar hoy Reanudé mi sesión y no pude replicar el error. Creé un Google Doc y experimenté con diferentes valores para el tamaño del cuerpo, la cantidad de núcleos y el tamaño de los trozos. En cada caso todo fue un éxito. Entonces, traté de correr en datos completos y todo funcionó. Sin embargo, para mi cordura, intenté correr de nuevo en datos completos y falló. Ahora, he vuelto a donde estaba ayer. Parece que haber ejecutado la función en un conjunto de datos más grande ha cambiado algo ... No sé qué. Tal vez una variable de sesión de algún tipo? Entonces, la nueva información es que este error solo ocurre después de ejecutar la función en un conjunto de datos muy grande. El reinicio de mi sesión no resolvió el problema, pero sí lo hizo al reanudar las sesiones después de haber estado ausente por varias horas.

Nueva información. Podría ser más fácil reproducir el problema en un corpus más grande ya que esto es lo que parece desencadenar el corpus <- do.call(c, replicate(250, corpus, simplify = F)) problema corpus <- do.call(c, replicate(250, corpus, simplify = F)) creará un corpus de 500k docs basado en el muestra que proporcioné La función puede funcionar la primera vez que la llamas, pero para mí parece fallar la segunda vez.

Este problema es difícil porque si pudiera reproducir el problema, probablemente podría identificarlo y solucionarlo.

Nueva información. Debido a que hay varias cosas que suceden con esta función, era difícil saber dónde enfocar los esfuerzos de depuración. Estaba viendo tanto el hecho de que estoy usando varios archivos RDS temporales para ahorrar memoria como el hecho de que estoy haciendo un procesamiento paralelo. Escribí dos versiones alternativas de la secuencia de comandos, una que aún usa los archivos rds y rompe el corpus pero no hace el procesamiento paralelo (reemplazé% dopar% con solo% do% y también eliminé la línea RegisterDoParallel) y una que usa el procesamiento paralelo pero no utiliza archivos temporales RDS para dividir el pequeño cuerpo de muestra. No pude producir el error con la versión de un solo núcleo del script, solo con la versión que usa% dopar% pude recrear el problema (aunque el problema es intermitente, no siempre falla con dopar). Entonces, este problema solo aparece cuando se usa %dopar% . El hecho de que esté usando archivos temp RDS no parece ser parte del problema.