この記事について
Teradataが独自拡張したSQL関数を用いて回帰分析の学習・予測を行う方法を紹介します。
これは、機械学習の学習から推論までを全てデータベース上で実行する、珍しい機能です。
分散データベースの処理に最適化された関数を用いるため、高い効率性を実現します。
実行コードは、日本テラデータGitHubにて公開中しています。
このコードは無料のTeradata環境 ClearScape Analytics Experience にて実行可能です。
要点
- TeradataのIn-DB分析関数により、線型回帰モデルを学習・予測
- 機械学習モデルの学習・デプロイ・推論の全てをデータベース内で完結
Teradata In-DB分析関数
この記事では線型回帰モデルを扱いますが、他にも主要な分析モデルをサポートしています。
たとえば、ロジスティック回帰、ランダムフォレスト、ARIMA、XGBoost、サポートベクトルマシンなどが利用可能です。
事前準備
必要なライブラリをインストールします。
pip install pandas "sqlalchemy<2" teradataml
sqlalchemy
バージョン2との互換性に不具合が出ているので、改善まではバージョン1を指定します
Teradataへの接続
実際の環境に合わせて接続情報を指定します。
わからなければデータベース管理者に聞いてみましょう。
この例はお試し環境 ClearScape Experience での設定です。
from getpass import getpass
from urllib.parse import quote_plus
host = "host.docker.internal"
user = "demo_user"
database = "demo_user"
password = getpass("Password > ")
dbs_port = 1025
encryptdata = "true"
# sqlalchemy用の接続文字列
connstr = (
f"teradatasql://{user}:{quote_plus(password)}@{host}/?"
f"&database={database}"
f"&dbs_port={dbs_port}"
f"&encryptdata={encryptdata}"
)
from sqlalchemy import create_engine
from teradataml import create_context, DataFrame
engine = create_engine(connstr)
context = create_context(tdsqlengine=engine, temp_database_name=user)
住宅価格の予測 (LightGBM)
カリフォルニア住宅価格データを用いて、価格予測を行います。
データの準備
from sklearn.datasets import fetch_california_housing
data = fetch_california_housing(as_frame=True)
df = data["data"]
df.insert(0, "target", data["target"])
# teradata へデータをロード
from teradataml import copy_to_sql, DataFrame
copy_to_sql(df, "housing", if_exists="replace", index=True)
# ロード結果を確認
DataFrame("housing")
#target MedInc HouseAge AveRooms AveBedrms Population AveOccup Latitude Longitude index_label
#1.208 3.75 10.0 3.45 0.8 50.0 2.5 38.01 -121.29 16385
#1.55 2.9821 32.0 6.576923076923077 1.1153846153846154 138.0 2.6538461538461537 38.02 -121.27 16387
#1.125 1.15 52.0 4.88 1.04 62.0 2.48 38.05 -121.3 16
#....
-
copy_to_sql
を用いてローカル環境のデータフレームをteradataへロードしています -
index=True
を指定することで、もともとの行番号を識別列として追加しています (データの順序は入れ替わってしまうので、後で突合するときに必要)
df = DataFrame("housing")
df_tr = df[df.index_label.mod(5) > 0]
df_te = df[df.index_label.mod(5) == 0]
copy_to_sql(df_tr, "housing_tr", if_exists="replace")
copy_to_sql(df_te, "housing_te", if_exists="replace")
-
index_label
を5で割った余りが0ならテストデータ、それ以外なら学習データとして用います - 他にもう少し混み入ったアルゴリズムでの分割も可能です (TrainTestSplit 関数)
- ここでも
copy_to_sql
関数を使っていますか、ここではteradataml.DataFrame
をテーブルとして保存するために使っています
データの標準化
from teradataml import ScaleFit, ScaleTransform
# 説明変数
cols = ["MedInc", "HouseAge", "AveRooms", "AveBedrms", "Population", "AveOccup", "Latitude", "Longitude"]
# 事前に説明変数を標準化する
scale = ScaleFit(data=x_tr, target_columns=cols, scale_method="USTD")
scale.output # 標準化にかかる情報はデータフレームとして保持される
#TD_STATTYPE_SCLFIT MedInc HouseAge ... Latitude Longitude
#sum 63944.67140000035 473791.0 ... 588353.2699999986 -1974336.8599999906
#null 0.0 0.0 ... 0.0 0.0
#avg 3.872618180717075 28.6937378875969 ... 35.63185985949604 -119.56981952519322
-
ScaleFit
関数でデータを標準化するための情報を学習します - 情報は、1つのテーブルとして保持されます
# 学習データ・テストデータに標準化を行う
x_tr_scaled = ScaleTransform(
data=x_tr, object=scale.output, accumulate=["target", "index_label"]).result
x_te_scaled = ScaleTransform(
data=x_te, object=scale.output, accumulate=["target", "index_label"]).result
- 標準化を実行するには、
ScaleTransform
関数を用います
線型回帰モデルの学習
from teradataml import GLM
glm = GLM(data=x_tr_scaled,
input_columns=cols,
response_column="target",
family="GAUSSIAN",
lambda1=0.01,
alpha=0.3,
batch_size=4500)
# 学習結果はテーブルとして保持される
glm.result.to_pandas().sort_index()
#attribute predictor estimate value
#0 (Intercept) 2.040508 None
#1 MedInc 0.775201 None
#2 HouseAge 0.100127 None
#...
-
GLM
関数で一般化線形モデルを学習します。family="GAUSSIAN"
とすれば線型回帰になります - 学習結果はやはり1つのテーブルとして保持されます
# 学習データへの予測
from teradataml import TDGLMPredict, RegressionEvaluator
# 予測を実行
pred_tr = TDGLMPredict(
newdata=x_tr_scaled, # 予測対象のデータを指定
object=glm.result, # 学習済モデルを保持するオブジェクトを指定
id_column="index_label", # id列を指定
accumulate="target" # 予測結果とともに抽出したい変数を指定
).result
pred_tr
#index_label prediction target
#16386 1.753725879086769 0.828
#16388 1.0432197226949214 1.125
#16389 1.800250953823959 1.068
#....
-
id_column
には識別列を指定 -
accumulate
には結果と一緒に出力したい列名を与えます
# 予測結果を評価
res_tr = RegressionEvaluator(
data=pred_tr, # 予測結果を保持するテーブルを指定
observation_column="target", # 真の値
prediction_column="prediction", # 予測値
metrics=["MSE", "MAE", "R2"] # 計算する指標
)
res_tr.result
#MAE MSE R2
#0.5725529079984077 0.6137348063921505 0.5384568788835442
結び
以上、In-DB分析関数を用いて、線型回帰モデルを学習し、それを用いた予測を行う手順を紹介しました。他にもランダムフォレストやXGBoostなど、主要な学習アルゴリズムが利用可能なので、ぜひお試しください。
疑問点・懸念点などありましたらぜひコメントください。GitHubの方にIssueを立てていただいても結構です。