機械学習の特徴量エンジニアリングをしていて行き詰まったから、主成分分析して2項目の角度を求めて追加してみたらこれが意外と精度向上につながって驚いている


はじめに

...とあるデータで機械学習をすることになり、それなりの精度にはなったものの、そこから精度があがらずに困っていたら、ふと思いついたので、軽い気持ちで試してみたのがタイトルのとおり。

ちなみに万能ではありません。
時系列で繰り返しが多いものに向いていて、離散的なものでは結果がでないような印象があります。

また、こういうことをやってはいけない場面もあると思いますので、ご利用は自己判断で...
もし、何か理論的に間違っているところなどがあれば、コメントでご指摘頂けると助かります。

以上、そんな感じでも良ければお試しください。

やっていることの概要



サンプルコード(追加前)

諸事情により実際のコードを示せませんので、処理内容は察して下さい。
以下のコードを使って学習と予測をしているとします。

original.py
# ライブラリ読込
import pandas as pd
from sklearn import model_selection
from sklearn.ensemble import RandomForestRegressor

# 学習データ読込
df_train = pd.read_csv("train.csv")

# 学習用データ加工
X = df_train[df_train.columns[~df_train.columns.str.contains("y")]]
y = df_train["y"]

# 学習用と検証用に分割
X_train, X_valid, y_train, y_valid = model_selection.train_test_split(X, y, test_size=.2, random_state=42)

# モデル構築
model = RandomForestRegressor(random_state=42)
model.fit(X_train, y_train)
print(model.score(X_valid, y_valid))

# テストデータ読込
df_test = pd.read_csv("test.csv")

# 予測値の取得とCSV出力
y_pred = model.predict(df_test)
pd.DataFrame(y_pred).to_csv("pred.csv")

追加するコード

学習用データのXを求めたところで、以下のコードを追加してみました。

from sklearn.decomposition import PCA
import math

# 2つの値から角度を求めて、配列を返す関数
def make_radian_row(pca_result):
    rad = []
    for r in pca_result:
        rad.append(math.atan(r[0]/r[1]))

    return rad

# 主成分分析
pca = PCA(n_components=2)
pca.fit(X)

X["rad"] = make_radian_row(pca.transform(X))

サンプルコード(修正後)

最初のコードに追加分を入れたら以下のようになりました。

edited.py
# ライブラリ読込
import pandas as pd
from sklearn.decomposition import PCA
import math
from sklearn import model_selection
from sklearn.ensemble import RandomForestRegressor

# 2つの値から角度を求めて、配列を返す関数
def make_radian_row(pca_result):
    rad = []
    for r in pca_result:
        rad.append(math.atan(r[0]/r[1]))

    return rad

# 学習データ読込
df_train = pd.read_csv("train.csv")

# 学習用データ加工
X = df_train[df_train.columns[~df_train.columns.str.contains("y")]]
y = df_train["y"]

# 学習用と検証用に分割
X_train, X_valid, y_train, y_valid = model_selection.train_test_split(X, y, test_size=.2, random_state=42)

# 主成分分析
pca = PCA(n_components=2)
pca.fit(X_train)

# 角度データの追加
X_train["rad"] = make_radian_row(pca.transform(X_train))
X_test["rad"] = make_radian_row(pca.transform(X_test))

# モデル構築
model = RandomForestRegressor(random_state=42)
model.fit(X_train, y_train)
print(model.score(X_valid, y_valid))

# テストデータ読込
df_test = pd.read_csv("test.csv")

# 角度データの追加
df_test["rad"] = make_radian_row(pca.transform(df_test))

# 予測値の取得とCSV出力
y_pred = model.predict(df_test)
pd.DataFrame(y_pred).to_csv("pred.csv")

結果

80%後半台の精度が90%前半の精度になりました(^_^;)

さて、次は何しようかな。