Scikit-Learn 決定木のサンプル

import pandas as pd
df = pd.read_csv("./jobs.txt", sep="\t")

# カテゴリ型の結果変数(担当(MANAGER))をエンコードする
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
df['MANAGER_E'] = le.fit_transform(df['MANAGER'].values)

# 復元する関数を作っておこう
def get_orig_manager(manager_e):
    return le.inverse_transform([manager_e])

# 確認
#print(get_orig_manager(3))

# カテゴリ型の特徴量(特徴量)をエンコードする
# LabelEncoderと異なりOrdinalEncoderは複数列を一括エンコードできる
from sklearn.preprocessing import OrdinalEncoder
oe = OrdinalEncoder()
df.loc[:,['SALES_SECTION_E', 'PRODUCT_TYPE_E', 'CUSTOMER_CODE_E']] = \
  oe.fit_transform(df[['SALES_SECTION','PRODUCT_TYPE','CUSTOMER_CODE']].values)

# 逆変換ができることを確認
print(oe.inverse_transform([[1,2,3],[2,1,3]]))

from sklearn.model_selection import train_test_split
X = df.loc[:,['SALES_SECTION_E', 'PRODUCT_TYPE_E', 'CUSTOMER_CODE_E', 'SALES_AMOUNT', 'PERIOD']]
y = df.loc[:,['MANAGER_E']]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25)

# 決定木の場合
from sklearn.tree import DecisionTreeClassifier
model = DecisionTreeClassifier(max_depth=10)

# 勾配ブースティング決定木の場合
# from sklearn.ensemble import GradientBoostingClassifier
# model = GradientBoostingClassifier(n_estimators=50, max_depth=3)

# ランダムフォレストの場合
# from sklearn.ensemble import RandomForestClassifier
# model = RandomForestClassifier(n_estimators=100,max_depth=7)

# おまけ K近傍法(KNN)の場合(この例だと性能が低い。0-1正規化が必要)
# from sklearn.neighbors import KNeighborsClassifier
# model = KNeighborsClassifier(n_neighbors=7)

# おまけ ニューラルネットワークの場合(この例だと性能が低い。0-1正規化が必要)
# from sklearn.neural_network import MLPClassifier
# model = MLPClassifier()

# 決定木の場合はy_trainを渡せばOKだが、ランダムフォレストだと警告が出るので1D配列に変形する
# ravelはNumPyの関数で、原義は「ほぐす」。他次元配列を一次元に平坦化する
# model.fit(X_train, y_train)
model.fit(X_train, y_train.values.ravel())

# テストデータでテストする
score = model.score(X_test, y_test)
print(score)

# テストデータ1件ごとに判定と正解を並べて表示する
y_pred = model.predict(X_test)
for i in range(len(y_test)):
    y_test_manager_name = le.inverse_transform([y_test.iloc[i,0]])
    y_pred_manager_name = le.inverse_transform([y_pred[i]])
    print('[{0}] correct:{1}({2}), predict:{3}({4})'.format(i, y_test.iloc[i,0], y_test_manager_name, y_pred[i],y_pred_manager_name))

# 1個予測してみよう
# 東京 G CPE 8000 370 の時担当者は?
print(oe.transform([['東京','G','CPE']]))
print(oe.inverse_transform([[2,1,0]]))
# 既存df定義をもとに空のdfを作成
dftest = pd.DataFrame(columns=X_train.columns)
dftest.loc["0"] = [2,1,0,8000,370]
print(dftest)

y_pred = model.predict(dftest)
print(y_pred)
print(get_orig_manager(y_pred[0]))

# 項目別の影響度を表示 列名も一緒に表示するためSeriesに加工している
print(pd.Series(model.feature_importances_, index=X_test.columns))

# splitの代わりにK交差検証(KFold)してみる
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score
kfold = KFold(n_splits=5, shuffle=True)
result = cross_val_score(model,X,y.values.ravel(),cv=kfold,scoring="accuracy")
print(result)

# dotファイルに出力してVSCodeのGraphVizプラグイン等で見る
# ※modelが決定木の場合のみ。RFだとエラーになります。
from sklearn.tree import export_graphviz
export_graphviz(model,out_file="tree1.dot",filled=True,rounded=True,
    feature_names=X_train.columns, class_names=["0","1"])

# dot.exeにPATHが通っていれば以下でPNGも出力可能
import pydot
(graph,) = pydot.graph_from_dot_file("tree1.dot")
graph.write_png("tree1.png")

Misc. Topics Top

(first uploaded 2024/02/11 last updated 2024/02/25, URANO398)