ワンホットエンコーディング(ダミー変数)
Overview
連続値特徴量(ピクセルの明るさ、花の大きさを測定した値など)に対して、離散値特徴量(製品のブランドや色、部門など)は一般に数値ではありません。また、離散値特徴量はカテゴリ特徴量やカテゴリ変数とも呼ばれます。
カテゴリ変数を表現する方法として、圧倒的によく用いられる手法が、ワンホットエンコーディング(one-hot-encodingもしくはone-out-of-N encoding)です。ダミー変数と呼ばれることもあります。ダミー変数とは、カテゴリ変数を1つ以上の0と1の値を持つ新しい特徴量で置き換えるものです。
Coding
pandasでカテゴリ変数をワンホットエンコーディングで数値に変換する
code: Python
import pandas as pd
# このファイルにはカラム名を含んだヘッダがないので、header=Noneを指定し、カラム名をnamesで明示的に指定
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',
'marital-status', 'occupation', 'relationship', 'race', 'gender',
'capital-gain', 'capital-loss', 'hours-per-week', 'native-country',
'income'])
data.head()
https://gyazo.com/2036c082b32ad4efcbbfe13d6816bc18
pandasのDataFrame中の行を表すSeriesクラスの関数value_countsを用いて、各行に含まれているユニークな値とその頻度を標示してみます。
code: Python
print(data.gender.value_counts())
--------------------------------------------------------------------------
Male 21790
Female 10771
Name: gender, dtype: int64
--------------------------------------------------------------------------
genderには「Male」と「Female」しか含まれていないことがわかります。例えば、性別には「man」、「male」、「Man」、「Male」など様々な書き方があるのでこれらは統一しないといけません。このデータに関しては、既に整理されているということなので、ワンホットエンコーディングできます。
pandasでは、get_dummies関数を使って簡単にデータをワンホットエンコーディングできます。
code: Python
data_dummies = pd.get_dummies(data)
# ターゲット変数(正解ラベル)は、分離する
# NumPy配列のスライスとは違って、最後のインデックスも取る
X = features.values
print('X.shape: {} y.shape: {}'.format(X.shape, y.shape))
--------------------------------------------------------------------------
X.shape: (32561, 108) y.shape: (32561,)
--------------------------------------------------------------------------
これでデータが数値になったので、学習を進めることができます。
code: Python
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
logreg = LogisticRegression()
logreg.fit(X_train, y_train)
print('Test score: {:.2f}'.format(logreg.score(X_test, y_test)))
--------------------------------------------------------------------------
Test score: 0.80
--------------------------------------------------------------------------