はじめに
2年以上前に流行っていた[1]らしいXGBoost[2]をいまさら試してみました。勾配ブースティング決定木(Gradient boosting decision tree)と呼ばれている手法です。手法自体の説明は探すと色々出てきますので、そちらを参照ください。今回は、回帰問題と識別問題を簡単なデータで試してみます。インストール
基本的には[2] を参考にインストールします。今回はWindows+VC2015のコマンドラインツールがインストールされている環境下で試しました。ソースコードの入手までは出来ている状態で、まず、VS2015 x64 Native Tools Command Prompt を立ち上げ、次のコマンドを実行すると、xgboostをビルドできます。vcvarsall amd64 cd (path to xgboost) mkdir build64 cd build64 cmake .. -G "Visual Studio 14 2015 Win64" cmake --build . --config ReleasePython環境下で利用するために、
cd (path to xgboost) cd python-package python setup.py installを実行します。これで、import xgboostが使えるようになります。
回帰
回帰には、XGBRegressorを利用します。実験データは正弦波にノイズを加えたものです。コード
コードは次の通りです。%matplotlib inline
import xgboost as xgb
import numpy as np
import matplotlib.pyplot as plt
from IPython import display
from IPython.display import HTML
x = []
y = []
for i in range(2):
xi = np.linspace(0,1,1000) + np.random.normal(0,0.1,1000)
yi = np.cos(xi*10) + np.random.normal(0,0.1,1000)
xi = xi.reshape(-1, 1)
yi = yi.reshape(-1, 1)
x.append(xi)
y.append(yi)
mod = xgb.XGBRegressor(learning_rate=0.1, max_depth=2, n_estimators=100)
mod.fit(x[0], y[0])
y_train_pred = mod.predict(x[0])
y_test_pred = mod.predict(x[1])
from sklearn.metrics import mean_squared_error
print('MSE train : {0:.3f}, test : {1:.3f}'.
format(mean_squared_error(y[0], y_train_pred),
mean_squared_error(y[1], y_test_pred)))
x_pred = np.linspace(-0.5,1.5,10000).reshape(-1, 1)
y_pred = mod.predict(x_pred)
#plt.scatter(x[0], y[0], s=1)
plt.scatter(x[1], y[1], s=1)
plt.plot(x_pred, y_pred, 'C3')
plt.show()
plt.close()
結果
Jupyter notebookで実行すると、以下のような結果が得られます。MSE train : 0.009, test : 0.013テストデータに対する回帰折れ線(?)は次のようになりました。ギザギザではありますが、中心付近を通過するように学習できていることが分かります。
識別
識別にはXGBClassifierを使います。データは、1個のガウス分布から1000個サンプリングした点をクラス-1、2個のガウス分布から500個ずつサンプリングした点をクラス1として作成しています。コード
コードは次の通りです。%matplotlib inline
import xgboost as xgb
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
from IPython import display
# Gaussian distribution for class -1
mu = [0, 0]
sigma = [[30, 0], [0, 50]]
x1 = np.random.multivariate_normal(mu, sigma, 1000) # Train
x1t = np.random.multivariate_normal(mu, sigma, 1000) # Test
# 2 Gaussian distribution for class 1
mu = [5, 5]
sigma = [[5, 0], [0, 3]]
x2 = np.random.multivariate_normal(mu, sigma, 500) # Train
x2t = np.random.multivariate_normal(mu, sigma, 500) # Test
mu = [-10, 15]
sigma = [[3, 2], [2, 3]]
x2 = np.concatenate([x2, np.random.multivariate_normal(mu, sigma, 500)]) # Train
x2t = np.concatenate([x2t, np.random.multivariate_normal(mu, sigma, 500)]) # Test
# Make labels of train and test
y = np.concatenate([np.ones(1000)*-1, np.ones(1000)*1])
# classify by xgboost
mod = xgb.XGBClassifier(
learning_rate=0.1,
max_depth=2, # Maximum depth of each tree
n_estimators=100) # The number of trees
x = np.concatenate([x1, x2])
xt = np.concatenate([x1t, x2t])
mod.fit(x, y)
y_pred = mod.predict(x)
yt_pred = mod.predict(xt)
from sklearn.metrics import accuracy_score
print('MSE train : {0:.3f}, test : {1:.3f}'.
format(accuracy_score(y, y_pred), accuracy_score(y, yt_pred)))
# Show boundaries between class -1 and 1
gx1 = np.linspace(-20, 20, 1000)
gx2 = np.linspace(-20, 20, 1000)
gx1, gx2 = np.meshgrid(gx1, gx2)
y = mod.predict(np.array([gx1, gx2]).T.reshape(-1, 2))
plt.scatter(x1t[:,0], x1t[:,1], s=0.2)
plt.scatter(x2t[:,0], x2t[:,1], s=0.2)
cm = LinearSegmentedColormap.from_list('cm', [(0, 'blue'),(1, 'blue')])
plt.contour(gx1, gx2, y.reshape(1000, -1).T, [0], alpha=1, cmap=cm)
plt.show()
結果
Jupyter notebookで実行すると、以下のような結果が得られます。MSE train : 0.926, test : 0.913クラス間の識別境界(青線)と、テストデータのクラス-1(青点)と1(橙点)の分布は次の図のようになります。決定木ベースなのでギザギザですが、見た目では分割できているように見えます。
参考
[1] http://smrmkt.hatenablog.jp/entry/2015/04/28/210039[2] http://xgboost.readthedocs.io/en/latest/build.html
0 件のコメント :
コメントを投稿