2013年12月11日水曜日

【PostgreSQL】PL/Pythonで機械学習


PostgreSQL Advent Calendar 2013 12/11 です。

DBに格納したデータに対して機械学習のアルゴリズムを適用したくなったとします。
DBからデータを出力して他のプログラム言語で処理してもいいのですが、PostgreSQLで処理が完結した方が便利なこともあるでしょう。

しかし、PostgreSQLで処理するために機械学習のアルゴリズムを一から自分で実装するのは大変です。

PL/Pythonを使えば、pythonで書かれたライブラリを利用して手軽に機械学習を行うことができます。
また、pythonの機械学習ライブラリはC言語で書かれていることが多いので、速度面でも悪くないです。

インストール

PL/Python

PostgreSQLをソースコードからインストールしている場合は、configureのオプションに--with-pythonをつけてビルドします。
今回はpython2系を使うので、ビルド時にpython2系にパスが通っているか、PYTHON環境変数にpythonのパスを指定するかして下さい。

OSのパッケージ管理でインストールしている場合は、apt-get install postgresql-plpython-9.xなどを試してください。

その後、CREATE EXTENSIONすればPL/Pythonが使えるようになります。
CREATE EXTENSION plpython2u;

scipy

pythonのscipyライブラリをインストールします。
pip install scipy
上記ですんなりインストールできればいいですが、失敗した場合は結構苦労するかもしれません。

実装

k-means法で2次元ベクトルのクラスタリングをやってみます。
scipyの使い方は下記を参考にして下さい。

K-means clustering and vector quantization (scipy.cluster.vq)

kmeans関数の作成

複数のベクトル(x, y)から、xとyそれぞれを配列にして渡し、
各ベクトルがどのクラスタに属すかを配列で取得する関数を作成します。

CREATE FUNCTION kmeans(x float[], y float[]) RETURNS int[] AS $$
 from numpy import array
 from scipy.cluster.vq import vq, kmeans, whiten

 features = array(zip(x, y))
 whitened = whiten(features)
 book = array((whitened[0], whitened[2]))
 codebook, distortion = kmeans(whitened, book)
 code, dist = vq(whitened, codebook)

 return list(code)
$$ LANGUAGE plpython2u;

SELECT kmeans(
 array[1.9,1.5,0.8,0.4,0.1,0.2,2.0,0.3,1.0],
 array[2.3,2.5,0.6,1.8,0.1,1.8,0.5,1.5,1.0])

/*
       kmeans        
---------------------
 {0,0,1,1,1,1,1,1,1}
(1 row)

2番目のベクトル(1.5,2.5)はクラスタ0に属する
*/

クラスタリングする

ベクトルの集合をkmeans関数に渡せるように配列に集約し、kmeansで得られた配列のn番目が集合のn行目のクラスタの値になります。

SELECT
 x, y,
 (
  kmeans(
   array_agg(x) OVER(),
   array_agg(y) OVER()
  )
 )[row_number() OVER()] as kmeans_cluster
FROM (VALUES
 (1.9::float,2.3::float),
 (1.5,2.5),
 (0.8,0.6),
 (0.4,1.8),
 (0.1,0.1),
 (0.2,1.8),
 (2.0,0.5),
 (0.3,1.5),
 (1.0,1.0)
) t(x, y)

/*
  x  |  y  | kmeans_cluster 
-----+-----+----------------
 1.9 | 2.3 |              0
 1.5 | 2.5 |              0
 0.8 | 0.6 |              1
 0.4 | 1.8 |              1
 0.1 | 0.1 |              1
 0.2 | 1.8 |              1
   2 | 0.5 |              1
 0.3 | 1.5 |              1
   1 |   1 |              1
(9 rows)
*/

以上、PL/Pythonでscipyライブラリを使ってk-means法を実装してみました。

おまけ

PostgreSQLのC言語関数で書かれたkmeansのライブラリもあります。
https://github.com/umitanuki/kmeans-postgresql

0 件のコメント:

コメントを投稿