pl/pythonで独自の集約関数を作ってみる
TRANSCRIPT
Copyright 2015 Uptime Technologies, LLC. All rights reserved. 1
PL/Pythonで独⾃の集約関数を作ってみる
アップタイム・テクノロジーズ永安 悟史
第6回 PostgreSQLアンカンファレンス
⽬次
• なぜPL/Pythonで集約関数なのか?• PostgreSQLにおける集約関数の作り⽅• PL/Pythonの関数の作り⽅• min(),max(),avg()を実装してみる• 単回帰分析を⾏う集約関数を実装してみる
Copyright 2015 Uptime Technologies, LLC. All rights reserved. 2
なぜPL/Pythonで集約関数なのか?
• Pythonとデータ処理
• データ処理と集約関数
• プロシージャ・UDFによるIn-Database処理
Copyright 2015 Uptime Technologies, LLC. All rights reserved. 3
PostgreSQLにおける集約関数の作り⽅
• CREATE AGGREGATEコマンドによる定義– 実⾏中の内部状態を処理するUDF:sfunc– 内部状態を保持するデータ型:state_data_type– 最終的な結果を出⼒するUDF:ffunc
Copyright 2015 Uptime Technologies, LLC. All rights reserved. 4
CREATE AGGREGATE myagg (arg1, arg2, ...)(
SFUNC = sfunc,STYPE = state_data_type,FINALFUNC = ffunc
);
ユーザ定義の集約https://www.postgresql.jp/document/9.4/html/xaggr.htmlCREATE AGGREGATEhttps://www.postgresql.jp/document/9.4/html/sql-createaggregate.html
sfuncargs
state
sfuncargs
state
ffuncreturn
PL/Pythonの関数の作り⽅
• CREATE FUNCTION– 単に中⾝がPythonスクリプトになるだけ
• データベースにアクセスする場合には plpy モジュール– CのUDFで⾔うところのSPI関数のようなもの– import plpy
• 注意すべきところ– plpython.soからリンクされているPythonのバージョン– データの相互マッピング(+エンコーディング)– ステート変数の global 宣⾔(変更するには global が必要。後述)– そもそも superuser しか使えない(untrusted なので)
Copyright 2015 Uptime Technologies, LLC. All rights reserved. 5
PL/Python - Python⼿続き⾔語https://www.postgresql.jp/document/9.4/html/plpython.html
PL/Pythonの関数の作り⽅
• 外部のPythonモジュールを使うUDFの例– ⽇本語⾃動要約ライブラリ
Copyright 2015 Uptime Technologies, LLC. All rights reserved. 6
⾃動要約API「summpy」を使ってPostgreSQLに⽂章の要約機能を追加するhttp://pgsqldeepdive.blogspot.jp/2015/11/pgsummpy.html
CREATE FUNCTION lexrank_summarize(p text, t text, s_limit integer)RETURNS SETOF text
AS $$import syssys.path.append(p)from summpy import lexrank
res = lexrank.summarize(unicode(t, 'utf‐8'), sent_limit=s_limit)for s in res:
yield(s.encode('utf‐8'))$$ LANGUAGE plpythonu;
min(),max(),avg()を実装してみる
• 組み込みのmin(), max(), avg() の機能を再現– 集約関数名は pymin(), pymax(), pyavg()
Copyright 2015 Uptime Technologies, LLC. All rights reserved. 7
‐‐ min()‐‐ sがstate変数、nが入力値、最後の計算は不要なのでffuncは無しCREATE FUNCTION float8_pymin(s float8, n float8)RETURNS float8
AS $$global s
if n is not None:if s is None or n < s:
s = nreturn s
$$ LANGUAGE plpython2u;
CREATE AGGREGATE pymin (float8)(
sfunc = float8_pymin,stype = float8
);
min(),max(),avg()を実装してみる
• avg() のPL/Python実装– ffunc を追加して、最後に平均値を計算して出⼒
Copyright 2015 Uptime Technologies, LLC. All rights reserved. 8
‐‐‐‐ avg()‐‐CREATE FUNCTION float8_pyavg(
s float8[], n float8)RETURNS float8[]
AS $$global s
if n is not None:if s is None:
# sum,counts = [0,0]
s[0] = s[0] + ns[1] = s[1] + 1
return s$$ LANGUAGE plpython2u;
CREATE FUNCTION float8_pyavg_final(s float8[])
RETURNS float8AS $$
global s
if s is not None:return s[0]/s[1]
return None$$ LANGUAGE plpython2u;
CREATE AGGREGATE pyavg (float8)(
sfunc = float8_pyavg,stype = float8[],finalfunc = float8_pyavg_final
);
pyagg.sql https://gist.github.com/snaga/7c3940e72fad172cca6f
単回帰分析を⾏う集約関数を実装してみる
• 単回帰分析のモデルは y = w0 + w1 * x
• データを⼆種類⽤意する(訓練⽤、評価⽤)
• 訓練⽤データのテーブルから y と x を拾う– w0 と w1 を集約関数で計算して出⼒する
• 別のテーブルの評価⽤データの x から y を予測する
• 結果および誤差を確認する
Copyright 2015 Uptime Technologies, LLC. All rights reserved. 9
Machine Learning: Regression - University of Washington | Courserahttps://www.coursera.org/learn/ml-regression/
単回帰分析を⾏う集約関数を実装してみる
Copyright 2015 Uptime Technologies, LLC. All rights reserved. 10
snaga=# ¥dList of relations
Schema | Name | Type | Owner‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+‐‐‐‐‐‐‐public | kc_house_data | table | snagapublic | kc_house_test_data | table | snagapublic | kc_house_train_data | table | snaga(3 rows)
snaga=# select simple_linear_regression(price,sqft_living) from kc_house_train_data;
simple_linear_regression‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐{‐47116.0791388,281.958839662}(1 row)
• デモ
snaga/SimpleLinearRegressionhttps://github.com/snaga/SimpleLinearRegression
単回帰分析を⾏う集約関数を実装してみる
Copyright 2015 Uptime Technologies, LLC. All rights reserved. 11
snaga=# select sqft_living,price,round(‐47116.0791388 + 281.958839662 * sqft_living) as
price_predicted,round((((‐47116.0791388 + 281.958839662 * sqft_living) ‐ price) /
price)::numeric, 2) as errorfrom kc_house_test_data;sqft_living | price | price_predicted | error‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐
1430 | 310000 | 356085 | 0.152950 | 650000 | 784662 | 0.211710 | 233000 | 435034 | 0.87
(...)2310 | 400000 | 604209 | 0.511020 | 402101 | 240482 | ‐0.40
(4229 rows)
• デモ
snaga/SimpleLinearRegressionhttps://github.com/snaga/SimpleLinearRegression
Q&A
Copyright 2015 Uptime Technologies, LLC. All rights reserved. 12
コメント、質問など
Twitter: @snagaE-Mail: [email protected]