1. kmeans

kmeans, k-均值聚类算法,能够实现发现数据集的 k 个簇的算法,每个簇通过其质心来描述。

kmeans步骤:

(1)随机找 k 个点作为质心(种子);
(2)计算其他点到这 k 个种子的距离,选择最近的那个作为该点的类别;
(3)更新各类的质心,迭代到质心的不变为止。

Q:如何选择 k 值?
A: 根据 k 取不同的值时,模型性能曲线图。
横坐标是聚类数目k,纵坐标是各点到距离中心的距离和。

kmean聚类算法 kmeans聚类算法基本步骤_算法

2. kmeans++

因为,kmeans的初始种子的随机找的,这样,算法的收敛快慢与初始值关系非常大,于是,kmeans++ 主要针对初始值的选取进行改进。
初始值选取,如下:

1、也是随机选取一个种子;
2、计算其他点到这个种子的距离;
3、选择这些较大的距离的那个点,替代随机选取的那个种子,作为新的种子点(这里的较大的距离,可以理解为maxDistance*随机数,随机数可以选取0.5-1;);
4、迭代1-3步,直到选取k个种子为止。

3. 评估聚类效果

轮廓系数法SC

轮廓系数(Silhouette Coefficient))结合了聚类的凝聚度(Cohesion)和分离度(Separation),用于评估聚类的效果。该值处于-1~1之间,值越大,表示聚类效果越好。
计算步骤:
(1)选择一个点 kmean聚类算法 kmeans聚类算法基本步骤_ci_02,计算该点 到同一簇内所有其他元素距离的平均值,记为 kmean聚类算法 kmeans聚类算法基本步骤_kmean聚类算法_03, 量化簇内的凝聚度;
(2)选择一个其他簇,计算该点到簇内的平均距离。选择该点与其他簇平均距离最小的值,记为 kmean聚类算法 kmeans聚类算法基本步骤_聚类_04, 用于量化簇间的分离度。
(3)对于样本点kmean聚类算法 kmeans聚类算法基本步骤_kmean聚类算法_05,轮廓系数为:

kmean聚类算法 kmeans聚类算法基本步骤_聚类_06
a(i) :i向量到同一簇内其他点不相似程度的平均值
b(i) :i向量到其他簇的平均不相似程度的最小值

kmean聚类算法 kmeans聚类算法基本步骤_kmean聚类算法_07


当轮廓系数<0, 该点可能误分; 值 = 0, 该点在两簇边缘; 值=1, 离其他簇很远。

计算所有点的轮廓系数,求平均值, 即为当前聚类的整体轮廓系数。

因此,轮廓系数可以用来确定Kmean的K值,选取轮廓系数最大的K作为最终的类数目。

(2)误差平方和

kmean聚类算法 kmeans聚类算法基本步骤_ci_08

4. 其他问题

(1)kmeans一定会收敛吗

kmeans的目标函数:

kmean聚类算法 kmeans聚类算法基本步骤_ci_09


E步:评估隐变量,每类样本属于的类别

kmean聚类算法 kmeans聚类算法基本步骤_数据集_10


M步:固定数据点的分配,更新参数

kmean聚类算法 kmeans聚类算法基本步骤_算法_11


由于EM算法具有收敛性,kmeans也会最终收敛。

(2) Kmeans 和KNN的区别

KNN:
分类算法
监督学习
数据集是带Label的数据
没有明显的训练过程,基于Memory-based learning
K值含义 - 对于一个样本X,要给它分类,首先从数据集中,在X附近找离它最近的K个数据点,将它划分为归属于类别最多的一类

K-means:

聚类算法
非监督学习
数据集是无Label,杂乱无章的数据
有明显的训练过程
K值含义- K是事先设定的数字,将数据集分为K个簇,需要依靠人的先验知识

不同点:

两种算法之间的根本区别是,K-means本质上是无监督学习,而KNN是监督学习;K-means是聚类算法,KNN是分类(或回归)算法。

K-means算法把一个数据集分割成簇,使得形成的簇是同构的,每个簇里的点相互靠近。该算法试图维持这些簇之间有足够的可分离性。由于无监督的性质,这些簇没有任何标签。KNN算法尝试基于其k(可以是任何数目)个周围邻居来对未标记的观察进行分类。它也被称为懒惰学习法,因为它涉及最小的模型训练。因此,它不用训练数据对未看见的数据集进行泛化。

5. 实践

Kmeans python 代码:

import numpy as np
class KMeans(object):
    def __init__(self, n_cluster, epochs=10):
        self.n_cluster = n_cluster
        self.epochs = epochs
        pass
    def init_centers(self, X):
        idx = np.random.randint(len(X), size=(self.n_cluster,))
        centers = X[idx,:]
        return centers

    def calculate_distance(self,arr1,arr2):
        # L2 distance.
        distance = np.mean(np.sqrt((arr1-arr2)**2))
        return distance
    def update_centers(self, X):
        predict_class = self.predict(X)
        # update centers
        centers = self.centers
        for ct in range(len(centers)):
            idx, = np.where(predict_class == ct)

            samples = X[idx, :]
            assert len(samples)>0
            centers[ct] = np.mean(samples,axis=0)
        self.centers = centers
        return self.centers

    def fit(self, X, y=None):
        self.centers = self.init_centers(X)
        for epoch in range(self.epochs):
            self.centers = self.update_centers(X)
        return self.centers
    def predict(self,X):
        predict_class = np.zeros(shape=(len(X),))
        centers = self.centers
        for n_sample,arr in enumerate(X):
            min_distance = float("inf")
            p_class = 0
            for ct in range(len(centers)):
                distance = self.calculate_distance(arr,centers[ct])
                if distance < min_distance:
                    min_distance = distance
                    p_class = ct
            predict_class[n_sample] = p_class
        return predict_class
    def score(self, X):
        pass

示例:
定义3个高斯分布。

np.random.seed(1)
data1 = np.random.normal(1, 0.5, size=(100, 2))
np.random.seed(1)
data2 = np.random.normal(4, 0.8, size=(100, 2))
np.random.seed(1)
data3 = np.random.normal(7, 0.8, size=(100, 2))
X = np.concatenate((data1, data2, data3),axis=0)#np.random.randint(10,size=(100,2))
print(X.shape)
kmeans = KMeans(3)
centers = kmeans.fit(X)
print(centers)

可视化聚类的结果:

# Generate scatter plot for training data
import matplotlib.pyplot as plt

plt.scatter(X[:,0], X[:,1], marker="o", picker=True)
plt.title('Clusters of data')
plt.xlabel('x1')
plt.ylabel('x2')
plt.scatter(centers[:,0], centers[:,1], marker="v", picker=True)
plt.show()

kmean聚类算法 kmeans聚类算法基本步骤_算法_12

轮廓系数的计算

sklearn.metrics.silhouette_score(X, labels, *, metric='euclidean', 
sample_size=None, random_state=None, **kwds)

示例:

# Initialize the clusterer with n_clusters value and a random generator
    # seed of 10 for reproducibility.
    clusterer = KMeans(n_clusters=n_clusters, random_state=10)
    cluster_labels = clusterer.fit_predict(X)

    # The silhouette_score gives the average value for all the samples.
    # This gives a perspective into the density and separation of the formed
    # clusters
    silhouette_avg = silhouette_score(X, cluster_labels)
    print("For n_clusters =", n_clusters,
          "The average silhouette_score is :", silhouette_avg)