0

こんにちは、これは私の最初の質問です。私は単語の見出し語 (見出し語の例を与える: 与える->与える) MElt と呼ばれるオープン ソース プログラムを使用しています。MElt は Linux で動作し、Perl と Python でプログラムされています。これまでのところうまく機能していますが、結果を出すには時間がかかりすぎます。私はコードを調べて、これを担当するループを見つけました:

while (<LEFFF>) { 
  chomp;
  s/ /_/g;
#  s/(\S)-(\S)/\1_-_\2/g;
  /^(.*?)\t(.*?)\t(.*?)(\t|$)/ || next;
  $form = $1; $cats = $2; $lemma = $3;
  #print "$form \n";
  #print "$cats \n";
  #print "$lemma \n";
  if ($lower_case_lemmas) {
    $lemma = lc($lemma);
  }
  if ($it_mapping) {
    next if ($form =~ /^.+'$/);
    next if ($form eq "dato" && $lemma eq "datare"); # bourrin
    next if ($form eq "stato" && $lemma eq "stare"); # bourrin
    next if ($form eq "stata" && $lemma eq "stare"); # bourrin
    next if ($form eq "parti" && $lemma eq "parto"); # bourrin
    if ($cats =~ /^(parentf|parento|poncts|ponctw)$/) {$cats = "PUNCT"}
    if ($cats =~ /^(PRO)$/) {$cats = "PRON"}
    if ($cats =~ /^(ARTPRE)$/) {$cats = "PREDET"}
    if ($cats =~ /^(VER|ASP|AUX|CAU)$/) {$cats = "VERB"}
    if ($cats =~ /^(CON)$/) {$cats = "CONJ"}
    if ($cats =~ /^(PRE)$/) {$cats = "PREP"}
    if ($cats =~ /^(DET)$/) {$cats = "ADJ"}
    if ($cats =~ /^(WH)$/) {$cats = "PRON|CONJ"}
    next if ($form =~ /^(una|la|le|gli|agli|ai|al|alla|alle|col|dagli|dai|dal|dalla|dalle|degli|dei|del|della|delle|dello|nei|nel|nella|nelle|nello|sul|sulla)$/ && $cats eq "ART");
    next if ($form =~ /^quest[aei]$/ && $cats eq "ADJ");
    next if ($form =~ /^quest[aei]$/ && $cats eq "PRON");
    next if ($form =~ /^quell[aei]$/ && $cats eq "ADJ");
    next if ($form =~ /^quell[aei]$/ && $cats eq "PRON");
    next if ($form =~ /^ad$/ && $cats eq "PREP");
    next if ($form =~ /^[oe]d$/ && $cats eq "CONJ");
  }
  $qmlemma = quotemeta ($lemma);
  for $cat (split /\|/, $cats) {
    if (defined ($cat_form2lemma{$cat}) && defined ($cat_form2lemma{$cat}{$form}) && $cat_form2lemma{$cat}{$form} !~ /(^|\|)$qmlemma(\||$)/) {
      $cat_form2lemma{$cat}{$form} .= "|$lemma";
    } else {
      $cat_form2lemma{$cat}{$form} = "$lemma";
      $form_lemma_suffs = "@".$form."###@".$lemma;
      while ($form_lemma_suffs =~ s/^(.)(.+)###\1(.+)/\2###\3/) {
    if (length($2) <= 8) {
      $cat_formsuff_lemmasuff2count{$cat}{$2}{$3}++;
      if ($multiple_lemmas) {
        $cat_formsuff_lemmasuff2count{$cat}{$2}{__ALL__}++;
      }
    }
      }
    }
  }
}

変数 LEFFF は 490489 行で構成される辞書です。そのため、ループは単語をすべての辞書行と 1 つずつ比較しています。これは本当に多すぎる。これを最適化する方法はありますか?ありがとうございました。医学。

4

1 に答える 1

0

/^(.*?)\t(.*?)\t(.*?)(\t|$)/ || next;この行を次のように変更してみてください。

/^([^\t]++)\t([^\t]++)\t([^\t]++)(\t|$)/ || next;

次の正規表現では、不要なキャプチャ括弧をすべて削除します。

/^(parentf|parento|poncts|ponctw)$/

/^parent[fo]|ponct[sw]$/   or why not   /^p(?>arent[fo]|onct[sw])$/

/^(una|la|le|gli|agli|ai|al|alla|alle|col|dagli|dai|dal|dalla|dalle|degli|dei|del|della|delle|dello|nei|nel|nella|nelle|nello|sul|sulla)$/

/^(?>una|l[ae]|a(?>i|l(?>l[ae])?)|col|d(?>ello|[ae](?>i|l(?l[ae])?|gli))|ne(?>i|l(?>ll[aeo])?)|sul(?>la)?)$/

(注意: この行を改善するには、順序を変更し、最も頻繁な決定要因/記事を先頭に置きます)

この行を変更してみてください:

while ($form_lemma_suffs =~ s/^(.)(.+)###\1(.+)/\2###\3/)

while ($form_lemma_suffs =~ s/^(.)([^#]++)###\1(.++)/\2###\3/)

条件を逆にすることができます:

next if ($form =~ /^quest[aei]$/ && $cats eq "ADJ");

next if ($cats eq "ADJ" && $form =~ /^quest[aei]$/ );

(実験的) 次の 2 行を置き換えることができます。

next if ($form eq "stato" && $lemma eq "stare"); # bourrin
next if ($form eq "stata" && $lemma eq "stare"); # bourrin

next if ($lemma eq "stare" && ($form eq "stato" || $form eq "stata"));

重要: perl を使用すると、正規表現をコンパイルできます。これは、while ループで同じ正規表現を使用する場合に役立ちます。その場合は、正規表現の定義をループの外に置くことを忘れないでください! 例:

my $regex = qr/^parent[fo]|ponct[sw]$/;
while (<LEFFF>) {
...
if ($cats =~ $regex) {$cats = "PUNCT"}
于 2013-08-27T15:17:14.310 に答える