from sklearn.cluster import KMeansimport numpy as npimport matplotlib.pyplot as plt# 设置matplotlib支持中文显示plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文显示plt.rcParams['axes.unicode_minus'] = False # 正确显示负号# 假想数据集:金庸小说中的武林高手# 武力值和内力深浅X = np.array([[5, 8], [6, 9], [5, 6], # 东邪、西毒、南帝[8, 5], [9, 6], [7, 5], # 北丐、中神通、老顽童[1, 2], [2, 1]]) # 平民武者1、平民武者2# 应用K-均值聚类算法,设置簇的数量为3(高手、中等、平民)kmeans = KMeans(n_clusters=3, random_state=0).fit(X)# 预测每个样本所属的簇labels = kmeans.labels_# 打印每个簇的中心centers = kmeans.cluster_centers_# 可视化结果plt.scatter(X[:, 0], X[:, 1], c=labels, s=50, cmap='viridis')plt.scatter(centers[:, 0], centers[:, 1], c='red', s=200, alpha=0.5)plt.title("武林高手聚类")plt.xlabel("武力值")plt.ylabel("内力深浅")plt.show()
2 层次聚类(Hierarchical Clustering)
from scipy.cluster.hierarchy import dendrogram, linkagefrom matplotlib import pyplot as pltimport numpy as np# 构建数据集:金庸小说武侠人物的侠义值和武功高低X = np.array([[5, 8], [6, 9], [5, 6], # 侠义高,武功高[8, 5], [9, 6], [7, 5], # 侠义中,武功中[1, 2], [2, 1]]) # 侠义低,武功低# 使用凝聚的层次聚类linked = linkage(X, 'single')# 绘制树状图plt.figure(figsize=(10, 7))dendrogram(linked,orientation='top',labels=range(1, 9),distance_sort='descending',show_leaf_counts=True)plt.title('武侠人物层次聚类树状图')plt.xlabel('侠义值')plt.ylabel('距离')plt.show()
3 DBSCAN
from sklearn.cluster import DBSCANimport numpy as npimport matplotlib.pyplot as plt# 模拟大量数据集:不同门派高手(高密度区),散落江湖侠客(中密度区),游走江湖普通人(低密度区)np.random.seed(0) # 确保生成数据的一致性# 生成高密度区数据(大派高手)high_density = np.random.randn(100, 2) * 0.5 + [5, 5]# 生成中密度区数据(散落江湖侠客)medium_density = np.random.randn(50, 2) + [10, 10]# 生成低密度区数据(游走江湖普通人)low_density = np.random.randn(30, 2) * 2 + [0, 10]# 合并成一个数据集X = np.vstack((high_density, medium_density, low_density))# 添加一些噪声点noise = np.random.uniform(low=-5, high=15, size=(20, 2))X = np.vstack((X, noise))# 应用DBSCAN聚类dbscan = DBSCAN(eps=1.5, min_samples=5).fit(X)# 获取每个点的簇标号labels = dbscan.labels_# 可视化聚类结果plt.figure(figsize=(10, 6))plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis', s=50, alpha=0.6, edgecolor='k')plt.title('模拟江湖人物分布聚类')plt.xlabel('武力值')plt.ylabel('江湖影响力')plt.grid(True)plt.show()
4 高斯混合模型
from sklearn.mixture import GaussianMixtureimport numpy as npimport matplotlib.pyplot as plt# 设置随机种子,确保结果的可重复性np.random.seed(42)# 生成三组中心点较接近的高斯分布数据group1 = np.random.randn(100, 2) * 2 + [20, 20]group2 = np.random.randn(100, 2) * 3 + [25, 25]group3 = np.random.randn(100, 2) * 1.5 + [22, 30]# 合并这些数据集成一个大的数据集X = np.vstack((group1, group2, group3))# 应用GMM聚类gmm = GaussianMixture(n_components=3, random_state=0).fit(X)labels = gmm.predict(X)# 可视化聚类结果plt.figure(figsize=(10, 6))plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis', s=40, alpha=0.6, edgecolor='k')plt.title('样本混合的 GMM 聚类结果')plt.xlabel('特征 1')plt.ylabel('特征 2')plt.grid(True)plt.show()
GaussianMixture模型对数据进行了聚类,并且设置了n_components=3,意味着我们假设数据由3个高斯分布组成。5 谱聚类(Spectral Clustering)
from sklearn.datasets import make_moonsfrom sklearn.cluster import SpectralClusteringimport matplotlib.pyplot as plt# 生成“月亮形”数据X, y = make_moons(n_samples=300, noise=0.1, random_state=4)# 应用谱聚类sc = SpectralClustering(n_clusters=2, affinity='nearest_neighbors', random_state=42)labels = sc.fit_predict(X)# 可视化聚类结果plt.figure(figsize=(10, 6))plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis', s=50, alpha=0.6, edgecolor='k')plt.title('谱聚类聚类结果')plt.xlabel('特征 1')plt.ylabel('特征 2')plt.grid(True)plt.show()
make_moons 函数生成了具有两个“月亮形”簇的数据集,这种数据集的特点是两个簇之间有明显的非线性边界。from sklearn.cluster import MeanShiftfrom sklearn.datasets import make_blobsimport matplotlib.pyplot as pltimport numpy as np# 生成数据集,包含不同密度的簇centers = [[1, 1], [5, 5], [9, 9]]X, _ = make_blobs(n_samples=1000, centers=centers, cluster_std=[0.5, 1, 0.5])# 应用均值漂移聚类meanshift = MeanShift(bandwidth=2)meanshift.fit(X)labels = meanshift.labels_# 可视化聚类结果plt.figure(figsize=(10, 6))plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis', s=50, alpha=0.6, edgecolor='k')plt.title('均值漂移聚类结果')plt.xlabel('特征 1')plt.ylabel('特征 2')plt.grid(True)plt.show()
make_blobs 函数生成了一个包含三个中心点,但标准差不同的簇的数据集。这模拟了具有不同密度簇的情形。from sklearn.cluster import OPTICSimport matplotlib.pyplot as pltimport numpy as np# 设置随机种子,确保结果的可重复性np.random.seed(42)# 创建数据集:模拟金庸小说中的武林世界# 大门派成员:密集分布big_sect = np.random.randn(100, 2) * 2 + [30, 30]# 小门派成员:较为稀疏small_sect = np.random.randn(50, 2) * 3 + [60, 20]# 散人:随机分布lone_wolf = (np.random.rand(50, 2) * 100) % 100 # 保证散人分布在整个100x100的区域内# 将这些分布合并到一起X = np.vstack((big_sect, small_sect, lone_wolf))# 应用OPTICS聚类optics = OPTICS(min_samples=10, xi=0.05, min_cluster_size=0.05) # 9optics.fit(X)# 获取每个点的簇标号labels = optics.labels_# 可视化聚类结果,使用不同颜色表示不同的聚类plt.figure(figsize=(10, 6))plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis', s=50, alpha=0.6, edgecolor='k', marker='o')# 未被归入任何聚类的点视为噪声点,特别标注noise = X[labels == -1]plt.scatter(noise[:, 0], noise[:, 1], c='red', s=50, alpha=1, edgecolor='k', marker='x', label='Noise')plt.title('武林人士的OPTICS聚类分布')plt.xlabel('武功高低')plt.ylabel('江湖声望')plt.legend()plt.grid(True)plt.show()
eps)和形成密集区域所需的最小点数(如DBSCAN中的min_samples)。min_samples但属于某个核心点邻域的点;噪声点既不是核心点也不是边界点。from sklearn.cluster import DBSCANfrom sklearn.datasets import make_blobsimport matplotlib.pyplot as pltimport numpy as np# 设置随机种子np.random.seed(42)# 生成示例数据:江湖门派和游侠centers = [[2, 2], [8, 8], [3, 7]] # 门派中心X, labels_true = make_blobs(n_samples=750, centers=centers, cluster_std=0.50)# 添加散布的游侠(噪声点)X = np.concatenate([X, np.random.uniform(low=0, high=10, size=(100, 2))])# 应用DBSCAN聚类dbscan = DBSCAN(eps=0.5, min_samples=10).fit(X)labels = dbscan.labels_# 可视化聚类结果plt.figure(figsize=(10, 6))# 标记噪声点plt.scatter(X[labels == -1, 0], X[labels == -1, 1], c='red', label='游侠', alpha=0.6, edgecolor='k')# 标记门派(聚类)plt.scatter(X[labels != -1, 0], X[labels != -1, 1], c='blue', label='江湖门派', alpha=0.6, edgecolor='k')plt.title('江湖门派和游侠的分布')plt.xlabel('位置X')plt.ylabel('位置Y')plt.legend()plt.show()
sklearn库不直接支持模糊C-均值聚类,这里我们使用skfuzzy库来实现,该库是一个开源的模糊逻辑工具包pip install scikit-fuzzy
import numpy as npimport skfuzzy as fuzzimport matplotlib.pyplot as plt# 生成数据:武侠世界中的人物,"武功高低"和"侠义度"np.random.seed(42)n_points = 300X = np.zeros((n_points, 2))# 生成三个门派X[:100, :] = np.random.normal(0, 2, (100, 2)) + [10, 10] # 门派AX[100:200, :] = np.random.normal(0, 2, (100, 2)) + [20, 5] # 门派BX[200:, :] = np.random.normal(0, 2, (100, 2)) + [5, 15] # 门派C# 应用模糊C-均值聚类cntr, u, u0, d, jm, p, fpc = fuzz.cluster.cmeans(X.T, 3, 2, error=0.005, maxiter=1000, init=None)# 聚类结果cluster_membership = np.argmax(u, axis=0)# 可视化结果fig, ax = plt.subplots()for j in range(3):ax.plot(X[cluster_membership == j, 0], X[cluster_membership == j, 1], '.', label='门派{}'.format(j))ax.legend()plt.title('武林中人物的模糊C-均值聚类结果')plt.xlabel('武功高低')plt.ylabel('侠义度')plt.show()
from sklearn.cluster import Birchfrom sklearn.datasets import make_blobsimport matplotlib.pyplot as pltimport numpy as np# 生成大规模数据集:武林人士X, _ = make_blobs(n_samples=10000, centers=8, cluster_std=0.60, random_state=2)# 应用BIRCH聚类brc = Birch(n_clusters=8)brc.fit(X)# 获取每个点的簇标号labels = brc.predict(X)# 可视化聚类结果plt.figure(figsize=(10, 6))plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis', s=10, alpha=0.6)plt.title('江湖中门派的BIRCH聚类分布')plt.xlabel('武功高低')plt.ylabel('江湖经验')plt.show()