1

我正在为 NLP 开发一个项目。我需要在 .txt 文件中获取一些博客、新闻和推文(您可能已经听说过这个顶点)并创建 n-gram 频率。

我对将txt文件带到频率data frame进行分析的步骤进行了实验:

Read > Conver to corpus > Clean corpus > Tokenize > Convert to dfm > Convert to df

该过程中的瓶颈是标记化和转换为 dfm 步骤(超过 5 倍以上的时间)。

我有两个选择:

1. Split the cleaned corpus to tokenize by piece
2. Split-read the .txt files from the beginning

No. 1 似乎是最好的,但到目前为止,我还没有找到可以以我想要的方式执行此操作的函数或包。所以我会写一个很长的代码,从头开始拆分读取 20 个块(由于我的计算限制)。

有没有办法可以将使用quanteda包创建的语料库(“语料库”“列表”)拆分成块(由我定义的行),以便我可以以“流式”的方式标记化并转向 dfm?

4

2 回答 2

1

由于这个问题还没有直接回答,所以我将我在 2016 年作为 JHU Capstone 的社区导师撰写的文章中的相关内容重新发布,Capstone n-grams:需要多少处理能力?

概述

约翰霍普金斯大学数据科学专业 Capstone 课程的学生通常会在课程项目中遇到困难,因为分析文本所需的对象会消耗大量内存。该问题询问处理原始数据文件中的 4+ 百万个文档的最佳方法。这个问题的简短回答是,它取决于机器上的 RAM 量。由于 R 对象必须驻留在 RAM 中,因此必须了解正在处理的对象消耗的 RAM 量。

需要一台具有 16Gb RAM 的机器来处理这三个文件中的所有数据,而不需要以较小的块进行处理或处理随机数据样本。我的测试表明,处理文件所需的工作内存大约是0.99.22 版quanteda::tokens_ngrams()函数输出的对象大小的 1.5 - 3 倍quanteda,因此是 1 Gb 的标记化语料库并消耗 9 Gb 的 RAM 来生成 4 Gb n-gram 对象。请注意,quanteda如果您的计算机具有多个内核/线程,则会自动使用多个线程。

为了帮助减少内存利用率的猜测,这里总结了分析 Swift Key 赞助的顶点文件所需的对象消耗的 RAM 量:预测文本。

原始数据

Capstone 项目中使用了三个原始数据文件。一旦使用诸如readLines()orreadr::read_lines()之类的文本处理函数加载到内存中,生成的对象大小如下。

  1. en_US.blogs.txt:249 Mb
  2. en_US.news.txt:250 Mb
  3. en_US.twitter.txt:301 Mb

这些文件必须连接到单个对象中并转换为语料库。它们一起消耗大约 800 Mb 的 RAM。

转换为语料库时quanteda::corpus(),生成的文件大小为 1.1 Gb。

N-gram 对象大小

为了最大化可用于 n-gram 处理的 RAM 量,一旦生成语料库,必须从内存中删除所有对象,而不是用作输入的标记化语料库tokens_ngrams()。各种 n-gram 的对象大小如下。

  1. 2 克:6.3 Gb
  2. 3 克:6.5 Gb
  3. 4 克:6.5 Gb
  4. 5 克:6.3 Gb
  5. 6 克:6.1 Gb

使用更少的内存

我能够在具有 8 Gb RAM 的 MacBook Pro 上处理 25% 的顶点数据样本,以及在运行 Ubuntu Linux 和 4 Gb RAM 的 HP Chromebook 上处理 5% 的样本。

对象大小:25% 样本

  1. 2 克:2.0 Gb
  2. 3 克:2.9 Gb
  3. 4 克:3.6 Gb
  4. 5 克:3.9 Gb
  5. 6 克:4.0 Gb

对象大小:5% 样本

  1. 2 克:492 Mb
  2. 3 克:649 Mb
  3. 4 克:740 Mb
  4. 5 克:747 Gb
  5. 6 克:733 Gb

以较小的组处理数据

添加到 Ken Benoit 对原始问题的评论中,可以分配一个数字组(例如,重复 1 - 20 的 ID 以拆分为 20 个组),然后使用该corpus_segment()功能在组 ID 上分割语料库。但是,这种方法会导致语料库被标记,而不是物理拆分。生成所有所需 n-gram 的一般过程在以下伪代码中表示。

 split the raw data into a list of <n> groups for processing
 create a list of corpuses 
 for each corpus
     for each size n-gram 
           1. generate n-grams
           2. write to file
           3. rm() n-gram object

swiftkey.zip一旦数据被下载并从文件中提取,用于将语料库拆分为列表并处理一组 n-gram 的代码如下所示。

library(readr)
library(data.table)
blogFile <- "./capstone/data/en_us.blogs.txt"
newsFile <- "./capstone/data/en_us.news.txt"
twitterFile <- "./capstone/data/en_us.twitter.txt"
blogData <- read_lines(blogFile)
newsData <- read_lines(newsFile)
twitterData <- read_lines(twitterFile) 
allData <- c(blogData,newsData,twitterData) # about 800mb file
rm(blogData,newsData,twitterData,blogFile,newsFile,twitterFile)

# create 20 groups, and use to split original data into a list
groupId <- paste0("GROUP",sprintf("%02.0f",(1:length(allData) %% 20)+1))
split_data <- split(allData,groupId)
library(quanteda)
theTexts <- lapply(split_data,corpus)
system.time(ngram2 <- lapply(theTexts,function(x) tokens_ngrams(tokens(x),n=2))) 
head(ngram2[[1]]) 

请注意,在配备 i7 Intel 处理器的 MacBook Pro 上,生成 n-ngram 大约需要 10 分钟,结果输出ngram2是 20 组 2-gram 的列表。

...第一组中前三个文本的输出是:

> head(ngram2[[1]])
Tokens consisting of 6 documents.
text1 :
[1] "Fallout_by"    "by_Ellen"      "Ellen_Hopkins" "Hopkins_("     "(_p"          
[6] "p_."           "._1-140"       "1-140_)"      

text2 :
 [1] "Ed_Switenky"         "Switenky_,"          ",_manager"          
 [4] "manager_of"          "of_traffic"          "traffic_engineering"
 [7] "engineering_and"     "and_operations"      "operations_,"       
[10] ",_couldn't"          "couldn't_comment"    "comment_on"         
[ ... and 21 more ]

text3 :
[1] "the_autumn"       "autumn_rains"     "rains_in"         "in_righteousness"
[5] "righteousness_." 

将文件写入磁盘以节省内存的附加代码,以及在处理之前清理数据并将 n-gram 合并到频率表中的代码,留给学生工作。

于 2018-01-02T22:28:56.200 回答
0

我认为你会发现目前最有用的包是 tm 包。它是一个相当复杂但完整的包,尽管它在 .7.1 版本中仍处于实验状态。如果没有更多详细信息,我无法为您提供更准确的使用信息,因为这完全取决于您的来源、您希望如何处理语料库和其他因素。您需要做的要点是首先根据您的源材料创建一个阅读器对象。它可以处理网络输入、纯文本、pdf 等。然后,您可以使用语料库创建功能之一,具体取决于您是否要将整个内容保存在内存中等。然后您可以使用各种“整理”功能对整个语料库进行操作,就好像每个文档都是向量中的一个元素一样. 您可以对标记化执行相同的操作。

于 2017-05-25T06:32:16.863 回答