関口宏司のLuceneブログ

OSS検索ライブラリのLuceneおよびそのサブプロジェクト(Solr/Tika/Mahoutなど)について
スポンサーサイト

一定期間更新がないため広告を表示しています

| スポンサードリンク | - | | - | - |
Luceneでベイズ分類(experimental)
Luceneのインデックスをベイズ分類に応用しようという実験的なパッチが提案されている:

LUCENE-1039

こちらの理論には素人なのでアルゴリズムは軽くスルーして、プログラムと実行結果を示す。

これを使えば、文章を学習させたLuceneインデックスを使って、別の新しい文章の分類ができる。

たとえば、こんな具合に「関西弁」と「標準語」を自動分類してくれる:



*****
どうなってまんねん => 関西弁
*****
どうなっているのですか => 標準語
*****
あほちゃうか => 関西弁
*****
ばかですね => 標準語



完璧では当然ないので、次のように間違うこともある(2番目は「政治」ではなく「芸能」と分類して欲しい):



*****
女優の広末涼子がイメージキャラクターを務める日本コカ・コーラ「からだ巡茶」の新CM「さよならハロー・フープ」編の撮影が行われた。 => 芸能
*****
榊原といえば先日車上荒らしの被害にあったばかり。 => 政治
*****
会談で大連立が話題になったかどうかについて「いろんな話をしたが、そこまで至らなかった」と否定した。首相官邸で記者団の質問に答えた。 => 政治
*****
(与野党)共通の認識を持った政治運営がなされる可能性が出てきた。場合によって大連立も考えられる => 政治



ただ、学習の量が足りないだけなのかもしれない。

プログラムは次のとおりである:



public class TestClassifier {

// 学習用文章
private static final String[][] MATERIALS = {
{ "なにいうてまんねん", "関西弁" },
{ "なにをいってるんですか", "標準語" },
{ "そうでんねん", "関西弁" },
{ "そうです", "標準語" },
{ "あほちゃうか", "関西弁" },
{ "ばかですね", "標準語" }
};

// テスト用文章
private static final String[] TESTS = {
"どうなってまんねん", "どうなっているのですか",
"あほちゃうか", "ばかですね" // 学習済みのものをチェック
};

public static void main(String[] args) throws IOException {
Instances instances = learn();
for( String test : TESTS )
classify( instances, test );
instances.close();
}

private static InstanceFactory getInstanceFactory(){
return new InstanceFactory() {
public Document factory(String text, String _class) {
Document doc = new Document();
doc.add(new Field("class", _class, Field.Store.YES,
Field.Index.NO_NORMS));
doc.add(new Field("text", text, Field.Store.YES, Field.Index.NO,
Field.TermVector.NO));
doc.add(new Field("text/ngrams/start", text, Field.Store.NO, Field.Index.TOKENIZED,
Field.TermVector.YES));
doc.add(new Field("text/ngrams/inner", text, Field.Store.NO, Field.Index.TOKENIZED,
Field.TermVector.YES));
doc.add(new Field("text/ngrams/end", text, Field.Store.NO, Field.Index.TOKENIZED,
Field.TermVector.YES));
return doc;
}
Analyzer analyzer = new Analyzer() {
private int minGram = 1;
private int maxGram = 2;
public TokenStream tokenStream(String fieldName, Reader reader){
String conf = System.getProperty("sen.home") + System.getProperty("file.separator") + "conf" +
System.getProperty("file.separator") + "sen.xml";
TokenStream ts = null;
try{
ts = new SenTokenizer(reader,conf);
}
catch(IOException ignored){}
ts = new LowerCaseFilter(ts);
if (fieldName.endsWith("/ngrams/start")) {
ts = new EdgeNGramTokenFilter(ts, EdgeNGramTokenFilter.Side.FRONT,
minGram, maxGram);
} else if (fieldName.endsWith("/ngrams/inner")) {
ts = new NGramTokenFilter(ts, minGram, maxGram);
} else if (fieldName.endsWith("/ngrams/end")) {
ts = new EdgeNGramTokenFilter(ts, EdgeNGramTokenFilter.Side.BACK,
minGram, maxGram);
}
return ts;
}
};

public Analyzer getAnalyzer() {
return analyzer;
}
};
}

private static Instances learn() throws IOException{
Directory dir = new RAMDirectory();
new IndexWriter(dir, null, true).close();

Instances instances = new Instances(dir, getInstanceFactory(), "class");
for( String[] mat : MATERIALS )
instances.addInstance( mat[0], mat[1] );
instances.flush();
return instances;
}

private static void classify( Instances instances, String test ) throws IOException{
// 以下のどちらかを使用
BayesianClassifier classifier = new NaiveBayesClassifier();
//BayesianClassifier classifier = new FishersMethodClassifier();
System.out.println( "*****" );
System.out.println( test + " => " + classifier.classify(instances, test )[0].getClassification());
}
}



なかなか楽しいプログラムなので、試したい人がいるかもしれない。そこで、LUCENE-1039のパッチの当て方とビルドの方法を簡単に説明しよう。

<1> パッチは大抵の場合、その時点の最新trunkのソースに合わせて提出されるため、trunkのソースをSVNから取得する:



$ svn co http://svn.apache.org/repos/asf/lucene/java/trunk



これ以降、上記のオペレーションでできたtrunkディレクトリを$LUCENE_HOMEとする。

<2> LUCENE-1039からパッチファイルLUCENE-1039.txtをダウンロードして$LUCENE_HOMEに置き、次のようにパッチを当てる:



$ cd $LUCENE_HOME
$ patch -p0 < LUCENE-1039.txt



<3> LUCENE-1039のパッチがJava 5.0前提になっているので、次のbuild.propertiesを作成して$LUCENE_HOMEに配置する:



javac.source=1.5
javac.target=1.5



<4> Lucene本体をビルドする:



$ cd $LUCENE_HOME
$ ant



<5> contribのAnalyzerをビルドする:



$ cd $LUCENE_HOME/contrib/analyzers
$ ant



<6> contribのclassifierをビルドする。今回のパッチにはbuild.xmlが含まれないので、contrib/analyzers/build.xmlをコピーして次のように編集してcontrib/classifier/build.xmlとする:



<?xml version="1.0"?>
<project name="classifier" default="default">

<description>
Classifier
</description>

<import file="../contrib-build.xml"/>
</project>



そしてclassifierをビルドする:



$ cd $LUCENE_HOME/contrib/classifier
$ ant



以上のビルドで$LUCENE_HOME/build/以下にできた3つのJARファイルを使って前述のプログラムをコンパイル、実行できる。
| 関口宏司 | Lucene自由自在 | 22:29 | comments(0) | trackbacks(1) |
ThinkIT記事「JBoss EAP+Luceneによる全文検索システム」
JBossチームとのコラボによるThinkIT記事が公開された。

JBoss EAP+Luceneによる全文検索システム
| 関口宏司 | Luceneとは? | 11:35 | comments(2) | trackbacks(0) |
ホワイトペーパー「10分で簡単!RailsとSolrの全文検索デモ構築」
前回はRails+Solrの全文検索のデモについて書いた。

Railsアプリというとその構築の容易さをアピールする「10分で作る〜」というビデオを撮って公開することがはやっているようだ。そのうちに「10分で作るRailsアプリ」大会とかできるのではないか。TVチャンピオンでやればいいのに。

今回のデモはどのくらいでできたかというと、FlareというSolrのクライアントを使ってまあだいたい10分くらいでできたように思う。もっとも、Yahoo!オークションの200万件の商品データをクロールするのに数週間はかかっているし、データの登録にも20時間くらいかかっている。そういった時間を除けばRailsをいじっていた時間は正味10分くらいだったろう。自分にもビデオを撮る技術と時間があれば作って公開したいところだが、できないので、代わりに「ホワイトペーパー」を作成した。

10分で簡単!RailsとSolrの全文検索デモ構築
http://www.rondhuit.com/download.html

このホワイトペーパーでは、Flareに付属のデモデータを使ってRails+Solrの全文検索のデモ環境を作る方法が書かれている。

フロントアプリをRailsで組み、バックにSolr検索サーバを配置するのは現時点でかなり強力なWebアプリの構築ソリューションのように思うのだが、どうだろう。
| 関口宏司 | Luceneとは? | 14:10 | comments(0) | trackbacks(0) |
RailsアプリからSolrを使う全文検索のデモ
RailsアプリケーションからSolrを使う全文検索のデモを作成したので公開する。

http://www.rondhuit-demo.com/yademo/

Rails+Solr全文検索のデモ

デモシステムの全体構成は、次のようになっている。

Rails+Solr全文検索のデモシステム構成

デモシステムは、「フロントアプリサーバ」と「検索エンジンサーバ」の2つのサーバプロセスからなる。

「検索エンジンサーバ」はTomcatの上にSolrをデプロイして構成している。「フロントアプリサーバ」にはRailsで作られたアプリケーションが載っており、これがバックエンドの「検索エンジンサーバ」に検索のリクエストを送っている。そしてSolrから返ってきた検索結果をHTMLにしてブラウザに戻している。

上図の「フロントアプリサーバ」にはRailsという記述がないが、Flareと書いてあるのがRailsで構築されたSolrクライアントアプリケーションだ。このFlareがsolr-rubyを使ってSolrとの検索リクエスト/レスポンスの処理を行っている。

デモデータには「Yahoo!オークション」の商品データ約201万件を使用している。このデモデータはYahoo!のWebサービスAPIを使用して2007年7月から9月頃にかけてクロールして収集したものである。

検索の結果表示される商品説明はクロールしたHTMLをそのまま表示しているため、検索結果画面が多少乱れたり、画像抜けが起こったりする部分がある。また、本デモにはYahoo!オークションとしての機能は一切なく、単なる全文検索システムのデモであることをあらかじめお断りしておく。

このデモの使い方や特徴を以下で簡単に述べる。

検索キーワードサジェスチョン

Flareのセールスポイントの一つが「検索キーワードのサジェスチョン」機能である。これはGoogle Suggestなどでおなじみのものだ。

Flareの検索キーワードサジェスチョン機能

「検索キーワードのサジェスチョン」は検索キーワードの最初の数文字を入力すると、ユーザが検索ボタンをクリックする前にシステムがバックグラウンドで検索を行い、検索ヒット数と共に検索キーワードの候補をユーザに提示してくれるものだ。

ユーザにとって「タイプ量が節約できる」「他人の検索キーワードからヒントが得られる」「検索ボタンをクリックする前にどのくらい絞り込めるのかがわかる」など、多くのメリットがあるのがこの機能の特徴である。Flareはこれを最初から提供している。しかもRailsプログラマの期待を裏切ることなく、簡単な「規約」にしたがうだけでこの強力な機能がUIについてくるので製作側にとってもメリットが大きい。

Flareのサジェスチョン機能はGoogleと異なり、あくまでもLuceneのインデックスを使ってサジェスチョンしているので、サジェスチョンの単位が「語」にとどまっている。また、その仕組み上から背後では膨大な計算が行われており、ドキュメント数やユーザ数が多い場合に応答速度の点で若干難がある。さらに上図のようにカタカナ1文字で「ソ」と入力する場面は(ローマ字変換入力の場合)日本語ではあまりないと考えられるので、日本語での利用を考えたときには別の仕組みが必要である。したがって、Flareの「検索キーワードのサジェスチョン」は使えるアプリケーションかどうかをよく考えて導入するのがよいだろう。なお、これらの問題点を解消した「検索キーワードのサジェスチョン」を弊社で開発中である。

絞り込み検索

FlareのデフォルトのUIでは、画面右側に自動的に絞り込み検索用のリンクが作成・表示される。Yahoo!オークションの商品データを使用したこのデモでは、Yahoo!オークションのカテゴリ(category)と出品者(seller_id)の上位20位までが表示されている。

絞り込み検索では、リンクをクリックするだけで簡単に検索結果を絞り込むことができるようになっているため、ユーザからの人気が高い機能の一つである。この機能もFlareの簡単な「規約」にしたがうだけで使うことができる。

検索条件の保存

Flareでは検索窓に入力した検索キーワードと、絞り込み検索でクリックしたリンクを「検索条件」としてCookieに保存している。その内容は画面左上のFlareのロゴ(このロゴ画像はいくつかあるベータ版のうちのひとつであり、将来変わる可能性がある)の下に表示されている。

Flareの検索条件の保存機能

検索のたびにこの条件は追加・保存されるので、新たな検索のときは[clear constraints]のリンクをクリックしてそれまでの検索条件を消去する。あるいは、各検索条件の右隣にある小さな[x]のアイコンをクリックして当該検索条件だけを削除することもできる。さらに、検索条件をクリックすると、検索条件をその場で変更して再検索もできる。

Flareの検索条件の編集機能

このUIはRailsプログラマにはおなじみのものだろう。

| 関口宏司 | Lucene自由自在 | 12:47 | comments(0) | trackbacks(1) |
ホワイトペーパー「Solrの検索性能」
6万円のノートPCで毎秒200クエリを達成
「Solrの検索性能」 - ホワイトペーパー無料ダウンロード
| 関口宏司 | Luceneパフォーマンス | 08:25 | comments(0) | trackbacks(1) |
インデックスの診断・修復ツールの登場
Luceneインデックスの診断・修復ツールのパッチが公開された。

Basic tool for checking & repairing an index
http://issues.apache.org/jira/browse/LUCENE-1020


使い方は次のように起動時の引数にインデックスのディレクトリ名を指定する:


$ java -cp Luceneのクラスパス org.apache.lucene.index.CheckIndex インデックスパス名

Opening index @ インデックスパス名

Segments file=segments_w numSegments=1 version=FORMAT_SINGLE_NORM_FILE [Lucene 2.2]
1 of 1: name=_u docCount=27177
compound=false
numFiles=8
size (MB)=174.767
no deletions
test: open reader.........OK
test: fields, norms.......OK [17 fields]
test: terms, freq, prox...OK [287079 terms; 12193805 terms/docs pairs; 46143892 tokens]
test: stored fields.......OK [434832 total field count; avg 16 fields per doc]
test: term vectors........OK [0 total vector count; avg 0 term/freq vector fields per doc]

No problems were detected with this index.


上記はLucene 2.2インデックスに対する診断結果である。Lucene 2.3(現trunk)のインデックスに対して実行すると、次のようになる:


$ java -cp Luceneのクラスパス org.apache.lucene.index.CheckIndex インデックスパス名

Opening index @ インデックスパス名

Segments file=segments_n numSegments=1 version=FORMAT_SHARED_DOC_STORE [Lucene 2.3]
1 of 1: name=_a docCount=10000
compound=true
numFiles=1
size (MB)=231.87
no deletions
test: open reader.........OK
test: fields, norms.......OK [1 fields]
test: terms, freq, prox...OK [9988356 terms; 9999998 terms/docs pairs; 10000000 tokens]
test: stored fields.......OK [10000 total field count; avg 1 fields per doc]

test: term vectors........OK [0 total vector count; avg 0 term/freq vector fields per doc]

No problems were detected with this index.


なお、上記はいずれもoptimizeされた1セグメントのインデックスに対する診断結果であり、複数のセグメントからなるインデックスの場合は出力はもっと長くなる。

診断結果でエラーが見つかったら、起動引数に"-fix"をつけて修復を試みることができる。修復実行には必ずあらかじめインデックスのバックアップを取り、自己責任で行うこと。
| 関口宏司 | Luceneツール | 09:52 | comments(0) | trackbacks(0) |
会社ホームページのリニューアル
>> 株式会社ロンウイット/RONDHUIT Co., Ltd
| 関口宏司 | その他(分類不能) | 08:52 | comments(0) | trackbacks(0) |
+ Solrによるブログ内検索
+ PROFILE
 123456
78910111213
14151617181920
21222324252627
28293031   
<< October 2007 >>
+ LINKS
検索エンジン製品 - 比較のポイント
商用検索エンジンを購入した企業担当者は読まないでください。ショックを受けますから・・・
>>製品比較 10のポイント
+ Lucene&Solrデモ
+ ThinkIT記事
+ RECOMMEND
Apache Solr入門 ―オープンソース全文検索エンジン
Apache Solr入門 ―オープンソース全文検索エンジン (JUGEMレビュー »)
関口 宏司,三部 靖夫,武田 光平,中野 猛,大谷 純
+ RECOMMEND
Lucene in Action
Lucene in Action (JUGEMレビュー »)
Erik Hatcher,Otis Gospodnetic,Mike McCandless
FastVectorHighlighterについて解説記事を寄稿しました。
+ RECOMMEND
+ SELECTED ENTRIES
+ RECENT COMMENTS
+ RECENT TRACKBACK
+ CATEGORIES
+ ARCHIVES
+ MOBILE
qrcode
+ SPONSORED LINKS