« 2012年9月 | メイン | 2012年11月 »

2012年10月

2012年10月17日 (水)

Solr4.0のデフォルトのschema.xmlを読む

こんにちは。

前回Herokuで全文検索事情について書きましたが結局は自前でSolrのサーバを立てることになりそうです。

Herokuには前回とりあげた以外にもElasticSearchのラッパーが現在ベータ版のAddOnとしていくつかあるんですが、多分どれも似たり寄ったりです。(--

結局のところ日本人スタッフのいない環境で作成された全文検索サービスはもれなく日本では使い物にならん!という結論に達しました。(^^;;;

□□□□

そんな訳で最近よくSolrをいじっているわけですが、日本語での全文検索エンジンを構築する場合に早い段階で意思決定しなければならない事柄の一つに単語分割にN-gramと形態素解析のどちらを使用するか?という命題があります。

この両者がどういうアルゴリズムであるか?またそれぞれにどういうメリット・デメリットがあるか?という点については多くのサイトで解説されているのでそれらのサイトを参照してもらえば良いかと思います。
ここではSolrに標準でバンドルされているschema.xml(example/solr/collection1/conf/schema.xml)から、実際にどのように文章が分割されインデックスされるのかを掘り下げてみようと思います。

 

★N-gram

schema.xmlの中でN-gram(厳密には2文字分割のBi-gram)の定義は「text_cjk」という名前のfieldTypeで行われています。

以下にその定義を示します。

 

    <!-- CJK bigram (see text_ja for a Japanese configuration using morphological analysis) -->
    <fieldType name="text_cjk" class="solr.TextField" positionIncrementGap="100">
      <analyzer>
        <tokenizer class="solr.StandardTokenizerFactory" />
        <!-- normalize width before bigram, as e.g. half-width dakuten combine  -->
        <filter class="solr.CJKWidthFilterFactory" />
        <!-- for any non-CJK -->
        <filter class="solr.LowerCaseFilterFactory" />
        <filter class="solr.CJKBigramFilterFactory" />
      </analyzer>
    </fieldType>

 

定義ファイルのそれぞれの要素や属性の詳細な解説はパスします。
ここでは「tokenizer」が単語分割を行うクラスの指定、「filter」が分割された単語のフィルタリングや正規化を行うクラス、という程度の理解があれば十分です。(というか、そもそもちゃんとドキュメント読んでないので僕の理解もその程度です。。。(^^;;;)

さて、この定義を見ていくとまず先頭のtokenizer定義でStandardTokenizerFactoryという全く特殊性の感じられないTokenizerが使用されていることがわかります。
実際、このTokenizerは英文などのホワイトスペース区切りの単語分割でも使用される最も一般的なTokenizerです。日本語の文章に対してこのTokenizerを適用した場合は英文や連続するカタカナなどは1単語として認識されますが、それ以外のひらがなや漢字などはすべて1文字1単語として分割されます。

実際にBi-gramを作成しているのは一番最後に定義されているCJKBigramFilterFactoryです。(つまりFilterで単語分割位置を変更するというややトリッキーな実装になっている)
ものの本によると昔はCJKTokenizerFactoryというのがあって、いきなりN-gramを作っていたようですが多分今の構成の方が後続のFilterを適用しやすいのでこのような実装になっているのではないかと思います。

間に挟まっている2つのFilterの役割は以下です。

 

CJKWidthFilterFactory

半角カナは全角に、全角英数字は半角に正規化します。

 

LowerCaseFilterFactory

英大文字をすべて小文字に正規化します。

 

要するに半角全角の違いや大文字小文字の違いはインデックス作成の際に吸収されており、検索者は気にする必要がないということです。

 

★形態素解析(Kuromoji)

次に形態素解析の定義を示します。
コメントが多いので削ろうか迷いましたが、これだけで定義内容がわかるほどの情報量があるのでそのまま残しました。

 

    <fieldType name="text_ja" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="false">
      <analyzer>
      <!-- Kuromoji Japanese morphological analyzer/tokenizer (JapaneseTokenizer)

           Kuromoji has a search mode (default) that does segmentation useful for search.  A heuristic
           is used to segment compounds into its parts and the compound itself is kept as synonym.

           Valid values for attribute mode are:
              normal: regular segmentation
              search: segmentation useful for search with synonyms compounds (default)
            extended: same as search mode, but unigrams unknown words (experimental)

           For some applications it might be good to use search mode for indexing and normal mode for
           queries to reduce recall and prevent parts of compounds from being matched and highlighted.
           Use <analyzer type="index"> and <analyzer type="query"> for this and mode normal in query.

           Kuromoji also has a convenient user dictionary feature that allows overriding the statistical
           model with your own entries for segmentation, part-of-speech tags and readings without a need
           to specify weights.  Notice that user dictionaries have not been subject to extensive testing.

           User dictionary attributes are:
                     userDictionary: user dictionary filename
             userDictionaryEncoding: user dictionary encoding (default is UTF-8)

           See lang/userdict_ja.txt for a sample user dictionary file.

           Punctuation characters are discarded by default.  Use discardPunctuation="false" to keep them.

           See http://wiki.apache.org/solr/JapaneseLanguageSupport for more on Japanese language support.
        -->
        <tokenizer class="solr.JapaneseTokenizerFactory" mode="search" />
        <!--<tokenizer class="solr.JapaneseTokenizerFactory" mode="search" userDictionary="lang/userdict_ja.txt" />-->
        <!-- Reduces inflected verbs and adjectives to their base/dictionary forms (辞書形) -->
        <filter class="solr.JapaneseBaseFormFilterFactory" />
        <!-- Removes tokens with certain part-of-speech tags -->
        <filter class="solr.JapanesePartOfSpeechStopFilterFactory" tags="lang/stoptags_ja.txt" enablePositionIncrements="true" />
        <!-- Normalizes full-width romaji to half-width and half-width kana to full-width (Unicode NFKC subset) -->
        <filter class="solr.CJKWidthFilterFactory" />
        <!-- Removes common tokens typically not useful for search, but have a negative effect on ranking -->
        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ja.txt" enablePositionIncrements="true" />
        <!-- Normalizes common katakana spelling variations by removing any last long sound character (U+30FC) -->
        <filter class="solr.JapaneseKatakanaStemFilterFactory" minimumLength="4" />
        <!-- Lower-cases romaji characters -->
        <filter class="solr.LowerCaseFilterFactory" />
      </analyzer>
    </fieldType>

 

TokenizerはKuromojiという形態素解析エンジンを利用したJapaneseTokenizerFactoryです。userDictionary属性でユーザー辞書を指定することができます。(サンプルとしてバンドルされているユーザー辞書には「朝青龍」とか定義されていてちょっと和みます。)

以下次の順序でFilterが適用されていきます。

 

JapaneseBaseFormFilterFactory

このFilterは動詞などの活用形を正規化します。
例えば(動詞と判定された)「し」を「する」に変換するみたいな。

 

JapanesePartOfSpeechStopFilterFactory

不要な品詞を削除します。
どの品詞が不要かはtags属性で指定したファイル内に記述します。
サンプルとしてバンドルされているファイルでは助詞、助動詞、接続詞、記号が削除されるようになっています。

 

CJKWidthFilterFactory

N-gramでも使用されていた半角カナと全角英数字を正規化するFilterです。

 

StopFilterFactory

words属性で指定されたファイルに記述されている単語を削除します。
サンプルとしてバンドルされているファイルでは「その」とか「そして」などのおよそ検索に使用されそうにない単語が100個程度定義されています。

 

JapaneseKatakanaStemFilterFactory

カタカナの最後の長音を削除します。ただし文字数がminimumLengthに満たないものでは削除されません。
例えば「ユーザー」は「ユーザ」に正規化されますが「コピー」はそのままです。

 

LowerCaseFilterFactory

N-gramでも使用されていた英大文字を小文字にするFilterです。

 

★考察

ここまで見てきた通りN-gramより形態素解析の方がきめ細かい設定が可能です。

ここではとりあげなかった有用そうなFilterとしてSynonymFilterという単語の同一視が可能なFilterもありますが、これもN-gramでは使用できません。

直観的には形態素解析の方が精度が高そうな気がしますが、品詞の削除などによって元の文章がインデックス作成時に破壊されているという点は大きなポイントだと思います。
例えば人名や書籍のタイトルなどを対象とする場合はN-gramの方が向いているように思います。

SolrではFieldTypeの定義によってどのように文章が分割されるのかが管理ツールで簡単に確認できます。そのため開発中には辞書や定義ファイルを変更しながらチューニングを行うことも可能ですが、その場合インデックスの再構築が必要なはずなので扱う文書量が多い場合は運用中に変更することは難しいかもしれません。

ここから先は実際に開発を始めてみないと何とも言えないですね。(^^;;;

2012年10月 4日 (木)

Herokuの全文検索事情

こんにちは。

Herokuで全文検索(当然日本語)を行う場合にどういう選択肢があるのか調査したのでそのレポートを書いてみます。

 

★評価のポイント

Herokuには複数の全文検索Addonがあり、またPostgreSQLにも全文検索の機能があるのですが今回評価のポイントとしたのは以下の2点です。

 

・日本語に対応しているか?

全文検索は英語などのヨーロッパ圏の言語と、日本語などのアジア圏の言語(CJK)では実装の難易度が大きくが異なります。

英語なんかは単語がスペースや改行などのホワイトスペースで区切られているので、単語の分割で悩む必要がないんですね。一方の日本語の文章は基本的に切れ目なく連続して記述されるのでどうにかして単語を分割しなければなりません。

この単語分割の方法には「形態素解析」と「N-gram」という2つの有力なロジックがあってそれぞれに特徴があるのですが、とりあえずそこはまぁどちらでも良いです。

問題なのは欧米圏で作成されている全文検索のサービスは往々にしてホワイトスペース区切りの英文分割にしか対応していないということです。(--
なので全文検索対応を謳っている製品であっても初手からアウトということは結構あります。

 

・セキュリティ

調査を始めてちょっとびっくりしたことなんですが、全文検索業界(?)のセキュリティ対策はとんでもなくザルです。(--

ほとんどすべてのサービスがREST形式のWebAPIで操作を行うんですが、驚いたことに何の制限もかかっていません。
つまりURLさえ知っていれば誰でもインデックスにアクセスできてしまう訳です。

検索APIがどこからでも使えるのはまぁ良いかと思えるんですが、更新APIまでアクセスフリーなのってアリっすか???

誰かが勝手にインデックスを更新したり削除したりできるサービスというのはちょっと怖くて使えないと思うんですけど。。。

 

以降この2点を中心に評価レポートを書いていきます。

 

PostgreSQLの全文検索

HerokuはPostgreSQLのバージョンアップにはかなり良いペースでついて行っていると思います。2012年10月現在HerokuのPostgreSQLのバージョンは9.1.6(9.1系の最新)です。
この9月には9.2が出たのでこれも近いうちに追随すると思われます。

なので、9.1で入ったN-gram対応の全文検索が使えるはずです。。。

。。。が!、現在この機能を日本語圏で使用する場合はソースの一部をコメントアウトしてリビルドしなければならないらしいです。(これもかなりビックリしましたが。。。)

configパラメータすら変更できないHerokuではまぁ無理ですね。。。(--

 

WebSolr

Solrベースの全文検索サービスです。
4月のHeroku Meetupの時に中の人が来て宣伝してました。(^^;

その時には「Solr3.6からKuromojiという形態素解析エンジンが使える。それを使えば日本語の形態素解析も使えるようになる。WebSolrはまだSolrのバージョンアップをしていないが近いうちにやるつもりだ」というようなことを話していたと思いますが、いまだにKuromojiは使えないようですね。。。
N-gramでの検索は問題なく通りました。

セキュリティは困ったことに検索、更新APIともにアクセスフリーです。(--
これについてはサポートフォーラムに質問があがっていて、今作っているところだという回答もありますが、どうなっていることやら。。。

なんとなくですがスタッフまで含めて数名でまわしている気配を感じるので、あんまり多くは期待できない気がします。(これは今回調査したHerokuのAddonベンダーすべてについて感じた感想でもあります。)

あとWebの管理コンソールが貧弱なのもなんとかしてほしい。
せめて検索のテストは管理コンソール上からできるようにしてほしいです。

スキーマの設定については一応Solrのschema.xmlを丸ごと貼り付けることができるのですが、今のUIのままだとKuromojiに対応してもユーザー辞書の設定やStopWordsの設定とかができない気がします。

 

Searchfy Hosted Search

Index TankというサービスをラップしたAddonです。
これもSolrのようです。

日本語対応はおそらくN-gram。管理コンソールで検索のテストもできますが、設定可能な項目はWebSolrよりも少ないですね。

そしてこれも検索、更新ともにアクセスフリーです。。。(--

どちらかというとまだWebSolrの方が良いですかね。

 

Flying Sphinx

SphinxはPythonで作られた全文検索エンジンらしいです。
これだけ実際には試しておらずドキュメントを読んだのと日本語の対応状況を検索しただけです。

日本語の対応方法はいくつかのサイトで解説されていますが、ソースを変更しないといけないのでHerokuのアドオンでは無理なんじゃないかと思っています。(N-gramには標準で対応しているかもしれませんけど。。。)

APIアクセスにはヘッダにAPIキーを含める必要がありますが、NonceやHashとの組み合わせではないので、URLさえ知っていればアクセスできるというのとあんまり変わらないような気もしています。

試さなかったのはJava用のクライアントライブラリが用意されておらず、自分でREST APIのラッパーを書くのが面倒だったからですが他に良いのがなければまた戻ってきます。

 

Amazon Cloud Search

HerokuのAddonではないですが、AWSにもCloud Search(Beta)という全文検索のサービスがあったので試してみました。

が、日本語対応されておらずあえなく終了。。。(--

APIアクセスに関してはアクセス可能なIPアドレスの範囲を制限できるのですが、Herokuから使う場合Dynoが再起動する度にIPが変わるので使えない気がします。

ちなみに検索をかけていたら自力で日本語を分割して使用するというツワモノがいました。

自力でのワード分割は考えたことありませんでしたがアリかもしれません。

 

★自力でEC2にSolrを立てる

思考実験です。

Solrのサーバーを自分で立てるのは難しくありません。
EC2に入れてWebAPIとしてアクセスできるようにするまではすぐだと思います。

この場合、日本語対応は自力で形態素解析でもN-gramでもどちらでも自由に設定できます。

Securityに関してもServletFilterでヘッダをチェックするロジックを入れれば良いだけなので多分どうにでもなる。

ただ障害に備えて冗長化構成を取ることを考えた場合にはどうするのが良いのか迷いますね。。。
マスタ1台とスレーブ2台を用意して参照系はELBを通して常にスレーブのみを参照するようにするのが楽かな?

まぁいずれにしても最後の手段ですね。

 

★PostgreSQLに自力で分割したカラムを追加

思考実験その2です。

AWSのツワモノ記事を見て思いついたんですが、クライアント側でKuromojiを使用して分割した文字列を別カラムに登録するのはアリですね。
クエリー文字列も同様にKuromoji分割すれば複数単語の組み合わせにも対応できます。

形態素解析を行うのはクライアント側のプログラムなので辞書やStopWordの設定も自由自在です。

スコアやファセットが必要ないならこれで十分な気もします。

 

★まとめ

どんなもんでしょうか?(^^;

残念ながら現状では日本語をちゃんと扱える全文検索のサービスはどれもイマイチというのが今回の結論です。

セキュリティに目を瞑ればWebSolrも悪くはないんですが、普通はアウトなんじゃないでしょうか。

正直Solrを使えばWebSolr相当のものを作るのはそれほど難しくないと思うので、日本発のAddonの候補としては悪くないと思いますよ。 > 誰?(^^;

2012年10月 2日 (火)

文字コードのお話のお話

こんにちは。

社内で勉強会をする機会があったのでその資料をSlideShareにアップしました。

http://www.slideshare.net/shunjikonishi/ss-14537848

僕自身は文字コードネタはJIS2004が出たあたりまでは、興味深く追いかけてましたがその後のあまりの混迷ぶりについていけなくなって脱落しました。(^^;;;

例えば製品やライブラリを調査する際にはよくソースコードを読んだりするわけですが、そういうのは深く調べていけばいつかは底にたどり着きます。しかし文字コードはどこまで潜っても底が見えない!そういう意味では技術者向きのネタではないような気もしています。

この資料でははしょっている部分もたくさんあるんですが、文字化けの原因を推測するという目的に対しては十分なんじゃないかと思います。
ご意見、ご感想、誤りの指摘等あれば是非コメントお寄せください。m(_ _)m

□□□□

今回久しぶりに気合を入れて文字コード関連の資料をあさりましたが、実のところそれほど目新しい発見はありませんでした。
Mac OS Xのファイル名で合成文字が普通に使われているのにびっくりしたくらい。

約5年のブランクがあるのにそれほど目新しい発見がないということは文字コード問題がようやく収束に向かいつつあるということなのかもしれません。
JISが新しい規格を提案することはおそらくもうないでしょうし、はやいところUnicode一択の世界になってほしいものです。

その一方でサロゲートペアへの対応は思ったほど進んでないとも感じました。
個人的にはこれはFEPの問題が大きい気がしています。例えばサロゲートペア説明の定番文字「魚花(ほっけ)」。(このブログでも保存できません。。。(--)

Windows7のOffice IME 2007では普通に変換候補として表示されますが、iOS6では候補に挙がってきません。要するに簡単に入力する手段がないからいつまでも普及しない
ただWindowsで入力できるのであればそろそろ「特殊な文字」という言い逃れもできないフェーズに来ていると思うんですけどね。。。。エンドユーザーに対して「できません」が、いつまで通用するのかはかなり怪しいと思っています。

メールに関してはもはや「正しいISO-2022-JP」が復権する可能性はないと思っています。「Shift_JIS」と「Windows-31J」が正しく使い分けられることも多分ないでしょう。
Webに関しては大分Unicode化が進んでいてそうしたことに煩わされる機会も減っているように思いますが、メールはiso-2022-jpで送信する慣習がなかなかすたれないですねぇ。。。(--
誰かが送信メールを各国語に自動翻訳してマルチパートで送ることができるようなメールクライアントを開発すればUnicode化が一気に進むかもしれません。(^^;;;

以上、文字コードの資料を作成してのとりとめのない感想でした。

採用情報

株式会社フレクトでは、事業拡大のため、
Salesforce/Force.comのアプリケーション
開発
HerokuやAWSなどのクラウドプラッ
トフォーム上でのWebアプリケーション開発

エンジニア、マネージャーを募集中です。

未経験でも、これからクラウドをやってみた
い方、是非ご応募下さい。

フレクト採用ページへ

会社紹介

株式会社フレクトは、
認定コンサルタント
認定上級デベロッパー
認定デベロッパー
が在籍している、
セールスフォースパートナーです。
heroku partnersにも登録されています。
herokuパートナー
株式会社フレクトのSalesforce/Force.com
導入支援サービス
弊社の認定プロフェッショナルが支援致します。
・Visualforce/Apexによるアプリ開発
・Salesforceと連携するWebアプリ開発
も承っております。
セールスフォースご検討の際は、
お気軽にお問合せください。
Powered by Six Apart