我试图build立一个基于英文wikipedia转储中的前100K字的n-gram语言模型。 我已经用一个用Java编写的修改过的XMLparsing器提取出纯文本,但是需要把它转换成一个vocab文件。
为了做到这一点,我发现一个perl脚本,据说是做这个工作,但缺乏如何执行的指示。 不用说,我是一个Perl的新手,这是我第一次遇到需要它的用法。
当我运行这个脚本的时候,在一个7.2GB的文本文件上使用4GB内存和runnung Ubuntu 10.04和10.10时,出现内存不足错误。
当我联系作者时,他说这个脚本在配备4GB RAM的MacBook Pro上运行良好,当在一个6.6GB的文本文件上执行perl 5.12时,总内存使用量约为78 MB。 作者还表示,该脚本逐行读取input文件,并在内存中创build一个HashMap。
脚本是:
#! /usr/bin/perl use FindBin; use lib "$FindBin::Bin"; use strict; require 'english-utils.pl'; ## Create a list of words and their frequencies from an input corpus document ## (format: plain text, words separated by spaces, no sentence separators) ## TODO should words with hyphens be expanded? (eg three-dimensional) my %dict; my $min_len = 3; my $min_freq = 1; while (<>) { chomp($_); my @words = split(" ", $_); foreach my $word (@words) { # Check validity against regexp and acceptable use of apostrophe if ((length($word) >= $min_len) && ($word =~ /^[AZ][AZ\'-]+$/) && (index($word,"'") < 0 || allow_apostrophe($word))) { $dict{$word}++; } } } # Output words which occur with the $min_freq or more often foreach my $dictword (keys %dict) { if ( $dict{$dictword} >= $min_freq ) { print $dictword . "\t" . $dict{$dictword} . "\n"; } }
我从命令行通过mkvocab.pl corpus.txt
执行这个脚本
包含的额外脚本只是一个正则expression式脚本来testing撇号的位置以及它们是否符合英语语法规则。
我以为内存泄漏是由于不同的版本,因为我的机器上安装了5.10。 所以我升级到5.14,但错误仍然存在。 根据free -m
,我的系统上有大约1.5GB的可用内存。
由于我完全不熟悉语言的语法和结构,能否指出问题所在,以及问题存在的原因以及如何解决。
把一个7,2Gb的文件加载到一个散列中是可能的,如果有一些重复的话,例如发生17,000次,等等。这似乎相当多,但是。
您的脚本假定文件中的行适当长。 如果你的文件不包含换行符,你将把整个文件加载到$_
内存中,然后用split
加载这个内存,然后在你的散列中添加更多的内容。 这会压制任何系统。
一个想法可能是使用空间" "
作为输入记录分隔符。 它会做大约你已经在做什么拆分,除了它会留下其他空白字符,并不会修剪多余的空格作为prettitily。 例如:
$/ = " "; while (<>) { for my $word ( split ) { # avoid eg "foo\nbar" being considered one word if ( (length($word) >= $min_len) && ($word =~ /^[AZ][AZ\'-]+$/) && (index($word,"'") < 0 || allow_apostrophe($word)) ) { $dict{$word}++; } } }
这将允许甚至非常长的行以一口大小的块来读取,假设在单词(而不是标签或换行符)之间确实有空格。
尝试运行
dos2unix corpus.txt
您可能正在将整个文件读取为一行…