不自然言語処理にはPHPをどうぞ
自然言語処理はPythonがいちばんという記事を読んで思い出したのだが、自分でもWordnetのPHP版フロントエンドをさくっと(Ruby版をコピーして)作っていた。ほんとまるコピーなのでほったらかしにしていたのだが、イテレータのところの醜さに悶絶してもいいなら責任は取らないが読むのは許可するので公開しておく。都市の空気は自由だ。
<?php class Wordnet{ public $db; function __construct($dsn){ $this->db =& $this->_connect($dsn); } function __destruct(){ } public function singleton($dsn){ static $obj = null; if(is_null($obj)){ $name = __CLASS__; $obj =& new $name($dsn); } return $obj; } private function _connect($dsn){ static $dbh = null; if(is_null($dbh)){ try { $dbh = new PDO($dsn); } catch(Exception $e) { echo $e->getMessage(); } } return $dbh; } private function _exception(&$e){ echo $e->getMessage(); } private function _select($sql, $param=array()){ $statement = $this->db->prepare($sql); $statement->setFetchMode(PDO::FETCH_ASSOC); if($statement->execute($param)){ return $statement->fetchAll(); }else{ $info = $statement->errorInfo(); foreach($info as $k => $v){ $message .= $k . ":" . $v . "\n"; } throw new Exception($message); } } private function _get($sql, $param){ try { $array = $this->_select($sql, $param); }catch(Exception $e){ $this->_exception($e); return null; } return $array; } public function get_words($lemma){ $sql = "SELECT * FROM word WHERE lemma=?"; $array = $this->_get($sql, array($lemma)); return $array; } public function get_word($wordid){ $sql = "SELECT * FROM word WHERE wordid=?"; $array = $this->_get($sql, array($wordid)); return $array; } public function get_senses($wordid){ $sql = "SELECT * FROM sense WHERE wordid=?"; $array = $this->_get($sql, array($wordid)); return $array; } public function get_sense($synset, $lang='jpn'){ $sql = "SELECT * FROM sense WHERE synset=? AND lang=?"; $array = $this->_get($sql, array($synset, $lang)); return $array; } public function get_synset($synset){ $sql = "SELECT * FROM synset WHERE synset=?"; $array = $this->_get($sql, array($synset)); return $array; } public function get_syn_links($synset1, $link){ $sql = "SELECT * FROM synlink WHERE synset1=? AND link=?"; $array = $this->_get($sql, array($synset1, $link)); return $array; } public function get_sys_links_recursive($senses, $link, $lang='jpn', $depth=0){ if(is_array($senses)){ foreach($senses as $sense){ $syn_links = $this->get_syn_links($sense['synset'], $link); if(count($syn_links) > 0){ $get_word = $this->get_word($sense['wordid']); $synset = $this->get_synset($sense['synset']); $space = str_repeat(' ', $depth); print($space . $get_word[0]['lemma'] . ' ' . $synset[0]['name'] . "\n"); $tmp_links = array(); foreach($syn_links as $k => $syn_link){ $tmp_sense = $this->get_sense($syn_link['synset2'], $lang); if($tmp_sense != ''){ $tmp_links[] = $tmp_sense[0]; } } $this->get_sys_links_recursive($tmp_links, $link, $lang, $depth + 1); } } } } public function main($word, $link, $lang='jpn'){ if($words = $this->get_words($word)){ $senses = $this->get_senses($words[0]['wordid']); $this->get_sys_links_recursive($senses, $link, $lang); }else{ return "nothing found"; } } public function usage(){ $usage = >>>EOS usage: wordnet.php word link [lang] word word to investigate link syns - Synonyms hype - Hypernyms inst - Instances hypo - Hyponym hasi - Has Instances mero - Meronyms mmem - Meronyms --- Member msub - Meronyms --- Substance mprt - Meronyms --- Part holo - Holonyms hmem - Holonyms --- Member hsub - Holonyms --- Substance hprt - Holonyms -- Part attr - Attributes sim - Similar to entag - Entails causg - Causes dmncg - Domain --- Category dmnug - Domain --- usage dmnrg - Domain --- Region dmtcg - In Domain --- Category dmtug - In Domain --- usage dmtrg - In Domain --- Region antsg - Antonyms lang (default: jpn) jpn - Japanese eng - English EOS; print($usage); } } $dsn = 'sqlite:./wnjpn-0.9.db'; $obj = Wordnet::singleton($dsn); $word = $_SERVER['argv'][1]; $link = $_SERVER['argv'][2]; $lang = $_SERVER['argv'][3] ? $_SERVER['argv'][3] : 'jpn'; if($word == '' || $link == ''){ $obj->usage(); exit; } $obj->main($word, $link, $lang); ?>
ではテスト。
$ ruby wordnet.rb 'うんこ' hype うんこ dung 大便 stool うんこ turd 大便 stool $ php -q wordnet.php 'うんこ' hype うんこ dung 大便 stool うんこ turd 大便 stool
そもそもlinkとか意味がわかってないのでこれ以上テストする気がないのだが、動いていそうな雰囲気ではある。うんこしかテストしていないので、不自然な言語処理にぜひともおすすめ。
テストしてない上にローカルで使ってたのでセキュリティとか一切考慮してないから、これを使って何をしようとも愚挙としかいいようがないので念のため。
Comments
PHP版を探してここにたどり着きました。
ありがとうございます。
手元の環境(Debian GNU/Linux 6.0)で動かすには以下の変更が必要でした。
if($tmp_sense != ”){
↓↓
if($tmp_sense != NULL){
$lang = $_SERVER[‘argv’][3] ? $_SERVER[‘argv’][3] : ‘jpn’;
↓↓
if (isset($_SERVER[‘argv’][3])) $lang = $_SERVER[‘argv’][3]; else $lang = ‘jpn’;
$usage = >>>EOS
↓↓
$usage = <<
すみません、訂正です。一部、文字が抜けていました。
$usage = >>>EOS
↓↓
$usage = <<EOS
が正解です。