CreateField Blog

オープンソースを使って個人でWebサービスを開発・運営していたブログ

GroongaとTokyoCabinetのHash表のベンチマークについて

はじめに

全文検索エンジンGroongaは超高速な全文検索ライブラリとしての機能を有しますが、単純なハッシュ表等のAPIも提供されており、ファイルへの永続化前提のインプロセス型のKVS(key value store)としても利用することができます。

ファイルへの永続化前提のインプロセス型のKVSとしては、Tokyo Cabinetが有名です。

今回は、簡単にGroongaとTokyo Cabinetの速度と容量について比較してみました。

なお、Tokyo Cabinetには、後継のKyoto Cabinetがありますが、メンテナンス性等を重視してC++で実装されており、単純な性能であれば、Tokyo Cabinetの方がやや良いということでしたので、今回はTokyo Cabinetを利用してみました。

検証環境

項目 バージョン/種類
CPU Intel(R) Xeon(R) CPU E5620 @ 2.40GHz 1CPU 4Core
Memory 32GB
HDD 2TB(SATA 7200rpm) * 2 Hardware RAID 0
OS CentOS 6.4
Groonga 4.0.3
Tokyo Cabinet 1.4.33

検証手順

以下のようにして、Groonga、Tokyo Cabinetをインストールします。

% rpm -ivh http://packages.groonga.org/centos/groonga-release-1.1.0-1.noarch.rpm
% yum makecache
% yum install -y groonga groonga-devel
% yum install -y tokyocabinet tokyocabinet-devel

Tokyo Cabinetは、CentOS6のbaseリポジトリ入りしており簡単にインストールできていいですね。

検証用に作ったC言語のプログラムをダウンロードしてコンパイルします。

https://github.com/naoa/groonga-tokyocabinet-bench

% git clone https://github.com/naoa/groonga-tokyocabinet-bench
% cd groonga-tokyocabinet-bench
% make

第1引数に構築するハッシュ表のキー数を設定して、キーと値の追加時間とキーから値を取得する時間を計測します。

% ./grn_hash_bench 1000000
% ./tchdb_bench 1000000

作成されたハッシュ表のファイルサイズを比較します。

% ls -lh groonga.grh tokyocabinet.tch

キーと値の追加時間

キー数 Tokyo Cabinet Groonga
10万 0.03sec 0.03sec
100万 0.54sec 0.35sec
1000万 40.17sec 4.35sec

Tokyo Cabinetは1000万で極端に遅くなっておりますが、何らかのチューニングポイントがあるかもしれません。ちなみに64GB以上はラージモードを使う必要があるらしいです。

http://alpha.mixi.co.jp/2010/10717/

キーから値を取得する時間

キー数 Tokyo Cabinet Groonga
10万 0.05sec 0.03sec
100万 0.56sec 0.28sec
1000万 18.91sec 2.78sec

ハッシュ表のファイルサイズ

キー数 Tokyo Cabinet Groonga
10万 5.1MiB 17MiB
100万 47MiB 65MiB
1000万 459MiB 661MiB

おわりに

Groongaは、全文検索だけではなく、ファイルベースのKVSとしてもとても優秀な速度性能を有しています。Tokyo Cabinetの方も十分に速く、空間効率に優れ、さらに、ファイルとして保持する場合はトランザクションの機能もあって堅牢性にも優れています。

GroongaのRubyバインディングのRroongaを使えば、Rubyからでも簡単にGroongaのハッシュ表を利用することができます。

以下の検証結果を見るとRubyのHashよりもTokyo CabinetのHashの方が速いということですので、Rubyで多数のキーと値のペアを保持したい場合は、Rroongaを使うことでRubyのHashよりも良いパフォーマンスが得られると思います。

http://www.xmisao.com/2013/10/04/tokyocabinet-ruby-benchmark.html

全文検索にGroongaを利用していて、KVSも利用したいという方はGroongaでのKVSを検討してみてはいかがでしょうか。

GroongaとElasticsearchの転置索引の違いと更新反映速度について

はじめに

こちらの記事では、GroongaElasticsearchの単純な検索性能、更新性能、 ディスク使用効率を比較しました。

その結果では、Groongaの検索速度がElasticsearchよりも数倍ほど速く、Elasticsearchの更新速度がGroongaよりも数倍ほど速かったです。

なお、前回の記事では、Elasticsearchでフレーズ検索がされていなかったり*1、punctuation、whiespaceが転置索引に入っていなかったため、追加検証結果を追記しています。

シーケンシャルなスクリプトではGroongaの更新速度のほうが遅かったですが、これは、GroongaとElasticsearchが利用しているLuceneの転置索引の作成方法や管理方法の違いによるものです。

Groongaにおける転置索引

Groongaでは、即時更新に強く更新にかかる処理コストが低くリアルタイムサーチであるという売り文句があります。

これは、転置索引更新の際に間に挿し込めるスペースがあるため、このスペースを使いつぶすまでの間、低負荷、且つ、高速な更新が見込めるとのことです。 このスペースに転置索引を差し込むことにより転置索引の断片化を防ぐことができ、検索性能の劣化を防ぐことができるようです。

http://qiita.com/tamano/items/663c2a958e897226e138
http://groonga.org/ja/blog/2011/07/28/innodb-fts.html

Groongaでは、カラムの値の更新の前に転置索引の更新が行われ、更新リクエストは転置索引とカラムの値の更新が完了した段階でレスポンスが返ってきます。 そのため、更新リクエストのレスポンスが返ってくればすでに全文検索可能な状態となっています。

たとえば、groonga-column-holeプラグインを使えば、転置索引を作った後カラムに値がセットされる前に値を削除して、カラムに値を更新させないなんてこともできます。

GroongaはOS資源関連(ファイルオープン数やmmap周り)のカーネルパラメータ以外はほとんどチューニングはいりません。というかありません。

Elasticsearchにおける転置索引

Elasticsearchでは、Nearリアルタイムサーチをうたっており、通常は1秒で検索可能になるということが書かれています。

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/_basic_concepts.html

Elasticsearchでは、ドキュメントの更新と転置索引の更新(リフレッシュ、フラッシュ、マージ)が独立しており、更新リクエストは、ドキュメントの更新が完了したタイミングでレスポンスが返ってくるみたいです。

デフォルトのインデックスのリフレッシュインターバルは、1sに設定されています。 おそらく、このリフレッシュによりドキュメントから作成された転置索引がメモリ上に乗って、その時点で検索が可能になると思われます。

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/index-modules.html

リフレッシュの後、フラッシュという処理が走るようです。フラッシュっていうのはマージと違って、新しくセグメントを作ってインデックスすることみたいです。 この状態では、ディスク上の転置索引が断片化し検索性能の劣化が生じていると思います。 デフォルトのフラッシュは、5sに設定されています。

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/index-modules-translog.html#index-modules-translog

その後、ディスク上に小分けに断片化した転置索引を所定のポリシーでマージしてディスク上に再配置する処理が走るみたいです。

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/index-modules-merge.html

さらっと読んだだけではデフォルトはtieredというポリシーでこのポリシーはlog_bytes_sizeと似たようなものだということはわかりましたが、どういったタイミングでマージが走るかよくわかりませんでした。 Elasticsearchは、設定項目がめちゃくちゃたくさんあってチューニングが大変そうですね。

optimizeをするとマージが明示的に行われるようです。

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-optimize.html

10/1追記
以下の記事には、Kyoto Cabinetにおける転置インデックスのバッファリング戦略が記載されています。
http://fallabs.com/blog-ja/promenade.cgi?id=127

前回のシーケンシャルな更新スクリプトの実行時間はGroongaの方ではデータ+転置索引の更新時間であり、Elasticsearchの方はデータの更新時間のみでした。

Elasticsearchは、Nearリアルタイムサーチということですが、使ったことがないので実際にどの程度で検索できるようになるのかよくわかりません。

そこで、GroongaとElasticsearchでデータ更新をしつつ実際に検索ができるまでの時間と、リアルタイム更新後の検索性能の違いを計測してみました。

検証環境

項目 バージョン/種類
CPU Intel(R) Xeon(R) CPU E5620 @ 2.40GHz 1CPU 4Core
Memory 32GB
HDD 2TB(SATA 7200rpm) * 2 Hardware RAID 0
OS CentOS 6.4
Groonga 4.0.3
Elasticsearch 1.1.2

検証準備

こちらの記事で紹介したスキーマを用意し、WikipediaのXMLを投入する準備をします。

これで、GroongaとElasticsearchはほぼ同じBigramのルールで転置索引が作られます。

厳密に言うと少し違います。GroongaのBigramでは前方一致検索*2を使えば1文字でも検索できるように末尾は1文字でトークナイズされます。 ElasticsearchのBigramでは末尾も2文字でトークナイズされます。

GroongaとElasticsearchの更新の反映速度

検証手順

以下のスクリプトを実行して、更新開始から全文検索可能になる時間を計測します。

(1) WikipediaのXMLをパースし、1件ずつ更新します。titleカラムには、短いタイトルでもユニークにするためidとtitleを結合して格納します。
(2) 更新後、更新したidとtitleでタイトルに対して全文検索します。
(3) 全文検索がヒットするまで10msec間隔でループします。
(4) (1)-(3)を1000件ループします。

検証結果

項目 平均
Elasticsearch 1.01sec
Groonga 0.09sec

このように、Groongaでは0.09secで検索可能となったのに対し、Elasticsearchではリフレッシュの間隔である約1secで検索可能となります。 ここはチューニングが可能なパラメータのようなので、おそらくindex.refresh_intervalを短くすれば速くすることができると思います。 ただし、その分処理負荷が増えると思います。

追記
リフレッシュも明示的に実行することができるようです。1s未満で検索したいときはこれを使えば検索可能になるようです。@johtaniさんが教えてくれました。ありがとうございます。

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-refresh.html#indices-refresh

ElasticsearchのoptimizeとGroongaの静的索引構築

Elasticsearchでは、以下のようにoptimizeすると明示的に転置索引をマージさせることができます。

% curl -XPOST 'http://localhost:9200/wikipedia/_optimize'

Groongaには、静的索引構築というものがあります。

http://groonga.org/ja/docs/reference/indexing.html

これを使えば、リアルタイムに更新を検索結果に反映させることはできませんが高速に転置索引を構築することができます。静的索引構築では転置索引の隙間が埋められるため、ディスク使用効率が良くなります。なお、静的索引構築中のカラムに対しても転置索引を使わない検索、データ出力は可能です。ただし、静的索引構築中は負荷が高いです。

前回の追加検証にGroongaの静的索引構築の結果を追加すると以下のようになります。

更新時間

Elasticsearch Groonga
(リアルタイム)
(参考) Groonga
(静的索引構築)
8853sec(2h27min) 21914sec(6h05min) データ:4271sec(1h11min)
インデックス:1685sec(28min)
合計:5956sec(1h39min)

※トータルの更新時間には、WikipediaのXMLパースが含まれています。前回と同様ですがElasticsearchには転置索引の構築完了の時間が考慮されていません。Elasticsearchはパース済みのデータをバルク投入させれば速くなると思います。Groonga(静的索引構築)の方もバルク投入させればデータ部分は数分もかからないと思います。

ディスクサイズ

Elasticsearch
(optimize前)
Elasticsearch
(optimize後)
Groonga
(リアルタイム)
Groonga
(静的索引構築)
19.3GiB 16.5GiB 18.9GiB 15.4GiB

全文検索時間

種別 Elasticsearch
(optimize前)
Elasticsearch
(optimize後)
Groonga
(リアルタイム)
Groonga
(静的索引構築)
トータル
(1千件)
216.161sec 141.701sec 50.062sec 52.236sec
平均 0.216sec 0.141sec 0.050sec 0.052sec
最長 4.313sec 1.037sec 0.339sec 0.401sec
最短 0.000960sec 0.00317sec 0.00215sec 0.00182sec

Groongaでは、リアルタイム更新でも静的索引構築でも検索性能がほとんど変わりません。 Elasticsearchでは、optimizeによって検索性能がかなり変わります。

Groongaでは、転置索引の断片化が抑制されているためリアルタイム更新だけしていても検索性能にはほとんど影響がありません。

したがって、Groongaでは、通常使用時には原則、静的索引構築し直す必要が有りません。バックアップからの戻しでは、静的索引構築すれば高速にリストアが可能となっています。静的索引構築は、リアルタイム更新に比べて、転置索引の更新時間だけで言うと10倍近く速いです。

まとめ

Groongaは、カラムが更新されると即時、転置索引が更新されます。そのため、リアルタイムに更新を検索結果に反映させることができます。 また、転置索引の間に隙間が設けられているため、転置索引の断片化による検索性能の劣化がほとんどありません。

このように、Groongaは検索速度や即時更新性という点が優れています。

Groongaには、ほとんど設定項目はありませんが、ファセット(ドリルダウン)、サジェスト、スニペット等、最低限、全文検索に必要な機能は一通り揃っています*3

たとえば、よりリアルな状態を反映したいECサイトではGroongaの方が向いているのではないでしょうか。 ユーザがECサイトで在庫有のものを絞り込んで全文検索をし、クリックしてアクセスしたら実際は在庫切れだったということを防ぐことができます。 また、ニュースサイトなど情報の鮮度が重要な場合にも向いていそうです。

一方、Elasticsearchは、Nearリアルタイムサーチを実現するために、リフレッシュやフラッシュ、マージ処理といった転置索引の管理処理が裏で走っています。 このため、検索可能となる時間はリフレッシュ間隔に依存します。フラッシュの転置索引の断片化により検索性能が劣化するため、マージによる転置索引のディスク上の再配置が必要です。

しかし、Elasticsearchは、非常に多機能で多数の設定項目があります。また、Elasticsearchは、容易にシャーディング、レプリケーションさせることができます。

Elasticsearchは、TBクラス、PBクラスの解析が必要な大規模分散環境におけるログ解析や統計解析に向いていそうです。 分散環境での反映速度はわかりませんが、1sで検索可能なら単純な全文検索エンジンの用途としてもほとんどの環境で問題がなさそうです。

Javaの知識が豊富なのでJavaで作られたElasticsearchの方が親和性が高くカスタマイズし易そう、 Elasticsearchの方が多数機能、多数設定項目があるのでリッチな全文検索システムがつくりやすそう、 Elasticsearchの方が世界で使われているし仕事の需要がありそう、 Elasticsearchの方がオシャレ、JVMで運用するのは特に気にならない、 という理由でElasticsearchを選ぶのもありかもしれません。

この他、SolrAmazon CloudSearchTokyo Cabinet/Kyoto Cabinetを利用した全文検索システムなど、それぞれの特性や制限事項*4、コスト等を検討して用途や環境にフィットするものを使えばいいと思います。

私は単純な全文検索エンジンとして利用するのであれば、Groongaがおすすめです。

7/28追記
GroongaをKVSとして利用した場合のベンチマークについて記事を書きました。Groongaは単純なKVSとして利用しても非常に高速です。よければ、こちらもご参照ください。
GroongaとTokyoCabinetのHash表のベンチマークについて

おわりに

Groongaは、国産のオープンソースで開発者も日本人で、且つ、かなり親切なので貢献に対する敷居も低いです。
私は仕事でプログラムを書いたことがなく、Gitも使ったことがありませんでしたが、Groongaを使うことによりGitの使い方や開発手法などたくさんのことを学ぶことができました。

*1:たとえば、Elasticsearchでは空白が含まれていなくともダブルクォーテーションでくくらないと、「東京都」のBigramが東京 OR 京都で検索されます。

*2:文書全体ではなく転置索引のトークンに対する前方一致です。たとえば、「日本の首都は東京です」という文書に対してBigramにすると「す*」でヒットします。Oracle TextのNgramなどでも同様に末尾は1文字でトークナイズされるらしいです。

*3:アナライザーやフィルターのラインナップは、Elasticsearch(というかLucene)の方が豊富ですが、文字列処理ですしGroongaでもトークナイザやノーマライザをカスタマイズ可能となっているので多少工夫すればなんとかなります。

*4:現状のGroongaには、カラム256GiB制限やレコード2億6千万という制限があります。

word2vecをDockerでプレーンテキストから簡単に使えるようにしました

はじめに

Dockerで簡単に使えるようにしてみた第2弾です。前回は、専門用語を自動抽出してくれるTermExtractをプレーンテキストで簡単に使えるようにしたDockerファイルについて紹介しました。

最近はword2vecが非常に話題になっていますが、word2vecは環境構築周りやテキストの前処理等がなかなかめんどくさいです。

そこで、word2vecと、プレーンテキストをRE2による正規表現フィルタ、ICUによるNFKC正規化(全角文字→半角文字変換等)、MeCabによる分かち書き等を実行してくれる自作のC++プログラムstring-splitterが自動で環境構築されるDockerファイルを作りました。

https://github.com/naoa/docker-word2vec

このDockerファイルには、単語間のベクトル距離が近い類義語っぽいものを出力するdistanceコマンドやking - man + woman = queenといった関係の類推語っぽいものを出力するword-analogyコマンドの他に、 ベクトルを自由に足し引き演算(+-)できるようにしたword2vec-calcコマンドも含まれています。

さらに実験的に、Word2vecの並列実行時の学習速度の改善で紹介されていた並列処理の高速化パッチも自動で適用されるようになっています。

これでDockerを実行できる環境があれば、スクリプトを組まなくとも、
(1)プレーンなテキストをdocker run経由でstring-splitterコマンドで分かち書き、
(2)分かち書きテキストをdocker run経由でword2vecコマンドで学習、
(3)学習済みモデルをdocker run経由でword2vec-calcコマンドでベクトル演算、
の3ステップで簡単*1にword2vecを試すことができます。

また、word2vec-calcコマンドではファイルからの入力やCSV(カンマ区切り)やTSV(タブ区切り)の出力形式も用意しているので、 単語を一気に読み込ませて、全文検索データベース用の同義語データを得るといったことも簡単にできるようになっています。

Dockerのインストール

Dockerが入っていない場合、まずはDockerをインストールしてください。Dockerは今結構旬なプロダクトなので導入に困ることはないんじゃないかなと思います。 CentOSなら以下のように簡単に導入できます。

% rpm --import http://ftp.riken.jp/Linux/fedora/epel/RPM-GPG-KEY-EPEL
% yum localinstall -y http://ftp-srv2.kddilabs.jp/Linux/distributions/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
% yum install -y docker-io
% service docker start
% chkconfig docker on

イメージ構築

まずは、Dockerイメージを作成します。コンテナとファイル共有するために/var/lib/word2vecディレクトリを作成しています

% git clone git@github.com:naoa/docker-word2vec.git
% cd docker-word2vec
% mkdir /var/lib/word2vec
% docker build -t naoa/word2vec .

Dockerイメージの構築が完了すると、以下のようにしてコンテナにターミナル接続することができます。

% docker run -v /var/lib/word2vec:/var/lib/word2vec \
  -i -t naoa/word2vec /bin/bash
% exit

Docker越しのコマンドは非常に長くなってしまいますが、たとえば、以下のようにエイリアスを張れば短くすることができます。

% alias word2vec="docker run -v /var/lib/word2vec:/var/lib/word2vec \
  -a stdin -a stdout -a stderr -i naoa/word2vec word2vec"
% alias word2vec-calc="docker run -v /var/lib/word2vec:/var/lib/word2vec \
  -a stdin -a stdout -a stderr -i naoa/word2vec word2vec-calc"
% alias string-splitter="docker run -v /var/lib/word2vec:/var/lib/word2vec \
  -a stdin -a stdout -a stderr -i naoa/word2vec string-splitter"

以下の作業は、コンテナ上ではなくホスト上でエイリアスが張られている前提で進めます。なお、コンテナ上で共有ディレクトリ以外に保存したファイルはコミットしなければコンテナの終了とともに消えるため注意してください。

MeCab辞書のコンテナへの共有

word2vecでより意味のある関係を得たいのであれば、文書のタイトル等抽出しやすい箇所からキーワードを拾い上げたり、前回紹介したTermExtractなどを使って、MeCab辞書をカスタマイズしたほうがいいと思います。
MeCab辞書のカスタマイズが終了したら、MeCab辞書をホストとコンテナの共有フォルダ/var/lib/word2vec/にコピーします。

% cp -rf /usr/lib64/mecab/dic/naist-jdic/ /var/lib/word2vec/naist-jdic

プレーンテキストを分かち書き

string-splitterコマンドを使ってプレーンテキストをword2vecで学習させる用のテキストファイルに変換します。
デフォルトの設定では、<>タグ、改行コード、一部の記号(\,.;:&^/-#'"()[]{}])が除去され、NFKC正規化+アルファベットの大文字小文字変換されてから分かち書きされます。
ここではコンテナからでも読み取れるように分かち書き済みテキストは共有フォルダ/var/lib/word2vec/wakati.txtに出力されるようにしています。

% cat example/open_source.txt | \
  string-splitter --mecab_dic /var/lib/word2vec/naist-jdic \
  > /var/lib/word2vec/wakati.txt

また、カスタマイズしたMeCab辞書を使用するために--mecab_dicオプションで/var/lib/word2vec/naist-jdicを指定しています。

string-splitterコマンドは、このほかMeCabを使って日本語の活用形を基本形に戻したり英語版WordNetを使って英語の複数形や過去形を基本形に戻したりするオプションも含まれています。

詳細はGitHubを参照してください。

分かち書き済みテキストをトレーニング

分かち書き済みテキスト/var/lib/word2vec/wakati.txtを読み込んで、/var/lib/word2vec/learn.binに学習済みモデルファイルを出力します。

% word2vec -train /var/lib/word2vec/wakati.txt -output /var/lib/word2vec/learn.bin \
  -size 200 -window 5 -negative 0 -hs 1 -sample 1e-3 -threads 12 -binary 1

学習モデルでベクトルの演算

トレーニングが完了するとコンテナ上のword2vec-calcコマンドで/var/lib/word2vec/learn.binを読み込ませることによりベクトル演算することができます。 なお、word2vec-calcコマンドではdistanceコマンド等と違い、--file_pathでファイルを指定するようになっているため、注意してください*2

word2vec-calcコマンドでは、単語半角スペース演算子(+-)半角スペース単語・・・で自由にベクトルの足し引きができるようになっています。たぶん100個ぐらいつなげられると思います。単語1個の場合はdistanceコマンド相当、単語2 - 単語1 + 単語3にするとword-analogyコマンド相当になると思います。

試しに前回構築した特許文書を学習させたモデルを使って、ベクトルの足し算をしてみます。なお、ここでは、echoコマンドを使ってコンテナの標準入力に渡していますが対話的に実行することも可能です。

% echo "データベース + 車両" | word2vec-calc --file_path /var/lib/word2vec/learn.bin --output 1
>
Word: データベース  Position in vocabulary: 1228

Word: 車両  Position in vocabulary: 305
0.743926        車両データ
0.739224        運行情報データベース
0.722270        走行履歴記憶部
0.712590        走行履歴データ
0.712389        自車両情報取得部
0.711377        走行経路情報
0.709190        車両運行情報
0.708623        中古車データベース
0.708502        状況認識部
0.707862        自車両情報

「データベース」に「車両」を足すことによって、車両関係のデータベースに関連するぽいような言葉が得られました。

echo "筆記具 + 消す" | word2vec-calc --file_path /var/lib/word2vec/jpa_abs.bin --output 1
>
Word: 筆記具  Position in vocabulary: 6017

Word: 消す  Position in vocabulary: 22672
0.674807        消しゴム
0.657548        筆記
0.655728        筆記用具
0.644496        万年筆
0.620492        描線
0.616586        マーカーペン
0.606570        サインペン
0.602623        化粧直し
0.597417        消せる

「筆記具」に「消す」を足すと最上位には「消しゴム」が現れました。それ以外はあまりそれっぽくないのでたまたまかもしれませんが、以下のように「消しゴム」は「筆記具」からの距離が4位なので少なくとも「筆記具」に「消す」を足すことで「消しゴム」に近づいているものと思われます。

echo "筆記具" | word2vec-calc --file_path /var/lib/word2vec/jpa_abst5.bin --output 1
>
Word: 筆記具  Position in vocabulary: 6017
0.784545        ボールペン
0.765932        筆記
0.763255        万年筆
0.754146        消しゴム
0.732143        水性ボールペン
0.720880        水性インキ

今度はパソコンの部品の「ディスプレイ」と「ハードディスク」と「ネットワーク」と「キーボード」を足してみます。

echo "ディスプレイ + ハードディスク + ネットワーク + キーボード" | word2vecalc --file_path /var/lib/word2vec/jpa_abst5.bin --output 1
>
Word: ディスプレイ  Position in vocabulary: 1262

Word: ハードディスク  Position in vocabulary: 4647

Word: ネットワーク  Position in vocabulary: 547

Word: キーボード  Position in vocabulary: 3742
0.736513        デスクトップ
0.711561        コンピュータ装置
0.705553        パソコン
0.702222        インタフェース
0.699718        コンピュータ用
0.689817        マルチウインドウ
0.687212        インターフェース
0.685114        携帯型コンピュータ
0.682025        コンピュータ機器
0.678986        コンピュータ本体
0.676609        画面共有システム
0.676334        プログラマブル表示器
0.674826        デスクトップ型
0.672900        コンピュータ
0.671351        汎用コンピュータ

上位にパソコンぽいものが得られましたね。

「動画」から「動き」を引いて見ます。

% echo "動画 - 動き" | word2vec-calc --file_path /var/lib/word2vec/jpa_abst5in --output 1
>
Word: 動画  Position in vocabulary: 2047

Word: 動き  Position in vocabulary: 1561
0.491828        静止画ファイル
0.480281        動画ファイル
0.456786        動画データ
0.456166        映像ファイル
0.451632        再生時間取得手段

「消しゴム」と同じように最上位以外は動画要素満々ですが、以下のように「静止画データ」は「動画」から7位でしたので、一応「動き」が減算されて、「静止画ファイル」が上位表示されたように見えます。

% echo "動画" | word2vec-calc --file_path /var/lib/word2vec/jpa_abst5.bin --output 1
>
Word: 動画  Position in vocabulary: 2047
0.742014        動画データ
0.740587        動画像データ
0.732553        動画ファイル
0.707877        静止画と動画
0.705789        高精細静止画
0.699955        映像
0.697672        映像データ
0.687976        静止画データ

このようにword2vec-calcコマンドでは、単語の足し算、引き算を自由に組み合わせることができます。 このほかword2vec-calcコマンドでは、オプションで出力を正規表現でフィルタさせたりCSVやTSVで出力できるようにしたりしています。
また、ファイルから一括で解析させることもできるので、全文検索データベース用の同義語(シノニム)ファイルを作ったりしやすくしています。

詳細はGitHubを参照してください。

おわりに

Dockerファイルを作っておけば、C言語やC++でライブラリに依存しまくってプログラムを作ったとしても、 簡単に環境構築できるため、非常に便利だなぁと思いました。

上記で実験した特許のデータはコーパスサイズ6.4Gとあまり規模を大きくしていないので、さらにコーパスを大きくしたらどうなるかも実験したいと思っています。 特許のデータは全体で数百GiBになるので分野を区切ったり色々実験したいと思います。

次は連想検索エンジンGETAssocのDockerファイルを作る予定です。 GETAssocは、word2vecのスキップグラムのように単語間のつながりまでは考慮していませんが、 文書に含まれる単語の共起表現から連想されるワードを高速、且つ、結構な精度で抽出することができます。 また、類似文書検索や文書から簡単に専門的な文書を検索することができます(参考)。

連想検索エンジンGETAssocはインデックス(NWAM)を作るのがめんどうだったり、データストアがなかったりするのですが、 このあたりは国産の超高速な全文検索エンジンGroongaと連携させて楽にできるようにしたいと考えています。

*1:Dockerコンテナでの作業イメージが沸かない方には簡単じゃないかもしれません。また、バージョンによってはホストの標準入力をコンテナの標準入力に渡すのがうまくいかないかも。

*2:なぜ、このようにしたかと言うと、単語の演算式を標準入力から渡せるようにしたかったからです。

専門用語を自動抽出するTermExtractをDockerで簡単に使えるようにしました

はじめに

品詞のつながりや出現頻度、学習情報から複合語らしきキーワードを自動で抽出するPerlモジュールTermExtractが公開されています。

これを利用すれば、形態素解析済みのテキストを食わせるだけでそこそこそれらしい専門用語をたくさん得ることができます。

このTermExtractは、ソースからインストールする必要があったり、EUC環境であったり形態素解析後のデータを入力に必要としたりなかなかめんどくさいです。

そこで、MeCabとTermExtractが自動で環境構築されるDockerファイルを作りました。

https://github.com/naoa/docker-termextract

このDockerファイルでは、正規表現フィルタや形態素解析、コスト推定などを自動でやってくれるPerlスクリプトも自動で導入されるようになっています。

これでDockerを実行できる環境があれば、プレーンなテキストをパイプでdocker runコマンドに渡すだけで、簡単に専門用語を抽出することができます。

また、形態素解析辞書の出力形式も用意しているので、出力結果を簡単に形態素解析辞書に組み込むこともできます。

Dockerのインストール

Dockerが入っていない場合、まずはDockerをインストールしてください。Dockerは今結構旬なプロダクトなので導入に困ることはないんじゃないかなと思います。 CentOSならepelリポジトリを有効にしてyum install -y docker-ioだけで導入できます。

イメージ構築

まずは、Dockerイメージを作成します。コンテナとファイル共有するために/var/lib/termextractディレクトリを作成しています。

% git clone git@github.com:naoa/docker-termextract.git
% cd docker-termextract
% mkdir /var/lib/termextract
% docker build -t naoa/termextract .

Docker上のTermExtractを実行して専門用語を抽出

echoコマンドやcatコマンドを使って、パイプ越しにプレーンテキストをdocker runコマンドに渡します。

% echo "印刷用紙を複合機で印刷する。" | \ 
  docker run -v /var/lib/termextract:/var/lib/termextract \
  -a stdin -a stdout -a stderr -i naoa/termextract termextract_mecab.pl
複合機                                298.54
印刷用紙                              14.01

Dockerコンテナ内に環境構築済みのTermExtractによって、「複合機」と「印刷用紙」という複合語を得ることができました。

数値は、重要度を示しています。学習機能を自動でオンにしているため、複数回実行すると重要度はどんどんあがっていきます。学習機能の詳細は本家サイトをご確認ください。学習用のDBは、/var/lib/termextract/stat.db/var/lib/termextract/comb.dbに作成されます。分野を変える場合やリセットする場合は、ファイルを移動するなり削除するなりしてください。

7/10追記

コマンドが長くてめんどくさいですが、エイリアスをはれば短縮できます。常用的に使う場合は、~/.bashrcなどの起動スクリプトに書けばよいです。

% alias termextract="docker run -v /var/lib/termextract:/var/lib/termextract \
  -a stdin -a stdout -a stderr -i naoa/termextract termextract_mecab.pl"

正規表現フィルタ

TermExtractでは、品詞のつながりや出現頻度、学習情報から複合語らしきものを結合しようとします。しかしながら機械的な処理なので誤って結合されることも結構あります。

形態素解析前にプレーンテキストから除去する文字列の正規表現パターンが記載されたファイル/var/lib/termextract/pre_filter.txtと、複合語抽出後に除外させる正規表現パターンが記載されたファイル/var/lib/termextract/post_filter.txtを用意しています。 TermExtractを実行しながらこれらのファイルを編集して適宜フィルタルールを調整することにより極力ノイズを減らすことができます。

出力形式

出力形式には、以下のように専門用語と重要度を出力してくれるモード、直接、IPAdic辞書の形式で出力してくれるモードを用意しています。

--output 説明
1 または 引数なし 専門用語+重要度
2 専門用語のみ
3 カンマ区切り
4 IPAdic辞書形式(自動コスト推定)
5 IPAdic辞書形式(文字列長)

せっかく自動コスト推定までしてくれる環境を作ったので、ついでにTermExtractを使わずに行ごとの単語リストをコスト推定してくれるモードも用意しています。

オプション 説明
--no_term_extract 専門用語抽出せずにコスト推定のみ実行

IPAdic辞書形式(自動コスト推定)

--output 4を指定するとMeCabで自動コスト推定したIPAdic形式の文字列が出力されます。

% echo "印刷用紙を複合機で印刷する。" | \
  docker run -v /var/lib/termextract:/var/lib/termextract \
  -a stdin -a stdout -a stderr -i naoa/termextract termextract_mecab.pl --output 4
複合機,1285,1285,7336,名詞,一般,*,*,*,*,複合機,*,*,ByTermExtractEst
印刷用紙,1285,1285,7336,名詞,一般,*,*,*,*,印刷用紙,*,*,ByTermExtractEst

これを利用すれば、プレーンテキストを入力するだけで、自動コスト推定までしたIPAdic辞書を簡単に追加することができます。

なお、自動コスト推定のアルゴリズムはよくわかっていませんが、自動推定によって追加した用語は推定コストが割り振られているため文脈によっては必ず区切られるとは限りません。

既存の形態素解析結果を極力壊したくない場合は、こちらを利用する方がいいかもしれません。

GroongaやElasticsearch、Solrなどの全文検索では、単語の前後の出現位置もマッチさせる完全転置索引方式をとっているため、コストを考慮せずに単純に用語を追加しただけの辞書を用いると検索漏れが多くなる惧れがあります。 全文検索では極力精度がおちないように慎重にチューニングするかNgramと併用するなど工夫が必要です。

MeCabには、既存の学習済みモデルと少量の学習データ(1行分の正解の形態素解析結果ぐらい)を使った再学習機能も備わっています。

再学習機能は、少量とはいえ自前で正解の形態素解析結果をつくる必要があるため、多数の用語ごとに学習データを準備するのはかなり大変です。しかし、ちゃんとドメイン適応したい場合は多少工数をかけてでも手動で学習モデルをつくったほうがいいかもしれません。

IPAdic辞書形式(文字列長)

--output 5を指定すると文字列長に応じてコストが設定されたIPAdic形式の文字列が出力されます。

% echo "印刷用紙を複合機で印刷する。" | \
  docker run -v /var/lib/termextract:/var/lib/termextract \
  -a stdin -a stdout -a stderr -i naoa/termextract termextract_mecab.pl --output 5 
複合機,0,0,-14500,名詞,一般,*,*,*,*,複合機,*,*,ByTermExtractLen
印刷用紙,0,0,-16000,名詞,一般,*,*,*,*,印刷用紙,*,*,ByTermExtractLen

これを利用すれば、プレーンテキストを入力するだけで、用語の文字列長に応じてコストが極端に低くなるように設定されたIPAdic辞書を簡単に追加することができます。

この場合、ほぼ既存の形態素解析辞書のコストよりも低くなるため、文脈によらず追加した用語が優先的に切りだされるようになります。

なお、この方法はすでに存在する用語を押しのけて切り出されるようになるので、短い用語や一般的な用語を追加するのはお勧めできません。

テキストマイニング系では多少の誤りは統計的に淘汰されることにより影響が低いと思われますので、多少ノイズがあっても専門用語を多数追加したほうがよい結果が得られるかもしれません。

IPAdic辞書形式(複合語抽出なし)

--no_term_extractを指定すると形態素解析、専門用語抽出をせずにMeCabで自動コスト推定したIPAdic形式の文字列が出力されます。

% echo "印刷用紙" | docker run -v /var/lib/termextract:/var/lib/termextract \
  -a stdin -a stdout -a stderr -i naoa/termextract termextract_mecab.pl --no_term_extract
印刷用紙,1285,1285,7336,名詞,一般,*,*,*,*,印刷用紙,*,*,ByMeCabEst

その他のオプション

その他、出力件数や重要度の閾値等を設定することができます。TermExtractのサンプルスクリプトにある設定項目はほぼすべてコマンドオプションにマッピングしています。 詳しくは、GitHubを参考にしてください。

MeCab辞書への追加

形態素解析速度を損なわないように、システム辞書へ追加することをおすすめします。

システム辞書への追加は、辞書ソースフォルダに辞書形式のテキストファイルを設置して再ビルドします。 なお、追加辞書ファイルの文字コードに注意です。このDockerの環境では、utf-8でテキストが書き出されるのでeuc-jpに戻す必要があります。

自動コスト推定した辞書の追加例

% docker run -v /var/lib/termextract:/var/lib/termextract -i -t naoa/termextract /bin/bash
% echo "印刷用紙を複合機で印刷する。" | termextract_mecab.pl --output 4 > /mecab-ipadic-2.7.0-20070801/user.csv
% cd /mecab-ipadic-2.7.0-20070801
% nkf -e --overwrite user.csv
% make clean
% ./configure --with-charset=utf8; make; make install
# echo "印刷用紙を複合機で印刷する。" | mecab
印刷用紙        名詞,一般,*,*,*,*,印刷用紙,*,*,ByTermExtractEst
を      助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
複合    名詞,サ変接続,*,*,*,*,複合,フクゴウ,フクゴー
機      名詞,接尾,一般,*,*,*,機,キ,キ
で      助詞,格助詞,一般,*,*,*,で,デ,デ
印刷    名詞,サ変接続,*,*,*,*,印刷,インサツ,インサツ
する    動詞,自立,*,*,サ変・スル,基本形,する,スル,スル
。      記号,句点,*,*,*,*,。,。,。
EOS

「印刷用紙」と「複合機」を追加していますが、「複合機」では分割されませんでしたね。MeCabの自動コスト推定の結果によって設定されたコストでは、この文脈では分割されませんでした。この文脈で正しく分割して欲しい場合は、正解の形態素解析結果を作って再学習させる必要があります。

文字列長に応じた低コスト辞書の追加例

% docker run -v /var/lib/termextract:/var/lib/termextract -i -t naoa/termextract /bin/bash
% echo "印刷用紙を複合機で印刷する。" | termextract_mecab.pl --output 5 > /mecab-ipadic-2.7.0-20070801/user.csv
% cd /mecab-ipadic-2.7.0-20070801
% nkf -e --overwrite user.csv
% make clean
% ./configure --with-charset=utf8; make; make install
% echo "印刷用紙を複合機で印刷する。" | mecab
印刷用紙        名詞,一般,*,*,*,*,印刷用紙,*,*,ByTermExtractLen
を      助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
複合機  名詞,一般,*,*,*,*,複合機,*,*,ByTermExtractLen
で      接続詞,*,*,*,*,*,で,デ,デ
印刷    名詞,サ変接続,*,*,*,*,印刷,インサツ,インサツ
する    動詞,自立,*,*,サ変・スル,基本形,する,スル,スル
。      記号,句点,*,*,*,*,。,。,。
EOS

こうすると、「印刷用紙」、「複合機」ともに優先して分割されるようになります。 ただし、この方法は、短い用語や一般的な用語が追加されないように注意した方がいいと思います。

Wikipediaでの用語抽出例

Wikipediaからオープンソースのカテゴリを持つページを抽出したテキストファイル6.4MBからTermExtractにより専門用語を抽出してみます。

なお、Wikipediaからのカテゴリを持つページの抽出は、以前、全文検索エンジンGroongaのRubyバインディングRroongaを使ったベンチマークプログラムで作成したデータベースから抽出しました。

% time cat example/open_source.txt | docker run -v /var/lib/termextract:/var/lib/termextract -a stdin -a stdout -a stderr -i naoa/termextract termextract_mecab.pl
real    0m57.540s
user    0m0.015s
sys     0m0.020s

解析結果の上位100位は以下の通りです。全データは、こちらから参照することができます。

% head -100 open_source_words.txt
オープンソース               3271565.53
ソースコード                  1148379.84
Linux                      1145244.41
Windows                              719143.07
フリーソフトウェア          528618.23
ファイルシステム             330097.36
プラグイン                      231639.42
Java                          224278.60
公式サイト                      178292.62
ソースファイル                119766.41
Linuxカーネル                    108254.88
ソフトウェア開発              99021.32
FreeBSD                       96416.05
Python                          85005.73
開発環境                          82837.95
BSDライセンス                    80794.42
設定ファイル                    79932.39
Webサイト                          76738.43
コンピュータシステム        71030.63
フレームワーク                 70935.05
Debian                       68897.67
コンピュータゲーム           68737.58
拡張機能                          66684.10
開発チーム                       64753.75
公式リリース                    62297.61
Unix系OS                             58288.22
Apache                           57019.52
Mozilla                          55182.90
処理系                             53580.87
Webシステム                       52866.46
Firefox                          50441.02
ファイル名                       49379.71
Webサーバ                          48128.29
管理画面                          46835.77
デスクトップ環境              46306.85
文字列                             44828.24
ゲーム機                          44209.68
Google                          44127.48
ファイル形式                    44066.47
開発プロジェクト              43722.48
仮想化                             42989.77
ゲームエンジン                 42329.06
ウェブブラウザ                 41486.02
Perl                          41174.69
Webアプリケーション           40369.26
フリーソフト                    40277.61
Debianプロジェクト              40133.80
Play                          39835.14
Apacheソフトウェア財団        39716.86
webページ                          36313.45
国際化                             35435.52
GNOME                           32105.18
コードベース                    30556.86
Webページ                          30230.03
GNUプロジェクト                 30071.87
文字コード                       29706.67
バックエンド                    27899.38
プロジェクト管理              27781.24
画面開発                          27641.52
著作権                             26789.01
ブラウザ                          26203.04
Unix                            25665.32
機能拡張                          25403.47
UNIX                          24603.10
デスクトップ                    24601.07
リンクコンピュータ           24400.02
サブプロジェクト              24241.51
Ruby                           24157.42
BSD系OS                              23188.30
アドベンチャーゲーム        23091.86
コマンドライン                 22857.34
作曲家                             22567.23
ファイルフォーマット        22391.98
変更点                             22186.33
Linuxシステム                     21900.20
ベースシステム                 21424.94
Unix系                        20711.56
ゲームプログラミング        20629.42
HTML                        20533.24
暗号化                             20299.04
編集機能                          19913.35
エンコード                       19837.66
オープンソース実装           19693.71
FLOSS                        19645.75
Windows用ゲーム                   19281.47
初期化                             19231.87
計算ソフト                       19102.70
クライアント                    19063.37
Emacs                          19013.35
研究プロジェクト              18959.65
開発終了                          18501.36
標準ソフト                       18411.54
オープンソース化              18354.86
MySQL                          18147.87
日本語化                          18143.13
Cライブラリ                      18091.82
ウェブサイト                    17744.98
機能開発                          17733.23
ブログ                             17712.72
データソース                    17667.48

経験則的に正規表現でフィルタをかけたおかげもありますが、重要度の上位はそこそこ良い感じにとれているのではないでしょうか。 なお、重要度が低い部分は結構ノイズがおおかったりするので、適宜閾値等を調整したり取捨選択したりする必要があると思います。

同様に、Wikipediaからファミリーコンピュータ用ソフトのカテゴリを持つテキストファイル11MBからTermExtractにより専門用語を抽出してみます。

%  time cat example/famicon.txt | docker run -
v /var/lib/termextract:/var/lib/termextract -a stdin -a stdout -a stderr -i naoa
/termextract termextract_mecab.pl > famicon_words.txt

real    1m1.901s
user    0m0.022s
sys     0m0.042s

解析結果の上位100位は以下の通りです。全データは、こちらから参照することができます。

# head -100 famicon_words.txt
ゲームオーバー                225391.74
コンピュータゲーム          207293.26
アクションゲーム             191859.12
ゲームソフト                   173559.54
アーケードゲーム              82471.63
攻撃力                             78720.54
ゲームシステム                 76020.80
シューティングゲーム        58060.15
バーチャルコンソール        47166.23
ゲーム画面                       47020.95
敵キャラクター                 41591.97
難易度                             38140.79
野球ゲーム                       33310.86
ゲームクリア                    31195.55
ステージクリア                 30310.27
ファミコンソフト              28704.64
アドベンチャーゲーム        27880.07
ゲーム作品                       25405.97
ゲーム機                          24178.18
ボスキャラクター              22827.36
ゲーム内容                       22718.59
ゲームモード                    22519.06
ボス戦                             19458.30
Aボタン                            19204.68
ボーナスステージ              18773.07
家庭用ゲーム機                 18195.87
プレイ                             16706.88
タイトル画面                    16570.34
残機                           14833.45
シリーズ作品                    14581.82
敵機                           14208.63
敵キャラ                          13983.64
戦闘機                             12714.64
Bボタン                            12165.97
ニンテンドーDS                  11585.81
ゲーム開始                       11576.77
ゲーム雑誌                       11135.99
パズルゲーム                    11131.51
ゲームシリーズ                 10931.45
ゲームボーイ                    10911.38
専用ソフト                       10823.23
キャラクターゲーム           10125.81
テレビゲーム                     9729.73
ゲームオリジナル               9713.91
ゲームブック                     8578.78
ボスキャラ                        8438.66
アクションゲーム画面         8421.34
敵弾                         8256.72
登場キャラクター               8193.54
攻撃アイテム                     8107.03
防御力                              7834.61
ゲーム終了                        7511.86
ファミリートレーナー         7510.19
ボス敵                              7395.66
攻略本                              7162.74
登場人物                           7125.86
戦闘力                              7112.11
仕事カード                        6867.87
ボスキャラクターボス         6849.71
攻撃ボタン                        6795.73
ゲームデザイン                  6549.28
ジャンプ力                        6441.60
ゲームデータ                     6272.59
パックマン                        6256.40
マリオシリーズ                  6251.48
守備力                              5980.39
ゲームソフトナムコ            5954.83
ファミコン用ソフト            5871.01
ゲームソフトサン電子         5733.77
移植作品                           5698.47
ゲームスタート                  5677.25
人同時プレイ                     5628.80
ナムコゲーム                     5594.78
体当たり                           5571.98
獣人                           5546.24
アクションステージ            5507.70
ハゲ丸                              5492.77
障害物                              5465.10
シリーズ作                        5406.64
ステージ構成                     5246.22
変更点                              5239.89
ステージ開始                     5236.79
スタートボタン                  5235.63
ゲームバランス                  5186.70
キャラクターデザイン         5149.77
ゲーム化                           5125.85
人対戦                              5061.89
赤影                            4954.96
対戦相手                           4934.96
PCゲーム                            4851.10
PCエンジン                         4830.22
ゲーム発売                        4825.91
ゲームソフトセガ               4792.47
マップ画面                        4769.02
リメイク                           4753.66
ボーナス点                        4691.56
攻撃方法                           4580.24
ステージボス                     4379.08
PC用ソフト                         4378.88
宝箱                             4226.46

「ゲームソフトセガ」、「ゲームソフトナムコ」、「ボスキャラクターボス」などあまり正しくない結合のされ方も含まれていますが、ある程度はそれらしい用語も抽出できていますね。 他のオプションを組み合わせたり学習情報によっては、うまく解析できるようになるかもしれません。

おわりに

このような一時的な解析環境の構築は一度やった後は、結構忘れがちなのでDockerで環境を作っておくと便利だなぁと思いました。

文書構造的に容易に抽出可能なタイトルやキーワードなどから固有名詞を抽出する方法が知られています。 たとえば、Wikipediaのタイトルやはてなキーワードなどがよく知られていますね。

よりキーワードを集めたい方は、TermExtractを使ったキーワード抽出を試してみるといいのではないのでしょうか。

最近は、word2vecなどに興味がある人が多いと思いますが、学習の前には用語を抽出して辞書に追加した方が面白い結果が得られると思いますよ。

word2vecや連想検索エンジンGETAssocのDockerファイルも近日中に作ろうと思っています。

7/14 記事を追加しました。

word2vecとプレーンテキストをフィルタや正規化をしつつ分かち書きしてくれるstring-splitterコマンドとベクトルを自由に足し引き演算(+-)できるようにしたword2vec-calcコマンドをDockerファイルdocker-word2vecで簡単に使えるようにしました。また、アナロジー以外のベクトル演算をした実験結果を紹介しています。

word2vecをDockerでプレーンテキストから簡単に使えるようにしました

全文検索エンジンGroongaユーザ勉強会@神戸を主催しました

2014/06/27(金)に全文検索エンジンGroongaユーザ勉強会@神戸を主催しました。

開催のきっかけ

草の根Groongaイベントのお誘いを受けて、関西圏でもGroongaのイベントがあるといいなと思い、神戸でも開催してみることにしました。

会議室の確保

人の集まり具合がどうなるかわからなかったので、三宮近辺でできるだけ費用が抑えられるというポイントで会場を探しました。WordBench神戸などが利用されているような貸会議室ビジネスしているところだと、平日夜間でも1万円を超えるところが多かったです。人が数十人来ることがほぼ確定しているプロダクトの勉強会なら千円徴収すればなんとかなりますが、小規模が想定される勉強会での利用は難しかったです。

そこで、公民館など市営の施設の会議室をこちらから探してみました。公民館等の場合、だいたい10数名規模の部屋で数千円といったところでした。

その他、インターネットで探して見ると、KIITOが1時間につき500円で時間単位の貸し出しOKで、且つ、比較的、予約も空いていたので利用することにしました。無料で備品も貸出しており、なかなか穴場なんじゃないかなぁと思いました。ただ、費用は安く抑えられましたが、駅からやや遠いのが難点でした。

告知

DoorkeeperやTwitter、メーリングリストなどで告知しました。また、近隣のRuby関西GDG神戸のAngularJSの勉強会などで簡単な開催のお知らせをしました。

当日の様子

19:00を超えると、入り口がclosedって札が立つのを知らなくて、入るのに戸惑った人がいて申し訳ありませんでした。

平日ということもあって、19:30ぐらいになるまでなかなか人が集まりませんでしたが、最終的には、当日キャンセルなしで合計10名が参加していただけました。ありがとうございました。

今回の勉強会では、Groongaの紹介と事例紹介を発表しました。

Groongaの紹介では、私が説明しながら、Groongaの開発に携わっている須藤(@ktou)さんが適宜、補足や質問に答える形で進めました。開発に携わっている方から直接、詳細な情報が聞けるいい機会になったんじゃないかなと思います。

事例紹介では、特許の全文検索サービスPatentFieldを紹介しました。当サービスでは、PHPからMroongaを使っていますが、Groongaの機能をすべて使いたかったので、全文検索はUDFを使ってGroongaのコマンドを使っています。基本的にGroongaのほぼすべての機能を使っているので、実際に使っている様子と工夫した点を紹介しました。

参加していただいた@shigeponさんが、ブログに勉強会の感想を書いてくれています。よければ、こちらもご参照ください。

懇親会

勉強会終了後、終電間近まで懇親会が行われました。懇親会では、Groonga関連の話もGroongaに関係ない話も盛り上がってた思います。@soundkitchenさんからdocker-mroongaについて紹介がありました。MroongaをDockerを使って簡単にイメージ作るにはこれしかない!と熱弁されていました。Dockerを使って、Mroongaを簡単にサーバにデプロイしたい方は是非使ってみるといいのではないでしょうか。

感想・反省点

進行がなかなかうまくいかず、発表を用意していただいた方もいらっしゃったのですが、時間を確保できなくて申し訳ありませんでした。

実際にコマンドをうちながら説明したいなぁと思ったのですが、現場では案外パッとでてこないので、事前に準備しておいたほうがよかったなぁとおもいました。

また、平日ということもあり、なかなか19時丁度に全員集まるのは難しかったので、今後、開催することがあれば、できるだけ休日に開催してみようかなと思っています。

勉強会の主催経験がなく拙い進行でしたが、参加いただいた皆様、および、わざわざ東京から来ていただいた須藤(@ktou)さん、どうもありがとうございました!

Groongaの今後への期待

当日できなかったGroongaの今後への期待の資料です。この資料は、メーリングリストで案内があった[groonga-dev,02439] Groongaの今後の開発への協力のお願いへの回答です。

61st Ruby/Rails勉強会@関西でLTしました

以下は、LTの資料です。

MacとRabbitの操作に戸惑ってしまい、デモの検証が一部しかできませんでした。デモができなかった分の検証結果を追記しています。

2014/6/27(金)19:00~神戸でGroongaの勉強会をします。Doorkeeperで募集していますので、興味がある方は是非ご参加ください。

http://koberoonga.doorkeeper.jp/events/11578

「Mroongaを使ったときの MySQLの制限との戦い」という内容で初LTしました

MySQL勉強会 in 大阪(第6回)でLTっていうのをはじめてやってみました。

内容は、「Mroongaを使ったときの MySQLの制限との戦い」です。

資料づくりにほとんど時間をかけられなくてすごい雑です。また、現場でちゃんとLTを見たこともなかったので、趣旨や作法があっているのかもよくわかりません。

うまくしゃべられなかった上に制限時間の5分を数十秒超えちゃってた気がします。

あまり人前での発表は得意ではないですが、無料で普段得られない経験値が得られるので大変お得だと思いました。

質問事項

LTの後、機材の調整の関係で少し時間があって、いくつか質問があったので覚えている範囲で書いておきます。

Q.ソースをいじってMroongaではいけるけど、その状態でInnoDBはどうなる?
A.ストレージエンジン側の制約をうけると思います。3072バイト制限はInnoDBでは3500バイトって書いてました。インデックス64個制限は、普段InnoDB使っていないのでわからないです。複数インデックス云々は、完全にGroongaのレイヤーで処理させる話なのでInnoDBには関係ないです。

Q.GroongaのコマンドはMySQLとは別にHTTPサーバたててる?
A.Groongaに直接コマンドを発行できるUDF(mroonga_command)があるのでそれを使っています。

Q.最終的にほぼGroongaでやるってことだけどMySQLを介す意味はある?
A.ないです。結局は、Groongaがはやいですよってことだけです。まぁでもやっぱりSQLで操作できるのはすごく楽で、GroongaでJSONをつくってloadさせるのは大変なんでINSERTやUPDATEはSQLでやっています。