ナード戦隊データマン

データサイエンスを用いて悪と戦うぞ

データの表現: ダミー変数, binning, 多項式特徴量

教師あり学習を行う際には、データの正しい表現を模索します。これは、特徴量エンジニアリングなどと呼ばれます。特徴量エンジニアリングはパラメータ選択よりも大きな影響を与えることがあります。ここでは、ダミー変数、binning, 多項式特徴量について見てみます。

ダミー変数(ワンホットエンコーディング)

ダミー変数とは、n種からなるカテゴリー変数をnつの0-1変数に置き換えたものです。例えば、以下の表現を見てください。

salary
1, middle
2, middle
3, high
4, low

これは、以下の0-1変数に置き換わります。

salary_middle
1, 1
2, 1
3, 0
4, 0

salary_high
1, 0
2, 0
3, 1
4, 0

salary_low
1, 0
2, 0
3, 0
4, 1

これにより、線形モデルはダミー変数に対する係数を定義することが可能となります。実際のコードの例を以下に書きます。

from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
import pandas as pd
import mglearn
import os

adult_path = os.path.join(mglearn.datasets.DATA_PATH, "adult.data")
data = pd.read_csv(adult_path, header=None, index_col=False,
                  names=["age","workclass", "fnlwgt", "education","education_num",
                        "martial-status", "occupation","relationship", "race", "gender",
                        "capital-gain", "capital-loss", "hours-per-week", "native-country", "income"])
data_dummied = pd.get_dummies(data) #ダミー変数を作成

X = data_dummied.ix[:, 0:(data_dummied.shape[1]-2)]
y = data_dummied.ix[:, data_dummied.shape[1]-1].values

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
clf = LogisticRegression()
clf.fit(X_train, y_train)
print("score:{:.2f}".format(clf.score(X_test, y_test)))
score:0.80

binning

binningとは、連続値をビンと呼ばれる離散値カテゴリーに置き換える方法です。線形モデルを柔軟にするために用いることができます。普通に線形回帰を用いると、以下のような直線の当てはめしかできません。

%matplotlib inline
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
import mglearn
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

X, y = mglearn.datasets.make_wave(n_samples=100)
line = np.linspace(-3, 3, 1000, endpoint=False).reshape(-1,1)

reg = LinearRegression().fit(X, y)
plt.plot(line, reg.predict(line), label="lreg")

plt.plot(X[:, 0], y, 'o', c='k')
plt.ylabel("out")
plt.xlabel("in")
plt.legend(loc="best")

f:id:mathgeekjp:20170910213133p:plain

binningを用いると、ビンごとの値に応じて定数を当てはめることができます。

from sklearn.preprocessing import OneHotEncoder

bins = np.linspace(-3, 3, 11)
which_bin = np.digitize(X, bins=bins)

encoder = OneHotEncoder(sparse=False)
encoder.fit(which_bin)
X_binned = encoder.transform(which_bin)

line_binned = encoder.transform(np.digitize(line, bins=bins))
reg = LinearRegression().fit(X_binned, y)
plt.plot(line, reg.predict(line_binned), label="lreg binned")

plt.plot(X[:, 0], y, 'o', c='k')

plt.vlines(bins, -3, 3, linewidth=1, alpha=.2)
plt.legend(loc="best")
plt.ylabel("out")
plt.xlabel("in")

f:id:mathgeekjp:20170910213416p:plain

しかし、定数ではまだ柔軟性に欠けます。ビンごとに傾きを定義するには、交互作用特徴量を定義します。

X_product = np.hstack([X_binned, X*X_binned])
reg = LinearRegression().fit(X_product, y)

line_product = np.hstack([line_binned, line * line_binned])
plt.plot(line, reg.predict(line_product), label="lreg product")

for bin in bins:
    plt.plot([bin, bin], [-3, 3], ':', c="k")

plt.legend(loc="best")
plt.ylabel("out")
plt.xlabel("in")
plt.plot(X[:, 0], y, 'o', c='k')

f:id:mathgeekjp:20170910213658p:plain

多項式特徴量

多項式特徴量とは、特徴量の多項式表現を新たな特徴量とする方法です。例えば、x1, x2, x3の特徴量の2次の表現を作ると、x1x2, x2x3, x3x1, x1x1, x2x2, x3x3という特徴量が作れます。カーネル法を用いたSVMのように、これらの特徴量を線形モデルに適用すると、柔軟性が高まります。

from sklearn.preprocessing import PolynomialFeatures

poly = PolynomialFeatures(degree=10, include_bias=False)
poly.fit(X)
X_poly = poly.transform(X)

reg = LinearRegression().fit(X_poly, y)

line_poly = poly.transform(line)
plt.plot(line, reg.predict(line_poly), label="poly lreg")

plt.legend(loc="best")
plt.ylabel("out")
plt.xlabel("in")
plt.plot(X[:, 0], y, 'o', c='k')

f:id:mathgeekjp:20170910213946p:plain

参考

1.shop.oreilly.com

  1. machinelearningmastery.com