12.31.2013

Getting Started with Erlang pt.2

Erlang をはじめよう その2

 

前回 - mog project: Getting Started with Erlang pt.1 の続き

CHAPTER 3: Atoms, Tuples, and Pattern Matching

 

アトム

アトムを利用したパターンマッチ、ブール値を示す特別なアトム

> hello.
> F = (fun(apple, Num) -> 100 * Num; (banana, Num) -> 200 * Num end).
> F(apple, 2).
> F(banana, 3).
> F(candy, 4).    % error
> 3<2.
> 3>2.
> 10 == 10.
> true and true.
> true or false.
> false xor false.
> not false.
ガード

when句、アンダースコアの利用

> Abs = (fun (Num) when Num =< 0 -> -Num; (Num) when Num > 0 -> Num end).
> Abs(-10).
> Abs(0).
> Abs(3).
> Abs = (fun (Num) when Num  -Num; (Num) when Num >= 0 -> Num end).  % error
> Abs2 = (fun
> (Num) when Num < 0 -> -Num;
> (0) -> 0;
> (Num) -> Num
> end).
> Abs2(-5).
> _.
> _ = 20.
> _.
> F = (fun(apple, Num) -> 100 * Num; (_, Num) -> 500 * Num end).
> F(apple, 3).
> F(candy, 10).
> G = (fun(apple, Num) -> 100 * Num; (_, _) -> 1 end).
> G(hello, world).
タプル

タプルの操作、パターンマッチでの利用

> {atom, 123, "string"}.
> T = {atom, 123, "string"}.
> element(2, T).
> setelement(2, T, 456).
> tuple_size(T).
> {A, B, C} = T.
> A.
> B.
> C.
> F = (fun ({apple, Num}) -> 100 * Num; ({banana, Num}) -> 200 * Num end).
> F({apple, 3}).

タプルを使った実装の隠蔽 (カプセル化)

-module(shop).
-export([buy/1]).

buy({Item, Num}) -> buy(Item, Num).

buy(apple, Num)  when Num >= 0 -> 100 * Num;
buy(banana, Num) when Num >= 0 -> 200 * Num;
buy(_, Num)      when Num >= 0 -> 500 * Num;
buy(_, _)                      -> 0.
> c(shop).
> shop:buy({apple, 3}).
> shop:buy({banana, 2}).
> shop:buy({candy, 1}).
> shop:buy({apple, -1}).
> shop:buy(apple, 3).    % error

CHAPTER 4: Logic and Recursion

 

case 構成要素 (case construct)

case は値を返す。case 内部でガードを行うことも可能。

> F = fun (Item, Num) ->
>   case Item of
>     apple -> 100 * Num;
>     banana -> 200 * Num
>   end
> end.
> F(apple, 3).
> G = fun (Item, Num) ->
>   X = case Item of
>     apple -> 100;
>     banana when Num >= 5 -> 198;
>     banana -> 200
>   end,
>   X * Num
> end.
> G(banana, 3).
> G(banana, 10).
if 構成要素 (if construct)
> F = fun (Item, Num) ->
> X = 100.
> if X >= 99 -> 'good' end.
> if X =< 99 -> 'good' end.
> F = fun(X) ->
>   if
>     X =< 99 -> io:format("X is less than ~w.~n", [100]);
>     true -> true
>   end
> end.
> F(10).
> F(100).
> A = 10.
> B = if A == 5 -> 100; true -> 20 end.
> B.
> BadFun = fun (X) ->
>   if
>     X < 0 -> Y = 1;
>     X >= 0 -> Z = 2
>   end,
>   Y + Z
> end.
再帰

カウントダウン

-module(count).
-export([countdown/1]).

countdown(From) when From > 0 ->
  io:format("~w!~n", [From]),
  countdown(From - 1);

countdown(From) ->
  io:format("blastoff!~n").
> c(count).
> count:countdown(10).

階乗

-module(fact).
-export([factorial/1]).

factorial(N) when N =< 1 -> 1;
factorial(N) -> N * factorial(N - 1).
> c(fact).
> fact:factorial(10).

階乗 (アキュムレーター付き)

-module(fact).
-export([factorial/1]).

factorial(N) -> factorial(1, N, 1).

factorial(Current, N, Result) when Current =< N ->
  factorial(Current + 1, N, Result * Current);
factorial(Current, N, Result) -> Result.
> c(fact).
> fact:factorial(10).

 

 

 

References

 

Related Posts

12.30.2013

Machine Learning: Logistic Regression vs SVMs

機械学習: ロジスティック回帰 vs サポートベクターマシン

Stanford大学の Andrew Ng 先生の Coursera での講義。
だいぶ遅れをとってしまったが、Week 7: Support Vector Machines を復習している。

 

ライブラリを使おう

世の中には、

といった優れたライブラリが既に存在するので、数値計算を自分で実装するのは避けよう。

 

アルゴリズムの選択

素性の数 (n) と学習データの数 (m) によって最適なアルゴリズムは変わってくる。

 

(mと比較して) n が大きい場合 [例: n  >= m, n = 10000, m = 10 .. 1000]

ロジスティック回帰、またはカーネルトリックなしの線形SVM

理由: 学習データが少ない状態で複雑なアルゴリズムを使うと過学習(overfit)が起こり、汎用性がなくなってしまうため。

n が小さく、m が中くらいの場合 [例: n = 1 .. 1000, m = 10 .. 10000]

ガウスカーネルを使ったSVM (非線形SVM)

n が小さく、m が大きい場合 [例: n = 1 .. 1000, m >= 50000)

新しい素性を付け加えた上で、ロジスティック回帰、またはカーネルトリックなしの線形SVM を使う

理由: 巨大な m に対して非線形SVMを行うと計算量が非常に多くなるので、コンピューティングリソースが不足するおそれがある。

 

その他、ニューラルネットワークはいずれの状況にも適用可能だが、学習処理の速度は遅くなる可能性が高い。

また、線形SVM、ガウスカーネル以外のSVMカーネルとして、以下のものが挙げられていた。

  • 多項式カーネル
  • 文字列カーネル
  • カイ二乗カーネル
  • ヒストグラムインターセクションカーネル

12.25.2013

Getting Started with Erlang pt.1

Erlang をはじめよう その1

 

本ブログ初のErlangエントリ。

Introducing Erlang - O'Reilly Media を読みながら、実行したコマンドを自身の復習のために書き連ねていく。

どのような結果になるか、考えながら手を動かしていくスタイル。
尚、以下に記載している内容は、書籍のサンプルコードとは異なります。

  • 凡例
    $     ===> OS のシェルプロンプト
    >     ===> Erlang Shell で実行
    %     ===> インラインコメント
    

CHAPTER 1: Getting Comfortable

Erlang Shell での基本的な操作。

起動と終了

erl コマンドを実行し、Erlang Shell を起動する。 (Windows の場合は werl コマンド)

$ erl
>     % Ctrl+G を押下
User switch command
 --> ?
 --> q
>     % Ctrl+C を押下
BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
       (v)ersion (k)ill (D)b-tables (d)istribution
a
> q().
> init:stop().
ディレクトリとヒストリの操作

Erlang Shell 組み込みコマンド。

1> help().
2> pwd().
3> ls().
4> h().
5> v(2).
6> results(3).
7> h().
8> v(2).    % エラー
8> v(-1).
9> e(2).
10> history(3).
11> h().
12> e(2).    % エラー
12> e(-1).
13> cd(..).    % エラー
13> cd("..").
14> cd("/tmp").
15> pwd().
数値の操作

どの処理でエラーが発生するか?

> 1+2.
> 10 - 100.
> 1+3.0.
> 100 * 10.
> 10.0 * 0.
> 100/33.
> 100 div 33.
> 100 rem 33.
> 100/0.
> -100.0/0.0.
> 0.0/0.0.
> 100 div -33.
> -100 div 33.
> 100 rem -33.
> -100 rem 33.
> -100 rem -33.
> 5 - 4 * (3 + 2).
> round(100/22).
> math:sin(math:pi()/2).
> math:sin(math:pi()).
> math:cos(0).
> math:pow(2, 10).
> math:pow(10, 333).
> 2#1111.
> -16#f0f0.
> 16#fffffffffffffffff.
> 36#a3Z.
> bnot 10.
> bnot -1.
> 5 band 15.
> -1 band -2.
> 5 bor 11.
> 5 bxor 11.
> 11 bsl 2.
> 11 bsr 2.
> 1 bsr 10.
> -1 bsr 10.
> 1 bsl 1000.
変数の操作

どの操作でエラーが発生するか?

> n=10.
> N=10.
> N=11.
> 10=N.
> 11=N.
> 25 = N * 2 + N div 2.
> N * 2 + N div 2 = 25.
> M=N+1.
> M=N+1.
> N+1=M.
> 11=M.
> M=11.
> b().
> f(M).
> b().
> M=N*3.
> N=11.
> f().
> N=M.
> N=11.

 

CHAPTER 2: Functions and Modules

引き続き Erlang Shell で実行。

関数の定義

今日はクリスマス。というわけで、ケーキの代金を求める Price 関数を作る。
ドル払い(端数は四捨五入)もできるようにしますよ。

> Price = fun(Num) -> trunc(348 * Num * 1.05) end.
> Yen_to_dollar = fun(Yen) -> round(Yen / 104.288) end.
> b().
> Price(3).
> Yen_to_dollar(Price(4)).
> Num.
> Yen.
> Price1 = Fun(Num) -> trunc(348 * Num * 1.05) end.
> price2 = fun(Num) -> trunc(348 * Num * 1.05) end.
> Price3 = fun(num) -> trunc(348 * num * 1.05) end.
> Price3(10).
モジュールの定義

ファイル(仮に prices.erl とする)に以下の内容を保存。

-module(prices).
-export([price/1, yen_to_dollar/1]).

price(Num) -> trunc(348 * Num * 1.05).
yen_to_dollar(Yen) -> round(Yen / 104.288).

Erlang Shell から、そのモジュールを利用できる。

> ls().
> prices:price(3).
> c(prices).
> ls().    % どのような拡張子のファイルが生成されるか?
> prices:price(3).
> prices:yen_to_dollar(10000).
ドキュメント(EDoc)の生成

ファイル(prices.erl)の内容を更新。

%% @author mogproject [http://mogproject.blogspot.com]
%% @doc Functions calculating price of cakes.
%% @reference REFERENCE HERE
%% @copyright 2013 by mogproject
%% @version 0.1

-module(prices).
-export([price/1, yen_to_dollar/1]).

%% @doc Calculates price of cakes.
%% You should specify how many cakes you want.

-spec(price(integer()) -> integer()).

price(Num) -> trunc(348 * Num * 1.05).

%% @doc Exchange yen to dollar.

-spec(yen_to_dollar(integer()) -> integer()).

yen_to_dollar(Yen) -> round(Yen / 104.288).

Erlang Shell で以下のコマンドを実行。

> edoc:files(["prices.erl"], [{dir, "doc"}]).

doc サブディレクトリ配下に各種HTMLファイルが作られるので、その内容をブラウザで確認しよう。

Screenshot 12 25 13 03 16

12.24.2013

Monitoring JMX in Zabbix

Zabbix: JMX監視について

 

バージョンによって手順に違いがあったり、公式ドキュメントでも日本語化されていない部分があったりしたので
導入のポイントをメモしておく。 

 

環境

監視サーバ
  • zabbix-server 2.2
  • Zabbix Java Gateway (後述) を同居

 

監視対象サーバ
  • RedHat Enterprise Linux または Cent OS (もちろんこれ以外でも動作する)
  • zabbix-agent
  • 適当な JVM アプリケーション
    • 適当な JMX ポートを決定し、監視サーバから接続可能にすること

 

監視対象サーバの設定

 

JMX ポートの起動

JVM の標準機能である JMX を有効にする。
起動スクリプトなどで JAVA_OPTION を指定すればよい。

設定例 (セキュリティ関連の項目は必要に応じて書き換えること)

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=12345
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false

 

疎通確認

監視サーバからの疎通確認には、cmdline-jmxclient を使うと便利だった。

実行例 (適当なディレクトリ配下で)

curl -O http://crawler.archive.org/cmdline-jmxclient/cmdline-jmxclient-0.10.4.jar
java -jar cmdline-jmxclient-0.10.4.jar - xxx.xxx.xxx.xxx:12345
java -jar cmdline-jmxclient-0.10.4.jar - xxx.xxx.xxx.xxx:12345 java.lang:type=Threading

Exception が発生せず、何らかの情報が表示されればひとまずOK。

 

補足

ネットワーク関連の問題が発生した場合、JVM の起動オプションで以下のように自分自身のIPアドレスを明記することで解決する場合がある。

監視対象サーバ自身のIPアドレスを書く

-Djava.rmi.server.hostname=xxx.xxx.xxx.xxx

 

監視サーバの設定

 

Zabbix Java Gateway のインストール

Zabbix 2.2 の場合(であっても)、zabbix-server を入れただけでは JMX の監視はできない。

ソースをダウンロードしてビルドする方法もあるが、パッケージが公開されているのでそのままインストールしたほうが簡単だ。

実行例 (サービス登録および起動も実施)

# rpm -Uv http://repo.zabbix.com/zabbix/2.2/rhel/6/x86_64/zabbix-java-gateway-2.2.0-1.el6.x86_64.rpm
# chkconfig zabbix-java-gateway on
# service zabbix-java-gateway start

設定ファイルの編集
  • /etc/zabbix/zabbix_server.conf の修正 (一部抜粋)
    Timeout=30
    JavaGateway=127.0.0.1
    JavaGatewayPort=10052
    StartJavaPollers=5

    Java Gateway はデフォルトでは10052ポートで起動する。
    Timeout の修正(デフォルト5秒) については、デメリットもあるので問題が起きた場合にのみ書き換えたほうがよいかもしれない。

    参考: zabbix_server.confのTimeoutについて | ZABBIX-JP

設定ファイルを保存したら、zabbix-server から再読み込み (または再起動)。

監視設定

ここから先は Zabbix の管理画面(GUI)での操作となる。

ホスト設定

Configuration -> Hosts -> 監視対象サーバ を選択。
JMX interfaces の部分で Add をクリックし、IPアドレスとJMXポートを指定して Save。

テンプレート・アイテム設定

ひとまずは標準の Template JMX Generic を使ってみるのを勧める。

Configuration -> Templates -> Template JMX Generic を選択。
Group または Host の追加を行った後、Save。

ダッシュボード画面で ホストにひもづく JMX のアイコンが緑色になればOKだ。

References

 

12.13.2013

Installing Docker on CentOS 6.5 (with Vagrant and VirtualBox)

Vagrant+VirtualBox 環境の CentOS 6.5 に Docker をインストールする

 

こちらのブログポストの内容を実践してみた。

なぜ Docker か

Docker とは、Linux のホストOS上で複数の仮想 Linux OS(コンテナ)を実行するためのソフトウェア。

VMWare のようなハイパーバイザー型の仮想OSと異なり、ハードウェア層やカーネルの大部分が共通して使われるため、パフォーマンスのオーバーヘッドが少ない。

LXC (Linux Containers) と aufs (Advanced multi layered unification filesystem) という要素技術が使われており、
Docker自体は Go言語で記述されている。

Docker を使うモチベーションを挙げれば以下のような感じだ。

  • とにかく起動が速い
    aufs の恩恵により、差分ベースでファイルシステムが構築されていく。
    一瞬でOSが立ち上がる様は感動的ですらある。

    Immutable Infrastructure (出典: Trash Your Servers and Burn Your Code: Immutable Infrastructure and Disposable Components - Chad Fowler) の前に立ちはだかっていた壁の一つが音もなく崩れ去った瞬間を目の当たりにしている。

    仮想化技術によって、インフラの「作って捨てて」を非常に短いサイクルでできるようになった結果、
    我々はこれまで混然としていた Immutable (OS, ミドルウェアのバージョン、コンフィギュレーションなど) と Mutable (各種ログ、エラー通知、リソース推移など) の意味的な区別に専念できるようになったのだ。
  • 開発PCのローカル環境 -> CI環境 -> ステージング環境 -> プロダクション環境と、 同一性が保証されたインフラをハードウェア構成に依存せずに作成することができ、 しかもその内容をコードとして管理できる。 (Infrastructure as Code)

    Docker at eBay // Speaker Deck
    (プロダクション環境での利用実績はまだ少ないようだが)
  • 従って、たとえばCI環境で使えば、DB の状態に依存するテストでも並列かつ迅速に実行できる。

 

目的

Mac OS (Mavericks) 上で Vagrant を実行し、VirtualBox 上に CentOS 6.5 インスタンスを作成。
そこに Docker をインストールし、さらにその上に複数のゲストコンテナを実行できるようにする。

事前準備

  • Vagrant インストール
  • VirtualBox インストール

ホストOSのセットアップ

とりあえず今日は Mac 上で Vagrant を実行し、VirtualBox 内のホストOS(いわゆる母艦)に Docker をインストールするまで。

  • VirtualBox Guest Additions を更新するため、Vagrant プラグイン vagrant-vbguest をインストール
  • opscode のテンプレートを利用して vagrant init
  • Vagrantfile を編集し、後処理として epel から docker パッケージを取得しインストール、起動
  • vagrant up
  • Docker 上で Hello World!

 

 

References

12.12.2013

How to Format Line Numbers in Emacs

Emacs: 行番号表示のフォーマット指定

忘れがちなのでメモ。

Emacs における行番号表示は、init.el で global-linum-mode を指定すれば実現できるが、
以下のように linum-format を指定すればそのフォーマットをカスタマイズすることも可能だ。

(require 'linum)
(global-linum-mode t)
(setq linum-format "%4d ")

フォーマット文字列は C のアレと同じで、上記の例であれば
4桁分の領域に行番号の数字が表示され、その後に一個スペースが入る。

How to Clone a Large Git Repocitory

巨大な Git リポジトリを少しずつクローンする方法

ファイルサイズの非常に大きな Git リポジトリの場合、git clone を行った時に メモリが不足しエラーとなってしまうケースがある。

$ git clone git://xxxxxxxx.xxx:awesome-project.git
Cloning into 'awesome-project'...
remote: Counting objects: 9999, done.
remote: warning: suboptimal pack - out of memory
remote: fatal: Out of memory, malloc failed
error: git upload-pack: git-pack-objects died with error.
fatal: git upload-pack: aborting due to possible repository corruption on the remote side.
remote: aborting due to possible repository corruption on the remote side.
fatal: early EOF
fatal: index-pack failed

depth を指定して shallow copy を行うことで解決できる場合がある。

具体的な手順は、以下のブログが参考になった。

How to Solve Vagrant+CentOS+VirtualBox Mount Error

Vagrant+CentOS+VirtualBox: ゲストOS起動時のマウントエラーの調査

 

事象

Vagrant で CentOS 6 の VirtualBox 用イメージを立ち上げようとしたところ、以下のようなエラーが出てしまった。

$ vagrant up <HOSTNAME>

(略)

[HOSTNAME] Mounting shared folders...
[HOSTNAME] -- /vagrant
Failed to mount folders in Linux guest. This is usually beacuse
the "vboxsf" file system is not available. Please verify that
the guest additions are properly installed in the guest and
can work properly. The command attempted was:

mount -t vboxsf -o uid=`id -u xxxxxxxx`,gid=`getent group xxxxxxxx | cut -d: -f3` /vagrant /vagrant
mount -t vboxsf -o uid=`id -u xxxxxxxx`,gid=`id -g xxxxxxxx` /vagrant /vagrant

このメッセージだけでは、VirtualBox Guest Additions (以下、Guest Additions) の機能である共有フォルダのマウントに失敗していることくらいしか分からない。

ちなみに Guest Additions とは、簡単に言えば VirtualBox ゲストの管理に特化した便利ツールだ。

これを利用しないなら無視しても構わないのだろうが、やっぱり気になるので調べてみる。

 

調査

vagrant status コマンドを実行して、OS自体は起動していることは確認できた。

$ vagrant status

Current machine states:

HOSTNAME                  running (virtualbox)

SSH 接続をしてみよう。

$ vagrant ssh <HOSTNAME>

以下はゲストOS上のプロンプト。
Guest Additions の状態を確認すると、停止状態であることが分かる。

$ service vboxadd status
The VirtualBox Additions are not currently running.

Guest Additions のインストール自体が失敗している可能性があると考え、ログを確認する。

$ cat /var/log/vboxadd-install.log
/tmp/vbox.0/Makefile.include.header:97: *** Error: unable to find the sources of your current Linux kernel. Specify KERN_DIR=<directory> and run Make again.  中止.
Creating user for the Guest Additions.
Creating udev rule for the Guest Additions kernel module.

やはりここに答えがあった。
カーネルのソース (kernel-devel) が不足していたために、Guest Additions のビルドが失敗していたのだった。

対応

 

誤った対応

パッケージが足りないなら、yum でインストールすればよいと安直に

$ sudo yum install kernel-devel -y

と実行するのはよくない。

上記のコマンドでは (基本的に) 最新の kernel-devel がダウンロードされるため、
実際のカーネルバージョンと異なるものがインストールされてしまう可能性があるためだ。

カーネルバージョンと kernel-devel が食い違った状態で Guest Additions のセットアップをすると、やはりビルドは失敗となる。

$ sudo /etc/init.d/vboxadd setup
Removing existing VirtualBox non-DKMS kernel modules       [  OK  ]
Building the VirtualBox Guest Additions kernel modules
The headers for the current running kernel were not found. If the following
module compilation fails then this could be the reason.
The missing package can be probably installed with
yum install kernel-devel-2.6.32-358.el6.x86_64

Building the main Guest Additions module                   [失敗]
(Look at /var/log/vboxadd-install.log to find out what went wrong)
Doing non-kernel setup of the Guest Additions              [  OK  ]

それぞれのバージョンは以下のようなコマンドで確認できる。

$ uname -r
2.6.32-358.el6.x86_64
$ rpm -qa |grep kernel-devel
kernel-devel-2.6.32-431.el6.x86_64

アンインストール。

$ sudo yum remove kernel-devel

 

 

正しい対応

では、適切なバージョンの kernel-devel をインストールするにはどうしたらよいか。

残念ながら、このまま yum でバージョンを指定してもうまくいかない。

$ sudo yum install kernel-devel-$(uname -r) -y
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftp.riken.jp
 * extras: ftp.riken.jp
 * updates: ftp.riken.jp
Setting up Install Process
No package kernel-devel-2.6.32-358.el6.x86_64 available.
Error: Nothing to do

古いバージョンのパッケージは CentOS-Vault リポジトリに置かれている。
以下いずれかの方法で対応が可能だ。

  • /etc/yum.repos.d/CentOS-Vault.repo ファイルを編集
    適切なOSバージョンの記載を追加し、「enabled=0」 を「enabled=1」へ書き換える
  • URLを指定して直接ダウンロード
    $ sudo yum install http://vault.centos.org/6.4/os/x86_64/Packages/kernel-devel-$(uname -r).rpm

インストールを終えたらゲストOS上で、Guest Additions のセットアップを再度実行。

$ sudo /etc/init.d/vboxadd setup
Removing existing VirtualBox non-DKMS kernel modules       [  OK  ]
Building the VirtualBox Guest Additions kernel modules
Building the main Guest Additions module                   [  OK  ]
Building the shared folder support module                  [  OK  ]
Building the OpenGL support module                         [  OK  ]
Doing non-kernel setup of the Guest Additions              [  OK  ]
Starting the VirtualBox Guest Additions                    [  OK  ]

うまくいった。

$ service vboxadd status
The VirtualBox Additions are currently running.

目的は達成できたので、一度ゲストOSから抜け、Vagrant から再起動する。

$ vagrant reload <HOSTNAME>

マウントエラーは晴れて解消された。

 

 

References