知识发现 发现事物之间的潜在关系
异常值检测
特征提取 数据压缩的例子
有监督:
给定训练集 X 和 标签Y
选择模型
根据生成的一组参数进行预测分类等任务
无监督:
拿到的数据只有X ,没有标签,只能根据X的相似程度做一些事情。
Clustering 聚类
降维算法,数据特征变少
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ftmw4PX0-1637635051050)(./images/1-聚类.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bepJWqwu-1637635051057)(./images/2-相似度.png)]
每一条数据都可以理解为多维空间中的一个点。
可以根据点和点之间的距离来评价数据间的相似度
近朱者赤近墨者黑!
欧氏距离:
d = ( x 1 − x 2 ) 2 + ( y 1 − y 2 ) 2 d = \sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2} d=(x1−x2)2+(y1−y2)2
d = ( x 1 − x 2 ) 2 + ( y 1 − y 2 ) 2 + ( z 1 − z 2 ) 2 d = \sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2 + (z_1 - z_2)^2} d=(x1−x2)2+(y1−y2)2+(z1−z2)2
d ( X , Y ) = ∣ x 1 − y 1 ∣ p + ∣ x 2 − y 2 ∣ p + … + ∣ x n − y n ∣ p p d(X,Y) = \sqrt[p]{|x_1 - y_1|^p + |x_2 - y_2|^p + … + |x_n - y_n|^p} d(X,Y)=p∣x1−y1∣p+∣x2−y2∣p+…+∣xn−yn∣p
P = 1 曼哈顿距离
P = 2 欧氏距离,就是两点之间的直线距离(以下简称欧氏距离)
P = 无穷,切比雪夫距离 ,哪个维度差值最大就是哪个差值作为距离。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PRN63YyQ-1637635051060)(./images/3-切比雪夫.png)]
将数据看做空间中的点的时候,评价远近可以用欧氏距离或者余弦距离。
计算过程如下:
c o s θ = a ⋅ b ∣ ∣ a ∣ ∣ 2 ∣ ∣ b ∣ ∣ 2 cos\theta = \frac{a \cdot b}{||a||_2||b||_2} cosθ=∣∣a∣∣2∣∣b∣∣2a⋅b
c o s θ = x 1 x 2 + y 1 y 2 x 1 2 + y 1 2 × x 2 2 + y 2 2 cos\theta = \frac{x_1x_2 + y_1y_2}{\sqrt{x_1^2 + y_1^2} \times \sqrt{x_2^2 + y_2^2}} cosθ=x12+y12×x22+y22x1x2+y1y2
将N个样本映射到K个簇中
每个簇至少有一个样本
基本思路:
先给定K个划分,迭代样本与簇的隶属关系,每次都比前一次好一些
迭代若干次就能得到比较好的结果
算法步骤:
选择K个初始的簇中心
逐个计算每个样本到簇中心的距离,将样本归属到距离最小的那个簇中心的簇中
每个簇内部计算平均值,更新簇中心
开始迭代
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PcwUmHkJ-1637635051069)(./images/4-Kmeans.gif)]
聚类过程如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T1MrLSxZ-1637635051073)(./images/5-Kmeans.png)]
优点:
缺点
KaTeX parse error: Got function '\min' with no arguments as argument to '\underset' at position 44: …et{\mu_j \in C}\̲m̲i̲n̲(||x_i - \mu_j|…
其中 μ j = 1 ∣ C j ∣ ∑ x ∈ C j x \mu_j = \frac{1}{|C_j|}\sum\limits_{x \in C_j}x μj=∣Cj∣1x∈Cj∑x是簇的均值向量,或者说是质心。
其中 ∣ ∣ x i − μ j ∣ ∣ 2 ||x_i - \mu_j||^2 ∣∣xi−μj∣∣2代表每个样本点到均值点的距离(其实也是范数)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-joJzQFGo-1637635051076)(./images/6-Kmeans过程.png)]
亚洲国家队划分:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
import pandas as pd
# 需要将亚洲国家队,分成三个类别
# 只有历年的统计数据,没有目标值(类别,等级)
data = pd.read_csv('./AsiaFootball.txt')
data
# 执行多次,分类结果会有所不同
kmeans = KMeans(n_clusters=3)
# 无监督,只需要给数据X就可以
kmeans.fit(data.iloc[:,1:])
y_ = kmeans.predict(data.iloc[:,1:])# 聚类算法预测、划分的类别
c = data['国家'].values
for i in range(3):
cond = y_ == i#索引条件
print('类别是%d的国家有:'%(i),c[cond])
类别是0的国家有: ['中国' '伊拉克' '卡塔尔' '阿联酋' '泰国' '越南' '阿曼' '印尼'] 类别是1的国家有: ['伊朗' '沙特' '乌兹别克斯坦' '巴林' '朝鲜'] 类别是2的国家有: ['日本' '韩国']
数据可视化:
plt.rcParams['font.family'] = 'STKaiti'
fig = plt.figure(figsize=(12,9))
ax = plt.axes(projection = '3d')
ax.scatter(data.iloc[:,1],data.iloc[:,2],data.iloc[:,3],c = y_,s = 100)
ax.set_xlabel('2006年世界杯',fontsize = 18)
ax.set_ylabel('2010年世界杯',fontsize = 18)
ax.set_zlabel('2007亚洲杯',fontsize = 18)
# 调整视图角度
ax.view_init(elev = 20,azim = -60)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0tSqQKQh-1637635051078)(./images/7-亚洲队等级划分.png)]
轮廓系数:
针对某个样本的轮廓系数s为:$ s= \frac{b - a}{max(a, b)}$
聚类总的轮廓系数SC为: S C = 1 N ∑ i = 1 N s i SC = \frac{1}{N}\sum\limits_{i = 1}^Ns_i SC=N1i=1∑Nsi,所有样本的 s i s_i si的均值称为聚类结果的轮廓系数,是该聚类是否合理、有效的度量。
import numpy as np
from sklearn import datasets
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
# 聚类:轮廓系数,对聚类的评价指标,对应数学公式
from sklearn.metrics import silhouette_score
# 创建数据
# 假数据,数据X划分成3类
X,y = datasets.make_blobs(centers=3)
plt.scatter(X[:,0],X[:,1],c = y)
# 指定不同的k,寻找最佳聚类类别数目
# 可以画图,一目了然,数据简单,属性只有两个,所以可以画图
# 属性多,无法可视化,评价指标
# 轮廓系数
plt.rcParams['font.sans-serif'] = 'KaiTi'
plt.rcParams['font.size'] = 18
plt.rcParams['axes.unicode_minus'] = False
score = []
for i in range(2,7):
kmeans = KMeans(n_clusters=i)
kmeans.fit(X)
y_ = kmeans.predict(X)# 预测类别 == 标签
# plt.scatter(X[:,0],X[:,1],c = y_)
score.append(silhouette_score(X,y_))
# print('当聚类类别是6的时候,评价指标轮廓系数: ',silhouette_score(X,y_))
plt.plot(range(2,7),score)
plt.xlabel('K值')
plt.ylabel('轮廓系数',c = 'red')
# 结论:,当k值是3的时候,轮廓系数最大,这个时候,说明划分效果最好!
效果图如下:(注意数据随机生成,数据展示的图片效果不是固定的~)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4wU2jA5o-1637635051080)(./images/8-聚类数据.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AH8KJalH-1637635051083)(./images/9-轮廓系数.png)]
调整兰德系数:
公式了解一下即可:
RI = a + b C 2 n s a m p l e s \text{RI} = \frac{a + b}{C_2^{n_{samples}}} RI=C2nsamplesa+b
用C表示实际的类别划分,K表示聚类结果。
定义a 为在C中被划分为同一类,在K中被划分为同一簇的实例对数量。
定义b为在C中被划分为不同类别,在K中被划分为不同簇的实例对数量。
兰德系数范围是[0,1]
调整兰德系数为:
ARI = RI − E [ RI ] max ( RI ) − E [ RI ] \text{ARI} = \frac{\text{RI} - E[\text{RI}]}{\max(\text{RI}) - E[\text{RI}]} ARI=max(RI)−E[RI]RI−E[RI]
范围为[-1,1]
from sklearn.metrics import adjusted_rand_score# 调整兰德系数
score = []
for i in range(2,7):
kmeans = KMeans(n_clusters=i)
kmeans.fit(X)
y_ = kmeans.predict(X)# 预测类别 == 标签
score.append(adjusted_rand_score(y,y_))
plt.plot(range(2,7),score)
plt.xlabel('K值')
plt.ylabel('调整兰德系数',c = 'red')
# 结论:,当k值是3的时候,轮廓系数最大,这个时候,说明划分效果最好!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AGR38HIg-1637635051088)(./images/10-兰德系数.png)]
import matplotlib.pyplot as plt # plt 用于显示图片
from sklearn.cluster import KMeans
import numpy as np
plt.figure(figsize=(8,4))
# 加载图片显示原图
pixel = plt.imread('11-bird.png')
plt.subplot(1,2,1)
plt.imshow(pixel)
# 聚类运算,压缩图片
pixel = pixel.reshape((128*128 , 3))
kmeans = KMeans(n_clusters=8).fit(pixel)
# 聚类结果合成新图片
newPixel = kmeans.cluster_centers_[kmeans.labels_].reshape(128,128,3)
plt.subplot(1,2,2)
plt.imshow(newPixel)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YYPNhqXO-1637635051092)(./images/12-图片压缩.png)]
DBSCAN(Density-Based Spatial Clustering of Applications with Noise,具有噪声的基于密度的聚类方法)是一种基于密度的空间聚类算法。 该算法将具有足够密度的区域划分为簇,并在具有噪声的空间数据库中发现任意形状的簇,它将簇定义为密度相连的点的最大集合。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aZfKn0xB-1637635051094)(./images/13-DBSCAN.png)]
下面这些点是分布在样本空间的众多样本,现在我们的目标是把这些在样本空间中距离相近的聚成一类。我们发现A点附近的点密度较大,红色的圆圈根据一定的规则在这里滚啊滚,最终收纳了A附近的5个点,标记为红色也就是定为同一个簇。其它没有被收纳的根据一样的规则成簇。(形象来说,我们可以认为这是系统在众多样本点中随机选中一个,围绕这个被选中的样本点画一个圆,规定这个圆的半径以及圆内最少包含的样本点,如果在指定半径内有足够多的样本点在内,那么这个圆圈的圆心就转移到这个内部样本点,继续去圈附近其它的样本点,类似传销一样,继续去发展下线。等到这个滚来滚去的圈发现所圈住的样本点数量少于预先指定的值,就停止了。那么我们称最开始那个点为核心点,如A,停下来的那个点为边界点,如B、C,没得滚的那个点为离群点,如N)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zu4YYle3-1637635051096)(./images/14-DBSCAN.png)]
基于密度这点有什么好处呢,我们知道Kmeans聚类算法只能处理球形的簇,也就是一个聚成实心的团(这是因为算法本身计算平均距离的局限)。但往往现实中还会有各种形状,比如下面两张图,环形和不规则形,这个时候,那些传统的聚类算法显然就悲剧了。于是就思考,样本密度大的成一类呗。这就是DBSCAN聚类算法。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-otEmO68X-1637635051099)(./images/15-DBSCAN.gif)]
网站动画解析
参数一eps:
DBSCAN算法参数,即我们的eps邻域的距离阈值,和样本距离超过eps的样本点不在eps邻域内。默认值是0.5.一般需要通过在多组值里面选择一个合适的阈值。eps过大,则更多的点会落在核心对象的eps邻域,此时我们的类别数可能会减少, 本来不应该是一类的样本也会被划为一类。反之则类别数可能会增大,本来是一类的样本却被划分开。
参数二min_samples:
DBSCAN算法参数,即样本点要成为核心对象所需要的eps邻域的样本数阈值。默认值是5。一般需要通过在多组值里面选择一个合适的阈值。通常和eps一起调参。在eps一定的情况下,min_samples过大,则核心对象会过少,此时簇内部分本来是一类的样本可能会被标为噪音点,类别数也会变多。反之min_samples过小的话,则会产生大量的核心对象,可能会导致类别数过少。
参数与三metrics:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oQyRdvs2-1637635051101)(./images/16-metrics.png)]
import numpy as np
from sklearn import datasets
from sklearn.cluster import KMeans,DBSCAN
import matplotlib.pyplot as plt
# y中是两类:0,1
X,y = datasets.make_circles(n_samples=1000,noise=0.05,factor = 0.5)
# centers = [(1.5,1.5)] 元组,代表着,中心点的坐标值
# y1一类:0 + 2
X1,y1 = datasets.make_blobs(n_samples=500,n_features=2,centers=[(1.5,1.5)],cluster_std=0.2)
# 将circle和散点进行了数据合并
X = np.concatenate([X,X1])
y = np.concatenate([y,y1 + 2])
plt.scatter(X[:,0],X[:,1],c = y)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kvJosSLU-1637635051103)(./images/17-密度数据.png)]
# 根据距离,划分‘势力范围’
kmeans = KMeans(3)
kmeans.fit(X)
y_ = kmeans.labels_
plt.scatter(X[:,0],X[:,1],c = y_)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PNCZGhCO-1637635051105)(./images/18-Kmeans聚类密度数据.png)]
dbscan = DBSCAN(eps = 0.2,min_samples=3)
dbscan.fit(X)
y_ = dbscan.labels_
plt.scatter(X[:,0],X[:,1],c = y_)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RynvBvRF-1637635051108)(./images/19-DBSCAN聚类密度数据.png)]
分层聚类输出层次结构,这种结构比平面聚类返回的非结构化聚类集更具信息性。
分层聚类法(hierarchical cluster method)一译“系统聚类法”。聚类分析的一种方法。其做法是开始时把每个样品作为一类,然后把最靠近的样品(即距离最小的群品)首先聚为小类,再将已聚合的小类按其类间距离再合并,不断继续下去,最后把一切子类都聚合到一个大类。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SbeEHK0k-1637635051110)(./images/20-分层聚类.png)]
一般来说,当考虑聚类效率时,我们选择平面聚类,当平面聚类的潜在问题(不够结构化,预定数量的聚类,非确定性)成为关注点时,我们选择层次聚类。 此外,许多研究人员认为,层次聚类比平面聚类产生更好的聚类。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1R9kUYVS-1637635051113)(./images/21-层次聚类.png)]
层次聚类(Hierarchical Clustering)是聚类算法的一种,通过计算不同类别数据点间的相似度来创建一棵有层次的嵌套聚类树。在聚类树中,不同类别的原始数据点是树的最低层,树的顶层是一个聚类的根节点。创建聚类树有自下而上合并和自上而下分裂两种方法。
我们着重看一下自底向上的合并算法:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FG9XDidB-1637635051116)(./images/22-自底向上.png)]
两个组合数据点间的距离:
n_clusters
划分类别数目
linkage
度量两个子类的相似度时所依据的距离
connectivity
连接性约束,作用:只有相邻的簇才能合并在一起,进行聚类!
导包
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d as p3
from sklearn.cluster import AgglomerativeClustering
from sklearn.datasets import make_swiss_roll
创建数据
X,y = datasets.make_swiss_roll(n_samples=1500,noise = 0.05)
fig = plt.figure(figsize=(12,9))
a3 = fig.add_subplot(projection = '3d')
a3.scatter(X[:,0],X[:,1],X[:,2],c = y)
a3.view_init(10,-80)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e9MIaEC7-1637635051121)(./images/24-分层聚类数据展示.png)]
Kmeans聚类效果
# Kmeans只负责分类,随机性,类别是数字几,不固定
clf = KMeans(n_clusters=6)
clf.fit(X)
y_ = clf.labels_
fig = plt.figure(figsize=(12,9))
a3 = plt.subplot(projection = '3d')
a3.scatter(X[:,0],X[:,1],X[:,2],c = y_)
a3.view_init(10,-80)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6mnhQEBh-1637635051124)(./images/26-Kmeans聚类划分效果.png)]
分层聚类
agg = AgglomerativeClustering(n_clusters=6,linkage='ward')# 最近的距离,作为标准,
agg.fit(X)
y_ = agg.labels_
fig = plt.figure(figsize=(12,9))
a3 = plt.subplot(projection = '3d')
a3.scatter(X[:,0],X[:,1],X[:,2],c = y_)
a3.view_init(10,-80)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-58dBnhVO-1637635051126)(./images/25-分层聚类划分效果.png)]
对于这种非欧几何的数据下,可见如果没有设置连接性约束,将会忽视其数据本身的结构,强制在欧式空间下聚类,于是很容易形成了上图这种跨越流形的不同褶皱。
分层聚类改进(连接性约束,对局部结构进行约束)
from sklearn.neighbors import kneighbors_graph# graph图形的意思
# 邻居数量变少,认为,条件宽松
conn = kneighbors_graph(X,n_neighbors=10) #采用邻居,进行约束
agg = AgglomerativeClustering(n_clusters=6,connectivity=conn,linkage='ward')# 最近的距离,作为标准,
agg.fit(X)
y_ = agg.labels_
fig = plt.figure(figsize=(12,9))
a3 = fig.add_subplot(projection = '3d')
a3.scatter(X[:,0],X[:,1],X[:,2],c = y_)
a3.view_init(10,-80)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u5bPXYxC-1637635051130)(./images/27-分层聚类连接性约束划分效果.png)]
)]
对于这种非欧几何的数据下,可见如果没有设置连接性约束,将会忽视其数据本身的结构,强制在欧式空间下聚类,于是很容易形成了上图这种跨越流形的不同褶皱。
分层聚类改进(连接性约束,对局部结构进行约束)
from sklearn.neighbors import kneighbors_graph# graph图形的意思
# 邻居数量变少,认为,条件宽松
conn = kneighbors_graph(X,n_neighbors=10) #采用邻居,进行约束
agg = AgglomerativeClustering(n_clusters=6,connectivity=conn,linkage='ward')# 最近的距离,作为标准,
agg.fit(X)
y_ = agg.labels_
fig = plt.figure(figsize=(12,9))
a3 = fig.add_subplot(projection = '3d')
a3.scatter(X[:,0],X[:,1],X[:,2],c = y_)
a3.view_init(10,-80)