関口宏司のLuceneブログ

OSS検索ライブラリのLuceneおよびそのサブプロジェクト(Solr/Tika/Mahoutなど)について
<< ThinkIT記事「JBoss EAP+Luceneによる全文検索システム」 | main | LuceneのHighlighterの重要性 >>
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) |









http://lucene.jugem.jp/trackback/153
[Java]Luceneでベイジアンフィルタ
Lucene使ってベイジアンフィルタつくって、まず、スパムフィルターでもやってみようかなと思ったら、Luceneのパッチで、ベイジアンフィルタを使うパッチというのがJIRAにあがっていた(via http://lucene.jugem.jp/?eid=153) https://issues.apache.org/jira/browse/LUC
| 此処から望む景色 | 2008/10/06 12:36 AM |
+ Solrによるブログ内検索
+ PROFILE
   1234
567891011
12131415161718
19202122232425
262728293031 
<< March 2017 >>
+ 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