XGLBoostを使用したデータ準備(LabelEncoder,One Hot Encode,欠落値の処理)


XGBoostはその速度と性能のために流行している勾配増強実装である.
内部ではXGBoostモデルはすべての問題を数値のみを入力とする回帰予測モデリング問題として表す.データが別の形式の場合は、予想されるフォーマットに準備する必要があります.
この文書では、PythonのXGBoostライブラリを使用して勾配強化のためにデータを準備する方法について説明します.
この文章を読むとわかります.
分類符号化文字列に変数を出力する方法.onehotを使用して分類入力変数を準備する方法.XGBoostを使用して、失われたデータを自動的に処理する方法.
始めましょう.
ラベルエンコーディング文字列クラス値
アヤメの分類問題は文字列クラス値を持つ問題の例である.
これは,センチメートル単位のアヤメの測定値を与え,与えられた花がどの種に属するかを予測することを任務とする予測問題である.
次に、元のデータセットの例を示します.このデータセットの詳細については、UCIマシンラーニングリポジトリからCSV形式の元のデータをダウンロードしてください.
5.1,3.5,1.4,0.2,Iris-setosa
4.9,3.0,1.4,0.2,Iris-setosa
4.7,3.2,1.3,0.2,Iris-setosa
4.6,3.1,1.5,0.2,Iris-setosa
5.0,3.6,1.4,0.2,Iris-setosa

XGBoostは、出力変数が数値であることが要求されるため、この問題をそのままモデリングすることはできません.
LabelEncoderを使用すると、文字列値を整数値に簡単に変換できます.これら3つのクラス値(アヤメ−setosa,アヤメ−versicolor,アヤメ−virginica)は、整数値(0,1,2)にマッピングされる.
# encode string class values as integers
label_encoder = LabelEncoder()
label_encoder = label_encoder.fit(Y)
label_encoded_y = label_encoder.transform(Y)

ラベルエンコーダを個別のオブジェクトとして保存し、同じ符号化スキームを使用してトレーニングデータセットを変換し、後でデータセットをテストおよび検証することができます.
次に、irisデータセットをロードする方法を示す完全な例を示します.なお、pandaは、文字列クラス値を処理するためにデータをロードするために使用されます.
# multiclass classification

import pandas
import xgboost
from sklearn import model_selection
from sklearn.metrics import accuracy_score
from sklearn.preprocessing import LabelEncoder

# load data
data = pandas.read_csv('iris.csv', header=None)
dataset = data.values

# split data into X and y
X = dataset[:,0:4]
Y = dataset[:,4]

# encode string class values as integers
label_encoder = LabelEncoder()
label_encoder = label_encoder.fit(Y)
label_encoded_y = label_encoder.transform(Y)
seed = 7
test_size = 0.33
X_train, X_test, y_train, y_test = cross_validation.train_test_split(X, label_encoded_y, test_size=test_size, random_state=seed)

# fit model no training data
model = xgboost.XGBClassifier()
model.fit(X_train, y_train)
print(model)

# make predictions for test data
y_pred = model.predict(X_test)
predictions = [round(value) for value in y_pred]

# evaluate predictions
accuracy = accuracy_score(y_test, predictions)
print("Accuracy: %.2f%%" % (accuracy * 100.0))

この例を実行すると、次の出力が生成されます.
XGBClassifier(base_score=0.5, colsample_bylevel=1, colsample_bytree=1,
       gamma=0, learning_rate=0.1, max_delta_step=0, max_depth=3,
       min_child_weight=1, missing=None, n_estimators=100, nthread=-1,
       objective='multi:softprob', reg_alpha=0, reg_lambda=1,
       scale_pos_weight=1, seed=0, silent=True, subsample=1)
Accuracy: 92.00%

XGBoostモデルはmulti:softprobターゲット(softmax loss functionの変形を使用してクラス確率をモデリングする)を使用して、多種類の分類問題を自動的にモデリングするように構成されていることに注意してください.これは,内部で出力クラスが自動的にonehot符号化に変換されることを示している.
One Hot Encode Categorical Data
一部のデータセットには、乳がんデータセットなどの分類データしか含まれていません.
このデータセットは乳がん生検の技術的詳細を記述し、予測任務は患者が癌の再発があるかどうかを予測することである.
次に、元のデータセットの例を示します.このデータセットの詳細については、UCIマシンラーニングリポジトリで確認し、mldataから入手できます.orgはCSV形式のデータセットをダウンロードします.
'40-49','premeno','15-19','0-2','yes','3','right','left_up','no','recurrence-events'
'50-59','ge40','15-19','0-2','no','1','right','central','no','no-recurrence-events'
'50-59','ge40','35-39','0-2','no','2','left','left_low','no','recurrence-events'
'40-49','premeno','35-39','0-2','yes','3','right','left_low','yes','no-recurrence-events'
'40-49','premeno','30-34','3-5','yes','2','left','right_up','no','recurrence-events'

9つの入力変数がすべて分類され、文字列形式で記述されていることがわかります.この問題は二分類予測問題であり,出力クラス値も文字列フォーマットで記述する.
前節の同じ方法を再利用し,文字列クラス値を整数値に変換してLabelEncoderを用いて予測をモデリングすることができる.例:
# encode string class values as integers
label_encoder = LabelEncoder()
label_encoder = label_encoder.fit(Y)
label_encoded_y = label_encoder.transform(Y)

X内の各入力特性に対して同じ方法を用いることができるが,これはただの起点である.
# encode string input values as integers
features = []
for i in range(0, X.shape[1]):
	label_encoder = LabelEncoder()
	feature = label_encoder.fit_transform(X[:,i])
	features.append(feature)
encoded_x = numpy.array(features)
encoded_x = encoded_x.reshape(X.shape[0], X.shape[1])

XGBoostは、各入力変数の符号化整数値にシーケンス番号関係があると仮定することができる.例えば、「left-up」を0に符号化し、「left-low」を1に符号化するbreast-quad変数は整数形式の有意義な関係を有する.この場合、この仮定は正しくありません.
逆に,これらの整数値を新しいバイナリ変数にマッピングし,各分類値は新しい変数に対応する必要がある.
たとえば、breast-quad変数には次の値があります.
left-up
left-low
right-up
right-low
central

5つのバイナリ変数としてモデリングできます.
left-up, left-low, right-up, right-low, central
1,0,0,0,0
0,1,0,0,0
0,0,1,0,0
0,0,0,1,0
0,0,0,0,1

これをホットコーディングといいます.scikit-learnのOneHotEncoderクラスを使用して、すべての分類入力変数をホットコーディングできます.
ラベル符号化後に各特性を熱符号化することができる.まず,各整数値が長さ1の特徴ベクトルである2次元NumPy配列に特徴配列を変換しなければならない.
feature = feature.reshape(X.shape[0], 1)

その後、OneHotEncoderを作成し、プロパティ配列をエンコードできます.
onehot_encoder = OneHotEncoder(sparse=False)
feature = onehot_encoder.fit_transform(feature)

最後に、熱符号化特性を次々と接続し、新しい列(axis=2)として追加することで、入力データセットを構築することができる.最終的に43個のバイナリ入力変数からなる入力ベクトルを得た.
# encode string input values as integers
encoded_x = None
for i in range(0, X.shape[1]):
	label_encoder = LabelEncoder()
	feature = label_encoder.fit_transform(X[:,i])
	feature = feature.reshape(X.shape[0], 1)
	onehot_encoder = OneHotEncoder(sparse=False)
	feature = onehot_encoder.fit_transform(feature)
	if encoded_x is None:
		encoded_x = feature
	else:
		encoded_x = numpy.concatenate((encoded_x, feature), axis=1)
print("X shape: : ", encoded_x.shape)

理想的には、最初のカラムageの値が「40〜49」および「50〜59」のような明示的な順序関係で符号化できるため、1つの熱符号化を使用していくつかの入力属性を符号化しないことを試みることができる.この例を拡張することに興味がある場合は、練習として使用できます.
次に、ラベルと熱符号化入力変数とラベル符号化出力変数の完全な例を示します.
# binary classification, breast cancer dataset, label and one hot encoded

import numpy
from pandas import read_csv
from xgboost import XGBClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OneHotEncoder

# load data
data = read_csv('datasets-uci-breast-cancer.csv', header=None)
dataset = data.values

# split data into X and y
X = dataset[:,0:9]
X = X.astype(str)
Y = dataset[:,9]

# encode string input values as integers
encoded_x = None
for i in range(0, X.shape[1]):
	label_encoder = LabelEncoder()
	feature = label_encoder.fit_transform(X[:,i])
	feature = feature.reshape(X.shape[0], 1)
	onehot_encoder = OneHotEncoder(sparse=False)
	feature = onehot_encoder.fit_transform(feature)
	if encoded_x is None:
		encoded_x = feature
	else:
		encoded_x = numpy.concatenate((encoded_x, feature), axis=1)
print("X shape: : ", encoded_x.shape)

# encode string class values as integers
label_encoder = LabelEncoder()
label_encoder = label_encoder.fit(Y)
label_encoded_y = label_encoder.transform(Y)

# split data into train and test sets
seed = 7
test_size = 0.33
X_train, X_test, y_train, y_test = train_test_split(encoded_x, label_encoded_y, test_size=test_size, random_state=seed)

# fit model no training data
model = XGBClassifier()
model.fit(X_train, y_train)
print(model)

# make predictions for test data
y_pred = model.predict(X_test)
predictions = [round(value) for value in y_pred]

# evaluate predictions
accuracy = accuracy_score(y_test, predictions)
print("Accuracy: %.2f%%" % (accuracy * 100.0))

この例を実行すると、次の出力が得られます.
('X shape: : ', (285, 43))
XGBClassifier(base_score=0.5, colsample_bylevel=1, colsample_bytree=1,
       gamma=0, learning_rate=0.1, max_delta_step=0, max_depth=3,
       min_child_weight=1, missing=None, n_estimators=100, nthread=-1,
       objective='binary:logistic', reg_alpha=0, reg_lambda=1,
       scale_pos_weight=1, seed=0, silent=True, subsample=1)
Accuracy: 71.58%

同様に,XGBoostフレームワークが自動的に「binary:logistic」ターゲットを選択していることがわかり,これはこのバイナリ分類問題の正しいターゲットである.
欠落データの処理
XGBoostでは、失われたデータの処理方法を自動的に学習できます.
実際、XGBoostは、前のセクションの熱符号化データと同様に、損失関数を最小化することによって、損失データを処理するために、疎データまたはゼロ値を処理するように設計されている.
Horse Colic datasetは、失われたデータが約30%含まれる良い例です.
Horse Colicデータセットの詳細については、UCIマシンラーニングリポジトリから元のデータファイルをダウンロードしてください.
これらの値はスペースで区切られており、panda関数read_を使用できます.csvは簡単にロードできます.
dataframe = read_csv("horse-colic.csv", delim_whitespace=True, header=None)

ロードすると、欠落したデータが疑問符('?')でマークされていることがわかります.これらの欠落した値をXGBoostが望む疎値、すなわち0(0)に変更することができる.
# set missing values to 0
X[X == '?'] = 0

欠落したデータは文字列としてマークされるため、欠落したデータの列は文字列データ型としてロードされます.入力データセット全体を数値に変換できます.
# convert to numeric
X = X.astype('float32')

最後に,クラス値は整数1と2で表記されるが,これはバイナリ分類問題である.XGBoostにおける二元分類問題をlogistic 0とlogistic 1としてモデル化した.LabelEncoderを使用して、iris flowersの例で行ったように、Yデータセットを0と1の整数に簡単に変換できます.
# encode Y class values as integers
label_encoder = LabelEncoder()
label_encoder = label_encoder.fit(Y)
label_encoded_y = label_encoder.transform(Y)

完全化のため、以下に完全なコードリストを提供します.
# binary classification, missing data

from pandas import read_csv
from xgboost import XGBClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.preprocessing import LabelEncoder

# load data
dataframe = read_csv("horse-colic.csv", delim_whitespace=True, header=None)
dataset = dataframe.values

# split data into X and y
X = dataset[:,0:27]
Y = dataset[:,27]

# set missing values to 0
X[X == '?'] = 0

# convert to numeric
X = X.astype('float32')

# encode Y class values as integers
label_encoder = LabelEncoder()
label_encoder = label_encoder.fit(Y)
label_encoded_y = label_encoder.transform(Y)

# split data into train and test sets
seed = 7
test_size = 0.33
X_train, X_test, y_train, y_test = train_test_split(X, label_encoded_y, test_size=test_size, random_state=seed)

# fit model no training data
model = XGBClassifier()
model.fit(X_train, y_train)
print(model)

# make predictions for test data
y_pred = model.predict(X_test)
predictions = [round(value) for value in y_pred]

# evaluate predictions
accuracy = accuracy_score(y_test, predictions)
print("Accuracy: %.2f%%" % (accuracy * 100.0))

この例を実行すると、次の出力が生成されます.
XGBClassifier(base_score=0.5, colsample_bylevel=1, colsample_bytree=1,
       gamma=0, learning_rate=0.1, max_delta_step=0, max_depth=3,
       min_child_weight=1, missing=None, n_estimators=100, nthread=-1,
       objective='binary:logistic', reg_alpha=0, reg_lambda=1,
       scale_pos_weight=1, seed=0, silent=True, subsample=1)
Accuracy: 83.84%

欠落値を0以外の値(例えば1)でマークすることで,XGBoostが欠落値を自動的に処理する効果を整理することができる.
X[X == '?'] = 1

この例を再実行すると,モデルの精度が低下したことを示した.
Accuracy: 79.80%

また、欠落したデータに特定の値を与えることもできます.
通常、カラムには平均値または中央値が使用されます.欠落したデータをscikit-learn Imputerクラスを使用して簡単に集計できます.
# impute missing values as the mean
imputer = Imputer()
imputed_x = imputer.fit_transform(X)

次に、欠落したデータが各カラムの平均値で入力される完全な例を示します.
# binary classification, missing data, impute with mean

import numpy
from pandas import read_csv
from xgboost import XGBClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import Imputer

# load data
dataframe = read_csv("horse-colic.csv", delim_whitespace=True, header=None)
dataset = dataframe.values

# split data into X and y
X = dataset[:,0:27]
Y = dataset[:,27]

# set missing values to 0
X[X == '?'] = numpy.nan

# convert to numeric
X = X.astype('float32')

# impute missing values as the mean
imputer = Imputer()
imputed_x = imputer.fit_transform(X)

# encode Y class values as integers
label_encoder = LabelEncoder()
label_encoder = label_encoder.fit(Y)
label_encoded_y = label_encoder.transform(Y)

# split data into train and test sets
seed = 7
test_size = 0.33
X_train, X_test, y_train, y_test = train_test_split(imputed_x, label_encoded_y, test_size=test_size, random_state=seed)

# fit model no training data
model = XGBClassifier()
model.fit(X_train, y_train)
print(model)

# make predictions for test data
y_pred = model.predict(X_test)
predictions = [round(value) for value in y_pred]

# evaluate predictions
accuracy = accuracy_score(y_test, predictions)
print("Accuracy: %.2f%%" % (accuracy * 100.0))

この例を実行すると、値を1(1)に固定することに相当します.これは、少なくともこの場合、有効値(1)または入力値ではなく、欠落した値を0(0)とマークすることが望ましいことを示している.
Accuracy: 79.80%

データに値が欠けている場合は、この2つの方法(自動処理と入力)を試してみるのが良い教訓です.
まとめ
この記事では、PythonのXGBoostを使用して勾配増強のためにマシン学習データを準備する方法を発見しました.
具体的には、
ラベル符号化を使用してバイナリ分類に文字列クラス値を準備する方法.分類入力変数をバイナリ変数として熱符号化モデルを使用する方法.XGBoostは、失われたデータを自動的に処理する方法と、失われた値をマークして入力する方法です.
原文の出典