2

スカラーで収集した 10 億語のコーパスがあります。データ (テキスト) から削除したいすべてのストップ ワードを含む .regex ファイルがあります。

この .regex ファイルの使い方がわからないので、配列を作成し、.regex ファイルのすべてのストップ ワードをストップ ワード配列に格納しました。

ストップワードを削除するには、次のようにします。

grep { $scalarText =~ s/\b\Q$_\E\b/ /g } @stopList;

これは実行に時間がかかります。Perl スクリプトで .regex ファイルを使用してストップ ワードを削除するにはどうすればよいですか? または、ストップワードを削除するより速い方法はありますか?

4

3 に答える 3

5

はい、いくつかの理由がありますが、あなたがそこでしていることは非常に遅いと思います。コーパスから数十億語の文字列を構築する前に、ストップワードの正規表現を処理する必要があると思います。

.regex ファイルが何であるかはわかりませんが、正当な Perl 正規表現が含まれていると推測します。

$stopword_string = `cat foo.regex`;
$stopword_rx     = qr/$stopword_string/;

それはおそらく、最初に a があることを前提としてい(?x)ます。

しかし、ストップワード ファイルが行のリストである場合は、さらに次のようにする必要があります。

chomp(@stopwords = `cat foo.regex`);

# if each stopword is an independent regex:
$stopword_string = join "|" => @stopwords;

# else if each stopword is a literal
$stopword_string = join "|" => map {quotemeta} @stopwords;

# now compile it (maybe add some qr//OPTS)
$stopword_rx     = qr/\b(?:$stopword_string)\b/;

警告

には非常に注意してください\b。最初の単語の最初の文字と最後の単語の最後の文字が英数字 (\w文字) である場合にのみ、上記のように動作すると考えられます。そうしないと、おそらく意味のない何かを主張することになります。その可能性がある場合は、より具体的にする必要があります。先頭\bは になる必要が(?:(?<=\A)|(?<=\s))あり、末尾\bは になる必要があり(?=\s|\z)ます。多くの人がそう思っ \bているようですが、実はそうではありません。

それを行ったら、コーパスを読み込んでいるときにストップワード正規表現をコーパスに適用する必要があります。これを行う最善の方法は、後で取り出す必要があるものを最初に文字列に入れないことです。 .

だから代わりに

$corpus_text = `cat some-giant-file`;
$corpus_text =~ s/$stopword_rx//g;

代わりに

my $corpus_path = "/some/path/goes/here";
open(my $corpus_fh, "< :encoding(UTF-8)", $corpus_path)
    || die "$0: couldn't open $corpus_path: $!";

my $corpus_text = q##;

while (<$corpus_fh>) {
    chomp;  # or not
    $corpus_text .= $_ unless /$stopword_rx/;
}

close($corpus_fh)
    || die "$0: couldn't close $corpus_path: $!";

これは、後で再び取り除かなければならないものをそこに入れるよりもはるかに高速です。

上記の私の使用catは単なるショートカットです。私はあなたが実際にプログラムを呼び出すとは思っていませんcat。特に、処理も妨害もされていない単一のファイルを読み込むためだけです。☺</p>

于 2010-10-31T21:43:45.437 に答える
2

Regexp::Assembleを使用して、Perl 正規表現のリストを 1 つの正規表現にコンパイルすることができます。

于 2010-10-31T21:39:58.527 に答える
0

私はそれを行うためのより速い方法を見つけました。約4秒節約できます。

my $qrstring = '\b(' . (join '|', @stopList) . ')\b';
$scalarText =~ s/$qrstring/ /g;

wherestopListはすべての単語の配列で、scalarTextはテキスト全体です。

どなたかご存知でしたらもっと早い方法を教えていただけないでしょうか?

于 2010-10-31T21:41:12.897 に答える