在处理包含数百万数据点的大型数据集时,聚类可能会变得非常昂贵。许多聚类算法不具备归纳能力,这意味着它们不能直接应用于新数据样本而不重新计算聚类,这可能是不切实际的。相反,可以使用聚类来学习一个分类器的归纳模型,这样做有几个好处:它允许聚类扩展并应用于新数据;与重新拟合新样本的聚类不同,它确保了标签过程随时间的一致性;它允许使用分类器的推理能力来描述或解释聚类。
以下示例展示了一个通用的元估计器实现,它通过从聚类标签中归纳出一个分类器来扩展聚类。这种方法不仅能够处理大规模数据,还能够确保对新数据的分类是一致的,并且可以利用分类器的推理能力来解释聚类。
首先,需要导入必要的库和模块。这包括用于数据可视化的matplotlib.pyplot,以及scikit-learn库中的各种组件,如BaseEstimator、clone、AgglomerativeClustering、make_blobs、RandomForestClassifier等。
import matplotlib.pyplot as plt
from sklearn.base import BaseEstimator, clone
from sklearn.cluster import AgglomerativeClustering
from sklearn.datasets import make_blobs
from sklearn.ensemble import RandomForestClassifier
from sklearn.inspection import DecisionBoundaryDisplay
from sklearn.utils.metaestimators import available_if
from sklearn.utils.validation import check_is_fitted
接下来,定义了一个名为InductiveClusterer的类,它继承自BaseEstimator。这个类有两个主要的属性:clusterer和classifier,分别用于聚类和分类。在fit方法中,首先克隆传入的聚类器和分类器,然后使用聚类器对数据进行拟合和预测,得到聚类标签。接着,使用这些标签来训练分类器。
class InductiveClusterer(BaseEstimator):
def __init__(self, clusterer, classifier):
self.clusterer = clusterer
self.classifier = classifier
def fit(self, X, y=None):
self.clusterer_ = clone(self.clusterer)
self.classifier_ = clone(self.classifier)
y = self.clusterer_.fit_predict(X)
self.classifier_.fit(X, y)
return self
@available_if(_classifier_has("predict"))
def predict(self, X):
check_is_fitted(self)
return self.classifier_.predict(X)
@available_if(_classifier_has("decision_function"))
def decision_function(self, X):
check_is_fitted(self)
return self.classifier_.decision_function(X)
为了可视化聚类结果,定义了一个名为plot_scatter的函数,它使用matplotlib的scatter方法来绘制散点图。还生成了一些用于聚类的训练数据,并使用AgglomerativeClustering算法对这些数据进行聚类,得到聚类标签。然后,使用这些标签来训练一个随机森林分类器,并使用InductiveClusterer类来预测新样本的聚类成员资格。
def plot_scatter(X, color, alpha=0.5):
return plt.scatter(X[:,0], X[:,1], c=color, alpha=alpha, edgecolor='k')
# 生成一些用于聚类的训练数据
X, y = make_blobs(n_samples=5000, cluster_std=[1.0, 1.0, 0.5], centers=[(-5, -5), (0, 0), (5, 5)], random_state=42)
# 使用AgglomerativeClustering算法对训练数据进行聚类,并得到聚类标签
clusterer = AgglomerativeClustering(n_clusters=3)
cluster_labels = clusterer.fit_predict(X)
plt.figure(figsize=(12, 4))
plt.subplot(131)
plot_scatter(X, cluster_labels)
plt.title("Ward Linkage")
# 生成一些新的样本,并与原始数据集一起绘制
X_new, y_new = make_blobs(n_samples=10, centers=[(-7, -1), (-2, 4), (3, 6)], random_state=42)
plt.subplot(132)
plot_scatter(X, cluster_labels)
plot_scatter(X_new, "black", 1)
plt.title("Unknown instances")
# 声明归纳学习模型,用于预测未知实例的聚类成员资格
classifier = RandomForestClassifier(random_state=42)
inductive_learner = InductiveClusterer(clusterer, classifier).fit(X)
probable_clusters = inductive_learner.predict(X_new)
ax = plt.subplot(133)
plot_scatter(X, cluster_labels)
plot_scatter(X_new, probable_clusters)
# 绘制决策区域
DecisionBoundaryDisplay.from_estimator(inductive_learner, X, response_method="predict", alpha=0.4, ax=ax)
plt.title("Classify unknown instances")
plt.show()
这个脚本的总运行时间为2.190秒。可以通过以下链接下载Jupyter笔记本和Python源代码。