2014-04-07

Ansible にて、ssh の接続情報を記述する方法

ようやく Ansible 始めたけど右も左も分からない初心者なので、忘れないようにメモっておきます。

ssh 接続に関する情報をどこに記述すればいいのか?

方法 1: .ssh/config に記述する

ssh コマンドが参照する .ssh/config ファイルに、ssh 接続に必要な情報を記述する方法です。

Host hoge.example.com
    HostName     hoge.example.com
    User         deployguy
    IdentityFile ~/.ssh/id_rsa.hoge.example.com

普段お使いの .ssh/config を Ansible にそのまま流用・活用することができるため、 開発者ごとにサーバへのログインアカウントが異なる場合に適している方法と言えるでしょう。

一方で、Ansible 自体のバージョン (1.2 以前) や OS にインストールされている OpenSSH のバージョン (具体的には、 ControlPersist をサポートしていないちょっと古いバージョン) によっては、 ssh コマンドではなく Paramiko という Python 製の SSH クライアント (?) が使われるようで、 その場合には .ssh/config が参照されませんので、注意が必要です。

上記の条件に当てはまる場合で、Paramiko ではなく ssh コマンドを使いたいときは、 以下のように Inventory ファイルで ansible_connection パラメータに ssh を指定すれば いいようです。

[server-hoge]
hoge.example.com  ansible_connection=ssh

方法 2: Ansible の Inventory ファイルに記述する

ansible-playbook コマンドのオプション -i で指定する Inventory ファイルに、 接続設定を記述する方法です。

[server-hoge]
hoge.example.com  ansible_ssh_user=deployguy  ansible_ssh_private_key_file=~/.ssh/id_rsa.hoge.example.com

各開発者の .ssh/config に依存しないことと、方法 1 にあったような Ansible / OpenSSH のバージョンによる ssh 接続手段の違いを意識する必要がないため、この Inventory ファイルをリポジトリで共有することで環境依存・属人的な状態を小さく保つことが出来るでしょう。

一方で、ログインアカウントの情報を Inventory ファイルに記述する必要があるため、開発者ごとにサーバへのログインアカウントが異なる場合にはこの方法はあまり向きません。

参考文献

9:02No comments

2014-03-31

バンディットアルゴリズムのシミュレータを作ってみました

お手軽に各種バンディットアルゴリズムの特性・性能を比較することができる Web ベースのバンディットアルゴリズムシミュレータを、Yeoman, Bower, Grunt, D3.js, NVD3.js, AngularJS, Bootstrap なんかを使って作ってみましたよ、というお話です。

デモサイト&ソースコード

シミュレータのデモサイトとソースコードはそれぞれ以下になります。

動機

とあるお仕事で各種バンディットアルゴリズムの特性を調査・検証したことがあって、そのときは Java で各種アルゴリズム&シミュレータを実装 → TSV ファイルにシミュレーション結果を出力して Excel でグラフ化、なんてことをやっていました。けど、これが結構な手間でして、どうにかならないかなーと悩んでいたところで、「あれ、これって JS でバンディットアルゴリズムを実装しちゃえば、d3.js とか使って Web ブラウザでお手軽にシミュレーション&可視化できるんじゃね?」と思い立ったので作ってみた次第です。

あと最近、仕事・プライベート問わず JS に触れる機会がめっきり減ってしまったことで、フロントエンドの開発事情にめっきり疎くなてしまったこともあり、そんな状況に危機感を抱いていて作ってみた、という副次的な動機もあったりします。

所感

作ってみた所感など。

  • この程度の規模の Web アプリケーションでも AngularJS を使って開発をしておくと、モジュール構成を疎結合にできてよい感じです。
  • Bower の依存モジュールの管理・解決の仕組み、フロントエンド開発でもこういうことが実現できるのは素晴らしいですね!
  • Grunt は詳細機能を使いこなす程度に慣れるまでに、ちょっと学習コストが掛かりそう。JSON でもりもりと設定を書かなきゃいけないのはやっぱり辛い…
  • D3.js を生で取り扱うとなると、結構辛いですね… 特に AngularJS と統合して使うのはかなり苦労するかも。
  • でも、出来合いのチャート表示をしたいだけなら NVD3.js を組み合わせて使うのがおすすめ! これを使うとすごく楽ちんです!

ToDo

もうちょっと機能を追加したり改善したいと思っています。

  • 1,000 回のイテレーションでも結構重いので、進捗を表示したい
  • 2 腕バンディット問題のシミュレーションしかできていないけど、n 腕対応したい
  • 何回かシミュレーションした結果を箱ひげ図表示したい
12:37No comments

2014-02-27

LZ4 の近況を確認してみる

lz4-ruby の開発を進めるために、LZ4 の近況を確認してみたところ、 それなりに活発に開発されているようで変更点が多かったため、メモを兼ねてエントリにまとめてみました。

r76 から r113 までの変更履歴を追う形で、主だった変更を列挙していきます。

API が増えた

r76 の時点ではマクロを含めて 6 個だった API が、r113 では obsolete を除いても 36 個と大幅に増えました。

LZ4 の基本機能は以前とはそう変わらないものの、後述するストリーム処理用 API など、 利用シーンごとに適した API を拡充しているようです。

liblz4 が作成されるようになった

r111 より。

以前の LZ4 は Makefile はあれど make してもライブラリは生成されず、 そのためアプリケーションから LZ4 の圧縮・伸長機能を利用しようとすると、 アプリケーションのビルド時に lz4.c などをあわせてコンパイルし、 同ソースコードのオブジェクトファイルをリンクする必要がありました。

この方法では LZ4 のリビジョンをアップデートしてアプリケーションを 再ビルドする手順がちょっと複雑になるデメリットがありましたが、 r111 で更新された Makefile によって、ライブラリ liblz4.a / liblz4.so が生成されるようになり、この問題は多少緩和されたのではないかと思います。

ただ、make install でのライブラリ / ヘッダファイルのインストールには 対応しているものの、 yum やら apt-get でインストールできるわけではないので、 依存パッケージの自動的な解決などはまだ期待できません。

ストリーミング処理に対応した

r102 より。

以前の LZ4 では、圧縮したい単位で圧縮対象のデータを API に渡し、また圧縮後のデータを記録する ヒープを十分に割り当てした上でAPI を呼び出す必要がありました。 この API 構成は zlib などの API とは大きく異なり、利用ケースによっては使い辛いこともあったようです。 (圧縮・伸長の時間性能を稼ぐためには仕方のない API 設計ではあったのですが…)

r102 で導入されたストリーム処理の API によって、ストリーミング的な圧縮処理を実現することができるようになりました。 (詳しい利用方法などは確認中です…)

LZ4 HC の圧縮レベルを指定できるようになった

r113 より。

LZ4 には、時間的な圧縮処理性能を犠牲にしつつ、空間効率的によりよい (= 圧縮率を重視した) 結果を得るためのモード、 LZ4 HC が存在します。

直近のリビジョンである r113 にて、この LZ4 HC に「圧縮レベル」パラメータが追加され、 圧縮率と処理時間のトレードオフのバランスを開発者がチューニングできるようになりました。

圧縮・伸長の時間効率がさらに向上した

LZ4 の一番の特徴である高速な圧縮・伸長処理は継続的に改善されているようです。 特にプラットフォームやコンパイラごとの細かな最適化がなされている印象です。

まとめ

更新履歴 を見るとそれなりに開発が継続されているようですし、 イシュー を見てもまだやるべきことは残されているようなので、今後も開発は継続されていくことでしょう。まだまだ要注目ですね!
23:11No comments

2014-01-21

Ubuntu 12.04 LTS 上で OpenCV 1.0.0 をソースコードからビルド&インストールする

はじめに

2.x 系が公開されているこのご時世に、やんごとなき理由により OpenCV 1.0.0 をソースコードビルド&インストールしなければならない状況、エンジニアの皆さんなら一度や二度は経験していますよね。ね?

今回、Ubuntu 12.04 LTS 上で OpenCV 1.0.0 を苦労しながらソースコードからビルドしてみたので、そのメモを残しておきます。

1. パッケージのインストール

パッケージのインストールなどを先に済ませます。個人的な好みで aptitude を使っていますが、 apt-get でも同様にインストールできるはずです。

$ sudo aptitude install build-essential

# コンパイルエラー/リンクエラーを阻止するために、これはインストール必須。
$ sudo aptitude install libv4l-dev
$ sudo ln -s /usr/include/libv4l1-videodev.h /usr/include/linux/videodev.h

# 必要に応じて、取捨選択する
$ sudo aptitude install libjpeg-dev libpng-dev

2. OpoenCV 1.0.0 のダウンロード

ブラウザから、こちら のページより tar.gz ファイルをダウンロードし、適当な作業用ディレクトリ上に展開しておきます。

3. OpenCV をビルドする

まずは作業用ディレクトリ上で

$ ./configure

します。問題なく実行完了がしたところで、 make ... をする前に、こちら のページの "1) Error message:" にあるとおり、 cxcore/include/cxmisc.h の条件式なしの #elif#else に書き換えておきます。この書き換えをしておかないと、早々にコンパイルエラーが発生してしまいます (残りの 2, 3 の Error message については、 libv4l-dev パッケージのインストールとその後のシンボリックリンク作成で対処できるようなので、スキップして構いません)。

cxmisc.h の書き換えを終えたところでようやく

$ make
$ sudo make install

でインストールは完了します。

19:02No comments

2013-11-18

第4回 #渋谷java で JUnit のオブジェクト等価比較処理を怠ける (ために Matcher を頑張る) トークをしてきました

通算3回目の参加・発表ということで大変お世話になっている 第4回 #渋谷java でお話してきました。5 分の LT では語れなかった内容が多々あるので、それらを盛り込んでエントリを残しておきます。

発表資料は以下です。

発表で使用する予定だったデモコードは komiya-atsushi/shibuya-java4 に置いておきました。

オブジェクト等価比較を怠けたくなった背景

事の発端

元々は SAStruts なとあるお仕事において、JSON を返却する Web API の Action クラスの各メソッドを JUnit でテストしたい、というのが事の発端でした。

このテストの本来の理想的な姿は、Tomcat などの AP サーバを経由して HTTP で実際に Web API を呼び出し、その結果のレスポンス の JSON が期待している内容と同一かどうかを比較する… というものでした。しかし、この構成を JUnit / S2JUnit4 で実施するにはなかなか難儀することが予想された(ぶっちゃけ面倒だった)ため、早々に Action クラスのメソッドを直接呼び出すことで得られる JSON 文字列を (デシリアライズして) アサーションする、という現実的な方針に切り替えました。

そういうわけで、Web API から返されるちょっと複雑なデータの JSON を Java のオブジェクトとして取り扱いつつ、それに対して期待している結果と等しいかどうかの等価比較 ( assertThat(actual, is(expected)); ) をすることが求められたわけですが… まあ Web API の戻り値として返すようなオブジェクトのクラスに Object#equals() がオーバーライド実装されていることなんてそうあるわけでもなく、ただひたすらにオブジェクトにプロパティ経由で値を参照して assertThat(actual.getHoge(), is(expected.getHoge()); する、みたいなテストコードの記述を強いられる残念な状況が生じたわけです(さすがに、さしみたんぽぽ作業をただひたすらに続けられるほど、僕はできているエンジニアではなかったので、2, 3 行試しに書いてみたところで見事に崩折れました)。

Object#equals() の実装

assertThat() の羅列が本当に羅列すぎて生きるのが辛いので、本来は equals() の実装は不要だけれども JUnit でのテストのために致し方なく本末転倒的にオーバーライドすることも念の為に考えてみました。

幸いにして、 Apache commons-langEqualsBuilder を使うと、比較的容易に equals() を実装することができます (commons-lang については こちらの資料 が参考になります)。特に、 EqualsBuilder#reflectionEquals() を使うと驚くほど簡単に equals() を実現できます。

しかし一方で、 EqualsBuilder を使って equals() を実装してアサーションを行うようにすると、アサーションに fail したときのメッセージが以下のように役立たずなメッセージになる、というデメリットが存在します。

java.lang.AssertionError: 
Expected: is <foo.bar.HogeBean@9a8d9b>
     but: was <foo.bar.HogeBean@22c6bb6c>

Matcher による解決の試み

Object#equals() を実装していないクラスのオブジェクトに対して等価比較なアサーションをしたい場合、 org.hamcrest.BaseMatcher クラスを継承実装するという手があります。この方法を利用すると、

  • 等価比較だけでなく、値の大小比較などのきめ細かいアサーションが可能になる。
  • fail したときの mismatch メッセージに不一致となった内容や各種コンテキスト情報などを載せることができ、fail メッセージからの不具合の原因追求が容易になる。
  • assertThat() まわりの記述がすっきり・シンプルになる。

というメリットを得ることができます。ただ、Web API のようにエンドポイントごとに返却されるオブジェクトが異なる場合などはエンドポイントの数だけクラスが実装されていることもあり、そのクラスの数だけ BaseMatcher クラスを継承実装するというのは現実的ではありません (そもそもの BaseMatcher の実装コストがかかる、というデメリットもあります)。

汎用的な等価比較用 Matcher を目指す

そういうわけで、「equals() を実装する」わけでもなく「個別 に Matcher を用意する」わけでもない方法で解決するアプローチとして、汎用的に利用できる等価比較用の Matcher である IsEquivalentTo を作成しました。

この Matcher を利用することで、

  • equals() の実装を必要とせず
  • もちろん独自 Matcher も実装不要で
  • assertThat() まわりのコードも比較的シンプルに保ち
  • 等価比較したくないプロパティ / フィールドも明示できる

テストコードの記述が可能になります! (なる予定です!)

Matcher の汎用化、というわけで、個別に Matcher を実装したときと比べてきめ細かなアサーションは実現が難しくなりますが、等価比較できるところだけをこの汎用化 Matcher を利用して比較し、等価比較ではないアサーションは別途 assertThat() の羅列などで対処する、というアプローチもとれることでしょう。

技術的だったり細かい話

IsEquivalentTo の実装では、以下の工夫を盛り込みつつ、等価比較の汎用化を実現しています。

  • 再帰的なオブジェクトのトラバース ... オブジェクトを木構造なデータ構造と見立て、List / Map / 配列 / その他オブジェクト、の 4 種類ごとに等価比較の戦略を分けています。List / Map / 配列であれば、単純に保有しているオブジェクトに対して等価比較をするようにします。

  • オブジェクトの等価比較 ... Object#equals() をオーバーライド実装していないオブジェクトの場合、単純に equals() による等価比較をしてしまっては残念な結果になることは目に見えているので、以降に示す「プロパティの参照」「public フィールドの参照」を試すようにしています。一方で equals() をオーバーライド実装しているようであれば、その equals() を呼び出すようにします。

  • プロパティの参照 ... JavaBeans の規約に従って定義されているプロパティは、JavaBeans APIjava.beans.PropertyDescriptor を利用して、getter メソッド経由で値を読み出すようにしています。

  • public フィールドの参照 ... 最近だと、JavaBeans の規約にあえて従わず、public にフィールドを定義してクラスの外にフィールドをさらけ出すような実装を見かけることも、実際にそのような実装をすることも多くなってきました (MessagePack が要求するクラスがまさにそのようなフィールド構成ですね)。そのため、public なフィールドについてはリフレクション API を利用して、プロパティの場合と同じようにその内部の値を取得・参照するようにしています。

  • 例外的に扱いしたいプロパティ / フィールドなどの指定 ... テスト実行した日時の情報など、不定な値がオブジェクトに含まれる場合は、その値を無視して等価比較したくなるものです。そのようなケースを考慮して、 JSONPath 的な記法で等価比較したくない要素を指定できるようにしています。

  • 比較的親切な fail 時の mismatch メッセージ ... JUnit のテストケースを作成する上で重要なことの一つに、テストケースが fail したときに「何が原因で fail したのか?」ができる限り把握できるメッセージを出力することがあります。 IsEquivalentTo の実装では、オブジェクト階層を意識して、JSONPath 的な表現で、「オブジェクトのどこがおかしいのか?」が把握可能なメッセージ出力ができます。

会場参加者への逆質問

今回話題にした等価比較の問題、他の人はどういうアプローチをとっているのかなー? と気になったので、会場参加されている方々に 逆質問してみたところ、

  • equals() が実装されていることは確かに少ないけど、 toString() が実装されていることは結構あるので、文字列比較で済ませている。
  • 割り切ってテストはしない。

との回答をいただきました。不定な値がオブジェクトに紛れることがなければ、確かに toString() で比較できますね… 参考になります。

その他、感想などなど

  • build.xml と JSP はそろそろ滅んで欲しい!
  • Groovy / Grails に俄然興味が湧いてきた!
  • TokyoWebmining の新たな講師がゲットできそう!
  • 資格試験 (統計検定) の前日に発表予定を入れるのはもうやめよう…

最後に、会場提供の BizReach さん、そして主催の @seri_k さん、お疲れさまでした&ありがとうございました!!

9:21No comments

2013-09-03

第 4 回 #DSIRNLP データ構造と情報検索と言語処理勉強会でお話してきました。

3週間ぐらい前かつ発表前後は業務的に憤死しててもおかしくない時期ではありましたが、ありがたいことに主催者の @overlast さんから今回の発表オファーを頂いたしせっかくだから何か話そう、と心に決めて、いまの会社 でのお仕事でよく取り扱っているコサイン類似度や Jaccard 係数などのいわゆる「類似度計算」の時間/空間計算量的に効率的な処理を実現する方法についてお話してきました。

自分含めた発表内容の一覧は こちら を参照してください。

発表スライドはこちらです。

発表後に頂いた質問はこんな感じだったはず。寝不足ゆえの言語認識力がだいぶ低下した状態で受け答えしたので、質問/回答は超意訳になってます。悪しからず。

  • バスケット分析的な方法の計算量的な話

    • 購買ログなどからバスケット分析的な方法で類似度計算しようとすると、ユーザごとにログを集約しなければならないという追加処理が必要となるものの、計算量的にはあんまり問題になってない。
    • むしろ問題になるのはアイテムの数。アイテム数の2乗に応じて空間計算量が必要になってしまうため、アイテム数が多い場合にはこの方法は向かない。
  • レコメンド精度の面で、Jaccard 係数とかコサイン類似度ってどうなのよ?

    • ビジネス的には、類似度計算によって得られる精度よりもドメイン知識を使ったフィルタリングを良くする方が大事だと考えてる。
    • あと弊社の事情となってしまうが、精度のよい弊社独自の類似度計算のロジックは社外秘的な扱いとなっているためしゃべれない(ので、あえて精度の話は触れなかった)。

今回の発表にあたって b-bit Min-wise hashing を Java で実装してみましたが、精度・処理性能面の特性がまだ把握しきれていないので、もうちょっと追求してみたいですね。現状の実装は以下のとおりです。

https://gist.github.com/komiya-atsushi/6414548

あと、他の方の発表の感想と今回の反省です。

  • ダブル配列の実装テクニック的な話が熱かった。Java で trie を実装するときの参考になるのでとってもためになります。

  • 浮動小数点型数値の圧縮の話、昔のとあるお仕事で FPC を組み込もうかという検討をしたことがあって、そのときのことを思い出してちょっと感慨深いものがあった。整数圧縮の部分を改善する余地がまだあるとのことなので、maropu 先生の次回作に超期待してます!

  • 僕の発表、頂いた時間内でちゃんと発表しきれたのはよかったが、聴講者の反応を見てるとあまり興味ない or 説明が不足しているゆえに理解が追いつかない状態だったっぽい。魅力的な発表テーマ&必要十分な説明を心がけたいですね。

  • 忙しいときこそ没頭してしまう「艦これ」を断つ勇気を僕にください…

10:18No comments