【问题标题】:Most memory-efficient way to combine word stemming and the elimination of hash words in Perl?在 Perl 中结合词干提取和哈希词消除的最节省内存的方法?
【发布时间】:2023-03-07 06:00:01
【问题描述】:

我已经将一些 Perl 脚本拼凑在一起,旨在从一批文档中提取每个单词,消除所有停用词,对剩余的词进行词干化,并创建一个包含每个词干化词及其出现频率的哈希。但是,在处理了几分钟后,我得到了“内存不足!”命令窗口中的消息。有没有更有效的方法来达到预期的效果,还是我只需要找到一种方法来访问更多的内存?

#!/usr/bin/perl
use strict;
use warnings;
use Lingua::EN::StopWords qw(%StopWords);
use Lingua::Stem qw(stem);
use Mojo::DOM;

my $path = "U:/Perl/risk disclosures/2006-28";
chdir($path) or die "Cant chdir to $path $!";

# This program counts the total number of unique sentences in a 10-K and enumerates the frequency     of each one.

my @sequence;
my %sequences;
my $fh;

# Opening each file and reading its contents.
for my $file (<*.htm>) {
    my $data = do {
        open my $fh, '<', $file;
        local $/;    # Slurp mode
        <$fh>;
    };
    my $dom  = Mojo::DOM->new($data);
    my $text = $dom->all_text();
    for ( split /\s+/, $text ) {
        # Here eliminating stop words.
        while ( !$StopWords{$_} ) {
            # Here retaining only the word stem.
            my $stemmed_word = stem($_);
            ++$sequences{"$stemmed_word"};
        }
    }
}

【问题讨论】:

  • 我认为您需要将while (!$StopWords{$_}) { ... } 更改为next if defined $StopWords{$_};。您已经使用for (split ...) 一次检查一个词,因此该词要么是停用词,要么不是,不需要第二个循环。
  • 是的,确实消除了“内存不足”错误消息,谢谢!

标签: performance perl memory stemming stop-words


【解决方案1】:

如果某个单词不在%StopWords 中,则进入无限循环:

while ( !$StopWords{$_} ) {
    my $stemmed_word = stem($_);
    ++$sequences{"$stemmed_word"};

    # %StopWords hasn't changed, so $_ is still not in it
}

实际上根本没有理由在这里使用循环。您已经使用for 循环一次检查一个单词。一个词要么是停用词,要么不是,所以你只需要检查一次。

我会做类似以下的事情:

my $dom  = Mojo::DOM->new($data);
my @words = split ' ', $dom->all_text();

foreach my $word (@words) {
    next if defined $StopWords{$word};

    my $stemmed_word = stem $word;
    ++$sequences{$stemmed_word};
}

除了用

替换内部while循环
next if defined $StopWords{$word};

我也

  • 删除了中间的 $text 变量,因为您似乎真的只关心单个单词,而不是整个文本块
  • for 中添加了一个显式循环变量。各种函数会自动更改 $_,因此为了避免意外的副作用,我对所有内容都使用显式循环变量,但像 say for @array; 这样的单行变量除外
  • ++$sequences{"$stemmed_word"}; 中删除了多余的引号

【讨论】:

  • 我已经采纳了你的所有建议,我的那部分代码现在似乎运行良好,谢谢!
猜你喜欢
  • 2018-01-19
  • 2014-08-30
  • 2019-02-12
  • 2010-12-12
  • 1970-01-01
  • 2014-11-25
  • 2011-04-22
  • 2021-05-02
  • 2018-06-17
相关资源
最近更新 更多