You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Sklearn的Mean Shift聚类中替换Flat核为Gaussian核或Joint核?

嘿,我来帮你搞定这个问题!Sklearn的MeanShift默认确实用的是flat(均匀)核,但要换成高斯核或者联合核完全是可行的,我给你分步骤讲清楚,代码示例都给你写好,新手也能跟着做~

用Sklearn实现高斯核Mean Shift

Sklearn官方的MeanShift类本身没有直接提供切换核函数的参数,但我们有两种方式实现高斯核的Mean Shift:

方法一:用高斯核估算带宽(简单快速)

这种方式是利用estimate_bandwidth函数的高斯核来估算合适的带宽值,再传给MeanShift。虽然算法内部还是用flat核,但带宽是基于高斯核特性估算的,能间接达到类似高斯核聚类的效果,适合快速上手:

from sklearn.cluster import MeanShift, estimate_bandwidth
from sklearn.datasets import make_blobs

# 生成示例聚类数据(你可以替换成自己的数据)
X, _ = make_blobs(n_samples=300, centers=3, cluster_std=0.6, random_state=42)

# 用高斯核估算带宽:quantile控制样本占比,值越小带宽越小,聚类越细
bandwidth = estimate_bandwidth(X, quantile=0.2, kernel='gaussian')

# 初始化MeanShift,传入估算好的带宽
ms = MeanShift(bandwidth=bandwidth)
ms.fit(X)

# 获取聚类结果
labels = ms.labels_
cluster_centers = ms.cluster_centers_

方法二:自定义高斯核MeanShift类(真正替换核函数)

如果你想完全替换算法内部的核函数为高斯核,我们可以继承MeanShift类,重写它的核心计算方法,直接用高斯核来计算权重:

import numpy as np
from sklearn.cluster import MeanShift
from sklearn.datasets import make_blobs
from sklearn.metrics.pairwise import rbf_kernel

class GaussianMeanShift(MeanShift):
    def _mean_shift_single_seed(self, X, seed_idx):
        n_samples, n_features = X.shape
        center = X[seed_idx].copy()
        while True:
            # 用高斯核(RBF核)计算每个样本的权重,gamma=1/(带宽²)是标准高斯核的参数
            weights = rbf_kernel(X, [center], gamma=1/(self.bandwidth**2)).flatten()
            # 计算加权均值作为新的聚类中心
            new_center = np.average(X, axis=0, weights=weights)
            # 检查是否收敛(新旧中心的距离小于阈值)
            if np.linalg.norm(new_center - center) < self.tol:
                break
            center = new_center
        return center, np.sum(weights)

# 生成数据
X, y_true = make_blobs(n_samples=300, centers=3, cluster_std=0.60, random_state=42)

# 用高斯核估算带宽(也可以手动指定固定带宽)
bandwidth = estimate_bandwidth(X, quantile=0.2, kernel='gaussian')

# 初始化自定义的高斯核MeanShift
gms = GaussianMeanShift(bandwidth=bandwidth, tol=1e-6)
gms.fit(X)

# 获取结果
labels = gms.labels_
cluster_centers = gms.cluster_centers_
实现联合核Mean Shift

如果你说的Joint kernel是指结合多种核函数(比如同时用flat核和高斯核),我们可以在自定义类里把两种核的权重结合起来,比如按比例加权:

class JointMeanShift(MeanShift):
    def _mean_shift_single_seed(self, X, seed_idx):
        n_samples, n_features = X.shape
        center = X[seed_idx].copy()
        # 调整alpha可以控制两种核的占比,0<=alpha<=1
        alpha = 0.5
        while True:
            # 计算flat核权重:距离小于带宽的样本权重为1,否则为0
            distances = np.linalg.norm(X - center, axis=1)
            flat_weights = (distances < self.bandwidth).astype(float)
            # 计算高斯核权重
            gaussian_weights = rbf_kernel(X, [center], gamma=1/(self.bandwidth**2)).flatten()
            # 联合权重:flat核和高斯核的加权平均
            joint_weights = alpha * flat_weights + (1 - alpha) * gaussian_weights
            # 更新聚类中心
            new_center = np.average(X, axis=0, weights=joint_weights)
            if np.linalg.norm(new_center - center) < self.tol:
                break
            center = new_center
        return center, np.sum(joint_weights)

# 使用方式和之前一样
bandwidth = estimate_bandwidth(X, quantile=0.2, kernel='gaussian')
jms = JointMeanShift(bandwidth=bandwidth, tol=1e-6)
jms.fit(X)
新手小贴士
  • 带宽(bandwidth)是Mean Shift最关键的参数,estimate_bandwidth的quantile参数可以调整:值越小,带宽越小,聚类数量越多;值越大,带宽越大,聚类数量越少。
  • 如果你有自己的数据集,只需要把示例中的X换成你的特征矩阵即可(注意要做标准化处理哦,避免特征尺度差异影响聚类效果)。
  • 自定义类的时候,可以根据需求修改核函数的组合方式,比如换成其他核(比如多项式核),只要调整权重计算部分就行。

内容的提问来源于stack exchange,提问作者Mahle_Nick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:20:26