PolMine / bignlp

Tools to process large corpora line-by-line and in parallel mode
1 stars 1 forks source link

Different results of byline and in-memory processing #20

Closed ablaette closed 3 years ago

ablaette commented 3 years ago

This is an example of Christoph Leonhardt that the two different methods described in the (new) package vignette may yield different results.

options(java.parameters = "-Xmx4g")

library(bignlp)
library(data.table)
library(magrittr)

sample_dt <- data.table(
  id = 1:2,
  text = c(
    "Vielen Dank. – Herr Präsident! Meine Damen und Herren! Am 25. März haben wir hier das COVID‑19-Insolvenzaussetzungsgesetz beschlossen, um die gesetzliche Pflicht zur Stellung eines Insolvenzantrags für Unternehmen, die durch die staatlichen Coronamaßnahmen zahlungsunfähig oder überschuldet werden, für sechs Monate auszusetzen. Wir als AfD-Fraktion haben diesem Gesetz damals zugestimmt. Die Begründung dafür ist auch rückblickend richtig – Zitat –:",
    "Vielen Dank. – Herr Präsident! Meine Damen und Herren! Am 25. März haben wir hier das COVID‑19-Insolvenzaussetzungsgesetz beschlossen, um die gesetzliche Pflicht zur Stellung eines Insolvenzantrags für Unternehmen, die durch die staatlichen Coronamaßnahmen zahlungsunfähig oder überschuldet werden, für sechs Monate auszusetzen. Wir als AfD-Fraktion haben diesem Gesetz damals zugestimmt. Die Begründung dafür ist auch rückblickend richtig – Zitat –:")
)

First the approach using temporary files.

props_file <- corenlp_get_properties_file(lang = "de", fast = TRUE)
props <- properties(x = props_file) %>% 
  properties_set_output_format("conll") %>%
  properties_set_threads(parallel::detectCores() - 1L)

Pipe <- StanfordCoreNLP$new(properties = props, output_format = "conll")
Pipe$verbose(FALSE)

segdirs <- segment(x = sample_dt, dir = (nlpdir <- tempdir()), chunksize = 1)
conll_files <- lapply(segdirs, Pipe$process_files)
Sys.sleep(0.5) # Java may still be working while R is moving on - then files are missing
df1 <- rbindlist(lapply(unlist(conll_files), fread, blank.lines.skip = TRUE, quote = "", header = FALSE))

Now using the in-memory approach ...

df2 <- corenlp_annotate(
  sample_dt,
  properties = properties(props_file),
  progress = FALSE
)

But now df2 is shorter - see where the tokenstreams are different.

df3 <- cbind(df1[, 2], df2[, 3])
DT::datatable(df3[20:24,], colnames = c("split-apply-combine", "Multithreading without temporary files"))
ablaette commented 3 years ago

This is not a CoreNLP issue, but results from a preprocessing corenlp_annotate() applies implicitly by default that the $process_files() approach doesn't (= calling purge()). In the most bignlp version on the dev branch, I introduced that argument purge so that we can control whether purge() is called. If we set the argument to FALSE, the result of the annotation df1 and df2 will have the same length.

df2 <- corenlp_annotate(
  sample_dt,
  properties = properties(props_file),
  progress = FALSE,
  purge = TRUE
)
ablaette commented 3 years ago

A unit test checks that results are identical now.