Dr.SumのPython連携機能を使った機械学習
BI技術者の雑記
今回は、Dr.SumのPython連携機能を使って、KaggleのTitanicのチュートリアルを機械学習(ランダムフォレスト)で予測する方法をご説明します。
※Dr.SumのPython連携機能の説明がメインなので、ランダムフォレストやPythonの細かい説明は割愛します。
1. 手順① 環境構築
前提として、Dr.Sumサーバがインストールされている必要があります。(Ver.5.6以上)
①-1 データの準備
まず、Kaggleサイトから「タイタニック号の生存者データ」を入手します。
「training set (train.csv)」「test set (test.csv)」の両方をダウンロードしてください。
次に、入手したデータをDr.Sumのテーブルに登録します。
テーブルのデータをインメモリ化します。
「Dr.Sum 5.6 In-Memory Server」のサービスが起動しているか確認し、起動していない場合は起動します。

作成したテーブルの上で右クリックし、「プロパティ」→「インメモリ化する」を選択します。
もう一度テーブルの上で右クリックし、「インメモリ」→「データをロード」を選択します。

これでデータの準備は完了です。
①-2 Dr.Sumサーバの設定
| <環境情報> | |
| Dr.Sum | Localhost:6001 |
| Python連携ルート設定パス | C:DrSum56Serversamplesudtf-py |
| クライアント用Python環境 | C:DrSum56AdminToolsudtf-pythonpython |
| サーバ用Python環境 | C:DrSum56IMServerlaunchpythonenvpython |
「Dr.Sum 5.6 Launch Server」のサービスが起動しているか確認し、起動していない場合は起動します。
Dr.Sumのクライアントおよびサーバ用Python環境に、コマンドラインから使用するライブラリをインストールします。
例:C:DrSum56AdminToolsudtf-pythonpythonpython.exe -m pip install scikit-learn
2. 手順② 予測モデルの作成
Dr.Sumに登録したトレーニングデータを使用して、予測モデルを作成します。
②-1 予測モデル作成用スクリプトの作成
<ファイル名>
C:/DrSum56/Server/samples/udtf-py/script/titanic_train.py
<スクリプト>
import io
import pandas as pd
from sklearn.model_selection import train_test_split
import joblib
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import mean_squared_error
import numpy as np
import csv
# Dr.SumからODBC接続で訓練データを取得
def import_data():
import pyodbc
con = pyodbc.connect(DRIVER="Dr.Sum 5.6 ODBC Driver",
HOST="localhost", DATABASE="test", trusted_connection="yes",
user="Administrator", password="", port = "6001"
)
TBL = "titanic_train"
query = "SELECT * FROM {tbl} ;".format(tbl=TBL)
train_data = pd.read_sql(query, con)
return train_data
def train(context,input):
input = preprocess(input)
# 訓練データとバリデーション用データを7:3で分割
train_x, test_x ,train_y, test_y = train_test_split(
input.drop("Survived", axis = 1).values,
input["Survived"].values,
test_size = 0.3, random_state = 0)
model = RandomForestClassifier(random_state=0)
model.fit(train_x, train_y)
y_pred = model.predict(test_x) # 予測
mse= mean_squared_error(test_y, y_pred) # 評価
# アウトプットとなるdataframeを定義
model_status = pd.DataFrame(columns = ["description", "value"])
# 各説明変数の重要度データをアウトプットとして追加する。
for i, feat in enumerate(input.columns[input.columns!="Survived"]):
model_status.loc[feat] = [feat, model.feature_importances_[i]]
# モデルの保存
stream = io.BytesIO()
joblib.dump(model, stream)
context.write_remote_file("PY_DATA_ROOT/titanic_model.sav", stream.getvalue())
return model_status
def preprocess(df):
df['Fare'] = df['Fare'].fillna(df['Fare'].mean())
df['Age'] = df['Age'].fillna(df['Age'].mean())
df['Embarked'] = df['Embarked'].fillna('Unknown')
df['Sex'] = df['Sex'].apply(lambda x: 1 if x == 'male' else 0)
df['Embarked'] = df['Embarked'].map( {'S': 0, 'C': 1, 'Q': 2, 'Unknown': 3} ).astype(int)
df['Age'] = df['Age'].astype(int)
df['Fare'] = df['Fare'].astype(int)
df['Survived'] = df['Survived'].astype(int)
df['Pclass'] = df['Pclass'].astype(int)
df['SibSp'] = df['SibSp'].astype(int)
df['Parch'] = df['Parch'].astype(int)
df = df.drop(['Cabin','Name','PassengerId','Ticket'],axis=1)
return df
def main():
import dspy.emulator
train_data = import_data()
# エミュレータを使ったデバッグ
builder=dspy.emulator.EmulatorBuilder(train_data)
emulator=builder.buildSerial(
py_file_path = "PY_SCRIPT_ROOT/titanic_train.py",
func_name = "train",
schema_func_name = "model_status",
)
result=emulator.execute(create_schema_mode = True) # Trueで結果表スキーマ取得関数を出力するようにする
print(result)
if __name__ == "__main__":
main()
<スクリプトの概要>
| 関数 | 内容 |
| def import_data() | Dr.Sumからのデータ取得 |
| def preprocess() | データのクレンジング |
| def train() | モデルの学習、作成 |
| def main() | メイン処理 |
②-2 実行
以下のコマンドでスクリプトを実行します。
C:DrSum56AdminToolsudtf-pythonpythonpython.exe C:DrSum56Serversamplesudtf-pyscripttitanic_train.py
モデルの内容が表示されます。
description value
0 Pclass 0.091828
1 Sex 0.285340
2 Age 0.298141
3 SibSp 0.059709
4 Parch 0.038032
5 Fare 0.185667
6 Embarked 0.041283
どうやら性別、年齢が生存に大きく影響していそうです。
モデルは同フォルダに作成されるので、作成されたファイルをC:DrSum56Serversamplesudtf-pydataにコピーしてください。
※今回のファイル名は「titanic_model.sav」です。
<補足>
実行すると下記のメッセージも表示されます。
この関数を同スクリプトに追加すると、コマンドラインで実施したことがDr.Sumサーバからも実施できますが、Dr.Sumサーバの呼び出しは「手順③ 予測の実行」で説明するため割愛します。
以下のスタブ関数をC:DrSum56Serversamplesudtf-pyscripttitanic_train.pyにコピーしてください。
def model_status(input_schema):
return ['description VARCHAR', 'value NUMERIC']
3. 手順③ 予測の実行
「手順② 予測モデルの作成」で作成したモデルをDr.Sumサーバから呼び出し、テストデータの生存者判定を行います。
スクリプトはPythonで作成しますが、実行はDr.Sumサーバから呼び出します。
③-1 予測実行用スクリプトの作成
<ファイル名>
C:/DrSum56/Server/samples/udtf-py/script/titanic_train.py
<スクリプト>
import pandas as pd
import joblib, io
def predict_schema(input_schema):
return ['PassengerId NUMERIC', 'Survived NUMERIC']
def predict(context, input):
test_data = preprocess(input)
load_stream = io.BytesIO(context.read_remote_file(f"PY_DATA_ROOT/titanic_model.sav"))
model = joblib.load(load_stream)
y_pred = model.predict(test_data.values) # 予測
output = test_data.assign(Survived = y_pred)
input = input['PassengerId']
output = output['Survived']
output = pd.concat([input, output],axis=1)
return output
def preprocess(df):
df['Fare'] = df['Fare'].fillna(df['Fare'].mean())
df['Age'] = df['Age'].fillna(df['Age'].mean())
df['Embarked'] = df['Embarked'].fillna('Unknown')
df['Sex'] = df['Sex'].apply(lambda x: 1 if x == 'male' else 0)
df['Embarked'] = df['Embarked'].map( {'S': 0, 'C': 1, 'Q': 2, 'Unknown': 3} ).astype(int)
df['Age'] = df['Age'].astype(int)
df['Fare'] = df['Fare'].astype(int)
df['Pclass'] = df['Pclass'].astype(int)
df['SibSp'] = df['SibSp'].astype(int)
df['Parch'] = df['Parch'].astype(int)
df = df.drop(['PassengerId','Cabin','Name','Ticket'],axis=1)
return df
<スクリプトの概要>
| 関数 | 内容 |
| def preprocess() | データのクレンジング |
| def predict() | モデルの読み込み、予測 |
| def predict_schema() | 結果のインターフェース |
※Dr.Sumサーバから呼び出されるため、main処理はありません。
③-2 予測の実行(Dr.SumサーバのSQL ExecutorでSQL実行)
SELECT
T.*
FROM
udtf::serial_py(
titanic_test,
py_file_path='PY_SCRIPT_ROOT/titanic_predict.py',
func_name='predict',
schema_func_name='predict_schema'
) T
実行すると予測結果が画面に表示されます。
※Survived=1は生存と予測

4.おわりに
今回は、Dr.SumのPython連携機能を使って、Kaggleの「タイタニックの生存者予測」を実施する方法についてご紹介しました。
環境構築は多少手間がかかりますが、構築後の予測の実行は比較的簡単にできると思います。
