Hadoop Conference Japan 2011に参加した
Hadoop Conference Japan 2011 - Eventbriteに参加してきました。
場所は豊洲にあるNTT DATAの本社ビルの36階セミナールームでした。さすがの絶好の景色ですね。
詳細な内容は登壇者の方や他の方のブログにもまとまってるので、簡単に感想だけ。
Hadoop on クラウド / Amazon Elastic MapReduceの真価
スライド: Amazon Elastic MapReduceの紹介(英語)
Amazon Elastic MapReduce(Hadoopクラスター Amazon EMR) | アマゾン ウェブ サービス(AWS 日本語)の紹介です。
- 簡単に使えそうな感じ
- Hadoopで処理するようなジョブを回した場合、いくら位かかるのか怖いですね
- 一度くらい試してみたい
- Hadoop上でRを実行するRHIPEも使えるらしい
MapReduceによる大規模データを利用した機械学習
Hadoop上で機械学習を使うお話。
- 機械学習のタスクの多くは、明示的な並列性があるので、MapReduceの計算パラダイムと割と相性がいいアルゴリズムが多い。
- Apache Mahout: Scalable machine learning and data mining で活発に機械学習タスクが実装されている
- 計算時間はマシン数に応じて線形
- ただし実装の質はアルゴリズムごとに異なる
- 最適化問題の並列化方法はIterative Parameter Mixture使っとけ
- MapReduceが不得意なshort term queryみたいなもので使われるDremelの紹介
モバゲーの大規模データマイニング基盤におけるHadoop活用
スライド: 『モバゲーの大規模データマイニング基盤におけるHadoop活用』-Hadoop Conference Japan 2011- #hcj...
モバゲーでのデータ分析のためのHadoopプラットフォームと行動データの分析の話。
- すでに社内でデータを活用するためのHadoopプラットフォームがしっかり整っている印象
- ログ形式の統一等社内の他の部署でも結構データ分析への理解があるんですね
- ユーザの感情に着目してマイニング、即座にサービスに反映させる
Enterprise Batch Processing Framework for Hadoop
基幹業務向けのHadoopフレームワークの紹介。
Hiveを用いたAmebaサービスのログ解析共通基盤
AmebaでのHadoopやHiveを使ったログ解析基板の話。
- Hiveを使ってみての紹介
- 社内ツール的なものも結構あったようなので詳細はちょっとわからず
- 現状を聞く限り、現在ログ解析の基板を作っている最中という感じかな?
ライトニングトーク
- 藤川さんの「Sneak Preview of "Hapyrus" ~ Hadoopアプリ開発&共有サービス on the CLOUD」がちょっと気になった。
- Hapyrus
- Hadoop版のAppStoreみたいなの作ります、という話。
- Hadoopに限らず、こういうコードを取引できる場ができるというのは面白いかも
マルチユーザーでHadoop環境を利用するためのポイント
Hadoopを複数人で使う場合のよくある問題とそれを回避する方法。
- Hadoopクラスタに勝手に入って触られるのは困るため、基本的にはゲートウェイ経由以外入れない
- 他の人のデータを勝手に見ることができるのも問題
- 特定のジョブが占有してしまうのも問題
Hadoopと分析統計ソフトKNIMEを用いた効率的データ活用
Hadoopを使う人が技術者だけでなく、分析者も使うため、GUIツールと連携させた話。
- 社内でHadoopを扱える技術者だけでなく、分析者も直にデータを見ることが出来るようにする必要がある
- KNIME | Konstanz Information MinerというGUIツールがあるので、それとHadoopを連携させる
- HadoopをMapReduceを知らない人や非技術者にも使えるようにしよう、という話は結構あるけど、やっぱり難しそうですよね
総括
Hadoopといっても、Hadoop上でのアルゴリズムの話から、Hadoopを使ったログ解析プラットフォームやHadoop周辺ライブラリなどの話、Hadoopチューニングの話などかなり多領域の話が聞けて、非常に面白かったですね。
ただ、Hadoopを使う上でこれだけ幅広い知識が求められるというのは、実際に活用するのは結構難しい、という印象ですね。
MBA
去年は全然ブログ書かなかったので、今年はちゃんと書きますかね。
vimプラグインの管理をpathogen.vimにした
vimプラグインの管理を最近はやりのpathogen.vimを使う方法に変更しました。
今までは、vimanaを使ってみたりいろいろ試してはみたのですが、なかなかしっくり来る方法が見つからなかったのですが、pathogen.vimを使ってみたら、かなり使い心地が良かったため、完全に移行しました。
pathogen.vimとはなんぞや
まず、pathogen.vimはvimプラグインの読み込みパスを変更するプラグインです。
従来は .vim/ 以下のpluginとかautoloadとかのディレクトリを読み込むようになっているところを、pathogen.vimをいれると .vim/bundle/<プラグイン名>/以下の各ディレクトリも .vim/ 直下と同じように読み込むようになってくれます。
これにより、bundle/ 以下にプラグインごとに別のディレクトリを切って管理をすることができるようになります。
従来のvimプラグインの管理の欠点として、すべてのプラグインを同じディレクトリに放り込まないといけなかったため、どのファイルがどのライブラリのためのものかわからなくなったり、プラグインごとにディレクトリを切らざるを得ないGitなどのレポジトリで管理されているライブラリとの相性が非常に悪かったことなどがあります。
このpathogen.vimを使うとそのあたりの欠点がすっきり解消されるため、vimプラグイン管理の見通しが非常によくなります。
pathogen.vim の導入
まずはpathogen.vimの導入です。
pathogen.vim はgithubで管理されているので、githubから落としてきます。
https://github.com/tpope/vim-pathogen
.vim/autoload/ 以下にpathogen.vimを一枚おくだけなのですが、個人的には今後のアップデートや他のプラグインとの整合性も考えて、.vim/bundle/ 以下において、.vim/autoload/ からシンボリックリンクを貼るのがいいかと思います。
また、後述しますが、.vim/ 自体もgit管理している場合は、gitのsubmoduleとして管理するのが楽かと思います。
$ mkdir .vim/bundle $ git submodule add git://github.com/tpope/vim-pathogen.git .vim/bundle/vim-pathogen $ ln -s .vim/bundle/vim-pathogen/autoload/pathogen.vim .vim/autoload/
あとは、.vimrcにpathogenを読み込む設定を書けばOKです。
$ vi .vimrc
call pathogen#runtime_append_all_bundles()
git管理のプラグインの移行
せっかくなので簡単にプラグインの移行方法も書いておきます。
まずは、gitレポジトリで管理されているプラグインです。
これは pathogen.vim を使うと導入が劇的に簡単になります。
gitには他のgitレポジトリをsubmoduleとして取り込む機能があります。
そのため、.vim/ 自体をgit管理している場合は、そのプラグインのgitレポジトリをsubmoduleとして取り込めばOK。
$ git submodule add git://github.com/msanders/snipmate.vim.git .vim/bundle/snipmate.vim
vimball プラグインの移行
vimballの場合はそのまま入れると.vim/直下に解凍されてしまうので、インストールパスを変えることでとりあえず対応してます。
$ mkdir .vim/bundle/Align/ $ vi Align.vba :let g:vimball_home = "~/.vim/bundle/Align/" :source %
tarやzipなどで配布されているプラグインの移行
これはそのまま、ディレクトリを掘って解凍すればOKですね。
$ mkdir .vim/bundle/project $ cd .vim/bundle/project $ tar zxvf ~/project-1.4.1.tar.gz
単体 .vim ファイルで配布されているプラグインの移行
個人的にどうするか迷ったのがこの単体.vimファイル1枚で管理されているプラグイン。
まあ、これくらい.vim直下に入れて管理してしまっても全然問題ないと思います。
ただ、なんとなく美しくないので、他と同じようにbundle以下にディレクトリを掘って同じように管理するようにしました。
$ mkdir -p ~/.vim/bundle/yanktmp/plugin $ mv .yanktmp ~/.vim/bundle/yanktmp/plugin/
最終的にこんな感じになりました。
https://github.com/mkataigi/dotfiles-vim
Ubuntuサーバにgit/gitosis/gitwebを入れてみる
Ubuntuサーバにgitを入れてみました。
あわせてgitosisとgitwebも入れてみました。
gitはもう言わずもがなな分散バージョン管理システムですね。
gitosisはgitのレポジトリの権限周りを管理するツールで、gitwebはgitレポジトリのウェブベースの簡易フロントエンドです。
gitを入れる
まずはgitです。
これは簡単にできます。
基本的にはaptでインストールすればOK。
普通に使う分には、特にこれといった設定も必要ありません。
server $ sudo apt-get install git-core
gitが入ったので、試しにサンプルのレポジトリを作ってみます。
server $ mkdir sample.git server $ cd sample.git server $ git init --bare --shared=true
local側で編集して、server側に反映させてみます。
空のレポジトリはクローンできないため、local側で編集したものを、server側にpushします。
local $ mkdir sample.git local $ cd sample.git local $ git init local $ touch test.txt local $ git remote add origin ssh://server.co.jp/git/sample.git local $ git add test.txt local $ git commit -m "init" local $ git push origin master
これでレポジトリのクローンが出来ます。
gitosisを入れる
続いてはgitosisです。
gitosisは、このgitosis自体もgitのひとつのレポジトリとして管理されていて、このレポジトリ内の設定ファイルを書き換えてコミットすることによって、git全体の設定を変える、というものです。
まあ、これだけだとよくわからないので、実際に見るのがいいですね。
aptにあるので、インストール自体はすぐです。
server $ sudo apt-get install gitosis
インストールすると、gitosisユーザとそのホームディレクトリとして/srv/gitosisができます。
gitosis-adminというレポジトリができているので、それをクローンしてきて、設定を変更します。
server $ git clone gitosis@localhost:gitosis-admin.git
server $ cd gitosis-admin.git
gitosis-adminレポジトリをクローンしてくると、keydirとgitosis.confが入っています。
レポジトリにコミットする権限を与えるには、権限を与えたい人の鍵をkeydir以下に配置して、その設定をgitosis.confに書くことで行います。
例えば、sampleレポジトリに対してlocalマシンからmkataigi権限でコミットできるようにするには以下のようにします。
server $ cp ~/local_public_key keydir/mkataigi@local.pub server $ vi gitosis.conf [group gitosis-admin] writable = gitosis-admin sample members = mkataigi@server mkataigi@local server $ git add . server $ git commit -m 'add configuration for mkataigi@local' server $ git push
これで、sampleディレクトリをlocalマシンからコミットできるようになります。
local $ cd ~/sample.git local $ git remote add origin gitosis@server:sample.git local $ git push origin master
gitwebを入れる
続いてはgitwebです。
これはwebベースのgitレポジトリの簡易フロントエンドです。
特にたいしたことが出来るわけではないのですが、ちょっと確認するには便利です。
aptの場合はこれも入っているので、インストールはすぐに終わります。
$ sudo apt-get install gitweb
gitwebの設定ファイルがあるので、レポジトリの配置にあわせて設定します。
ウェブベースなので、CSSなどの読み込みのパスを修正します。
$ sudo vi /etc/gitweb.conf $projectroot = "/srv/gitosis/repositories"; $stylesheet = "/gitweb/gitweb.css"; $logo = "/gitweb/git-logo.png"; $favicon = "/gitweb/git-favicon.png";
あわせてapache側も設定します。
$ cd /etc/apache2/sites-available $ sudo vi gitweb Alias /git /usr/lib/cgi-bin Alias /gitweb /usr/share/gitweb <Directory /usr/lib/cgi-bin> Options ExecCGI AddHandler cgi-script .cgi AllowOverride None DirectoryIndex gitweb.cgi Order allow,deny allow from all </Directory> $ cd ../sites-enabled $ sudo ln -s ../sites-available/gitweb 001-gitweb $ sudo service apache2 restart
これで http://server/cgi-bin/gitweb.cgi で見えます。
gitosisのレポジトリについては、そのままではパーミッションがありません。
しょうがないので変更してしまいます。
$ chmod 755 /srv/git/repositories/*.git
このあたりは、いまいちなので、うまい回避策調査中です。
Ubuntu Server に Redmine をインストールしてみる
Redmineとは、Ruby on Railsで書かれたBTSです。Bugzillaとかに変わって最近人気なようなので、試しにUbuntu Serverにインストールしてみました。
基本的には公式に書いてある通りやれば、たいして難しい事でもないのですが、いくつか小ハマリがあったので、残しておきます。
Redmine の構築
まずは依存するいくつかのパッケージを apt でインストール。ベースのRubyを入れます。DBはMySQLで構築する予定なので、MySQL関連も一緒に入れます。
$ sudo apt-get install ruby rubygems mysql-server mysql-client
Redmine は Ruby on Rails 依存なので、その関係の gem インストール。
$ sudo gem install rails mysql
ベース部分のインストールができたら、次は本体を入れます。レポジトリから落としてきて配置するだけです。
$ svn checkout http://redmine.rubyforge.org/svn/trunk/ redmine $ sudo mv redmine /var/lib/rails/ $ sudo chown root:root /var/lib/rails/redmine $ cd /var/lib/rails/redmine
続いては DB の設定。
$ mysql -u root -p SQL> GRANT ALL PRIVILEGES ON *.* TO redmine@localhost IDENTIFIED BY 'redminepassword' WITH GRANT OPTION; SQL> create database redmine SQL> \q
Redmine 本体側の設定もします。config/database.yml で接続する DB の設定をします。複数設定を書いて置いて、切り替えて使うような使い方もできるみたい。rake を使って DB 周りの初期化をします。
$ config/database.yml production: adapter: mysql database: redmine username: redmine password: redminepassword host: localhost encoding: utf8 $ sudo rake config/initializers/session_store.rb $ sudo rake db:migrate RAILS_ENV=production $ sudo rake redmine:load_default_data RAILS_ENV=production
一応 config/email.yml で e-mail の設定も。
$ sudo vi config/email.yml
production:
delivery_method: :smtp
smtp_settings:
address: localhost
port: 25
domain: mkataigi.com
基本的にはこれだけで大丈夫なハズ。Rails の組み込みのサーバを起動させればもう見えます。
$ sudo script/server -e production
http://localhost:3000/ でアクセスできます。
Passenger 上で動かす
公式に Passenger で動かす方法も書いてあるのでやってみます。Passenger とは、apache モジュールで Rails をデプロイするものです。
まずは Passenger を入れます。
$ sudo gem install passenger
どうやらパスも通しておかないといけないようなので、設定します。
$ vi ~/.bashrc export APXS2=/usr/local/apache2/bin/apxs export PATH=/usr/local/apache2/bin:$PATH
次は passenger-install-apache2-module という、インストールスクリプトを実行するようなのですが、これが見つかりません。locate で探すとちょっと予想外のところに入っていたので、フルパス指定で実行。
$ sudo /var/lib/gems/1.8/bin/passenger-install-apache2-module
実行するといくつか足りてないライブラリを指定されるので、表示されるとおりに実行してインストール。一通りインストールして、再度上記スクリプトを実行したところ、インストールできたみたい。
あとは、apache 側で設定します。
$ sudo vi /etc/apache2/mods-available/ruby_passenger.load LoadModule passenger_module /var/lib/gems/1.8/gems/passenger-2.2.11/ext/apache2/mod_passenger.so $ sudo vi /etc/apache2/mods-available/ruby_passenger.conf PassengerRoot /var/lib/gems/1.8/gems/passenger-2.2.11 PassengerRuby /usr/bin/ruby1.8 $ cd /etc/apache2/mods-enabled $ sudo ln -s ../mods-available/ruby_passenger.load . $ sudo ln -s ../mods-available/ruby_passenger.conf . $ sudo vi /etc/apache2/sites-available/redmine RailsBaseURI /redmine DocumentRoot /var/www $ cd ../sites-enabled/ $ sudo ln -s ../sites-available/redmine 001-redmine
Redmine を apache で見える場所にリンクを貼ります。
$ cd /var/www $ sudo ln -s /var/lib/rails/redmine/public redmine
Rails って、public の部分にリンク貼ればいいんですね。
あとは apache を再起動すれば OK。
$ sudo service apache2 restart
http://localhost/redmine/ で確認します。ポート指定いらなくなった。
ちゃんと動いてる!ヨカッタヨカッタ。
グレイコード
先日某勉強会で出たグレイコードについて、一応概念的には知っていたのですが、実装とかをよく知らなかったため調査。
グレイコードについてはWikipediaに結構詳しく書いてあります。
グレイコード - Wikipedia
このグレイコード、何がいいかというと、数字的な近さがそのままグレイコード表現でも近くなることです。
普通の2進数の場合だと、例えば、
7 => 0111 8 => 1000
となって、数字上ではとなりの数字なのに、2進数では4ビットも違う表現になってしまいます。
しかし、グレイコードの場合は、
7 => 0100 8 => 1100
のようになって、数字上のとなりの数字が、グレイコード表現でも1ビット違いで表現されます。
このグレイコードの構成方法ですが、いろいろとあるのですが、ひとつの簡単な方法としては「反射2進グレイコード」というものがあります。
これは前半部分のグレイコードを反転して、先頭に0,1をつけることによってグレイコードの続きを作っていく方法です。
説明だとよくわからないので、実例で。
0 0 00 1 反転 1 0,1付与 01 --- ===> --- ======> ---- 1 11 0 10
この数字 => グレイコード変換は単純な2進演算で実装できます。
この変換を実装するとこんな感じ。
#!/usr/bin/perl use strict; use warnings; for (0 .. 15) { my $gray = $_ ^ ($_ >> 1); print sprintf("%2d => %04b\n", $_, $gray); }
結果
$ ./graycode.pl 0 => 0000 1 => 0001 2 => 0011 3 => 0010 4 => 0110 5 => 0111 6 => 0101 7 => 0100 8 => 1100 9 => 1101 10 => 1111 11 => 1110 12 => 1010 13 => 1011 14 => 1001 15 => 1000
こんな感じで数字からグレイコードへの変換は簡単にできます。
ただ、逆のグレイコードから数字への変換はちょっと難しいようです。
ここら辺は後でもうちょっと詳しく調ベる。
MacPortsのソフトウェアを一括でインストールするスクリプト書いた
先日、mac portsのソフトウェアの依存関係がどうにもおかしくなってしまっていたので、一念発起してまっさらにして入れなおしました。
アンインストールする方は結構簡単にいくんですが、アンインストールした物を再度インストールしなおすのが大変。
mac portsではローカルでコンパイルしてるらしいので、一個一個が結構時間かかるんですね。
どうにも面倒になってきたので、一括でインストールするスクリプト書きました。
とりあえず一回動けばいいので、エラー処理もテストもろくにしてないです。
自分で動かしたときにはうまくいきました。
一応依存関係には配慮して、自動でインストール順を決めるようにはしています。
ただ、ガッツリmac portsの出力依存なので、バージョン変わると動かないかも。
使うときには、インストールしたいportのソフトをvariant付きでひとつのファイルにズラズラ書き出して、それを引数に与えてスクリプトを実行すればOK。
$ port version Version: 1.8.2 $ cat install_list.txt gcc43 perl5 +perl5_10 #sqlite3 $ sudo ./port_install.pl install_list.txt
なかでport installを回しているだけなので、相当時間がかかるので、夜中に実行して、朝起きたら終わってる、位の感覚で実行するといいかも。
以下スクリプト本体。
#!/usr/bin/perl use strict; use warnings; use IO::File; if (scalar(@ARGV) < 1) { exit(1); } my $filename = $ARGV[0]; my $file = IO::File->new($filename, 'r'); my @not_install = (); my %variants = (); while (my $line = $file->getline) { chomp $line; if ($line ne "" and $line !~ /^\s*#/) { my ($cmd, @variant) = split(/\s+/, $line); $variants{$cmd} = \@variant; push @not_install, $cmd; } } my %dependencies = (); for my $cmd (@not_install) { my ($name, @deps); my $out = `port deps $cmd @{$variants{$cmd}}`; for my $l (split(/\n/, $out)) { if ($l =~ /Full Name:\s([^ ]*)\s/) { $name = $1; } elsif ($l =~ /has no Build Dependencies/) { } elsif ($l =~ /Build Dependencies:\s+(.*)$/) { foreach my $dline (split(/,\s/, $1)) { if ($dline ne "" and $dline ne ",") { chomp $dline; push @deps, $dline; } } } elsif ($l =~ /Library Dependencies:\s+(.*)$/) { foreach my $dline (split(/,\s/, $1)) { chomp $dline; if ($dline ne "" and $dline ne ",") { push @deps, $dline; } } } } $dependencies{$name} = \@deps; } my @installed = (); while (scalar @not_install) { my $cmd = shift @not_install; my $dep_flag = 0; for my $dep (@{$dependencies{$cmd}}) { for my $not_install_cmd (@not_install) { if ($dep eq $not_install_cmd) { $dep_flag= 1; last; } } last if $dep_flag; } if ($dep_flag) { push @not_install, $cmd; } else { push @installed, $cmd; } } my @install_ok = (); my @install_ng = (); for my $cmd (@installed) { eval { system("port", "install", $cmd, @{$variants{$cmd}}); }; if ($@) { push @install_ng, "$cmd @{$variants{$cmd}}"; eval { system("port", "clean", $cmd); }; } else { push @install_ok, "$cmd @{$variants{$cmd}}"; } } print "install OK\n" . join("\n", @install_ok) . "\n\n"; print "install NG\n" . join("\n", @install_ng) . "\n\n";