自定义 k-means 聚类 GridSearchCV

Posted

技术标签:

【中文标题】自定义 k-means 聚类 GridSearchCV【英文标题】:Custom k-means clustering GridSearchCV 【发布时间】:2020-07-28 09:23:02 【问题描述】:

我试图通过使用管道为 k-means 聚类找到 k 的“最佳”值,在该管道中,我使用标准缩放器,然后是自定义 k-means,最后是决策树分类器。然后,我尝试将此管道用于网格搜索,以获得k 的最佳值。正在使用 Python 3.7 和 sklearn。

我的代码如下:

from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import make_blobs
from sklearn.pipeline import Pipeline

import numpy as np
import matplotlib.pyplot as plt

from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.cluster import KMeans
from sklearn.preprocessing import OneHotEncoder
from sklearn.model_selection import GridSearchCV, RandomizedSearchC


class KMeansTransformer(BaseEstimator, TransformerMixin):

    def __init__(self, **kwargs):
        # The purpose of 'self.model' is to contain the
        # underlying cluster model-
        self.model = KMeans(**kwargs)
        

    def fit(self, X):
        self.X = X
        self.model.fit(X)


    def transform(self, X):
        pred = self.model.predict(X)
        return np.hstack([self.X, pred.reshape(-1, 1)])


    def fit_transform(self, X, y=None):
        self.fit(X)
        return self.transform(X)


# Create features and target-
X, y = make_blobs(n_samples=100, n_features=2, centers=3)

# Get shape/dimension-
X.shape, y.shape
# ((100, 2), (100,))


# Create another pipeline using Decision Tree as classifier-
pipe_dt = Pipeline(
    [
        ('sc', StandardScaler()),
        ('kmt', KMeansTransformer()),
        ('dt_clf', DecisionTreeClassifier())
    ]
)

# Train defined pipline-
pipe_dt.fit(X, y)

# Get accuracy score of pipeline-
pipe_dt.score(X, y)
# 1.0

# Make predictions using pipeline defined above-
y_pred_dt = pipe_dt.predict(X)


# Perform hyperparameter search/optimization using 'GridSearchCV'-
# Specify parameters to be hyper-tuned-
params = 
            'n_clusters': [2, 3, 5, 7]
            

# Initialize GridSearchCV() object using 3-fold CV-
grid_kmt = GridSearchCV(param_grid=params, estimator=pipe_dt, cv = 3)

# Perform GridSearchCV on training data-
grid_kmt.fit(X, y)

当我使用 'grid_kmt.fit(X, y)' 时,它给了我以下错误:

ValueError:估计器的参数 n_clusters 无效 管道(内存=无, 步骤= [('sc', StandardScaler(copy=True, with_mean=True, with_std=True)), ('kmt', KMeansTransformer()), ('dt_clf', 决策树分类器(ccp_alpha=0.0,class_weight=None, 标准='gini',最大深度=无, max_features=无,max_leaf_nodes=无, min_impurity_decrease=0.0, min_impurity_split=无, min_samples_leaf=1, min_samples_split=2, min_weight_fraction_leaf=0.0, presort='不推荐使用',random_state=None, 拆分器='最佳'))], 详细=假)。检查可用参数列表 estimator.get_params().keys().

但是,当我为自定义 kmeans 初始化一个对象时-

# Initialize a new clustering object-
km = KMeansTransformer(n_clusters=3, init = 'k-means++')

# Get the list of available parameters-
km.get_params().keys()                                                  
# dict_keys([])

那为什么我会收到“ValueError”? n_clusters 恰好在自定义聚类对象的可用参数列表中。

【问题讨论】:

【参考方案1】:

仔细查看错误信息:

ValueError: Invalid parameter n_clusters for estimator Pipeline [...]

很明显,您的GridSearchCV 在管道本身(不是在其组件中)查找参数n_clusters,找不到任何参数,并返回错误。要正确访问('kmt', KMeansTransformer()) 组件的n_clusters 参数,您应该使用

params = 
            'kmt__n_clusters': [2, 3, 5, 7]  # two underscores
            

当然前提是您自己的KMeansTransformer 确实接受参数n_clusters

【讨论】:

以上是关于自定义 k-means 聚类 GridSearchCV的主要内容,如果未能解决你的问题,请参考以下文章

在 Apache Spark Python 中自定义 K-means 的距离公式

覆盖聚类算法中的距离度量

☀️机器学习入门☀️ 图解K-Means聚类算法 | 附加小练习

K-means聚类分析案例(二)

Spark 的 MLlib 库中预定义的 Streaming k-means 聚类是有监督的还是无监督的?

聚类算法(K-Means)