LoginSignup
3
2

データサイエンスのためのTeradata入門: In-DB分析機能による回帰分析

Last updated at Posted at 2024-04-09

この記事について

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を立てていただいても結構です。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2