11
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

特徴量エンジニアリングの手法としてのクラスタリング(とX-meansによる最適なクラスタ数の導入)

Posted at

はじめに

前回、Votingと言うアルゴリズムを使い、タイタニックに果敢に挑戦しましたが、あまりいい精度とは言えませんでした。

僕「なぜ精度が出ないんだ? 最強のアルゴリズムを使っているはずなのに。」
???「特徴量エンジニアリングをするとよいでしょう。」

※注意※ 

機械学習のための特徴量エンジニアリングの7章「非線形特徴量の生成:k-meansを使ったスタッキング」を読んだ勢いで書いた記事です。

クラスタリングとは

教師なし学習と呼ばれる機械学習の手法の一つで、正解ラベルが与えられていないデータ群を分類してくれる手法です。

今回はこのクラスタリングにより、適当 適切に処理したデータを分類し、新しい特徴量として学習させます。
※使用するライブラリはsklearnのKMeansになります。

タイタニックでやってみる

##ソース


import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from sklearn.model_selection import StratifiedKFold
from sklearn.cluster import KMeans

# X-meansを使用しない場合不要です。
# Kaggleで使用する際、pip等で[pyclustering]をインストールする必要があります。
from pyclustering.cluster.xmeans import xmeans, kmeans_plusplus_initializer
from pyclustering.utils import draw_clusters

# 〜〜〜データ処理部〜〜〜

# 後工程でデータを分けるために使用
train["tmp"] = "train"
test["tmp"] = "test"

# 変数を生成するために一時的にtrainとtestを結合
conb = pd.concat([train.drop(["Survived","PassengerId"],axis=1),test.drop("PassengerId",axis=1)])

# データ処理のためにpandasからnp.arrayに変換
conb_array = np.array(conb[conb.columns[1]].tolist())
for i in range(len(conb.columns)):
    if i <= 1:
        continue
    if conb.columns[i]=="tmp":
        continue
    conb_array = np.vstack((conb_array,conb[conb.columns[i]]))
conb_array = conb_array.T

# クラスタリングを行います。
# 変数 cluster_point は分類するクラスタの数を指定します。
# 2以上の任意の整数を指定してください。
cluster_point = 10
pred = KMeans(n_clusters=cluster_point).fit_predict(conb_array)
conb["cluster"] = pred

# trainとtestに再分割
train["cluster"] = conb[conb["tmp"]=="train"]["cluster"]
test["cluster"] = conb[conb["tmp"]=="test"]["cluster"]
train.drop("tmp",axis=1,inplace=True)
test.drop("tmp",axis=1,inplace=True)

ソース

「あ、あれ・・・? スコアが0.746までさがった・・・?」
前回のスコアは0.765

原因を考える

「データ処理はクラスタの情報以外追加していないはず・・・」
「なのにスコアが大きく低下すると言うことは分類するクラスタ数が悪いのか?」
「適切なクラスタ数か。。。自動でやってくれるようなツールはないかな」

X-meansについて

k-meansの拡張で、k-meansによる計算を複数回繰り返すことによって最適なクラスタ数を探し出すと言うアルゴリズム、、、みたいです(自分の理解)

ソース

# 後工程でデータを分けるために使用
train["tmp"] = "train"
test["tmp"] = "test"

# 変数を生成するために一時的にtrainとtestを結合
conb = pd.concat([train.drop(["Survived","PassengerId"],axis=1),test.drop("PassengerId",axis=1)])

# データ処理のためにpandasからnp.arrayに変換
conb_array = np.array(conb[conb.columns[1]].tolist())
for i in range(len(conb.columns)):
    if i <= 1:
        continue
    if conb.columns[i]=="tmp":
        continue
    conb_array = np.vstack((conb_array,conb[conb.columns[i]]))
conb_array = conb_array.T

# X-meansによるクラスタ数の計算
initial_centers = kmeans_plusplus_initializer(conb_array, 2).initialize()
instances = xmeans(conb_array, initial_centers, ccore=True)
instances.process()
clusters = instances.get_clusters()

# 各クラスタの中心の数を求める
centers = []
conb_array = np.array(conb_array)
for cluster in clusters:
    c = conb_array[cluster, :]
    centers.append(np.mean(c, axis=0))

# cluster_point = 10   
cluster_point = len(centers)

pred = KMeans(n_clusters=cluster_point).fit_predict(conb_array)
conb["cluster"] = pred

# trainとtestに再分割
train["cluster"] = conb[conb["tmp"]=="train"]["cluster"]
test["cluster"] = conb[conb["tmp"]=="test"]["cluster"]
train.drop("tmp",axis=1,inplace=True)
test.drop("tmp",axis=1,inplace=True)

ソース

「よっしゃ!スコアが0.765まで上がったぜ!」
「あれ?」
前回のスコアは0.765

まとめ

クラスタリングを用いた特徴量生成を行ってみました。
Qiita記事用に適当な前処理しか行っていなかったためか、パラメータチューニングが甘かったためか、
あまり精度は出ませんでしたが、他のコンペでは若干スコアが上がりました。

すべてのデータに当てはまるわけではないですが、一つの手段として覚えておく価値はあると思います。

参考文献

  • 機械学習のための特徴量エンジニアリング ――その原理とPythonによる実践
    Alice Zheng、Amanda Casari 著、株式会社ホクソエム 訳
    リンク

  • 【Python】 x-meansを使ってクラスタリングする例
    リンク

11
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?