不自然言語処理には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とか意味がわかってないのでこれ以上テストする気がないのだが、動いていそうな雰囲気ではある。うんこしかテストしていないので、不自然な言語処理にぜひともおすすめ。
テストしてない上にローカルで使ってたのでセキュリティとか一切考慮してないから、これを使って何をしようとも愚挙としかいいようがないので念のため。
Popularity: 3% [?]

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 = <<
$dsn = ‘sqlite:./wnjpn-0.9.db’;
↓↓
$dsn = ‘sqlite:./wnjpn.db’; // ダウンロードしたデータベースがこの名前だった
すみません、訂正です。一部、文字が抜けていました。
$usage = >>>EOS
↓↓
$usage = <<EOS
が正解です。