Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

PL/Pythonで独自の集約関数を作ってみる

第6回 PostgreSQLアンカンファレンスでの発表資料です。

  • Be the first to comment

PL/Pythonで独自の集約関数を作ってみる

  1. 1. Copyright 2015 Uptime Technologies, LLC. All rights reserved. 1 PL/Pythonで独⾃の集約関数を 作ってみる アップタイム・テクノロジーズ 永安 悟史 第6回 PostgreSQLアンカンファレンス
  2. 2. ⽬次 • なぜPL/Pythonで集約関数なのか? • PostgreSQLにおける集約関数の作り⽅ • PL/Pythonの関数の作り⽅ • min(),max(),avg()を実装してみる • 単回帰分析を⾏う集約関数を実装してみる Copyright 2015 Uptime Technologies, LLC. All rights reserved. 2
  3. 3. なぜPL/Pythonで集約関数なのか? • Pythonとデータ処理 • データ処理と集約関数 • プロシージャ・UDFによるIn-Database処理 Copyright 2015 Uptime Technologies, LLC. All rights reserved. 3
  4. 4. 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.html CREATE AGGREGATE https://www.postgresql.jp/document/9.4/html/sql-createaggregate.html sfunc args state sfunc args state ffunc return
  5. 5. 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
  6. 6. 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 sys sys.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;
  7. 7. 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 = n return s $$ LANGUAGE plpython2u; CREATE AGGREGATE pymin (float8) ( sfunc = float8_pymin, stype = float8 );
  8. 8. 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,count s = [0,0] s[0] = s[0] + n s[1] = s[1] + 1 return s $$ LANGUAGE plpython2u; CREATE FUNCTION float8_pyavg_final( s float8[]) RETURNS float8 AS $$ 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
  9. 9. 単回帰分析を⾏う集約関数を実装してみる • 単回帰分析のモデルは 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 | Coursera https://www.coursera.org/learn/ml-regression/
  10. 10. 単回帰分析を⾏う集約関数を実装してみる Copyright 2015 Uptime Technologies, LLC. All rights reserved. 10 snaga=# ¥d List of relations Schema |        Name         | Type  | Owner ‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+‐‐‐‐‐‐‐ public | kc_house_data | table | snaga public | kc_house_test_data | table | snaga public | 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/SimpleLinearRegression https://github.com/snaga/SimpleLinearRegression
  11. 11. 単回帰分析を⾏う集約関数を実装してみる 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 error from kc_house_test_data; sqft_living | price  | price_predicted | error ‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐ 1430 | 310000 |          356085 |  0.15 2950 | 650000 |          784662 |  0.21 1710 | 233000 |          435034 |  0.87 (...) 2310 | 400000 |          604209 |  0.51 1020 | 402101 |          240482 | ‐0.40 (4229 rows) • デモ snaga/SimpleLinearRegression https://github.com/snaga/SimpleLinearRegression
  12. 12. Q&A Copyright 2015 Uptime Technologies, LLC. All rights reserved. 12 コメント、質問など Twitter: @snaga E-Mail: snaga@uptime.jp

×