聚类算法
- 算法概括
- 聚类(clustering)
- 聚类的概念
- 聚类的要求
- 聚类与分类的区别
- 常见算法分类
- 聚类算法中存在的问题
- 距离度量
- 闵可夫斯基距离
- 欧式距离(欧几里得距离)
- 曼哈顿距离
- 切比雪夫距离
- 皮尔逊相关系数
- 余弦相似度
- 杰卡德相似系数
- 划分聚类
- K-means聚类算法
- 算法原理
- 基本概念
- 算法实例
- 题目背景
- k-means的手动实现
- sklearn库中K-means算法
- 聚类分析的度量
算法概括
机器学习有两种学习类型:
- 有监督学习:即数据点有已知的结果。
- 无监督学习:即数据点没有已知的结果,利用无标签的数据学习数据的分布或数据与数据之间的关系被称作无监督学习。
注:
①有监督学习和无监督学习的最大区别在于数据是否有标签。
②无监督学习最常应用的场景是聚类和降维,聚类算法用于识别数据中未知的结构,降维则是使用数据中的结构特征来简化数据。
聚类(clustering)
聚类的概念
- 聚类就是根据数据的“相似性”将数据分为多类的过程。
- 聚类把各不相同的个体分割为有更多相似子集合的工作。
- 聚类生成的子集合称为簇。
聚类的要求
- 生成的簇内部的任意两个对象之间具有较高的相似度。
- 属于不同簇的两个对象间具有较高的相异度
聚类与分类的区别
之前学习过k近邻算法分类算法,分类和聚类听上去好像很相似,但是两者完全是不同的应用和原理。
例如,根据下图的四个属性进行预测某一输入的所属类别:
概括而来就是这样一个流程:
可以看出训练样本是有明确的标签的,数据点是有已知结果的,而聚类不同,聚类算法本身训练的样本就是无标签的,你不知道它属于哪一类,而把具有空间相近性、性质相似性的数据点归为一类,这就是聚类算法要做的事情。
还是上面的例子:
这个时候训练样本的标签被盖住了,我们必须从这四个属性入手,把样本聚合成不同的簇,每个簇中的数据点的属性最相似。
概括而来就是这样一个过程:
现在小结一下,分类和聚类的区别概括而来就是这样:
分类:学习/训练有监督,训练样本有明确标签。
聚类:学习/训练过程无监督,样本无明确标签。
聚类与分类的区别在于聚类不依赖于预先定义的类,没有预定义的类和样本——聚类是一种无监督的数据挖掘任务。
常见算法分类
- 划分聚类: 大部分方法是基于距离的聚类算法。如:K-Means、K-Medoids、CLARANS等。
- 层次聚类: 例如:BIRCH、CURE、CHAMELEON等。层次聚类可采用“自底向上”或“自顶向下”方案。在“自底向上”方案中,初始时每一个数据纪录都被视作一个单独的簇,接着再把那些相互邻近的簇合并成一个新的簇,直到所有的记录都在一个簇或者满足某个终止条件为止。
- 密度聚类: 该方法是基于(结点)密度的聚类算法,主要算法有:DBSCAN、OPTICS、DENCLUE等。只要一个区域中的点的密度大于某个阈值,就把它加到与之相近的聚类中去。
- 网格聚类: 主要算法有:STING、CLIQUE、WAVE-CLUSTER。将数据空间按某种特征(属性)划分成网格,聚类处理以网格(单元)为基本单位。
注:
①后边三种聚类不做介绍,主要以划分聚类中的K-Means算法作为本章学习重点。
②需要说明的是,这些算法本身无所谓优劣,而最终运用于数据的效果却存在好坏差异,这在很大程度上取决于数据使用者对于算法的选择是否得当。
聚类算法中存在的问题
- ①高维数据集中存在大量无关的属性,所有维中存在簇的可能性几乎为零。
- ②高维空间中数据较低维空间中数据分布稀疏,其中数据间距离几乎相等是普遍现象,而传统聚类方法是基于距离进行聚类的,因此在高维空间中无法基于距离来构建簇。
距离度量
评估两个不同样本之间的“相似性”,通常使用的方法就是计算两个样本之间的“距离”,使用不同的方法计算样本间的距离关系到聚类结果的好坏。
大多数聚类分析是以相似性计算为基础的,同一个聚类中的个体模式相似,不在同一个聚类中的个体模式则相异。目前,相似性距离的计算都是基于向量的,也就是计算两个向量的距离,距离相近则相似度越大。
下面,介绍几种常见的距离计算方法。
闵可夫斯基距离
闵可夫斯基距离(Minkowski Distance)是一种常见的方法,用于衡量数值点之间距离。
假设 X ( x 1 , x 2 , . . . , x n ) , Y ( y 1 , y 2 , . . . , y n ) X(x_1,x_2,...,x_n),Y(y_1,y_2,...,y_n) X(x1,x2,...,xn),Y(y1,y2,...,yn)是n维空间的两个向量,那么,闵可夫斯基距离定义为:
d i s t ( X , Y ) = ∑ k = 1 n ∣ x k − y k ∣ p p dist(X,Y)=\sqrt[p]{\textstyle \sum_{k=1}^{n} |x_k-y_k|^p} dist(X,Y)=p∑k=1n∣xk−yk∣p
注:该距离最常用的p是2和1,前者是欧几里得距离,后者是曼哈顿距离。当p趋近于无穷大时,闵可夫斯基距离转化为切比雪夫距离。
闵可夫斯基距离计算距离如下:
import numpy as np
x=np.random.random(10)
y=np.random.random(10)
dist=np.linalg.norm(x-y,ord=4)#闵可夫斯基距离,此时p=4
欧式距离(欧几里得距离)
欧式距离(Euclidean Distance)最初用于计算欧几里得空间中两个点的距离。假设 X ( x 1 , x 2 , . . . , x n ) , Y ( y 1 , y 2 , . . . , y n ) X(x_1,x_2,...,x_n),Y(y_1,y_2,...,y_n) X(x1,x2,...,xn),Y(y1,y2,...,yn)是n维空间的两个向量,它们之间的欧几里得距离是:
d i s t ( X , Y ) = ∑ k = 1 n ( x k − y k ) 2 p dist(X,Y)=\sqrt[p]{\textstyle \sum_{k=1}^{n} (x_k-y_k)^2} dist(X,Y)=p∑k=1n(xk−yk)2
n=2欧几里得距离就是平面上两个点的距离。如果欧式距离看作物品相似程度,那么距离越近就越相似,也就是说距离越小,相似度越大。
欧式距离计算举例如下:
import numpy as np
import scipy.spatial.distance as dis
x=np.random.random(10)
y=np.random.random(10)
X=np.vstack([x,y])
dist=dis.pdist(X,metric='euclidean')
#或者直接按照闵可夫斯基距离的计算方式
dist=np.linalg.norm(x-y,ord=2)
曼哈顿距离
曼哈段距离也称为城市街区距离(City Block distance),或绝对距离。即在欧几里得空间的固定直角坐标系上两点所形成的线段对轴的投影距离总和。
坐标 ( x 1 , y 1 ) (x_1,y_1) (x1,y1)的点 P 1 P_1 P1与坐标 ( x 2 , y 2 ) (x_2,y_2) (x2,y2)的点 P 2 P_2 P2的曼哈顿距离为:
d i s t ( P 1 , P 2 ) = ∣ x 1 − x 2 ∣ + ∣ y 1 − y 2 ∣ dist(P_1,P_2)=|x_1-x_2|+|y_1-y_2| dist(P1,P2)=∣x1−x2∣+∣y1−y2∣
曼哈顿距离计算Python语句如下:
import numpy as np
x=np.random.random(10)
y=np.random.random(10)
dist=np.linalg.norm(x-y,ord=1)
切比雪夫距离
闵可夫斯基距离定义中,当p= + ∞ +\infty +∞时,称为切比雪夫距离(Chebyshev Distance)。
假设 X ( x 1 , x 2 , . . . , x n ) , Y ( y 1 , y 2 , . . . , y n ) X(x_1,x_2,...,x_n),Y(y_1,y_2,...,y_n) X(x1,x2,...,xn),Y(y1,y2,...,yn)是n维空间的两个向量,它们之间的切比雪夫距离是:
d i s t ( X , Y ) = lim n → ∞ ) ( ∑ i = 1 n ∣ x i − y i ∣ k ) 1 k = max ( ∣ x i − y i ∣ ) , 1 ≤ i ≤ n dist(X,Y) = \lim_{n \to \infty})(\sum_{i=1}^{n}|x_i-y_i|^k)^\frac{1}{k} = \max(|x_i-y_i|), 1 \leq i \leq n dist(X,Y)=n→∞lim)(i=1∑n∣xi−yi∣k)k1=max(∣xi−yi∣),1≤i≤n
切比雪夫距离计算Python语句如下:
import numpy as np
x=np.random.random(10)
y=np.random.random(10)
dist=np.linalg.norm(x-y,ord=np.inf)
皮尔逊相关系数
皮尔逊相关系数(Pearson Correlation Coeffient)即相关分析中的相关系数r,一般用于计算两个定距变量间联系的紧密程度,它的取值在[-1,+1]之间。
当相关系数为0时,X和Y两变量无线性关系(不代表没有除了线性关系外的其他关系);当X的值增大,Y也增大,正相关关系,相关系数在0.00与1.00之间;当X的值增大,Y减小,负相关关系,相关系数在-1.00与0.00之间。相关系数的绝对值越大,相关性越强,相关系数越接近于1和-1,相关度越强,相关系数越接近于0,相关度越弱。
公式如下:
r ( x , y ) = E ( x y ) − E ( x ) ( y ) E ( x 2 ) − ( E ( x ) ) 2 E ( y 2 ) − ( E ( y ) ) 2 = c o v ( x , y ) σ x σ y r(x,y) = \frac{E(xy)-E(x)(y)}{\sqrt[]{E(x^2)-(E(x))^2}{\sqrt[]{E(y^2)-(E(y))^2}}} = \frac{cov(x,y)}{\sigma_x\sigma_y} r(x,y)=E(x2)−(E(x))2E(y2)−(E(y))2E(xy)−E(x)(y)=σxσycov(x,y)
皮尔逊相关系数计算Python语句如下:
import numpy as np
import scipy.spatial.distance as dis
x=np.random.random(10)
y=np.random.random(10)
X=np.vstack([x,y])
dist=1-dis.pdist(X,metric='correlation')
余弦相似度
余弦相似度就是两个向量之间的夹角的余弦值。假设 X ( x 1 , x 2 , . . . , x n ) , Y ( y 1 , y 2 , . . . , y n ) X(x_1,x_2,...,x_n),Y(y_1,y_2,...,y_n) X(x1,x2,...,xn),Y(y1,y2,...,yn)是n维空间的两个向量,它们之间的余弦相似度是:
cos θ = X Y ∣ X ∣ ∣ Y ∣ \cos \theta = \frac{XY}{|X||Y|} cosθ=∣X∣∣Y∣XY
余弦相似度用向量空间中两个向量夹角的余弦值作为衡量两个个体间差异的大小。相比距离向量,余弦相似度更加注重两个向量在方向上的差异,而非距离或长度。
夹角余弦取值范围为[-1,1]。夹角余弦越大表示两个向量的夹角越小,夹角余弦越大表示两个向量的夹角越大。当两个向量的方向重合时余弦取最大值1,当两个向量的方向完全相反夹角余弦取最小值-1。
余弦相似度计算Python语句如下:
import numpy as np
import scipy.spatial.distance as dis
x=np.random.random(10)
y=np.random.random(10)
X=np.vstack([x,y])
dist=1-dis.pdist(X,metric='cosine')
欧几里得vs余弦距离
- 欧几里得距离适合于基于坐标的度量。
- 余弦距离更适合那些出现位置不重要的数据,例如文本数据。
- 欧几里得距离对维度灾难更敏感。
杰卡德相似系数
Jaccard系数主要用于计算符号度量或布尔值度量的个体间的相似度,只关心个体间共同具有的特征是否一致这个问题。假设集合 A和 B,两个集合的杰卡德相似系数表示如下:
J ( A , B ) = ∣ A ∩ B ∣ ∣ A ∪ B ∣ J(A,B)= \frac {|A∩B|}{|A∪B|} J(A,B)=∣A∪B∣∣A∩B∣
杰卡德相似距离计算Python语句如下:
import numpy as np
import scipy.spatial.distance as dis
x=np.random.random(10)
y=np.random.random(10)
X=np.vstack([x,y])
dist=dis.pdist(X,metric='jaccard')
划分聚类
K-means聚类算法
算法原理
k-means算法以k为参数,把n个对象分为k个簇,使簇内具有较高的相似度,而簇间的相似度较低。
其处理过程如下:
①随机选择k个点作为初始的聚类中心。
②对于剩下的点,根据其与聚类中心的距离,将其归入最近的簇。
③对于每个簇,计算所有点的均值作为新的聚类中心。
④重复2、3直到聚类中心不再发生改变。
算法流程如下所示:
如下图所示为聚类A、B、C、D、E五个点的聚类中心的选取过程:
基本概念
要得到簇的个数,需要指定K值。
质心:均值,即向量各维取平均即可。
距离的度量:常用欧几里得距离和余弦相似度(先标准化)。
优化目标: min ∑ i = 1 K ∑ x ∈ C i d i s t ( c i , x ) 2 \min \sum_{i=1}^{K}\sum_{x \in C_i}^{}dist(c_i,x)^2 min∑i=1K∑x∈Cidist(ci,x)2
算法实例
题目背景
练习算法实例,要求做到:
1、理解程序中每个函数以及每个变量的含义;
2、掌握k-means算法的实现过程;
3、使用k-means算法对下表中的5个样本进行聚类(k=2)。
k-means的手动实现
import numpy as np
def kmeans(X, k, max_iter=300):
# 随机选择k个初始质心
centroids = X[np.random.choice(X.shape[0], k)]
for i in range(max_iter):
# 计算每个样本点到质心的距离,并分配到最近质心所在的簇中
distances = np.sqrt(((X - centroids[:, np.newaxis])**2).sum(axis=2))
labels = distances.argmin(axis=0)
# 重新计算每个簇的质心
new_centroids = np.array([X[labels == j].mean(axis=0) for j in range(k)])
# 检查质心是否变化,若没有则退出
if np.all(centroids == new_centroids):
break
centroids = new_centroids
return labels, centroids
X=np.array([[170,70],[178,75],[100,100],[120,40],[10,0.1]])
labels,centroids=kmeans(X,k=2)
print("当k=3时,簇划分情况为:",labels)
print("当k=3时,质心为:\n",centroids)
sklearn库中K-means算法
scikit-learn模块提供了k-Means聚类方法,原型为:
class sklearn.cluster.KMeans(n_clusters=8, init=’k-means++’, n_init=10, max_iter=300, tol=0.0001, precompute_distances=’auto’, verbose=0, random_state=None, copy_x=True, n_jobs=1, algorithm=’auto’)
主要参数包括:
- n_clusters:整型,可选,默认参数值为8,聚类数量。
- init:‘k-means++’,‘random’或者ndarray之一,默认为’k-means++’。
’k-means++’: 以一种巧妙的方式选择k-均值聚类的初始集群中心,以加快收敛速度。
‘random’:从初始质心的数据中随机选取 k 观察 (行)。
ndarray:给出形状 (n_clusters, n_features)的初始中心。- n_init:整型,默认参数值为10。用不同的初始化质心运行算法的次数。由于k-Means是结果受初始值影响的局部最优的迭代算法,因此需要多跑几次以选择一个较好的聚类效果。
- max_iter:整型,默认参数值为300,最大的迭代次数。
- tol:浮点型,默认参数值为0.0001,最小容忍误差,当误差小于tol就会退出迭代。
- algorithm:可以是‘auto’,‘full’或者’elkan’之一,默认参数值为’auto’。’full’适合于EM类算法;’elkan’适合于三角形不等式,但暂不支持稀疏数据;而当设置为’auto’时,稠密数据用’elkan’,稀疏数据用’full’。
- random_state:整型,RandonState实例或None,默认参数值为None。具体如下:
int:该参数用于设置随机数发生器的种子;
RandonState instance:该参数是一个随机数发生器;
None:使用np.random作为随机数发生器。
import numpy as np
from sklearn.cluster import KMeans
#使用k-means算法对数据进行聚类
X=np.array([[170,70],[178,75],[100,100],[120,40],[10,0.1]])
kmeans_model=KMeans(n_clusters=2,init="k-means++")
kmeans_model.fit(X)
print("当k=2时,簇划分情况为:",kmeans2_model.labels_)
print("当k=2时,质心为:\n",kmeans2_model.cluster_centers_)
聚类分析的度量
- 聚类分析的度量指标用于对聚类结果进行评判,分为内部指标和外部指标两大类:
外部指标指用事先指定的聚类模型作为参考来评判聚类结果的好坏。
内部指标是指不借助任何外部参考,只用参与聚类的样本评判聚类结果好坏。- 聚类的目标是得到较高的簇内相似度和较低的簇间相似度,使得簇间的距离尽可能大,簇内样本与簇中心的距离尽可能小。
- 聚类得到的簇可以用聚类中心、簇大小、簇密度和簇描述等来表示:
聚类中心是一个簇中所有样本点的均值(质心)。
簇大小表示簇中所含样本的数量。
簇密度表示簇中样本点的紧密程度。
簇描述是簇中样本的业务特征。
注:初始质心的选择和聚类簇数k的选择都会对聚类结果产生影响,它们的选择会导致不同的聚类效果,因此需要进行多次实验,选择最优的初始质心、聚类簇数k。在极端情况下,有时候会出现局部最优解问题,即算法陷入局部最优解,无法到达全局最优解。总的来说,KMeans算法具有一定的随机性。
未完待续~~