TAMALOG

プログラミングがあれば遠いところへ行けます。プログラムと人の共生を記録します。

NGT(高次元ベクトルデータ検索技術)をGolangでごまかして雑なJSON APIにする

類似画像検索システムに組み込むための高次元ベクトルデータ検索技術を探していました。Yahoo! Japanが開発したNGT(高次元ベクトルデータ検索技術)を見つけたので試してみます。

f:id:tamanobi:20170627025115p:plain https://www.flickr.com/photos/21001756@N06/2087512650/

表形式をJSON APIに変換する

前回は、NGTをDockerで動かすところまで紹介しました。 tamanobi.hatenablog.com

公式ドキュメントに従って検索コマンドを実行すると、表形式の出力が得られます。 github.com

 $ ngt search -n 20 index ./data/sift-query-3.tsv
  Query No.1
  Rank  ID  Distance
  1 3031    239.332
  2 4079    240.002
  3 3164    244.504
  4 3718    246.763
  5 157 251.094
  6 2422    251.185
  7 1313    251.34
  8 379 252.446
  9 3521    260.158
  10    2594    261.132
  11    4627    262.381
  12    2159    263.471
  13    3519    264.909
  14    1764    265.136
  15    4400    266.156
  16    2717    266.914
  17    3168    269.637
  18    4236    270.673
  19    4700    272.725
  20    679 272.973
  Query Time= 0.000472 (sec), 0.472 (msec)

検索システムとして利用する上では、この表示形式は使いづらいためJSONで返せるようにパッチを当てます。

JSON出力ができるようにパッチを当てる

NGTはC++で書かれているので、STLをJSONにシリアライズするライブラリを探します。今回はヘッダーを読み込むだけで利用できるライブラリを使用しました。 github.com

ngt searchコマンドにjson出力用のオプションを加えました。本家のmasterとの差分は以下のリンクを参照してください。個人向けの雑な修正なので本家にPRは送らない予定です。

Comparing yahoojapan:master...tamanobi:feature/json_output · yahoojapan/NGT · GitHub

差分を取り込んで、buildすればjsonオプションが有効になります。例えば、 ngt search -o j -n 20 index ./data/sift-query-3.tsvとoオプションにjを渡せば、JSONが出力できます。

ここまでで検索バックエンドの下準備は終わりました。JSONは出力されるものの、HTTP経由でのアクセスに対応していないので何かしらの言語でウェブサーバーを立ててAPIサーバーにします。

GolangでさくっとAPIサーバー

開発速度を鑑みて、それなりに高速でシンプルにJSON APIサーバーかける言語を採用します。今回はGolangにしました。コードはとてもシンプルです。特定のエンドポイントにファイルがPOSTされたらコマンドを実行するだけです。

https://gist.github.com/tamanobi/d10c932eebbd8c4c5ee0ca6f5143f3e9

tsv形式のファイルをいちいち送らないといけないのが、ナンセンスですが今回はよしとします。

Docker

これまでに、2つの変更を行いました。NGTにパッチを当てたこと、GoでのAPIサーバーの作成です。何も考えずに実行できるようにDockerfileを作りました。

github.com

リポジトリにDockerfileが入っているので、 docker build -t tamanobi/ngt_webapp .としてビルドを行ってください。ビルド後に、docker run -it -p 2300:8000 tamanobi/ngt_webappとすればウェブサーバーが立ち上がり、ホストOSの2300番ポートにAPIサーバーに転送されるようになります。

まとめ

NGTをHTTPを介して使うために、2つの準備を行いました。

  1. NGTにパッチを当てて、JSON出力に対応
  2. GolangでNGTコマンドを発行するウェブサーバーを立てる

次回

次回は、Golangのサーバーに対してリクエストを送ってNGTのデータベース構築や検索を行ってみます。

高次元ベクトルデータ検索技術「NGT」の環境をDockerで爆速構築

類似画像検索システムを構築するにあたり、高次元ベクトルデータの検索にNGTを使いました。本稿では、NGTの環境をDockerで爆速構築する方法を紹介します。

f:id:tamanobi:20170626030130j:plain

NGT

NGTとは、高次元ベクトルデータを高速に検索するコマンド及びライブラリのことです。Yahoo! Japanによって開発されました。

techblog.yahoo.co.jp

膨大なベクトルデータの検索でこのようなライブラリが必要とされます。僕は、十万枚規模の画像特徴ベクトル(4000次元)の検索に利用しました。

Docker

NGTはUbuntuでの動作確認が行われています。UbuntuをベースイメージとしたDockerコンテナを作っていきます。

Dockerコンテナの作成

以下のようなDockerfileとシェルスクリプトを用意します。これらを実行するだけです。

for NGT · GitHub

シェルスクリプトを動作させれば、NGTがコンパイルされた状態のDockerコンテナが作成され、コンテナのbashにアタッチできます。 アタッチした環境(Bash環境)では、 ngt コマンドが動作します。

ビルド時間は長いですが、一度環境を作ってしまえばとても簡単にベクトルデータ検索ライブラリが使えるようになります。

NGTを試す

NGTの試し方は公式を参考にしてください。

github.com

まとめ

Yahoo! Japanが作成した高次元ベクトルデータ検索ライブラリNGTを試せる環境をDockerを用いて瞬時に作成する方法を紹介しました。

Dockerfileに環境構築の手順が書いてあるので、時間が経ったあとでも環境を再現しやすいでしょう。

次回予定

次はGolangでNGTをバックエンドにした(雑な)APIサーバーを作ります。

画像収集基盤の構築ログ10

目的

人の代わりに画像を集めてくれるシステムを構築すること。なお、個人的な趣味でイラスト画像を対象としている。

tamanobi.hatenablog.com

進捗

  • Dockerのネットワーク絡みの問題を解消
  • 暫定的にローカルに保存していた画像をテーブルに格納した
  • Viewのコード整理(DRY)
  • Controllerのコード整理(ハードコーディング除去)

  • そろそろクローリング戦略に手をつけたい

画像収集基盤の構築ログ9

目的

人の代わりに画像を集めてくれるシステムを構築すること。なお、個人的な趣味でイラスト画像を対象としている。

tamanobi.hatenablog.com

進捗

雑感

これまでやりたいと思っていたことが優秀なミドルウェアによってスムーズに実現できている。この数日間は特にDockerにとても助けられている。それぞれ別の役割を持ったアプリケーションサーバーが10弱も必要になったことがわかったときにはシステムの起動・再起動をどう制御しようか思いつかなかった。Dockerであれば構成がテキストファイルとして管理できる。再起動も容易だ。こんなに便利な存在を教えてくれた GitHub - isucon/isucon6-final には感謝している。ISUCONは勝ち負けのあるコンテストだが、負けたからといって学びがないわけではない。雑なアプリケーションがどういうものか知ることができるし、そもそもアプリケーションの構成も学びになる。Dockerもそれで知った。たったひとつのコマンドでミドルウェアを含めてアプリケーションが立ち上がる様は、圧巻だった。

参考文献

画像収集基盤の構築ログ8

目的

人の代わりに画像を集めてくれるシステムを構築すること。なあ、個人的な趣味でイラスト画像を対象としている。

tamanobi.hatenablog.com

進捗

  • Jubatusの近似近傍探索を試した
    • illustration2vecを使って1000次元弱の特徴量をJubatusに登録した
    • 登録データから類似画像を検索する事に成功した

類似画像検索について

illustration2vecはイラストのタグ(一人の女性、猫耳、青い髪など)を学習・推論する手法です。1000個のタグを学習していれば、最終的な出力は1000次元ベクトルとなります。Jubatusにはこのデータを登録しています。つまり、illustration2vecを特徴量抽出として利用しているわけですが、タグというイラストのメタ情報を予測する性質があります。描かれているそのものを対象とした類似画像検索よりも、抽象度の高い検索をかけることが可能です。似ている画像を探すのではなく似たような画像を探すような、探索的検索に力を発揮しそうです。

Jubatusでは、画像データを渡すとORB特徴量を取り出す機能があります。ORB特徴量は画像特徴量の一種で、画像の拡大・縮小・回転・トリミング・ノイズに対して頑健な特徴量です。パテントフリーなので安心して使えます。illustration2vecとORBそれぞれでJubatusの近傍探索を試してみたいと思います。それぞれ違う用途として使えそうで楽しみです。

画像収集基盤の構築ログ7

目的

目的は、人間の代わりに画像を集めてきてくれるシステムを構築することです。個人的な趣味からイラスト画像を対象としています。

tamanobi.hatenablog.com

進捗

  • スクレイピングを試せるような管理画面を作成
    • これまでのCLIをウェブアプリ化
    • プレビュー(Dry Run)機能を追加
    • CSSフレームワークの選定
    • リファクタリング
  • 推薦システムに関する論文を読んだ

f:id:tamanobi:20170504212532p:plain

余談

SAOをやっと視聴しましたが、夢のある話でとても良いですね。アニメーションの話つながりで思い出しましたが、「東のエデン」という作品で「東のエデンシステム」というシステムが登場します。カメラをかざすだけでそこに写っている物体が何かわかるそういうシステムです。最近の機械学習界隈でそのシステムの実現が現実味を帯びてきています。あのシステムの存在は僕にとって大きな衝撃を与えてくれたのでかなりワクワクしています。

参考資料

Alpine LinuxのRoswell環境をDockerで作った

複数のmacOSでLispプログラムを書くとき、環境を用意することが面倒なので、RoswellのDockerをAlpine Linuxベースで作成しました。デプロイ時にもコンテナがあれば便利ですね!

https://hub.docker.com/r/tamanobi/alpine-roswell/

今度はこのコンテナを使ってHerokuにLispウェブアプリをデプロイする予定です。