Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: Эвристическое (без словаря) извлечение корня из русского слова.
Форумы портала PHP.SU » Разное » Обсуждение статей » Эвристическое (без словаря) извлечение корня из русского слова.

Страниц (1): [1]
 

1. snikers987 - 13 Ноября, 2011 - 15:07:44 - перейти к сообщению
Искал поиском по форуму и не нашел данной темы, тема в общем-то принципиально не новая, но думаю для тех кто о ней не знают (новички имеются ввиду, ибо на них форум в основном в данное время и направлен) найдут ее весьма интересной

http://snowball[dot]tartarus[dot]org/alg[dot][dot][dot]ian/stemmer[dot]html

Class:

Спойлер (Отобразить)


Пример использования:

PHP:
скопировать код в буфер обмена
  1. $stemmer = new Lingua_Stem_Ru();
  2. echo $stemmer->stem_word('Котеровыми');


От себя внес изменения и теперь все корректно работает с UTF-8.
(Добавление)
немного переработал class
PHP:
скопировать код в буфер обмена
  1.  
  2. class Lingua_Stem_Ru
  3. {
  4.     private $VERSION = "0.02";
  5.         private $unset_predlog = true; //удалять пердлоги ?
  6.     private $Stem_Caching = 0;
  7.     private $Stem_Cache = array();
  8.     private $VOWEL = '/аеиоуыэюя/u';
  9.     private $PERFECTIVEGROUND = '/((ив|ивши|ившись|ыв|ывши|ывшись)|((?<=[ая])(в|вши|вшись)))$/u';
  10.     private $REFLEXIVE = '/(с[яь])$/u';
  11.     private $ADJECTIVE = '/(ее|ие|ые|ое|ими|ыми|ей|ий|ый|ой|ем|им|ым|ом|его|ого|еых|ую|юю|ая|яя|ою|ею)$/u';
  12.     private $PARTICIPLE = '/((ивш|ывш|ующ)|((?<=[ая])(ем|нн|вш|ющ|щ)))$/u';
  13.     private $VERB = '/((ила|ыла|ена|ейте|уйте|ите|или|ыли|ей|уй|ил|ыл|им|ым|ены|ить|ыть|ишь|ую|ю)|((?<=[ая])(ла|на|ете|йте|ли|й|л|ем|н|ло|но|ет|ют|ны|ть|ешь|нно)))$/u';
  14.     private $NOUN = '/(а|ев|ов|ие|ье|е|иями|ями|ами|еи|ии|и|ией|ей|ой|ий|й|и|ы|ь|ию|ью|ю|ия|ья|я)$/u';
  15.     private $RVRE = '/^(.*?[аеиоуыэюя])(.*)$/u';
  16.     private $DERIVATIONAL = '/[^аеиоуыэюя][аеиоуыэюя]+[^аеиоуыэюя]+[аеиоуыэюя].*(?<=о)сть?$/u';
  17.         private $PREDLOG = '/(^|\s)(и|для|в|на|под|из|с|по)(\s|$)/u';
  18.         private function s(&$s, $re, $to)
  19.     {
  20.         $orig = $s;
  21.         $s = preg_replace($re, $to, $s);
  22.         return $orig !== $s;
  23.     }
  24.  
  25.    private function m($s, $re)
  26.     {
  27.         return preg_match($re, $s);
  28.     }
  29.         public function stem_string($words) // string stem_string( string $words )
  30.     {
  31.         $word=explode(' ',$words);
  32.         for ($i=0;$i<count($word);$i++)
  33.         {
  34.                 if ($this->unset_predlog === TRUE) $word[$i] = preg_replace($this->PREDLOG, '', $word[$i]);
  35.                         $word[$i]=$this->stem_word($word[$i]);
  36.                         if(empty($word[$i])) unset($word[$i]);
  37.         }
  38.         return implode(' ',$word); //if you need return array change on -> return $word;
  39.     }
  40.        
  41.    private function stem_word($word)
  42.     {
  43.                 mb_regex_encoding( 'UTF-8' );
  44.                 mb_internal_encoding( 'UTF-8' );
  45.         $word = mb_strtolower($word);
  46.         $word= str_ireplace('ё', 'е', $word);
  47.         # Check against cache of stemmed words
  48.        if ($this->Stem_Caching && isset($this->Stem_Cache[$word])) {
  49.             return $this->Stem_Cache[$word];
  50.         }
  51.        
  52.                 $stem = $word;
  53.         do {
  54.           if (!preg_match($this->RVRE, $word, $p)) break;
  55.           $start = $p[1];
  56.           $RV = $p[2];
  57.           if (!$RV) break;
  58.  
  59.           # Step 1
  60.          if (!$this->s($RV, $this->PERFECTIVEGROUND, '')) {
  61.               $this->s($RV, $this->REFLEXIVE, '');
  62.  
  63.               if ($this->s($RV, $this->ADJECTIVE, '')) {
  64.                   $this->s($RV, $this->PARTICIPLE, '');
  65.               } else {
  66.                   if (!$this->s($RV, $this->VERB, ''))
  67.                       $this->s($RV, $this->NOUN, '');
  68.               }
  69.           }
  70.  
  71.           # Step 2
  72.          $this->s($RV, '/и$/', '');
  73.  
  74.           # Step 3
  75.          if ($this->m($RV, $this->DERIVATIONAL))
  76.               $this->s($RV, '/ость?$/', '');
  77.  
  78.           # Step 4
  79.          if (!$this->s($RV, '/ь$/', '')) {
  80.               $this->s($RV, '/ейше?/', '');
  81.               $this->s($RV, '/нн$/', 'н');
  82.           }
  83.  
  84.           $stem = $start.$RV;
  85.         } while(false);
  86.         if ($this->Stem_Caching) $this->Stem_Cache[$word] = $stem;
  87.         return $stem;
  88.     }
  89.  
  90.     private function stem_caching($parm_ref)
  91.     {
  92.         $caching_level = @$parm_ref['-level'];
  93.         if ($caching_level) {
  94.             if (!$this->m($caching_level, '/^[012]$/')) {
  95.                 die(__CLASS__ . "::stem_caching() - Legal values are '0','1' or '2'. '$caching_level' is not a legal value");
  96.             }
  97.             $this->Stem_Caching = $caching_level;
  98.         }
  99.         return $this->Stem_Caching;
  100.     }
  101.  
  102.     public function clear_stem_cache()
  103.     {
  104.         $this->Stem_Cache = array();
  105.     }
  106. }
  107.  


теперь на входе можно принимать строку:

PHP:
скопировать код в буфер обмена
  1. echo $stemmer->stem_string('Дождливыми вечерами мы читали книги под лампой');//дождлив вечер мы чита книг ламп


Также из строки будут удалены союзы и предлоги (при установке флага $unset_predlog в true) перечисленные в:

PHP:
скопировать код в буфер обмена
  1. private $PREDLOG = '/(^|\s)(и|для|в|на|под|из|с|по)(\s|$)/u';


Пример использования:

PHP:
скопировать код в буфер обмена
  1. $stemmer = new Lingua_Stem_Ru();
  2. echo $stemmer->stem_string('Дождливыми вечерами мы читали книги под лампой');//дождлив вечер мы чита книг ламп
2. snikers987 - 13 Ноября, 2011 - 17:10:18 - перейти к сообщению
Может быть кому пригодится=)
3. Данил_123 - 13 Ноября, 2011 - 17:13:42 - перейти к сообщению
Много изменений внес?
Спойлер (Отобразить)
4. snikers987 - 13 Ноября, 2011 - 17:22:40 - перейти к сообщению
Данил_123 пишет:
Много изменений внес?
Спойлер (Отобразить)


Я и так написал что сделал.
5. Данил_123 - 13 Ноября, 2011 - 17:27:49 - перейти к сообщению
snikers987 зачем выложил, вроде все сначала в гугле пасутся после тут.. Я написал название топика и подобных достаточно много
6. snikers987 - 13 Ноября, 2011 - 17:32:09 - перейти к сообщению
Данил_123 пишет:
snikers987 зачем выложил, вроде все сначала в гугле пасутся после тут.. Я написал название топика и подобных достаточно много


Если бы все 'послись' сначала в гугле форум бы не был зас[sensored]т повторяющимися 20 раз нубовскими темами. И найти не сложно когда знаеш что ищешь, вот ты например знал об таком классе? Уверен что нет.
7. Данил_123 - 13 Ноября, 2011 - 18:16:32 - перейти к сообщению
snikers987 нет не знал, спасибо почитал, и в гугле тоже.. Можно было выложить ссылку на источник..
8. Самогонщик - 15 Ноября, 2011 - 15:57:16 - перейти к сообщению
Полезный для меня материал, что-то он у меня плохо гуглился, а здесь случайно попался.
9. EuGen - 17 Ноября, 2011 - 08:40:19 - перейти к сообщению
snikers987
А класс написали Вы? Если нет, то прошу ознакомиться с правилами раздела. Мы относимся очень внимательно к таким публикациям. Если код не Ваш, то, пожалуйста, укажите первоисточники в первом сообщении темы.
10. snikers987 - 17 Ноября, 2011 - 10:18:20 - перейти к сообщению
Я не знаю где первоисточники на PHP, я не предендую на авторство, только мои правки, ссылку на проект Мартина Портера (разработчика алгоритма) добавил в первый пост. Вообще, удаляй тему за несоответствие правилам, для меня это не принципиально, хотел как лучше.
11. EuGen - 17 Ноября, 2011 - 10:24:27 - перейти к сообщению
Нет, почему же удалить. Согласно правилам это просто относится к обсуждению сторонних статей. Все в порядке. Благодарю за полезный материал.
12. victordax - 28 Апреля, 2013 - 20:24:03 - перейти к сообщению
snikers987 пишет:
От себя внес изменения и теперь все корректно работает с UTF-8.

Спасибо тебе огромное! Как долго я бился с этой кодировкой...выручил!

 

Powered by ExBB FM 1.0 RC1