由于这个问题还没有直接回答,所以我将我在 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()
之类的文本处理函数加载到内存中,生成的对象大小如下。
- en_US.blogs.txt:249 Mb
- en_US.news.txt:250 Mb
- en_US.twitter.txt:301 Mb
这些文件必须连接到单个对象中并转换为语料库。它们一起消耗大约 800 Mb 的 RAM。
转换为语料库时quanteda::corpus()
,生成的文件大小为 1.1 Gb。
N-gram 对象大小
为了最大化可用于 n-gram 处理的 RAM 量,一旦生成语料库,必须从内存中删除所有对象,而不是用作输入的标记化语料库tokens_ngrams()
。各种 n-gram 的对象大小如下。
- 2 克:6.3 Gb
- 3 克:6.5 Gb
- 4 克:6.5 Gb
- 5 克:6.3 Gb
- 6 克:6.1 Gb
使用更少的内存
我能够在具有 8 Gb RAM 的 MacBook Pro 上处理 25% 的顶点数据样本,以及在运行 Ubuntu Linux 和 4 Gb RAM 的 HP Chromebook 上处理 5% 的样本。
对象大小:25% 样本
- 2 克:2.0 Gb
- 3 克:2.9 Gb
- 4 克:3.6 Gb
- 5 克:3.9 Gb
- 6 克:4.0 Gb
对象大小:5% 样本
- 2 克:492 Mb
- 3 克:649 Mb
- 4 克:740 Mb
- 5 克:747 Gb
- 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 合并到频率表中的代码,留给学生工作。