自動アノテーション(注釈)ブックマークレット

ウェブコンテンツに情報を自動的に付加するブックマークレット(bookmarklet)を作りました。

閲覧しているページに自身の興味を持つキーワードが多数含まれているとき、クリック一つで各キーワードがハイライト表示され、更には関連情報が得られるリンクが新たに加えられるなら便利と思いませんか?
Read more »

RDF serializationinに関するPerlモジュール比較

RDFデータの直列化(serialization)を実現するためのPerlモジュールを色々と試した。

これは2月に開かれたBioHackathon 2010に関連して行ったもの。英語ページはhackathonのページにあるので、日本語でここに記述しておくことに。

まずは環境。

RDF::Simple (0.415)
RDF::Trine (0.122)
RDF::Redland (1.0.5.4)
RDF::Core (0.51)

RDF::Simpleは文字通りシンプル。このため、私見としては直列化がどのようにして行われるかについて、小さいデータセットで試してみる目的のみに向いているといえる。
モジュールの説明にある通り、ノードタイプを識別しないため、URIであるかリテラルであるかを明示出来ない。
ただ、RDF::Trine/RDF::Redlandよりも生成される出力(RDF/XML)はより組織化されていてコンパクトになる。

RDF::Trineは現在開発が活発に行われているRDF処理関連の唯一のモジュールで、今後、最も高機能になることが予想される。
RDF/XMLの他にも、N-Quads、N-Triples、RDF/JSON、Turtleなどの形式で出力出来る。これは他のモジュールには無い。

ただ、現時点では生成されるRDF/XMLは冗長な点がある。本モジュールは直列化すべきトリプル群を主語毎にグループ化し、それらをタグで括る。これ自体は問題ないが、利用者が定義する名前空間を冒頭のタグ内で宣言せず、各rdf-Descriptionタグで行っている。また、入れ子のレベルが1であったり、名前空間のQNAMEを指定出来なかったりする。
それでもRDF::Redlandより小さなRDF/XMLデータを生成する。

RDF::RedlandはピュアPerlモジュールでは無く、構築時にコンパイルを必要とする。このため、プラットフォームや環境によっては構築に困難を伴う可能性がある。
今回試したLinux (RedHat)マシンではcpanコマンドでの構築にはmake testが通らずに失敗した。原因はswigにより生成されたライブラリが標準ライブラリパスにあると想定して動作するテストスクリプトにあり、本問題を手当てすることで構築出来た。具体的にはLD_LIBRARY_PATH環境変数に次のパスを加える。

Redland-1.0.5.4/redland/rasqal/src/.libs
Redland-1.0.5.4/redland/raptor/src/.libs

RDF::Coreは長いこと手が付けられておらず、ブランクノードを扱えない問題がある。
ただ、直列化された結果は良くまとまっている。
RDF::Trineと同様に名前空間のQNAMEを設定出来ない。

以下、今回のために作ったプログラム。 Read more »

Protegeの利用

Protege? 法造?

ひょんなことからオントロジーをあれこれする必要が生じ、しかも共同作業が必要になるということで、メジャーなツールであるProtegeを使うことに。
今回は日本語コンテンツなので、法造(hozo)もインストールして試した見たが、ネットワークを用いた共同作業がWindowsマシンのみを想定した作りになっているので取りやめに。

Protegeインストール

Read more »

Hadoop java.library.path 問題

今回はSWIGを利用してC++で書かれたプログラムをHadoop MapReduceから使おうとした。
これを参考にして以下のような処理を実行。

swig -c++ -java -package yayamamo -outdir yayamamo -noproxy hoge.i
g++ -fPIC -c HogeFuga.cpp
g++ -fPIC -c hoge_wrap.cxx -I/usr/local/java/include -I/usr/local/java/include/linux
g++ -shared HogeFuga.o hoge_wrap.o -o hoge.so

これに倣った実行テストプログラムはめでたく動作、かと思われたが、実はC++で書かれたそのサブルーチンは引数に文字列 (= char * ) を取り、それを直接書き換えるもので、javaから呼び出すとその引数である文字列は変化しない。javaのStringオブジェクトの中身を直接書き換えるようにはなっていないから。なので、C++側で、引数で与えられた文字列を変更した結果が戻り値となる新規ルーチンを用意。

続いて Hadoop で使うための環境を整える。ここを見るとどうやら mapred-site.xml で mapred.child.java.optsプロパティの値に -Djava.library.path=/home/mycompany/lib を加えるだけのように思われた。しかし、ここに設定するとジョブが失敗する。それまで正常に動作していたものも。Hadoop 本体を実行するするスクリプト内で設定している JAVA_LIBRARY_PATH と競合している模様。仕方ないので、Hadoop にバンドルされているネイティブコードライブラリの置かれるディレクトリ lib/native/Linux-amd64-64 以下に先ほど生成した hoge.so をコピー。問題無く動作することを確認。

OpenID Client on Perl

今回、TogoDoc で利用している OpenID のクライアントモジュールをNet::OpenID::Consumerから OpenID4Perl に変更。というよりは、追加という状況。Perlのコードそのものは何も変更せず。

さて、Consumer.pm は Crypt::DH を利用しており、DH.pm の冒頭には以下のコードがある。

use Math::BigInt lib => "GMP,Pari";

そして、TogoDoc では、Pari を利用しているため、Math::BigInt から Pari ライブラリを呼ぶ形になる。このため、Math::BigInt::Pari をインストールする。そうしないと、Crypt::DHを利用する際に、以下のような警告が出力される。

Math::BigInt: couldn't load specified math lib(s), fallback to Math::BigInt::FastCalc at .../local/lib/perl5/site_perl/5.10.1/Crypt/DH.pm line 6

また、Pari のスタックサイズの変更は最初にモジュールがロードされる前に宣言せねばならず、そしてmod_perl (2.0) 利用環境下でPariモジュールをロードするので、下記宣言を startup.pl に記述。

use Math::PariInit qw( stack=1e9 );

OpenID4Perl にすることで、一部のプロバイダのOpenIDでログイン出来なかった問題が解消された。

MySQL ストアドプロシージャ

mysql に保存されているデータベースに対して一気に特定の処理をする必要に迫られ、表記について学ぶ。
参考ページはhttp://dev.mysql.com/doc/refman/5.1/ja/stored-procedures.html
要はMySQLデータベースに保存可能な手続き、或いはプログラムということ。

もちろん、Perlなどから同じ処理は出来るが、頻繁に行うことでも無いし、何をしたのか良く分からなくなるプログラムが放置されるのも後で整理する時に困るので今回はこれを試してみた。

覚えておくと良い事項は、

  • デリミタを変更するコマンド DELIMITER を用いてプログラム内の1命令の終わりを示すセミコロンをMySQLコマンドの終わりとして解釈されないようにする。
  • プログラムの定義は “CREATE PROCEDURE プログラム() BEGIN” で開始、”END” で終了。
  • 変数宣言は “DECLARE”。
  • ある一定の条件を満たす行に対して、その内容を変更したい時、ストアドプロシージャではカーソル (CURSOR) という概念が使われる。
  • 条件を満たす行が複数あり、各行に同じ処理を施すならば、繰り返しを使うが、その終了条件は “SQLSTATE ‘0200’” 。
  • プログラムの保存先は、mysql.proc テーブル。

例えば、userinfo テーブルの RATE 列が 0 であるとき、それを 1 にしたい場合は以下のようなプログラムで実現可能。

DELIMITER $$
CREATE PROCEDURE myProc()
BEGIN
  DECLARE done INT DEFAULT 0;
  DECLARE r INT;
  DECLARE cur CURSOR FOR SELECT id FROM userinfo WHERE RATE=0;
  DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1; 

  OPEN cur;
  REPEAT FETCH cur INTO r;
    UPDATE userinfo SET RATE=1 WHERE id=r;
  UNTIL done END REPEAT;
  CLOSE cur;
END$$

“SELECT * FROM mysql.proc\G” というコマンドを発行すると実際に宣言したプログラムが保存されていることを確認出来る。
また、実行する場合は、CALL myProc;というコマンドを発行する。

Allie 検索間口を拡大

少しでも多くのエントリポイントを Allie に持たせるために、片っ端から閲覧可能な入り口を追加。

http://allie.dbcls.jp/cgi-bin/browse.cgi

従来版だと全ての結果が、その内容と直接は無関係の余り有益ではないタイトルとURLとなってしまうのでよろしくない (そして現状直ぐには修正不可)。
そのため、今回は全てのページのタイトルやURLに結果を含む形にし、検索エンジンでヒットした時には実際にアクセスする前にタイトルと抜粋(スニペット)を見ることで予めどのような情報が得られるかを簡単に利用者が想像出来るようにした。

下記の検索結果をこまめにチェックしていこう。

http://www.google.com/webhp?hl=en#hl=en&source=hp&q=allie.dbcls.jp%2Fcgi-bin&btnG=Google+Search&aq=f&aqi=&oq=&fp=8ec9ea851cee2c5b

CiteULike まとめ

http://www.citeulike.org/faq/data.adpに記述されているURLを利用してデータを取得。

誰(匿名)がいつ、何を投稿したのかが分かるデータ(Who-posted-what)と、各書誌情報についての情報が格納されているデータ(Article linkout data)を取得可能。
毎日更新している模様。

2009-08-30について調査。
Who-posted-what: 6 668 545行
一つの書誌情報について利用者が複数のタグを付けた場合は別々の行になるのでそこを吸収すると、
2 106 362行
のべ210万程度の書誌情報が投稿されていることになる。
更に、書誌情報についての重複を吸収すると、
1 783 077行
ということで、180万程度の書誌情報が投稿されていることになる。

また、利用者数は52 431人。一人当たりの平均登録件数は40件。
標準偏差が323もあるので、バラつきの大きいことが分かる。(最大は32 313…。続いて、30 695, 27 836, 27 825, 9 675…などと続く)
トップ1%を過ぎた時点での登録件数は600件。中央値は2(件)。したがって、半分以上の利用者が1, 2件しか登録していない。

因みに、最もCiteULike利用者の間で人気が高い論文は「The Structure of Collaborative Tagging Systems / Scott Golder, Bernardo A. Huberman / 2005」で、238人が投稿している。
CiteULikeのシステムに関連する話題のようで。
この分布もパワーローに従っているのでしょう。
それに続いて140人が登校しているのが、PMIDの付けられている、「Defrosting the digital library: bibliographic tools for the next generation web.」。
これまた、CiteULikeに関連する話題。
3番目は、「Conference on Hypertext and Hypermedia」。
その他、PMIDが付けられているところでは、「Collective dynamics of ‘small-world’ networks.」
ここの利用者の興味を反映した形ですね。

登録されているPMID付きの書誌情報は290 660なので、全体の16パーセント、1/6弱程度と少ない。
生命科学系の利用者は少数派なのだろう。
なお、15 192人が少なくとも一つのPMID付きの書誌情報を登録しており、これは全利用者の約3割にあたる。

hadoop取り敢えずまとめ

hadoop ver. 0.20.0 について

下記の項目に留意して効率アップをする

  • プログラム中でのconf.setNumReduceTasks(<INT>)の記述
  • プログラム中でのcombineの工夫
  • プログラム中でのconf.setCompressMapOutput(true);conf.setMapOutputCompressorClass(DefaultCodec.class);の記述
  • core-site.xmlでのio.sort.factorの設定(100など)

また、hdfsを使わない時の設定として留意する点は、core-site.xmlt中においてfs.default.nameをfile:///とすることとともに、mapred-site.xml中に、mapred.system.dirとmapred.temp.dirに対して、cluster環境下(=複数ノードに渡る構成)でも物理的に同一パスを指すようにする。

cluster環境下で、各ノードのローカルディスクが殆ど無いような環境では、/tmp下(=各ノードの物理ディスク領域)にそれぞれのノードで別々のnfsパスへのシンボリックリンクを張る。物理的に同じディスク領域が指定されるとディスクアクセスが適切に動作しない。

hadoop & eclipse

hadoopアプリの効率的な開発のためにeclipseを導入。
hadoop pluginがhadoopに梱包されているのでそれをeclipseのpluginフォルダにコピーする。

適切に初期設定をすると、eclipse内からhdfsが閲覧できたり、hadoopアプリを簡単にデバッグできるようになる。
とはいえ、hadoopバージョンアップに完全に追随できていない部分があるから、pluginの提供する機能の一部が使えない。

例えば、Project Explorerの、自分が実行させたいソースコードのファイル名の上で右クリックして「Run As」で表示される、「Run on Hadoop」は効かない。
今回はここを参考にしてみた。

因みに、hdfsを利用しないでhadoopのmap/reduceを走らせる時は、core-site.xml (0.20.0)かhadoop-site.xml (0.19.2)のfs.default.nameをfile:///とする。