机器学习_聚类

聚类就是对无标签样本的特征的相似度进行度量,使类内相似度大,类间相似度小。

一、相似度度量

在这里插入图片描述
上图,p=2为欧式距离。Jaccard相似度可以度量集合间的相似度。余弦相似度可度量语句或主题模型中的文档展成的向量的相似度。实际物理点用欧式距离做。函数间相似度用K-L距离。

二、K-means算法

1、算法
在这里插入图片描述
注意:K-means对于初值的选择(初值选不好会震荡)和异常值的出现非常敏感;可以多做几次k-means取最好的。

2、重要:k-means算法的改进

  • 1、k-means++算法
    依概率去取(定一个种子点,求其余样本点到种子点距离 l i l_i li,则 p = l i Σ i = 1 m l i p=\frac{l_i}{\Sigma_{i=1}^{m}l_i} p=Σi=1mlili距离远的概率大,更容易被选为种子,再重复上述步骤至选出k个种子。

  • 2、Mini-batch k-means++算法
    样本量太大时, 每次聚类不是对第 i i i个簇的所有样本取均值得到新的种子点,而是从第 i i i个簇中,取部分样本求均值作为种子点

3、从损失函数的角度理解k-means

  • 假设k-means的各个簇的样本都服从 N ( μ j , σ ) , j = 1 , . . . , K N(\mu_j,\sigma),j=1,...,K N(μj,σ),j=1,...,K
  • 求所有样本的似然函数,令似然函数最小
  • 得到损失函数

在这里插入图片描述

4、k-means优缺点
在这里插入图片描述
5、评价指标

  • 需要知道y标签
    在这里插入图片描述

  • 不需要y标签
    在这里插入图片描述

三、层次聚类

当簇具有特定形状(即非平坦流形)且标准欧氏距离不是正确的度量方法时,非平坦几何聚类(Non-flat geometry clustering)很有用。

层次聚类就是按类间相似度来一层一层的进行聚类,可以由上向下把大的类别(cluster)分割,叫作分裂法;也可以由下向上对小的类别进行聚合,叫作凝聚法;但是一般用的比较多的是由下向上的凝聚方法。
在这里插入图片描述
度量两个类之间的距离

  • 最远距离:两个簇中两最远样本的距离
  • 最近距离:两个簇中两最近样本的距离
  • 平均距离:两个簇间任意两两样本之间求距离的和,再取平均;或取平方。

下图是层次聚类采用不同的类间距离度量方式的距离结果,其中第二四行的小兰点表示噪声。

第二四栏有噪声

四、密度聚类

只要样本点的密度大于某阈值,则将该样本添加到最近的簇中。

  • 优点:它能克服"基于距离的聚类算法"只能发现凸聚类的缺点。且密度聚类对噪声不敏感。
  • 缺点:计算复杂度高,需建立空间索引降低计算量。

DBSCAN算法(允许带噪声的基于密度的空间聚类算法)

  • 1、基本概念
    在这里插入图片描述

  • 2、算法
    在这里插入图片描述
    密度处理可以去噪。

  • 3、调参
    可调参数为 m m m ε \varepsilon ε。从下图可以看出,当m过小,核心对象可能会增多,从而类别数增多。
    在这里插入图片描述

密度最大值聚类(确定簇的中心)

  • 1、两个概念(局部密度、高局部密度点距离)
    局部密度 ρ i \rho_i ρi越大,说明样本 x i x_i xi周围的样本点越多, δ i \delta_i δi大,说明样本 x i x_i xi附近有局部密度更大的样本点。
    在这里插入图片描述
  • 2、通过 ρ i \rho_i ρi δ i \delta_i δi识别簇中心
    • ρ i \rho_i ρi δ i \delta_i δi都很大,则对应 x i x_i xi为簇中心;
    • ρ i \rho_i ρi小, δ i \delta_i δi大,则对应 x i x_i xi为异常点;
      在这里插入图片描述
    • 簇中心已知后,按密度可达或距离最小来聚类

五、谱聚类

谱聚类是一种基于图论的聚类方法,对样本数据的拉普拉斯阵特征向量进行聚类,从而达到对样本数据聚类的目的。
1、基础知识

  • 实对称阵特征值是实数
  • 实对称阵不同特征值所对应的特征向量正交
  • 方阵的谱:方阵所有特征值的全体
  • 方阵的谱半径:方阵的最大特征值
  • 矩阵A的谱半径: A T A A^TA ATA的最大特征值

2、拉普拉斯矩阵分类
在这里插入图片描述
未加说明,使优先选择随机游走拉普拉斯矩阵。

3、谱聚类算法
在这里插入图片描述
4、谱聚类K的选择
k = arg max ⁡ k ∣ λ k + 1 − λ k ∣ k=\argmax_k|\lambda_{k+1}-\lambda_k| k=kargmaxλk+1λk

k-means、dbscan和图像压缩

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import sklearn.datasets as ds
from sklearn.cluster import KMeans,DBSCAN

"""自己做一份数据"""
# x是(400,2),2个特征,y是400行,有四类
x, y = ds.make_blobs(400, n_features=2, centers=4, random_state=2)


"""K-means聚类"""
model=KMeans(n_clusters=4,init='k-means++')
y_pred=model.fit_predict(x,y)

"""密度聚类"""
model_1 = DBSCAN(eps=0.75, min_samples=10)
y_pred_1 = model_1.fit_predict(x, y)

"""绘制图像"""
# 原始图像
plt.figure()
plt.subplot(2,2,1)
plt.scatter(x[:,0],x[:,1],c=y,edgecolors='k',alpha=0.7)
plt.title('initial picture')
plt.grid()

plt.subplot(2,2,2)
plt.scatter(x[:,0],x[:,1],c=y_pred,edgecolors='k',alpha=0.7)
plt.title('k-means picture')
plt.grid()

plt.subplot(2,2,3)
plt.scatter(x[:,0],x[:,1],c=y_pred_1,edgecolors='k',alpha=0.7)
plt.title('DBSCAN picture')
plt.grid()
plt.show()
plt.show()

在这里插入图片描述

import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans

"""显示图片"""
img = plt.imread('flower2.png')
plt.figure()
plt.subplot(1, 2, 1)
plt.title('initial picture')
plt.imshow(img)

"""k-means"""
# 将图像转为像素点,每个样本(像素点)有RGB三个特征
N = img.shape[0] * img.shape[1]
data = img.reshape(N, img.shape[2])
# 数据量太大,从中随机选择1000个进行聚类,形成聚类中心
index = np.random.randint(1, N, size=1000)
x = data[index]

# k-means训练模型
K=20
model = KMeans(n_clusters=K, init='k-means++')
model.fit(x)
y_pred = model.predict(data)
# print('聚类结果:\n', y_pred)
print('聚类中心:\n', model.cluster_centers_)

# 把不同类别的像素点的RGB替换为聚类中心
for k in range(0,K):
    data[np.where(y_pred==k)]=model.cluster_centers_[k]

plt.subplot(1,2,2)
plt.title('k-means K={}'.format(K))
plt.imshow(data.reshape(img.shape))
plt.show()

六、Python_k-means

1.观察距离最近样本点是否分类准确

在这里插入图片描述

import numpy as np
def find_closest_centroids(X, centroids):
    K = centroids.shape[0]
    m = X.shape[0]
    idx = np.zeros(m) #用来存放每一个样本点的索引号

    # ===================== Your Code Here =====================
    for i in range(m):
        idx[i] = np.argmin(np.sqrt(np.sum(np.power((centroids - X[i]), 2), 1)))
    return idx

 # ===================== 主程序 =====================
 # 读取ex7data2文件
data = scio.loadmat('data/ex7data2.mat')
# print(data.keys())
X = data['X']

#  随机初始化三个种子点
k = 3
initial_centroids = np.array([[3, 3], [6, 2], [8, 5]])

# 验证距离最近的样本点的类别是否分类正确
idx = find_closest_centroids(X, initial_centroids)
print('idx:', idx[:3],'\n(the closest centroids should be 0, 2, 1 respectively)')

2.重新计算聚类中心

在这里插入图片描述

import numpy as np
def compute_centroids(X, idx, K):
    (m, n) = X.shape
    centroids = np.zeros((K, n))

    # ===================== Your Code Here =====================
    for i in range(K):
        centroids[i] = np.mean(X[np.where(idx == i)], axis=0)
    return centroids
     # ===================== 主程序调用 ===================== 
     centroids = compute_centroids(X, idx, k)
	print('Centroids computed after initial finding of closest 	centroids: \n{}'.format(centroids))
	print('the centroids should be')
	print('[[ 2.428301 3.157924 ]')
	print(' [ 5.813503 2.633656 ]')
	print(' [ 7.119387 3.616684 ]]')

新学到的语句(需要挑出特定类别时常用)
np.where(y==i)其返回为y=i对应的在y中的位置

>>>y=np.array([1,1,1,2,3,0,1,1,1])
>>>np.where(y==1)
(array([0, 1, 2, 6, 7, 8], dtype=int64),)
>>>y[np.where(y==1)] # 取出y的对应np.where(y==1)位置处的元素。
array([1, 1, 1, 1, 1, 1])

3.K-means聚类

(十次迭代循环,按一次键,更新一次轨迹。for循环里在一张图片上更新曲线,需要用到 plt.pause(ts))
聚类算法运行后,得到如下结果。黑叉为10次聚类中心移动
在这里插入图片描述

4. 随机初始化种子点

从样本点中随机挑选K个作为种子点。

import numpy as np
def kmeans_init_centroids(X, K):
    centroids = np.zeros((K, X.shape[1]))

    # ===================== Your Code Here =====================
    centroids = X[np.random.choice(X.shape[0], K)
    return centroids

5. K-means图像压缩

一幅RGB图片中有很多像素点,并且这幅图片有0-255中颜色的可能性,K-means用来寻找16个基本像素点,然后实现聚类,进行图片压缩,最终图片就只有16种颜色了。
程序流程:
给一幅RGB图像(1281283),转为可以处理的输入样本X(16384(m)3(n))。随机取16个种子点,调用K-means算法,得到最终的16个聚类中心,以及16384个输入样本分别属于那一类,将对应的类的RGB值换为16个聚类中心对应的类的RGB值。最终得到一组新的样本X(16384(m)3(n)),为显示压缩图像,需reshape(1281283)

# ===================== Part 4: Image compression with K-means =====================
img = cv2.imread('data/bird_small.png')
cv2.imshow("image_uncompressed", img)  # 显示图片,后面会讲解
# cv2.waitKey(0)  # 等待按键
# cv2.destroyAllWindows()
X = img.reshape(img.shape[0]*img.shape[1], 3)
K = 16
max_iters = 10
initial_centroids = kmeans_init_centroids(X, K) # 这是随机初始化种子点
centroids, idx = km.run_kmeans(X, initial_centroids, max_iters, False)
X_recovered = centroids[idx.astype(int)]
X_recovered = np.reshape(X_recovered, (img.shape[0], img.shape[1], 3))
X_recovered = X_recovered.astype("uint8")  # opencv显示的数组类型必须为uint8
cv2.imshow("image_compressed", X_recovered)

在这里插入图片描述
在这里插入图片描述
为什么有压缩效果(存位置加少量颜色)
在这里插入图片描述

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hellobigorange

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值