【笔记整理】常见聚类算法

【笔记整理】常见聚类算法

文章目录

多种聚类算法总结参考

10种比较流行的聚类算法:

亲和力传播;聚合聚类;BIRCH

DBSCAN;K-均值;Mini-Batch K-均值

Mean Shift;OPTICS;谱聚类;高斯混合

一、均值偏移 - Mean-shift(★★★★)

核心:与DBSCAN不同的是,聚类中心是由均值偏移向量和当前的中心位置累加得到的(均值偏移向量仍然需要定义圆圈,对邻居样本点进行"汇总"),而不是对圈内未处理的点进行再次画圈(SCAN)

参考机器学习笔记三:K-Means和MeanShift聚类算法介绍_耐心的小黑的博客

1、概述 & 图解(“偏心”)

Mean-shift(即:均值迁移)的基本思想:在数据集中选定一个点,然后以这个点为圆心,r为半径,画一个圆(二维下是圆),求出这个点到所有点的向量的平均值,而圆心与向量均值的和为新的圆心,然后迭代此过程,直到满足一点的条件结束。(Fukunage在1975年提出)

后来Yizong Cheng 在此基础上加入了 核函数权重系数 ,使得Mean-shift 算法开始流行起来。目前它在聚类、图像平滑、图像分割、目标跟踪等方面有着广泛的应用。

为了方便大家理解,借用下动图来说明Mean-shift的基本过程。

在这里插入图片描述

Mean-shift如何产生多个聚类中心

在这里插入图片描述

由上图可以很容易看到,Mean-shift 算法的核心思想就是不断的寻找新的圆心坐标,直到密度最大的区域

2、公式 & 步骤

参考

1)基本公式(“偏移量更新圆心”)

均值漂移的基本形式如下:

给定d维空间中的n个样本点,对于空间中的任意点x的MeanShift向量的基本形式定义为:
M h = 1 K ∑ x i ∈ S k ( x i − x ) M_h = \frac{1}{K} \sum_{x_i \in S_k} (x_i - x) Mh=K1xiSk(xix)
这个向量就是漂移向量,其中,$S_h $是一个半径为h的高维球区域,k表示n个样本点中有k个点落入区域,也就是:
S h ( x ) = { y : ( y − x i ) T ( y − x i ) < h 2 } S_h(x) = \{y:(y-x_i)^T(y-x_i) < h^2\} Sh(x)={ y:(yxi)T(yxi)<h2}
而漂移的过程,说的简单一点,就是通过计算得漂移向量,然后把球圆心x的位置更新一下,更新公式为:
x : = x + M h x := x + M_h x:=x+Mh
总结为一句话就是:求解一个向量,使得圆心一直往数据集密度最大的方向移动。说的再简单一点,就是每次迭代的时候,都是找到圆里面点的平均位置作为新的圆心位置。

2)扩展公式(“加入核函数权值”)

在扩展的MeanShift中,引入了核函数和权重的概念,相当于给不同的点赋予不同的质量,求解这些不同质量分布的点的质心位置。MeanShift的拓展形式可以表示为:

每次更新的圆心坐标为:
m ( x ) = ∑ i = 1 n g ( ∣ ∣ x − x i h ∣ ∣ 2 ) w ( x i ) x i ∑ i = 1 n g ( ∣ ∣ x − x i h ∣ ∣ 2 ) w ( x i ) m(x) = \frac{\sum_{i = 1}^ng(||\frac{x-x_i}{h}||^2)w(x_i)x_i}{\sum_{i = 1}^ng(||\frac{x-x_i}{h}||^2)w(x_i)} m(x)=i=1ng(∣∣hxxi2)w(xi)i=1ng(∣∣hxxi2)w(xi)xi

3)mean shift聚类流程

假设在一个多维空间中有很多数据点需要进行聚类,Mean Shift的过程如下:

1、在未被标记的数据点中随机选择一个点作为中心center

2、找出离center距离在bandwidth之内的所有点,记做集合M,认为这些点属于簇c。同时,把这些球内点属于这个类的概率加1,这个参数将用于最后步骤的分类

3、以center为中心点,计算从center开始到集合M中每个元素的向量,将这些向量相加,得到向量shift。

4、center = center+shift。即center沿着shift的方向移动,移动距离是||shift||。

5、重复步骤2、3、4,直到shift的大小很小(就是迭代到收敛),记住此时的center。注意,这个迭代过程中遇到的点都应该归类到簇c。(“shift小则结束当前center”

6、如果收敛时当前簇c的center与其它已经存在的簇c2中心的距离小于阈值,那么把c2和c合并。否则,把c作为新的聚类,增加1类。(“合并不同簇为新簇”)

7、重复1、2、3、4、5直到所有的点都被标记访问。(“所有样本被标记则结束”

8、分类:根据每个类,对每个点的访问频率,取访问频率最大的那个类,作为当前点集的所属类。

简单的说,mean shift就是沿着密度上升的方向寻找同属一个簇的数据点

3、代码

# -*- coding:utf-8 -*-
from sklearn.datasets._samples_generator import make_blobs
from sklearn.cluster import MeanShift, estimate_bandwidth
import numpy as np
import matplotlib.pyplot as plt
from itertools import cycle  ##python自带的迭代器模块

##产生随机数据的中心
centers = [[1, 1], [-1, -1], [1, -1]]
##产生的数据个数
n_samples=10000
##生产数据
X, _ = make_blobs(n_samples=n_samples, centers= centers, cluster_std=0.6,
                  random_state =0)

##带宽,也就是以某个点为核心时的搜索半径
bandwidth = estimate_bandwidth(X, quantile=0.2, n_samples=500)
##设置均值偏移函数
ms = MeanShift(bandwidth=bandwidth, bin_seeding=True)
##训练数据
ms.fit(X)
##每个点的标签
labels = ms.labels_
print(labels)
##簇中心的点的集合
cluster_centers = ms.cluster_centers_
print('cluster_centers:',cluster_centers)
##总共的标签分类
labels_unique = np.unique(labels)
##聚簇的个数,即分类的个数
n_clusters_ = len(labels_unique)
print("number of estimated clusters : %d" % n_clusters_)


##绘图
plt.figure(1)
plt.clf()

colors = cycle('bgrcmykbgrcmykbgrcmykbgrcmyk')
for k, col in zip(range(n_clusters_), colors):
    ##根据lables中的值是否等于k,重新组成一个True、False的数组
    my_members = labels == k
    cluster_center = cluster_centers[k]
    ##X[my_members, 0] 取出my_members对应位置为True的值的横坐标
    plt.plot(X[my_members, 0], X[my_members, 1], col + '.')
    plt.plot(cluster_center[0], cluster_center[1], 'o', markerfacecolor=col,
             markeredgecolor='k', markersize=14)
plt.title('Estimated number of clusters: %d' % n_clusters_)
plt.show()

在这里插入图片描述

4、应用 - 目标跟踪(“计算中心和各点相似度”)

参考

Mean-shift实现目标跟踪

在这里插入图片描述

在MeanShift目标跟踪算法中,其样本点 x i ( i = 1 , . . . , n ) x_i(i=1,...,n) xi(i=1,...,n)域内的像素点,其核函数g采用Epanechnikov,即计算空间中任意一点到中心位置(质心处)的欧式距离。而最重要的是权重的求解,方法如下:

首先计算目标核函数直方图

其中C表示归一化常数,k表示核函数(在核估计中通常是平滑作用),目标区域共n个样本点,该区域颜色分布成m级,。

然后是候选核函数直方图

其中** y y y表示候选区域的中心位置**,h表示核函数 k k k 的窗宽(用作归一化) x i x_i xi为目标候选区域的样本点。其余变量物理意义同上。当目标区域与候选区域之间存在一定差异时,直方图的相似性较弱,MeanShift通过加入核函数 k k k ,来改变候选框质心的位置,提高 的相似性,进而进行目标的追踪,其相似度度量准则为:

经过Taylor展开,并将代入并化简得到:

由于第一项为常量,因此我们最大化,本质上是寻找新的质心y使得候选区域和模板的相似程度最大化。对相似性函数求导,可得目标的新位置

  1. 在当前帧,计算候选目标的特征(候选图像块的颜色直方图):
%计算侯选区域直方图
hist2 = zeros(1,4096);

% 计算候选区域直方图
for i = 1:a
    for j = 1:b
        % rgb 颜色空间量化为 16*16*16 bins
        q_r = fix(double(current_temp(i,j,1))/16);  % fix为趋近0取整函数
        q_g = fix(double(current_temp(i,j,2))/16);
        q_b = fix(double(current_temp(i,j,3))/16);
        q_temp(i, j) = q_r*256 + q_g*16 + q_b;    % 设置每个像素点红色、绿色、蓝色分量所占比重
        % 计算直方图统计中每个像素点占的权重
        hist2(q_temp(i, j)+1) = hist2(q_temp(i, j)+1) + m_wei(i,j);    
    end
end
hist2 = hist2 * C;  % 以上步骤完成了目标核函数直方图

2.计算候选目标与初始目标的相似度

rho(frame-1) = sum(sqrt(hist1 .* hist2));

3.计算权值

% 目标权重直方图
hist_wei = zeros(1, 4096);
for i = 1:length(hist_wei)
    if hist2(i) ~= 0
        hist_wei(i) = hist1(i) / hist2(i); 
    else
        hist_wei(i) = 0;
    end
end

4.利用MeanShift算法,计算目标新位置

% 计算迭代步长并更新目标的位置
numerator = 0;
denominator = 0;
for i = 1:a
    for j = 1:b
        w_temp = hist_wei(uint32(q_temp(i, j))+1);
        numerator = numerator + w_temp * m_wei(i, j) * [i - y(1) - 0.5, j - y(2) - 0.5];
        denominator = denominator + w_temp * m_wei(i, j);
    end
end
delta = numerator ./ denominator;
  1. ∣ ∣ y 1 − y 0 ∣ ∣ < ε ||y_1 - y_0|| < \varepsilon ∣∣y1y0∣∣<ε 转步骤3。限制条件:新目标中心需要位于原目标中心附近
% 迭代步长:
% update the rect
rect(1) = rect(1) + delta(2);
rect(2) = rect(2) + delta(1);

二、谱聚类 - Spectral Clustering

参考

1、谱聚类概览
谱聚类演化于图论,后由于其表现出优秀的性能被广泛应用于聚类中,对比其他无监督聚类(如kmeans),spectral clustering的优点主要有以下

1.过程对数据结构并没有太多的假设要求,如kmeans则要求数据为凸集。
2.可以通过构造稀疏similarity graph,使得对于更大的数据集表现出明显优于其他算法的计算速度。
3.由于spectral clustering是对图切割处理,不会存在像kmesns聚类时将离散的小簇聚合在一起的情况。
4.无需像GMM一样对数据的概率分布做假设。

同样,spectral clustering也有自己的缺点,主要存在于构图步骤,有如下:

1.对于选择不同的similarity graph比较敏感(如 epsilon-neighborhood, k-nearest neighborhood,fully connected等)。
2.对于参数的选择也比较敏感(如 epsilon-neighborhood的epsilon,k-nearest neighborhood的k,fully connected的 )。

谱聚类过程主要有两步,第一步是构图,将采样点数据构造成一张网图,表示为 G ( V , E ) G(V,E) G(V,E),V表示图中的点,E表示点与点之间的边,如下图:

在这里插入图片描述

​ 图1 谱聚类构图(来源wiki)

第二步是切图,即将第一步构造出来的按照一定的切边准则,切分成不同的图,而不同的子图,即我们对应的聚类结果,举例如下:

在这里插入图片描述
​ 图2 谱聚类切图

2、谱聚类构图
在构图中,一般有三种构图方式:

  • ε-neighborhood

  • k-nearest neighborhood

  • fully connected

前两种可以构造出稀疏矩阵,适合大样本的项目,第三种则相反,在大样本中其迭代速度会受到影响制约,在讲解三种构图方式前,需要引入similarity function,即计算两个样本点的距离,一般用欧氏距离 s i , j = ∥ x i − x j ∥ 2 s_{i,j}=∥x_i−x_j∥^2 si,j=xixj2, s i , j s_{i,j} si,j表示样本点 x i x_i xi x j x_j xj的距离,或者使用高斯距离
s i , j = e ∣ ∣ x i − x ∣ ∣ 2 2 σ 2 s_{i,j}=e^\frac{||xi−x||^2}{2\sigma^2} si,j=e2σ2∣∣xix2 ​ 其中σσ的选取也是对结果有一定影响,其表示为数据分布的分散程度,通过上述两种方式之一即可初步构造矩阵 S : S i , j = [ s ] i , j S: S_{i,j}=[s]_{i,j} S:Si,j=[s]i,j一般称 为Similarity matrix(相似矩阵)

  • 对于第一种构图ε -neighborhood,顾名思义是取 s i , j ≤ ε s_{i,j}≤ε si,jε的点,则相似矩阵S可以进一步重构为邻接矩阵(adjacency matrix)W :

    在这里插入图片描述

​ 可以看出,在 ε-neighborhood重构下,样本点之间的权重没有包含更多的信息了。

  • 对于第二种构图k-nearest neighborhood,其利用KNN算法,遍历所有的样本点,取每个样本最近的k个点作为近邻,但是这种方法会造成重构之后的邻接矩阵 W非对称,为克服这种问题,一般采取下面两种方法之一:
    一是只要点 x i x_i xi x j x_j xj的K个近邻中或者 x j x_j xj x i x_i xi的K个近邻中,则保留 s i , j s_{i,j} si,j,并对其做进一步处理 W,此时 为:

在这里插入图片描述

二是必须满足点 x i x_i xi x j x_j xj的K个近邻中 x j x_j xj x i x_i xi的K个近邻中,才会保留 s i , j s_{i,j} si,j并做进一步变换,此时 W为:

在这里插入图片描述

  • 对于第三种构图fully connected,一般使用高斯距离 s i , j = e ∣ ∣ x i − x ∣ ∣ 2 2 σ 2 s_{i,j}=e^\frac{||xi−x||^2}{2\sigma^2} si,j=e2σ2∣∣xix2,则重构之后的矩阵W与之前的相似矩阵S相同,为: W i , j = S i , j = [ s ] i , j W_{i,j}=S_{i,j}=[s]_{i,j} Wi,j=Si,j=[s]i,j

在了解三种构图方式后,还需要注意一些细节,对于第一二中构图,一般是重构基于欧氏距离的 ,而第三种构图方式,则是基于高斯距离的 ,注意到高斯距离的计算蕴含了这样一个情况:对于 ∣ ∣ x i − x j ∣ ∣ 2 ||xi−xj||^2 ∣∣xixj2比较大的样本点,其得到的高斯距离反而值是比较小的,而这也正是S可以直接作为W的原因,主要是为了将距离近的点的边赋予高权重。

得到邻接矩阵 W后,需要做进一步的处理:

  • (1).计算阶矩(degree matrix)D, 若边权值均为1,则D为度矩阵:

    在这里插入图片描述

    其中其中 w i , j w_{i,j} wi,j为邻接矩阵 W元素, ∑ j w i , j ∑_jw_{i,j} jwi,j表示将图中某点所连接的其他点的边的权重之和,可以看出, D为对角矩阵.

  • (2).计算拉普拉斯矩阵(Laplacians matrix)$ L: L=D−W$

如此,在构图阶段基本就完成了,至于为什么要计算出拉普拉斯矩阵 L,可以说 L = D − W L=D−W L=DW这种形式对于后面极大化问题是非常有利的(不知道前人是怎么想到的,不然 L也不会被命名为拉普拉斯了吧)。

1、概述(”切图、组间低、组内高”)

Spectral Clustering(SC,即谱聚类),是一种基于图论的聚类方法,它的主要思想是把所有的数据看做空间中的点,这些点之间可以用边连接起来。距离较远的两个点之间的边权重值较低,而距离较近的两个点之间的边权重值较高,通过对所有数据点组成的图进行切图,让切图后不同的子图间边权重和尽可能的低,而子图内的边权重和尽可能的高,从而达到聚类的目的。

它能够识别任意形状的样本空间且收敛于全局最有解,它是利用样本数据的相似矩阵进行特征分解后得到的特征向量进行聚类。它与样本特征无关而只与样本个数有关。

基本思路:将样本看作顶点, 样本间的相似度看作带权的边, 从而将聚类问题转为图分割问题: 找到一种图分割的方法使得连接不同组的边的权重尽可能低(这意味着组间相似度要尽可能低),组内的边的权重尽可能高(这意味着组内相似度要尽可能高).

在这里插入图片描述

2、公式

1)无向权重图

在这里插入图片描述

2)相似矩阵(”相似度计算 -> 权重计算 -> 度计算“)

在这里插入图片描述

3)拉普拉斯矩阵(“L = D-W”)

在这里插入图片描述

4)无向图切图(”组间相似度“)

在这里插入图片描述

5)RatioCut切图(“最小最大子图 - > 降维PCA -> 聚类)

在这里插入图片描述

在这里插入图片描述

6)Ncut切图

3、算法流程

最常用的相似矩阵的生成方式是基于高斯核距离的全连接方式,最常用的切图方式是Ncut。而到最后常用的聚类方法为K-Means。下面以Ncut总结谱聚类算法流程。

输入:样本集 D = ( x 1 , x 2 , . . . , x n ) D=(x_1,x_2,...,x_n) D=(x1,x2,...,xn),相似矩阵的生成方式, 降维后的维度 k 1 k1 k1, 聚类方法,聚类后的维度 k 2 k2 k2

输出: 簇划分 C ( c 1 , c 2 , . . . c k 2 ) C(c_1,c_2,...c_{k2}) C(c1,c2,...ck2).

  1. 根据输入的相似矩阵的生成方式构建样本的相似矩阵S

2)根据相似矩阵S构建邻接矩阵W,构建度矩阵D

3)计算出拉普拉斯矩阵L

4)构建标准化后的拉普拉斯矩阵 D − 1 / 2 L D − 1 / 2 D^{−1/2}LD^{−1/2} D1/2LD1/2

5)计算 D − 1 / 2 L D − 1 / 2 D^{−1/2}LD^{−1/2} D1/2LD1/2最小的 k 1 k_1 k1个特征值所各自对应的特征向量f

  1. 将各自对应的特征向量f组成的矩阵按行标准化,最终组成 n × k 1 n×k_1 n×k1维的特征矩阵F

7)对F中的每一行作为一个 k 1 k1 k1维的样本,共n个样本,用输入的聚类方法进行聚类,聚类维数为 k 2 k2 k2

8)得到簇划分 C ( c 1 , c 2 , . . . c k 2 ) C(c1,c2,...ck2) C(c1,c2,...ck2).

4、代码

这里对二维数据进行谱聚类,以及对二维数据进行可视化,如果是对于高维数据的谱聚类,在可视化时,可以考虑使用散点矩阵图的形式绘制(!!!)

1)spectral_clustering

from sklearn.datasets._samples_generator import make_blobs
from sklearn.cluster import spectral_clustering
import numpy as np
import matplotlib.pyplot as plt
from sklearn import metrics
from itertools import cycle  ##python自带的迭代器模块

##产生随机数据的中心
centers = [[1, 1], [-1, -1], [1, -1]]
##产生的数据个数
n_samples=3000
##生产数据
X, lables_true = make_blobs(n_samples=n_samples, centers= centers, cluster_std=0.6, 
                  random_state =0)

##变换成矩阵,输入必须是对称矩阵
metrics_metrix = (-1 * metrics.pairwise.pairwise_distances(X)).astype(np.int32)
metrics_metrix += -1 * metrics_metrix.min()
##设置谱聚类函数
n_clusters_= 4
lables = spectral_clustering(metrics_metrix,n_clusters=n_clusters_)

##绘图
plt.figure(1)
plt.clf()

colors = cycle('bgrcmykbgrcmykbgrcmykbgrcmyk')
for k, col in zip(range(n_clusters_), colors):
    ##根据lables中的值是否等于k,重新组成一个True、False的数组
    my_members = lables == k
    ##X[my_members, 0] 取出my_members对应位置为True的值的横坐标
    plt.plot(X[my_members, 0], X[my_members, 1], col + '.')

plt.title('Estimated number of clusters: %d' % n_clusters_)
plt.show()

'''模型保存和加载'''
dump(model,"spectual.joblib")
spectual_temp = load("spectual.joblib")

在这里插入图片描述

2)SpectralClustering

from sklearn.datasets._samples_generator import make_blobs
from sklearn.cluster import spectral_clustering
from sklearn.cluster import SpectralClustering
import numpy as np
import matplotlib.pyplot as plt
from sklearn import metrics
from itertools import cycle  ##python自带的迭代器模块
from joblib import dump, load

##产生随机数据的中心
centers = [[1, 1], [-1, -1], [1, -1]]
##产生的数据个数
n_samples = 3000
##生产数据
X, lables_true = make_blobs(n_samples=n_samples, centers=centers, cluster_std=0.6,
                            random_state=0)

##变换成矩阵,输入必须是对称矩阵
metrics_metrix = (-1 * metrics.pairwise.pairwise_distances(X)).astype(np.int32)
metrics_metrix += -1 * metrics_metrix.min()   #把相似度取值变为正数
##设置谱聚类函数
n_clusters_ = 4
'''
spectral_clustering谱聚类方法,无需setting affinity='precomputed'
@_deprecate_positional_args
def spectral_clustering(affinity, *, n_clusters=8, n_components=None,
                        eigen_solver=None, random_state=None, n_init=10,
                        eigen_tol=0.0, assign_labels='kmeans',
                        verbose=False):
'''
# lables = spectral_clustering(metrics_metrix, n_clusters=n_clusters_)

'''``fit``now constructs an affinity matrix from data. To use a custom affinity matrix, set ``affinity=precomputed``.'''
model = SpectralClustering(n_clusters=n_clusters_,affinity='precomputed')
clustering = model.fit(metrics_metrix)
labels = clustering.labels_

##绘图
plt.figure(1)
plt.clf()

colors = cycle('bgrcmykbgrcmykbgrcmykbgrcmyk')
for k, col in zip(range(n_clusters_), colors):
    ##根据lables中的值是否等于k,重新组成一个True、False的数组
    my_members = labels == k
    ##X[my_members, 0] 取出my_members对应位置为True的值的横坐标
    plt.plot(X[my_members, 0], X[my_members, 1], col + '.')

plt.title('Estimated number of clusters: %d' % n_clusters_)
plt.show()

'''模型保存和加载'''
dump(model,"spectual.joblib")
spectual_temp = load("spectual.joblib")

输出结果同1),只不过在使用model.fit(matrix)时有些不同,注意

  • SpectralClustering(n_clusters=n_clusters_,affinity='precomputed')要修改affinity属性,默认的affinity='rbf'在处理邻接矩阵会报错

    `````fitnow constructs an affinity matrix from data. To use a custom affinity matrix, set affinity=precomputed``.```

  • 如果matrix不是邻接矩阵,则无所谓,如下代码

    from sklearn.cluster import SpectralClustering
    import numpy as np
    X = np.array([[1, 1], [2, 1], [1, 0],
                  [4, 7], [3, 5], [3, 6]])
    clustering = SpectralClustering(n_clusters=2,
            assign_labels='discretize',
            random_state=0).fit(X)
    
    print(clustering.labels_)
    
    print(clustering)
    ---
    [1 1 1 0 0 0]
    SpectralClustering(assign_labels='discretize', n_clusters=2, random_state=0)
    

3)预测(倾向预测2方式)

预测1:随机产生新的预测数据,生成邻接矩阵,但是这样生成的分类结果似乎和原始数据没有关系(预测的数据没有和原始数据计算相似度

spectual_temp = load("spectual.joblib")

'''注意在预测时需要输入邻接矩阵(n x n),否则会报  {ValueError}array must be 2-dimensional and square. shape = (3000, 2)'''
# y = spectual_temp.fit_predict(X[0])
y = spectual_temp.fit_predict(metrics_metrix)

'''预测1:随机产生预测数据,生成邻接矩阵,但是这样生成的分类结果似乎和原始数据没有关系(没有和原始数据计算相似度)'''
##产生的数据个数
n_samples = 100
##生产数据
X_pred, y_pred_true = make_blobs(n_samples=n_samples, centers=centers, cluster_std=0.2,
                            random_state=0)

##变换成矩阵,输入必须是对称矩阵(计算预测数据自己的相似矩阵)
metrics_metrix = (-1 * metrics.pairwise.pairwise_distances(X_pred)).astype(np.int32)
metrics_metrix += -1 * metrics_metrix.min()   #把相似度取值变为正数
y_pred = spectual_temp.fit_predict(metrics_metrix)

print(f"new spectualClustering: x = {
      
      X_pred}, \n y = {
      
      y_pred}")

colors = cycle('bgrcmykbgrcmykbgrcmykbgrcmyk')
for k, col in zip(range(n_clusters_), colors):
    ##根据lables中的值是否等于k,重新组成一个True、False的数组
    my_members = y_pred == k
    ##X[my_members, 0] 取出my_members对应位置为True的值的横坐标
    plt.plot(X_pred[my_members, 0], X_pred[my_members, 1], col + '.')

plt.title('Estimated number of clusters: %d' % n_clusters_)
plt.show()
---
new spectualClustering: x = [[ 1.03098949  1.0756325 ]
 [ 0.87127632 -1.44468063]
 [ 1.01330344  1.06049438]
 [ 0.77912333 -0.98956698]
 [ 0.9088935  -0.99650417]
 [ 1.30655584  1.29387175]
 [ 1.03548523  0.91964381]
 [ 0.87283078 -0.86471334]
 ...
 [ 0.89806956  0.91238514]
 [ 0.90039351 -0.61409359]
 [ 1.08877265  1.06673487]
 [ 0.8520874  -0.69139708]
 [ 1.29881581  0.95896835]
 [-1.06231051 -0.98876693]
 [-1.17415943 -1.11576993]
 [ 0.70174848 -0.91212166]
 [ 1.0091517   0.96256323]
 [-1.21415052 -0.78910965]
 [ 0.81743555 -0.77659674]
 [-0.97461758 -0.91960213]
 [-0.81054961 -1.03100202]
 [-0.85418189 -0.97420342]], 
 y = [1 2 1 2 2 1 1 2 0 1 2 3 0 2 2 1 2 0 2 3 3 1 0 0 0 1 0 1 3 0 1 1 0 2 2 2 2
 1 2 2 1 2 2 2 0 1 0 1 0 2 1 0 1 1 1 2 3 2 2 2 0 0 3 3 1 1 1 2 0 1 1 0 1 2
 1 1 1 3 1 0 3 2 2 1 2 2 1 2 1 2 1 0 3 2 1 3 2 0 0 0]

在这里插入图片描述

预测2: 将原始的X和预测的x_pred进行拼接, 可以让新的数据(row = 1)和原始的数据计算相似度,预测的分类结果和原始数据关系较大

'''预测2: 将原始的X和预测的x_pred进行拼接, 可以让新的数据和原始的数据计算相似度,预测的分类结果和原始数据关系较大'''
# shape = np.expand_dims(X[0],axis=0).shape
shape = [1,len(X[0])]
X_pred = np.random.rand(shape[0],shape[1])
X_t = X_pred.tolist()
X_t.extend(X.tolist())
X_pred = np.array(X_t)
##变换成矩阵,输入必须是对称矩阵
metrics_metrix = (-1 * metrics.pairwise.pairwise_distances(X_pred)).astype(np.int32)
metrics_metrix += -1 * metrics_metrix.min()   #把相似度取值变为正数
y_pred = spectual_temp.fit_predict(metrics_metrix)

print(f"x_pred = {
      
      X_pred[0]}, y_pred = {
      
      y_pred[0]}")

colors = cycle('bgrcmykbgrcmykbgrcmykbgrcmyk')
for k, col in zip(range(n_clusters_), colors):
    ##根据lables中的值是否等于k,重新组成一个True、False的数组
    my_members = y_pred == k
    ##X[my_members, 0] 取出my_members对应位置为True的值的横坐标
    plt.plot(X_pred[my_members, 0], X_pred[my_members, 1], col + '.')

plt.title('Estimated number of clusters: %d' % n_clusters_)
plt.show()
---
x_pred = [0.44530753 0.71075785], y_pred = 0

在这里插入图片描述

5、优缺点

谱聚类算法是一个使用起来简单,但是讲清楚却不是那么容易的算法,它需要你有一定的数学基础。如果你掌握了谱聚类,相信你会对矩阵分析,图论有更深入的理解。同时对降维里的主成分分析也会加深理解。

下面总结下谱聚类算法的优缺点。

谱聚类算法的主要优点有:

1)谱聚类只需要数据之间的相似度矩阵,因此对于处理稀疏数据的聚类很有效。这点传统聚类算法比如K-Means很难做到

2)由于使用了降维,因此在处理高维数据聚类时的复杂度比传统聚类算法好

谱聚类算法的主要缺点有:

1)如果最终聚类的维度非常高,则由于降维的幅度不够,谱聚类的运行速度和最后的聚类效果均不好。

  1. 聚类效果依赖于相似矩阵,不同的相似矩阵得到的最终聚类效果可能很不同

三、层次聚类 - Hierarchical Clustering

1、概述 & 图解(“凝聚分裂”)

Hierarchical Clustering(层次聚类):就是按照某种方法进行层次分类,直到满足某种条件为止。

主要分成两类:

a)凝聚:从下到上。首先将每个对象作为一个簇,然后合并这些原子簇为越来越大的簇,直到所有的对象都在一个簇中,或者某个终结条件被满足。

算法步骤:

a)将每个对象归为一类, 共得到N类, 每类仅包含一个对象. 类与类之间的距离就是它们所包含的对象之间的距离.

b)找到最接近的两个类并合并成一类, 于是总的类数少了一个.

c)重新计算新的类与所有旧类之间的距离.
d)重复第a步和第b步, 直到最后合并成一个类为止(此类包含了N个对象)

在这里插入图片描述

b)分裂:从上到下。首先将所有对象置于同一个簇中,然后逐渐细分为越来越小的簇,直到每个对象自成一簇,或者达到了某个终止条件。(较少用)

2、代码(聚合聚类)

主要参数(详细参数)

  • n_clusters:聚类的个数
  • linkage:指定层次聚类判断相似度的方法,有以下三种:
    • ward:组间距离等于两类对象之间的最小距离。(即single-linkage聚类)
    • average:组间距离等于两组对象之间的平均距离。(average-linkage聚类)
    • complete:组间距离等于两组对象之间的最大距离。(complete-linkage聚类)
from sklearn.datasets._samples_generator import make_blobs
from sklearn.cluster import AgglomerativeClustering #聚合聚类
import numpy as np
import matplotlib.pyplot as plt
from itertools import cycle  ##python自带的迭代器模块

##产生随机数据的中心
centers = [[1, 1], [-1, -1], [1, -1]]
##产生的数据个数
n_samples=3000
##生产数据
X, lables_true = make_blobs(n_samples=n_samples, centers= centers, cluster_std=0.6, 
                  random_state =0)


##设置分层聚类函数
linkages = ['ward', 'average', 'complete']
n_clusters_ = 3
ac = AgglomerativeClustering(linkage=linkages[2],n_clusters = n_clusters_)
##训练数据
ac.fit(X)

##每个数据的分类
lables = ac.labels_

##绘图
plt.figure(1)
plt.clf()

colors = cycle('bgrcmykbgrcmykbgrcmykbgrcmyk')
for k, col in zip(range(n_clusters_), colors):
    ##根据lables中的值是否等于k,重新组成一个True、False的数组
    my_members = lables == k
    ##X[my_members, 0] 取出my_members对应位置为True的值的横坐标
    plt.plot(X[my_members, 0], X[my_members, 1], col + '.')

plt.title('Estimated number of clusters: %d' % n_clusters_)
plt.show()

效果图:参数linkage的取值依次为:[‘ward’, ‘average’, ‘complete’]

在这里插入图片描述

四、具有噪声的基于密度的聚类 - DBSCAN(★★★)

核心:初始起始点,圆圈约束(半径,最小样本个数)找同类,同类继续画圈扩大类集合,若扩展失败划分为噪声点(边缘点),并随机新起点,开辟新的类别

参考

1、概述 & 图解(“去噪”)

DBSCAN(Density-Based Spatial Clustering of Applications with Noise,具有噪声的基于密度的聚类方法)是一种基于密度的空间聚类算法。该算法将具有足够密度的区域划分为簇(即要求聚类空间中的一定区域内所包含对象的数目不小于某一给定阈值),并在具有噪声的空间数据库中发现任意形状的簇,它将簇定义为密度相连的点的最大集合

算法步骤

DBSCAN需要二个参数: 扫描半径 (eps)和 最小包含点数(min_samples)

a)遍历所有点,寻找核心点

b)连通核心点,并且在此过程中扩展某个分类集合中点的个数

在这里插入图片描述

在上图中,第一步就是寻找红色的核心点,第二步就是用绿色箭头联通红色点。图中点以绿色线条为中心被分成了两类。没在黑色圆中的点是噪声点

Note:如果不进行第二步中的扩展,所有的小圆点都应该是噪声点(不符合第一步核心点的要求)

2、算法流程

参考 https://baike.baidu.com/item/DBSCAN/4864716?fr=aladdin

具体算法描述如下:

(1)检测数据库中尚未检查过的对象p,如果p未被处理(归为某个簇或者标记为噪声),则检查其邻域,若包含的对象数不小于minPts,建立新簇C,将其中的所有点加入候选集N

(2)对候选集N 中所有尚未被处理的对象q,检查其邻域,若至少包含minPts个对象,则将这些对象加入N;如果q 未归入任何一个簇,则将q 加入C

(3)重复步骤2),继续检查N 中未处理的对象,当前候选集N为空

(4)重复步骤1)~3),直到所有对象都归入了某个簇或标记为噪声。

在这里插入图片描述

还是没有解释噪声类别怎么来的,那看看下面这个算法解释

DBSCAN算法描述:

输入: 包含n个对象的数据库,半径e,最少数目MinPts;

输出:所有生成的簇,达到密度要求。

(1)Repeat

(2)从数据库中抽出一个未处理的点;

(3)IF抽出的点是核心点 THEN 找出所有从该点密度相连的对象,形成一个簇

(4)ELSE 抽出的点是边缘点(非核心对象),跳出本次循环,寻找下一个点;

(5)UNTIL 所有的点都被处理。

DBSCAN对用户定义的参数很敏感,细微的不同都可能导致差别很大的结果,而参数的选择无规律可循,只能靠经验确定。

3、代码

from joblib import dump, load
from sklearn.datasets._samples_generator import make_blobs
from sklearn.cluster import DBSCAN
import numpy as np
import matplotlib.pyplot as plt
from itertools import cycle  ##python自带的迭代器模块
from sklearn.preprocessing import StandardScaler

##产生随机数据的中心
centers = [[1, 1], [-1, -1], [1, -1]]
##产生的数据个数
n_samples=750
##生产数据:此实验结果受cluster_std的影响,或者说受eps 和cluster_std差值影响
X, lables_true = make_blobs(n_samples=n_samples, centers= centers, cluster_std=0.4, 
                  random_state =0)


##设置分层聚类函数
db = DBSCAN(eps=0.3, min_samples=10)
##训练数据
db.fit(X)
##初始化一个全是False的bool类型的数组
core_samples_mask = np.zeros_like(db.labels_, dtype=bool)
'''
   这里是关键点(针对这行代码:xy = X[class_member_mask & ~core_samples_mask]):
   db.core_sample_indices_  表示的是某个点在寻找核心点集合的过程中暂时被标为噪声点的点(即周围点
   小于min_samples),并不是最终的噪声点。在对核心点进行联通的过程中,这部分点会被进行重新归类(即标签
   并不会是表示噪声点的-1),也可也这样理解,这些点不适合做核心点,但是会被包含在某个核心点的范围之内
'''
core_samples_mask[db.core_sample_indices_] = True

##每个数据的分类
lables = db.labels_

##分类个数:lables中包含-1,表示噪声点
n_clusters_ =len(np.unique(lables)) - (1 if -1 in lables else 0)

##绘图
unique_labels = set(lables)
'''
   1)np.linspace 返回[0,1]之间的len(unique_labels) 个数
   2)plt.cm 一个颜色映射模块
   3)生成的每个colors包含4个值,分别是rgba
   4)其实这行代码的意思就是生成4个可以和光谱对应的颜色值
'''
colors = plt.cm.Spectral(np.linspace(0, 1, len(unique_labels)))

plt.figure(1)
plt.clf()


for k, col in zip(unique_labels, colors):
    ##-1表示噪声点,这里的k表示黑色
    if k == -1:
        col = 'k'

    ##生成一个True、False数组,lables == k 的设置成True
    class_member_mask = (lables == k)

    ##两个数组做&运算,找出即是核心点又等于分类k的值  markeredgecolor='k',
    xy = X[class_member_mask & core_samples_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', c=col,markersize=14)
    '''
       1)~优先级最高,按位对core_samples_mask 求反,求出的是噪音点的位置
       2)& 于运算之后,求出虽然刚开始是噪音点的位置,但是重新归类却属于k的点
       3)对核心分类之后进行的扩展
    '''
    xy = X[class_member_mask & ~core_samples_mask]     
    plt.plot(xy[:, 0], xy[:, 1], 'o', c=col,markersize=6)

plt.title('Estimated number of clusters: %d' % n_clusters_)
plt.show()


'''模型保存和加载'''
dump(db,"dbscan.joblib")
db_temp = load("dbscan.joblib")
y = db_temp.fit_predict(X)
print(y)
---
Estimated number of clusters: 3
Estimated number of noise points: 18
Homogeneity: 0.953
Completeness: 0.883
V-measure: 0.917
Adjusted Rand Index: 0.952
Adjusted Mutual Information: 0.916
[ 0  1  0  2  0  1  1  2  0  0  1  1  1  2  1  0 -1  1  1  2  2  2  2  2
  1  1  2  0  0  2  0  1  1  0  1  0  2  0  0  2  2  1  1  1  1  1  0  2
  0  1  2  2  1  1  2  2  1  0  2  1  2  2  2  2  2  0  2  2  0  0  0  2
 ...
  1  2  0  0  2  2  1  2  2  2  0  2  1  2  1  1  1  2  0  2  0  2  2  0
  0  2  1  2  0  2  0  0  0  1  0  2  1  2  0  1  0  0  2  0  2  1  1  2
  1  0  1  2  1  2]

在这里插入图片描述

4、算法优缺点

a)优点:可以发现任意形状的聚类

这类算法能克服基于距离的算法只能发现“类圆形”(凸)的聚类的缺点
可发现任意形状的聚类,且对噪声数据不敏感。
不需要指定类的数目cluster
算法中只有两个参数,扫描半径 (eps)和最小包含点数(min_samples)

b)缺点:随着数据量的增加,对I/O、内存的要求也随之增加。如果密度分布不均匀,聚类效果较差

1、计算复杂度,不进行任何优化时,算法的时间复杂度是O(N^{2}),通常可利用R-tree,k-d tree, ball
tree索引来加速计算,将算法的时间复杂度降为O(Nlog(N))。
2、受eps影响较大。在类中的数据分布密度不均匀时,eps较小时,密度小的cluster会被划分成多个性质相似的cluster;eps较大时,会使得距离较近且密度较大的cluster被合并成一个cluster。在高维数据时,因为维数灾难问题,eps的选取比较困难。
3、依赖距离公式的选取,由于维度灾害,距离的度量标准不重要
4、不适合数据集集中密度差异很大的,因为eps和metric选取很困难

五、聚类特征树 - Birch

1、概述(“聚类特征”)

Birch(利用层次方法的平衡迭代规约(减少)和聚类):就是通过聚类特征(CF)形成一个聚类特征树,root层的CF个数就是聚类个数。

聚类特征(CF):每一个CF是一个三元组,可以用**(N,LS,SS)**表示.其中

  • N代表了这个CF中拥有的样本点的数量;
  • LS代表了这个CF中拥有的样本点各特征维度的和向量 (3 + 2 + 4 + 4 + 3 = 16,4 + 6 + 5 + 7 + 8 = 30)
  • SS代表了这个CF中拥有的样本点各特征维度的平方和(9 + 4 + 16 + 16 + 9 = 54,…)

在这里插入图片描述

在这里插入图片描述

对于上图中的CF Tree,限定了B=7,L=5, 也就是说内部节点最多有7个CF(CF90下的圆),而叶子节点最多有5个CF(CF90到CF94)。叶子节点是通过双向链表连通的。

2、代码

主要参数(详细参数

  • n_clusters :聚类的目标个数。(可选)
  • threshold :扫描半径(个人理解,官方说法比较绕口),设置小了分类就多。
  • branches_factor:每个节点中CF子集群的最大数量,默认为50。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets.samples_generator import make_blobs
from sklearn.cluster import Birch

# X为样本特征,Y为样本簇类别, 共1000个样本,每个样本2个特征,共4个簇,簇中心在[-1,-1], [0,0],[1,1], [2,2]
X, y = make_blobs(n_samples=1000, n_features=2, centers=[[-1,-1], [0,0], [1,1], [2,2]], cluster_std=[0.4, 0.3, 0.4, 0.3], 
                  random_state =9)

##设置birch函数
birch = Birch(n_clusters = None)
##训练数据
y_pred = birch.fit_predict(X)
##绘图
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.show()

效果图为n_clusters = None

在这里插入图片描述

效果图为n_clusters = 4

在这里插入图片描述

六、高斯混合模型 - GMM

参考一文详解高斯混合模型原理 - 知乎 (zhihu.com)

1、概述(“多个高斯分布组合去拟合任意概率分布”)

GaussianMixtureModel(高斯混合模型,GMM):正太分布也叫高斯分布,正太分布的概率密度曲线也叫高斯分布概率曲线。

聚类算法大多数通过相似度来判断,而相似度又大多采用欧式距离长短作为衡量依据。而GMM采用了新的判断依据:概率,即通过属于某一类的概率大小来判断最终的归属类别。

GMM的基本思想就是:任意形状的概率分布都可以用多个高斯分布函数去近似,也就是说GMM就是有多个单高斯密度分布(Gaussian)组成的,每个Gaussian叫一个"Component",这些"Component"线性加权在一起就组成了 GMM 的概率密度函数,也就是下面的函数。

2、公式

GMM模型的数学公式如下:
p ( x ) = ∑ k = 1 K π k p ( x ∣ k ) p(x) = \sum_{k=1}^K \pi_k p(x|k) p(x)=k=1Kπkp(xk)

  • 其中 K K K模型的个数,即Component的个数(聚类的个数)

  • π k \pi_k πk为第 k k k个高斯分布(概率密度函数)的权重

  • p ( x ∣ k ) p(x|k) p(xk) 则为第 k k k高斯概率密度, 其均值为 μ k μ_k μk,方差为 σ k σ_k σk

3、代码

主要参数(详细参数

  • n_components :高斯模型的个数,即聚类的目标个数
  • covariance_type : 通过EM算法估算参数时使用的协方差类型,默认是"full"
  • full:每个模型使用自己的一般协方差矩阵
  • tied:所用模型共享一个一般协方差矩阵
  • diag:每个模型使用自己的对角线协方差矩阵
  • spherical:每个模型使用自己的单一方差
import matplotlib.pyplot as plt
from sklearn.datasets.samples_generator import make_blobs
from sklearn.mixture import GaussianMixture

# X为样本特征,Y为样本簇类别, 共1000个样本,每个样本2个特征,共4个簇,簇中心在[-1,-1], [0,0],[1,1], [2,2]
X, y = make_blobs(n_samples=1000, n_features=2, centers=[[-1,-1], [0,0], [1,1], [2,2]], cluster_std=[0.4, 0.3, 0.4, 0.3], 
                  random_state = 0)

##设置gmm函数
gmm = GaussianMixture(n_components=4, covariance_type='full').fit(X)
##训练数据
y_pred = gmm.predict(X)

##绘图
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.show()

在这里插入图片描述

4、高斯混合模型之分类 & 回归

七、K-means - K均值(★★)

核心:预设K个分类点,最小距离归类,means更新质心

参考

  • K-means:K个分类点,最小距离归类,means更新质心 https://zhuanlan.zhihu.com/p/78798251
  • K-means中K的确定 https://zhuanlan.zhihu.com/p/149441104
  • K-means聚类可视化 https://www.naftaliharris.com/blog/visualizing-k-means-clustering/
  • k-means sklearn学习笔记 https://blog.csdn.net/jiangkui007/article/details/82866942

1、概述

K-均值聚类可以是最常见的聚类算法,并涉及向群集分配示例,以尽量减少每个群集内的方差。
本文的主要目的是描述一种基于样本将 N 维种群划分为 k 个集合的过程。这个叫做“ K-均值”的过程似乎给出了在类内方差意义上相当有效的分区。
-源自:《关于多元观测的分类和分析的一些方法》1967年。

2、代码

它是通过 K-均值类实现的,要优化的主要配置是**“ n _ clusters ”超参数设置为数据中估计的群集数量**。

from joblib import dump, load
from numpy import unique
from numpy import where
from sklearn.datasets import make_classification
from sklearn.cluster import KMeans
from matplotlib import pyplot
# 定义数据集
X, _ = make_classification(n_samples=1000, n_features=2, n_informative=2, n_redundant=0, n_clusters_per_class=1, random_state=4)
# 定义模型
model = KMeans(n_clusters=10)
# 模型拟合
model.fit(X)
# 为每个示例分配一个集群
yhat = model.predict(X)
# 检索唯一群集
clusters = unique(yhat)
# 为每个群集的样本创建散点图
for cluster in clusters:
# 获取此群集的示例的行索引
row_ix = where(yhat == cluster)
# 创建这些样本的散布
pyplot.scatter(X[row_ix, 0], X[row_ix, 1])
# 绘制散点图
pyplot.show()

'''模型保存和加载'''
dump(model,"kmeans.joblib")
kmeans_temp = load("kmeans.joblib")
y = kmeans_temp.fit_predict(X)
print(y)
---
[2 9 9 2 8 0 2 1 1 1 0 7 7 0 3 0 0 7 7 7 0 1 5 7 8 3 2 0 2 2 9 2 2 5 0 4 4
 0 4 3 4 7 7 3 9 1 0 1 4 7 1 7 8 7 1 1 8 2 9 2 4 0 2 1 7 2 9 7 3 2 2 0 0 0
 8 9 3 9 8 2 4 4 0 2 1 9 8 7 0 2 7 3 9 0 1 1 7 7 7 2 3 2 1 3 0 6 3 0 2 5 5
 0 7 0 1 0 0 0 0 2 3 8 8 3 8 9 4 6 7 5 9 9 2 9 3 7 0 9 4 0 5 1 2 3 7 0 7 5
 ...
 4 5 1 1 8 4 0 9 8 1 7 7 5 9 1 5 7 0 4 4 2 9 4 8 1 3 1 8 8 3 9 9 2 9 4 8 9
 1 3 4 8 2 5 6 6 4 5 3 0 7 7 0 7 4 9 5 3 2 7 7 9 0 1 7 4 9 7 0 3 1 3 6 2 1
 7 1 1 3 0 9 3 4 0 2 4 3 7 0 8 4 2 5 7 6 8 7 2 3 3 0 5 2 1 5 0 8 0 1 0 9 0
 0 6 9 0 3 0 5 1 9 7 2 1 2 0 4 7 7 6 8 0 2 3 9 3 0 9 0 1 6 3 0 0 0 2 3 1 2
 2]

在这里插入图片描述

八、Mini-Batch K-均值

1、概述

Mini-Batch K-均值是 K-均值的修改版本,它使用小批量的样本而不是整个数据集对群集质心进行更新,这可以使大数据集的更新速度更快,并且可能对统计噪声更健壮。
…我们建议使用 k-均值聚类的迷你批量优化。与经典批处理算法相比,这降低了计算成本的数量级,同时提供了比在线随机梯度下降更好的解决方案。
—源自:《Web-Scale K-均值聚类》2010

2、代码

它是通过 MiniBatchKMeans 类实现的,要优化的主配置是**“ n _ clusters ”**超参数,设置为数据中估计的群集数量。

# mini-batch k均值聚类
from numpy import unique
from numpy import where
from sklearn.datasets import make_classification
from sklearn.cluster import MiniBatchKMeans
from matplotlib import pyplot
# 定义数据集
X, _ = make_classification(n_samples=1000, n_features=2, n_informative=2, n_redundant=0, n_clusters_per_class=1, random_state=4)
# 定义模型
model = MiniBatchKMeans(n_clusters=2)
# 模型拟合
model.fit(X)
# 为每个示例分配一个集群
yhat = model.predict(X)
# 检索唯一群集
clusters = unique(yhat)
# 为每个群集的样本创建散点图
for cluster in clusters:
# 获取此群集的示例的行索引
row_ix = where(yhat == cluster)
# 创建这些样本的散布
pyplot.scatter(X[row_ix, 0], X[row_ix, 1])
# 绘制散点图
pyplot.show()

九、OPTICS

1、概述

OPTICS 聚类( OPTICS 短于订购点数以标识聚类结构)是 DBSCAN 的修改版本。
我们为聚类分析引入了一种新的算法,它不会显式地生成一个数据集的聚类;而是创建表示其基于密度的聚类结构的数据库的增强排序。此群集排序包含相当于密度聚类的信息,该信息对应于范围广泛的参数设置。
—源自:《OPTICS :排序点以标识聚类结构》,1999

2、代码

它是通过 OPTICS 类实现的,主要配置是“ eps ”和“ min _ samples ”超参数。

# optics聚类
from numpy import unique
from numpy import where
from sklearn.datasets import make_classification
from sklearn.cluster import OPTICS
from matplotlib import pyplot
# 定义数据集
X, _ = make_classification(n_samples=1000, n_features=2, n_informative=2, n_redundant=0, n_clusters_per_class=1, random_state=4)
# 定义模型
model = OPTICS(eps=0.8, min_samples=10)
# 模型拟合与聚类预测
yhat = model.fit_predict(X)
# 检索唯一群集
clusters = unique(yhat)
# 为每个群集的样本创建散点图
for cluster in clusters:
# 获取此群集的示例的行索引
row_ix = where(yhat == cluster)
# 创建这些样本的散布
pyplot.scatter(X[row_ix, 0], X[row_ix, 1])
# 绘制散点图
pyplot.show()

十、亲和力传播

1、概述

亲和力传播包括找到一组最能概括数据的范例。
我们设计了一种名为“亲和传播”的方法,它作为两对数据点之间相似度的输入度量。在数据点之间交换实值消息,直到一组高质量的范例和相应的群集逐渐出现
—源自:《通过在数据点之间传递消息》2007

2、代码

它是通过 AffinityPropagation 类实现的,要调整的主要配置是将“ 阻尼 ”设置为0.5到1,甚至可能是“首选项”。

# 亲和力传播聚类
from numpy import unique
from numpy import where
from sklearn.datasets import make_classification
from sklearn.cluster import AffinityPropagation
from matplotlib import pyplot
# 定义数据集
X, _ = make_classification(n_samples=1000, n_features=2, n_informative=2, n_redundant=0, n_clusters_per_class=1, random_state=4)
# 定义模型
model = AffinityPropagation(damping=0.9)
# 匹配模型
model.fit(X)
# 为每个示例分配一个集群
yhat = model.predict(X)
# 检索唯一群集
clusters = unique(yhat)
# 为每个群集的样本创建散点图
for cluster in clusters:
# 获取此群集的示例的行索引
row_ix = where(yhat == cluster)
# 创建这些样本的散布
pyplot.scatter(X[row_ix, 0], X[row_ix, 1])
# 绘制散点图
pyplot.show()

十一、t-SNE(★★★★)

核心:将相似度关系转化为概率(softmax),在原空间中转为高斯分布概率,在嵌入空间中转化为t分布概率,优化方法是通过梯度下降的方式降低两空间的KL散度(相对熵)t-SNE适合降维可视化,分析样本间是否可分离(需提供y标签)不适合对样本分类。

t-SNE为t分布的随机邻域嵌入

参考

  • t-SNE聚类可视化 https://distill.pub/2016/misread-tsne/#perplexity=10&epsilon=5&demo=0&demoParams=16

  • t-SNE算法_CongliYin的博客-CSDN博客 https://blog.csdn.net/sinat_20177327/article/details/80298645

  • https://zhuanlan.zhihu.com/p/38274719

  • t-SNE主要用于高维数据的探索性分析 https://blog.csdn.net/scythe666/article/details/79203239,
    因此可以考虑对5维的眨眼特征采用t-SNE进行可视化,而不是多维散点图的形式

  • sklearn-t 分布随机邻域嵌入(t-SNE) https://www.scikitlearn.com.cn/0.21.3/21/#229-t-t-sne

1、t-SNE概述

参考 https://blog.csdn.net/hustqb/article/details/80628721

t-SNE可将样本点间的相似度关系转化为概率:在原空间(高维空间)中转化为基于高斯分布的概率;在嵌入空间(二维空间)中转化为基于t分布的概率。这使得t-SNE不仅可以关注局部(SNE只关注相邻点之间的相似度映射而忽略了全局之间的相似度映射,使得可视化后的边界不明显),还关注全局,使可视化效果更好(簇内不会过于集中,簇间边界明显)。

目标函数原空间与嵌入空间样本分布之间的KL散度
优化算法梯度下降
注意问题:KL散度作目标函数是非凸的,故可能需要多次初始化以防止陷入局部次优解。 (相对熵,又称为KL散度或者信息散度,是两个概率分布间差异的非对称度量。信息论中,相对熵等价于两个概率分布的信息熵的差值 https://zhuanlan.zhihu.com/p/144884251)

2、t-SNE优缺点

使用 t - SNE 的缺点大致如下:

  • t-SNE 的计算成本很高,在百万样本数据集上可能需要几个小时,而PCA将在几秒或几分钟内完成同样工作。
  • Barnes-Hut t-SNE 方法仅限于二维或三维嵌入。
  • 该算法是随机的,不同种子的多次重新开始可以产生不同的嵌入。然而,以最小的误差选择嵌入是完全合理的。
  • 未明确保留全局结构。用PCA初始化点(使用 init=’pca’ ),可以减轻此问题。

3、代码

参考 https://blog.csdn.net/hustqb/article/details/80628721

import numpy as np
import matplotlib.pyplot as plt
from sklearn import manifold, datasets
from joblib import dump,load

'''https://blog.csdn.net/hustqb/article/details/80628721'''
digits = datasets.load_digits(n_class=6)
X, y = digits.data, digits.target
n_samples, n_features = X.shape

'''显示原始数据'''
n = 20  # 每行20个数字,每列20个数字
img = np.zeros((10 * n, 10 * n))
for i in range(n):
    ix = 10 * i + 1
    for j in range(n):
        iy = 10 * j + 1
        img[ix:ix + 8, iy:iy + 8] = X[i * n + j].reshape((8, 8))
plt.figure(figsize=(8, 8))
plt.imshow(img, cmap=plt.cm.binary)
plt.xticks([])
plt.yticks([])
plt.show()

'''t-SNE'''
tsne = manifold.TSNE(n_components=2, init='pca', random_state=501)
X_tsne = tsne.fit_transform(X)  #Fit X into an embedded space and return that transformed output

print("Org data dimension is {}.Embedded data dimension is {}".format(X.shape[-1], X_tsne.shape[-1]))

'''嵌入空间可视化(带y标签,方便查看各样本的分解情况)'''
x_min, x_max = X_tsne.min(0), X_tsne.max(0)
X_norm = (X_tsne - x_min) / (x_max - x_min)  # 归一化
plt.figure(figsize=(8, 8))
for i in range(X_norm.shape[0]):
    '''同一标签同种颜色'''
    plt.text(X_norm[i, 0], X_norm[i, 1], str(y[i]), color=plt.cm.Set1(y[i]),
             fontdict={
    
    'weight': 'bold', 'size': 9})
plt.xticks([])
plt.yticks([])
plt.show()

'''tsne不能预测类别,只能起到降维可视化数据的作用(没有predict func)'''
# dump(tsne,"tSNE.joblib")
# tsne_temp = load("tSNE.joblib")
---
Org data dimension is 64.Embedded data dimension is 2

猜你喜欢

转载自blog.csdn.net/qq_33934427/article/details/130920168